using System.Collections.Generic; public class EntityEnemyRebirthSDX : EntityEnemy { public override string EntityName { get { string name = Localization.Get(this.entityName); if (this.EntityTags.Test_AnySet(FastTags.Parse("invisible"))) { name = ""; } return name; } } public override void Awake() { base.Awake(); } public override void InitCommon() { base.InitCommon(); if (this.walkType == 4) { this.TurnIntoCrawler(); } } public override void OnAddedToWorld() { base.OnAddedToWorld(); this.timeToDie = this.world.worldTime + 1800UL + (ulong)(22000f * this.rand.RandomFloat); if (this.IsFeral && base.GetSpawnerSource() == EnumSpawnerSource.Biome) { int num = (int)SkyManager.GetDawnTime(); int num2 = (int)SkyManager.GetDuskTime(); int num3 = GameUtils.WorldTimeToHours(this.WorldTimeBorn); if (num3 < num || num3 >= num2) { int num4 = GameUtils.WorldTimeToDays(this.world.worldTime); if (GameUtils.WorldTimeToHours(this.world.worldTime) >= num2) { num4++; } this.timeToDie = GameUtils.DayTimeToWorldTime(num4, num, 0); } } } private int attackTargetTime; private bool bJumping; private bool bClimbing; private bool hasAI; private bool isMoveDirAbsolute; private float proneRefillRate; private float kneelRefillRate; private float proneRefillCounter; private float kneelRefillCounter; private int ticksToCheckSeenByPlayer; private bool wasSeenByPlayer; private bool disableFallBehaviorUntilOnGround; private DynamicRagdollFlags _dynamicRagdoll; private Vector3 _dynamicRagdollRootMotion; private readonly List _ragdollPositionsPrev = new List(); private readonly List _ragdollPositionsCur = new List(); private void UpdateDynamicRagdoll() { if (this._dynamicRagdoll.HasFlag(DynamicRagdollFlags.Active)) { if (this.accumulatedRootMotion != Vector3.zero) { this._dynamicRagdollRootMotion = this.accumulatedRootMotion; } if (this._dynamicRagdoll.HasFlag(DynamicRagdollFlags.UseBoneVelocities)) { this._ragdollPositionsPrev.Clear(); this._ragdollPositionsCur.CopyTo(this._ragdollPositionsPrev); this.emodel.CaptureRagdollPositions(this._ragdollPositionsCur); } if (this._dynamicRagdoll.HasFlag(DynamicRagdollFlags.RagdollOnFall) && !this.onGround) { this.ActivateDynamicRagdoll(); return; } } } public override void OnUpdateLive() { try { base.OnUpdateLive(); } catch (Exception ex) { Log.Out("EntityEnemyRebirthSDX-OnUpdateLive ERROR: " + ex.Message); } if (this.moveSpeedRagePer > 0f && this.bodyDamage.CurrentStun == EnumEntityStunType.None) { this.moveSpeedScaleTime -= 0.05f; if (this.moveSpeedScaleTime <= 0f) { this.StopRage(); } } ///////////////////////////////////////////////////////// if (emodel != null && emodel.avatarController != null) { emodel.avatarController.UpdateBool("CanFall", !emodel.IsRagdollActive && bodyDamage.CurrentStun == EnumEntityStunType.None && !isSwimming); emodel.avatarController.UpdateBool("IsOnGround", onGround || isSwimming); } ///////////////////////////////////////////////////////// if (!this.isEntityRemote) { if (!this.IsDead() && this.world.worldTime >= this.timeToDie && !this.attackTarget) { this.Kill(DamageResponse.New(true)); } if (this.emodel) { AvatarController avatarController = this.emodel.avatarController; if (avatarController) { bool flag = this.onGround || this.isSwimming || this.bInElevator; if (flag) { this.fallTime = 0f; this.fallThresholdTime = 0f; if (this.bInElevator) { this.fallThresholdTime = 0.6f; } } else { if (this.fallThresholdTime == 0f) { this.fallThresholdTime = 0.1f + this.rand.RandomFloat * 0.3f; } this.fallTime += 0.05f; } bool canFall = !this.emodel.IsRagdollActive && this.bodyDamage.CurrentStun == EnumEntityStunType.None && !this.isSwimming && !this.bInElevator && this.jumpState == EntityAlive.JumpState.Off && !this.IsDead(); if (this.fallTime <= this.fallThresholdTime) { canFall = false; } avatarController.SetFallAndGround(canFall, flag); } } } } public override Ray GetLookRay() { Ray result; if (base.IsBreakingBlocks) { result = new Ray(this.position + new Vector3(0f, this.GetEyeHeight(), 0f), this.GetLookVector()); } else if (base.GetWalkType() == 8) { result = new Ray(this.getHeadPosition(), this.GetLookVector()); } else { result = new Ray(this.getHeadPosition(), this.GetLookVector()); } return result; } public override Vector3 GetLookVector() { if (this.lookAtPosition.Equals(Vector3.zero)) { return base.GetLookVector(); } return this.lookAtPosition - this.getHeadPosition(); } public override bool IsRunning { get { EnumGamePrefs eProperty = EnumGamePrefs.ZombieMove; if (this.IsBloodMoon) { eProperty = EnumGamePrefs.ZombieBMMove; } else if (this.IsFeral) { eProperty = EnumGamePrefs.ZombieFeralMove; } else if (this.world.IsDark()) { eProperty = EnumGamePrefs.ZombieMoveNight; } return GamePrefs.GetInt(eProperty) >= 2; } } public override float GetMoveSpeedAggro() { EnumGamePrefs eProperty = EnumGamePrefs.ZombieMove; if (this.IsBloodMoon) { eProperty = EnumGamePrefs.ZombieBMMove; } else if (this.IsFeral) { eProperty = EnumGamePrefs.ZombieFeralMove; } else if (this.world.IsDark()) { eProperty = EnumGamePrefs.ZombieMoveNight; } int @int = GamePrefs.GetInt(eProperty); float num = EntityEnemyRebirthSDX.moveSpeeds[@int]; if (this.moveSpeedRagePer > 1f) { num = EntityEnemyRebirthSDX.moveSuperRageSpeeds[@int]; } else if (this.moveSpeedRagePer > 0f) { float num2 = EntityEnemyRebirthSDX.moveRageSpeeds[@int]; num = num * (1f - this.moveSpeedRagePer) + num2 * this.moveSpeedRagePer; } if (num < 1f) { num = this.moveSpeedAggro * (1f - num) + this.moveSpeedAggroMax * num; } else { num = this.moveSpeedAggroMax * num; } return EffectManager.GetValue(PassiveEffects.RunSpeed, null, num, this, null, new FastTags(), true, true, true, true, true, 1); } public override float getNextStepSoundDistance() { if (!this.IsRunning) { return 0.5f; } return 1.5f; } public override void MoveEntityHeaded(Vector3 _direction, bool _isDirAbsolute) { // Check the state to see if the controller IsBusy or not. If it's not, then let it walk. var isBusy = false; if (emodel != null && emodel.avatarController != null) emodel.avatarController.TryGetBool("IsBusy", out isBusy); if (isBusy) return; if (this.walkType == 4 && this.Jumping) { this.motion = this.accumulatedRootMotion; this.accumulatedRootMotion = Vector3.zero; this.IsRotateToGroundFlat = true; if (this.moveHelper != null) { Vector3 vector = this.moveHelper.JumpToPos - this.position; if (Utils.FastAbs(vector.y) < 0.2f) { this.motion.y = vector.y * 0.2f; } if (Utils.FastAbs(vector.x) < 0.3f) { this.motion.x = vector.x * 0.2f; } if (Utils.FastAbs(vector.z) < 0.3f) { this.motion.z = vector.z * 0.2f; } if (vector.sqrMagnitude < 0.010000001f) { if (this.emodel && this.emodel.avatarController) { this.emodel.avatarController.StartAnimationJump(AnimJumpMode.Land); } this.Jumping = false; } } this.entityCollision(this.motion); return; } base.MoveEntityHeaded(_direction, _isDirAbsolute); } public override void UpdateJump() { if (this.walkType == 4 && !this.isSwimming) { base.FaceJumpTo(); this.jumpState = EntityAlive.JumpState.Climb; if (!this.emodel.avatarController || !this.emodel.avatarController.IsAnimationJumpRunning()) { this.Jumping = false; } if (this.jumpTicks == 0 && this.accumulatedRootMotion.y > 0.005f) { this.jumpTicks = 30; } return; } base.UpdateJump(); if (this.isSwimming) { return; } this.accumulatedRootMotion.y = 0f; } public override void EndJump() { base.EndJump(); this.IsRotateToGroundFlat = false; } public override bool ExecuteFallBehavior(EntityAlive.FallBehavior behavior, float _distance, Vector3 _fallMotion) { if (behavior == null || !this.emodel) { return false; } AvatarController avatarController = this.emodel.avatarController; if (!avatarController) { return false; } avatarController.UpdateInt("RandomSelector", this.rand.RandomRange(0, 64)); switch (behavior.ResponseOp) { case EntityAlive.FallBehavior.Op.None: avatarController.UpdateInt(AvatarController.jumpLandResponseHash, -1); break; case EntityAlive.FallBehavior.Op.Land: avatarController.UpdateInt(AvatarController.jumpLandResponseHash, 0); break; case EntityAlive.FallBehavior.Op.LandLow: avatarController.UpdateInt(AvatarController.jumpLandResponseHash, 1); break; case EntityAlive.FallBehavior.Op.LandHard: avatarController.UpdateInt(AvatarController.jumpLandResponseHash, 2); break; case EntityAlive.FallBehavior.Op.Stumble: avatarController.UpdateInt(AvatarController.jumpLandResponseHash, 3); break; case EntityAlive.FallBehavior.Op.Ragdoll: this.emodel.DoRagdoll(this.rand.RandomFloat * 2f, EnumBodyPartHit.None, _fallMotion * 20f, Vector3.zero, false); break; } if (this.attackTarget != null && behavior.RagePer.IsSet() && behavior.RageTime.IsSet() && this.StartRage(behavior.RagePer.Random(this.rand), behavior.RageTime.Random(this.rand))) { avatarController.StartAnimationRaging(); } return true; } public override bool ExecuteDestroyBlockBehavior(EntityAlive.DestroyBlockBehavior behavior, ItemActionAttack.AttackHitInfo attackHitInfo) { if (behavior == null || attackHitInfo == null || this.moveHelper == null || this.emodel == null || this.emodel.avatarController == null) { return false; } if (this.walkType == 4) { return false; } this.moveHelper.ClearBlocked(); this.moveHelper.ClearTempMove(); this.emodel.avatarController.UpdateInt("RandomSelector", this.rand.RandomRange(0, 64)); switch (behavior.ResponseOp) { case EntityAlive.DestroyBlockBehavior.Op.Ragdoll: this.emodel.avatarController.BeginStun(EnumEntityStunType.StumbleBreakThroughRagdoll, EnumBodyPartHit.LeftLowerLeg, Utils.EnumHitDirection.None, false, 1f); base.SetStun(EnumEntityStunType.StumbleBreakThroughRagdoll); break; case EntityAlive.DestroyBlockBehavior.Op.Stumble: this.emodel.avatarController.BeginStun(EnumEntityStunType.StumbleBreakThrough, EnumBodyPartHit.LeftLowerLeg, Utils.EnumHitDirection.None, false, 1f); base.SetStun(EnumEntityStunType.StumbleBreakThrough); this.bodyDamage.StunDuration = 1f; break; } if (this.attackTarget != null && behavior.RagePer.IsSet() && behavior.RageTime.IsSet()) { this.StartRage(behavior.RagePer.Random(this.rand), behavior.RageTime.Random(this.rand)); } return true; } public override int DamageEntity(DamageSource _damageSource, int _strength, bool _criticalHit, float impulseScale) { if (_damageSource.GetDamageType() == EnumDamageTypes.Falling) { _strength = (_strength + 1) / 2; int num = (this.GetMaxHealth() + 2) / 3; if (_strength > num) { _strength = num; } } //return base.DamageEntity(_damageSource, _strength, _criticalHit, impulseScale); EnumDamageSource source = _damageSource.GetSource(); if (_damageSource.IsIgnoreConsecutiveDamages() && source != EnumDamageSource.Internal) { if (this.damageSourceTimeouts.ContainsKey(source) && GameTimer.Instance.ticks - this.damageSourceTimeouts[source] < 30UL) { return 0; } this.damageSourceTimeouts[source] = GameTimer.Instance.ticks; } EntityAlive entityAlive = this.world.GetEntity(_damageSource.getEntityId()) as EntityAlive; if (!this.FriendlyFireCheck(entityAlive)) { return 0; } bool flag = _damageSource.GetDamageType() == EnumDamageTypes.Heat; /*if (!flag && entityAlive is EntityZombie && this is EntityZombie) { return 0; }*/ if (this.IsGodMode.Value) { return 0; } if (!this.IsDead() && entityAlive) { float value = EffectManager.GetValue(PassiveEffects.DamageBonus, null, 0f, entityAlive, null, new FastTags(), true, true, true, true, true, 1); if (value > 0f) { _damageSource.DamageMultiplier = value; _damageSource.BonusDamageType = EnumDamageBonusType.Sneak; } } DamageResponse damageResponse = this.damageEntityLocal(_damageSource, _strength, _criticalHit, impulseScale); NetPackage package = NetPackageManager.GetPackage().Setup(this.entityId, damageResponse); if (this.world.IsRemote()) { SingletonMonoBehaviour.Instance.SendToServer(package, false); } else { int excludePlayer = -1; if (!flag && _damageSource.CreatorEntityId != -2) { excludePlayer = _damageSource.getEntityId(); if (_damageSource.CreatorEntityId != -1) { Entity entity = this.world.GetEntity(_damageSource.CreatorEntityId); if (entity && !entity.isEntityRemote) { excludePlayer = -1; } } } this.world.entityDistributer.SendPacketToTrackedPlayersAndTrackedEntity(this.entityId, excludePlayer, package); } return damageResponse.ModStrength; } public bool StartRage(float speedPercent, float time) { if (speedPercent >= this.moveSpeedRagePer) { this.moveSpeedRagePer = speedPercent; this.moveSpeedScaleTime = time; return true; } return false; } public void StopRage() { this.moveSpeedRagePer = 0f; this.moveSpeedScaleTime = 0f; } public override Vector3i dropCorpseBlock() { if (this.lootContainer != null && this.lootContainer.IsUserAccessing()) { return Vector3i.zero; } Vector3i vector3i = base.dropCorpseBlock(); if (vector3i == Vector3i.zero) { return Vector3i.zero; } TileEntityLootContainer tileEntityLootContainer = this.world.GetTileEntity(0, vector3i) as TileEntityLootContainer; if (tileEntityLootContainer == null) { return Vector3i.zero; } if (this.lootContainer != null) { tileEntityLootContainer.CopyLootContainerDataFromOther(this.lootContainer); } else { tileEntityLootContainer.lootListName = this.lootListOnDeath; tileEntityLootContainer.SetContainerSize(LootContainer.GetLootContainer(this.lootListOnDeath, true).size, true); } tileEntityLootContainer.SetModified(); return vector3i; } public override void AnalyticsSendDeath(DamageResponse _dmResponse) { DamageSource source = _dmResponse.Source; if (source == null) { return; } string name; if (source.BuffClass != null) { name = source.BuffClass.Name; } else { if (source.ItemClass == null) { return; } name = source.ItemClass.Name; } GameSparksCollector.IncrementCounter(GameSparksCollector.GSDataKey.ZombiesKilledBy, name, 1, true, GameSparksCollector.GSDataCollection.SessionUpdates); } public override void TurnIntoCrawler() { BoxCollider component = base.gameObject.GetComponent(); if (component) { component.center = new Vector3(0f, 0.35f, 0f); component.size = new Vector3(0.8f, 0.8f, 0.8f); } base.SetupBounds(); this.boundingBox.center = this.boundingBox.center + this.position; this.bCanClimbLadders = false; } public override void BuffAdded(BuffValue _buff) { if (_buff.BuffClass.DamageType == EnumDamageTypes.Electrical) { this.Electrocuted = true; } } public ulong timeToDie; private float moveSpeedRagePer; private float moveSpeedScaleTime; private float fallTime; private float fallThresholdTime; private static float[] moveSpeeds = new float[] { 0f, 0.35f, 0.7f, 1f, 1.35f }; private static float[] moveRageSpeeds = new float[] { 0.75f, 0.8f, 0.9f, 1.15f, 1.7f }; private static float[] moveSuperRageSpeeds = new float[] { 0.88f, 0.92f, 1f, 1.2f, 1.7f }; private static float[] rageChances = new float[] { 0f, 0.15f, 0.3f, 0.35f, 0.4f, 0.5f }; private static float[] superRageChances = new float[] { 0f, 0.01f, 0.03f, 0.05f, 0.08f, 0.15f }; private Vector3i blockPosStandingOn; private float nextSwimDistance; private float nextStepDistance; private string soundFootstepModifier; private int ticksUntilVisible = 2; }