mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Net6
This commit is contained in:
parent
15d93830a3
commit
cb2e2f0128
8 changed files with 393 additions and 357 deletions
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
[submodule "OtterGui"]
|
||||||
|
path = OtterGui
|
||||||
|
url = git@github.com:Ottermandias/OtterGui.git
|
||||||
|
branch = main
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<LangVersion>preview</LangVersion>
|
<LangVersion>preview</LangVersion>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<RootNamespace>Glamourer</RootNamespace>
|
<RootNamespace>Glamourer</RootNamespace>
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
||||||
|
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
|
@ -32,31 +34,33 @@
|
||||||
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Dalamud">
|
<Reference Include="Dalamud">
|
||||||
<HintPath>$(DALAMUD_ROOT)\Dalamud.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
|
||||||
<HintPath>..\libs\Dalamud.dll</HintPath>
|
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="FFXIVClientStructs">
|
<Reference Include="FFXIVClientStructs">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
|
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ImGuiScene">
|
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Lumina">
|
<Reference Include="Lumina">
|
||||||
<HintPath>$(DALAMUD_ROOT)\Lumina.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
|
||||||
<HintPath>..\libs\Lumina.dll</HintPath>
|
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Lumina.Excel">
|
<Reference Include="Lumina.Excel">
|
||||||
<HintPath>$(DALAMUD_ROOT)\Lumina.Excel.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
|
||||||
<HintPath>..\libs\Lumina.Excel.dll</HintPath>
|
<Private>False</Private>
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll</HintPath>
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ImGuiScene">
|
||||||
|
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
149
Glamourer/CurrentManipulations.cs
Normal file
149
Glamourer/CurrentManipulations.cs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Glamourer.Customization;
|
||||||
|
using Penumbra.GameData.Enums;
|
||||||
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
namespace Glamourer;
|
||||||
|
|
||||||
|
public class CurrentManipulations
|
||||||
|
{
|
||||||
|
private readonly RestrictedGear _restrictedGear = GameData.RestrictedGear(Dalamud.GameData);
|
||||||
|
private readonly Dictionary<Actor.IIdentifier, CharacterSave> _characterSaves = new();
|
||||||
|
|
||||||
|
public CharacterSave CreateSave(Actor actor)
|
||||||
|
{
|
||||||
|
var id = actor.GetIdentifier();
|
||||||
|
if (_characterSaves.TryGetValue(id, out var save))
|
||||||
|
return save;
|
||||||
|
|
||||||
|
save = new CharacterSave(actor);
|
||||||
|
_characterSaves.Add(id.CreatePermanent(), save);
|
||||||
|
return save;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetDesign(Actor.IIdentifier identifier, [NotNullWhen(true)] out CharacterSave? save)
|
||||||
|
=> _characterSaves.TryGetValue(identifier, out save);
|
||||||
|
|
||||||
|
public CharacterArmor? ChangeEquip(Actor actor, EquipSlot slot, CharacterArmor data)
|
||||||
|
{
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
(_, data) = _restrictedGear.ResolveRestricted(data, slot, save.Customize.Race, save.Customize.Gender);
|
||||||
|
if (save.Equipment[slot] == data)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
save.Equipment[slot] = data;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ChangeWeapon(Actor actor, CharacterWeapon main)
|
||||||
|
{
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
if (save.MainHand == main)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
save.MainHand = main;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ChangeWeapon(Actor actor, CharacterWeapon main, CharacterWeapon off)
|
||||||
|
{
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
if (main == save.MainHand && off == save.OffHand)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
save.MainHand = main;
|
||||||
|
save.OffHand = off;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeCustomization(Actor actor, Customize customize)
|
||||||
|
{
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
FixRestrictedGear(save, customize.Gender, customize.Race);
|
||||||
|
save.Customize.Load(customize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ChangeCustomization(Actor actor, CustomizationId id, byte value)
|
||||||
|
{
|
||||||
|
if (id == CustomizationId.Race)
|
||||||
|
return ChangeRace(actor, (SubRace)value);
|
||||||
|
if (id == CustomizationId.Gender)
|
||||||
|
return ChangeGender(actor, (Gender)value);
|
||||||
|
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
var customize = save.Customize;
|
||||||
|
if (customize[id] != value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
customize[id] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change a gender and fix up all required customizations afterwards.
|
||||||
|
public bool ChangeGender(Actor actor, Gender gender)
|
||||||
|
{
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
if (save.Customize.Gender == gender)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var customize = save.Customize;
|
||||||
|
FixRestrictedGear(save, gender, customize.Race);
|
||||||
|
FixUpAttributes(customize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change a race and fix up all required customizations afterwards.
|
||||||
|
public bool ChangeRace(Actor actor, SubRace clan)
|
||||||
|
{
|
||||||
|
var save = CreateSave(actor);
|
||||||
|
if (save.Customize.Clan == clan)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var customize = save.Customize;
|
||||||
|
var race = clan.ToRace();
|
||||||
|
var gender = race == Race.Hrothgar ? Gender.Male : customize.Gender; // TODO Female Hrothgar
|
||||||
|
FixRestrictedGear(save, gender, race);
|
||||||
|
customize.Gender = gender;
|
||||||
|
customize.Race = race;
|
||||||
|
customize.Clan = clan;
|
||||||
|
|
||||||
|
FixUpAttributes(customize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through a whole customization struct and fix up all settings that need fixing.
|
||||||
|
private void FixUpAttributes(Customize customize)
|
||||||
|
{
|
||||||
|
var set = Glamourer.Customization.GetList(customize.Clan, customize.Gender);
|
||||||
|
foreach (CustomizationId id in Enum.GetValues(typeof(CustomizationId)))
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case CustomizationId.Race: break;
|
||||||
|
case CustomizationId.Clan: break;
|
||||||
|
case CustomizationId.BodyType: break;
|
||||||
|
case CustomizationId.Gender: break;
|
||||||
|
case CustomizationId.FacialFeaturesTattoos: break;
|
||||||
|
case CustomizationId.HighlightsOnFlag: break;
|
||||||
|
case CustomizationId.Face: break;
|
||||||
|
default:
|
||||||
|
var count = set.Count(id);
|
||||||
|
if (set.DataByValue(id, customize[id], out _) < 0)
|
||||||
|
customize[id] = count == 0 ? (byte)0 : set.Data(id, 0).Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixRestrictedGear(CharacterSave save, Gender gender, Race race)
|
||||||
|
{
|
||||||
|
if (race == save.Customize.Race && gender == save.Customize.Gender)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var equip = save.Equipment;
|
||||||
|
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||||
|
(_, equip[slot]) = _restrictedGear.ResolveRestricted(equip[slot], slot, race, gender);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Glamourer/FixedDesigns.cs
Normal file
12
Glamourer/FixedDesigns.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Glamourer;
|
||||||
|
|
||||||
|
public class FixedDesigns
|
||||||
|
{
|
||||||
|
public bool TryGetDesign(Actor.IIdentifier actor, [NotNullWhen(true)] out CharacterSave? save)
|
||||||
|
{
|
||||||
|
save = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,10 @@
|
||||||
using System.Collections;
|
using System.Reflection;
|
||||||
using System.ComponentModel.Design;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices.ComTypes;
|
|
||||||
using Dalamud.Data;
|
|
||||||
using Dalamud.Game.ClientState.JobGauge.Enums;
|
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game.Command;
|
||||||
using Dalamud.Hooking;
|
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using FFXIVClientStructs.Attributes;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.Excel;
|
|
||||||
using Glamourer.Api;
|
using Glamourer.Api;
|
||||||
using Glamourer.Customization;
|
using Glamourer.Customization;
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using Lumina.Data.Parsing;
|
|
||||||
using Microsoft.VisualBasic.CompilerServices;
|
|
||||||
using OtterGui.Table;
|
|
||||||
using Penumbra.GameData.Enums;
|
|
||||||
using Penumbra.GameData.Structs;
|
|
||||||
using static FFXIVClientStructs.FFXIV.Client.UI.Misc.RaptureMacroModule;
|
|
||||||
using static System.Collections.Specialized.BitVector32;
|
|
||||||
using static System.Reflection.Metadata.BlobBuilder;
|
|
||||||
using Race = Lumina.Excel.GeneratedSheets.Race;
|
|
||||||
|
|
||||||
namespace Glamourer;
|
namespace Glamourer;
|
||||||
|
|
||||||
|
|
@ -45,10 +26,11 @@ public class Glamourer : IDalamudPlugin
|
||||||
public static GlamourerConfig Config = null!;
|
public static GlamourerConfig Config = null!;
|
||||||
|
|
||||||
public static PenumbraAttach Penumbra = null!;
|
public static PenumbraAttach Penumbra = null!;
|
||||||
|
|
||||||
public static ICustomizationManager Customization = null!;
|
public static ICustomizationManager Customization = null!;
|
||||||
public static RedrawManager RedrawManager = null!;
|
public static RedrawManager RedrawManager = null!;
|
||||||
private readonly WindowSystem _windowSystem = new("Glamourer");
|
private readonly WindowSystem _windowSystem = new("Glamourer");
|
||||||
|
private readonly FixedDesigns _fixedDesigns;
|
||||||
|
private readonly CurrentManipulations _currentManipulations;
|
||||||
|
|
||||||
private readonly Interface _interface;
|
private readonly Interface _interface;
|
||||||
//public readonly DesignManager Designs;
|
//public readonly DesignManager Designs;
|
||||||
|
|
@ -62,11 +44,12 @@ public class Glamourer : IDalamudPlugin
|
||||||
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||||
Config = GlamourerConfig.Load();
|
Config = GlamourerConfig.Load();
|
||||||
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
||||||
|
_fixedDesigns = new FixedDesigns();
|
||||||
|
|
||||||
//Designs = new DesignManager();
|
//Designs = new DesignManager();
|
||||||
|
|
||||||
//GlamourerIpc = new GlamourerIpc(Dalamud.ClientState, Dalamud.Objects, Dalamud.PluginInterface);
|
//GlamourerIpc = new GlamourerIpc(Dalamud.ClientState, Dalamud.Objects, Dalamud.PluginInterface);
|
||||||
RedrawManager = new RedrawManager();
|
RedrawManager = new RedrawManager(_fixedDesigns, _currentManipulations);
|
||||||
|
|
||||||
Dalamud.Commands.AddHandler(MainCommandString, new CommandInfo(OnGlamourer)
|
Dalamud.Commands.AddHandler(MainCommandString, new CommandInfo(OnGlamourer)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<LangVersion>preview</LangVersion>
|
<LangVersion>preview</LangVersion>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<RootNamespace>Glamourer</RootNamespace>
|
<RootNamespace>Glamourer</RootNamespace>
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
|
@ -45,39 +47,39 @@
|
||||||
<EmbeddedResource Include="LegacyTattoo.raw" />
|
<EmbeddedResource Include="LegacyTattoo.raw" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Dalamud">
|
<Reference Include="Dalamud">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="FFXIVClientStructs">
|
<Reference Include="FFXIVClientStructs">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
|
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ImGui.NET">
|
<Reference Include="ImGui.NET">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
|
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ImGuiScene">
|
<Reference Include="ImGuiScene">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SDL2-CS">
|
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\SDL2-CS.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Lumina">
|
<Reference Include="Lumina">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Lumina.Excel">
|
<Reference Include="Lumina.Excel">
|
||||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -116,7 +118,9 @@
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
<Exec Command="if $(Configuration) == Release powershell Compress-Archive -Force $(TargetPath), $(TargetDir)$(SolutionName).json, $(TargetDir)$(SolutionName).GameData.dll, $(TargetDir)Penumbra.GameData.dll $(SolutionDir)$(SolutionName).zip" />
|
<Exec
|
||||||
<Exec Command="if $(Configuration) == Release powershell Copy-Item -Force $(TargetDir)$(SolutionName).json -Destination $(SolutionDir)" />
|
Command="if $(Configuration) == Release powershell Compress-Archive -Force $(TargetPath), $(TargetDir)$(SolutionName).json, $(TargetDir)$(SolutionName).GameData.dll, $(TargetDir)Penumbra.GameData.dll $(SolutionDir)$(SolutionName).zip" />
|
||||||
|
<Exec
|
||||||
|
Command="if $(Configuration) == Release powershell Copy-Item -Force $(TargetDir)$(SolutionName).json -Destination $(SolutionDir)" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1,163 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
|
using Dalamud.Logging;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using Glamourer.Customization;
|
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
using static Glamourer.Actor;
|
||||||
|
|
||||||
namespace Glamourer;
|
namespace Glamourer;
|
||||||
|
|
||||||
public class CurrentManipulations
|
|
||||||
{
|
|
||||||
private readonly RestrictedGear _restrictedGear = GameData.RestrictedGear(Dalamud.GameData);
|
|
||||||
private readonly Dictionary<Actor.IIdentifier, CharacterSave> _characterSaves = new();
|
|
||||||
|
|
||||||
public CharacterSave CreateSave(Actor actor)
|
|
||||||
{
|
|
||||||
var id = actor.GetIdentifier();
|
|
||||||
if (_characterSaves.TryGetValue(id, out var save))
|
|
||||||
return save;
|
|
||||||
|
|
||||||
save = new CharacterSave(actor);
|
|
||||||
_characterSaves.Add(id.CreatePermanent(), save);
|
|
||||||
return save;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool GetSave(Actor actor, [NotNullWhen(true)] out CharacterSave? save)
|
|
||||||
{
|
|
||||||
save = null;
|
|
||||||
return actor && _characterSaves.TryGetValue(actor.GetIdentifier(), out save);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool GetSave(Actor.IIdentifier identifier, [NotNullWhen(true)] out CharacterSave? save)
|
|
||||||
=> _characterSaves.TryGetValue(identifier, out save);
|
|
||||||
|
|
||||||
public CharacterArmor? ChangeEquip(Actor actor, EquipSlot slot, CharacterArmor data)
|
|
||||||
{
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
(_, data) = _restrictedGear.ResolveRestricted(data, slot, save.Customize.Race, save.Customize.Gender);
|
|
||||||
if (save.Equipment[slot] == data)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
save.Equipment[slot] = data;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ChangeWeapon(Actor actor, CharacterWeapon main)
|
|
||||||
{
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
if (save.MainHand == main)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
save.MainHand = main;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ChangeWeapon(Actor actor, CharacterWeapon main, CharacterWeapon off)
|
|
||||||
{
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
if (main == save.MainHand && off == save.OffHand)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
save.MainHand = main;
|
|
||||||
save.OffHand = off;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ChangeCustomization(Actor actor, Customize customize)
|
|
||||||
{
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
FixRestrictedGear(save, customize.Gender, customize.Race);
|
|
||||||
save.Customize.Load(customize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ChangeCustomization(Actor actor, CustomizationId id, byte value)
|
|
||||||
{
|
|
||||||
if (id == CustomizationId.Race)
|
|
||||||
return ChangeRace(actor, (SubRace)value);
|
|
||||||
if (id == CustomizationId.Gender)
|
|
||||||
return ChangeGender(actor, (Gender)value);
|
|
||||||
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
var customize = save.Customize;
|
|
||||||
if (customize[id] != value)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
customize[id] = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change a gender and fix up all required customizations afterwards.
|
|
||||||
public bool ChangeGender(Actor actor, Gender gender)
|
|
||||||
{
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
if (save.Customize.Gender == gender)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var customize = save.Customize;
|
|
||||||
FixRestrictedGear(save, gender, customize.Race);
|
|
||||||
FixUpAttributes(customize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change a race and fix up all required customizations afterwards.
|
|
||||||
public bool ChangeRace(Actor actor, SubRace clan)
|
|
||||||
{
|
|
||||||
var save = CreateSave(actor);
|
|
||||||
if (save.Customize.Clan == clan)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var customize = save.Customize;
|
|
||||||
var race = clan.ToRace();
|
|
||||||
var gender = race == Race.Hrothgar ? Gender.Male : customize.Gender; // TODO Female Hrothgar
|
|
||||||
FixRestrictedGear(save, gender, race);
|
|
||||||
customize.Gender = gender;
|
|
||||||
customize.Race = race;
|
|
||||||
customize.Clan = clan;
|
|
||||||
|
|
||||||
FixUpAttributes(customize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through a whole customization struct and fix up all settings that need fixing.
|
|
||||||
private void FixUpAttributes(Customize customize)
|
|
||||||
{
|
|
||||||
var set = Glamourer.Customization.GetList(customize.Clan, customize.Gender);
|
|
||||||
foreach (CustomizationId id in Enum.GetValues(typeof(CustomizationId)))
|
|
||||||
{
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case CustomizationId.Race: break;
|
|
||||||
case CustomizationId.Clan: break;
|
|
||||||
case CustomizationId.BodyType: break;
|
|
||||||
case CustomizationId.Gender: break;
|
|
||||||
case CustomizationId.FacialFeaturesTattoos: break;
|
|
||||||
case CustomizationId.HighlightsOnFlag: break;
|
|
||||||
case CustomizationId.Face: break;
|
|
||||||
default:
|
|
||||||
var count = set.Count(id);
|
|
||||||
if (set.DataByValue(id, customize[id], out _) < 0)
|
|
||||||
customize[id] = count == 0 ? (byte)0 : set.Data(id, 0).Value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FixRestrictedGear(CharacterSave save, Gender gender, Race race)
|
|
||||||
{
|
|
||||||
if (race == save.Customize.Race && gender == save.Customize.Gender)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var equip = save.Equipment;
|
|
||||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
|
||||||
(_, equip[slot]) = _restrictedGear.ResolveRestricted(equip[slot], slot, race, gender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe partial class RedrawManager
|
public unsafe partial class RedrawManager
|
||||||
{
|
{
|
||||||
public delegate ulong FlagSlotForUpdateDelegate(Human* drawObject, uint slot, CharacterArmor* data);
|
public delegate ulong FlagSlotForUpdateDelegate(Human* drawObject, uint slot, CharacterArmor* data);
|
||||||
|
|
@ -168,25 +20,27 @@ public unsafe partial class RedrawManager
|
||||||
|
|
||||||
private ulong FlagSlotForUpdateDetour(Human* drawObject, uint slot, CharacterArmor* data)
|
private ulong FlagSlotForUpdateDetour(Human* drawObject, uint slot, CharacterArmor* data)
|
||||||
{
|
{
|
||||||
//try
|
try
|
||||||
//{
|
{
|
||||||
// var actor = Glamourer.Penumbra.GameObjectFromDrawObject((IntPtr)drawObject);
|
var actor = Glamourer.Penumbra.GameObjectFromDrawObject((IntPtr)drawObject);
|
||||||
// if (actor && CurrentManipulations.GetSave(actor, out _))
|
var identifier = actor.GetIdentifier();
|
||||||
// // TODO fixed design
|
|
||||||
//
|
if (_fixedDesigns.TryGetDesign(identifier, out var save))
|
||||||
// *data = CurrentManipulations.ChangeEquip(actor, slot.ToEquipSlot(), *data) ?? *data;
|
PluginLog.Information($"Loaded {slot.ToEquipSlot()} from fixed design for {identifier}.");
|
||||||
//}
|
else if (_currentManipulations.TryGetDesign(identifier, out save))
|
||||||
//catch
|
PluginLog.Information($"Updated {slot.ToEquipSlot()} from current designs for {identifier}.");
|
||||||
//{
|
}
|
||||||
// // ignored
|
catch (Exception e)
|
||||||
//}
|
{
|
||||||
|
PluginLog.Error($"Error on loading new gear:\n{e}");
|
||||||
|
}
|
||||||
|
|
||||||
return _flagSlotForUpdateHook!.Original(drawObject, slot, data);
|
return _flagSlotForUpdateHook!.Original(drawObject, slot, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ChangeEquip(Actor actor, EquipSlot slot, CharacterArmor data)
|
public bool ChangeEquip(Actor actor, EquipSlot slot, CharacterArmor data)
|
||||||
{
|
{
|
||||||
if (actor && CurrentManipulations.ChangeEquip(actor, slot, data).HasValue && actor.DrawObject != null)
|
if (actor && actor.DrawObject != null)
|
||||||
return _flagSlotForUpdateHook?.Original(actor.DrawObject, slot.ToIndex(), &data) != 0;
|
return _flagSlotForUpdateHook?.Original(actor.DrawObject, slot.ToIndex(), &data) != 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -214,6 +68,20 @@ public unsafe partial class RedrawManager
|
||||||
|
|
||||||
private void LoadWeaponDetour(IntPtr characterOffset, uint slot, CharacterWeapon weapon, byte unk1, byte unk2, byte unk3, byte unk4)
|
private void LoadWeaponDetour(IntPtr characterOffset, uint slot, CharacterWeapon weapon, byte unk1, byte unk2, byte unk3, byte unk4)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var character = (Actor)(characterOffset - CharacterWeaponOffset);
|
||||||
|
var identifier = character.GetIdentifier();
|
||||||
|
if (_fixedDesigns.TryGetDesign(identifier, out var save))
|
||||||
|
PluginLog.Information($"Loaded weapon from fixed design for {identifier}.");
|
||||||
|
else if (unk1 == 1 && _currentManipulations.TryGetDesign(identifier, out save))
|
||||||
|
PluginLog.Information($"Loaded weapon from current design for {identifier}.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
PluginLog.Error($"Error on loading new weapon:\n{e}");
|
||||||
|
}
|
||||||
|
|
||||||
_loadWeaponHook!.Original(characterOffset, slot, weapon, unk1, unk2, unk3, unk4);
|
_loadWeaponHook!.Original(characterOffset, slot, weapon, unk1, unk2, unk3, unk4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,14 +91,14 @@ public unsafe partial class RedrawManager
|
||||||
switch (slot)
|
switch (slot)
|
||||||
{
|
{
|
||||||
case EquipSlot.MainHand:
|
case EquipSlot.MainHand:
|
||||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 1, 1, 0, 1);
|
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 0, 1, 0, 0);
|
||||||
return;
|
return;
|
||||||
case EquipSlot.OffHand:
|
case EquipSlot.OffHand:
|
||||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, weapon, 1, 1, 0, 1);
|
LoadWeaponDetour(character + CharacterWeaponOffset, 1, weapon, 0, 1, 0, 0);
|
||||||
return;
|
return;
|
||||||
case EquipSlot.BothHand:
|
case EquipSlot.BothHand:
|
||||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 1, 1, 0, 1);
|
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 0, 1, 0, 0);
|
||||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, CharacterWeapon.Empty, 1, 1, 0, 1);
|
LoadWeaponDetour(character + CharacterWeaponOffset, 1, CharacterWeapon.Empty, 0, 1, 0, 0);
|
||||||
return;
|
return;
|
||||||
// function can also be called with '2', but does not seem to ever be.
|
// function can also be called with '2', but does not seem to ever be.
|
||||||
}
|
}
|
||||||
|
|
@ -242,8 +110,8 @@ public unsafe partial class RedrawManager
|
||||||
// Load specific Main- and Offhand weapons.
|
// Load specific Main- and Offhand weapons.
|
||||||
public void LoadWeapon(IntPtr character, CharacterWeapon main, CharacterWeapon off)
|
public void LoadWeapon(IntPtr character, CharacterWeapon main, CharacterWeapon off)
|
||||||
{
|
{
|
||||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, main, 1, 1, 0, 1);
|
LoadWeaponDetour(character + CharacterWeaponOffset, 0, main, 0, 1, 0, 0);
|
||||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, off, 1, 1, 0, 1);
|
LoadWeaponDetour(character + CharacterWeaponOffset, 1, off, 0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadWeapon(Character* character, CharacterWeapon main, CharacterWeapon off)
|
public void LoadWeapon(Character* character, CharacterWeapon main, CharacterWeapon off)
|
||||||
|
|
@ -254,10 +122,15 @@ public unsafe partial class RedrawManager : IDisposable
|
||||||
{
|
{
|
||||||
internal readonly CurrentManipulations CurrentManipulations = new();
|
internal readonly CurrentManipulations CurrentManipulations = new();
|
||||||
|
|
||||||
public RedrawManager()
|
private readonly FixedDesigns _fixedDesigns;
|
||||||
|
private readonly CurrentManipulations _currentManipulations;
|
||||||
|
|
||||||
|
public RedrawManager(FixedDesigns fixedDesigns, CurrentManipulations currentManipulations)
|
||||||
{
|
{
|
||||||
SignatureHelper.Initialise(this);
|
SignatureHelper.Initialise(this);
|
||||||
Glamourer.Penumbra.CreatingCharacterBase += OnCharacterRedraw;
|
Glamourer.Penumbra.CreatingCharacterBase += OnCharacterRedraw;
|
||||||
|
_fixedDesigns = fixedDesigns;
|
||||||
|
_currentManipulations = currentManipulations;
|
||||||
//_flagSlotForUpdateHook?.Enable();
|
//_flagSlotForUpdateHook?.Enable();
|
||||||
//_loadWeaponHook?.Enable();
|
//_loadWeaponHook?.Enable();
|
||||||
}
|
}
|
||||||
|
|
@ -271,13 +144,19 @@ public unsafe partial class RedrawManager : IDisposable
|
||||||
|
|
||||||
private void OnCharacterRedraw(IntPtr addr, IntPtr modelId, IntPtr customize, IntPtr equipData)
|
private void OnCharacterRedraw(IntPtr addr, IntPtr modelId, IntPtr customize, IntPtr equipData)
|
||||||
{
|
{
|
||||||
//if (CurrentManipulations.GetSave(addr, out var save))
|
try
|
||||||
//{
|
{
|
||||||
// *(CustomizationData*)customize = *(CustomizationData*)save.Customization.Address;
|
var actor = (Actor)addr;
|
||||||
// var equip = (CharacterEquip)equipData;
|
var identifier = actor.GetIdentifier();
|
||||||
// var newEquip = save.Equipment;
|
|
||||||
// for (var i = 0; i < 10; ++i)
|
if (_currentManipulations.TryGetDesign(identifier, out var save))
|
||||||
// equip[i] = newEquip[i];
|
PluginLog.Information($"Loaded current design for {identifier}.");
|
||||||
//}
|
else if (_fixedDesigns.TryGetDesign(identifier, out save))
|
||||||
|
PluginLog.Information($"Loaded fixed design for {identifier}.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
PluginLog.Error($"Error on new draw object creation:\n{e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1
OtterGui
Submodule
1
OtterGui
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4c92479175161617161d8faf844c8f683aa2d5d2
|
||||||
Loading…
Add table
Add a link
Reference in a new issue