public override bool ShouldExecute() { // React immediately on hurt, otherwise only 1/10 chance of execution if (rand.NextDouble() > 0.1f && (whenInEmotionState == null || bhEmo?.IsInEmotionState(whenInEmotionState) != true)) { return(false); } if (whenInEmotionState != null && bhEmo?.IsInEmotionState(whenInEmotionState) != true) { return(false); } if (whenNotInEmotionState != null && bhEmo?.IsInEmotionState(whenNotInEmotionState) == true) { return(false); } if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } if (cooldownUntilMs > entity.World.ElapsedMilliseconds) { return(false); } float range = maxDist; lastSearchTotalMs = entity.World.ElapsedMilliseconds; Vec3d ownPos = entity.ServerPos.XYZ; targetEntity = partitionUtil.GetNearestEntity(entity.ServerPos.XYZ, range, (e) => IsTargetableEntity(e, range) && hasDirectContact(e, range, range / 2f)); return(targetEntity != null); }
public override bool ShouldExecute() { // React immediately on hurt, otherwise only 1/10 chance of execution if (rand.NextDouble() > 0.1f && (whenInEmotionState == null || !entity.HasEmotionState(whenInEmotionState))) { return(false); } if (whenInEmotionState != null && !entity.HasEmotionState(whenInEmotionState)) { return(false); } if (whenNotInEmotionState != null && entity.HasEmotionState(whenNotInEmotionState)) { return(false); } if (lastSearchTotalMs + 4000 > entity.World.ElapsedMilliseconds) { return(false); } if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } if (jumpAnimOn && entity.World.ElapsedMilliseconds - finishedMs > 2000) { entity.AnimManager.StopAnimation("jump"); } if (cooldownUntilMs > entity.World.ElapsedMilliseconds) { return(false); } if (belowTempThreshold > -99) { ClimateCondition conds = entity.World.BlockAccessor.GetClimateAt(entity.Pos.AsBlockPos, EnumGetClimateMode.NowValues); lowTempMode = conds != null && conds.Temperature <= belowTempThreshold; } float range = lowTempMode ? belowTempSeekingRange : seekingRange; lastSearchTotalMs = entity.World.ElapsedMilliseconds; Vec3d ownPos = entity.ServerPos.XYZ; targetEntity = (EntityAgent)partitionUtil.GetNearestEntity(entity.ServerPos.XYZ, range, (e) => { if (!e.Alive || !e.IsInteractable || e.EntityId == this.entity.EntityId) { return(false); } for (int i = 0; i < seekEntityCodesExact.Length; i++) { if (e.Code.Path == seekEntityCodesExact[i]) { if (e.Code.Path == "player") { float rangeMul = e.Stats.GetBlended("animalSeekingRange"); IPlayer player = entity.World.PlayerByUid(((EntityPlayer)e).PlayerUID); return ((rangeMul == 1 || e.ServerPos.DistanceTo(ownPos) < range * rangeMul) && (player == null || (player.WorldData.CurrentGameMode != EnumGameMode.Creative && player.WorldData.CurrentGameMode != EnumGameMode.Spectator && (player as IServerPlayer).ConnectionState == EnumClientState.Playing)) ); } return(true); } } for (int i = 0; i < seekEntityCodesBeginsWith.Length; i++) { if (e.Code.Path.StartsWithFast(seekEntityCodesBeginsWith[i])) { return(true); } } return(false); }); if (targetEntity != null) { if (alarmHerd && entity.HerdId > 0) { entity.World.GetNearestEntity(entity.ServerPos.XYZ, range, range, (e) => { EntityAgent agent = e as EntityAgent; if (e.EntityId != entity.EntityId && agent != null && agent.Alive && agent.HerdId == entity.HerdId) { agent.Notify("seekEntity", targetEntity); } return(false); }); } targetPos = targetEntity.ServerPos.XYZ; if (entity.ServerPos.SquareDistanceTo(targetPos) <= MinDistanceToTarget()) { return(false); } return(true); } return(false); }
public override bool ShouldExecute() { if (rand.NextDouble() > 0.1f) { return(false); // was 0.04 before, but that made creatures react very slowly when in emotionstate aggressiveondamage. So lets double the reaction time when in that emotion state } if (whenInEmotionState != null && !entity.HasEmotionState(whenInEmotionState)) { return(false); } if (whenNotInEmotionState != null && entity.HasEmotionState(whenNotInEmotionState)) { return(false); } if (lastSearchTotalMs + 4000 > entity.World.ElapsedMilliseconds) { return(false); } if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } if (jumpAnimOn && entity.World.ElapsedMilliseconds - finishedMs > 2000) { entity.AnimManager.StopAnimation("jump"); } if (cooldownUntilMs > entity.World.ElapsedMilliseconds) { return(false); } lastSearchTotalMs = entity.World.ElapsedMilliseconds; targetEntity = (EntityAgent)partitionUtil.GetNearestEntity(entity.ServerPos.XYZ, seekingRange, (e) => { if (!e.Alive || !e.IsInteractable || e.EntityId == this.entity.EntityId) { return(false); } for (int i = 0; i < seekEntityCodesExact.Length; i++) { if (e.Code.Path == seekEntityCodesExact[i]) { if (e.Code.Path == "player") { IPlayer player = entity.World.PlayerByUid(((EntityPlayer)e).PlayerUID); return (player == null || (player.WorldData.CurrentGameMode != EnumGameMode.Creative && player.WorldData.CurrentGameMode != EnumGameMode.Spectator && (player as IServerPlayer).ConnectionState == EnumClientState.Playing)); } return(true); } } for (int i = 0; i < seekEntityCodesBeginsWith.Length; i++) { if (e.Code.Path.StartsWithFast(seekEntityCodesBeginsWith[i])) { return(true); } } return(false); }); if (targetEntity != null) { if (alarmHerd && entity.HerdId > 0) { entity.World.GetNearestEntity(entity.ServerPos.XYZ, seekingRange, seekingRange, (e) => { EntityAgent agent = e as EntityAgent; if (e.EntityId != entity.EntityId && agent != null && agent.Alive && agent.HerdId == entity.HerdId) { agent.Notify("seekEntity", targetEntity); } return(false); }); } targetPos = targetEntity.ServerPos.XYZ; if (entity.ServerPos.SquareDistanceTo(targetPos) <= MinDistanceToTarget()) { return(false); } return(true); } return(false); }
public override bool ShouldExecute() { if (noEntityCodes && (attackedByEntity == null || !retaliateAttacks)) { return(false); } // React immediately on hurt, otherwise only 1/10 chance of execution if (rand.NextDouble() > 0.1f && (whenInEmotionState == null || bhEmo?.IsInEmotionState(whenInEmotionState) != true) && !RecentlyAttacked) { return(false); } if (whenInEmotionState != null && bhEmo?.IsInEmotionState(whenInEmotionState) != true) { return(false); } if (whenNotInEmotionState != null && bhEmo?.IsInEmotionState(whenNotInEmotionState) == true) { return(false); } if (lastSearchTotalMs + searchWaitMs > entity.World.ElapsedMilliseconds) { return(false); } if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } if (jumpAnimOn && entity.World.ElapsedMilliseconds - finishedMs > 2000) { entity.AnimManager.StopAnimation("jump"); } if (cooldownUntilMs > entity.World.ElapsedMilliseconds && !RecentlyAttacked) { return(false); } if (belowTempThreshold > -99) { ClimateCondition conds = entity.World.BlockAccessor.GetClimateAt(entity.Pos.AsBlockPos, EnumGetClimateMode.NowValues); lowTempMode = conds != null && conds.Temperature <= belowTempThreshold; } float range = NowSeekRange; lastSearchTotalMs = entity.World.ElapsedMilliseconds; if (!RecentlyAttacked) { attackedByEntity = null; } if (retaliateAttacks && attackedByEntity != null && attackedByEntity.Alive && IsTargetableEntity(attackedByEntity, range, true)) { targetEntity = attackedByEntity; targetPos = targetEntity.ServerPos.XYZ; return(true); } else { ownPos.Set(entity.ServerPos); targetEntity = partitionUtil.GetNearestEntity(ownPos, range, (e) => IsTargetableEntity(e, range)); if (targetEntity != null) { if (alarmHerd && entity.HerdId > 0) { entity.World.GetNearestEntity(ownPos, range, range, (e) => { EntityAgent agent = e as EntityAgent; if (e.EntityId != entity.EntityId && agent != null && agent.Alive && agent.HerdId == entity.HerdId) { agent.Notify("seekEntity", targetEntity); } return(false); }); } targetPos = targetEntity.ServerPos.XYZ; if (entity.ServerPos.SquareDistanceTo(targetPos) <= MinDistanceToTarget()) { return(false); } return(true); } } return(false); }
public override bool ShouldExecute() { soundChance = Math.Min(1.01f, soundChance + 1 / 500f); if (rand.NextDouble() > 2 * executionChance) { return(false); } if (noEntityCodes && (attackedByEntity == null || !retaliateAttacks)) { return(false); } if (whenInEmotionState != null && bhEmo?.IsInEmotionState(whenInEmotionState) != true) { return(false); } if (whenNotInEmotionState != null && bhEmo?.IsInEmotionState(whenNotInEmotionState) == true) { return(false); } // Double exec chance, but therefore halved here again to increase response speed for creature when aggressive if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } // This code section controls drifter behavior - they retreat (flee slowly) from the player in the daytime, this is "switched off" below ground or at night, also switched off in temporal storms // Has to be checked every tick because the drifter attributes change during temporal storms (grrr, this is a slow way to do it) if (!entity.Attributes.GetBool("ignoreDaylightFlee", false)) { if (ignoreDeepDayLight && entity.ServerPos.Y < world.SeaLevel - 2) { return(false); } float sunlight = entity.World.BlockAccessor.GetLightLevel((int)entity.ServerPos.X, (int)entity.ServerPos.Y, (int)entity.ServerPos.Z, EnumLightLevelType.TimeOfDaySunLight) / (float)entity.World.SunBrightness; if (sunlight < minDayLight) { return(false); } } int generation = entity.WatchedAttributes.GetInt("generation", 0); float fearReductionFactor = (whenInEmotionState != null) ? 1 : Math.Max(0f, (tamingGenerations - generation) / tamingGenerations); ownPos.Set(entity.ServerPos); float hereRange = fearReductionFactor * seekingRange; targetEntity = (EntityAgent)partitionUtil.GetNearestEntity(ownPos, hereRange, (e) => { if (!IsTargetableEntity(e, hereRange)) { return(false); } if (!(e is EntityPlayer) || !lowStabilityAttracted) { return(true); } return(e.WatchedAttributes.GetDouble("temporalStability", 1) < 0.25); }); if (targetEntity != null) { updateTargetPosFleeMode(targetPos); return(true); } return(false); }
public override bool ShouldExecute() { soundChance = Math.Min(1.01f, soundChance + 1 / 500f); if (rand.NextDouble() > 2 * executionChance) { return(false); } if (whenInEmotionState != null && !entity.HasEmotionState(whenInEmotionState)) { return(false); } if (whenNotInEmotionState != null && entity.HasEmotionState(whenNotInEmotionState)) { return(false); } // Double exec chance, but therefore halved here again to increase response speed for creature when aggressive if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } float sunlight = entity.World.BlockAccessor.GetLightLevel((int)entity.ServerPos.X, (int)entity.ServerPos.Y, (int)entity.ServerPos.Z, EnumLightLevelType.TimeOfDaySunLight) / (float)entity.World.SunBrightness; if ((ignoreDeepDayLight && entity.ServerPos.Y < world.SeaLevel - 2) || sunlight < minDayLight) { if (!entity.Attributes.GetBool("ignoreDaylightFlee", false)) { return(false); } } int generation = entity.WatchedAttributes.GetInt("generation", 0); float fearReductionFactor = Math.Max(0f, (10f - generation) / 10f); if (whenInEmotionState != null) { fearReductionFactor = 1; } Vec3d ownPos = entity.ServerPos.XYZ; double hereRange = fearReductionFactor * seekingRange; targetEntity = (EntityAgent)partitionUtil.GetNearestEntity(ownPos, hereRange, (e) => { if (!e.Alive || e.EntityId == this.entity.EntityId || e is EntityItem) { return(false); } for (int i = 0; i < fleeEntityCodesExact.Length; i++) { if (e.Code.Path == fleeEntityCodesExact[i]) { if (e is EntityAgent eagent) { float rangeMul = 1f; // Sneaking reduces the detection range if (eagent.Controls.Sneak && eagent.OnGround) { rangeMul *= 0.6f; } // Trait bonus if (e.Code.Path == "player") { rangeMul *= eagent.Stats.GetBlended("animalSeekingRange"); } if (rangeMul != 1 && e.ServerPos.DistanceTo(ownPos) > hereRange * rangeMul) { return(false); } } if (e.Code.Path == "player") { IPlayer player = entity.World.PlayerByUid(((EntityPlayer)e).PlayerUID); bool ok = player == null || (player.WorldData.CurrentGameMode != EnumGameMode.Creative && player.WorldData.CurrentGameMode != EnumGameMode.Spectator); ok &= !lowStabilityAttracted || e.WatchedAttributes.GetDouble("temporalStability", 1) > 0.25; return(ok); } return(true); } } for (int i = 0; i < fleeEntityCodesBeginsWith.Length; i++) { if (e.Code.Path.StartsWithFast(fleeEntityCodesBeginsWith[i])) { return(true); } } return(false); }); //yawOffset = 0; if (targetEntity != null) { updateTargetPos(); return(true); } return(false); }
public override bool ShouldExecute() { soundChance = Math.Min(1.01f, soundChance + 1 / 500f); if (rand.NextDouble() > 2 * executionChance) { return(false); } if (entity.World.Calendar.DayLightStrength < minDayLight) { return(false); } if (whenInEmotionState != null && !entity.HasEmotionState(whenInEmotionState)) { return(false); } if (whenNotInEmotionState != null && entity.HasEmotionState(whenNotInEmotionState)) { return(false); } // Double exec chance, but therefore halved here again to increase response speed for creature when aggressive if (whenInEmotionState == null && rand.NextDouble() > 0.5f) { return(false); } int generation = entity.WatchedAttributes.GetInt("generation", 0); float fearReductionFactor = Math.Max(0f, (10f - generation) / 10f); if (whenInEmotionState != null) { fearReductionFactor = 1; } targetEntity = (EntityAgent)partitionUtil.GetNearestEntity(entity.ServerPos.XYZ, fearReductionFactor * seekingRange, (e) => { if (!e.Alive || e.EntityId == this.entity.EntityId || e is EntityItem) { return(false); } for (int i = 0; i < fleeEntityCodesExact.Length; i++) { if (e.Code.Path == fleeEntityCodesExact[i]) { if (e.Code.Path == "player") { IPlayer player = entity.World.PlayerByUid(((EntityPlayer)e).PlayerUID); bool ok = player == null || (player.WorldData.CurrentGameMode != EnumGameMode.Creative && player.WorldData.CurrentGameMode != EnumGameMode.Spectator); ok &= !lowStabilityAttracted || e.WatchedAttributes.GetDouble("temporalStability", 1) > 0.25; return(ok); } return(true); } } for (int i = 0; i < fleeEntityCodesBeginsWith.Length; i++) { if (e.Code.Path.StartsWithFast(fleeEntityCodesBeginsWith[i])) { return(true); } } return(false); }); //yawOffset = 0; if (targetEntity != null) { updateTargetPos(); return(true); } return(false); }