| using System; |
| using System; |
| using System.Collections.Generic; |
| using System.Collections.Generic; |
| using UnityEngine; |
| using UnityEngine; |
| |
| |
| public class MonsterAI : BaseAI |
| public class MonsterAI : BaseAI |
| { |
| { |
| protected override void Awake() |
| protected override void Awake() |
| { |
| { |
| base.Awake(); |
| base.Awake(); |
| this.m_despawnInDay = this.m_nview.GetZDO().GetBool(ZDOVars.s_despawnInDay, this.m_despawnInDay); |
| this.m_despawnInDay = this.m_nview.GetZDO().GetBool(ZDOVars.s_despawnInDay, this.m_despawnInDay); |
| this.m_eventCreature = this.m_nview.GetZDO().GetBool(ZDOVars.s_eventCreature, this.m_eventCreature); |
| this.m_eventCreature = this.m_nview.GetZDO().GetBool(ZDOVars.s_eventCreature, this.m_eventCreature); |
| this.m_sleeping = this.m_nview.GetZDO().GetBool(ZDOVars.s_sleeping, this.m_sleeping); |
| this.m_sleeping = this.m_nview.GetZDO().GetBool(ZDOVars.s_sleeping, this.m_sleeping); |
| this.m_animator.SetBool(MonsterAI.s_sleeping, this.IsSleeping()); |
| this.m_animator.SetBool(MonsterAI.s_sleeping, this.IsSleeping()); |
| this.m_interceptTime = UnityEngine.Random.Range(this.m_interceptTimeMin, this.m_interceptTimeMax); |
| this.m_interceptTime = UnityEngine.Random.Range(this.m_interceptTimeMin, this.m_interceptTimeMax); |
| this.m_pauseTimer = UnityEngine.Random.Range(0f, this.m_circleTargetInterval); |
| this.m_pauseTimer = UnityEngine.Random.Range(0f, this.m_circleTargetInterval); |
| this.m_updateTargetTimer = UnityEngine.Random.Range(0f, 2f); |
| this.m_updateTargetTimer = UnityEngine.Random.Range(0f, 2f); |
| if (this.m_wakeUpDelayMin > 0f || this.m_wakeUpDelayMax > 0f) |
| if (this.m_wakeUpDelayMin > 0f || this.m_wakeUpDelayMax > 0f) |
| { |
| { |
| this.m_sleepDelay = UnityEngine.Random.Range(this.m_wakeUpDelayMin, this.m_wakeUpDelayMax); |
| this.m_sleepDelay = UnityEngine.Random.Range(this.m_wakeUpDelayMin, this.m_wakeUpDelayMax); |
| } |
| } |
| if (this.m_enableHuntPlayer) |
| if (this.m_enableHuntPlayer) |
| { |
| { |
| base.SetHuntPlayer(true); |
| base.SetHuntPlayer(true); |
| } |
| } |
| this.m_nview.Register("RPC_Wakeup", new Action<long>(this.RPC_Wakeup)); |
| this.m_nview.Register("RPC_Wakeup", new Action<long>(this.RPC_Wakeup)); |
| } |
| } |
| |
| |
| . | protected override void OnEnable() |
| |
| { |
| |
| base.OnEnable(); |
| |
| MonsterAI.Instances.Add(this); |
| |
| } |
| |
| |
| |
| protected override void OnDisable() |
| |
| { |
| |
| base.OnDisable(); |
| |
| MonsterAI.Instances.Remove(this); |
| |
| } |
| |
| |
| |
| private void Start() |
| private void Start() |
| { |
| { |
| if (this.m_nview && this.m_nview.IsValid() && this.m_nview.IsOwner()) |
| if (this.m_nview && this.m_nview.IsValid() && this.m_nview.IsOwner()) |
| { |
| { |
| Humanoid humanoid = this.m_character as Humanoid; |
| Humanoid humanoid = this.m_character as Humanoid; |
| if (humanoid) |
| if (humanoid) |
| { |
| { |
| humanoid.EquipBestWeapon(null, null, null, null); |
| humanoid.EquipBestWeapon(null, null, null, null); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| protected override void OnDamaged(float damage, Character attacker) |
| protected override void OnDamaged(float damage, Character attacker) |
| { |
| { |
| base.OnDamaged(damage, attacker); |
| base.OnDamaged(damage, attacker); |
| this.Wakeup(); |
| this.Wakeup(); |
| this.SetAlerted(true); |
| this.SetAlerted(true); |
| this.SetTarget(attacker); |
| this.SetTarget(attacker); |
| } |
| } |
| |
| |
| private void SetTarget(Character attacker) |
| private void SetTarget(Character attacker) |
| { |
| { |
| if (attacker != null && this.m_targetCreature == null) |
| if (attacker != null && this.m_targetCreature == null) |
| { |
| { |
| if (attacker.IsPlayer() && this.m_character.IsTamed()) |
| if (attacker.IsPlayer() && this.m_character.IsTamed()) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| this.m_targetCreature = attacker; |
| this.m_targetCreature = attacker; |
| this.m_lastKnownTargetPos = attacker.transform.position; |
| this.m_lastKnownTargetPos = attacker.transform.position; |
| this.m_beenAtLastPos = false; |
| this.m_beenAtLastPos = false; |
| this.m_targetStatic = null; |
| this.m_targetStatic = null; |
| } |
| } |
| } |
| } |
| |
| |
| protected override void RPC_OnNearProjectileHit(long sender, Vector3 center, float range, ZDOID attackerID) |
| protected override void RPC_OnNearProjectileHit(long sender, Vector3 center, float range, ZDOID attackerID) |
| { |
| { |
| if (!this.m_nview.IsOwner()) |
| if (!this.m_nview.IsOwner()) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| if (ZoneSystem.instance.GetGlobalKey(GlobalKeys.PassiveMobs)) |
| if (ZoneSystem.instance.GetGlobalKey(GlobalKeys.PassiveMobs)) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| this.SetAlerted(true); |
| this.SetAlerted(true); |
| if (this.m_fleeIfNotAlerted) |
| if (this.m_fleeIfNotAlerted) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| GameObject gameObject = ZNetScene.instance.FindInstance(attackerID); |
| GameObject gameObject = ZNetScene.instance.FindInstance(attackerID); |
| if (gameObject != null) |
| if (gameObject != null) |
| { |
| { |
| Character component = gameObject.GetComponent<Character>(); |
| Character component = gameObject.GetComponent<Character>(); |
| if (component) |
| if (component) |
| { |
| { |
| this.SetTarget(component); |
| this.SetTarget(component); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| public void MakeTame() |
| public void MakeTame() |
| { |
| { |
| this.m_character.SetTamed(true); |
| this.m_character.SetTamed(true); |
| this.SetAlerted(false); |
| this.SetAlerted(false); |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| this.m_targetStatic = null; |
| this.m_targetStatic = null; |
| } |
| } |
| |
| |
| private void UpdateTarget(Humanoid humanoid, float dt, out bool canHearTarget, out bool canSeeTarget) |
| private void UpdateTarget(Humanoid humanoid, float dt, out bool canHearTarget, out bool canSeeTarget) |
| { |
| { |
| this.m_unableToAttackTargetTimer -= dt; |
| this.m_unableToAttackTargetTimer -= dt; |
| this.m_updateTargetTimer -= dt; |
| this.m_updateTargetTimer -= dt; |
| if (this.m_updateTargetTimer <= 0f && !this.m_character.InAttack()) |
| if (this.m_updateTargetTimer <= 0f && !this.m_character.InAttack()) |
| { |
| { |
| this.m_updateTargetTimer = (Player.IsPlayerInRange(base.transform.position, 50f) ? 2f : 6f); |
| this.m_updateTargetTimer = (Player.IsPlayerInRange(base.transform.position, 50f) ? 2f : 6f); |
| Character character = base.FindEnemy(); |
| Character character = base.FindEnemy(); |
| if (character) |
| if (character) |
| { |
| { |
| this.m_targetCreature = character; |
| this.m_targetCreature = character; |
| this.m_targetStatic = null; |
| this.m_targetStatic = null; |
| } |
| } |
| bool flag = this.m_targetCreature != null && this.m_targetCreature.IsPlayer(); |
| bool flag = this.m_targetCreature != null && this.m_targetCreature.IsPlayer(); |
| bool flag2 = this.m_targetCreature != null && this.m_unableToAttackTargetTimer > 0f && !base.HavePath(this.m_targetCreature.transform.position); |
| bool flag2 = this.m_targetCreature != null && this.m_unableToAttackTargetTimer > 0f && !base.HavePath(this.m_targetCreature.transform.position); |
| if (this.m_attackPlayerObjects && (!this.m_aggravatable || base.IsAggravated()) && !ZoneSystem.instance.GetGlobalKey(GlobalKeys.PassiveMobs) && (this.m_targetCreature == null || flag2) && !this.m_character.IsTamed()) |
| if (this.m_attackPlayerObjects && (!this.m_aggravatable || base.IsAggravated()) && !ZoneSystem.instance.GetGlobalKey(GlobalKeys.PassiveMobs) && (this.m_targetCreature == null || flag2) && !this.m_character.IsTamed()) |
| { |
| { |
| StaticTarget staticTarget = base.FindClosestStaticPriorityTarget(); |
| StaticTarget staticTarget = base.FindClosestStaticPriorityTarget(); |
| if (staticTarget) |
| if (staticTarget) |
| { |
| { |
| this.m_targetStatic = staticTarget; |
| this.m_targetStatic = staticTarget; |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| } |
| } |
| bool flag3 = false; |
| bool flag3 = false; |
| if (this.m_targetStatic != null) |
| if (this.m_targetStatic != null) |
| { |
| { |
| Vector3 vector = this.m_targetStatic.FindClosestPoint(this.m_character.transform.position); |
| Vector3 vector = this.m_targetStatic.FindClosestPoint(this.m_character.transform.position); |
| flag3 = base.HavePath(vector); |
| flag3 = base.HavePath(vector); |
| } |
| } |
| if ((this.m_targetStatic == null || !flag3) && base.IsAlerted() && flag) |
| if ((this.m_targetStatic == null || !flag3) && base.IsAlerted() && flag) |
| { |
| { |
| StaticTarget staticTarget2 = base.FindRandomStaticTarget(10f); |
| StaticTarget staticTarget2 = base.FindRandomStaticTarget(10f); |
| if (staticTarget2) |
| if (staticTarget2) |
| { |
| { |
| this.m_targetStatic = staticTarget2; |
| this.m_targetStatic = staticTarget2; |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| if (this.m_targetCreature && this.m_character.IsTamed()) |
| if (this.m_targetCreature && this.m_character.IsTamed()) |
| { |
| { |
| Vector3 vector2; |
| Vector3 vector2; |
| if (base.GetPatrolPoint(out vector2)) |
| if (base.GetPatrolPoint(out vector2)) |
| { |
| { |
| if (Vector3.Distance(this.m_targetCreature.transform.position, vector2) > this.m_alertRange) |
| if (Vector3.Distance(this.m_targetCreature.transform.position, vector2) > this.m_alertRange) |
| { |
| { |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| } |
| } |
| } |
| } |
| else if (this.m_follow && Vector3.Distance(this.m_targetCreature.transform.position, this.m_follow.transform.position) > this.m_alertRange) |
| else if (this.m_follow && Vector3.Distance(this.m_targetCreature.transform.position, this.m_follow.transform.position) > this.m_alertRange) |
| { |
| { |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| } |
| } |
| } |
| } |
| . | if (this.m_targetCreature && this.m_targetCreature.IsDead()) |
| if (this.m_targetCreature) |
| { |
| |
| this.m_targetCreature = null; |
| |
| } |
| |
| if (this.m_targetCreature && !base.IsEnemy(this.m_targetCreature)) |
| |
| { |
| { |
| . | this.m_targetCreature = null; |
| if (this.m_targetCreature.IsDead()) |
| |
| { |
| |
| this.m_targetCreature = null; |
| |
| } |
| |
| else if (!base.IsEnemy(this.m_targetCreature)) |
| |
| { |
| |
| this.m_targetCreature = null; |
| |
| } |
| |
| else if (this.m_skipLavaTargets && this.m_targetCreature.AboveOrInLava()) |
| |
| { |
| |
| this.m_targetCreature = null; |
| |
| } |
| } |
| } |
| canHearTarget = false; |
| canHearTarget = false; |
| canSeeTarget = false; |
| canSeeTarget = false; |
| if (this.m_targetCreature) |
| if (this.m_targetCreature) |
| { |
| { |
| canHearTarget = base.CanHearTarget(this.m_targetCreature); |
| canHearTarget = base.CanHearTarget(this.m_targetCreature); |
| canSeeTarget = base.CanSeeTarget(this.m_targetCreature); |
| canSeeTarget = base.CanSeeTarget(this.m_targetCreature); |
| if (canSeeTarget | canHearTarget) |
| if (canSeeTarget | canHearTarget) |
| { |
| { |
| this.m_timeSinceSensedTargetCreature = 0f; |
| this.m_timeSinceSensedTargetCreature = 0f; |
| } |
| } |
| if (this.m_targetCreature.IsPlayer()) |
| if (this.m_targetCreature.IsPlayer()) |
| { |
| { |
| this.m_targetCreature.OnTargeted(canSeeTarget | canHearTarget, base.IsAlerted()); |
| this.m_targetCreature.OnTargeted(canSeeTarget | canHearTarget, base.IsAlerted()); |
| } |
| } |
| base.SetTargetInfo(this.m_targetCreature.GetZDOID()); |
| base.SetTargetInfo(this.m_targetCreature.GetZDOID()); |
| } |
| } |
| else |
| else |
| { |
| { |
| base.SetTargetInfo(ZDOID.None); |
| base.SetTargetInfo(ZDOID.None); |
| } |
| } |
| this.m_timeSinceSensedTargetCreature += dt; |
| this.m_timeSinceSensedTargetCreature += dt; |
| if (base.IsAlerted() || this.m_targetCreature != null) |
| if (base.IsAlerted() || this.m_targetCreature != null) |
| { |
| { |
| this.m_timeSinceAttacking += dt; |
| this.m_timeSinceAttacking += dt; |
| float num = 60f; |
| float num = 60f; |
| float num2 = Vector3.Distance(this.m_spawnPoint, base.transform.position); |
| float num2 = Vector3.Distance(this.m_spawnPoint, base.transform.position); |
| bool flag4 = this.HuntPlayer() && this.m_targetCreature && this.m_targetCreature.IsPlayer(); |
| bool flag4 = this.HuntPlayer() && this.m_targetCreature && this.m_targetCreature.IsPlayer(); |
| if (this.m_timeSinceSensedTargetCreature > 30f || (!flag4 && (this.m_timeSinceAttacking > num || (this.m_maxChaseDistance > 0f && this.m_timeSinceSensedTargetCreature > 1f && num2 > this.m_maxChaseDistance)))) |
| if (this.m_timeSinceSensedTargetCreature > 30f || (!flag4 && (this.m_timeSinceAttacking > num || (this.m_maxChaseDistance > 0f && this.m_timeSinceSensedTargetCreature > 1f && num2 > this.m_maxChaseDistance)))) |
| { |
| { |
| this.SetAlerted(false); |
| this.SetAlerted(false); |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| this.m_targetStatic = null; |
| this.m_targetStatic = null; |
| this.m_timeSinceAttacking = 0f; |
| this.m_timeSinceAttacking = 0f; |
| this.m_updateTargetTimer = 5f; |
| this.m_updateTargetTimer = 5f; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| . | public new void UpdateAI(float dt) |
| public override bool UpdateAI(float dt) |
| { |
| { |
| . | if (!this.m_nview.IsOwner()) |
| if (!base.UpdateAI(dt)) |
| { |
| { |
| . | return; |
| return false; |
| } |
| } |
| if (this.IsSleeping()) |
| if (this.IsSleeping()) |
| { |
| { |
| this.UpdateSleep(dt); |
| this.UpdateSleep(dt); |
| . | return; |
| return true; |
| } |
| } |
| Humanoid humanoid = this.m_character as Humanoid; |
| Humanoid humanoid = this.m_character as Humanoid; |
| if (this.HuntPlayer()) |
| if (this.HuntPlayer()) |
| { |
| { |
| this.SetAlerted(true); |
| this.SetAlerted(true); |
| } |
| } |
| bool flag; |
| bool flag; |
| bool flag2; |
| bool flag2; |
| this.UpdateTarget(humanoid, dt, out flag, out flag2); |
| this.UpdateTarget(humanoid, dt, out flag, out flag2); |
| if (this.m_tamable && this.m_tamable.m_saddle && this.m_tamable.m_saddle.UpdateRiding(dt)) |
| if (this.m_tamable && this.m_tamable.m_saddle && this.m_tamable.m_saddle.UpdateRiding(dt)) |
| { |
| { |
| . | return; |
| return true; |
| } |
| } |
| if (this.m_avoidLand && !this.m_character.IsSwimming()) |
| if (this.m_avoidLand && !this.m_character.IsSwimming()) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Move to water"; |
| |
| } |
| |
| base.MoveToWater(dt, 20f); |
| base.MoveToWater(dt, 20f); |
| . | return; |
| return true; |
| } |
| } |
| . | if (this.DespawnInDay() && EnvMan.instance.IsDay() && (this.m_targetCreature == null || !flag2)) |
| if (this.DespawnInDay() && EnvMan.IsDay() && (this.m_targetCreature == null || !flag2)) |
| { |
| { |
| base.MoveAwayAndDespawn(dt, true); |
| base.MoveAwayAndDespawn(dt, true); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Trying to despawn "; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| if (this.IsEventCreature() && !RandEventSystem.HaveActiveEvent()) |
| if (this.IsEventCreature() && !RandEventSystem.HaveActiveEvent()) |
| { |
| { |
| base.SetHuntPlayer(false); |
| base.SetHuntPlayer(false); |
| if (this.m_targetCreature == null && !base.IsAlerted()) |
| if (this.m_targetCreature == null && !base.IsAlerted()) |
| { |
| { |
| base.MoveAwayAndDespawn(dt, false); |
| base.MoveAwayAndDespawn(dt, false); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Trying to despawn "; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| } |
| } |
| if (this.m_fleeIfNotAlerted && !this.HuntPlayer() && this.m_targetCreature && !base.IsAlerted() && Vector3.Distance(this.m_targetCreature.transform.position, base.transform.position) - this.m_targetCreature.GetRadius() > this.m_alertRange) |
| if (this.m_fleeIfNotAlerted && !this.HuntPlayer() && this.m_targetCreature && !base.IsAlerted() && Vector3.Distance(this.m_targetCreature.transform.position, base.transform.position) - this.m_targetCreature.GetRadius() > this.m_alertRange) |
| { |
| { |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Avoiding conflict"; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| . | if (this.m_fleeIfLowHealth > 0f && this.m_character.GetHealthPercentage() < this.m_fleeIfLowHealth && this.m_timeSinceHurt < 20f && this.m_targetCreature != null) |
| if (this.m_fleeIfLowHealth > 0f && this.m_timeSinceHurt < this.m_fleeTimeSinceHurt && this.m_targetCreature != null && this.m_character.GetHealthPercentage() < this.m_fleeIfLowHealth) |
| { |
| { |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| } |
| this.m_aiStatus = "Low health, flee"; |
| if (this.m_fleeInLava && this.m_character.InLava() && (this.m_targetCreature == null || this.m_targetCreature.AboveOrInLava())) |
| } |
| { |
| return; |
| base.Flee(dt, this.m_character.transform.position - this.m_character.transform.forward); |
| |
| return true; |
| } |
| } |
| if ((this.m_afraidOfFire || this.m_avoidFire) && base.AvoidFire(dt, this.m_targetCreature, this.m_afraidOfFire)) |
| if ((this.m_afraidOfFire || this.m_avoidFire) && base.AvoidFire(dt, this.m_targetCreature, this.m_afraidOfFire)) |
| { |
| { |
| if (this.m_afraidOfFire) |
| if (this.m_afraidOfFire) |
| { |
| { |
| this.m_targetStatic = null; |
| this.m_targetStatic = null; |
| this.m_targetCreature = null; |
| this.m_targetCreature = null; |
| } |
| } |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Avoiding fire"; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| if (!this.m_character.IsTamed()) |
| if (!this.m_character.IsTamed()) |
| { |
| { |
| if (this.m_targetCreature != null) |
| if (this.m_targetCreature != null) |
| { |
| { |
| if (EffectArea.IsPointInsideNoMonsterArea(this.m_targetCreature.transform.position)) |
| if (EffectArea.IsPointInsideNoMonsterArea(this.m_targetCreature.transform.position)) |
| { |
| { |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Avoid no-monster area"; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| } |
| } |
| else |
| else |
| { |
| { |
| EffectArea effectArea = EffectArea.IsPointCloseToNoMonsterArea(base.transform.position); |
| EffectArea effectArea = EffectArea.IsPointCloseToNoMonsterArea(base.transform.position); |
| if (effectArea != null) |
| if (effectArea != null) |
| { |
| { |
| base.Flee(dt, effectArea.transform.position); |
| base.Flee(dt, effectArea.transform.position); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Avoid no-monster area"; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| } |
| } |
| } |
| } |
| if (this.m_fleeIfHurtWhenTargetCantBeReached && this.m_targetCreature != null && this.m_timeSinceAttacking > 30f && this.m_timeSinceHurt < 20f) |
| if (this.m_fleeIfHurtWhenTargetCantBeReached && this.m_targetCreature != null && this.m_timeSinceAttacking > 30f && this.m_timeSinceHurt < 20f) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Hide from unreachable target"; |
| |
| } |
| |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| base.Flee(dt, this.m_targetCreature.transform.position); |
| this.m_lastKnownTargetPos = base.transform.position; |
| this.m_lastKnownTargetPos = base.transform.position; |
| this.m_updateTargetTimer = 1f; |
| this.m_updateTargetTimer = 1f; |
| . | return; |
| return true; |
| } |
| } |
| if ((!base.IsAlerted() || (this.m_targetStatic == null && this.m_targetCreature == null)) && this.UpdateConsumeItem(humanoid, dt)) |
| if ((!base.IsAlerted() || (this.m_targetStatic == null && this.m_targetCreature == null)) && this.UpdateConsumeItem(humanoid, dt)) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Consume item"; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| if (this.m_circleTargetInterval > 0f && this.m_targetCreature) |
| if (this.m_circleTargetInterval > 0f && this.m_targetCreature) |
| { |
| { |
| this.m_pauseTimer += dt; |
| this.m_pauseTimer += dt; |
| if (this.m_pauseTimer > this.m_circleTargetInterval) |
| if (this.m_pauseTimer > this.m_circleTargetInterval) |
| { |
| { |
| if (this.m_pauseTimer > this.m_circleTargetInterval + this.m_circleTargetDuration) |
| if (this.m_pauseTimer > this.m_circleTargetInterval + this.m_circleTargetDuration) |
| { |
| { |
| this.m_pauseTimer = UnityEngine.Random.Range(0f, this.m_circleTargetInterval / 10f); |
| this.m_pauseTimer = UnityEngine.Random.Range(0f, this.m_circleTargetInterval / 10f); |
| } |
| } |
| base.RandomMovementArroundPoint(dt, this.m_targetCreature.transform.position, this.m_circleTargetDistance, base.IsAlerted()); |
| base.RandomMovementArroundPoint(dt, this.m_targetCreature.transform.position, this.m_circleTargetDistance, base.IsAlerted()); |
| . | if (this.m_aiStatus != null) |
| return true; |
| { |
| |
| this.m_aiStatus = "Attack pause"; |
| |
| } |
| |
| return; |
| |
| } |
| } |
| } |
| } |
| ItemDrop.ItemData itemData = this.SelectBestAttack(humanoid, dt); |
| ItemDrop.ItemData itemData = this.SelectBestAttack(humanoid, dt); |
| bool flag3 = itemData != null && Time.time - itemData.m_lastAttackTime > itemData.m_shared.m_aiAttackInterval && this.m_character.GetTimeSinceLastAttack() >= this.m_minAttackInterval && !base.IsTakingOff(); |
| bool flag3 = itemData != null && Time.time - itemData.m_lastAttackTime > itemData.m_shared.m_aiAttackInterval && this.m_character.GetTimeSinceLastAttack() >= this.m_minAttackInterval && !base.IsTakingOff(); |
| . | |
| if (!base.IsCharging() && (this.m_targetStatic != null || this.m_targetCreature != null) && itemData != null && flag3 && !this.m_character.InAttack() && itemData.m_shared.m_attack != null && !itemData.m_shared.m_attack.IsDone() && !string.IsNullOrEmpty(itemData.m_shared.m_attack.m_chargeAnimationBool)) |
| |
| { |
| |
| base.ChargeStart(itemData.m_shared.m_attack.m_chargeAnimationBool); |
| |
| } |
| if ((this.m_character.IsFlying() ? this.m_circulateWhileChargingFlying : this.m_circulateWhileCharging) && (this.m_targetStatic != null || this.m_targetCreature != null) && itemData != null && !flag3 && !this.m_character.InAttack()) |
| if ((this.m_character.IsFlying() ? this.m_circulateWhileChargingFlying : this.m_circulateWhileCharging) && (this.m_targetStatic != null || this.m_targetCreature != null) && itemData != null && !flag3 && !this.m_character.InAttack()) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Move around target weapon ready:" + flag3.ToString(); |
| |
| } |
| |
| if (itemData != null && this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = this.m_aiStatus + " Weapon:" + itemData.m_shared.m_name; |
| |
| } |
| |
| Vector3 vector = (this.m_targetCreature ? this.m_targetCreature.transform.position : this.m_targetStatic.transform.position); |
| Vector3 vector = (this.m_targetCreature ? this.m_targetCreature.transform.position : this.m_targetStatic.transform.position); |
| base.RandomMovementArroundPoint(dt, vector, this.m_randomMoveRange, base.IsAlerted()); |
| base.RandomMovementArroundPoint(dt, vector, this.m_randomMoveRange, base.IsAlerted()); |
| . | return; |
| return true; |
| } |
| } |
| if ((this.m_targetStatic == null && this.m_targetCreature == null) || itemData == null) |
| if ((this.m_targetStatic == null && this.m_targetCreature == null) || itemData == null) |
| { |
| { |
| if (this.m_follow) |
| if (this.m_follow) |
| { |
| { |
| base.Follow(this.m_follow, dt); |
| base.Follow(this.m_follow, dt); |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Follow"; |
| |
| return; |
| |
| } |
| |
| } |
| } |
| else |
| else |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| string[] array = new string[7]; |
| |
| array[0] = "Random movement (weapon: "; |
| |
| array[1] = ((itemData != null) ? itemData.m_shared.m_name : "none"); |
| |
| array[2] = ") (targetpiece: "; |
| |
| int num = 3; |
| |
| StaticTarget targetStatic = this.m_targetStatic; |
| |
| array[num] = ((targetStatic != null) ? targetStatic.ToString() : null); |
| |
| array[4] = ") (target: "; |
| |
| array[5] = (this.m_targetCreature ? this.m_targetCreature.gameObject.name : "none"); |
| |
| array[6] = ")"; |
| |
| this.m_aiStatus = string.Concat(array); |
| |
| } |
| |
| base.IdleMovement(dt); |
| base.IdleMovement(dt); |
| } |
| } |
| . | return; |
| base.ChargeStop(); |
| |
| return true; |
| } |
| } |
| if (itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Enemy) |
| if (itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Enemy) |
| { |
| { |
| if (this.m_targetStatic) |
| if (this.m_targetStatic) |
| { |
| { |
| Vector3 vector2 = this.m_targetStatic.FindClosestPoint(base.transform.position); |
| Vector3 vector2 = this.m_targetStatic.FindClosestPoint(base.transform.position); |
| . | if (Vector3.Distance(vector2, base.transform.position) >= itemData.m_shared.m_aiAttackRange || !base.CanSeeTarget(this.m_targetStatic)) |
| if (Vector3.Distance(vector2, base.transform.position) < itemData.m_shared.m_aiAttackRange && base.CanSeeTarget(this.m_targetStatic)) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| base.LookAt(this.m_targetStatic.GetCenter()); |
| |
| if (itemData.m_shared.m_aiAttackMaxAngle == 0f) |
| { |
| { |
| . | this.m_aiStatus = "Move to static target"; |
| ZLog.LogError("AI Attack Max Angle for " + itemData.m_shared.m_name + " is 0!"); |
| } |
| } |
| . | base.MoveTo(dt, vector2, 0f, base.IsAlerted()); |
| if (base.IsLookingAt(this.m_targetStatic.GetCenter(), itemData.m_shared.m_aiAttackMaxAngle, itemData.m_shared.m_aiInvertAngleCheck) && flag3) |
| return; |
| { |
| } |
| this.DoAttack(null, false); |
| base.LookAt(this.m_targetStatic.GetCenter()); |
| } |
| if (base.IsLookingAt(this.m_targetStatic.GetCenter(), itemData.m_shared.m_aiAttackMaxAngle) && flag3) |
| else |
| { |
| |
| if (this.m_aiStatus != null) |
| |
| { |
| { |
| . | this.m_aiStatus = "Attacking piece"; |
| base.StopMoving(); |
| } |
| } |
| . | this.DoAttack(null, false); |
| |
| return; |
| |
| } |
| } |
| . | base.StopMoving(); |
| else |
| return; |
| { |
| |
| base.MoveTo(dt, vector2, 0f, base.IsAlerted()); |
| |
| base.ChargeStop(); |
| |
| } |
| } |
| } |
| else if (this.m_targetCreature) |
| else if (this.m_targetCreature) |
| { |
| { |
| if (flag || flag2 || (this.HuntPlayer() && this.m_targetCreature.IsPlayer())) |
| if (flag || flag2 || (this.HuntPlayer() && this.m_targetCreature.IsPlayer())) |
| { |
| { |
| this.m_beenAtLastPos = false; |
| this.m_beenAtLastPos = false; |
| this.m_lastKnownTargetPos = this.m_targetCreature.transform.position; |
| this.m_lastKnownTargetPos = this.m_targetCreature.transform.position; |
| . | float num2 = Vector3.Distance(this.m_lastKnownTargetPos, base.transform.position) - this.m_targetCreature.GetRadius(); |
| float num = Vector3.Distance(this.m_lastKnownTargetPos, base.transform.position) - this.m_targetCreature.GetRadius(); |
| float num3 = this.m_alertRange * this.m_targetCreature.GetStealthFactor(); |
| float num2 = this.m_alertRange * this.m_targetCreature.GetStealthFactor(); |
| if (flag2 && num2 < num3) |
| if (flag2 && num < num2) |
| { |
| { |
| this.SetAlerted(true); |
| this.SetAlerted(true); |
| } |
| } |
| . | bool flag4 = num2 < itemData.m_shared.m_aiAttackRange; |
| bool flag4 = num < itemData.m_shared.m_aiAttackRange; |
| if (!flag4 || !flag2 || itemData.m_shared.m_aiAttackRangeMin < 0f || !base.IsAlerted()) |
| if (!flag4 || !flag2 || itemData.m_shared.m_aiAttackRangeMin < 0f || !base.IsAlerted()) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Move closer"; |
| |
| } |
| |
| Vector3 velocity = this.m_targetCreature.GetVelocity(); |
| Vector3 velocity = this.m_targetCreature.GetVelocity(); |
| Vector3 vector3 = velocity * this.m_interceptTime; |
| Vector3 vector3 = velocity * this.m_interceptTime; |
| Vector3 vector4 = this.m_lastKnownTargetPos; |
| Vector3 vector4 = this.m_lastKnownTargetPos; |
| . | if (num2 > vector3.magnitude / 4f) |
| if (num > vector3.magnitude / 4f) |
| { |
| { |
| vector4 += velocity * this.m_interceptTime; |
| vector4 += velocity * this.m_interceptTime; |
| } |
| } |
| base.MoveTo(dt, vector4, 0f, base.IsAlerted()); |
| base.MoveTo(dt, vector4, 0f, base.IsAlerted()); |
| if (this.m_timeSinceAttacking > 15f) |
| if (this.m_timeSinceAttacking > 15f) |
| { |
| { |
| this.m_unableToAttackTargetTimer = 15f; |
| this.m_unableToAttackTargetTimer = 15f; |
| } |
| } |
| } |
| } |
| else |
| else |
| { |
| { |
| base.StopMoving(); |
| base.StopMoving(); |
| } |
| } |
| if (flag4 && flag2 && base.IsAlerted()) |
| if (flag4 && flag2 && base.IsAlerted()) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "In attack range"; |
| |
| } |
| |
| base.LookAt(this.m_targetCreature.GetTopPoint()); |
| base.LookAt(this.m_targetCreature.GetTopPoint()); |
| . | if (flag3 && base.IsLookingAt(this.m_lastKnownTargetPos, itemData.m_shared.m_aiAttackMaxAngle)) |
| if (flag3 && base.IsLookingAt(this.m_lastKnownTargetPos, itemData.m_shared.m_aiAttackMaxAngle, itemData.m_shared.m_aiInvertAngleCheck)) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Attacking creature"; |
| |
| } |
| |
| this.DoAttack(this.m_targetCreature, false); |
| this.DoAttack(this.m_targetCreature, false); |
| . | return; |
| |
| } |
| } |
| } |
| } |
| } |
| } |
| else |
| else |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| base.ChargeStop(); |
| { |
| |
| this.m_aiStatus = "Searching for target"; |
| |
| } |
| |
| if (this.m_beenAtLastPos) |
| if (this.m_beenAtLastPos) |
| { |
| { |
| base.RandomMovement(dt, this.m_lastKnownTargetPos, false); |
| base.RandomMovement(dt, this.m_lastKnownTargetPos, false); |
| if (this.m_timeSinceAttacking > 15f) |
| if (this.m_timeSinceAttacking > 15f) |
| { |
| { |
| this.m_unableToAttackTargetTimer = 15f; |
| this.m_unableToAttackTargetTimer = 15f; |
| . | return; |
| |
| } |
| } |
| } |
| } |
| else if (base.MoveTo(dt, this.m_lastKnownTargetPos, 0f, base.IsAlerted())) |
| else if (base.MoveTo(dt, this.m_lastKnownTargetPos, 0f, base.IsAlerted())) |
| { |
| { |
| this.m_beenAtLastPos = true; |
| this.m_beenAtLastPos = true; |
| . | return; |
| |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| else if (itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.FriendHurt || itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Friend) |
| else if (itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.FriendHurt || itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Friend) |
| { |
| { |
| . | if (this.m_aiStatus != null) |
| |
| { |
| |
| this.m_aiStatus = "Helping friend"; |
| |
| } |
| |
| Character character = ((itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.FriendHurt) ? base.HaveHurtFriendInRange(this.m_viewRange) : base.HaveFriendInRange(this.m_viewRange)); |
| Character character = ((itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.FriendHurt) ? base.HaveHurtFriendInRange(this.m_viewRange) : base.HaveFriendInRange(this.m_viewRange)); |
| if (character) |
| if (character) |
| { |
| { |
| . | if (Vector3.Distance(character.transform.position, base.transform.position) >= itemData.m_shared.m_aiAttackRange) |
| if (Vector3.Distance(character.transform.position, base.transform.position) < itemData.m_shared.m_aiAttackRange) |
| { |
| { |
| . | base.MoveTo(dt, character.transform.position, 0f, base.IsAlerted()); |
| if (flag3) |
| return; |
| { |
| |
| base.StopMoving(); |
| |
| base.LookAt(character.transform.position); |
| |
| this.DoAttack(character, true); |
| |
| } |
| |
| else |
| |
| { |
| |
| base.RandomMovement(dt, character.transform.position, false); |
| |
| } |
| } |
| } |
| . | if (flag3) |
| else |
| { |
| { |
| . | base.StopMoving(); |
| base.MoveTo(dt, character.transform.position, 0f, base.IsAlerted()); |
| base.LookAt(character.transform.position); |
| |
| this.DoAttack(character, true); |
| |
| return; |
| |
| } |
| } |
| . | base.RandomMovement(dt, character.transform.position, false); |
| |
| return; |
| |
| } |
| } |
| else |
| else |
| { |
| { |
| base.RandomMovement(dt, base.transform.position, true); |
| base.RandomMovement(dt, base.transform.position, true); |
| } |
| } |
| } |
| } |
| . | |
| return true; |
| } |
| } |
| |
| |
| private bool UpdateConsumeItem(Humanoid humanoid, float dt) |
| private bool UpdateConsumeItem(Humanoid humanoid, float dt) |
| { |
| { |
| if (this.m_consumeItems == null || this.m_consumeItems.Count == 0) |
| if (this.m_consumeItems == null || this.m_consumeItems.Count == 0) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| this.m_consumeSearchTimer += dt; |
| this.m_consumeSearchTimer += dt; |
| if (this.m_consumeSearchTimer > this.m_consumeSearchInterval) |
| if (this.m_consumeSearchTimer > this.m_consumeSearchInterval) |
| { |
| { |
| this.m_consumeSearchTimer = 0f; |
| this.m_consumeSearchTimer = 0f; |
| if (this.m_tamable && !this.m_tamable.IsHungry()) |
| if (this.m_tamable && !this.m_tamable.IsHungry()) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| this.m_consumeTarget = this.FindClosestConsumableItem(this.m_consumeSearchRange); |
| this.m_consumeTarget = this.FindClosestConsumableItem(this.m_consumeSearchRange); |
| } |
| } |
| if (this.m_consumeTarget) |
| if (this.m_consumeTarget) |
| { |
| { |
| if (base.MoveTo(dt, this.m_consumeTarget.transform.position, this.m_consumeRange, false)) |
| if (base.MoveTo(dt, this.m_consumeTarget.transform.position, this.m_consumeRange, false)) |
| { |
| { |
| base.LookAt(this.m_consumeTarget.transform.position); |
| base.LookAt(this.m_consumeTarget.transform.position); |
| . | if (base.IsLookingAt(this.m_consumeTarget.transform.position, 20f) && this.m_consumeTarget.RemoveOne()) |
| if (base.IsLookingAt(this.m_consumeTarget.transform.position, 20f, false) && this.m_consumeTarget.RemoveOne()) |
| { |
| { |
| if (this.m_onConsumedItem != null) |
| if (this.m_onConsumedItem != null) |
| { |
| { |
| this.m_onConsumedItem(this.m_consumeTarget); |
| this.m_onConsumedItem(this.m_consumeTarget); |
| } |
| } |
| humanoid.m_consumeItemEffects.Create(base.transform.position, Quaternion.identity, null, 1f, -1); |
| humanoid.m_consumeItemEffects.Create(base.transform.position, Quaternion.identity, null, 1f, -1); |
| this.m_animator.SetTrigger("consume"); |
| this.m_animator.SetTrigger("consume"); |
| this.m_consumeTarget = null; |
| this.m_consumeTarget = null; |
| } |
| } |
| } |
| } |
| return true; |
| return true; |
| } |
| } |
| return false; |
| return false; |
| } |
| } |
| |
| |
| private ItemDrop FindClosestConsumableItem(float maxRange) |
| private ItemDrop FindClosestConsumableItem(float maxRange) |
| { |
| { |
| if (MonsterAI.m_itemMask == 0) |
| if (MonsterAI.m_itemMask == 0) |
| { |
| { |
| MonsterAI.m_itemMask = LayerMask.GetMask(new string[] { "item" }); |
| MonsterAI.m_itemMask = LayerMask.GetMask(new string[] { "item" }); |
| } |
| } |
| Collider[] array = Physics.OverlapSphere(base.transform.position, maxRange, MonsterAI.m_itemMask); |
| Collider[] array = Physics.OverlapSphere(base.transform.position, maxRange, MonsterAI.m_itemMask); |
| ItemDrop itemDrop = null; |
| ItemDrop itemDrop = null; |
| float num = 999999f; |
| float num = 999999f; |
| foreach (Collider collider in array) |
| foreach (Collider collider in array) |
| { |
| { |
| if (collider.attachedRigidbody) |
| if (collider.attachedRigidbody) |
| { |
| { |
| ItemDrop component = collider.attachedRigidbody.GetComponent<ItemDrop>(); |
| ItemDrop component = collider.attachedRigidbody.GetComponent<ItemDrop>(); |
| if (!(component == null) && component.GetComponent<ZNetView>().IsValid() && this.CanConsume(component.m_itemData)) |
| if (!(component == null) && component.GetComponent<ZNetView>().IsValid() && this.CanConsume(component.m_itemData)) |
| { |
| { |
| float num2 = Vector3.Distance(component.transform.position, base.transform.position); |
| float num2 = Vector3.Distance(component.transform.position, base.transform.position); |
| if (itemDrop == null || num2 < num) |
| if (itemDrop == null || num2 < num) |
| { |
| { |
| itemDrop = component; |
| itemDrop = component; |
| num = num2; |
| num = num2; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| if (itemDrop && base.HavePath(itemDrop.transform.position)) |
| if (itemDrop && base.HavePath(itemDrop.transform.position)) |
| { |
| { |
| return itemDrop; |
| return itemDrop; |
| } |
| } |
| return null; |
| return null; |
| } |
| } |
| |
| |
| private bool CanConsume(ItemDrop.ItemData item) |
| private bool CanConsume(ItemDrop.ItemData item) |
| { |
| { |
| using (List<ItemDrop>.Enumerator enumerator = this.m_consumeItems.GetEnumerator()) |
| using (List<ItemDrop>.Enumerator enumerator = this.m_consumeItems.GetEnumerator()) |
| { |
| { |
| while (enumerator.MoveNext()) |
| while (enumerator.MoveNext()) |
| { |
| { |
| if (enumerator.Current.m_itemData.m_shared.m_name == item.m_shared.m_name) |
| if (enumerator.Current.m_itemData.m_shared.m_name == item.m_shared.m_name) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| } |
| } |
| } |
| } |
| return false; |
| return false; |
| } |
| } |
| |
| |
| private ItemDrop.ItemData SelectBestAttack(Humanoid humanoid, float dt) |
| private ItemDrop.ItemData SelectBestAttack(Humanoid humanoid, float dt) |
| { |
| { |
| if (this.m_targetCreature || this.m_targetStatic) |
| if (this.m_targetCreature || this.m_targetStatic) |
| { |
| { |
| this.m_updateWeaponTimer -= dt; |
| this.m_updateWeaponTimer -= dt; |
| if (this.m_updateWeaponTimer <= 0f && !this.m_character.InAttack()) |
| if (this.m_updateWeaponTimer <= 0f && !this.m_character.InAttack()) |
| { |
| { |
| this.m_updateWeaponTimer = 1f; |
| this.m_updateWeaponTimer = 1f; |
| Character character; |
| Character character; |
| Character character2; |
| Character character2; |
| base.HaveFriendsInRange(this.m_viewRange, out character, out character2); |
| base.HaveFriendsInRange(this.m_viewRange, out character, out character2); |
| humanoid.EquipBestWeapon(this.m_targetCreature, this.m_targetStatic, character, character2); |
| humanoid.EquipBestWeapon(this.m_targetCreature, this.m_targetStatic, character, character2); |
| } |
| } |
| } |
| } |
| return humanoid.GetCurrentWeapon(); |
| return humanoid.GetCurrentWeapon(); |
| } |
| } |
| |
| |
| private bool DoAttack(Character target, bool isFriend) |
| private bool DoAttack(Character target, bool isFriend) |
| { |
| { |
| ItemDrop.ItemData currentWeapon = (this.m_character as Humanoid).GetCurrentWeapon(); |
| ItemDrop.ItemData currentWeapon = (this.m_character as Humanoid).GetCurrentWeapon(); |
| if (currentWeapon == null) |
| if (currentWeapon == null) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| if (!base.CanUseAttack(currentWeapon)) |
| if (!base.CanUseAttack(currentWeapon)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| bool flag = this.m_character.StartAttack(target, false); |
| bool flag = this.m_character.StartAttack(target, false); |
| if (flag) |
| if (flag) |
| { |
| { |
| this.m_timeSinceAttacking = 0f; |
| this.m_timeSinceAttacking = 0f; |
| } |
| } |
| return flag; |
| return flag; |
| } |
| } |
| |
| |
| public void SetDespawnInDay(bool despawn) |
| public void SetDespawnInDay(bool despawn) |
| { |
| { |
| this.m_despawnInDay = despawn; |
| this.m_despawnInDay = despawn; |
| this.m_nview.GetZDO().Set(ZDOVars.s_despawnInDay, despawn); |
| this.m_nview.GetZDO().Set(ZDOVars.s_despawnInDay, despawn); |
| } |
| } |
| |
| |
| public bool DespawnInDay() |
| public bool DespawnInDay() |
| { |
| { |
| if (Time.time - this.m_lastDespawnInDayCheck > 4f) |
| if (Time.time - this.m_lastDespawnInDayCheck > 4f) |
| { |
| { |
| this.m_lastDespawnInDayCheck = Time.time; |
| this.m_lastDespawnInDayCheck = Time.time; |
| this.m_despawnInDay = this.m_nview.GetZDO().GetBool(ZDOVars.s_despawnInDay, this.m_despawnInDay); |
| this.m_despawnInDay = this.m_nview.GetZDO().GetBool(ZDOVars.s_despawnInDay, this.m_despawnInDay); |
| } |
| } |
| return this.m_despawnInDay; |
| return this.m_despawnInDay; |
| } |
| } |
| |
| |
| public void SetEventCreature(bool despawn) |
| public void SetEventCreature(bool despawn) |
| { |
| { |
| this.m_eventCreature = despawn; |
| this.m_eventCreature = despawn; |
| this.m_nview.GetZDO().Set(ZDOVars.s_eventCreature, despawn); |
| this.m_nview.GetZDO().Set(ZDOVars.s_eventCreature, despawn); |
| } |
| } |
| |
| |
| public bool IsEventCreature() |
| public bool IsEventCreature() |
| { |
| { |
| if (Time.time - this.m_lastEventCreatureCheck > 4f) |
| if (Time.time - this.m_lastEventCreatureCheck > 4f) |
| { |
| { |
| this.m_lastEventCreatureCheck = Time.time; |
| this.m_lastEventCreatureCheck = Time.time; |
| this.m_eventCreature = this.m_nview.GetZDO().GetBool(ZDOVars.s_eventCreature, this.m_eventCreature); |
| this.m_eventCreature = this.m_nview.GetZDO().GetBool(ZDOVars.s_eventCreature, this.m_eventCreature); |
| } |
| } |
| return this.m_eventCreature; |
| return this.m_eventCreature; |
| } |
| } |
| |
| |
| protected override void OnDrawGizmosSelected() |
| protected override void OnDrawGizmosSelected() |
| { |
| { |
| base.OnDrawGizmosSelected(); |
| base.OnDrawGizmosSelected(); |
| . | |
| this.DrawAILabel(); |
| |
| } |
| |
| |
| |
| private void OnDrawGizmos() |
| |
| { |
| |
| if (Terminal.m_showTests) |
| |
| { |
| |
| this.DrawAILabel(); |
| |
| } |
| |
| } |
| |
| |
| |
| private void DrawAILabel() |
| |
| { |
| } |
| } |
| |
| |
| public override Character GetTargetCreature() |
| public override Character GetTargetCreature() |
| { |
| { |
| return this.m_targetCreature; |
| return this.m_targetCreature; |
| } |
| } |
| |
| |
| public StaticTarget GetStaticTarget() |
| public StaticTarget GetStaticTarget() |
| { |
| { |
| return this.m_targetStatic; |
| return this.m_targetStatic; |
| } |
| } |
| |
| |
| private void UpdateSleep(float dt) |
| private void UpdateSleep(float dt) |
| { |
| { |
| if (!this.IsSleeping()) |
| if (!this.IsSleeping()) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| this.m_sleepTimer += dt; |
| this.m_sleepTimer += dt; |
| if (this.m_sleepTimer < this.m_sleepDelay) |
| if (this.m_sleepTimer < this.m_sleepDelay) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| if (this.HuntPlayer()) |
| if (this.HuntPlayer()) |
| { |
| { |
| this.Wakeup(); |
| this.Wakeup(); |
| return; |
| return; |
| } |
| } |
| if (this.m_wakeupRange > 0f) |
| if (this.m_wakeupRange > 0f) |
| { |
| { |
| Player closestPlayer = Player.GetClosestPlayer(base.transform.position, this.m_wakeupRange); |
| Player closestPlayer = Player.GetClosestPlayer(base.transform.position, this.m_wakeupRange); |
| if (closestPlayer && !closestPlayer.InGhostMode() && !closestPlayer.IsDebugFlying()) |
| if (closestPlayer && !closestPlayer.InGhostMode() && !closestPlayer.IsDebugFlying()) |
| { |
| { |
| this.Wakeup(); |
| this.Wakeup(); |
| return; |
| return; |
| } |
| } |
| } |
| } |
| if (this.m_noiseWakeup) |
| if (this.m_noiseWakeup) |
| { |
| { |
| Player playerNoiseRange = Player.GetPlayerNoiseRange(base.transform.position, this.m_maxNoiseWakeupRange); |
| Player playerNoiseRange = Player.GetPlayerNoiseRange(base.transform.position, this.m_maxNoiseWakeupRange); |
| if (playerNoiseRange && !playerNoiseRange.InGhostMode() && !playerNoiseRange.IsDebugFlying()) |
| if (playerNoiseRange && !playerNoiseRange.InGhostMode() && !playerNoiseRange.IsDebugFlying()) |
| { |
| { |
| this.Wakeup(); |
| this.Wakeup(); |
| return; |
| return; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| public void OnPrivateAreaAttacked(Character attacker, bool destroyed) |
| public void OnPrivateAreaAttacked(Character attacker, bool destroyed) |
| { |
| { |
| if (attacker.IsPlayer() && base.IsAggravatable() && !base.IsAggravated()) |
| if (attacker.IsPlayer() && base.IsAggravatable() && !base.IsAggravated()) |
| { |
| { |
| this.m_privateAreaAttacks++; |
| this.m_privateAreaAttacks++; |
| if (this.m_privateAreaAttacks > this.m_privateAreaTriggerTreshold || destroyed) |
| if (this.m_privateAreaAttacks > this.m_privateAreaTriggerTreshold || destroyed) |
| { |
| { |
| base.SetAggravated(true, BaseAI.AggravatedReason.Damage); |
| base.SetAggravated(true, BaseAI.AggravatedReason.Damage); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| private void RPC_Wakeup(long sender) |
| private void RPC_Wakeup(long sender) |
| { |
| { |
| if (this.m_nview.GetZDO().IsOwner()) |
| if (this.m_nview.GetZDO().IsOwner()) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| this.m_sleeping = false; |
| this.m_sleeping = false; |
| } |
| } |
| |
| |
| private void Wakeup() |
| private void Wakeup() |
| { |
| { |
| if (!this.IsSleeping()) |
| if (!this.IsSleeping()) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| this.m_animator.SetBool(MonsterAI.s_sleeping, false); |
| this.m_animator.SetBool(MonsterAI.s_sleeping, false); |
| this.m_nview.GetZDO().Set(ZDOVars.s_sleeping, false); |
| this.m_nview.GetZDO().Set(ZDOVars.s_sleeping, false); |
| this.m_wakeupEffects.Create(base.transform.position, base.transform.rotation, null, 1f, -1); |
| this.m_wakeupEffects.Create(base.transform.position, base.transform.rotation, null, 1f, -1); |
| this.m_sleeping = false; |
| this.m_sleeping = false; |
| this.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_Wakeup", Array.Empty<object>()); |
| this.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_Wakeup", Array.Empty<object>()); |
| } |
| } |
| |
| |
| public override bool IsSleeping() |
| public override bool IsSleeping() |
| { |
| { |
| return this.m_sleeping; |
| return this.m_sleeping; |
| } |
| } |
| |
| |
| protected override void SetAlerted(bool alert) |
| protected override void SetAlerted(bool alert) |
| { |
| { |
| if (alert) |
| if (alert) |
| { |
| { |
| this.m_timeSinceSensedTargetCreature = 0f; |
| this.m_timeSinceSensedTargetCreature = 0f; |
| } |
| } |
| base.SetAlerted(alert); |
| base.SetAlerted(alert); |
| } |
| } |
| |
| |
| public override bool HuntPlayer() |
| public override bool HuntPlayer() |
| { |
| { |
| . | return base.HuntPlayer() && (!this.IsEventCreature() || RandEventSystem.InEvent()) && (!this.DespawnInDay() || !EnvMan.instance.IsDay()); |
| return base.HuntPlayer() && (!this.IsEventCreature() || RandEventSystem.InEvent()) && (!this.DespawnInDay() || !EnvMan.IsDay()); |
| } |
| } |
| |
| |
| public GameObject GetFollowTarget() |
| public GameObject GetFollowTarget() |
| { |
| { |
| return this.m_follow; |
| return this.m_follow; |
| } |
| } |
| |
| |
| public void SetFollowTarget(GameObject go) |
| public void SetFollowTarget(GameObject go) |
| { |
| { |
| this.m_follow = go; |
| this.m_follow = go; |
| } |
| } |
| |
| |
| . | public new static List<MonsterAI> Instances { get; } = new List<MonsterAI>(); |
| |
| |
| |
| private float m_lastDespawnInDayCheck = -9999f; |
| private float m_lastDespawnInDayCheck = -9999f; |
| |
| |
| private float m_lastEventCreatureCheck = -9999f; |
| private float m_lastEventCreatureCheck = -9999f; |
| |
| |
| public Action<ItemDrop> m_onConsumedItem; |
| public Action<ItemDrop> m_onConsumedItem; |
| |
| |
| private const float m_giveUpTime = 30f; |
| private const float m_giveUpTime = 30f; |
| |
| |
| private const float m_updateTargetFarRange = 50f; |
| private const float m_updateTargetFarRange = 50f; |
| |
| |
| private const float m_updateTargetIntervalNear = 2f; |
| private const float m_updateTargetIntervalNear = 2f; |
| |
| |
| private const float m_updateTargetIntervalFar = 6f; |
| private const float m_updateTargetIntervalFar = 6f; |
| |
| |
| private const float m_updateWeaponInterval = 1f; |
| private const float m_updateWeaponInterval = 1f; |
| |
| |
| private const float m_unableToAttackTargetDuration = 15f; |
| private const float m_unableToAttackTargetDuration = 15f; |
| |
| |
| [Header("Monster AI")] |
| [Header("Monster AI")] |
| public float m_alertRange = 9999f; |
| public float m_alertRange = 9999f; |
| |
| |
| public bool m_fleeIfHurtWhenTargetCantBeReached = true; |
| public bool m_fleeIfHurtWhenTargetCantBeReached = true; |
| |
| |
| . | |
| public float m_fleeUnreachableSinceAttacking = 30f; |
| |
| |
| |
| public float m_fleeUnreachableSinceHurt = 20f; |
| |
| |
| public bool m_fleeIfNotAlerted; |
| public bool m_fleeIfNotAlerted; |
| |
| |
| public float m_fleeIfLowHealth; |
| public float m_fleeIfLowHealth; |
| |
| |
| . | |
| public float m_fleeTimeSinceHurt = 20f; |
| |
| |
| |
| public bool m_fleeInLava = true; |
| |
| |
| public bool m_circulateWhileCharging; |
| public bool m_circulateWhileCharging; |
| |
| |
| public bool m_circulateWhileChargingFlying; |
| public bool m_circulateWhileChargingFlying; |
| |
| |
| public bool m_enableHuntPlayer; |
| public bool m_enableHuntPlayer; |
| |
| |
| public bool m_attackPlayerObjects = true; |
| public bool m_attackPlayerObjects = true; |
| |
| |
| public int m_privateAreaTriggerTreshold = 4; |
| public int m_privateAreaTriggerTreshold = 4; |
| |
| |
| public float m_interceptTimeMax; |
| public float m_interceptTimeMax; |
| |
| |
| public float m_interceptTimeMin; |
| public float m_interceptTimeMin; |
| |
| |
| public float m_maxChaseDistance; |
| public float m_maxChaseDistance; |
| |
| |
| public float m_minAttackInterval; |
| public float m_minAttackInterval; |
| |
| |
| [Header("Circle target")] |
| [Header("Circle target")] |
| public float m_circleTargetInterval; |
| public float m_circleTargetInterval; |
| |
| |
| public float m_circleTargetDuration = 5f; |
| public float m_circleTargetDuration = 5f; |
| |
| |
| public float m_circleTargetDistance = 10f; |
| public float m_circleTargetDistance = 10f; |
| |
| |
| [Header("Sleep")] |
| [Header("Sleep")] |
| public bool m_sleeping; |
| public bool m_sleeping; |
| |
| |
| public float m_wakeupRange = 5f; |
| public float m_wakeupRange = 5f; |
| |
| |
| public bool m_noiseWakeup; |
| public bool m_noiseWakeup; |
| |
| |
| public float m_maxNoiseWakeupRange = 50f; |
| public float m_maxNoiseWakeupRange = 50f; |
| |
| |
| public EffectList m_wakeupEffects = new EffectList(); |
| public EffectList m_wakeupEffects = new EffectList(); |
| |
| |
| public float m_wakeUpDelayMin; |
| public float m_wakeUpDelayMin; |
| |
| |
| public float m_wakeUpDelayMax; |
| public float m_wakeUpDelayMax; |
| |
| |
| [Header("Other")] |
| [Header("Other")] |
| public bool m_avoidLand; |
| public bool m_avoidLand; |
| |
| |
| [Header("Consume items")] |
| [Header("Consume items")] |
| public List<ItemDrop> m_consumeItems; |
| public List<ItemDrop> m_consumeItems; |
| |
| |
| public float m_consumeRange = 2f; |
| public float m_consumeRange = 2f; |
| |
| |
| public float m_consumeSearchRange = 5f; |
| public float m_consumeSearchRange = 5f; |
| |
| |
| public float m_consumeSearchInterval = 10f; |
| public float m_consumeSearchInterval = 10f; |
| |
| |
| private ItemDrop m_consumeTarget; |
| private ItemDrop m_consumeTarget; |
| |
| |
| private float m_consumeSearchTimer; |
| private float m_consumeSearchTimer; |
| |
| |
| private static int m_itemMask = 0; |
| private static int m_itemMask = 0; |
| . | |
| |
| private string m_aiStatus; |
| |
| |
| |
| private bool m_despawnInDay; |
| private bool m_despawnInDay; |
| |
| |
| private bool m_eventCreature; |
| private bool m_eventCreature; |
| |
| |
| private Character m_targetCreature; |
| private Character m_targetCreature; |
| |
| |
| private Vector3 m_lastKnownTargetPos = Vector3.zero; |
| private Vector3 m_lastKnownTargetPos = Vector3.zero; |
| |
| |
| private bool m_beenAtLastPos; |
| private bool m_beenAtLastPos; |
| |
| |
| private StaticTarget m_targetStatic; |
| private StaticTarget m_targetStatic; |
| |
| |
| private float m_timeSinceAttacking; |
| private float m_timeSinceAttacking; |
| |
| |
| private float m_timeSinceSensedTargetCreature; |
| private float m_timeSinceSensedTargetCreature; |
| |
| |
| private float m_updateTargetTimer; |
| private float m_updateTargetTimer; |
| |
| |
| private float m_updateWeaponTimer; |
| private float m_updateWeaponTimer; |
| |
| |
| private float m_interceptTime; |
| private float m_interceptTime; |
| |
| |
| private float m_sleepDelay = 0.5f; |
| private float m_sleepDelay = 0.5f; |
| |
| |
| private float m_pauseTimer; |
| private float m_pauseTimer; |
| |
| |
| private float m_sleepTimer; |
| private float m_sleepTimer; |
| |
| |
| private float m_unableToAttackTargetTimer; |
| private float m_unableToAttackTargetTimer; |
| |
| |
| private GameObject m_follow; |
| private GameObject m_follow; |
| |
| |
| private int m_privateAreaAttacks; |
| private int m_privateAreaAttacks; |
| |
| |
| private static readonly int s_sleeping = ZSyncAnimation.GetHash("sleeping"); |
| private static readonly int s_sleeping = ZSyncAnimation.GetHash("sleeping"); |
| } |
| } |
| |
| |