// Reassigns some allied soldiers in order to redistribute them. private static void TryReassignAllArmy() { int armiesCount = UnitSystem.inst.ArmyCount(); for (int i = 0; i < armiesCount; i++) { UnitSystem.Army army = UnitSystem.inst.GetAmry(i); IMoveTarget target = army.moveTarget; Vector3 armyPos = army.GetPos(); bool alliedSoldier = army.TeamID() == 0 && army.armyType == UnitSystem.ArmyType.Default; bool valid = !army.IsInvalid(); // Only valid allied soldiers can be reassigned. if (!alliedSoldier || !valid) { continue; } IMoveTarget newTarget = GetTargetForArmy(army, settings.patrolRadius.Value); // If the current target enemy is not a viking, disabled through settings, or invalid (dying or getting // on a boat), always reassign. bool targetIsViking = target != null && enemyAssignments.ContainsKey(target); if (!targetIsViking || !TargetTypeEnabled(target) || TargetTypeInvalid(target)) { MoveArmyToTarget(army, newTarget); } else if (target != null && target is UnitSystem.Army) { if (newTarget is UnitSystem.Army && !AtMinimumAssignment(target) && LessThanMinimumAssignment(newTarget)) { MoveArmyToTarget(army, newTarget); } else if (newTarget is SiegeMonster && LessThanMinimumAssignment(newTarget)) { // Ogres are always prioritized by always pulling soldiers away from viking squads. MoveArmyToTarget(army, newTarget); } } else if (target != null && target is SiegeMonster) { if (!AtMinimumAssignment(target) && LessThanMinimumAssignment(newTarget)) { MoveArmyToTarget(army, newTarget); } } } }
private static bool TargetTypeInvalid(IMoveTarget target) { UnitSystem.Army army = target as UnitSystem.Army; SiegeMonster ogre = target as SiegeMonster; if (ogre != null) { return(ogre.IsInvalid()); } if (army != null) { return(army.IsInvalid()); } return(true); }
public static void Prefix(IMoveableUnit moveableUnit, IMoveTarget moveTarget) { UnitSystem.Army army = moveableUnit as UnitSystem.Army; if (army != null && army.TeamID() == 0 && army.armyType == UnitSystem.ArmyType.Default && !army.IsInvalid()) { if (moveTarget != null && !(moveTarget is SiegeMonster) && !(moveTarget is UnitSystem.Army) && VikingInvasion()) { originalPos[army] = moveTarget.GetPos(); } string armyType = army.armyType.ToString(); RemoveAssignment(army.moveTarget); RecordAssignment(moveTarget); } }
public static void Postfix(General __instance) { UnitSystem.Army army = __instance.army; if (!settings.enabled.Value || army.TeamID() != 0 || army.armyType != UnitSystem.ArmyType.Default || army.IsInvalid()) { return; } if (VikingInvasion()) { try { if (!army.moving && ArmyIdle(army)) { if (!originalPos.ContainsKey(army)) { // At the beginning of an invasion, record the soldier squad's original position so it // can be returned at the end. originalPos[army] = army.GetPos(); } AssignTargetToArmyAndMove(army, settings.patrolRadius.Value); } } catch {} } else { if (originalPos.ContainsKey(army)) { // At the end of a viking invasion, move all soldiers back to their original position. IMoveTarget target = World.inst.GetCellData(originalPos[army]); if (target != null) { OrdersManager.inst.MoveTo(army, target); } originalPos.Remove(army); } } }
private static IMoveTarget GetNextViking(Vector3 pos, float range) { // Refer to SiegeMonster::ClosestMonster and UnitSystem::GetClosestDamageable. float rangeSquared = range * range; float currentClosestDistance = float.MaxValue; int currentLowestAssigned = int.MaxValue; IMoveTarget nextViking = null; foreach (IMoveTarget viking in enemyAssignments.Keys) { UnitSystem.Army army = viking as UnitSystem.Army; SiegeMonster ogre = viking as SiegeMonster; if ((army == null && ogre == null) || (army != null && (army.IsInvalid() || !OnSameLandmass(pos, army.GetPos()))) || (ogre != null && (ogre.IsInvalid() || !OnSameLandmass(pos, ogre.GetPos()))) || !TargetTypeEnabled(viking)) { continue; } // Select the closest viking squad or ogre with the least points to obey the assignment and distribution // rules. int assigned = enemyAssignments[viking]; float distanceSquared = Mathff.DistSqrdXZ(pos, viking.GetPos()); if (distanceSquared > rangeSquared || assigned > currentLowestAssigned) { continue; } if (nextViking == null || assigned < currentLowestAssigned || (distanceSquared < currentClosestDistance && assigned == currentLowestAssigned)) { nextViking = viking; currentClosestDistance = distanceSquared; currentLowestAssigned = assigned; } } return(nextViking); }