mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-20 06:27:43 +01:00
.
This commit is contained in:
parent
80ab57e96d
commit
d1d369a56b
31 changed files with 1637 additions and 80 deletions
|
|
@ -1,8 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Interface.Internal.Notifications;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Customization;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
@ -60,6 +59,26 @@ public sealed class CustomizationService : AsyncServiceWrapper<ICustomizationMan
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary> Returns whether a clan is valid. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsClanValid(SubRace clan)
|
||||
=> AwaitedService.Clans.Contains(clan);
|
||||
|
||||
/// <summary> Returns whether a gender is valid for the given race. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsGenderValid(Race race, Gender gender)
|
||||
=> race is Race.Hrothgar ? gender == Gender.Male : AwaitedService.Genders.Contains(gender);
|
||||
|
||||
/// <summary> Returns whether a customization value is valid for a given clan/gender set and face. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static bool IsCustomizationValid(CustomizationSet set, CustomizeValue face, CustomizeIndex type, CustomizeValue value)
|
||||
=> set.DataByValue(type, value, out _, face) >= 0;
|
||||
|
||||
/// <summary> Returns whether a customization value is valid for a given clan, gender and face. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsCustomizationValid(SubRace race, Gender gender, CustomizeValue face, CustomizeIndex type, CustomizeValue value)
|
||||
=> AwaitedService.GetList(race, gender).DataByValue(type, value, out _, face) >= 0;
|
||||
|
||||
/// <summary>
|
||||
/// Check that the given race and clan are valid.
|
||||
/// The returned race and clan fit together and are valid.
|
||||
|
|
@ -67,7 +86,7 @@ public sealed class CustomizationService : AsyncServiceWrapper<ICustomizationMan
|
|||
/// </summary>
|
||||
public string ValidateClan(SubRace clan, Race race, out Race actualRace, out SubRace actualClan)
|
||||
{
|
||||
if (AwaitedService.Clans.Contains(clan))
|
||||
if (IsClanValid(clan))
|
||||
{
|
||||
actualClan = clan;
|
||||
actualRace = actualClan.ToRace();
|
||||
|
|
@ -113,7 +132,7 @@ public sealed class CustomizationService : AsyncServiceWrapper<ICustomizationMan
|
|||
}
|
||||
|
||||
// TODO: Female Hrothgar
|
||||
if (gender == Gender.Female && race == Race.Hrothgar)
|
||||
if (gender is Gender.Female && race is Race.Hrothgar)
|
||||
{
|
||||
actualGender = Gender.Male;
|
||||
return $"{Race.Hrothgar.ToName()} do not currently support {Gender.Female.ToName()} characters, reset to {Gender.Male.ToName()}.";
|
||||
|
|
@ -134,7 +153,6 @@ public sealed class CustomizationService : AsyncServiceWrapper<ICustomizationMan
|
|||
return modelId != 0 ? $"Model IDs different from 0 are not currently allowed, reset {modelId} to 0." : string.Empty;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Validate a single customization value against a given set of race and gender (and face).
|
||||
/// The returned actualValue is either the correct value or the one with index 0.
|
||||
|
|
@ -143,9 +161,7 @@ public sealed class CustomizationService : AsyncServiceWrapper<ICustomizationMan
|
|||
public static string ValidateCustomizeValue(CustomizationSet set, CustomizeValue face, CustomizeIndex index, CustomizeValue value,
|
||||
out CustomizeValue actualValue)
|
||||
{
|
||||
var count = set.Count(index, face);
|
||||
var idx = set.DataByValue(index, value, out var data, face);
|
||||
if (idx >= 0 && idx < count)
|
||||
if (IsCustomizationValid(set, face, index, value))
|
||||
{
|
||||
actualValue = value;
|
||||
return string.Empty;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Plugin;
|
||||
using Lumina.Excel;
|
||||
|
|
@ -135,6 +136,14 @@ public class ItemManager : IDisposable
|
|||
: new EquipItem($"Unknown ({id.Value}-{type.Value}-{variant})", 0, 0, id, type, variant, 0);
|
||||
}
|
||||
|
||||
/// <summary> Returns whether an item id represents a valid item for a slot and gives the item. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsItemValid(EquipSlot slot, uint itemId, out EquipItem item)
|
||||
{
|
||||
item = Resolve(slot, itemId);
|
||||
return item.Valid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether an item id resolves to an existing item of the correct slot (which should not be weapons.)
|
||||
/// The returned item is either the resolved correct item, or the Nothing item for that slot.
|
||||
|
|
@ -145,22 +154,26 @@ public class ItemManager : IDisposable
|
|||
if (slot is EquipSlot.MainHand or EquipSlot.OffHand)
|
||||
throw new Exception("Internal Error: Used armor functionality for weapons.");
|
||||
|
||||
item = Resolve(slot, itemId);
|
||||
if (item.Valid)
|
||||
if (IsItemValid(slot, itemId, out item))
|
||||
return string.Empty;
|
||||
|
||||
item = NothingItem(slot);
|
||||
return $"The {slot.ToName()} item {itemId} does not exist, reset to Nothing.";
|
||||
}
|
||||
|
||||
/// <summary> Returns whether a stain id is a valid stain. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsStainValid(StainId stain)
|
||||
=> stain.Value == 0 || Stains.ContainsKey(stain);
|
||||
|
||||
/// <summary>
|
||||
/// Check whether a stain id is an existing stain.
|
||||
/// The returned stain id is either the input or 0.
|
||||
/// The return value is an empty string if there was no problem and a warning otherwise.
|
||||
/// </summary>
|
||||
public string ValidateStain(StainId stain, out StainId ret)
|
||||
public string ValidateStain(StainId stain, out StainId ret)
|
||||
{
|
||||
if (stain.Value == 0 || Stains.ContainsKey(stain))
|
||||
if (IsStainValid(stain))
|
||||
{
|
||||
ret = stain;
|
||||
return string.Empty;
|
||||
|
|
@ -170,6 +183,19 @@ public class ItemManager : IDisposable
|
|||
return $"The Stain {stain} does not exist, reset to unstained.";
|
||||
}
|
||||
|
||||
/// <summary> Returns whether an offhand is valid given the required offhand type. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsOffhandValid(FullEquipType offType, uint offId, out EquipItem off)
|
||||
{
|
||||
off = Resolve(offType, offId);
|
||||
return off.Valid;
|
||||
}
|
||||
|
||||
/// <summary> Returns whether an offhand is valid given mainhand. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public bool IsOffhandValid(in EquipItem main, uint offId, out EquipItem off)
|
||||
=> IsOffhandValid(main.Type.Offhand(), offId, out off);
|
||||
|
||||
/// <summary>
|
||||
/// Check whether a combination of an item id for a mainhand and for an offhand is valid.
|
||||
/// The returned items are either the resolved correct items,
|
||||
|
|
@ -180,42 +206,30 @@ public class ItemManager : IDisposable
|
|||
public string ValidateWeapons(uint mainId, uint offId, out EquipItem main, out EquipItem off)
|
||||
{
|
||||
var ret = string.Empty;
|
||||
main = Resolve(EquipSlot.MainHand, mainId);
|
||||
if (!main.Valid)
|
||||
if (!IsItemValid(EquipSlot.MainHand, mainId, out main))
|
||||
{
|
||||
main = DefaultSword;
|
||||
ret = $"The mainhand weapon {mainId} does not exist, reset to default sword.";
|
||||
ret = $"The mainhand weapon {mainId} does not exist, reset to default sword.";
|
||||
}
|
||||
|
||||
var offhandType = main.Type.Offhand();
|
||||
off = Resolve(offhandType, offId);
|
||||
if (off.Valid)
|
||||
var offType = main.Type.Offhand();
|
||||
if (IsOffhandValid(offType, offId, out off))
|
||||
return ret;
|
||||
|
||||
// Try implicit offhand.
|
||||
off = Resolve(offhandType, mainId);
|
||||
if (off.Valid)
|
||||
// Can not be set to default sword before because then it could not be valid.
|
||||
if (IsOffhandValid(offType, mainId, out off))
|
||||
return $"The offhand weapon {offId} does not exist, reset to implied offhand.";
|
||||
|
||||
if (FullEquipTypeExtensions.OffhandTypes.Contains(offType))
|
||||
{
|
||||
// Can not be set to default sword before because then it could not be valid.
|
||||
ret = $"The offhand weapon {offId} does not exist, reset to implied offhand.";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FullEquipTypeExtensions.OffhandTypes.Contains(offhandType))
|
||||
{
|
||||
main = DefaultSword;
|
||||
off = NothingItem(FullEquipType.Shield);
|
||||
ret =
|
||||
$"The offhand weapon {offId} does not exist, but no default could be restored, reset mainhand to default sword and offhand to nothing.";
|
||||
}
|
||||
else
|
||||
{
|
||||
off = NothingItem(offhandType);
|
||||
if (ret.Length == 0)
|
||||
ret = $"The offhand weapon {offId} does not exist, reset to no offhand.";
|
||||
}
|
||||
main = DefaultSword;
|
||||
off = NothingItem(FullEquipType.Shield);
|
||||
return
|
||||
$"The offhand weapon {offId} does not exist, but no default could be restored, reset mainhand to default sword and offhand to nothing.";
|
||||
}
|
||||
|
||||
return ret;
|
||||
off = NothingItem(offType);
|
||||
return ret.Length == 0 ? $"The offhand weapon {offId} does not exist, reset to no offhand." : ret;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Gui;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Gui.Tabs;
|
||||
using Glamourer.Gui.Tabs.ActorTab;
|
||||
using Glamourer.Gui.Tabs.DesignTab;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.State;
|
||||
|
|
@ -49,7 +52,8 @@ public static class ServiceManager
|
|||
private static IServiceCollection AddEvents(this IServiceCollection services)
|
||||
=> services.AddSingleton<VisorStateChanged>()
|
||||
.AddSingleton<UpdatedSlot>()
|
||||
.AddSingleton<DesignChanged>();
|
||||
.AddSingleton<DesignChanged>()
|
||||
.AddSingleton<StateChanged>();
|
||||
|
||||
private static IServiceCollection AddData(this IServiceCollection services)
|
||||
=> services.AddSingleton<IdentifierService>()
|
||||
|
|
@ -76,8 +80,15 @@ public static class ServiceManager
|
|||
private static IServiceCollection AddUi(this IServiceCollection services)
|
||||
=> services.AddSingleton<DebugTab>()
|
||||
.AddSingleton<SettingsTab>()
|
||||
.AddSingleton<ActorTab>()
|
||||
.AddSingleton<ActorSelector>()
|
||||
.AddSingleton<ActorPanel>()
|
||||
.AddSingleton<MainWindow>()
|
||||
.AddSingleton<GlamourerWindowSystem>();
|
||||
.AddSingleton<GlamourerWindowSystem>()
|
||||
.AddSingleton<CustomizationDrawer>()
|
||||
.AddSingleton<DesignFileSystemSelector>()
|
||||
.AddSingleton<DesignPanel>()
|
||||
.AddSingleton<DesignTab>();
|
||||
|
||||
private static IServiceCollection AddApi(this IServiceCollection services)
|
||||
=> services.AddSingleton<CommandService>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue