Tutorials » Combat Rotation » Step 6: Combat Rotation
The combat rotation continues until the target or the player has died.
Or until the target has changed due to priority considerations.
Alignment with the target occurs automatically. A distinction is made here between
IUnit (NPC) and IPlayer. This allows for different rotation behaviors to be implemented.
-
As
Rogue, we always want to maintain a maximumdistance of 3 yards (CombatDistance). To do this, we move him close enough to the target if the target moves further away thanCombatDistanceduring combat. -
If our
Power (Energy) is below 40, we should continue attacking the target.40represents the minimum Energy value required for our spells (Sinister Strike,Eviscerate) to be cast. -
Sinister Strikeshould only be cast when my combo points are less than or equal to 1.
Eviscerateshould only be cast when my combo points are greater than or equal to 2.
// 1. Maintain distancing.
if (Target.Distance3D > CombatDistance)
{
await GC.MM.FollowAsync(Target, new GroundPathConfig(GC)
{
StopFollowDistance = 2.0,
});
await GC.MM.InteractAsync(Target);
}
// 2. Maintain attack if Energy is less than 40.
if (GC.OM.Me.CurrentPower < 40)
{
await GC.MM.InteractAsync(Target);
return;
}
// 3. Execute spells.
await GC.SM.TryCastAsync("Sinister Strike", Target, new()
{
() => GC.OM.Me.ComboPoints <= 1,
});
await GC.SM.TryCastAsync("Eviscerate", Target, new()
{
() => GC.OM.Me.ComboPoints >= 2,
});
-
As
Mage, we always want to maintain a maximumdistance of 25 yards (CombatDistance). To do this, we move him close enough to the target if the target moves further away thanCombatDistanceduring combat. We also want to try to finish our current cast. -
If our
Power (Mana) is below 312, we could use our wand. In this case, we want to approach the target at close range so we can hit it by hand. -
Counterspell,Frostbolt,FireballundFire Blastare our main spells which we carry out under different conditions. -
If the target is not in sight, we will approach it at close range.
// 1. Maintain distancing.
if (Target.Distance3D > CombatDistance && !GC.OM.Me.IsCastingOrChanneling)
{
await GC.MM.FollowAsync(Target, new GroundPathConfig(GC)
{
StopFollowDistance = 20.0,
});
await GC.MM.InteractAsync(Target);
}
// Attack the target at close range if you don't have enough mana.
if (GC.OM.Me.CurrentPower < 312)
{
if (Target.Distance3D > 5)
await GC.MM.FollowAsync(Target, new GroundPathConfig(GC)
{
StopFollowDistance = 4.0,
});
await GC.MM.InteractAsync(Target);
return;
}
// Our main spells.
await GC.SM.TryCastAsync("Counterspell", Target, new()
{
() => Target.IsCastingOrChanneling,
});
await GC.SM.TryCastAsync("Frostbolt", Target, new()
{
() => !Target.HasAura("Frostbolt"),
});
await GC.SM.TryCastAsync("Fireball", Target);
await GC.SM.TryCastAsync("Fire Blast", Target, new()
{
() => Target.HasAura("Fireball"),
});
// Approach when it is not in sight.
if (!Target.IsInLightOfSight)
{
await GC.MM.FollowAsync(Target, new GroundPathConfig(GC)
{
StopFollowDistance = 4.0,
});
}
Further information on the functions shown in this example:
Manager → ObjectManager → Models → IUnit → Distance3D
Manager → ObjectManager → Models → IUnit → IsCastingOrChanneling
Manager → MovementManager → Ground Pathing → FollowAsync
Manager → MovementManager → Interact → InteractAsync
Manager → ObjectManager → Models → IUnit → CurrentPower
Manager → SpellManager → Cast Spell → TryCastAsync
Manager → ObjectManager → Models → IMe → ComboPoints
Manager → ObjectManager → Models → IUnit → HasAura
Manager → ObjectManager → Models → IUnit → IsInLightOfSight
The procedure for creating the CombatApproach method is the same.
Keep in mind that combat behavior against a real player is different. Stealth as rogue
would perform significantly better in the CombatRotation method under different conditions.
More on this in the next step: Step 6: Combat Rotation
If you want to use a single rotation for both types, you can do so as follows.
public async Task CombatRotation(IUnit Target)
{
var Model = GC.OM.CreateModel(Target);
await CombatApproach(Model);
}
public async Task CombatRotation(IPlayer Target)
{
var Model = GC.OM.CreateModel(Target);
await CombatApproach(Model);
}
// Add this to your template.
private async Task CombatRotation(IModel Model)
{
// My rotation ...
}
Use different rotations for different opponents.
public async Task CombatRotation(IUnit Target)
{
switch (Target.Name)
{
case "Boss name": MeVsBoss(Target); return;
case "Evil enemy name 1": MeVsEvilEnemy1(Target); return;
case "Evil enemy name 2": MeVsEvilEnemy2(Target); return;
default: MyDefaultRotation(Target); return;
}
}
private async Task MeVsBoss(IUnit Target)
{
// Me vs. Boss Rotation...
}
private async Task MeVsEvilEnemy1(IUnit Target)
{
// Me vs. Evil Enemy Rotation 1...
}
private async Task MeVsEvilEnemy2(IUnit Target)
{
// Me vs. Evil Enemy Rotation 2...
}
private async Task MyDefaultRotation(IUnit Target)
{
// My Default Rotation...
}
The examples shown are not guidelines. They are intended to serve as food for thought.
Take a look at the Spell Manager
to understand the differences between Cast and TryCast
and to get an overview of your options.
The Object Manager and its
Models is also worth checking out to learn about your character's and your enemies' abilities.