445 lines
19 KiB
C#
445 lines
19 KiB
C#
using KFCommonUtilityLib.Scripts.StaticManagers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace KFCommonUtilityLib.Scripts.Utilities
|
|
{
|
|
public static class MultiActionUtils
|
|
{
|
|
public static readonly string[] ActionMetaNames = new string[]
|
|
{
|
|
"Meta0",
|
|
"Meta1",
|
|
"Meta2",
|
|
"Meta3",
|
|
"Meta4",
|
|
};
|
|
public static readonly string[] ActionSelectedAmmoNames = new string[]
|
|
{
|
|
"AmmoIndex0",
|
|
"AmmoIndex1",
|
|
"AmmoIndex2",
|
|
"AmmoIndex3",
|
|
"AmmoIndex4",
|
|
};
|
|
public static readonly int ExecutingActionIndexHash = Animator.StringToHash("ExecutingActionIndex");
|
|
|
|
public static void SetMinEventArrays()
|
|
{
|
|
MinEvent.Start = new[]
|
|
{
|
|
MinEventTypes.onSelfPrimaryActionStart,
|
|
MinEventTypes.onSelfSecondaryActionStart,
|
|
MinEventTypes.onSelfAction2Start,
|
|
MinEventTypes.onSelfPrimaryActionStart,
|
|
MinEventTypes.onSelfPrimaryActionStart,
|
|
};
|
|
|
|
MinEvent.Update = new[]
|
|
{
|
|
MinEventTypes.onSelfPrimaryActionUpdate,
|
|
MinEventTypes.onSelfSecondaryActionUpdate,
|
|
MinEventTypes.onSelfAction2Update,
|
|
MinEventTypes.onSelfPrimaryActionUpdate,
|
|
MinEventTypes.onSelfPrimaryActionUpdate,
|
|
};
|
|
|
|
MinEvent.End = new[]
|
|
{
|
|
MinEventTypes.onSelfPrimaryActionEnd,
|
|
MinEventTypes.onSelfSecondaryActionEnd,
|
|
MinEventTypes.onSelfAction2End,
|
|
MinEventTypes.onSelfPrimaryActionEnd,
|
|
MinEventTypes.onSelfPrimaryActionEnd,
|
|
};
|
|
}
|
|
|
|
//public static int GetActionIndexForItemValue(this ItemValue self)
|
|
//{
|
|
// object val = self.GetMetadata(MultiActionMapping.STR_MULTI_ACTION_INDEX);
|
|
// if (val is int index)
|
|
// return index;
|
|
// return 0;
|
|
//}
|
|
|
|
public static string GetPropertyName(int index, string prop)
|
|
{
|
|
return $"Action{index}.{prop}";
|
|
}
|
|
|
|
public static void FixedItemReloadServer(int entityId, int actionIndex)
|
|
{
|
|
if (GameManager.Instance.World == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FixedItemReloadClient(entityId, actionIndex);
|
|
|
|
if (!SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
|
|
{
|
|
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(NetPackageManager.GetPackage<NetPackageFixedReload>().Setup(entityId, actionIndex), false);
|
|
return;
|
|
}
|
|
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageFixedReload>().Setup(entityId, actionIndex), false, -1, entityId);
|
|
}
|
|
|
|
public static void FixedItemReloadClient(int entityId, int actionIndex)
|
|
{
|
|
if (GameManager.Instance.World == null)
|
|
{
|
|
return;
|
|
}
|
|
EntityAlive entityAlive = (EntityAlive)GameManager.Instance.World.GetEntity(entityId);
|
|
if (entityAlive != null && entityAlive.inventory.holdingItem.Actions[actionIndex] is ItemActionRanged actionRanged)
|
|
{
|
|
entityAlive.MinEventContext.ItemActionData = entityAlive.inventory.holdingItemData.actionData[actionIndex];
|
|
actionRanged.ReloadGun(entityAlive.inventory.holdingItemData.actionData[actionIndex]);
|
|
}
|
|
}
|
|
|
|
public static void CopyLauncherValueToProjectile(ItemValue launcherValue, ItemValue projectileValue, int index)
|
|
{
|
|
projectileValue.Meta = launcherValue.type;
|
|
projectileValue.SelectedAmmoTypeIndex = (byte)index;
|
|
projectileValue.UseTimes = launcherValue.UseTimes;
|
|
projectileValue.Quality = launcherValue.Quality;
|
|
projectileValue.Modifications = new ItemValue[launcherValue.Modifications.Length];
|
|
Array.Copy(launcherValue.Modifications, projectileValue.Modifications, launcherValue.Modifications.Length);
|
|
projectileValue.CosmeticMods = new ItemValue[launcherValue.CosmeticMods.Length];
|
|
Array.Copy(launcherValue.CosmeticMods, projectileValue.CosmeticMods, launcherValue.CosmeticMods.Length);
|
|
}
|
|
|
|
public static void SetMinEventParamsActionData(EntityAlive entity, int actionIndex)
|
|
{
|
|
if (actionIndex >= 0 && actionIndex < entity.inventory?.holdingItemData?.actionData?.Count)
|
|
entity.MinEventContext.ItemActionData = entity.inventory.holdingItemData.actionData[actionIndex];
|
|
}
|
|
|
|
public static string GetPropertyOverrideForAction(this ItemValue self, string _propertyName, string _originalValue, int actionIndex)
|
|
{
|
|
if (self.Modifications.Length == 0 && self.CosmeticMods.Length == 0)
|
|
{
|
|
return _originalValue;
|
|
}
|
|
string text = "";
|
|
ItemClass item = self.ItemClass;
|
|
for (int i = 0; i < self.Modifications.Length; i++)
|
|
{
|
|
ItemValue itemValue = self.Modifications[i];
|
|
if (itemValue != null)
|
|
{
|
|
if (itemValue.ItemClass is ItemClassModifier mod && GetPropertyOverrideForMod(mod, _propertyName, item, ref text, actionIndex))
|
|
{
|
|
return text;
|
|
}
|
|
}
|
|
}
|
|
text = "";
|
|
for (int j = 0; j < self.CosmeticMods.Length; j++)
|
|
{
|
|
ItemValue itemValue2 = self.CosmeticMods[j];
|
|
if (itemValue2 != null)
|
|
{
|
|
if (itemValue2.ItemClass is ItemClassModifier cos && GetPropertyOverrideForMod(cos, _propertyName, item, ref text, actionIndex))
|
|
{
|
|
return text;
|
|
}
|
|
}
|
|
}
|
|
return _originalValue;
|
|
}
|
|
|
|
public static IEnumerable<string> GetAllPropertyOverridesForAction(this ItemValue self, string _propertyName, int actionIndex)
|
|
{
|
|
if (self.Modifications.Length == 0 && self.CosmeticMods.Length == 0)
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
string text = "";
|
|
ItemClass item = self.ItemClass;
|
|
for (int i = 0; i < self.Modifications.Length; i++)
|
|
{
|
|
ItemValue itemValue = self.Modifications[i];
|
|
if (itemValue != null)
|
|
{
|
|
if (itemValue.ItemClass is ItemClassModifier mod && GetPropertyOverrideForMod(mod, _propertyName, item, ref text, actionIndex))
|
|
{
|
|
yield return text;
|
|
}
|
|
}
|
|
}
|
|
text = "";
|
|
for (int j = 0; j < self.CosmeticMods.Length; j++)
|
|
{
|
|
ItemValue itemValue2 = self.CosmeticMods[j];
|
|
if (itemValue2 != null)
|
|
{
|
|
if (itemValue2.ItemClass is ItemClassModifier cos && GetPropertyOverrideForMod(cos, _propertyName, item, ref text, actionIndex))
|
|
{
|
|
yield return text;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool GetPropertyOverrideForMod(ItemClassModifier mod, string _propertyName, ItemClass _item, ref string _value, int actionIndex)
|
|
{
|
|
//Log.Out($"Get property override for item {_item.Name} itemID{_item.Id} property {_propertyName} mod {mod.Name} modID {mod.Id} action {actionIndex} should exclude {MultiActionManager.ShouldExcludeMod(_item.Id, mod.Id, actionIndex)}");
|
|
if (MultiActionManager.ShouldExcludeProperty(_item.Id, mod.Id, actionIndex))
|
|
return false;
|
|
string _itemName = _item.GetItemName();
|
|
string itemNameWithActionIndex = $"{_itemName}_{actionIndex}";
|
|
if (mod.PropertyOverrides.ContainsKey(itemNameWithActionIndex) && mod.PropertyOverrides[itemNameWithActionIndex].Values.ContainsKey(_propertyName))
|
|
{
|
|
_value = mod.PropertyOverrides[itemNameWithActionIndex].Values[_propertyName];
|
|
return true;
|
|
}
|
|
if (mod.PropertyOverrides.ContainsKey(_itemName) && mod.PropertyOverrides[_itemName].Values.ContainsKey(_propertyName))
|
|
{
|
|
_value = mod.PropertyOverrides[_itemName].Values[_propertyName];
|
|
return true;
|
|
}
|
|
itemNameWithActionIndex = $"*_{actionIndex}";
|
|
if (mod.PropertyOverrides.ContainsKey(itemNameWithActionIndex) && mod.PropertyOverrides[itemNameWithActionIndex].Values.ContainsKey(_propertyName))
|
|
{
|
|
_value = mod.PropertyOverrides[itemNameWithActionIndex].Values[_propertyName];
|
|
return true;
|
|
}
|
|
if (mod.PropertyOverrides.ContainsKey("*") && mod.PropertyOverrides["*"].Values.ContainsKey(_propertyName))
|
|
{
|
|
_value = mod.PropertyOverrides["*"].Values[_propertyName];
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static int GetMode(this ItemValue self)
|
|
{
|
|
object mode = self.GetMetadata(MultiActionMapping.STR_MULTI_ACTION_INDEX);
|
|
if (mode is int v)
|
|
{
|
|
return v;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public static int GetActionIndexByEntityEventParams(EntityAlive entity)
|
|
{
|
|
return GetActionIndexByEventParams(entity?.MinEventContext ?? MinEventParams.CachedEventParam);
|
|
}
|
|
|
|
public static int GetActionIndexByEventParams(MinEventParams pars)
|
|
{
|
|
if (pars?.ItemActionData == null)
|
|
return 0;
|
|
return pars.ItemActionData.indexInEntityOfAction;
|
|
}
|
|
|
|
public static int GetActionIndexByMetaData(this ItemValue self)
|
|
{
|
|
int mode = self.GetMode();
|
|
MultiActionIndice indice = MultiActionManager.GetActionIndiceForItemID(self.type);
|
|
return indice.GetActionIndexForMode(mode);
|
|
}
|
|
|
|
public static int GetSelectedAmmoIndexByMode(this ItemValue self, int mode)
|
|
{
|
|
MultiActionIndice indice = MultiActionManager.GetActionIndiceForItemID(self.type);
|
|
int metaIndex = indice.GetMetaIndexForMode(mode);
|
|
if (metaIndex >= 0)
|
|
{
|
|
object ammoIndex = self.GetMetadata(ActionSelectedAmmoNames[metaIndex]);
|
|
if (ammoIndex is int)
|
|
{
|
|
return (int)ammoIndex;
|
|
}
|
|
}
|
|
return self.SelectedAmmoTypeIndex;
|
|
}
|
|
|
|
public static int GetMetaByMode(this ItemValue self, int mode)
|
|
{
|
|
MultiActionIndice indice = MultiActionManager.GetActionIndiceForItemID(self.type);
|
|
int metaIndex = indice.GetMetaIndexForMode(mode);
|
|
if (metaIndex >= 0)
|
|
{
|
|
object meta = self.GetMetadata(ActionMetaNames[metaIndex]);
|
|
if (meta is int)
|
|
{
|
|
return (int)meta;
|
|
}
|
|
}
|
|
return self.Meta;
|
|
}
|
|
|
|
public static int GetSelectedAmmoIndexByActionIndex(this ItemValue self, int actionIndex)
|
|
{
|
|
MultiActionIndice indice = MultiActionManager.GetActionIndiceForItemID(self.type);
|
|
int mode = indice.GetModeForAction(actionIndex);
|
|
if (mode < 0)
|
|
return self.SelectedAmmoTypeIndex;
|
|
int metaIndex = indice.GetMetaIndexForMode(mode);
|
|
if (metaIndex >= 0)
|
|
{
|
|
object ammoIndex = self.GetMetadata(ActionSelectedAmmoNames[metaIndex]);
|
|
if (ammoIndex is int)
|
|
{
|
|
return (int)ammoIndex;
|
|
}
|
|
}
|
|
return self.SelectedAmmoTypeIndex;
|
|
}
|
|
|
|
public static int GetMetaByActionIndex(this ItemValue self, int actionIndex)
|
|
{
|
|
MultiActionIndice indice = MultiActionManager.GetActionIndiceForItemID(self.type);
|
|
int mode = indice.GetModeForAction(actionIndex);
|
|
if (mode < 0)
|
|
return self.Meta;
|
|
int metaIndex = indice.GetMetaIndexForMode(mode);
|
|
if (metaIndex >= 0)
|
|
{
|
|
object meta = self.GetMetadata(ActionMetaNames[metaIndex]);
|
|
if (meta is int)
|
|
{
|
|
//Log.Out($"GetMetaByActionIndex: mode: {mode}, action: {metaIndex}, meta: {(int)meta}\n{StackTraceUtility.ExtractStackTrace()}");
|
|
return (int)meta;
|
|
}
|
|
}
|
|
|
|
return self.Meta;
|
|
}
|
|
|
|
public static void SetMinEventParamsByEntityInventory(EntityAlive entity)
|
|
{
|
|
if (entity != null && entity.MinEventContext != null)
|
|
{
|
|
entity.MinEventContext.ItemActionData = entity.inventory?.holdingItemData?.actionData[MultiActionManager.GetActionIndexForEntity(entity)];
|
|
}
|
|
}
|
|
|
|
public static bool MultiActionRemoveAmmoFromItemStack(ItemStack stack, List<ItemStack> result)
|
|
{
|
|
ItemValue itemValue = stack.itemValue;
|
|
object mode = itemValue.GetMetadata(MultiActionMapping.STR_MULTI_ACTION_INDEX);
|
|
if (mode is false || mode is null)
|
|
{
|
|
return false;
|
|
}
|
|
MultiActionIndice indices = MultiActionManager.GetActionIndiceForItemID(itemValue.type);
|
|
ItemClass item = ItemClass.GetForId(itemValue.type);
|
|
for (int i = 0; i < MultiActionIndice.MAX_ACTION_COUNT; i++)
|
|
{
|
|
int metaIndex = indices.GetMetaIndexForMode(i);
|
|
if (metaIndex < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int actionIndex = indices.GetActionIndexForMode(i);
|
|
if (item.Actions[actionIndex] is ItemActionRanged ranged && !(ranged is ItemActionTextureBlock))
|
|
{
|
|
object meta = itemValue.GetMetadata(MultiActionUtils.ActionMetaNames[metaIndex]);
|
|
object ammoIndex = itemValue.GetMetadata(MultiActionUtils.ActionSelectedAmmoNames[metaIndex]);
|
|
if (meta is int && ammoIndex is int && (int)meta > 0)
|
|
{
|
|
itemValue.SetMetadata(MultiActionUtils.ActionMetaNames[metaIndex], 0, TypedMetadataValue.TypeTag.Integer);
|
|
ItemStack ammoStack = new ItemStack(ItemClass.GetItem(ranged.MagazineItemNames[(int)ammoIndex]), (int)meta);
|
|
result.Add(ammoStack);
|
|
Log.Out($"Remove ammo: metadata {MultiActionUtils.ActionMetaNames[metaIndex]}, meta {(int)meta}, left {itemValue.GetMetadata(MultiActionUtils.ActionMetaNames[metaIndex])}");
|
|
}
|
|
}
|
|
}
|
|
itemValue.Meta = 0;
|
|
return true;
|
|
}
|
|
|
|
public static readonly ItemActionData[] DummyActionDatas = new ItemActionData[]
|
|
{
|
|
new ItemActionData(null, 0),
|
|
new ItemActionData(null, 3),
|
|
new ItemActionData(null, 4)
|
|
};
|
|
|
|
public static int GetMultiActionInitialMetaData(this ItemClass itemClass, ItemValue itemValue)
|
|
{
|
|
MultiActionIndice indice = MultiActionManager.GetActionIndiceForItemID(itemClass.Id);
|
|
if (indice.modeCount <= 1)
|
|
{
|
|
return itemClass.GetInitialMetadata(itemValue);
|
|
}
|
|
|
|
var prevItemValue = MinEventParams.CachedEventParam.ItemValue;
|
|
var prevActionData = MinEventParams.CachedEventParam.ItemActionData;
|
|
MinEventParams.CachedEventParam.ItemValue = itemValue;
|
|
itemValue.SetMetadata(MultiActionMapping.STR_MULTI_ACTION_INDEX, 0, TypedMetadataValue.TypeTag.Integer);
|
|
int ret = 0;
|
|
for (int i = 0; i < indice.modeCount; i++)
|
|
{
|
|
MinEventParams.CachedEventParam.ItemActionData = DummyActionDatas[i];
|
|
|
|
ItemAction itemAction = itemClass.Actions[indice.GetActionIndexForMode(i)];
|
|
int meta = itemAction.GetInitialMeta(itemValue);
|
|
if (i == 0)
|
|
{
|
|
ret = meta;
|
|
}
|
|
else if (itemAction.Properties.Contains("ActionUnlocked") && !itemAction.Properties.GetBool("ActionUnlocked"))
|
|
{
|
|
meta = 0;
|
|
}
|
|
if (indice.GetMetaIndexForMode(i) == indice.GetActionIndexForMode(i))
|
|
itemValue.SetMetadata(MultiActionUtils.ActionMetaNames[indice.GetMetaIndexForMode(i)], meta, TypedMetadataValue.TypeTag.Integer);
|
|
}
|
|
MinEventParams.CachedEventParam.ItemValue = prevItemValue;
|
|
MinEventParams.CachedEventParam.ItemActionData = prevActionData;
|
|
return ret;
|
|
}
|
|
|
|
public static void SetCachedEventParamsDummyAction(ItemStack itemStack)
|
|
{
|
|
ItemClass itemClass = itemStack?.itemValue?.ItemClass;
|
|
if (itemClass != null)
|
|
{
|
|
MinEventParams.CachedEventParam.ItemActionData = MultiActionUtils.DummyActionDatas[itemStack.itemValue.GetMode()];
|
|
MinEventParams.CachedEventParam.ItemValue = itemStack.itemValue;
|
|
MinEventParams.CachedEventParam.Seed = itemStack.itemValue.Seed;
|
|
}
|
|
}
|
|
|
|
public static string GetDisplayTypeForAction(ItemStack itemStack)
|
|
{
|
|
return GetDisplayTypeForAction(itemStack?.itemValue);
|
|
}
|
|
|
|
public static string GetDisplayTypeForAction(ItemValue itemValue)
|
|
{
|
|
if (itemValue == null || itemValue.IsEmpty())
|
|
{
|
|
return "";
|
|
}
|
|
if (itemValue.ItemClass.Actions[itemValue.GetActionIndexByMetaData()] is IModuleContainerFor<ActionModuleMultiActionFix> module)
|
|
{
|
|
return module.Instance.GetDisplayType(itemValue);
|
|
}
|
|
return itemValue.ItemClass.DisplayType;
|
|
}
|
|
|
|
public static bool CanCompare(ItemValue itemValue1, ItemValue itemValue2)
|
|
{
|
|
if (itemValue1 == null || itemValue2 == null || itemValue1.IsEmpty() || itemValue2.IsEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string displayType1 = itemValue1.ItemClass.IsBlock() ? Block.list[itemValue1.ItemClass.Id].DisplayType : GetDisplayTypeForAction(itemValue1);
|
|
string displayType2 = itemValue2.ItemClass.IsBlock() ? Block.list[itemValue2.ItemClass.Id].DisplayType : GetDisplayTypeForAction(itemValue2);
|
|
ItemDisplayEntry displayStatsForTag = UIDisplayInfoManager.Current.GetDisplayStatsForTag(displayType1);
|
|
ItemDisplayEntry displayStatsForTag2 = UIDisplayInfoManager.Current.GetDisplayStatsForTag(displayType2);
|
|
return displayStatsForTag != null && displayStatsForTag2 != null && displayStatsForTag.DisplayGroup == displayStatsForTag2.DisplayGroup;
|
|
}
|
|
}
|
|
} |