using System; using System.Collections.Generic; using FullInspector; using MoleMole.Config; using UniRx; using UnityEngine; namespace MoleMole { public class AvatarActor : BaseAbilityActor { public enum SwitchEffectLevel { Idle = 0, SwitchEffect = 1, QTESwitchEffect = 2 } [Serializable] public class SKillInfo { public string skillName; public SafeFloat CD = 0f; public SafeFloat costSP = 0f; public SafeFloat needSP = 0f; public SafeFloat cdTimer = 0f; public SafeInt32 MaxChargesCount = 0; public SafeInt32 chargesCounter = 0; public bool canHold; public bool IsInstantTrigger; public bool muted; public bool muteHighlighted; public string maskIconPath; public int avatarSkillID; public string iconPath; public ReviveSkillCDAction reviveCDAction; } private enum TiedState { Idle = 0, Tieing = 1 } private enum ParalyzeState { Idle = 0, WaitForGrounded = 1, ParalyzeFreezed = 2, ParalyzeHitResuming = 3 } private const float COOLED_DOWN_TIME = -253f; public BaseMonoAvatar avatar; public SafeFloat critical = 0f; [InspectorCollapsedFoldout] public ConfigAvatar config; [ShowInInspector] protected bool _isOnStage; public string avatarIconPath; public List skillInfoList; private Dictionary _skillInfoMap; private EntityTimer _switchInTimer; private bool _allowOtherCanSwithInWhenSelfOnStage; private bool _useATKButtonHoldMode; private bool _isInQTEWarning; private bool _muteOtherQTE; public Action onQTEChange; public Action onSkillChargeChanged; public Action onSkillSPNeedChanged; [InspectorCollapsedFoldout] public AvatarDataItem avatarDataItem; public List maskedSkillButtons; private static string[] DEFAULT_SKILL_BUTTON_NAMES = new string[3] { "ATK", "SKL01", "SKL02" }; private TiedState _tiedState; private ParalyzeState _paralyzeState; private EntityTimer _paralyzeTimer; private int _paralyzeMassRatioIx; private int _freezeMassRatioIx; private int _stunMassRatioIx; private int _paralyzeAnimatorSpeedIx; private int _freezeAnimatorSpeedIx; public bool AllowOtherSwitchIn { get { return _allowOtherCanSwithInWhenSelfOnStage; } set { _allowOtherCanSwithInWhenSelfOnStage = value; } } public SwitchEffectLevel switchButtonEffect { get; private set; } public string CurrentQTEName { get; private set; } public bool IsInQTE { get { return _isInQTEWarning; } } public bool MuteOtherQTE { get { return _muteOtherQTE; } set { _muteOtherQTE = value; } } public bool isLeader { get; set; } public override void Init(BaseMonoEntity entity) { avatar = (BaseMonoAvatar)entity; runtimeID = avatar.GetRuntimeID(); config = AvatarData.GetAvatarConfig(avatar.AvatarTypeName); commonConfig = config.CommonConfig; base.Init(entity); skillInfoList = new List(); _skillInfoMap = new Dictionary(); maskedSkillButtons = new List(); foreach (string key in config.Skills.Keys) { ConfigAvatarSkill skillConfig = config.Skills[key]; string skillName = GetSkillNameByAnimEventID(key); if (!Miscs.ArrayContains(DEFAULT_SKILL_BUTTON_NAMES, skillName) || _skillInfoMap.ContainsKey(skillName)) { continue; } SKillInfo sKillInfo = new SKillInfo(); sKillInfo.skillName = skillName; sKillInfo.cdTimer = -253f; sKillInfo.CD = Mathf.Max(0f, skillConfig.SkillCD + Evaluate(skillConfig.SkillCDDelta)); sKillInfo.costSP = Mathf.Max(0f, skillConfig.SPCost + Evaluate(skillConfig.SPCostDelta)); sKillInfo.needSP = Mathf.Max(0f, skillConfig.SPNeed + Evaluate(skillConfig.SPCostDelta)); sKillInfo.MaxChargesCount = skillConfig.ChargesCount + Evaluate(skillConfig.ChargesCountDelta); sKillInfo.canHold = skillConfig.CanHold; sKillInfo.reviveCDAction = skillConfig.ReviveCDAction; sKillInfo.IsInstantTrigger = skillConfig.IsInstantTrigger; sKillInfo.muted = false; sKillInfo.muteHighlighted = skillConfig.MuteHighlighted; sKillInfo.maskIconPath = null; SKillInfo sKillInfo2 = sKillInfo; sKillInfo2.chargesCounter = sKillInfo2.MaxChargesCount; if (skillName == "ATK") { sKillInfo2.muteHighlighted = true; } skillInfoList.Add(sKillInfo2); _skillInfoMap.Add(skillName, sKillInfo2); if (skillConfig.SkillCDDelta.isDynamic) { RegisterPropertyChangedCallback(skillConfig.SkillCDDelta.dynamicKey, delegate { _skillInfoMap[skillName].CD = Mathf.Max(0f, skillConfig.SkillCD + Evaluate(skillConfig.SkillCDDelta)); }); } if (skillConfig.ChargesCountDelta.isDynamic) { RegisterPropertyChangedCallback(skillConfig.ChargesCountDelta.dynamicKey, delegate { int arg = _skillInfoMap[skillName].chargesCounter; _skillInfoMap[skillName].MaxChargesCount = skillConfig.ChargesCount + Evaluate(skillConfig.ChargesCountDelta); _skillInfoMap[skillName].chargesCounter = _skillInfoMap[skillName].MaxChargesCount; if (onSkillChargeChanged != null) { onSkillChargeChanged(skillName, arg, _skillInfoMap[skillName].chargesCounter); } }); } if (!skillConfig.SPCostDelta.isDynamic) { continue; } RegisterPropertyChangedCallback(skillConfig.SPCostDelta.dynamicKey, delegate { float arg = _skillInfoMap[skillName].needSP; _skillInfoMap[skillName].costSP = Mathf.Max(0f, skillConfig.SPCost + Evaluate(skillConfig.SPCostDelta)); _skillInfoMap[skillName].needSP = Mathf.Max(0f, skillConfig.SPNeed + Evaluate(skillConfig.SPCostDelta)); if (onSkillSPNeedChanged != null) { onSkillSPNeedChanged(skillName, arg, _skillInfoMap[skillName].needSP); } }); } BaseMonoAvatar baseMonoAvatar = avatar; baseMonoAvatar.onActiveChanged = (Action)Delegate.Combine(baseMonoAvatar.onActiveChanged, new Action(OnActiveChanged)); _switchInTimer = new EntityTimer(config.CommonArguments.SwitchInCD, entity); EntityTimer switchInTimer = _switchInTimer; switchInTimer.timeupAction = (Action)Delegate.Combine(switchInTimer.timeupAction, new Action(OnSwitchInReady)); _switchInTimer.Reset(false); _switchInTimer.isTimeUp = true; AddPlugin(new AvatarAIPlugin(this)); Singleton.Instance.FireEvent(new EvtAvatarCreated(runtimeID)); _paralyzeTimer = new EntityTimer(); _paralyzeTimer.SetActive(false); _paralyzeState = ParalyzeState.Idle; InitAbilityStateImmune(); InitDebuffDurationRatio(); CurrentQTEName = string.Empty; } private void InitAbilityStateImmune() { ConfigDebuffResistance debuffResistance = config.DebuffResistance; List immuneStates = debuffResistance.ImmuneStates; foreach (AbilityState item in immuneStates) { SetAbilityStateImmune(item, true); } } private void InitDebuffDurationRatio() { ConfigDebuffResistance debuffResistance = config.DebuffResistance; float durationRatio = debuffResistance.DurationRatio; if (durationRatio > 0f) { PushProperty("Actor_DebuffDurationRatioDelta", 0f - durationRatio); } } public void InitAvatarDataItem(AvatarDataItem avatarDataItem, bool isLocal, bool isHelper, bool isLeader, bool leaderSkillOn) { this.avatarDataItem = avatarDataItem; this.isLeader = isLeader; InitHPAndSP(); level = avatarDataItem.level; attack = avatarDataItem.FinalAttack; critical = avatarDataItem.FinalCritical; defense = avatarDataItem.FinalDefense; avatarIconPath = avatarDataItem.IconPathInLevel; LevelActor levelActor = Singleton.Instance.levelActor; if (levelActor.levelMode == LevelActor.Mode.Single) { _isOnStage = isLocal || isHelper; } else { _isOnStage = true; } maskedSkillButtons.AddRange(config.CommonArguments.MaskedSkillButtons); AvatarData.UnlockAvatarAbilities(avatarDataItem, this, isLeader || leaderSkillOn); SetupSkillInfo(avatarDataItem); List skillEntryList = new List(); EquipmentSkillData.AddAvatarWeaponEquipSkillAbilities(avatarDataItem, this, ref skillEntryList); EquipmentSkillData.AddAvatarStigmataEquipSkillAbilities(avatarDataItem, this, ref skillEntryList); EquipmentSkillData.AddAvatarSetEquipSkillAbilities(avatarDataItem, this, ref skillEntryList); SetupWeaponActiveSkillInfo(skillEntryList); if (isHelper) { AddPlugin(new AvatarHelperStatePlugin(this)); } } public void InitGalTouchBuff(AvatarDataItem avatarDataItem) { int num = Singleton.Instance.UseBuff(avatarDataItem.avatarID); if (num != 0) { TouchBuffItem touchBuffItem = GalTouchData.GetTouchBuffItem(num); if (touchBuffItem != null) { int characterHeartLevel = Singleton.Instance.GetCharacterHeartLevel(avatarDataItem.avatarID); float calculatedParam = GalTouchBuffData.GetCalculatedParam(touchBuffItem.param1, touchBuffItem.param1Add, characterHeartLevel); float calculatedParam2 = GalTouchBuffData.GetCalculatedParam(touchBuffItem.param2, touchBuffItem.param2Add, characterHeartLevel); float calculatedParam3 = GalTouchBuffData.GetCalculatedParam(touchBuffItem.param3, touchBuffItem.param3Add, characterHeartLevel); GalTouchBuffData.ApplyGalTouchBuffEntry(this, num, calculatedParam, calculatedParam2, calculatedParam3); } } } private void InitHPAndSP() { baseMaxHP = (maxHP = (HP = avatarDataItem.FinalHP)); baseMaxSP = (maxSP = avatarDataItem.FinalSP); SP = 0f; } private void ResetHPAndSPWhenRevive() { DelegateUtils.UpdateField(ref maxHP, avatarDataItem.FinalHP, onMaxHPChanged); DelegateUtils.UpdateField(ref maxSP, avatarDataItem.FinalSP, onMaxSPChanged); DelegateUtils.UpdateField(ref HP, maxHP, 0f, onHPChanged); DelegateUtils.UpdateField(ref SP, maxSP, 0f, onSPChanged); HPPropertyChangedCallback(); SPPropertyChangedCallback(); } private bool SetupSkillInfo(AvatarDataItem avatarDataItem) { foreach (AvatarSkillDataItem skillData in avatarDataItem.skillDataList) { if (_skillInfoMap.ContainsKey(skillData.ButtonName)) { _skillInfoMap[skillData.ButtonName].avatarSkillID = skillData.skillID; _skillInfoMap[skillData.ButtonName].iconPath = skillData.IconPathInLevel; } } return false; } private void SetupWeaponActiveSkillInfo(List skillEntryList) { foreach (ConfigEquipmentSkillEntry skillEntry in skillEntryList) { if (skillEntry.IsActiveSkill) { EquipSkillMetaData equipSkillMetaDataByKey = EquipSkillMetaDataReader.GetEquipSkillMetaDataByKey(skillEntry.EquipmentSkillID); SKillInfo sKillInfo = new SKillInfo(); sKillInfo.skillName = "SKL_WEAPON"; sKillInfo.CD = skillEntry.SkillCD; sKillInfo.costSP = skillEntry.SPCost; sKillInfo.needSP = skillEntry.SPNeed; sKillInfo.MaxChargesCount = skillEntry.MaxChargesCount; sKillInfo.chargesCounter = skillEntry.MaxChargesCount; sKillInfo.cdTimer = -253f; sKillInfo.canHold = false; sKillInfo.avatarSkillID = skillEntry.EquipmentSkillID; sKillInfo.iconPath = equipSkillMetaDataByKey.skillIconPath; SKillInfo sKillInfo2 = sKillInfo; skillInfoList.Add(sKillInfo2); _skillInfoMap.Add("SKL_WEAPON", sKillInfo2); break; } } } public Dictionary CreateAppliedAbility(ConfigAbility abilityConfig) { Dictionary dictionary = new Dictionary(); appliedAbilities.Add(Tuple.Create(abilityConfig, dictionary)); return dictionary; } public override void PostInit() { base.PostInit(); abilityPlugin.onKillBehavior = ActorAbilityPlugin.OnKillBehavior.RemoveAllDebuffsAndDurationed; Singleton.Instance.RegisterEventListener(runtimeID); } public override bool OnEventWithPlugins(BaseEvent evt) { bool result = base.OnEventWithPlugins(evt); if (evt is EvtSkillStart) { return OnSkillStart((EvtSkillStart)evt); } if (evt is EvtHittingOther) { return OnHittingOther((EvtHittingOther)evt); } if (evt is EvtBeingHit) { return OnBeingHit((EvtBeingHit)evt); } if (evt is EvtKilled) { return OnKill((EvtKilled)evt); } if (evt is EvtAttackLanded) { return OnAttackLanded((EvtAttackLanded)evt); } if (evt is EvtDamageLanded) { return OnDamageLanded((EvtDamageLanded)evt); } if (evt is EvtAvatarSwapOutStart) { return OnAvatarSwappedOutStart((EvtAvatarSwapOutStart)evt); } return result; } public override bool OnEventResolves(BaseEvent evt) { bool flag = false; if (evt is EvtHittingOther) { flag |= OnHittingOtherResolve((EvtHittingOther)evt); } else if (evt is EvtBeingHit) { flag |= OnBeingHitResolve((EvtBeingHit)evt); } flag |= base.OnEventResolves(evt); return false; } public override bool ListenEvent(BaseEvent evt) { bool flag = base.ListenEvent(evt); if (evt is EvtLevelBuffState) { flag |= OnLevelBuffState((EvtLevelBuffState)evt); } return flag; } private bool OnSkillStart(EvtSkillStart evt) { string skillID = evt.skillID; string skillNameByAnimEventID = GetSkillNameByAnimEventID(skillID); float skillSPCost = GetSkillSPCost(skillNameByAnimEventID); DelegateUtils.UpdateField(ref SP, Mathf.Clamp((float)SP - skillSPCost, 0f, maxSP), 0f - skillSPCost, onSPChanged); if ((int)_skillInfoMap[skillNameByAnimEventID].MaxChargesCount > 0) { int num = _skillInfoMap[skillNameByAnimEventID].chargesCounter; int num2 = Mathf.Clamp(num - 1, 0, _skillInfoMap[skillNameByAnimEventID].MaxChargesCount); _skillInfoMap[skillNameByAnimEventID].chargesCounter = num2; if (onSkillChargeChanged != null) { onSkillChargeChanged(evt.skillID, num, num2); } if (!IsSkillInCD(skillNameByAnimEventID)) { _skillInfoMap[skillNameByAnimEventID].cdTimer = GetSkillCD(skillNameByAnimEventID); } } else { _skillInfoMap[skillNameByAnimEventID].cdTimer = GetSkillCD(skillNameByAnimEventID); } avatar.ClearAttackTriggers(); return true; } protected virtual bool OnHittingOther(EvtHittingOther evt) { if (evt.attackData == null) { evt.attackData = DamageModelLogic.CreateAttackDataFromAttackerAnimEvent(this, evt.animEventID); } if (evt.attackData.hitCollision == null && evt.hitCollision != null) { evt.attackData.hitCollision = evt.hitCollision; } else if (evt.hitCollision == null && evt.attackData.hitCollision == null) { BaseMonoAnimatorEntity baseMonoAnimatorEntity = Singleton.Instance.GetEntity(evt.toID) as BaseMonoAnimatorEntity; if (baseMonoAnimatorEntity != null) { evt.hitCollision = new AttackResult.HitCollsion { hitPoint = baseMonoAnimatorEntity.RootNodePosition, hitDir = baseMonoAnimatorEntity.XZPosition - avatar.XZPosition }; } } return true; } protected virtual bool OnHittingOtherResolve(EvtHittingOther evt) { evt.Resolve(); Singleton.Instance.FireEvent(new EvtBeingHit(evt.toID, runtimeID, evt.animEventID, evt.attackData)); MarkImportantEventIsHandled(evt); return true; } protected virtual bool OnBeingHit(EvtBeingHit evt) { if (!_isOnStage) { evt.attackData.Reject(AttackResult.RejectType.RejectAll); return true; } if (!isAlive) { evt.attackData.Reject(AttackResult.RejectType.RejectAll); return true; } DamageModelLogic.ResolveAttackDataByAttackee(this, evt.attackData); return true; } protected virtual bool OnBeingHitResolve(EvtBeingHit evt) { evt.Resolve(); if (evt.attackData.isAnimEventAttack && abilityState.ContainsState(AbilityState.BlockAnimEventAttack)) { evt.attackData.Reject(AttackResult.RejectType.RejectAll); } if (evt.attackData.rejected) { if (evt.attackData.rejectState == AttackResult.RejectType.RejectButShowAttackEffect) { AmendHitCollision(evt.attackData); FireAttackDataEffects(evt.attackData); } return false; } AttackResult attackResult = DamageModelLogic.ResolveAttackDataFinal(this, evt.attackData); AmendHitCollision(attackResult); if (abilityState.ContainsState(AbilityState.Invincible)) { attackResult.damage = 0f; attackResult.plainDamage = 0f; attackResult.fireDamage = 0f; attackResult.thunderDamage = 0f; attackResult.iceDamage = 0f; attackResult.alienDamage = 0f; attackResult.hitLevel = AttackResult.ActorHitLevel.Mute; attackResult.hitEffect = AttackResult.AnimatorHitEffect.Mute; attackResult.frameHalt += 5; } else if (abilityState.ContainsState(AbilityState.Endure)) { attackResult.hitEffect = AttackResult.AnimatorHitEffect.Mute; attackResult.frameHalt += 5; } if (!attackResult.isAnimEventAttack) { attackResult.hitEffect = AttackResult.AnimatorHitEffect.Mute; attackResult.hitEffectPattern = AttackResult.HitEffectPattern.OnlyBeHit; attackResult.attackCameraShake = null; } float totalDamage = attackResult.GetTotalDamage(); float num = (float)HP - totalDamage; if (num <= 0f) { num = 0f; } if (abilityState.ContainsState(AbilityState.Undamagable)) { DelegateUtils.UpdateField(ref HP, HP, num - (float)HP, onHPChanged); } else { DelegateUtils.UpdateField(ref HP, num, num - (float)HP, onHPChanged); evt.resolvedDamage = totalDamage; } if ((float)HP == 0f) { if ((abilityState & AbilityState.Limbo) != AbilityState.None) { evt.beHitEffect = BeHitEffect.NormalBeHit; BeingHit(attackResult, BeHitEffect.NormalBeHit, evt.sourceID); } else { evt.beHitEffect = BeHitEffect.KillingBeHit; Kill(evt.sourceID, evt.animEventID, KillEffect.KillNow); BeingHit(attackResult, BeHitEffect.KillingBeHit, evt.sourceID); } } else { evt.beHitEffect = BeHitEffect.NormalBeHit; BeingHit(attackResult, BeHitEffect.NormalBeHit, evt.sourceID); } FireAttackDataEffects(attackResult); if (_tiedState == TiedState.Tieing && evt.attackData.isAnimEventAttack && evt.attackData.hitEffect >= AttackResult.AnimatorHitEffect.Normal) { abilityPlugin.RemoveModifierByState(AbilityState.Tied); } if (evt.attackData.isAnimEventAttack) { EvtAttackLanded evt2 = new EvtAttackLanded(evt.sourceID, runtimeID, evt.animEventID, attackResult); Singleton.Instance.FireEvent(evt2); } else { Singleton.Instance.FireEvent(new EvtDamageLanded(evt.sourceID, runtimeID, attackResult)); } MarkImportantEventIsHandled(evt); return true; } public void AmendHitCollision(AttackResult attackResult) { if (attackResult.hitCollision == null) { attackResult.hitCollision = new AttackResult.HitCollsion { hitPoint = avatar.RootNodePosition, hitDir = -avatar.FaceDirection }; } else if (attackResult.hitCollision.hitDir == Vector3.zero) { attackResult.hitCollision.hitPoint = avatar.RootNodePosition; attackResult.hitCollision.hitDir = -avatar.FaceDirection; } } public void FireAttackDataEffects(AttackResult attackResult) { if (attackResult.attackEffectPattern != null && (attackResult.hitEffectPattern == AttackResult.HitEffectPattern.Normal || attackResult.hitEffectPattern == AttackResult.HitEffectPattern.OnlyAttack)) { AttackPattern.ActAttackEffects(attackResult.attackEffectPattern, avatar, attackResult.hitCollision.hitPoint, attackResult.hitCollision.hitDir); } if (attackResult.attackCameraShake != null) { AttackPattern.ActCameraShake(attackResult.attackCameraShake); } } private bool OnKill(EvtKilled evt) { abilityPlugin.RemoveAllDebuffModifiers(); Singleton.Instance.RemoveEventListener(runtimeID); return true; } private bool OnAttackLanded(EvtAttackLanded evt) { AttackLanded(evt); if (evt.animEventID == null) { return true; } ConfigAvatarAnimEvent configAvatarAnimEvent = SharedAnimEventData.ResolveAnimEvent(config, evt.animEventID); if (configAvatarAnimEvent == null) { return true; } if ((bool)isAlive) { float num = configAvatarAnimEvent.AttackProperty.SPRecover * config.CommonArguments.AttackSPRecoverRatio * (1f + GetProperty("Actor_SPRecoverRatio")); DelegateUtils.UpdateField(ref SP, Mathf.Clamp((float)SP + num, 0f, maxSP), num, onSPChanged); float num2 = evt.attackResult.damage * GetProperty("Actor_AttackStealHPRatio"); DelegateUtils.UpdateField(ref HP, Mathf.Clamp((float)HP + num2, 0f, maxHP), num2, onHPChanged); } MarkImportantEventIsHandled(evt); return true; } private bool OnDamageLanded(EvtDamageLanded evt) { DamageLanded(evt); return true; } public bool OnAvatarSwappedOutStart(EvtAvatarSwapOutStart evt) { bool flag = false; foreach (BaseMonoAvatar allPlayerAvatar in Singleton.Instance.GetAllPlayerAvatars()) { if (allPlayerAvatar.GetRuntimeID() != runtimeID) { AvatarActor actor = Singleton.Instance.GetActor(allPlayerAvatar.GetRuntimeID()); if (actor.CanSwitchInQTE()) { flag = true; break; } } } if (flag) { _switchInTimer.timespan *= config.CommonArguments.QTESwitchInCDRatio; } _switchInTimer.Reset(true); return true; } public bool OnLevelBuffState(EvtLevelBuffState evt) { if (evt.levelBuff == LevelBuffType.WitchTime && evt.state == LevelBuffState.Start && Singleton.Instance.IsLocalAvatar(runtimeID) && evt.sourceId == runtimeID) { MonoEntityAudio component = entity.GetComponent(); if (component != null) { component.PostWitchTime(); } } return true; } public override void Core() { base.Core(); if (!_allowOtherCanSwithInWhenSelfOnStage) { _switchInTimer.Core(1f); } if (!isAlive) { return; } MonoLevelEntity levelEntity = Singleton.Instance.levelEntity; for (int i = 0; i < skillInfoList.Count; i++) { SKillInfo sKillInfo = skillInfoList[i]; if (!((float)sKillInfo.cdTimer >= 0f)) { continue; } sKillInfo.cdTimer = (float)sKillInfo.cdTimer - levelEntity.TimeScale * Time.deltaTime; if ((float)sKillInfo.cdTimer < 0f) { sKillInfo.cdTimer = -253f; } if ((float)sKillInfo.cdTimer == -253f && (int)sKillInfo.MaxChargesCount > 0) { int num = sKillInfo.chargesCounter; int num2 = Mathf.Clamp(num + 1, 0, sKillInfo.MaxChargesCount); sKillInfo.chargesCounter = num2; if (onSkillChargeChanged != null) { onSkillChargeChanged(sKillInfo.skillName, num, num2); } if ((int)sKillInfo.chargesCounter < (int)sKillInfo.MaxChargesCount) { sKillInfo.cdTimer = GetSkillCD(sKillInfo.skillName); } } } UpdateAbilityState(); } public virtual void AttackLanded(EvtAttackLanded evt) { avatar.FrameHalt(evt.attackResult.frameHalt); } protected virtual void DamageLanded(EvtDamageLanded evt) { avatar.FrameHalt(evt.attackResult.frameHalt); } public virtual void BeingHit(AttackResult attackResult, BeHitEffect beHitEffect, uint sourceID) { bool doSteerToHitForward = false; bool targetLockSource = false; if (attackResult.hitEffect > AttackResult.AnimatorHitEffect.Light && attackResult.hitCollision.hitDir != Vector3.zero) { doSteerToHitForward = true; } if (Singleton.Instance.IsLocalAvatar(runtimeID) && avatar.AttackTarget == null && avatar.IsAnimatorInTag(AvatarData.AvatarTagGroup.AllowTriggerInput) && Singleton.Instance.ParseCategory(sourceID) == 4) { BaseMonoMonster baseMonoMonster = Singleton.Instance.TryGetMonsterByRuntimeID(sourceID); if (baseMonoMonster != null && !baseMonoMonster.denySelect) { targetLockSource = true; } } if (_paralyzeState == ParalyzeState.ParalyzeFreezed && attackResult.hitEffect > AttackResult.AnimatorHitEffect.Light) { avatar.SetPropertyByStackIndex("Animator_OverallSpeedRatioMultiplied", _paralyzeAnimatorSpeedIx, 1f); _paralyzeTimer.timespan = 0.35f; _paralyzeTimer.Reset(true); _paralyzeState = ParalyzeState.ParalyzeHitResuming; } if (abilityState.ContainsState(AbilityState.Frozen)) { doSteerToHitForward = false; if (attackResult.hitEffect > AttackResult.AnimatorHitEffect.Light) { attackResult.hitEffect = AttackResult.AnimatorHitEffect.Light; } } avatar.BeHit(attackResult.frameHalt, attackResult.hitEffect, attackResult.hitEffectAux, attackResult.killEffect, beHitEffect, attackResult.aniDamageRatio, attackResult.hitCollision.hitDir, attackResult.retreatVelocity, sourceID, targetLockSource, doSteerToHitForward); } public virtual void Kill(uint killerID, string killerAnimEventID, KillEffect killEffect) { if (onJustKilled != null) { onJustKilled(killerID, killerAnimEventID, killEffect); } if (!isAlive) { if (killEffect == KillEffect.KillImmediately) { avatar.SetDied(KillEffect.KillImmediately); } } else { isAlive = false; Singleton.Instance.FireEvent(new EvtKilled(runtimeID, killerID, killerAnimEventID)); avatar.SetDied(KillEffect.KillNow); } } public void ForceKill() { Kill(562036737u, null, KillEffect.KillNow); } public override void ForceKill(uint killerID, KillEffect killEffect) { Kill(killerID, null, killEffect); } public void Revive(Vector3 revivePosition) { isAlive = true; ResetHPAndSPWhenRevive(); SetSkillCDWhenRevive(); abilityPlugin.ResetKilled(); avatar.Revive(revivePosition); BaseMonoAvatar localAvatar = Singleton.Instance.GetLocalAvatar(); if (Singleton.Instance.levelActor.levelMode == LevelActor.Mode.Single) { if (localAvatar == avatar || localAvatar.switchState == BaseMonoAvatar.AvatarSwitchState.OffStage) { Singleton.Instance.levelActor.SingleModeSwapTo(revivePosition, localAvatar.FaceDirection, avatar); } else { Singleton.Instance.levelActor.TriggerSwapLocalAvatar(localAvatar.GetRuntimeID(), runtimeID, true); } } else if (Singleton.Instance.levelActor.levelMode == LevelActor.Mode.Multi || Singleton.Instance.levelActor.levelMode == LevelActor.Mode.MultiRemote) { Singleton.Instance.levelActor.SingleModeSwapTo(revivePosition, localAvatar.FaceDirection, avatar); if (localAvatar != avatar && localAvatar.switchState == BaseMonoAvatar.AvatarSwitchState.OnStage) { localAvatar.RefreshController(); } } } private void SetSkillCDWhenRevive() { foreach (SKillInfo value in _skillInfoMap.Values) { ReviveSkillCDAction reviveCDAction = value.reviveCDAction; if (reviveCDAction != ReviveSkillCDAction.KeepLast && reviveCDAction == ReviveSkillCDAction.Cleer) { value.cdTimer = -253f; value.chargesCounter = value.MaxChargesCount; } } } public override void OnRemoval() { base.OnRemoval(); DisableQTEAttack(); onSkillChargeChanged = null; onSkillSPNeedChanged = null; onQTEChange = null; } private void OnActiveChanged(bool active) { _isOnStage = active; } public void OnSwitchInReady() { _switchInTimer.timespan = config.CommonArguments.SwitchInCD; } public void SetMuteSkill(string skillName, bool muted) { _skillInfoMap[skillName].muted = muted; } public bool CanUseSkill(string skillName) { if (_skillInfoMap[skillName].muted) { return false; } if (IsSkillLocked(skillName)) { return false; } if ((int)_skillInfoMap[skillName].MaxChargesCount > 0) { if (skillName == "SKL01") { return IsSPEnough(skillName); } return IsSPEnough(skillName) && (int)_skillInfoMap[skillName].chargesCounter > 0; } return IsSPEnough(skillName) && !IsSkillInCD(skillName); } public bool HasChargesLeft(string skillName) { return (int)_skillInfoMap[skillName].MaxChargesCount <= 0 || (int)_skillInfoMap[skillName].chargesCounter > 0; } public void SetAllowOtherCanSwitchIn(bool canSwitchIn) { _allowOtherCanSwithInWhenSelfOnStage = canSwitchIn; } public void SetAttackButtonHoldMode(bool useHoldMod) { _useATKButtonHoldMode = useHoldMod; } public bool IsAttackButtonHoldMode() { return _useATKButtonHoldMode || avatar.IsAttackHoldMode(); } public void EnableQTEAttack(string QTEName) { CurrentQTEName = QTEName; _isInQTEWarning = true; if (onQTEChange != null) { onQTEChange(true); } } public void DisableQTEAttack() { CurrentQTEName = string.Empty; _isInQTEWarning = false; if (onQTEChange != null) { onQTEChange(false); } } public bool CanSwitchInQTE() { return !string.IsNullOrEmpty(CurrentQTEName); } public bool IsSPEnough(string skillName) { return (float)SP >= GetSkillSPCost(skillName) && (float)SP >= GetSkillSPNeed(skillName); } public bool IsSkillInCD(string skillName) { return (float)_skillInfoMap[skillName].cdTimer >= 0f; } public bool IsSkillLocked(string skillName) { return maskedSkillButtons.Contains(skillName); } public bool IsSkillHasCD(string skillName) { return (float)_skillInfoMap[skillName].CD > 0f; } public bool IsSwitchInCD() { return !_switchInTimer.isTimeUp; } public void ChangeSwitchInCDTime(float CDTime) { _switchInTimer = new EntityTimer(CDTime, entity); EntityTimer switchInTimer = _switchInTimer; switchInTimer.timeupAction = (Action)Delegate.Combine(switchInTimer.timeupAction, new Action(OnSwitchInReady)); _switchInTimer.Reset(false); _switchInTimer.isTimeUp = true; } public void ResetSwitchInTimer() { _switchInTimer.Reset(false); _switchInTimer.isTimeUp = false; } public float GetSkillSPNeed(string skillName) { float result = 0f; switch (skillName) { case "SKL01": case "SKL02": case "SKL_WEAPON": { SKillInfo sKillInfo = _skillInfoMap[skillName]; float num = Mathf.Max(sKillInfo.costSP, sKillInfo.needSP); result = num; break; } } return result; } public float GetSkillSPCost(string skillName) { float result = 0f; switch (skillName) { case "SKL01": case "SKL02": case "SKL_WEAPON": { float property = GetProperty("Actor_SkillSPCostDelta"); float property2 = GetProperty("Actor_SkillSPCostRatio"); result = ((float)_skillInfoMap[skillName].costSP + property) * (1f + property2); break; } } return result; } public float GetSkillCD(string skillName) { float num = _skillInfoMap[skillName].CD; if (skillName == "SKL01") { num *= 1f + GetProperty("Actor_SKL01CDRatio"); } else if (skillName == "SKL02") { num *= 1f + GetProperty("Actor_SKL02CDRatio"); } return num; } public float GetSwtichCDRatio() { return _switchInTimer.timer / _switchInTimer.timespan; } public string GetSkillNameByAnimEventID(string animEventID) { return (!animEventID.StartsWith("ATK")) ? animEventID : "ATK"; } public SKillInfo GetSkillInfo(string skillName) { return (!_skillInfoMap.ContainsKey(skillName)) ? null : _skillInfoMap[skillName]; } public bool IsOnStage() { return _isOnStage; } public void SetAvatarAttackRatio(float ratio) { attack = (float)attack * ratio; } protected override void OnAbilityStateAdd(AbilityState state, bool muteDisplayEffect) { base.OnAbilityStateAdd(state, muteDisplayEffect); switch (state) { case AbilityState.Stun: avatar.SetTrigger("TriggerHit"); avatar.SetLocomotionBool("BuffStun", true); _stunMassRatioIx = PushProperty("Entity_MassRatio", 1000f); break; case AbilityState.Paralyze: avatar.SetTrigger("TriggerHit"); avatar.SetLocomotionBool("BuffParalyze", true); _paralyzeAnimatorSpeedIx = avatar.PushProperty("Animator_OverallSpeedRatioMultiplied", 1f); avatar.SetCountedMuteControl(true); _paralyzeMassRatioIx = PushProperty("Entity_MassRatio", 1000f); _paralyzeTimer.Reset(true); _paralyzeTimer.timespan = 0.35f; _paralyzeState = ParalyzeState.ParalyzeHitResuming; avatar.OrderMove = false; avatar.ClearAttackTriggers(); break; case AbilityState.Frozen: avatar.SetLocomotionBool("BuffParalyze", true); _freezeAnimatorSpeedIx = avatar.PushProperty("Animator_OverallSpeedRatioMultiplied", 0f); avatar.SetCountedMuteControl(true); _freezeMassRatioIx = PushProperty("Entity_MassRatio", 1000f); break; case AbilityState.Tied: _tiedState = TiedState.Tieing; break; } Singleton.Instance.FireEvent(new EvtBuffAdd(runtimeID, state)); } protected override void OnAbilityStateRemove(AbilityState state) { base.OnAbilityStateRemove(state); switch (state) { case AbilityState.Stun: avatar.SetLocomotionBool("BuffStun", false); PopProperty("Entity_MassRatio", _stunMassRatioIx); avatar.ClearAttackTriggers(); break; case AbilityState.Paralyze: avatar.SetLocomotionBool("BuffParalyze", false); avatar.PopProperty("Animator_OverallSpeedRatioMultiplied", _paralyzeAnimatorSpeedIx); avatar.SetCountedMuteControl(false); PopProperty("Entity_MassRatio", _paralyzeMassRatioIx); _paralyzeState = ParalyzeState.Idle; avatar.OrderMove = false; avatar.ClearAttackTriggers(); break; case AbilityState.Frozen: avatar.SetLocomotionBool("BuffParalyze", false); avatar.PopProperty("Animator_OverallSpeedRatioMultiplied", _freezeAnimatorSpeedIx); avatar.SetCountedMuteControl(false); avatar.PopProperty("Entity_MassRatio", _freezeMassRatioIx); avatar.ClearAttackTriggers(); break; case AbilityState.Tied: _tiedState = TiedState.Idle; break; } Singleton.Instance.FireEvent(new EvtBuffRemove(runtimeID, state)); } private void UpdateAbilityState() { if (_paralyzeState == ParalyzeState.WaitForGrounded) { if (!avatar.IsAnimatorInTag(AvatarData.AvatarTagGroup.Throw)) { avatar.SetPropertyByStackIndex("Animator_OverallSpeedRatioMultiplied", _paralyzeAnimatorSpeedIx, 0f); _paralyzeState = ParalyzeState.ParalyzeFreezed; } } else if (_paralyzeState != ParalyzeState.ParalyzeFreezed && _paralyzeState == ParalyzeState.ParalyzeHitResuming) { _paralyzeTimer.Core(1f); if (avatar.IsAnimatorInTag(AvatarData.AvatarTagGroup.Throw)) { avatar.SetPropertyByStackIndex("Animator_OverallSpeedRatioMultiplied", _paralyzeAnimatorSpeedIx, 1f); _paralyzeTimer.Reset(false); _paralyzeState = ParalyzeState.WaitForGrounded; } else if (_paralyzeTimer.isTimeUp) { avatar.SetPropertyByStackIndex("Animator_OverallSpeedRatioMultiplied", _paralyzeAnimatorSpeedIx, 0f); _paralyzeTimer.Reset(false); _paralyzeState = ParalyzeState.ParalyzeFreezed; } } } } }