From e3c48b54dc36ad3bd2e67b880145a8161ae75c8a Mon Sep 17 00:00:00 2001 From: Nathaniel Cosford Date: Wed, 4 Jun 2025 16:13:36 +0930 Subject: [PATCH] Upload from upload_mods.ps1 --- .gitignore | 80 +++++++ FullautoLauncher.csproj | 86 ++++++++ FullautoLauncher.dll | Bin 0 -> 25600 bytes FullautoLauncher.pdb | Bin 0 -> 13648 bytes Harmony/Init.cs | 21 ++ Harmony/Patches.cs | 208 ++++++++++++++++++ ModInfo.xml | 9 + Properties/AssemblyInfo.cs | 36 +++ .../ItemActions/ItemActionBetterLauncher.cs | 138 ++++++++++++ .../CustomProjectileManager.cs | 51 +++++ Scripts/ProjectileManager/PHGameObject.cs | 36 +++ Scripts/ProjectileManager/PHSimpleMesh.cs | 48 ++++ Scripts/ProjectileManager/PIGGameObject.cs | 49 +++++ Scripts/ProjectileManager/PIGSimpleMesh.cs | 54 +++++ .../ProjectileManager/ParameterHolderAbs.cs | 32 +++ .../ProjectileItemGroupAbs.cs | 121 ++++++++++ Scripts/ProjectileManager/ProjectileParams.cs | 188 ++++++++++++++++ 17 files changed, 1157 insertions(+) create mode 100644 .gitignore create mode 100644 FullautoLauncher.csproj create mode 100644 FullautoLauncher.dll create mode 100644 FullautoLauncher.pdb create mode 100644 Harmony/Init.cs create mode 100644 Harmony/Patches.cs create mode 100644 ModInfo.xml create mode 100644 Properties/AssemblyInfo.cs create mode 100644 Scripts/ItemActions/ItemActionBetterLauncher.cs create mode 100644 Scripts/ProjectileManager/CustomProjectileManager.cs create mode 100644 Scripts/ProjectileManager/PHGameObject.cs create mode 100644 Scripts/ProjectileManager/PHSimpleMesh.cs create mode 100644 Scripts/ProjectileManager/PIGGameObject.cs create mode 100644 Scripts/ProjectileManager/PIGSimpleMesh.cs create mode 100644 Scripts/ProjectileManager/ParameterHolderAbs.cs create mode 100644 Scripts/ProjectileManager/ProjectileItemGroupAbs.cs create mode 100644 Scripts/ProjectileManager/ProjectileParams.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f69e0d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,80 @@ +# Build and Object Folders +bin/ +obj/ + +# Nuget packages directory +packages/ + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +x64/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.log +*.vspscc +*.vssscc +.builds + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper* + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help +UpgradeLog*.XML + +# Lightswitch +_Pvt_Extensions +GeneratedArtifacts +*.xap +ModelManifest.xml + +#Backup file +*.bak + +#zzzili +v15/ + diff --git a/FullautoLauncher.csproj b/FullautoLauncher.csproj new file mode 100644 index 0000000..a39e5c8 --- /dev/null +++ b/FullautoLauncher.csproj @@ -0,0 +1,86 @@ + + + + + Debug + AnyCPU + {F485DD15-9EDF-42C3-A31B-66AE0DFB7356} + Library + Properties + FullautoLauncher + FullautoLauncher + v4.8 + 512 + true + + + true + full + false + .\ + DEBUG;TRACE + prompt + 4 + + + portable + true + .\ + TRACE + prompt + 4 + true + + + + ..\0_TFP_Harmony\0Harmony.dll + False + + + ..\..\7DaysToDie_Data\Managed\Assembly-CSharp.dll + False + + + ..\..\7DaysToDie_Data\Managed\LogLibrary.dll + False + + + + + + + + + + + ..\..\7DaysToDie_Data\Managed\UnityEngine.dll + False + + + ..\..\7DaysToDie_Data\Managed\UnityEngine.AnimationModule.dll + False + + + ..\..\7DaysToDie_Data\Managed\UnityEngine.CoreModule.dll + False + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FullautoLauncher.dll b/FullautoLauncher.dll new file mode 100644 index 0000000000000000000000000000000000000000..3ce6192d5c7b7695c5a4103239a08fdcab6e94fd GIT binary patch literal 25600 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 literal 0 HcmV?d00001 diff --git a/Harmony/Init.cs b/Harmony/Init.cs new file mode 100644 index 0000000..c4be087 --- /dev/null +++ b/Harmony/Init.cs @@ -0,0 +1,21 @@ +using FullautoLauncher.Scripts.ProjectileManager; +using System.Reflection; + +public class FullautoLauncherInit : IModApi +{ + private static bool inited = false; + public void InitMod(Mod _modInstance) + { + if(inited) + { + return; + } + inited = true; + Log.Out(" Loading Patch: " + GetType()); + var harmony = new HarmonyLib.Harmony(GetType().ToString()); + harmony.PatchAll(Assembly.GetExecutingAssembly()); + + ModEvents.UnityUpdate.RegisterHandler(CustomProjectileManager.Update); + } +} + diff --git a/Harmony/Patches.cs b/Harmony/Patches.cs new file mode 100644 index 0000000..2d96560 --- /dev/null +++ b/Harmony/Patches.cs @@ -0,0 +1,208 @@ +using FullautoLauncher.Scripts.ProjectileManager; +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using System.Xml.Linq; +using UnityEngine; + +[HarmonyPatch] +class ItemActionLauncherProjectilePatch +{ + public static FieldInfo fldinfo_meta = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Meta)); + public static MethodInfo mtdinfo_gbc = AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.GetBurstCount), new Type[] { typeof(ItemActionData) }); + public static MethodInfo mtdinfo_gac = AccessTools.Method(typeof(AnimatorRangedReloadState), "GetAmmoCount", new Type[] { typeof(EntityAlive), typeof(ItemValue), typeof(Int32) }); + public static MethodInfo mtdinfo_sta = AccessTools.Method(typeof(GameObject), nameof(GameObject.SetActive), new Type[] { typeof(bool) }); + public static int getProjectileCount(ItemActionData _data) + { + int rps = 1; + ItemInventoryData invD = _data != null ? _data.invData : null; + if (invD != null) + { + ItemClass item = invD.itemValue != null ? invD.itemValue.ItemClass : null; + rps = (int)EffectManager.GetValue(PassiveEffects.RoundRayCount, invD.itemValue, rps, invD.holdingEntity, null, item != null ? item.ItemTags | _data.ActionTags : default); + } + return rps > 0 ? rps : 1; + } + + [HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.StartHolding))] + [HarmonyTranspiler] + private static IEnumerable Transpiler_StartHolding_ItemActionLauncher(IEnumerable instructions, ILGenerator generator) + { + var codes = new List(instructions); + + LocalBuilder lbd_rps = generator.DeclareLocal(typeof(int)); + + var list_insert = new List + { + new CodeInstruction(OpCodes.Ldloc_S, lbd_rps), + new CodeInstruction(OpCodes.Mul) + }; + + for (int i = 0; i < codes.Count; i++) + { + if ( codes[i].LoadsField(fldinfo_meta)) + { + codes.InsertRange(i + 1, list_insert); + i += list_insert.Count; + } + } + + codes.InsertRange(0, new CodeInstruction[] + { + new CodeInstruction(OpCodes.Ldarg_1), + CodeInstruction.Call(typeof(ItemActionLauncherProjectilePatch), nameof(getProjectileCount), new Type[] { typeof(ItemActionData) }), + new CodeInstruction(OpCodes.Stloc_S, lbd_rps) + }); + + return codes; + } + + [HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.ItemActionEffects))] + [HarmonyTranspiler] + private static IEnumerable Transpiler_ItemActionEffects_ItemActionLauncher(IEnumerable instructions) + { + var codes = new List(instructions); + + for(int i = 0, totali = codes.Count; i < totali; i++) + { + if (codes[i].Calls(mtdinfo_gbc)) + { + codes.InsertRange(i + 1, new CodeInstruction[] + { + new CodeInstruction(OpCodes.Ldarg_2), + CodeInstruction.Call(typeof(ItemActionLauncherProjectilePatch), nameof(getProjectileCount), new Type[] { typeof(ItemActionData) }) + }); + codes.RemoveRange(i - 2, 3); + break; + } + } + + return codes; + } + + [HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.ConsumeAmmo))] + [HarmonyTranspiler] + private static IEnumerable Transpiler_ConsumeAmmo_ItemActionLauncher(IEnumerable instructions) + { + var codes = new List() + { + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Ldarg_1), + CodeInstruction.Call(typeof(ItemActionRanged), nameof(ItemActionRanged.ConsumeAmmo), new Type[]{ typeof(ItemActionData) }), + new CodeInstruction(OpCodes.Ret) + }; + + return codes; + } + + [HarmonyPatch(typeof(ItemClass), nameof(ItemClass.ExecuteAction))] + [HarmonyTranspiler] + private static IEnumerable Transpiler_ExecuteAction_ItemClass(IEnumerable instructions) + { + var codes = new List(instructions); + + for (int i = 0; i < codes.Count; i++) + { + if (codes[i].opcode == OpCodes.Isinst && codes[i].OperandIs(typeof(ItemActionLauncher))) + { + codes.RemoveRange(i - 2, 4); + break; + } + } + + return codes; + } + + [HarmonyPatch(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.OnStateEnter))] + [HarmonyTranspiler] + private static IEnumerable Transpiler_OnStateEnter_AnimatorRangedReloadState(IEnumerable instructions, ILGenerator generator) + { + var codes = new List(instructions); + + LocalBuilder lbd_rps = generator.DeclareLocal(typeof(int)); + + for (int i = 0, totali = codes.Count; i < totali; i++) + { + if (codes[i].Calls(mtdinfo_gac)) + { + codes.InsertRange(i + 1, new CodeInstruction[] + { + new CodeInstruction(OpCodes.Ldloc_S, 6), + CodeInstruction.Call(typeof(ItemActionLauncherProjectilePatch), nameof(getProjectileCount), new Type[] { typeof(ItemActionData) }), + new CodeInstruction(OpCodes.Stloc_S, lbd_rps), + new CodeInstruction(OpCodes.Ldloc_S, lbd_rps), + new CodeInstruction(OpCodes.Mul) + }); + totali += 5; + break; + } + //else if (codes[i].opcode == OpCodes.Ldc_R4 && codes[i].OperandIs(0.005f)) + //{ + // codes.Insert(i + 2, new CodeInstruction(OpCodes.Ldc_R4, 0f)); + // codes.RemoveRange(i - 2, 4); + // break; + //} + } + + return codes; + } + + [HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.instantiateProjectile))] + [HarmonyPrefix] + private static bool Prefix_instantiateProjectile_ItemActionLauncher(ref Vector3 _positionOffset) + { + _positionOffset = Vector3.zero; + return true; + } + + [HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.instantiateProjectile))] + [HarmonyPostfix] + private static void Postfix_instantiateProjectile_ItemActionLauncher(Transform __result, ItemActionLauncher __instance) + { + if (__instance.Properties.Contains("VisibleInMag") && !__instance.Properties.GetBool("VisibleInMag")) + { + __result.gameObject.SetActive(false); + } + } + + [HarmonyPatch(typeof(GameManager), nameof(GameManager.FixedUpdate))] + [HarmonyPostfix] + private static void Postfix_FixedUpdate_GameManager() + { + CustomProjectileManager.FixedUpdate(); + } + + //custom projectile manager workarounds + private static void ParseProjectileType(XElement _node) + { + string itemName = _node.GetAttribute("name"); + if (string.IsNullOrEmpty(itemName)) + { + return; + } + ItemClass item = ItemClass.GetItemClass(itemName); + for (int i = 0; i < item.Actions.Length; i++) + { + if (item.Actions[i] is ItemActionProjectile proj && proj.Properties.Contains("CustomProjectileType")) + { + CustomProjectileManager.InitClass(item, proj.Properties.GetString("CustomProjectileType")); + } + } + } + + [HarmonyPatch(typeof(ItemClassesFromXml), nameof(ItemClassesFromXml.parseItem))] + [HarmonyPostfix] + private static void Postfix_parseItem_ItemClassesFromXml(XElement _node) + { + ParseProjectileType(_node); + } + + [HarmonyPatch(typeof(GameManager), nameof(GameManager.SaveAndCleanupWorld))] + [HarmonyPostfix] + private static void Postfix_SaveAndCleanupWorld_GameManager() + { + CustomProjectileManager.Cleanup(); + } +} \ No newline at end of file diff --git a/ModInfo.xml b/ModInfo.xml new file mode 100644 index 0000000..82916a2 --- /dev/null +++ b/ModInfo.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b3c7a68 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("FullautoLauncher")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FullautoLauncher")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("f485dd15-9edf-42c3-a31b-66ae0dfb7356")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Scripts/ItemActions/ItemActionBetterLauncher.cs b/Scripts/ItemActions/ItemActionBetterLauncher.cs new file mode 100644 index 0000000..342a340 --- /dev/null +++ b/Scripts/ItemActions/ItemActionBetterLauncher.cs @@ -0,0 +1,138 @@ +using Audio; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine.Scripting; +using UnityEngine; +using FullautoLauncher.Scripts.ProjectileManager; +using static ItemActionLauncher; +using static ItemActionRanged; + +[Preserve] +public class ItemActionBetterLauncher : ItemActionRanged +{ + private IProjectileItemGroup group; + public override ItemActionData CreateModifierData(ItemInventoryData _invData, int _indexInEntityOfAction) + { + return new ItemActionDataBetterLauncher(_invData, _indexInEntityOfAction); + } + + public override void ReadFrom(DynamicProperties _props) + { + base.ReadFrom(_props); + } + + public override void StartHolding(ItemActionData _actionData) + { + base.StartHolding(_actionData); + ItemActionDataBetterLauncher ItemActionDataBetterLauncher = (ItemActionDataBetterLauncher)_actionData; + ItemValue launcherValue = ItemActionDataBetterLauncher.invData.itemValue; + ItemClass forId = ItemClass.GetForId(ItemClass.GetItem(MagazineItemNames[launcherValue.SelectedAmmoTypeIndex], false).type); + group = CustomProjectileManager.Get(forId.Name); + if (launcherValue.Meta != 0 && GetMaxAmmoCount(ItemActionDataBetterLauncher) != 0) + { + group.Pool(launcherValue.Meta * (int)EffectManager.GetValue(PassiveEffects.RoundRayCount, launcherValue, 1f, ItemActionDataBetterLauncher.invData.holdingEntity)); + } + ItemActionDataBetterLauncher.info = new ProjectileParams.ItemInfo() + { + actionData = ItemActionDataBetterLauncher, + itemProjectile = forId, + itemActionProjectile = (ItemActionProjectile)((forId.Actions[0] is ItemActionProjectile) ? forId.Actions[0] : forId.Actions[1]), + itemValueLauncher = launcherValue, + itemValueProjectile = new ItemValue(forId.Id) + }; + } + + public override void OnModificationsChanged(ItemActionData _data) + { + base.OnModificationsChanged(_data); + } + + public override void StopHolding(ItemActionData _data) + { + base.StopHolding(_data); + ItemActionDataBetterLauncher itemActionDataLauncher = (ItemActionDataBetterLauncher)_data; + itemActionDataLauncher.info = null; + } + + public override void SwapAmmoType(EntityAlive _entity, int _ammoItemId = -1) + { + base.SwapAmmoType(_entity, _ammoItemId); + ItemActionDataBetterLauncher ItemActionDataBetterLauncher = (ItemActionDataBetterLauncher)_entity.inventory.holdingItemData.actionData[ActionIndex]; + ItemValue itemValue = ItemActionDataBetterLauncher.invData.itemValue; + ItemClass forId = ItemClass.GetForId(ItemClass.GetItem(MagazineItemNames[itemValue.SelectedAmmoTypeIndex], false).type); + group = CustomProjectileManager.Get(forId.Name); + ItemActionDataBetterLauncher.info = new ProjectileParams.ItemInfo() + { + actionData = ItemActionDataBetterLauncher, + itemProjectile = forId, + itemActionProjectile = (ItemActionProjectile)((forId.Actions[0] is ItemActionProjectile) ? forId.Actions[0] : forId.Actions[1]), + itemValueLauncher = itemValue, + itemValueProjectile = new ItemValue(forId.Id) + }; + } + + public override Vector3 fireShot(int _shotIdx, ItemActionDataRanged _actionData, ref bool hitEntity) + { + hitEntity = true; + return Vector3.zero; + } + + public override void ItemActionEffects(GameManager _gameManager, ItemActionData _actionData, int _firingState, Vector3 _startPos, Vector3 _direction, int _userData = 0) + { + base.ItemActionEffects(_gameManager, _actionData, _firingState, _startPos, _direction, _userData); + if (_firingState == 0) + { + return; + } + EntityAlive entity = _actionData.invData.holdingEntity; + if (entity.isEntityRemote && GameManager.IsDedicatedServer) + { + return; + } + ItemActionDataBetterLauncher ItemActionDataBetterLauncher = (ItemActionDataBetterLauncher)_actionData; + ItemValue holdingItemItemValue = _actionData.invData.holdingEntity.inventory.holdingItemItemValue; + ItemClass forId = ItemClass.GetForId(ItemClass.GetItem(MagazineItemNames[holdingItemItemValue.SelectedAmmoTypeIndex], false).type); + int projCount = (int)EffectManager.GetValue(PassiveEffects.RoundRayCount, ItemActionDataBetterLauncher.invData.itemValue, 1f, ItemActionDataBetterLauncher.invData.holdingEntity); + if (projCount <= 0) + { + return; + } + if (ItemActionDataBetterLauncher.info == null) + { + Log.Error("null info!"); + return; + } + if (ItemActionDataBetterLauncher.projectileJoint == null) + { + return; + } + Vector3 realStartPosition = ItemActionDataBetterLauncher.projectileJoint.position + Origin.position; + for (int i = 0; i < projCount; i++) + { + var par = group.Fire(entity.entityId, ItemActionDataBetterLauncher.info, _startPos, realStartPosition, getDirectionOffset(ItemActionDataBetterLauncher, _direction, i), entity, hitmaskOverride); + } + } + + public override void getImageActionEffectsStartPosAndDirection(ItemActionData _actionData, out Vector3 _startPos, out Vector3 _direction) + { + Ray lookRay = _actionData.invData.holdingEntity.GetLookRay(); + _startPos = lookRay.origin; + _direction = lookRay.direction;//getDirectionOffset(ItemActionDataBetterLauncher, lookRay.direction, 0); + } + + public class ItemActionDataBetterLauncher : ItemActionDataRanged + { + public ItemActionDataBetterLauncher(ItemInventoryData _invData, int _indexInEntityOfAction) + : base(_invData, _indexInEntityOfAction) + { + projectileJoint = (_invData.model?.FindInChilds("ProjectileJoint", false)); + } + + public Transform projectileJoint; + public ProjectileParams.ItemInfo info; + } + +} diff --git a/Scripts/ProjectileManager/CustomProjectileManager.cs b/Scripts/ProjectileManager/CustomProjectileManager.cs new file mode 100644 index 0000000..07fd586 --- /dev/null +++ b/Scripts/ProjectileManager/CustomProjectileManager.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FullautoLauncher.Scripts.ProjectileManager +{ + public static class CustomProjectileManager + { + private static readonly Dictionary dict_item_groups = new Dictionary(); + + public static IProjectileItemGroup Get(string name) => dict_item_groups[name]; + + public static void InitClass(ItemClass item, string typename) + { + if (dict_item_groups.ContainsKey(item.Name)) + { + return; + } + Type type = ReflectionHelpers.GetTypeWithPrefix("PIG", typename); + IProjectileItemGroup group = (IProjectileItemGroup)Activator.CreateInstance(type, new object[] {item}); + dict_item_groups.Add(item.Name, group); + } + + public static void Update() + { + foreach (var group in dict_item_groups.Values) + { + group.Update(); + } + } + + public static void FixedUpdate() + { + foreach (var group in dict_item_groups.Values) + { + group.FixedUpdate(); + } + } + + public static void Cleanup() + { + foreach (var group in dict_item_groups.Values) + { + group.Cleanup(); + } + dict_item_groups.Clear(); + } + } +} diff --git a/Scripts/ProjectileManager/PHGameObject.cs b/Scripts/ProjectileManager/PHGameObject.cs new file mode 100644 index 0000000..548bacc --- /dev/null +++ b/Scripts/ProjectileManager/PHGameObject.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace FullautoLauncher.Scripts.ProjectileManager +{ + public class PHGameObject : ParameterHolderAbs, IDisposable + { + public Transform Transform { get; } + public PHGameObject(Transform transform, ProjectileParams par) : base(par) + { + Transform = transform; + } + + public override void Fire() + { + Transform.gameObject.SetActive(true); + UpdatePosition(); + } + + public override void UpdatePosition() + { + Vector3 realPos = par.renderPosition - Origin.position; + Transform.position = realPos; + Transform.LookAt(realPos + par.moveDir); + } + + public void Dispose() + { + GameObject.Destroy(Transform.gameObject); + } + } +} diff --git a/Scripts/ProjectileManager/PHSimpleMesh.cs b/Scripts/ProjectileManager/PHSimpleMesh.cs new file mode 100644 index 0000000..328ebb2 --- /dev/null +++ b/Scripts/ProjectileManager/PHSimpleMesh.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using static AstarManager; + +namespace FullautoLauncher.Scripts.ProjectileManager +{ + public class SimpleMeshTransformData + { + public readonly Matrix4x4 TRS; + public readonly Bounds bounds; + + public SimpleMeshTransformData(Matrix4x4 TRS, Bounds bounds) + { + this.TRS = TRS; + this.bounds = bounds; + } + } + + public class PHSimpleMesh : ParameterHolderAbs + { + public Matrix4x4 finalMat; + public RenderParams renderParams; + private SimpleMeshTransformData data; + + public PHSimpleMesh(ProjectileParams par, SimpleMeshTransformData data, in RenderParams renderPar) : base(par) + { + this.data = data; + this.renderParams = renderPar; + } + + public override void Fire() + { + UpdatePosition(); + } + + public override void UpdatePosition() + { + finalMat = Matrix4x4.Translate(par.renderPosition - Origin.position) * Matrix4x4.Rotate(Quaternion.LookRotation(par.moveDir)) * data.TRS; + Bounds bounds = data.bounds; + bounds.center = finalMat.MultiplyPoint3x4(bounds.center); + renderParams.worldBounds = bounds; + } + } +} diff --git a/Scripts/ProjectileManager/PIGGameObject.cs b/Scripts/ProjectileManager/PIGGameObject.cs new file mode 100644 index 0000000..2f12c67 --- /dev/null +++ b/Scripts/ProjectileManager/PIGGameObject.cs @@ -0,0 +1,49 @@ +using FullautoLauncher.Scripts.ProjectileManager; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +public class PIGGameObject : ProjectileItemGroupAbs +{ + public PIGGameObject(ItemClass item) : base(item) + { + } + + public override void Cleanup() + { + foreach (var proj in queue_pool) + { + proj.Dispose(); + } + queue_pool.Clear(); + + foreach (var set in dict_fired_projectiles.Values) + { + foreach (var proj in set) + { + proj.Dispose(); + } + } + dict_fired_projectiles.Clear(); + } + + public override void Pool(PHGameObject par) + { + base.Pool(par); + par.Transform.gameObject.SetActive(false); + } + + public override void Update() + { + + } + + protected override PHGameObject Create(ProjectileParams par) + { + return new PHGameObject(item.CloneModel(GameManager.Instance.World, new ItemValue(item.Id), Vector3.zero, null), par); + } +} + diff --git a/Scripts/ProjectileManager/PIGSimpleMesh.cs b/Scripts/ProjectileManager/PIGSimpleMesh.cs new file mode 100644 index 0000000..267e36f --- /dev/null +++ b/Scripts/ProjectileManager/PIGSimpleMesh.cs @@ -0,0 +1,54 @@ +using FullautoLauncher.Scripts.ProjectileManager; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +public class PIGSimpleMesh : ProjectileItemGroupAbs +{ + private Transform renderTrans; + private Mesh mesh; + private RenderParams renderParams; + private SimpleMeshTransformData data; + + public PIGSimpleMesh(ItemClass item) : base(item) + { + renderTrans = item.CloneModel(GameManager.Instance.World, new ItemValue(item.Id), Vector3.zero, null); + MeshFilter filter = renderTrans.GetComponentInChildren(); + mesh = filter.sharedMesh; + MeshRenderer renderer = renderTrans.GetComponentInChildren(); + renderParams = new RenderParams(renderer.material) + { + layer = renderer.gameObject.layer, + lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off, + shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off, + rendererPriority = renderer.rendererPriority, + renderingLayerMask = renderer.renderingLayerMask, + motionVectorMode = MotionVectorGenerationMode.ForceNoMotion + }; + data = new SimpleMeshTransformData(renderer.localToWorldMatrix, mesh.bounds); + } + + public override void Update() + { + if (GameManager.IsDedicatedServer) + { + return; + } + + foreach (var set in dict_fired_projectiles.Values) + { + foreach (var projectile in set) + { + Graphics.RenderMesh(in projectile.renderParams, mesh, 0, projectile.finalMat); + } + } + } + + protected override PHSimpleMesh Create(ProjectileParams par) + { + return new PHSimpleMesh(par, data, in renderParams); + } +} diff --git a/Scripts/ProjectileManager/ParameterHolderAbs.cs b/Scripts/ProjectileManager/ParameterHolderAbs.cs new file mode 100644 index 0000000..3291ee2 --- /dev/null +++ b/Scripts/ProjectileManager/ParameterHolderAbs.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FullautoLauncher.Scripts.ProjectileManager +{ + public abstract class ParameterHolderAbs + { + public ProjectileParams Params => par; + + protected readonly ProjectileParams par; + + protected ParameterHolderAbs(ProjectileParams par) + { + this.par = par; + } + + public override int GetHashCode() + { + return par.ProjectileID; + } + + public abstract void UpdatePosition(); + + public virtual void Fire() + { + + } + } +} diff --git a/Scripts/ProjectileManager/ProjectileItemGroupAbs.cs b/Scripts/ProjectileManager/ProjectileItemGroupAbs.cs new file mode 100644 index 0000000..50813ce --- /dev/null +++ b/Scripts/ProjectileManager/ProjectileItemGroupAbs.cs @@ -0,0 +1,121 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace FullautoLauncher.Scripts.ProjectileManager +{ + public interface IProjectileItemGroup + { + void Pool(int count); + ProjectileParams Fire(int entityID, ProjectileParams.ItemInfo info, Vector3 _idealStartPosition, Vector3 _realStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride = 0, float _radius = 0f); + void Update(); + void FixedUpdate(); + void Cleanup(); + } + + public abstract class ProjectileItemGroupAbs : IProjectileItemGroup where T : ParameterHolderAbs + { + protected readonly Queue queue_pool = new Queue(); + protected readonly Dictionary> dict_fired_projectiles = new Dictionary>(); + protected readonly ItemClass item; + protected readonly int maxPoolCount = 1000; + private int nextID; + private int NextID { get => nextID++; } + + public ProjectileItemGroupAbs(ItemClass item) + { + this.item = item; + } + + protected abstract T Create(ProjectileParams par); + + public virtual void Cleanup() + { + } + + public void Pool(int count) + { + count = Mathf.Min(maxPoolCount - queue_pool.Count, count - queue_pool.Count); + for (int i = 0; i < count; i++) + { + queue_pool.Enqueue(Create(new ProjectileParams(NextID))); + } + } + + public virtual void Pool(T par) + { + if (maxPoolCount > queue_pool.Count) + { + par.Params.bOnIdealPosition = false; + queue_pool.Enqueue(par); + } + } + + public ProjectileParams Fire(int entityID, ProjectileParams.ItemInfo info, Vector3 _idealStartPosition, Vector3 _realStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride = 0, float _radius = 0f) + { + T par = queue_pool.Count == 0 ? Create(new ProjectileParams(NextID)) : queue_pool.Dequeue(); + if(!dict_fired_projectiles.TryGetValue(entityID, out HashSet set)) + { + set = new HashSet(); + dict_fired_projectiles.Add(entityID, set); + } + set.Add(par); + par.Params.Fire(info, _idealStartPosition, _realStartPosition, _flyDirection, _firingEntity, _hmOverride, _radius); + par.Fire(); + return par.Params; + } + + public abstract void Update(); + + private List list_remove = new List(); + public void FixedUpdate() + { + if (GameManager.Instance == null || GameManager.Instance.IsPaused() || GameManager.Instance.World == null) + return; + foreach (var pair in dict_fired_projectiles) + { + EntityAlive entityAlive = GameManager.Instance.World.GetEntity(pair.Key) as EntityAlive; + + list_remove.Clear(); + foreach (var projectile in pair.Value) + { + if (projectile.Params.UpdatePosition()) + { + list_remove.Add(projectile); + } + else + { + projectile.UpdatePosition(); + } + } + + if (entityAlive != null) + { + int prevLayer = 0; + if (entityAlive.emodel != null) + { + prevLayer = entityAlive.GetModelLayer(); + entityAlive.SetModelLayer(2, false, null); + } + foreach (var projectile in pair.Value) + { + if (projectile.Params.CheckCollision(entityAlive)) + { + list_remove.Add(projectile); + } + } + if (entityAlive.emodel != null) + { + entityAlive.SetModelLayer(prevLayer, false, null); + } + } + + foreach (var remove in list_remove) + { + pair.Value.Remove(remove); + Pool(remove); + } + list_remove.Clear(); + } + } + } +} diff --git a/Scripts/ProjectileManager/ProjectileParams.cs b/Scripts/ProjectileManager/ProjectileParams.cs new file mode 100644 index 0000000..c28d525 --- /dev/null +++ b/Scripts/ProjectileManager/ProjectileParams.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace FullautoLauncher.Scripts.ProjectileManager +{ + public class ProjectileParams + { + public int ProjectileID; + public ItemInfo info; + public Vector3 flyDirection; + public Vector3 renderPosition; + public Vector3 velocity; + public Vector3 previousPosition; + public Vector3 currentPosition; + public Vector3 gravity; + public Vector3 moveDir; + public float timeShotStarted; + public int hmOverride; + public float radius; + public bool bOnIdealPosition = false; + public CollisionParticleController waterCollisionParticles = new CollisionParticleController(); + + public ProjectileParams(int projectileID) + { + ProjectileID = projectileID; + } + + public void Fire(ItemInfo _info, Vector3 _idealStartPosition, Vector3 _realStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride = 0, float _radius = 0f) + { + info = _info; + flyDirection = _flyDirection.normalized; + moveDir = flyDirection; + previousPosition = currentPosition = _idealStartPosition; + renderPosition = _realStartPosition; + velocity = flyDirection.normalized * EffectManager.GetValue(PassiveEffects.ProjectileVelocity, info.itemValueLauncher, info.itemActionProjectile.Velocity, _firingEntity as EntityAlive); + hmOverride = _hmOverride; + radius = _radius; + waterCollisionParticles.Init(_firingEntity.entityId, info.itemProjectile.MadeOfMaterial.SurfaceCategory, "water", 16); + gravity = Vector3.up * EffectManager.GetValue(PassiveEffects.ProjectileGravity, info.itemValueLauncher, info.itemActionProjectile.Gravity, _firingEntity as EntityAlive); + timeShotStarted = Time.time; + } + + public override int GetHashCode() + { + return ProjectileID; + } + + public bool UpdatePosition() + { + float flyTime = Time.time - timeShotStarted; + if (flyTime >= info.itemActionProjectile.LifeTime) + { + return true; + } + if (flyTime >= info.itemActionProjectile.FlyTime) + { + velocity += gravity * Time.fixedDeltaTime; + } + moveDir = velocity * Time.fixedDeltaTime; + previousPosition = currentPosition; + currentPosition += moveDir; + renderPosition += moveDir; + if (!bOnIdealPosition) + { + bOnIdealPosition = flyTime > 0.5f; + } + if(!bOnIdealPosition) + { + renderPosition = Vector3.Lerp(renderPosition, currentPosition, flyTime * 2f); + } + //Log.Out($"projectile {ProjectileID} position {currentPosition} entity position {info.actionData.invData.holdingEntity.position}"); + return false; + } + + public bool CheckCollision(EntityAlive entityAlive) + { + //Already checked in ItemActionBetterLauncher.ItemActionEffects, projectiles are not created on dedi if fired from remote entity. + //if(entityAlive.isEntityRemote && GameManager.IsDedicatedServer) + // return true; + World world = GameManager.Instance.World; + Vector3 dir = currentPosition - previousPosition; + Vector3 dirNorm = dir.normalized; + float magnitude = dir.magnitude; + if (magnitude < 0.04f) + { + return false; + } + + Ray ray = new Ray(previousPosition, dir); + waterCollisionParticles.CheckCollision(ray.origin, ray.direction, magnitude, (entityAlive != null) ? entityAlive.entityId : (-1)); + int hitmask = ((hmOverride == 0) ? 80 : hmOverride); + bool bHit = Voxel.Raycast(world, ray, magnitude, -538750997, hitmask, radius); + if (bHit && (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag) || Voxel.voxelRayHitInfo.tag.StartsWith("E_"))) + { + if (entityAlive != null && !entityAlive.isEntityRemote) + { + entityAlive.MinEventContext.Other = ItemActionAttack.FindHitEntity(Voxel.voxelRayHitInfo) as EntityAlive; + ItemActionAttack.AttackHitInfo attackHitInfo = new ItemActionAttack.AttackHitInfo + { + WeaponTypeTag = ItemActionAttack.RangedTag + }; + ItemActionAttack.Hit(Voxel.voxelRayHitInfo, + entityAlive.entityId, + EnumDamageTypes.Piercing, + info.itemActionProjectile.GetDamageBlock(info.itemValueLauncher, ItemActionAttack.GetBlockHit(world, Voxel.voxelRayHitInfo), entityAlive, info.actionData.indexInEntityOfAction), + info.itemActionProjectile.GetDamageEntity(info.itemValueLauncher, entityAlive, info.actionData.indexInEntityOfAction), + 1f, + 1f, + EffectManager.GetValue(PassiveEffects.CriticalChance, info.itemValueLauncher, info.itemProjectile.CritChance.Value, entityAlive, null, info.itemProjectile.ItemTags), + ItemAction.GetDismemberChance(info.actionData, Voxel.voxelRayHitInfo), + info.itemProjectile.MadeOfMaterial.SurfaceCategory, + info.itemActionProjectile.GetDamageMultiplier(), + info.itemActionProjectile.BuffActions, + attackHitInfo, + 1, + info.itemActionProjectile.ActionExp, + info.itemActionProjectile.ActionExpBonusMultiplier, + null, + null, + ItemActionAttack.EnumAttackMode.RealNoHarvesting, + null, + -1, + info.itemValueLauncher); + if (entityAlive.MinEventContext.Other == null) + { + entityAlive.FireEvent(MinEventTypes.onSelfPrimaryActionMissEntity, true); + } + entityAlive.FireEvent(MinEventTypes.onProjectileImpact, false); + MinEventParams.CachedEventParam.Self = entityAlive; + MinEventParams.CachedEventParam.Position = Voxel.voxelRayHitInfo.hit.pos; + MinEventParams.CachedEventParam.ItemValue = info.itemValueProjectile; + MinEventParams.CachedEventParam.Other = entityAlive.MinEventContext.Other; + info.itemProjectile.FireEvent(MinEventTypes.onProjectileImpact, MinEventParams.CachedEventParam); + if (info.itemActionProjectile.Explosion.ParticleIndex > 0) + { + Vector3 vector3 = Voxel.voxelRayHitInfo.hit.pos - dirNorm * 0.1f; + Vector3i vector3i = World.worldToBlockPos(vector3); + if (!world.GetBlock(vector3i).isair) + { + BlockFace blockFace; + vector3i = Voxel.OneVoxelStep(vector3i, vector3, -dirNorm, out vector3, out blockFace); + } + GameManager.Instance.ExplosionServer(Voxel.voxelRayHitInfo.hit.clrIdx, vector3, vector3i, Quaternion.identity, info.itemActionProjectile.Explosion, entityAlive.entityId, 0f, false, info.itemValueProjectile); + } + else if (info.itemProjectile.IsSticky) + { + GameRandom gameRandom = world.GetGameRandom(); + if (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag)) + { + if (gameRandom.RandomFloat < EffectManager.GetValue(PassiveEffects.ProjectileStickChance, info.itemValueLauncher, 0.5f, entityAlive, null, info.itemProjectile.ItemTags | FastTags.Parse(Voxel.voxelRayHitInfo.fmcHit.blockValue.Block.blockMaterial.SurfaceCategory))) + { + global::ProjectileManager.AddProjectileItem(null, -1, Voxel.voxelRayHitInfo.hit.pos, dirNorm, info.itemValueProjectile.type); + } + else + { + GameManager.Instance.SpawnParticleEffectServer(new ParticleEffect("impact_metal_on_wood", Voxel.voxelRayHitInfo.hit.pos, Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace), 1f, Color.white, string.Format("{0}hit{1}", Voxel.voxelRayHitInfo.fmcHit.blockValue.Block.blockMaterial.SurfaceCategory, info.itemProjectile.MadeOfMaterial.SurfaceCategory), null), entityAlive.entityId, false, false); + } + } + else if (gameRandom.RandomFloat < EffectManager.GetValue(PassiveEffects.ProjectileStickChance, info.itemValueLauncher, 0.5f, entityAlive, null, info.itemProjectile.ItemTags)) + { + int id = global::ProjectileManager.AddProjectileItem(null, -1, Voxel.voxelRayHitInfo.hit.pos, dirNorm, info.itemValueProjectile.type); + Utils.SetLayerRecursively(global::ProjectileManager.GetProjectile(id).gameObject, 14, null); + } + else + { + GameManager.Instance.SpawnParticleEffectServer(new ParticleEffect("impact_metal_on_wood", Voxel.voxelRayHitInfo.hit.pos, Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace), 1f, Color.white, "bullethitwood", null), entityAlive.entityId, false, false); + } + } + } + return true; + } + return false; + } + + public class ItemInfo + { + public ItemActionProjectile itemActionProjectile; + public ItemClass itemProjectile; + public ItemValue itemValueProjectile; + public ItemValue itemValueLauncher; + public ItemActionData actionData; + } + } +}