public void Reset() { Entity = EcsEntity.Null; Target = EcsEntity.Null; Character = null; CombatEntity = null; Connection = null; CurrentCooldown = 0f; HeadId = 0; HeadFacing = HeadFacing.Center; IsMale = true; QueueAttack = false; }
public void Reset() { Entity = EcsEntity.Null; Character = null; aiEntries = null; SpawnEntry = null; CombatEntity = null; searchTarget = null; aiTickRate = 0.1f; nextAiUpdate = Time.ElapsedTimeFloat + GameRandom.NextFloat(0, aiTickRate); target = EcsEntity.Null; }
private bool OutPerformAttack() { var targetEntity = targetCharacter.Entity.Get <CombatEntity>(); if (!targetEntity.IsValidTarget(CombatEntity)) { return(false); } CombatEntity.PerformMeleeAttack(targetEntity); nextAiUpdate += MonsterBase.AttackTime; return(true); }
public void Initialize(ref EcsEntity e, Character character, CombatEntity combat, MonsterDatabaseInfo monData, MonsterAiType type, MapSpawnEntry spawnEntry, string mapName) { Entity = e; Character = character; this.SpawnEntry = spawnEntry; CombatEntity = combat; MonsterBase = monData; aiType = type; SpawnMap = mapName; aiEntries = DataManager.GetAiStateMachine(aiType); nextAiUpdate = Time.ElapsedTimeFloat + 1f; if (Character.ClassId >= 4000 && SpawnEntry == null) { throw new Exception("Monster created without spawn entry"); //remove when arbitrary monster spawning is added } UpdateStats(); currentState = MonsterAiState.StateIdle; }
public bool IsValidTarget(CombatEntity source) { if (this == source) { return(false); } if (Entity.IsNull() || !Entity.IsAlive()) { return(false); } if (!Character.IsActive || Character.State == CharacterState.Dead) { return(false); } if (Character.Map == null) { return(false); } if (source.Character.Map != Character.Map) { return(false); } if (Character.SpawnImmunity > 0f) { return(false); } if (source.Character.ClassId == Character.ClassId) { return(false); } if (Character.ClassId == 1000) { return(false); //hack } return(true); }
public void PerformMeleeAttack(CombatEntity target) { #if DEBUG if (!target.IsValidTarget(this)) { throw new Exception("Entity attempting to attack an invalid target! This should be checked before calling PerformMeleeAttack."); } #endif if (Character.AttackCooldown + Time.DeltaTimeFloat + 0.005f < Time.ElapsedTimeFloat) { Character.AttackCooldown = Time.ElapsedTimeFloat + Stats.AttackMotionTime; //they are consecutively attacking } else { Character.AttackCooldown += Stats.AttackMotionTime; } Character.FacingDirection = DistanceCache.Direction(Character.Position, target.Character.Position); var atk1 = Stats.Atk; var atk2 = Stats.Atk2; if (atk1 <= 0) { atk1 = 1; } if (atk2 < atk1) { atk2 = atk1; } var damage = (short)GameRandom.Next(Stats.Atk, Stats.Atk2); var di = new DamageInfo() { Damage = damage, HitCount = 1, KnockBack = 0, Source = Entity, Target = target.Entity, Time = Time.ElapsedTimeFloat + Stats.SpriteAttackTiming }; //ServerLogger.Log($"{aiCooldown} {character.AttackCooldown} {angle} {dir}"); Character.Map.GatherPlayersForMultiCast(ref Entity, Character); CommandBuilder.AttackMulti(Character, target.Character, di); CommandBuilder.ClearRecipients(); target.QueueDamage(di); if (target.Character.Type == CharacterType.Monster && di.Damage > target.Stats.Hp) { var mon = target.Entity.Get <Monster>(); mon.AddDelay(Stats.SpriteAttackTiming); //make sure it stops acting until it dies } if (Character.Type == CharacterType.Player && di.Damage > target.Stats.Hp) { var player = Entity.Get <Player>(); player.ClearTarget(); } }