001package com.fs.starfarer.api.impl.campaign.skills;
002
003import com.fs.starfarer.api.characters.AfterShipCreationSkillEffect;
004import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
005import com.fs.starfarer.api.characters.ShipSkillEffect;
006import com.fs.starfarer.api.characters.SkillSpecAPI;
007import com.fs.starfarer.api.combat.MutableShipStatsAPI;
008import com.fs.starfarer.api.combat.ShipAPI;
009import com.fs.starfarer.api.combat.ShipAPI.HullSize;
010import com.fs.starfarer.api.fleet.FleetMemberAPI;
011import com.fs.starfarer.api.ui.TooltipMakerAPI;
012
013public class WolfpackTactics {
014        
015        public static float DAMAGE_TO_LARGER_BONUS = 20f;
016        public static float DAMAGE_TO_LARGER_BONUS_DEST = 10f;
017        public static float PEAK_TIME_BONUS = 50f;
018        public static float PEAK_TIME_BONUS_DEST = 25f;
019        
020//      public static float FLAGSHIP_SPEED_BONUS = 25f;
021//      public static float FLAGSHIP_CP_BONUS = 100f;
022        
023        public static boolean isFrigateAndOfficer(MutableShipStatsAPI stats) {
024                if (stats.getEntity() instanceof ShipAPI) {
025                        ShipAPI ship = (ShipAPI) stats.getEntity();
026                        if (!ship.isFrigate()) return false;
027                        return !ship.getCaptain().isDefault();
028                } else {
029                        FleetMemberAPI member = stats.getFleetMember();
030                        if (member == null) return false;
031                        if (!member.isFrigate()) return false;
032                        return !member.getCaptain().isDefault();
033                }
034        }
035        
036        public static boolean isDestroyerAndOfficer(MutableShipStatsAPI stats) {
037                if (stats.getEntity() instanceof ShipAPI) {
038                        ShipAPI ship = (ShipAPI) stats.getEntity();
039                        if (!ship.isDestroyer()) return false;
040                        return !ship.getCaptain().isDefault();
041                } else {
042                        FleetMemberAPI member = stats.getFleetMember();
043                        if (member == null) return false;
044                        if (!member.isDestroyer()) return false;
045                        return !member.getCaptain().isDefault();
046                }
047        }
048        
049//      public static boolean isFrigateAndFlagship(MutableShipStatsAPI stats) {
050//              if (stats.getEntity() instanceof ShipAPI) {
051//                      ShipAPI ship = (ShipAPI) stats.getEntity();
052//                      if (!ship.isFrigate()) return false;
053//                      if (ship.getFleetMember() != null && 
054//                                      ship.getFleetMember().getFleetCommander() == ship.getCaptain()) {
055//                              return true;
056//                      }
057//                      return ship.getCaptain().isPlayer();
058//              } else {
059//                      FleetMemberAPI member = stats.getFleetMember();
060//                      if (member == null) return false;
061//                      if (!member.isFrigate()) return false;
062//                      if (member.isFlagship()) {
063//                              return true;
064//                      }
065//                      return member.getCaptain().isPlayer();
066//              }
067//      }
068//      public static boolean isDestroyerAndFlagship(MutableShipStatsAPI stats) {
069//              if (stats.getEntity() instanceof ShipAPI) {
070//                      ShipAPI ship = (ShipAPI) stats.getEntity();
071//                      if (!ship.isDestroyer()) return false;
072//                      if (ship.getFleetMember() != null && 
073//                                      ship.getFleetMember().getFleetCommander() == ship.getCaptain()) {
074//                              return true;
075//                      }
076//                      return ship.getCaptain().isPlayer();
077//              } else {
078//                      FleetMemberAPI member = stats.getFleetMember();
079//                      if (member == null) return false;
080//                      if (!member.isDestroyer()) return false;
081//                      if (member.isFlagship()) {
082//                              return true;
083//                      }
084//                      return member.getCaptain().isPlayer();
085//              }
086//      }
087        
088        public static class Level1A implements ShipSkillEffect {
089                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
090                        if (isFrigateAndOfficer(stats)) {
091                                stats.getDamageToDestroyers().modifyPercent(id, DAMAGE_TO_LARGER_BONUS);
092                                stats.getDamageToCruisers().modifyPercent(id, DAMAGE_TO_LARGER_BONUS);
093                                stats.getDamageToCapital().modifyPercent(id, DAMAGE_TO_LARGER_BONUS);
094                                
095                                stats.getPeakCRDuration().modifyPercent(id, PEAK_TIME_BONUS);
096                                //stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).modifyFlat(id, 1000f);
097                        } else if (isDestroyerAndOfficer(stats)) {
098                                stats.getDamageToCruisers().modifyPercent(id, DAMAGE_TO_LARGER_BONUS_DEST);
099                                stats.getDamageToCapital().modifyPercent(id, DAMAGE_TO_LARGER_BONUS_DEST);
100                                
101                                stats.getPeakCRDuration().modifyPercent(id, PEAK_TIME_BONUS_DEST);
102                                //stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).modifyFlat(id, 1000f);
103                        }
104                }
105                
106                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
107                        stats.getDamageToDestroyers().unmodifyPercent(id);
108                        stats.getDamageToCruisers().unmodifyPercent(id);
109                        stats.getDamageToCapital().unmodifyPercent(id);
110                        
111                        stats.getPeakCRDuration().unmodifyPercent(id);
112                        //stats.getDynamic().getMod(Stats.INDIVIDUAL_SHIP_RECOVERY_MOD).unmodify(id);
113                }
114                
115                public String getEffectDescription(float level) {
116                        //return "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS) + "% damage to ships larger than frigates";
117                        
118                        return "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS) + "% damage to ships larger than frigates if frigate, " +
119                                   "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS_DEST) + "% damage to capital ships and cruisers if destroyer\n" +
120                                   "+" + (int)(PEAK_TIME_BONUS) + "% seconds peak operating time if frigate, " + 
121                                   "+" + (int)(PEAK_TIME_BONUS_DEST) + "% if destroyer";
122//                      return "+" + (int)Math.round(DAMAGE_TO_LARGER_BONUS) + "% damage to ships larger than frigates\n" +
123//                      "+" + (int)(PEAK_TIME_BONUS) + " seconds peak operating time\n" +
124//                      "If lost in combat, ship is almost always recoverable";
125                }
126                
127                public String getEffectPerLevelDescription() {
128                        return null;
129                }
130                
131                public ScopeDescription getScopeDescription() {
132                        return ScopeDescription.PILOTED_SHIP;
133                }
134        }
135        
136        
137//      public static class Level1B extends BaseSkillEffectDescription implements ShipSkillEffect {
138//              public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
139//                      if (isFrigateAndFlagship(stats)) {
140//                              stats.getDynamic().getMod(Stats.COMMAND_POINT_RATE_FLAT).modifyFlat(id, FLAGSHIP_CP_BONUS * 0.01f);
141//                      } else if (isDestroyerAndFlagship(stats)) {
142//                              stats.getZeroFluxSpeedBoost().modifyFlat(id, FLAGSHIP_SPEED_BONUS);
143//                      }
144//              }
145//              
146//              public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
147//                      stats.getDynamic().getMod(Stats.COMMAND_POINT_RATE_FLAT).unmodify(id);
148//                      stats.getZeroFluxSpeedBoost().unmodifyFlat(id);
149//              }
150//              
151//              public String getEffectDescription(float level) {
152//                      return null;
153//                      //return "\n+" + (int) DESTROYER_CP_BONUS + "% to command point recovery rate if flagship is a destroyer";
154//              }
155//              
156//              public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 
157//                              TooltipMakerAPI info, float width) {
158//                      init(stats, skill);
159//
160//                      float opad = 10f;
161//                      Color c = Misc.getBasePlayerColor();
162//                      info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "flagship");
163//                      info.addSpacer(opad);
164//                      info.addPara("+%s to command point recovery rate if flagship is a frigate", 0f, hc, hc,
165//                                   "" + (int) FLAGSHIP_CP_BONUS + "%");
166//                      info.addPara("+%s to 0-flux speed boost if flagship is a destroyer", 0f, hc, hc,
167//                                      "" + (int) FLAGSHIP_SPEED_BONUS + "");
168//
169//                      //info.addSpacer(5f);
170//              }
171//              
172//              public String getEffectPerLevelDescription() {
173//                      return null;
174//              }
175//              
176//              public ScopeDescription getScopeDescription() {
177//                      return ScopeDescription.PILOTED_SHIP;
178//              }
179//      }
180        
181        
182        //public static class Level1C extends BaseSkillEffectDescription implements ShipSkillEffect, AfterShipCreationSkillEffect {
183        public static class Level1C extends BaseSkillEffectDescription implements AfterShipCreationSkillEffect {
184                public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
185//                      MutableShipStatsAPI stats = ship.getMutableStats();
186//                      Global.getCombatEngine().getListenerManager().addListener(listener);
187//                      if (isDmoddedAndOfficer(stats)) {
188//                              ship.addListener(new DCDamageTakenMod(ship));
189//                              
190//                              float dmods = DModManager.getNumDMods(ship.getVariant());
191//                              if (dmods <= 0) return;
192//                              if (dmods > MAX_DMODS) dmods = MAX_DMODS;
193//                              
194//                              if (ship.getShield() == null) {
195//                                      stats.getMinArmorFraction().modifyFlat(id, SHIELDLESS_ARMOR_BONUS_PER_DMOD * dmods);
196//                              }
197//                      }
198                }
199
200                public void unapplyEffectsAfterShipCreation(ShipAPI ship, String id) {
201//                      ship.removeListenerOfClass(DCDamageTakenMod.class);
202//                      
203//                      if (ship.getShield() == null) {
204//                              MutableShipStatsAPI stats = ship.getMutableStats();
205//                              stats.getMinArmorFraction().unmodifyFlat(id);
206//                      }
207                }
208                
209                
210                public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 
211                                TooltipMakerAPI info, float width) {
212//                      init(stats, skill);
213
214//                      info.addPara("%s chance per d-mod* to have incoming hull damage reduced by %s", 0f, hc, hc,
215//                                      "" + (int)AVOID_DAMAGE_CHANCE_PER_DMOD + "%",
216//                                      "" + (int)Math.round((1f - AVOID_DAMAGE_DAMAGE_MULT) * 100f) + "%"
217//                      );
218//                      info.addPara("%s crew lost due to hull damage in combat per d-mod*", 0f, hc, hc,
219//                                      "-" + (int)CREW_LOSS_REDUCTION_PER_DMOD + "%"
220//                      );
221//                      info.addPara("%s maximum combat readiness per d-mod*", 0f, hc, hc,
222//                                      "+" + (int)CR_PER_DMOD + "%"
223//                      );
224//                      
225//                      info.addSpacer(5f);
226//                      info.addPara("%s minimum armor value** for damage reduction per d-mod for unshielded ships", 0f, hc, hc,
227//                                      "+" + (int)Math.round(SHIELDLESS_ARMOR_BONUS_PER_DMOD * 100f) + "%"
228//                      );
229//                      
230                }
231
232                public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) {
233                }
234
235                public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) {
236                }
237        }
238        
239        /*
240        public static class WolfpackExtraDamageMod implements DamageDealtModifier, AdvanceableListener {
241                protected int owner;
242                public WolfpackExtraDamageMod(int owner) {
243                        this.owner = owner;
244                }
245                
246                protected boolean addDamage = false;
247                protected boolean addDamageAlly = false;
248                public void advance(float amount) {
249                        CombatFleetManagerAPI cfm = Global.getCombatEngine().getFleetManager(owner);
250                        for (DeployedFleetMemberAPI dfm : cfm.getDeployedCopyDFM()) {
251                                FleetMemberAPI member = dfm.getMember();
252                                if (member == null) continue;
253                                PersonAPI commander = member.getFleetCommanderForStats();
254                                if (commander == null) continue;
255                                
256                                ShipAPI ship = cfm.getShipFor(commander);
257
258                        }
259                }
260                
261                public String modifyDamageDealt(Object param, CombatEntityAPI target, DamageAPI damage, Vector2f point, boolean shieldHit) {
262                        return null;
263                }
264
265                public String modifyDamageTaken(Object param,
266                                                                                CombatEntityAPI target, DamageAPI damage,
267                                                                                Vector2f point, boolean shieldHit) {
268                        MutableShipStatsAPI stats = ship.getMutableStats();
269                        stats.getHullDamageTakenMult().unmodifyMult(DAMAGE_MOD_ID);
270                        
271                        if (shieldHit) return null;
272
273                        float chance = stats.getDynamic().getMod(AVOID_HULL_DAMAGE_CHANCE).computeEffective(0f);
274                        if (Math.random() >= chance) {
275                                return null;
276                        }
277                        
278                        stats.getHullDamageTakenMult().modifyMult(DAMAGE_MOD_ID, AVOID_DAMAGE_DAMAGE_MULT);
279                        
280                        return null;
281                }
282        }
283        */
284
285
286}