357 lines
14 KiB
C#
357 lines
14 KiB
C#
#if NotEditor
|
|
using KFCommonUtilityLib;
|
|
|
|
#endif
|
|
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
[AddComponentMenu("KFAttachments/Utils/Animation Reload Events")]
|
|
public class AnimationReloadEvents : MonoBehaviour, IPlayableGraphRelated
|
|
{
|
|
private void Awake()
|
|
{
|
|
animator = GetComponent<Animator>();
|
|
#if NotEditor
|
|
player = GetComponentInParent<EntityAlive>();
|
|
#endif
|
|
}
|
|
|
|
public void OnReloadFinish()
|
|
{
|
|
OnReloadAmmo();
|
|
OnReloadEnd();
|
|
}
|
|
|
|
public void OnReloadAmmo()
|
|
{
|
|
#if NotEditor
|
|
if (actionData == null || !actionData.isReloading)
|
|
{
|
|
#if DEBUG
|
|
Log.Out($"ANIMATION RELOAD EVENT NOT RELOADING : {actionData?.invData.item.Name ?? "null"}");
|
|
#endif
|
|
return;
|
|
}
|
|
if (!actionData.isReloadCancelled)
|
|
{
|
|
player.MinEventContext.ItemActionData = actionData;
|
|
ItemValue item = ItemClass.GetItem(actionRanged.MagazineItemNames[actionData.invData.itemValue.SelectedAmmoTypeIndex], false);
|
|
int magSize = actionRanged.GetMaxAmmoCount(actionData);
|
|
actionData.reloadAmount = GetAmmoCountToReload(player, item, magSize);
|
|
if (actionData.reloadAmount > 0)
|
|
{
|
|
actionData.invData.itemValue.Meta = Utils.FastMin(actionData.invData.itemValue.Meta + actionData.reloadAmount, magSize);
|
|
if (actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle] != null)
|
|
{
|
|
actionData.invData.holdingEntitySoundID = -1;
|
|
}
|
|
}
|
|
#if DEBUG
|
|
Log.Out($"ANIMATION RELOAD EVENT AMMO : {actionData.invData.item.Name}");
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public void OnReloadEnd()
|
|
{
|
|
StopAllCoroutines();
|
|
animator.SetWrappedBool(Animator.StringToHash("Reload"), false);
|
|
animator.SetWrappedBool(Animator.StringToHash("IsReloading"), false);
|
|
animator.speed = 1f;
|
|
#if NotEditor
|
|
cancelReloadCo = null;
|
|
if (actionData == null || !actionData.isReloading)
|
|
{
|
|
return;
|
|
}
|
|
actionData.isReloading = false;
|
|
actionData.isWeaponReloading = false;
|
|
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
|
actionData.invData.holdingEntity.FireEvent(MinEventTypes.onReloadStop, true);
|
|
actionData.invData.holdingEntity.OnReloadEnd();
|
|
actionData.invData.holdingEntity.inventory.CallOnToolbeltChangedInternal();
|
|
AnimationAmmoUpdateState.SetAmmoCountForEntity(actionData.invData.holdingEntity, actionData.invData.slotIdx);
|
|
actionData.isReloadCancelled = false;
|
|
actionData.isWeaponReloadCancelled = false;
|
|
actionData.isChangingAmmoType = false;
|
|
if (actionData is IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData> dataModule)
|
|
{
|
|
dataModule.Instance.SetCurrentBarrel(actionData.invData.itemValue.Meta);
|
|
}
|
|
#if DEBUG
|
|
Log.Out($"ANIMATION RELOAD EVENT FINISHED : {actionData.invData.item.Name}");
|
|
#endif
|
|
actionData = null;
|
|
#endif
|
|
}
|
|
|
|
public void OnPartialReloadEnd()
|
|
{
|
|
#if NotEditor
|
|
if (actionData == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
player.MinEventContext.ItemActionData = actionData;
|
|
ItemValue ammo = ItemClass.GetItem(actionRanged.MagazineItemNames[actionData.invData.itemValue.SelectedAmmoTypeIndex], false);
|
|
int magSize = (int)EffectManager.GetValue(PassiveEffects.MagazineSize, actionData.invData.itemValue, (float)actionRanged.BulletsPerMagazine, player);
|
|
int partialReloadCount = (int)EffectManager.GetValue(CustomEnums.PartialReloadCount, actionData.invData.itemValue, 1, player);
|
|
actionData.reloadAmount = GetPartialReloadCount(player, ammo, magSize, partialReloadCount);
|
|
if (actionData.reloadAmount > 0)
|
|
{
|
|
actionData.invData.itemValue.Meta = Utils.FastMin(actionData.invData.itemValue.Meta + actionData.reloadAmount, magSize);
|
|
if (actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle] != null)
|
|
{
|
|
actionData.invData.holdingEntitySoundID = -1;
|
|
}
|
|
}
|
|
AnimationAmmoUpdateState.SetAmmoCountForEntity(actionData.invData.holdingEntity, actionData.invData.slotIdx);
|
|
|
|
if (actionData.isReloadCancelled || actionData.isWeaponReloadCancelled || actionData.invData.itemValue.Meta >= magSize || player.GetItemCount(ammo) <= 0)
|
|
{
|
|
Log.Out("Partial reload finished");
|
|
animator.SetWrappedBool(Animator.StringToHash("IsReloading"), false);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if NotEditor
|
|
//public bool ReloadUpdatedThisFrame => reloadUpdatedThisFrame;
|
|
//private bool reloadUpdatedThisFrame = false;
|
|
//internal void OnReloadUpdate()
|
|
//{
|
|
// reloadUpdatedThisFrame = true;
|
|
//}
|
|
|
|
//private void OnAnimatorMove()
|
|
//{
|
|
// if (actionData != null)
|
|
// {
|
|
// //if (actionData.isReloading && !reloadUpdatedThisFrame)
|
|
// //{
|
|
// // Log.Warning("Animator not sending update msg this frame, reloading is cancelled!");
|
|
// // actionData.isReloadCancelled = true;
|
|
// // OnReloadFinish();
|
|
// //}
|
|
// }
|
|
// else
|
|
// {
|
|
// //Log.Warning("actionData is null!");
|
|
// }
|
|
// reloadUpdatedThisFrame = false;
|
|
//}
|
|
|
|
public void OnReloadStart(int actionIndex)
|
|
{
|
|
if (player == null)
|
|
{
|
|
player = GetComponentInParent<EntityAlive>();
|
|
}
|
|
actionData = player.inventory.holdingItemData.actionData[actionIndex] as ItemActionRanged.ItemActionDataRanged;
|
|
actionRanged = (ItemActionRanged)player.inventory.holdingItem.Actions[actionIndex];
|
|
if (actionData == null || actionData.isReloading)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle] != null && actionData.invData.holdingEntitySoundID >= 0)
|
|
{
|
|
Audio.Manager.Stop(actionData.invData.holdingEntity.entityId, actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle]);
|
|
}
|
|
actionData.wasAiming = actionData.invData.holdingEntity.AimingGun;
|
|
if (actionData.invData.holdingEntity.AimingGun && actionData.invData.item.Actions[1] is ItemActionZoom)
|
|
{
|
|
actionData.invData.holdingEntity.inventory.Execute(1, false, null);
|
|
actionData.invData.holdingEntity.inventory.Execute(1, true, null);
|
|
}
|
|
if (animator.GetCurrentAnimatorClipInfo(0).Length != 0 && animator.GetCurrentAnimatorClipInfo(0)[0].clip.events.Length == 0)
|
|
{
|
|
if (actionRanged.SoundReload != null)
|
|
{
|
|
player.PlayOneShot(actionRanged.SoundReload.Value, false);
|
|
}
|
|
}
|
|
else if (animator.GetNextAnimatorClipInfo(0).Length != 0 && animator.GetNextAnimatorClipInfo(0)[0].clip.events.Length == 0 && actionRanged.SoundReload != null)
|
|
{
|
|
player.PlayOneShot(actionRanged.SoundReload.Value, false);
|
|
}
|
|
|
|
ItemValue itemValue = actionData.invData.itemValue;
|
|
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
|
int magSize = (int)EffectManager.GetValue(PassiveEffects.MagazineSize, itemValue, actionRanged.BulletsPerMagazine, actionData.invData.holdingEntity);
|
|
ItemActionLauncher itemActionLauncher = actionRanged as ItemActionLauncher;
|
|
if (itemActionLauncher != null && itemValue.Meta < magSize)
|
|
{
|
|
ItemValue ammoValue = ItemClass.GetItem(actionRanged.MagazineItemNames[itemValue.SelectedAmmoTypeIndex], false);
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"loading ammo {ammoValue.ItemClass.Name}");
|
|
ItemActionLauncher.ItemActionDataLauncher itemActionDataLauncher = actionData as ItemActionLauncher.ItemActionDataLauncher;
|
|
if (itemActionDataLauncher.isChangingAmmoType)
|
|
{
|
|
if (ConsoleCmdReloadLog.LogInfo)
|
|
Log.Out($"is changing ammo type {itemActionDataLauncher.isChangingAmmoType}");
|
|
itemActionLauncher.DeleteProjectiles(actionData);
|
|
itemActionDataLauncher.isChangingAmmoType = false;
|
|
}
|
|
int projectileCount = 1;
|
|
if (!actionData.invData.holdingEntity.isEntityRemote)
|
|
{
|
|
projectileCount = (itemActionLauncher.HasInfiniteAmmo(actionData) ? magSize : GetAmmoCount(actionData.invData.holdingEntity, ammoValue, magSize));
|
|
projectileCount *= getProjectileCount(itemActionDataLauncher);
|
|
}
|
|
int times = 1;
|
|
IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData> dataModule = actionData as IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData>;
|
|
if (dataModule != null && dataModule.Instance.oneRoundMultishot)
|
|
{
|
|
times = dataModule.Instance.roundsPerShot;
|
|
}
|
|
for (int j = itemActionDataLauncher.projectileInstance.Count; j < projectileCount; j++)
|
|
{
|
|
for (int i = 0; i < times; i++)
|
|
{
|
|
if (dataModule != null)
|
|
{
|
|
itemActionDataLauncher.projectileJoint = dataModule.Instance.projectileJoints[i];
|
|
}
|
|
itemActionDataLauncher.projectileInstance.Add(itemActionLauncher.instantiateProjectile(actionData, Vector3.zero));
|
|
}
|
|
}
|
|
}
|
|
actionData.isReloading = true;
|
|
actionData.isWeaponReloading = true;
|
|
actionData.invData.holdingEntity.FireEvent(MinEventTypes.onReloadStart, true);
|
|
#if DEBUG
|
|
Log.Out($"ANIMATION EVENT RELOAD START : {actionData.invData.item.Name}");
|
|
#endif
|
|
}
|
|
|
|
private Coroutine cancelReloadCo = null;
|
|
|
|
public void DelayForceCancelReload(float delay)
|
|
{
|
|
if (cancelReloadCo == null)
|
|
cancelReloadCo = StartCoroutine(ForceCancelReloadCo(delay));
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (animator)
|
|
{
|
|
OnReloadEnd();
|
|
}
|
|
}
|
|
|
|
private IEnumerator ForceCancelReloadCo(float delay)
|
|
{
|
|
yield return new WaitForSecondsRealtime(delay);
|
|
if (actionData != null && (actionData.isReloading || actionData.isWeaponReloading) && (actionData.isReloadCancelled || actionData.isWeaponReloadCancelled))
|
|
OnReloadEnd();
|
|
cancelReloadCo = null;
|
|
}
|
|
|
|
public int GetAmmoCountToReload(EntityAlive ea, ItemValue ammo, int modifiedMagazineSize)
|
|
{
|
|
int meta = actionData.invData.itemValue.Meta;
|
|
int target = modifiedMagazineSize - meta;
|
|
if (actionRanged.HasInfiniteAmmo(actionData))
|
|
{
|
|
if (actionRanged.AmmoIsPerMagazine)
|
|
{
|
|
return modifiedMagazineSize;
|
|
}
|
|
return target;
|
|
}
|
|
|
|
int res = 0;
|
|
if (ea.bag.GetItemCount(ammo, -1, -1, true) > 0)
|
|
{
|
|
if (actionRanged.AmmoIsPerMagazine)
|
|
{
|
|
return modifiedMagazineSize * ea.bag.DecItem(ammo, 1, false, null);
|
|
}
|
|
res = ea.bag.DecItem(ammo, target, false, null);
|
|
if (res == target)
|
|
{
|
|
return res;
|
|
}
|
|
}
|
|
|
|
if (actionRanged.AmmoIsPerMagazine)
|
|
{
|
|
return modifiedMagazineSize * ea.inventory.DecItem(ammo, 1, false, null);
|
|
}
|
|
|
|
if (ea.inventory.GetItemCount(ammo, false, -1, -1, true) <= 0)
|
|
{
|
|
return res;
|
|
}
|
|
return res + actionData.invData.holdingEntity.inventory.DecItem(ammo, target - res, false, null);
|
|
}
|
|
|
|
public int GetPartialReloadCount(EntityAlive ea, ItemValue ammo, int modifiedMagazineSize, int partialReloadCount)
|
|
{
|
|
int meta = actionData.invData.itemValue.Meta;
|
|
int target = Mathf.Min(partialReloadCount, modifiedMagazineSize - meta);
|
|
if (actionRanged.HasInfiniteAmmo(actionData))
|
|
{
|
|
return target;
|
|
}
|
|
|
|
int res = 0;
|
|
if (ea.bag.GetItemCount(ammo) > 0)
|
|
{
|
|
res = ea.bag.DecItem(ammo, target);
|
|
if (res == target)
|
|
{
|
|
return res;
|
|
}
|
|
}
|
|
|
|
if (ea.inventory.GetItemCount(ammo) <= 0)
|
|
{
|
|
return res;
|
|
}
|
|
return res + actionData.invData.holdingEntity.inventory.DecItem(ammo, target - res);
|
|
}
|
|
|
|
public int GetAmmoCount(EntityAlive ea, ItemValue ammo, int modifiedMagazineSize)
|
|
{
|
|
return Mathf.Min(ea.bag.GetItemCount(ammo, -1, -1, true) + ea.inventory.GetItemCount(ammo, false, -1, -1, true) + actionData.invData.itemValue.Meta, modifiedMagazineSize);
|
|
}
|
|
|
|
public 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);
|
|
}
|
|
return rps > 0 ? rps : 1;
|
|
}
|
|
|
|
public EntityAlive player;
|
|
public ItemActionRanged.ItemActionDataRanged actionData;
|
|
public ItemActionRanged actionRanged;
|
|
#endif
|
|
private Animator animator;
|
|
|
|
public MonoBehaviour Init(Transform playerAnimatorTrans, bool isLocalPlayer)
|
|
{
|
|
var copy = playerAnimatorTrans.AddMissingComponent<AnimationReloadEvents>();
|
|
if (copy)
|
|
{
|
|
copy.enabled = true;
|
|
}
|
|
return copy;
|
|
}
|
|
|
|
public void Disable(Transform playerAnimatorTrans)
|
|
{
|
|
enabled = false;
|
|
}
|
|
}
|