using GamePath; using System.Collections.Generic; using System.Globalization; public class EAIApproachAndAttackTargetSDX : EAIApproachAndAttackTarget { public override void Init(EntityAlive _theEntity) { //Log.Out("EAIApproachAndAttackTargetSDX-Init START"); base.Init(_theEntity); this.MutexBits = 3; this.executeDelay = 0.1f; } public override void SetData(DictionarySave data) { //Log.Out("EAIApproachAndAttackTargetSDX-SetData START"); base.SetData(data); this.targetClasses = new List(); string text; if (data.TryGetValue("class", out text)) { string[] array = text.Split(new char[] { ',' }); for (int i = 0; i < array.Length; i += 2) { EAIApproachAndAttackTargetSDX.TargetClass item = default(EAIApproachAndAttackTargetSDX.TargetClass); item.type = EntityFactory.GetEntityType(array[i]); item.maxChaseTime = 0f; if (i + 1 < array.Length) { item.maxChaseTime = StringParsers.ParseFloat(array[i + 1], 0, -1, NumberStyles.Any); } this.targetClasses.Add(item); } } } public override bool CanExecute() { //Log.Out("EAIApproachAndAttackTargetSDX-CanExecute START"); if (RebirthUtilities.canAttack(theEntity)) { return false; } if (!this.theEntity.GetRevengeTarget()) { EntityPlayer closestPlayer = null; float num = 200 * 200; float num2 = float.MaxValue; for (int i = this.theEntity.world.Players.list.Count - 1; i >= 0; i--) { EntityPlayer entityPlayer = this.theEntity.world.Players.list[i]; if (!entityPlayer.IsDead() && entityPlayer.Spawned && !entityPlayer.IsSpectator) { //Log.Out("FOUND PLAYER: " + entityPlayer.EntityName); float distanceSq = entityPlayer.GetDistanceSq(this.theEntity.position); if (distanceSq < num2 && distanceSq <= num) { num2 = distanceSq; closestPlayer = entityPlayer; } } } if (closestPlayer != null) { this.theEntity.SetAttackTarget(closestPlayer, 200); this.entityTarget = closestPlayer; //Log.Out("CanExecute GOT CLOSEST PLAYER"); } else { this.entityTarget = this.theEntity.GetAttackTarget(); //Log.Out("CanExecute NO CLOSEST PLAYER"); } } else { this.entityTarget = this.theEntity.GetRevengeTarget(); } if (this.entityTarget == null) { //Log.Out("CanExecute NO TARGET"); return false; } Type type = this.entityTarget.GetType(); for (int i = 0; i < this.targetClasses.Count; i++) { EAIApproachAndAttackTargetSDX.TargetClass targetClass = this.targetClasses[i]; if (targetClass.type != null && targetClass.type.IsAssignableFrom(type)) { this.maxChaseTime = targetClass.maxChaseTime; return true; } } return false; } public override void Start() { //Log.Out("EAIApproachAndAttackTargetSDX-Start START"); this.entityTargetPos = this.entityTarget.position; this.entityTargetVel = Vector3.zero; this.isTargetToEat = this.entityTarget.IsDead() && !(this.entityTarget is EntityZombie); this.isEating = false; this.theEntity.IsEating = false; this.homeTimeout = (this.theEntity.IsSleeper ? 90f : this.maxChaseTime); this.hasHome = (this.homeTimeout > 0f); this.isGoingHome = false; if (this.theEntity.ChaseReturnLocation == Vector3.zero) { this.theEntity.ChaseReturnLocation = (this.theEntity.IsSleeper ? this.theEntity.SleeperSpawnPosition : this.theEntity.position); } this.pathCounter = 0; this.relocateTicks = 0; if (this.isTargetToEat) { Vector3 moveToLocation = this.GetMoveToLocation(0f); this.theEntity.FindPath(moveToLocation, this.theEntity.GetMoveSpeedAggro(), true, this); } this.attackTimeout = 5; } public override bool Continue() { //Log.Out($"EAIApproachAndAttackTargetSDX-Continue START this {theEntity}, attackTarget: {theEntity.attackTarget}"); if (RebirthUtilities.canAttack(theEntity)) { return false; } EntityAlive attackTarget = this.theEntity.GetAttackTarget(); if (this.isGoingHome) { return !attackTarget && this.theEntity.ChaseReturnLocation != Vector3.zero; } return attackTarget && !(attackTarget != this.entityTarget) && attackTarget.IsDead() == this.isTargetToEat; } public override void Reset() { //Log.Out("EAIApproachAndAttackTargetSDX-Reset START"); this.theEntity.IsEating = false; this.theEntity.navigator.clearPath(); if (this.blockTargetTask != null) { this.blockTargetTask.canExecute = false; } } public override void Update() { //Log.Out("EAIApproachAndAttackTargetSDX-Update START"); if (this.hasHome && !this.isTargetToEat) { if (this.isGoingHome) { Vector3 vector = this.theEntity.ChaseReturnLocation - this.theEntity.position; float y = vector.y; vector.y = 0f; if (vector.sqrMagnitude <= 0.16000001f && Utils.FastAbs(y) < 2f) { Vector3 chaseReturnLocation = this.theEntity.ChaseReturnLocation; chaseReturnLocation.y = this.theEntity.position.y; this.theEntity.SetPosition(chaseReturnLocation, true); this.theEntity.ChaseReturnLocation = Vector3.zero; if (this.theEntity.IsSleeper) { this.theEntity.ResumeSleeperPose(); } return; } int num = this.pathCounter - 1; this.pathCounter = num; if (num <= 0 && !PathFinderThread.Instance.IsCalculatingPath(this.theEntity.entityId)) { this.pathCounter = 60; float moveSpeed = this.theEntity.GetMoveSpeedAggro() * 0.8f; this.theEntity.FindPath(this.theEntity.ChaseReturnLocation, moveSpeed, true, this); } return; } else { this.homeTimeout -= 0.05f; if (this.homeTimeout <= 0f) { if (this.blockTargetTask == null) { List targetTasks = this.manager.GetTargetTasks(); if (targetTasks != null) { this.blockTargetTask = targetTasks[0]; } } if (this.blockTargetTask != null) { this.blockTargetTask.canExecute = true; } this.theEntity.attackTarget = (EntityAlive) null; this.theEntity.SetLookPosition(Vector3.zero); this.theEntity.PlayGiveUpSound(); this.pathCounter = 0; this.isGoingHome = true; return; } } } if (this.entityTarget == null) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 1"); //Log.Out("Update NO TARGET"); EntityPlayer closestPlayer = null; float numTarget = 200 * 200; float numTarget2 = float.MaxValue; //Log.Out("EAIApproachAndAttackTargetSDX-Update 1ba"); for (int i = this.theEntity.world.Players.list.Count - 1; i >= 0; i--) { EntityPlayer entityPlayer = this.theEntity.world.Players.list[i]; if (!entityPlayer.IsDead() && entityPlayer.Spawned) { //Log.Out("FOUND PLAYER: " + entityPlayer.EntityName); float distanceSq = entityPlayer.GetDistanceSq(this.theEntity.position); if (distanceSq < numTarget2 && distanceSq <= numTarget) { numTarget2 = distanceSq; closestPlayer = entityPlayer; } } } if (closestPlayer != null) { this.theEntity.SetAttackTarget(closestPlayer, 120); this.entityTarget = closestPlayer; //Log.Out("Update GOT PLAYER TARGET: " + closestPlayer.EntityName); } if (this.entityTarget == null) { return; } } else { //Log.Out("UPDATE-EntityTarget Name: " + this.entityTarget.EntityName); } if (this.relocateTicks > 0) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 2"); if (!this.theEntity.navigator.noPathAndNotPlanningOne()) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 3"); this.relocateTicks--; this.theEntity.moveHelper.SetFocusPos(this.entityTarget.position); return; } this.relocateTicks = 0; } Vector3 position = this.entityTarget.position; Vector3 vector2 = position - this.entityTargetPos; if (vector2.sqrMagnitude < 1f) { this.entityTargetVel = this.entityTargetVel * 0.7f + vector2 * 0.3f; } this.entityTargetPos = position; this.attackTimeout--; if (this.isEating) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 4"); if (this.theEntity.bodyDamage.HasLimbs) { this.theEntity.RotateTo(position.x, position.y, position.z, 30f, 30f); } if (this.attackTimeout <= 0) { this.theEntity.PlayOneShot("eat_player", false); this.attackTimeout = 60 + base.GetRandom(20); } return; } this.theEntity.moveHelper.CalcIfUnreachablePos(); ItemAction itemAction = this.theEntity.inventory.holdingItem.Actions[0]; float num2 = 1.095f; if (!this.isTargetToEat) { num2 = ((itemAction != null) ? Utils.FastMax(0.5f, itemAction.Range - 0.35f) : 0.5f); } float num3 = num2 * num2; float estimatedTicks = 1f + base.RandomFloat * 10f; float targetXZDistanceSq = this.GetTargetXZDistanceSq(estimatedTicks); float num4 = position.y - this.theEntity.position.y; float num5 = Utils.FastAbs(num4); bool flag = targetXZDistanceSq <= num3 && num5 < 1f; if (!flag && !this.isTargetToEat) { if (!PathFinderThread.Instance.IsCalculatingPath(this.theEntity.entityId)) { PathEntity path = this.theEntity.navigator.getPath(); if (path != null && path.NodeCountRemaining() <= 2) { this.pathCounter = 0; } } int num = this.pathCounter - 1; this.pathCounter = num; if (num <= 0 && !PathFinderThread.Instance.IsCalculatingPath(this.theEntity.entityId)) { this.pathCounter = 6 + base.GetRandom(10); Vector3 moveToLocation = this.GetMoveToLocation(num2); this.theEntity.FindPath(moveToLocation, this.theEntity.GetMoveSpeedAggro(), true, this); } } if (this.theEntity.Climbing) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 5"); return; } bool flag2 = this.theEntity.CanSee(this.entityTarget); if (!flag2) { //Log.Out("Update - CANNOT SEE TARGET"); } this.theEntity.SetLookPosition((!this.theEntity.IsBreakingBlocks) ? this.entityTarget.getHeadPosition() : Vector3.zero); if (!flag) { if (this.theEntity.navigator.noPathAndNotPlanningOne() && num4 < 2.1f) { Vector3 moveToLocation2 = this.GetMoveToLocation(num2); this.theEntity.moveHelper.SetMoveTo(moveToLocation2, true); } } else { this.theEntity.navigator.clearPath(); this.theEntity.moveHelper.Stop(); this.pathCounter = 0; } float num6 = this.isTargetToEat ? 1.095f : ((itemAction != null) ? (itemAction.Range - 0.1f) : 0f); float num7 = num6 * num6; if (targetXZDistanceSq > num7 || num5 >= 1.25f) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 6"); return; } this.theEntity.IsBreakingBlocks = false; this.theEntity.IsBreakingDoors = false; if (this.theEntity.bodyDamage.HasLimbs) { this.theEntity.RotateTo(position.x, position.y, position.z, 30f, 30f); } if (this.isTargetToEat) { this.isEating = true; this.theEntity.IsEating = true; this.attackTimeout = 0; //Log.Out("EAIApproachAndAttackTargetSDX-Update 6a"); return; } if (this.theEntity.GetDamagedTarget() == this.entityTarget || (this.entityTarget != null && this.entityTarget.GetDamagedTarget() == this.theEntity)) { this.homeTimeout = (this.theEntity.IsSleeper ? 90f : this.maxChaseTime); if (this.blockTargetTask != null) { this.blockTargetTask.canExecute = false; } this.theEntity.ClearDamagedTarget(); if (this.entityTarget) { this.entityTarget.ClearDamagedTarget(); } } if (this.attackTimeout > 0) { //Log.Out("EAIApproachAndAttackTargetSDX-Update 7"); return; } if (this.manager.groupCircle > 0f) { Entity targetIfAttackedNow = this.theEntity.GetTargetIfAttackedNow(); if (targetIfAttackedNow != this.entityTarget && (!this.entityTarget.AttachedToEntity || this.entityTarget.AttachedToEntity != targetIfAttackedNow)) { if (targetIfAttackedNow != null) { this.relocateTicks = 46; Vector3 vector3 = (this.theEntity.position - position).normalized * (num6 + 1.1f); float num8 = base.RandomFloat * 28f + 18f; if (base.RandomFloat < 0.5f) { num8 = -num8; } vector3 = Quaternion.Euler(0f, num8, 0f) * vector3; Vector3 targetPos = position + vector3; this.theEntity.FindPath(targetPos, this.theEntity.GetMoveSpeedAggro(), true, this); } //Log.Out("EAIApproachAndAttackTargetSDX-Update 8"); return; } } //Log.Out("EAIApproachAndAttackTargetSDX-Update 9"); this.theEntity.SleeperSupressLivingSounds = false; if (this.theEntity.Attack(false)) { this.attackTimeout = this.theEntity.GetAttackTimeoutTicks(); this.theEntity.Attack(true); } } private float GetTargetXZDistanceSq(float estimatedTicks) { Vector3 vector = this.entityTarget.position; vector += this.entityTargetVel * estimatedTicks; if (this.isTargetToEat) { EModelBase emodel = this.entityTarget.emodel; if (emodel && emodel.bipedPelvisTransform) { vector = emodel.bipedPelvisTransform.position + Origin.position; } } Vector3 vector2 = this.theEntity.position + this.theEntity.motion * estimatedTicks - vector; vector2.y = 0f; return vector2.sqrMagnitude; } private Vector3 GetMoveToLocation(float maxDist) { //Log.Out("EAIApproachAndAttackTargetSDX-GetMoveToLocation START"); Vector3 vector = this.entityTarget.position; vector += this.entityTargetVel * 6f; if (this.isTargetToEat) { EModelBase emodel = this.entityTarget.emodel; if (emodel && emodel.bipedPelvisTransform) { vector = emodel.bipedPelvisTransform.position + Origin.position; } } vector = this.entityTarget.world.FindSupportingBlockPos(vector); if (maxDist > 0f) { Vector3 vector2 = new Vector3(this.theEntity.position.x, vector.y, this.theEntity.position.z); Vector3 vector3 = vector - vector2; float magnitude = vector3.magnitude; if (magnitude < 3f) { if (magnitude <= maxDist) { float num = vector.y - this.theEntity.position.y; if (num < -3f || num > 1.5f) { return vector; } return vector2; } else { vector3 *= maxDist / magnitude; Vector3 vector4 = vector - vector3; vector4.y += 0.51f; Vector3i pos = World.worldToBlockPos(vector4); BlockValue block = this.entityTarget.world.GetBlock(pos); Block block2 = block.Block; if (block2.PathType <= 0) { RaycastHit raycastHit; if (Physics.Raycast(vector4 - Origin.position, Vector3.down, out raycastHit, 1.02f, 1082195968)) { vector4.y = raycastHit.point.y + Origin.position.y; return vector4; } if (block2.IsElevator((int)block.rotation)) { vector4.y = vector.y; return vector4; } } } } } return vector; } public override string ToString() { ItemAction itemAction = this.theEntity.inventory.holdingItem.Actions[0]; float value = (itemAction != null) ? (itemAction.Range - 0.1f) : 0f; float targetXZDistanceSq = this.GetTargetXZDistanceSq(0f); return string.Format("{0}, {1}{2}{3}{4}{5} dist {6} rng {7} timeout {8}", new object[] { base.ToString(), this.entityTarget ? this.entityTarget.EntityName : "", this.theEntity.CanSee(this.entityTarget) ? "(see)" : "", this.theEntity.navigator.noPathAndNotPlanningOne() ? "(-path)" : (this.theEntity.navigator.noPath() ? "(!path)" : ""), this.isTargetToEat ? "(eat)" : "", this.isGoingHome ? "(home)" : "", Mathf.Sqrt(targetXZDistanceSq).ToCultureInvariantString("0.000"), value.ToCultureInvariantString("0.000"), this.homeTimeout.ToCultureInvariantString("0.00") }); } private const float cSleeperChaseTime = 90f; private List targetClasses; private float maxChaseTime; private bool hasHome; private bool isGoingHome; private float homeTimeout; private EntityAlive entityTarget; private Vector3 entityTargetPos; private Vector3 entityTargetVel; private int attackTimeout; private int pathCounter; private bool isTargetToEat; private bool isEating; private EAIBlockingTargetTask blockTargetTask; private int relocateTicks; private struct TargetClass { public Type type; public float maxChaseTime; } }