public override void OnPlayerApproaching(Players.Player player) { if (player.Position.DistanceSquared(ref _position) < ActorData.Sphere.Radius * ActorData.Sphere.Radius * this.Scale * this.Scale && !_collapsed) { _collapsed = true; // TODO most of the fields here are unknown, find out about animation playing duration int duration = 500; // ticks World.BroadcastIfRevealed(new PlayAnimationMessage { ActorID = this.DynamicID, Field1 = 11, Field2 = 0, tAnim = new Net.GS.Message.Fields.PlayAnimationMessageSpec[] { new Net.GS.Message.Fields.PlayAnimationMessageSpec() { Duration = duration, AnimationSNO = ActorData.TagMap.ContainsKey(ActorKeys.DeathAnimationTag) ? AnimationSet.TagMapAnimDefault[ActorData.TagMap[ActorKeys.DeathAnimationTag]].Int : AnimationSet.TagMapAnimDefault[AnimationSetKeys.DeathDefault] , PermutationIndex = 0, Speed = 1 } } }, this); World.BroadcastIfRevealed(new SetIdleAnimationMessage { ActorID = this.DynamicID, AnimationSNO = AnimationSetKeys.DeadDefault.ID }, this); this.Attributes[GameAttribute.Deleted_On_Server] = true; Attributes.BroadcastChangedIfRevealed(); RelativeTickTimer destroy = new RelativeTickTimer(World.Game, duration, x => this.Destroy()); } }
public override IEnumerable<TickTimer> Run() { //UsePrimaryResource(15f); // dashing strike never specifies the target's id so we just search for the closest target // ultimately need to know the radius of each target and select the one most covered float min_distance = float.MaxValue; foreach (Actor actor in GetEnemiesInRadius(TargetPosition, 8f)) { float distance = PowerMath.Distance(actor.Position, TargetPosition); if (distance < min_distance) { min_distance = distance; Target = actor; } } if (Target != null) { // put dash destination just beyond target TargetPosition = PowerMath.ProjectAndTranslate2D(User.Position, Target.Position, Target.Position, 7f); } else { // if no target, always dash fixed amount TargetPosition = PowerMath.ProjectAndTranslate2D(User.Position, TargetPosition, User.Position, 13f); } // dash speed seems to always be actor speed * 10 float speed = User.Attributes[GameAttribute.Running_Rate_Total] * 10f; TickTimer minDashWait = WaitSeconds(0.15f); TickTimer waitDashEnd = new RelativeTickTimer(World.Game, (int)(PowerMath.Distance2D(User.Position, TargetPosition) / speed)); // if dash ticks is too small the effect won't show at all, so always make it at least minDashWait waitDashEnd = minDashWait.TimeoutTick > waitDashEnd.TimeoutTick ? minDashWait : waitDashEnd; // dashing effect buff AddBuff(User, new DashingBuff0(waitDashEnd)); // TODO: Generalize this and put it in Actor User.World.BroadcastInclusive(new NotifyActorMovementMessage { ActorId = (int)User.DynamicID, Position = TargetPosition, Angle = PowerMath.AngleLookAt(User.Position, TargetPosition), Field3 = true, // turn instantly toward target Speed = speed, Field5 = 0x9206, // alt: 0x920e, not sure what this param is for. AnimationTag = 69808, // dashing strike attack animation Field7 = 6, // ticks to wait before playing animation }, User); User.Position = TargetPosition; yield return waitDashEnd; if (Target != null && Target.World != null) // target could've died or left world { User.TranslateFacing(Target.Position, true); yield return WaitSeconds(0.1f); User.PlayEffectGroup(113720); WeaponDamage(Target, 1.60f, DamageType.Physical); } }