001package com.fs.starfarer.api.impl.combat.dweller; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import com.fs.starfarer.api.Global; 007import com.fs.starfarer.api.combat.CombatAssignmentType; 008import com.fs.starfarer.api.combat.CombatEngineAPI; 009import com.fs.starfarer.api.combat.CombatFleetManagerAPI; 010import com.fs.starfarer.api.combat.CombatFleetManagerAPI.AssignmentInfo; 011import com.fs.starfarer.api.combat.CombatTaskManagerAPI; 012import com.fs.starfarer.api.combat.DeployedFleetMemberAPI; 013import com.fs.starfarer.api.combat.ShipAPI; 014import com.fs.starfarer.api.fleet.FleetGoal; 015import com.fs.starfarer.api.impl.campaign.ids.HullMods; 016import com.fs.starfarer.api.impl.campaign.ids.Tags; 017import com.fs.starfarer.api.util.IntervalUtil; 018 019/** 020 * Like the Threat one: 021 * Doesn't care about command points etc, just functions in a different way. May use command points/tasks/etc 022 * to accomplish its goals, just as an implementation detail, but conceptually it's fundamentally different from how 023 * human-type fleets work. 024 * 025 * @author Alex 026 * 027 */ 028public class DwellerCombatStrategyAI { 029 030 public static float SND_BASE = 60f; 031 public static float SND_TIMER = 60f; 032 public static float SND_FRACTION = 0.5f; 033 034 protected boolean playerSide; 035 protected CombatTaskManagerAPI taskManager; 036 protected CombatFleetManagerAPI fleetManager; 037 protected CombatFleetManagerAPI enemyFleetManager; 038 protected int owner; 039 protected boolean allyMode = false; 040 041 protected IntervalUtil everySecond = new IntervalUtil(0.8f, 1.2f); 042 protected CombatEngineAPI engine; 043 protected float mw, mh; 044 045 protected boolean abort = false; 046 047 protected AssignmentInfo mainDefend1; 048 protected AssignmentInfo mainDefend2; 049 050 protected boolean gaveInitialOrders = false; 051 052 053 public DwellerCombatStrategyAI(int owner) { 054 engine = Global.getCombatEngine(); 055 this.owner = owner; 056 playerSide = owner == 0; 057 allyMode = playerSide; 058 //allyMode = false; 059 fleetManager = engine.getFleetManager(owner); 060 taskManager = fleetManager.getTaskManager(allyMode); 061 taskManager.getCommandPointsStat().modifyFlat("DwellerCombatStrategyAI", 1000000000); 062 063 enemyFleetManager = engine.getFleetManager(owner == 0 ? 1 : 0); 064 065 if (fleetManager.getGoal() == FleetGoal.ESCAPE || enemyFleetManager.getGoal() == FleetGoal.ESCAPE) { 066 abort = true; 067 } else { 068 if (fleetManager.getAdmiralAI() != null) { 069 taskManager.clearTasks(); 070 fleetManager.getAdmiralAI().setNoOrders(true); 071 } 072 } 073 074 mw = engine.getMapWidth(); 075 mh = engine.getMapHeight(); 076 } 077 078 protected void giveInitialOrders() { 079 080 } 081 082 083 public void advance(float amount) { 084 //if (true) return; 085 if (abort) return; 086 if (engine.isPaused()) return; 087 088 everySecond.advance(amount); 089 if (everySecond.intervalElapsed()) { 090 // if non-threat ships are deployed from this fleetManager, don't want to be doing any Threat things 091 List<DeployedFleetMemberAPI> deployed = fleetManager.getDeployedCopyDFM(); 092 if (deployed.isEmpty()) return; 093 094 boolean someMatching = false; 095 for (DeployedFleetMemberAPI member : deployed) { 096 if (!member.isFighterWing() && member.getShip() != null && 097 member.isAlly() == allyMode && 098 !member.getShip().getVariant().hasHullMod(HullMods.DWELLER_HULLMOD)) { 099 abort = true; 100 return; 101 } else if (!member.isFighterWing() && member.getShip() != null && 102 member.isAlly() == allyMode) { 103 someMatching = true; 104 } 105 } 106 107 if (!someMatching) return; 108 109 if (!gaveInitialOrders) { 110 giveInitialOrders(); 111 gaveInitialOrders = true; 112 } 113 114 for (DeployedFleetMemberAPI member : fleetManager.getDeployedCopyDFM()) { 115 ShipAPI ship = member.getShip(); 116 if (ship == null || ship.getAI() == null) continue; 117 118 if (isMaw(ship)) { 119 AssignmentInfo curr = taskManager.getAssignmentInfoForTarget(member); 120 if (curr == null) { 121 taskManager.createAssignment(CombatAssignmentType.DEFEND, member, false); 122 taskManager.orderSearchAndDestroy(member, false); 123 } 124 } else if (isEye(ship)) { 125 AssignmentInfo curr = taskManager.getAssignmentInfoForTarget(member); 126 if (curr == null) { 127 taskManager.createAssignment(CombatAssignmentType.HEAVY_ESCORT, member, false); 128 taskManager.orderSearchAndDestroy(member, false); 129 } 130 } else if (isStinger(ship)) { 131// AssignmentInfo curr = taskManager.getAssignmentInfoForTarget(member); 132// if (curr == null) { 133// taskManager.createAssignment(CombatAssignmentType.HEAVY_ESCORT, member, false); 134// taskManager.orderSearchAndDestroy(member, false); 135// } 136 } 137 } 138 139 cleanUpEmptyAssignments(); 140 } 141 } 142 143 144 protected void cancelOrders(DeployedFleetMemberAPI member, boolean withSearchAndDestroy) { 145 AssignmentInfo curr = taskManager.getAssignmentFor(member.getShip()); 146 if (curr != null) { 147 taskManager.removeAssignment(curr); 148 } 149 if (withSearchAndDestroy) { 150 taskManager.orderSearchAndDestroy(member, false); 151 } 152 } 153 154 public void cleanUpEmptyAssignments() { 155 taskManager.reassign(); // so assigned members isn't empty 156 List<AssignmentInfo> remove = new ArrayList<>(); 157 for (AssignmentInfo curr : taskManager.getAllAssignments()) { 158 if (curr.getType() == CombatAssignmentType.CONTROL) continue; 159 if (curr.getType() == CombatAssignmentType.CAPTURE) continue; 160 if (curr.getType() == CombatAssignmentType.DEFEND) continue; 161 if (curr.getAssignedMembers().isEmpty()) { 162 remove.add(curr); 163 } 164 } 165 for (AssignmentInfo curr : remove) { 166 taskManager.removeAssignment(curr); 167 } 168 169 taskManager.clearEmptyWaypoints(); 170 } 171 172 173 public static boolean isMaw(ShipAPI ship) { 174 boolean isMaw = ship != null && ship.isCapital(); 175 return isMaw; 176 } 177 public static boolean isEye(ShipAPI ship) { 178 boolean isEye = ship != null && ship.isCruiser() && ship.getHullSpec().hasTag(Tags.DWELLER_RECKLESS); 179 return isEye; 180 } 181 public static boolean isStinger(ShipAPI ship) { 182 boolean isEye = ship != null && ship.isCruiser() && ship.getHullSpec().hasTag(Tags.DWELLER_TIMID); 183 return isEye; 184 } 185 public static boolean isTendril(ShipAPI ship) { 186 boolean isTendril = ship != null && ship.isDestroyer(); 187 return isTendril; 188 } 189} 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212