// flocking logic private void flockTasks() { if (GamePrefs.GetBool(EnumGamePrefs.DebugStopEnemiesMoving) || GameStats.GetInt(EnumGameStats.GameState) == 2) { return; } if (this.world.IsRemote()) { return; } if (this.IsDead()) { return; } if (masterEntity == null && !hasFlock && maxToSpawn > 0) { SpawnFlock(); } else if (masterEntity == null && hasFlock && oldmasterID > 0) { FindOldMaster(); } base.GetEntitySenses().ClearIfExpired(); if (this.AttackTimeout > 0) { this.AttackTimeout--; } if (this.AttackTimeout <= 0) { Vector3 a = this.Waypoint - this.position; float sqrMagnitude = a.sqrMagnitude; if (sqrMagnitude < 1f || sqrMagnitude > 6400f) { if (!base.isWithinHomeDistanceCurrentPosition() && this.GetMasterEntity() == null && !isHunting) { // uses vanilla code to stay near "home position" if its a "master" Vector3 ye = RandomPositionGenerator.CalcTowards(this, 2 * base.getMaximumHomeDistance(), 2 * base.getMaximumHomeDistance(), 2 * base.getMaximumHomeDistance(), base.getHomePosition().position.ToVector3()); if (!ye.Equals(Vector3.zero)) { if (debug) { Debug.Log("Going Home"); } this.Waypoint = ye; this.HasWaypoint = true; } } else { this.HasWaypoint = false; if (base.GetRevengeTarget() != null && ((base.GetRevengeTarget().GetDistanceSq(this) < 6400f && UnityEngine.Random.value <= 0.5f) || isHunting)) { // if it's targeting an enemy. Notice that if it's hunting I just want it to get it done. this.Waypoint = base.GetRevengeTarget().GetPosition() + Vector3.up; } else { if (this.GetMasterEntity() == null) { // if it finds a target block nearby, it will go for it. Not attack it, just go near it // this will make them "destroy" crops for example, if we make them target crop blocks. if (FindLandSpot()) { // going for landing spot this.Waypoint = landPosition + new Vector3((float)((this.rand.RandomDouble * 2.0 - 1.0) * 3.0), (float)((this.rand.RandomDouble * 2.0 - 1.0) * 3.0), (float)((this.rand.RandomDouble * 2.0 - 1.0) * 3.0)); } else { // chooses a random waypoint - vanilla code this.Waypoint = base.GetPosition() + new Vector3((float)((this.rand.RandomDouble * 2.0 - 1.0) * 16.0), (float)((this.rand.RandomDouble * 2.0 - 1.0) * 16.0), (float)((this.rand.RandomDouble * 2.0 - 1.0) * 16.0)); // maximum Y. Just to avoid them going too high (out of sight, out of heart) int maxY = this.world.GetHeight((int)this.Waypoint.x, (int)this.Waypoint.z) + maxHeight; if (this.Waypoint.y > maxY) { this.Waypoint.y = maxY; if (debug) { Debug.Log("Prevented it from going higher"); } } } } else { if ((this.GetMasterEntity() as EntityZombieFlockSDX).GetRevengeTarget() != null) { // attacks the same target as master this.SetRevengeTarget((this.GetMasterEntity() as EntityZombieFlockSDX).GetRevengeTarget()); this.Waypoint = (this.GetMasterEntity() as EntityZombieFlockSDX).GetRevengeTarget().GetPosition() + Vector3.up; } else { // if the master has a landing spot, it goes to random position near the landing spot, otherwise just follows master if ((this.GetMasterEntity() as EntityZombieFlockSDX).GetLandingSpot() == Vector3.zero) { this.Waypoint = this.GetMasterEntity().GetPosition() + Vector3.up; } else { this.Waypoint = (this.GetMasterEntity() as EntityZombieFlockSDX).GetLandingSpot() + new Vector3((float)((this.rand.RandomDouble * 2.0 - 1.0) * 3.0), (float)((this.rand.RandomDouble * 2.0 - 1.0) * 3.0), (float)((this.rand.RandomDouble * 2.0 - 1.0) * 3.0)); } } } } int num = 255; // if waypoint is not in the air, change it up while (this.world.GetBlock(new Vector3i(this.Waypoint)).type != BlockValue.Air.type && num > 0) { this.Waypoint.y = this.Waypoint.y + 1f; num--; } } this.Waypoint.y = Mathf.Min(this.Waypoint.y, 250f); } if (this.CourseCheck-- <= 0) { this.CourseCheck += this.rand.RandomRange(5) + 2; //if (base.isCourseTraversable(this.Waypoint, out sqrMagnitude)) //{ // this.motion += a / sqrMagnitude * 0.1f; //} //else //{ this.Waypoint = base.GetPosition(); //} } } if (base.GetRevengeTarget() != null) { if (!retaliateAttack && !targetPlayers && !isHunting) { base.SetRevengeTarget(null); } else if (base.GetRevengeTarget().IsDead()) { base.SetRevengeTarget(null); isHunting = false; } } // if it's a parent and has no target, then it will look for one. if ((base.GetRevengeTarget() == null) && this.GetMasterEntity() == null) { if (this.TargetInterval-- <= 0) { isHunting = false; if (targetPlayers) { // if it's an agressive animal, will look for a player to attack FindClosestPlayer(); } if ((base.GetRevengeTarget() == null)) { if (naturalEnemies != null) { if (naturalEnemies.Length > 0) { // if it has natural enemies, will look for one to attack FindNaturalEnemy(); } } } if (base.GetRevengeTarget() != null) { this.TargetInterval = 20; } } } float intendedRotation; if (!this.HasWaypoint) { if (base.GetRevengeTarget() != null) { float distanceSq; if ((distanceSq = base.GetRevengeTarget().GetDistanceSq(this)) < 6400f) { float y = base.GetRevengeTarget().position.x - this.position.x; float x = base.GetRevengeTarget().position.z - this.position.z; if (distanceSq < 5f) { intendedRotation = Mathf.Atan2(y, x) * 180f / 3.14159274f; } else { intendedRotation = (float)Math.Atan2((double)this.motion.x, (double)this.motion.z) * 180f / 3.14159274f; if (this.motion.magnitude < 0.25f) { this.motion = this.motion.normalized * 0.25f; } } if (this.AttackTimeout <= 0) { if (distanceSq < 2.8f) { if (this.position.y >= base.GetRevengeTarget().position.y) { if (!isHunting) { if (this.position.y <= base.GetRevengeTarget().getHeadPosition().y - 0.25f) { if (base.Attack(false)) { this.AttackTimeout = base.GetAttackTimeoutTicks(); base.Attack(true); } } } else { // just marks the "target" to unload, as if it had captured it. if (UnityEngine.Random.value <= 0.5f) { if (debug) { Debug.Log("Eating the target!!!"); } base.GetRevengeTarget().MarkToUnload(); // stops hunting to look for another suitable target after a bit isHunting = false; base.SetRevengeTarget(null); this.TargetInterval = 50; } } } } } this.rotation.y = EntityAlive.UpdateRotation(this.rotation.y, intendedRotation, 10f); return; } } } intendedRotation = (float)Math.Atan2((double)this.motion.x, (double)this.motion.z) * 180f / 3.14159274f; this.rotation.y = EntityAlive.UpdateRotation(this.rotation.y, intendedRotation, 10f); }