public override IEnumerable<TickTimer> Main() { //StartCooldown(WaitSeconds(10f)); ActorMover mover = new ActorMover(User); mover.MoveArc(TargetPosition, 10, -0.1f, new ACDTranslateArcMessage { //Field3 = 303110, // used for male barb leap, not needed? FlyingAnimationTagID = AnimationSetKeys.Attack2.ID, LandingAnimationTagID = -1, Field7 = PowerSNO }); // wait for landing while (!mover.Update()) yield return WaitTicks(1); // extra wait for leap to finish yield return WaitTicks(1); // ground smash effect User.PlayEffectGroup(162811); bool hitAnything = false; AttackPayload attack = new AttackPayload(this); attack.Targets = GetEnemiesInRadius(TargetPosition, 8f); attack.AddWeaponDamage(0.70f, DamageType.Physical); attack.OnHit = hitPayload => { hitAnything = true; }; attack.Apply(); if (hitAnything) GeneratePrimaryResource(15f); yield break; }
public override IEnumerable <TickTimer> Main() { //StartCooldown(WaitSeconds(10f)); ActorMover mover = new ActorMover(User); mover.MoveArc(TargetPosition, 10, -0.1f, new ACDTranslateArcMessage { //Field3 = 303110, // used for male barb leap, not needed? FlyingAnimationTagID = AnimationSetKeys.Attack2.ID, LandingAnimationTagID = -1, Field7 = PowerSNO }); // wait for landing while (!mover.Update()) { yield return(WaitTicks(1)); } // extra wait for leap to finish yield return(WaitTicks(1)); // ground smash effect User.PlayEffectGroup(162811); bool hitAnything = false; AttackPayload attack = new AttackPayload(this); attack.Targets = GetEnemiesInRadius(TargetPosition, 8f); attack.AddWeaponDamage(0.70f, DamageType.Physical); attack.OnHit = hitPayload => { hitAnything = true; }; attack.Apply(); if (hitAnything) { GeneratePrimaryResource(15f); } yield break; }
public override void Update(int tickCounter) { // if power executed, wait for attack/cooldown to finish. if (_powerRan) { if (_powerFinishTimer.TimedOut) { this.Done = true; } return; } // try to get nearest target if no target yet acquired if (_target == null) { if (this.Owner is Minion) // assume minions are player controlled and are targeting monsters { _target = this.Owner.GetMonstersInRange(MaxTargetRange).OrderBy( (monster) => PowerMath.Distance2D(monster.Position, this.Owner.Position)) .FirstOrDefault(); } else // monsters targeting players { _target = this.Owner.GetPlayersInRange(MaxTargetRange).OrderBy( (player) => PowerMath.Distance2D(player.Position, this.Owner.Position)) .FirstOrDefault(); } } if (_target != null) { float targetDistance = PowerMath.Distance2D(_target.Position, this.Owner.Position); // if target has moved out of range, deselect it as the target if (targetDistance > MaxTargetRange) { _target = null; } else if (targetDistance < _baseAttackRadius + _target.ActorData.Cylinder.Ax2) // run power if within range { // stop any movement _ownerMover.Move(this.Owner.Position, this.Owner.WalkSpeed); this.Owner.World.PowerManager.RunPower(this.Owner, _power, _target, _target.Position); _powerFinishTimer = new SecondsTickTimer(this.Owner.World.Game, _power.EvalTag(PowerKeys.AttackSpeed) + _power.EvalTag(PowerKeys.CooldownTime)); _powerRan = true; } else { // update or create path movement if (_pathUpdateTimer == null || _pathUpdateTimer.TimedOut) { _pathUpdateTimer = new SecondsTickTimer(this.Owner.World.Game, PathUpdateDelay); // move the space between each path update, or up to target. float moveAmount = this.Owner.WalkSpeed * (_pathUpdateTimer.TimeoutTick - this.Owner.World.Game.TickCounter); if (targetDistance < moveAmount) { moveAmount = targetDistance; // -(_baseAttackRadius + _target.ActorData.Cylinder.Ax2) - 0.1f; } Vector3D movePos = PowerMath.TranslateDirection2D(this.Owner.Position, _target.Position, this.Owner.Position, moveAmount); this.Owner.TranslateFacing(_target.Position, false); // find suitable movement animation int aniTag; if (this.Owner.AnimationSet == null) { aniTag = -1; } else if (this.Owner.AnimationSet.TagExists(Mooege.Common.MPQ.FileFormats.AnimationTags.Walk)) { aniTag = this.Owner.AnimationSet.GetAnimationTag(Mooege.Common.MPQ.FileFormats.AnimationTags.Walk); } else if (this.Owner.AnimationSet.TagExists(Mooege.Common.MPQ.FileFormats.AnimationTags.Run)) { aniTag = this.Owner.AnimationSet.GetAnimationTag(Mooege.Common.MPQ.FileFormats.AnimationTags.Run); } else { aniTag = -1; } _ownerMover.Move(movePos, this.Owner.WalkSpeed, new ACDTranslateNormalMessage { TurnImmediately = false, AnimationTag = aniTag }); } else { _ownerMover.Update(); } } } }
//there is a changed walking speed multiplier from 8101 patch. public override IEnumerable<TickTimer> Main() { //if (User.CurrentScene.NavMesh.WalkGrid[(int)((TargetPosition.X - //this.World.QuadTree.Query<Mooege.Core.GS.Map.Scene>(TargetPosition).FirstOrDefault().Bounds.Left) / 2.5f), //(int)((TargetPosition.Y - this.World.QuadTree.Query<Mooege.Core.GS.Map.Scene>(TargetPosition).FirstOrDefault().Bounds.Top) / 2.5f)] == 0) //yield break; bool hitAnything = false; StartCooldown(EvalTag(PowerKeys.CooldownTime)); if (Rune_C > 0) { AttackPayload launch = new AttackPayload(this); launch.Targets = GetEnemiesInRadius(User.Position, ScriptFormula(31)); launch.AddWeaponDamage(ScriptFormula(30), DamageType.Physical); launch.OnHit = hitPayload => { hitAnything = true; }; launch.Apply(); User.PlayEffectGroup(165924); //Not sure if this is the only effect to be displayed in this case } ActorMover mover = new ActorMover(User); mover.MoveArc(TargetPosition, 10, -0.1f, new ACDTranslateArcMessage { //Field3 = 303110, // used for male barb leap, not needed? FlyingAnimationTagID = AnimationSetKeys.Attack2.ID, LandingAnimationTagID = -1, Field7 = PowerSNO }); // wait for landing while (!mover.Update()) yield return WaitTicks(1); // extra wait for leap to finish yield return WaitTicks(1); if (Rune_D > 0) { AddBuff(User, new LeapAttackArmorBuff()); } // ground smash effect User.PlayEffectGroup(162811); AttackPayload attack = new AttackPayload(this); attack.Targets = GetEnemiesInRadius(TargetPosition, ScriptFormula(0)); //ScriptFormula(1) states "% of willpower Damage", perhaps the damage should be calculated that way instead. attack.AddWeaponDamage(0.70f, DamageType.Physical); attack.OnHit = hitPayload => { hitAnything = true; if (Rune_E > 0) { if (Rand.NextDouble() < ScriptFormula(37)) { AddBuff(hitPayload.Target, new DebuffStunned(WaitSeconds(ScriptFormula(38)))); } } }; attack.Apply(); if (hitAnything) GeneratePrimaryResource(EvalTag(PowerKeys.ResourceGainedOnFirstHit)); //TODO: Eventually att visuals, and check if the current uber-drag is really intended :P if (Rune_A > 0) { TargetList targets = GetEnemiesInRadius(User.Position, ScriptFormula(3)); Actor curTarget; int affectedTargets = 0; while (affectedTargets < ScriptFormula(12)) //SF(11) states "Min number to Knockback", and is 5, what can that mean? { curTarget = targets.GetClosestTo(User.Position); if (curTarget != null) { targets.Actors.Remove(curTarget); if (curTarget.World != null) { Knockback(curTarget, ScriptFormula(8), ScriptFormula(9), ScriptFormula(10)); } affectedTargets++; } else { break; } } } if (Rune_B > 0) { TargetList targets = GetEnemiesInRadius(User.Position, ScriptFormula(3)); foreach (Actor curTarget in targets.Actors) { Knockback(curTarget, ScriptFormula(17), ScriptFormula(18), ScriptFormula(19)); var secondKnockBack = GetEnemiesInRadius(curTarget.Position, 1f); // this will hackfully check for collision if (secondKnockBack.Actors.Count > 1) { foreach (Actor secondaryTarget in GetEnemiesInRadius(curTarget.Position, ScriptFormula(23)).Actors) { Knockback(secondaryTarget, ScriptFormula(24), ScriptFormula(25), ScriptFormula(26)); var thirdKnockBack = GetEnemiesInRadius(secondaryTarget.Position, 1f); if (thirdKnockBack.Actors.Count > 1) { foreach (Actor thirdTarget in GetEnemiesInRadius(secondaryTarget.Position, ScriptFormula(23)).Actors) { Knockback(thirdTarget, ScriptFormula(24), ScriptFormula(25), ScriptFormula(26)); } } } } } } yield break; }
public override IEnumerable<TickTimer> Main() { bool hitAnything = false; //StartCooldown(WaitSeconds(10f)); if (Rune_C > 0) { AttackPayload launch = new AttackPayload(this); launch.Targets = GetEnemiesInRadius(User.Position, ScriptFormula(31)); launch.AddWeaponDamage(ScriptFormula(30), DamageType.Physical); launch.OnHit = hitPayload => { hitAnything = true; }; launch.Apply(); User.PlayEffectGroup(165924); //Not sure if this is the only effect to be displayed in this case } ActorMover mover = new ActorMover(User); mover.MoveArc(TargetPosition, 10, -0.1f, new ACDTranslateArcMessage { //Field3 = 303110, // used for male barb leap, not needed? FlyingAnimationTagID = AnimationSetKeys.Attack2.ID, LandingAnimationTagID = -1, Field7 = PowerSNO }); // wait for landing while (!mover.Update()) yield return WaitTicks(1); // extra wait for leap to finish yield return WaitTicks(1); if (Rune_D > 0) { AddBuff(User, new LeapAttackArmorBuff()); } // ground smash effect User.PlayEffectGroup(162811); AttackPayload attack = new AttackPayload(this); attack.Targets = GetEnemiesInRadius(TargetPosition, ScriptFormula(0)); //ScriptFormula(1) states "% of willpower Damage", perhaps the damage should be calculated that way instead. attack.AddWeaponDamage(0.70f, DamageType.Physical); attack.OnHit = hitPayload => { hitAnything = true; if (Rune_E > 0) { if (Rand.NextDouble() < ScriptFormula(37)) { AddBuff(hitPayload.Target, new DebuffStunned(WaitSeconds(ScriptFormula(38)))); } } }; attack.Apply(); if (hitAnything) GeneratePrimaryResource(15f); //TODO: Eventually att visuals, and check if the current uber-drag is really intended :P if (Rune_A > 0) { TargetList targets = GetEnemiesInRadius(User.Position, ScriptFormula(3)); Actor curTarget; int affectedTargets = 0; while (affectedTargets < ScriptFormula(12)) //SF(11) states "Min number to Knockback", and is 5, what can that mean? { curTarget = targets.GetClosestTo(User.Position); if (curTarget != null) { targets.Actors.Remove(curTarget); if (curTarget.World != null) { Knockback(curTarget, ScriptFormula(8), ScriptFormula(9), ScriptFormula(10)); } affectedTargets++; } else { break; } } } yield break; }
public override IEnumerable<TickTimer> Main() { //StartCooldown(WaitSeconds(10f)); ActorMover mover = new ActorMover(User); mover.MoveArc(TargetPosition, 3, -0.1f, new ACDTranslateArcMessage { //Field3 = 303110, // used for male barb leap, not needed? FlyingAnimationTagID = AnimationSetKeys.Attack2.ID, LandingAnimationTagID = -1, PowerSNO = PowerSNO }); // wait for landing while (!mover.Update()) yield return WaitTicks(1); yield break; }
public override void Update(int tickCounter) { // if power executed, wait for attack/cooldown to finish. if (_powerRan) { if (_powerFinishTimer.TimedOut) { this.Done = true; } return; } // try to get nearest target if no target yet acquired if (_target == null) { _target = this.Owner.GetPlayersInRange(MaxTargetRange).OrderBy( (player) => PowerMath.Distance2D(player.Position, this.Owner.Position)) .FirstOrDefault(); } if (_target != null) { float targetDistance = PowerMath.Distance2D(_target.Position, this.Owner.Position); // if target has moved out of range, deselect it as the target if (targetDistance > MaxTargetRange) { _target = null; } else if (targetDistance < _baseAttackRadius + _target.ActorData.Cylinder.Ax2) // run power if within range { // stop any movement this.Owner.Move(this.Owner.Position, MovementHelpers.GetFacingAngle(this.Owner, _target)); //this.Owner.TranslateFacing(_target.Position, true); this.Owner.World.PowerManager.RunPower(this.Owner, _power, _target, _target.Position); _powerFinishTimer = new SecondsTickTimer(this.Owner.World.Game, _power.EvalTag(PowerKeys.AttackSpeed) + _power.EvalTag(PowerKeys.CooldownTime)); _powerRan = true; } else { // update or create path movement if (_pathUpdateTimer == null || _pathUpdateTimer.TimedOut) { _pathUpdateTimer = new SecondsTickTimer(this.Owner.World.Game, PathUpdateDelay); // move the space between each path update Vector3D movePos = PowerMath.TranslateDirection2D(this.Owner.Position, _target.Position, this.Owner.Position, this.Owner.WalkSpeed * (_pathUpdateTimer.TimeoutTick - this.Owner.World.Game.TickCounter)); this.Owner.TranslateFacing(_target.Position, false); _ownerMover.Move(movePos, this.Owner.WalkSpeed, new Net.GS.Message.Definitions.Actor.NotifyActorMovementMessage { TurnImmediately = false, AnimationTag = this.Owner.AnimationSet == null ? 0 : this.Owner.AnimationSet.GetAnimationTag(Mooege.Common.MPQ.FileFormats.AnimationTags.Walk) }); } else { _ownerMover.Update(); } } } }
public override bool Update() { return(_mover.Update()); }
public override bool Update() { _mover.Update(); return(base.Update()); }
public override void Update(int tickCounter) { // if power executed, wait for attack/cooldown to finish. if (_powerRan) { if (_powerFinishTimer.TimedOut) { this.Done = true; } return; } // try to get nearest target if no target yet acquired if (_target == null) { _target = this.Owner.GetPlayersInRange(MaxTargetRange).OrderBy( (player) => PowerMath.Distance2D(player.Position, this.Owner.Position)) .FirstOrDefault(); //.FirstOrDefault(x => x.Attributes[GameAttribute.Untargetable] == false); // If target is marked untargetable then we shouldnt consider him for targeting - DarkLotus } if (_target != null) { float targetDistance = PowerMath.Distance2D(_target.Position, this.Owner.Position); // if target has moved out of range, deselect it as the target if (targetDistance > MaxTargetRange) { _target = null; } else if (targetDistance < _baseAttackRadius + _target.ActorData.Cylinder.Ax2) // run power if within range { // stop any movement this.Owner.Move(this.Owner.Position, MovementHelpers.GetFacingAngle(this.Owner, _target)); //this.Owner.TranslateFacing(_target.Position, true); this.Owner.World.PowerManager.RunPower(this.Owner, _power, _target, _target.Position); _powerFinishTimer = new SecondsTickTimer(this.Owner.World.Game, _power.EvalTag(PowerKeys.AttackSpeed) + _power.EvalTag(PowerKeys.CooldownTime)); _powerRan = true; } else { if (_pathRequestTask == null) { _pathRequestTask = Owner.World.Game.Pathfinder.GetPath(Owner, Owner.Position, _target.Position); // called once to create task } if (!_pathRequestTask.PathFound) { return; } // No path found, so end Action. if (_pathRequestTask.Path.Count < 1) { return; } if (_path == null) { _path = _pathRequestTask.Path; } if (_ownerMover.ArrivalTime == null || _ownerMover.Arrived) { //if (_ownerMover.Arrived) //{ _pathUpdateTimer = new SecondsTickTimer(this.Owner.World.Game, PathUpdateDelay); //_pathRequestTask = null; Vector3D movePos = _path[0];// PowerMath.TranslateDirection2D(this.Owner.Position, _path[0], this.Owner.Position, //this.Owner.WalkSpeed * (_pathUpdateTimer.TimeoutTick - this.Owner.World.Game.TickCounter)); this.Owner.TranslateFacing(movePos, false); _ownerMover.Move(movePos, this.Owner.WalkSpeed, new Net.GS.Message.Definitions.ACD.ACDTranslateNormalMessage { TurnImmediately = false, AnimationTag = this.Owner.AnimationSet == null ? 0 : this.Owner.AnimationSet.GetAnimationTag(Mooege.Common.MPQ.FileFormats.AnimationTags.Walk) }); //if(PowerMath.Distance2D(movePos,_path[0]) < 5f) _path.RemoveAt(0); if (_path.Count == 0) { _pathRequestTask = null; _path = null; return; } //} //_path.Clear(); } /*// update or create path movement * if (_pathUpdateTimer == null || _pathUpdateTimer.TimedOut) * { * _pathUpdateTimer = new SecondsTickTimer(this.Owner.World.Game, PathUpdateDelay); * * // move the space between each path update * Vector3D movePos = PowerMath.TranslateDirection2D(this.Owner.Position, _target.Position, this.Owner.Position, * this.Owner.WalkSpeed * (_pathUpdateTimer.TimeoutTick - this.Owner.World.Game.TickCounter)); * if (!this.Owner.World.CheckLocationForFlag(movePos, Mooege.Common.MPQ.FileFormats.Scene.NavCellFlags.AllowWalk)) * { * var xdiff = movePos.X - this.Owner.Position.X; * var ydiff = movePos.Y - this.Owner.Position.Y; * movePos.Y = Owner.Position.Y; * // make sure mesh is a non walking one... * // could use gridsquares if hit left move one south etc * movePos.X = Owner.Position.X + xdiff; * foreach (var mesh in this.Owner.CurrentScene.NavZone.NavCells)// need to check scenes prob * { * if ((mesh.Bounds.Contains(movePos.X - Owner.CurrentScene.Position.X, movePos.Y - Owner.CurrentScene.Position.Y)) && !mesh.Flags.HasFlag(Mooege.Common.MPQ.FileFormats.Scene.NavCellFlags.AllowWalk)) * { * movePos.X = Owner.Position.X; * ydiff *= 1.4f; * break; * } * * } * movePos.Y += ydiff; * foreach (var mesh in this.Owner.CurrentScene.NavZone.NavCells)// need to check scenes prob * { * if ((mesh.Bounds.Contains(movePos.X - Owner.CurrentScene.Position.X, movePos.Y - Owner.CurrentScene.Position.Y)) && !mesh.Flags.HasFlag(Mooege.Common.MPQ.FileFormats.Scene.NavCellFlags.AllowWalk)) * { * movePos.Y = Owner.Position.Y; * movePos.X += (xdiff * 0.4f); * break; * } * } * * //var localmovepos = new Vector3D(movePos); * System.Windows.Rect oldPosRectSceneLocal = new System.Windows.Rect(Owner.Position.X - Owner.CurrentScene.Position.X, Owner.Position.Y- Owner.CurrentScene.Position.Y, Owner.Bounds.Width, Owner.Bounds.Height); * System.Windows.Rect movePosSceneLocal = new System.Windows.Rect(movePos.X - Owner.CurrentScene.Position.X, movePos.Y - Owner.CurrentScene.Position.Y, Owner.Bounds.Width, Owner.Bounds.Height); * movePos.X -= (float)this.Owner.CurrentScene.Bounds.Location.X; * movePos.Y -= (float)this.Owner.CurrentScene.Bounds.Location.Y; * Circle mob = new Circle(movePos.X - (float)Owner.CurrentScene.Position.X, movePos.Y - (float)Owner.CurrentScene.Position.Y, (float)this.Owner.Bounds.Width); * * foreach (var mesh in this.Owner.CurrentScene.NavZone.NavCells)// need to check scenes prob * { * /*if (mob.Intersects(mesh.Bounds)) * { * if(PowerMath.CircleInBeam(mob,mesh.Bounds.TopLeft,mesh.Bounds.BottomLeft,1f)) * { * * } * } * if ((mesh.Bounds.Contains(movePos.X, movePos.Y)) && mesh.Flags.HasFlag(Mooege.Common.MPQ.FileFormats.Scene.NavCellFlags.AllowWalk)) * { * if ((oldPosRectSceneLocal.Left >= mesh.Bounds.Right && movePosSceneLocal.Left < mesh.Bounds.Right)) // Right collisions * { * ydiff = 0; * xdiff = xdiff * 1.5f; * break; * } * if ((oldPosRectSceneLocal.Right < mesh.Bounds.Left && movePosSceneLocal.Right >= mesh.Bounds.Left))//Left * { * ydiff = 0; * xdiff = xdiff * 1.5f; * break; * } * if ((oldPosRectSceneLocal.Top >= mesh.Bounds.Bottom && movePosSceneLocal.Top < mesh.Bounds.Bottom) || (oldPosRectSceneLocal.Bottom < mesh.Bounds.Top && movePosSceneLocal.Bottom >= mesh.Bounds.Top)) // Bottom then Top * { * * xdiff = 0; * ydiff = ydiff * 1.5f; * break; * } * /*if (movePos.X > mesh.Min.X || movePos.X < mesh.Max.X) * { * xdiff = 0; * break; * } * else if (movePos.Y > mesh.Min.Y || movePos.Y < mesh.Max.Y) * { * ydiff = 0; * break; * } * } * * } * movePos.X = this.Owner.Position.X + xdiff; * movePos.Y = this.Owner.Position.Y + ydiff; * } * * * * this.Owner.TranslateFacing(movePos,false);//_target.Position, false); * * _ownerMover.Move(movePos, this.Owner.WalkSpeed, new Net.GS.Message.Definitions.ACD.ACDTranslateNormalMessage * { * TurnImmediately = false, * AnimationTag = this.Owner.AnimationSet == null ? 0 : this.Owner.AnimationSet.GetAnimationTag(Mooege.Common.MPQ.FileFormats.AnimationTags.Walk) * }); * }*/ else { if (_ownerMover.Velocity != null) { _ownerMover.Update(); } //if (_ownerMover.Arrived) // _ownerMover = new ActorMover(this.Owner); } } } }