protected void EnemiesListenAction() { if (Npc.Target != null || Npc.LifeStats.IsDead()) { PlayerInFocus = null; return; } const int agroDistance = 300; if (PlayerInFocus != null) { if (PlayerInFocus.Position.DistanceTo(Npc.Position) > agroDistance || PlayerInFocus.LifeStats.IsDead()) { PlayerInFocus = null; Global.VisibleService.Send(Npc, new SpNpcStatus(Npc, 5, 0)); } } if (PlayerInFocus != null) { long now = RandomUtilities.GetCurrentMilliseconds(); if (NextChangeDirectionUts < now) { short heading = Geom.GetHeading(Npc.Position, PlayerInFocus.Position); short turnTime = (short)(2 * System.Math.Abs(Npc.Position.Heading - heading) / System.Math.Max(45, System.Math.Max(Npc.NpcTemplate.Shape.TurnSpeed, Npc.NpcTemplate.Shape.WalkSpeed))); if (turnTime > 200 && !MoveController.IsActive) { Global.VisibleService.Send(Npc, new SpDirectionChange(Creature, heading, turnTime)); Npc.Position.Heading = heading; NextChangeDirectionUts = now + turnTime; } else { NextChangeDirectionUts = now + 500; } } return; } Npc.VisiblePlayers.Each( player => { if (PlayerInFocus != null || player.LifeStats.IsDead() || player.Position.DistanceTo(Npc.Position) > agroDistance) { return; } OnCreatureApproached(player); }); }
public void Action(long elapsed) { try { if (IsMove) { Creature.Position.X += MoveVector.X; Creature.Position.Y += MoveVector.Y; IsMove = false; } if (!IsActive) { return; } if (TargetDistance != 0) { double d = TargetPosition.DistanceTo2D(Creature.Position) - 10; double a = Geom.GetHeading(Creature.Position, Creature.Target.Position) * Math.PI / 32768; TargetPosition.X = Creature.Position.X + (float)(Math.Cos(a) * d); TargetPosition.Y = Creature.Position.Y + (float)(Math.Sin(a) * d); TargetDistance = 0; } double distance = TargetPosition.DistanceTo2D(Creature.Position); if (distance < 10) { TargetPosition.CopyTo(Creature.Position); IsActive = false; return; } int speed = GetSpeed(); if (IsNewDirection) { IsNewDirection = false; Global.Global.VisibleService.Send(Creature, new SpNpcMove(Creature, TargetPosition.X, TargetPosition.Y, TargetPosition.Z, (Creature.Target != null) ? 2 : 1)); } double angle = Geom.GetHeading(Creature.Position) * Math.PI / 32768; MoveVector.X = (float)(Math.Cos(angle)); MoveVector.Y = (float)(Math.Sin(angle)); IsMove = true; } catch (Exception e) { Log.ErrorException("NpcMoveController.Action():", e); } }
public static float CheckIntersections(Creature creature, short heading, Point3D moveVector, float distance) { if (distance <= 0f) { return(0f); } WorldPosition targetPosition = moveVector.Clone().Add(creature.Position).ToWorldPosition(); double minDistance = distance; List <Creature> around = Global.VisibleService.FindTargets(creature, creature.Position, distance + 40, TargetingAreaType.All); for (int x = 0; x < around.Count; x++) { if (around[x] == creature) { continue; } short diff = Geom.GetAngleDiff(heading, Geom.GetHeading(creature.Position, around[x].Position)); if (diff > 90) { continue; } double d = Geom.DistanceToLine(around[x].Position, creature.Position, targetPosition); if (d > 40) { continue; } d = creature.Position.DistanceTo(around[x].Position) - 40; if (d <= 0) { return(0f); } if (d < minDistance) { minDistance = d; } } return((float)(minDistance / distance)); }
public void UseSkill(Npc npc, Skill skill) { if (npc.Target == null) { return; } npc.Position.Heading = Geom.GetHeading(npc.Position, npc.Target.Position); ProcessSkill(npc, new UseSkillArgs { IsTargetAttack = false, SkillId = skill.Id + 0x40000000 + (npc.NpcTemplate.HuntingZoneId << 16), StartPosition = npc.Position.Clone(), }, skill); }
public static void DebugLine(Creature creature, Point3D start, Point3D end) { const int iterations = 3; Point3D vector = Geom.GetNormal(Geom.GetHeading(start, end)) .Multiple((float)(start.DistanceTo(end) / (iterations - 1))); for (int i = 0; i < iterations; i++) { DropItem(creature, 20000001, 0, start.ToWorldPosition(), true); start.Add(vector); } Player player = creature as Player; if (player != null) { player.Visible.Update(); } }
private async void ProcessArea(Creature creature, Skill skill, Targeting targeting, TargetingArea area, Projectile projectile = null) { try { bool isProjectileSkill = skill.Type == SkillType.Projectile || skill.Type == SkillType.Userslug; int skillId = creature.Attack.Args.SkillId; if (isProjectileSkill) { skillId += 20; } if (targeting.Time > 0) { await Task.Delay((int)(targeting.Time / skill.TimeRate)); } int elapsed = targeting.Time; Player player = creature as Player; do { try { if (creature.LifeStats.IsDead()) { return; } if (area.DropItem != null) { creature.Instance.AddDrop(new Item { Owner = player, ItemId = (int)area.DropItem, Count = 1, Position = Geom.ForwardPosition(creature.Position, 40), Instance = player.Instance, }); } Point3D center = projectile != null ? projectile.Position.ToPoint3D() : Geom.GetNormal(creature.Position.Heading) .Multiple(area.OffsetDistance) .Add(creature.Position); int count = 0; List <Creature> targets = creature.Attack.Args.Targets.Count > 0 ? creature.Attack.Args.Targets : VisibleService.FindTargets(creature, center, projectile != null ? projectile.AttackDistance : area.MaxRadius, area.Type); foreach (Creature target in targets) { if (target != creature && //Ignore checks for self-target !isProjectileSkill && !creature.Attack.Args.IsItemSkill) { if (center.DistanceTo(target.Position) < area.MinRadius - 40) { continue; } if (center.DistanceTo(target.Position) > area.MaxRadius) { continue; } short diff = Geom.GetAngleDiff(creature.Attack.Args.StartPosition.Heading, Geom.GetHeading(center, target.Position)); //diff from 0 to 180 //area.RangeAngel from 0 to 360 if (diff * 2 > (creature.Attack.Args.IsTargetAttack ? 90 : Math.Abs(area.RangeAngle) + 10)) { continue; } } if (skill.TotalAtk > 0) { int damage = SeUtils.CalculateDamage(creature, target, skill.TotalAtk * area.Effect.Atk); AttackResult result = new AttackResult { AttackType = AttackType.Normal, AttackUid = creature.Attack.UID, Damage = damage, Target = target, }; result.AngleDif = Geom.GetAngleDiff(creature.Attack.Args.StartPosition.Heading, result.Target.Position.Heading); SeUtils.UpdateAttackResult(creature, result); if (result.AttackType == AttackType.Block) { VisibleService.Send(target, new SpAttackShowBlock(target, skillId)); } VisibleService.Send(target, new SpAttackResult(creature, skillId, result)); AiLogic.OnAttack(creature, target); AiLogic.OnAttacked(target, creature, result.Damage); if (target is Player && ((Player)target).Duel != null && player != null && ((Player)target).Duel.Equals(player.Duel) && target.LifeStats.GetHpDiffResult(damage) < 1) { DuelService.FinishDuel(player); } else { CreatureLogic.HpChanged(target, target.LifeStats.MinusHp(result.Damage)); } } if (area.Effect.HpDiff > 0) { AttackResult result = new AttackResult { HpDiff = area.Effect.HpDiff, Target = target }; PassivityProcessor.OnHeal(player, result); if (target is Player) { PassivityProcessor.OnHealed((Player)target, result); } CreatureLogic.HpChanged(target, target.LifeStats.PlusHp(result.HpDiff), creature); } if (area.Effect.MpDiff > 0) { CreatureLogic.MpChanged(target, target.LifeStats.PlusMp(area.Effect.MpDiff), creature); } if (area.Effect.AbnormalityOnCommon != null) { for (int i = 0; i < area.Effect.AbnormalityOnCommon.Count; i++) { AbnormalityProcessor.AddAbnormality(target, area.Effect.AbnormalityOnCommon[i], creature); } } if (player != null) { DuelService.ProcessDamage(player); //MP regen on combo skill if (skill.Id / 10000 == 1 && player.GameStats.CombatMpRegen > 0) { CreatureLogic.MpChanged(player, player.LifeStats.PlusMp( player.MaxMp * player.GameStats.CombatMpRegen / 200)); } } if (++count == area.MaxCount) { break; } } } catch (Exception ex) { Logger.WriteLine(LogState.Exception, "SkillEngine: ProcessAreaExc: " + ex); } if (targeting.Interval > 0) { await Task.Delay((int)(targeting.Interval / skill.TimeRate)); elapsed += targeting.Interval; } } while (targeting.Interval > 0 && elapsed < targeting.Until); } catch (Exception ex) { Logger.WriteLine(LogState.Exception, "SkillEngine: ProcessArea: " + ex); } }
public void Action(long elapsed) { if (IsMove) { MoveVector.Multiple(elapsed / 1000f); Creature.Position.X += MoveVector.X; Creature.Position.Y += MoveVector.Y; if (Projectile != null) { Creature.Position.Z += MoveVector.Z; } //Global.GeoService.FixZ(Npc.Position); IsMove = false; } if (!IsActive) { return; } Creature.Position.Heading = Geom.GetHeading(Creature.Position, TargetPosition); if (TargetDistance != 0) { double d = TargetPosition.DistanceTo2D(Creature.Position); double a = Creature.Position.Heading * Math.PI / 32768; TargetPosition.X = Creature.Position.X + (float)(d * Math.Cos(a)); TargetPosition.Y = Creature.Position.Y + (float)(d * Math.Sin(a)); TargetDistance = 0; } double distance = TargetPosition.DistanceTo2D(Creature.Position); if (distance < 10) { TargetPosition.CopyTo(Creature.Position); IsActive = false; return; } int speed = GetSpeed(); if (Projectile == null && IsNewDirection) { IsNewDirection = false; Global.VisibleService.Send(Creature, new SpNpcMove(Creature, (short)speed, TargetPosition.X, TargetPosition.Y, TargetPosition.Z)); } double angle = Creature.Position.Heading * Math.PI / 32768; MoveVector.X = speed * (float)Math.Cos(angle); MoveVector.Y = speed * (float)Math.Sin(angle); if (Projectile != null) { MoveVector.Z = speed * (TargetPosition.Z - Creature.Position.Z) / (float)distance; } IsMove = true; }
public short GetHeadingToTarget(WorldPosition worldPosition) { return(Geom.GetHeading(((float)((worldPosition.X - X) / DistanceTo(worldPosition)) * 45), ((float)((worldPosition.Y - Y) / DistanceTo(worldPosition)) * 45))); }