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">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<RootNamespace>Glamourer</RootNamespace>
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
@ -32,31 +34,33 @@
|
|||
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Dalamud">
|
||||
<HintPath>$(DALAMUD_ROOT)\Dalamud.dll</HintPath>
|
||||
<HintPath>..\libs\Dalamud.dll</HintPath>
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="FFXIVClientStructs">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGuiScene">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina">
|
||||
<HintPath>$(DALAMUD_ROOT)\Lumina.dll</HintPath>
|
||||
<HintPath>..\libs\Lumina.dll</HintPath>
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina.Excel">
|
||||
<HintPath>$(DALAMUD_ROOT)\Lumina.Excel.dll</HintPath>
|
||||
<HintPath>..\libs\Lumina.Excel.dll</HintPath>
|
||||
<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>
|
||||
</Reference>
|
||||
<Reference Include="ImGuiScene">
|
||||
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</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.ComponentModel.Design;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game.ClientState.JobGauge.Enums;
|
||||
using System.Reflection;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin;
|
||||
using FFXIVClientStructs.Attributes;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using FFXIVClientStructs.FFXIV.Component.Excel;
|
||||
using Glamourer.Api;
|
||||
using Glamourer.Customization;
|
||||
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;
|
||||
|
||||
|
|
@ -45,10 +26,11 @@ public class Glamourer : IDalamudPlugin
|
|||
public static GlamourerConfig Config = null!;
|
||||
|
||||
public static PenumbraAttach Penumbra = null!;
|
||||
|
||||
public static ICustomizationManager Customization = null!;
|
||||
public static RedrawManager RedrawManager = null!;
|
||||
private readonly WindowSystem _windowSystem = new("Glamourer");
|
||||
private readonly FixedDesigns _fixedDesigns;
|
||||
private readonly CurrentManipulations _currentManipulations;
|
||||
|
||||
private readonly Interface _interface;
|
||||
//public readonly DesignManager Designs;
|
||||
|
|
@ -62,11 +44,12 @@ public class Glamourer : IDalamudPlugin
|
|||
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||
Config = GlamourerConfig.Load();
|
||||
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
||||
_fixedDesigns = new FixedDesigns();
|
||||
|
||||
//Designs = new DesignManager();
|
||||
|
||||
//GlamourerIpc = new GlamourerIpc(Dalamud.ClientState, Dalamud.Objects, Dalamud.PluginInterface);
|
||||
RedrawManager = new RedrawManager();
|
||||
RedrawManager = new RedrawManager(_fixedDesigns, _currentManipulations);
|
||||
|
||||
Dalamud.Commands.AddHandler(MainCommandString, new CommandInfo(OnGlamourer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<RootNamespace>Glamourer</RootNamespace>
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
@ -45,39 +47,39 @@
|
|||
<EmbeddedResource Include="LegacyTattoo.raw" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Dalamud">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="FFXIVClientStructs">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGui.NET">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGuiScene">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="SDL2-CS">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\SDL2-CS.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina">
|
||||
<HintPath>$(appdata)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
|
||||
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<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>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -116,7 +118,9 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
<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 Command="if $(Configuration) == Release powershell Copy-Item -Force $(TargetDir)$(SolutionName).json -Destination $(SolutionDir)" />
|
||||
<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
|
||||
Command="if $(Configuration) == Release powershell Copy-Item -Force $(TargetDir)$(SolutionName).json -Destination $(SolutionDir)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,163 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Customization;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using static Glamourer.Actor;
|
||||
|
||||
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 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)
|
||||
{
|
||||
//try
|
||||
//{
|
||||
// var actor = Glamourer.Penumbra.GameObjectFromDrawObject((IntPtr)drawObject);
|
||||
// if (actor && CurrentManipulations.GetSave(actor, out _))
|
||||
// // TODO fixed design
|
||||
//
|
||||
// *data = CurrentManipulations.ChangeEquip(actor, slot.ToEquipSlot(), *data) ?? *data;
|
||||
//}
|
||||
//catch
|
||||
//{
|
||||
// // ignored
|
||||
//}
|
||||
try
|
||||
{
|
||||
var actor = Glamourer.Penumbra.GameObjectFromDrawObject((IntPtr)drawObject);
|
||||
var identifier = actor.GetIdentifier();
|
||||
|
||||
if (_fixedDesigns.TryGetDesign(identifier, out var save))
|
||||
PluginLog.Information($"Loaded {slot.ToEquipSlot()} from fixed design for {identifier}.");
|
||||
else if (_currentManipulations.TryGetDesign(identifier, out save))
|
||||
PluginLog.Information($"Updated {slot.ToEquipSlot()} from current designs for {identifier}.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error($"Error on loading new gear:\n{e}");
|
||||
}
|
||||
|
||||
return _flagSlotForUpdateHook!.Original(drawObject, slot, 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 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -223,14 +91,14 @@ public unsafe partial class RedrawManager
|
|||
switch (slot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 1, 1, 0, 1);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 0, 1, 0, 0);
|
||||
return;
|
||||
case EquipSlot.OffHand:
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, weapon, 1, 1, 0, 1);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, weapon, 0, 1, 0, 0);
|
||||
return;
|
||||
case EquipSlot.BothHand:
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 1, 1, 0, 1);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, CharacterWeapon.Empty, 1, 1, 0, 1);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, weapon, 0, 1, 0, 0);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, CharacterWeapon.Empty, 0, 1, 0, 0);
|
||||
return;
|
||||
// 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.
|
||||
public void LoadWeapon(IntPtr character, CharacterWeapon main, CharacterWeapon off)
|
||||
{
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, main, 1, 1, 0, 1);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, off, 1, 1, 0, 1);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 0, main, 0, 1, 0, 0);
|
||||
LoadWeaponDetour(character + CharacterWeaponOffset, 1, off, 0, 1, 0, 0);
|
||||
}
|
||||
|
||||
public void LoadWeapon(Character* character, CharacterWeapon main, CharacterWeapon off)
|
||||
|
|
@ -254,10 +122,15 @@ public unsafe partial class RedrawManager : IDisposable
|
|||
{
|
||||
internal readonly CurrentManipulations CurrentManipulations = new();
|
||||
|
||||
public RedrawManager()
|
||||
private readonly FixedDesigns _fixedDesigns;
|
||||
private readonly CurrentManipulations _currentManipulations;
|
||||
|
||||
public RedrawManager(FixedDesigns fixedDesigns, CurrentManipulations currentManipulations)
|
||||
{
|
||||
SignatureHelper.Initialise(this);
|
||||
Glamourer.Penumbra.CreatingCharacterBase += OnCharacterRedraw;
|
||||
_fixedDesigns = fixedDesigns;
|
||||
_currentManipulations = currentManipulations;
|
||||
//_flagSlotForUpdateHook?.Enable();
|
||||
//_loadWeaponHook?.Enable();
|
||||
}
|
||||
|
|
@ -271,13 +144,19 @@ public unsafe partial class RedrawManager : IDisposable
|
|||
|
||||
private void OnCharacterRedraw(IntPtr addr, IntPtr modelId, IntPtr customize, IntPtr equipData)
|
||||
{
|
||||
//if (CurrentManipulations.GetSave(addr, out var save))
|
||||
//{
|
||||
// *(CustomizationData*)customize = *(CustomizationData*)save.Customization.Address;
|
||||
// var equip = (CharacterEquip)equipData;
|
||||
// var newEquip = save.Equipment;
|
||||
// for (var i = 0; i < 10; ++i)
|
||||
// equip[i] = newEquip[i];
|
||||
//}
|
||||
try
|
||||
{
|
||||
var actor = (Actor)addr;
|
||||
var identifier = actor.GetIdentifier();
|
||||
|
||||
if (_currentManipulations.TryGetDesign(identifier, out var save))
|
||||
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