001package com.fs.starfarer.api.impl.combat.threat;
002
003import java.awt.Color;
004
005import com.fs.starfarer.api.Global;
006import com.fs.starfarer.api.combat.BaseHullMod;
007import com.fs.starfarer.api.combat.CombatEngineAPI;
008import com.fs.starfarer.api.combat.MutableShipStatsAPI;
009import com.fs.starfarer.api.combat.ShipAPI;
010import com.fs.starfarer.api.combat.ShipAPI.HullSize;
011import com.fs.starfarer.api.impl.campaign.ids.Stats;
012import com.fs.starfarer.api.ui.Alignment;
013import com.fs.starfarer.api.ui.TooltipMakerAPI;
014import com.fs.starfarer.api.util.Misc;
015
016/**
017 * Hidden hullmod for managing the special properties of Threat ships.
018 * @author Alex
019 *
020 */
021public class ThreatHullmod extends BaseHullMod {
022
023        public static String SHIP_BEING_RECLAIMED = "ship_being_reclaimed";
024        
025        public static String HIVE_UNIT = "hive_unit";
026        public static String FABRICATOR_UNIT = "fabricator_unit";
027        
028        public static float AIM_BONUS = 1f;
029        public static float MISSILE_GUIDANCE_BONUS = 1f;
030        public static float CR_BONUS = 30f;
031        public static float SENSOR_PROFILE_MULT = 0f;
032        public static float EW_PENALTY_MULT = 0.5f;
033        
034//      public static float HIVE_UNIT_REGEN_RATE_MULT = 8f;
035//      public static float HIVE_UNIT_SWARM_SIZE_MULT = 2f;
036        public static float HIVE_UNIT_REGEN_RATE_MULT = 2f;
037        public static float HIVE_UNIT_SWARM_SIZE_MULT = 4f;
038        public static float FABRICATOR_UNIT_REGEN_RATE_MULT = 1f;
039        public static float FABRICATOR_UNIT_SWARM_SIZE_MULT = 2f;
040        
041        public static float MODULE_DAMAGE_TAKEN_MULT = 0.5f;
042        public static float EMP_DAMAGE_TAKEN_MULT = 0.5f;
043        
044        @Override
045        public void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id) {
046                ConstructionSwarmSystemScript.init();
047                
048                stats.getAutofireAimAccuracy().modifyFlat(id, AIM_BONUS);
049                stats.getMissileGuidance().modifyFlat(id, MISSILE_GUIDANCE_BONUS);
050                stats.getMaxCombatReadiness().modifyFlat(id, CR_BONUS * 0.01f);
051                
052                stats.getSensorProfile().modifyMult(id, SENSOR_PROFILE_MULT);
053                
054                stats.getDynamic().getMod(Stats.ELECTRONIC_WARFARE_PENALTY_MOD).modifyMult(id, EW_PENALTY_MULT);
055                
056                stats.getEmpDamageTakenMult().modifyMult(id, EMP_DAMAGE_TAKEN_MULT);
057                stats.getEngineDamageTakenMult().modifyMult(id, MODULE_DAMAGE_TAKEN_MULT);
058                stats.getWeaponDamageTakenMult().modifyMult(id, MODULE_DAMAGE_TAKEN_MULT);
059                stats.getDynamic().getMod(Stats.CAN_REPAIR_MODULES_UNDER_FIRE).modifyFlat(id, 1f);
060                
061                if (stats.getVariant() != null && stats.getVariant().getHullSpec().getHullId().equals(HIVE_UNIT)) {
062                        stats.getDynamic().getStat(Stats.FRAGMENT_SWARM_RESPAWN_RATE_MULT).modifyMult(id, HIVE_UNIT_REGEN_RATE_MULT);
063                        stats.getDynamic().getMod(Stats.FRAGMENT_SWARM_SIZE_MOD).modifyMult(id, HIVE_UNIT_SWARM_SIZE_MULT);
064//                      stats.getDynamic().getStat(Stats.FRAGMENT_SWARM_RESPAWN_RATE_MULT).modifyMult(id, 2f);
065//                      stats.getDynamic().getMod(Stats.FRAGMENT_SWARM_SIZE_MOD).modifyMult(id, 4f);
066                } else if (stats.getVariant() != null && stats.getVariant().getHullSpec().getHullId().equals(FABRICATOR_UNIT)) {
067                        stats.getDynamic().getStat(Stats.FRAGMENT_SWARM_RESPAWN_RATE_MULT).modifyMult(id, FABRICATOR_UNIT_REGEN_RATE_MULT);
068                        stats.getDynamic().getMod(Stats.FRAGMENT_SWARM_SIZE_MOD).modifyMult(id, FABRICATOR_UNIT_SWARM_SIZE_MULT);
069                }
070                
071                //if (hullSize == HullSize.FIGHTER) {
072                        //stats.getEnergyAmmoRegenMult().modifyMult(id, 1000f);
073                //}
074                
075                // no officers, but baseline affected by certain skill effects
076                // or not - actually really difficult with these
077                if (hullSize != HullSize.FIGHTER) {
078//                      new ImpactMitigation.Level2().apply(stats, hullSize, id, 1f);
079//                      new ImpactMitigation.Level4().apply(stats, hullSize, id, 1f);
080//                      
081//                      new DamageControl.Level3().apply(stats, hullSize, id, 1f);
082//                      new DamageControl.Level4().apply(stats, hullSize, id, 1f);
083//                      new DamageControl.Level8().apply(stats, hullSize, id, 1f); // elite
084//                      
085//                      new TargetAnalysis.Level2().apply(stats, hullSize, id, 1f);
086//                      new TargetAnalysis.Level3().apply(stats, hullSize, id, 1f);
087//                      new TargetAnalysis.Level1A().apply(stats, hullSize, id, 1f); // elite
088//                      new TargetAnalysis.Level1().apply(stats, hullSize, id, 1f); // elite
089//                      new TargetAnalysis.Level4().apply(stats, hullSize, id, 1f); // elite
090//                      
091//                      new BallisticMastery.Level1().apply(stats, hullSize, id, 1f);
092//                      new BallisticMastery.Level2().apply(stats, hullSize, id, 1f);
093                }               
094        }
095        
096
097        @Override
098        public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
099//              CombatEngineAPI engine = Global.getCombatEngine();
100//              if (!engine.hasPluginOfClass(ThreatCombatStrategyForBothSidesPlugin.class)) {
101//                      engine.addPlugin(new ThreatCombatStrategyForBothSidesPlugin());
102//              }
103//              if (ship.getSystem() != null && ship.getSystem().getScript() instanceof EnergyLashActivatedSystem) {
104//                      EnergyLashActivatedSystem script = (EnergyLashActivatedSystem) ship.getSystem().getScript();
105//                      script.resetAfterShipCreation(ship);
106//              }
107        }
108        
109        
110        @Override
111        public void applyEffectsAfterShipAddedToCombatEngine(ShipAPI ship, String id) {
112                CombatEngineAPI engine = Global.getCombatEngine();
113                if (!engine.hasPluginOfClass(ThreatCombatStrategyForBothSidesPlugin.class)) {
114                        engine.addPlugin(new ThreatCombatStrategyForBothSidesPlugin());
115                }
116        }
117
118
119        @Override
120        public void advanceInCombat(ShipAPI ship, float amount) {
121                super.advanceInCombat(ship, amount);
122                
123                if (!ship.isHulk() || ship.hasTag(SHIP_BEING_RECLAIMED)) return;
124                if (ThreatCombatStrategyAI.isFabricator(ship)) return;
125                
126                float elapsedAsHulk = 0f;
127                String key = "elapsedAsHulkKey";
128                if (ship.getCustomData().containsKey(key)) {
129                        elapsedAsHulk = (float) ship.getCustomData().get(key);
130                }
131                elapsedAsHulk += amount;
132                ship.setCustomData(key, elapsedAsHulk);
133                if (elapsedAsHulk > 1f) {
134                        CombatEngineAPI engine = Global.getCombatEngine();
135                        int owner = ship.getOriginalOwner();
136                        boolean found = false;
137                        for (ShipAPI curr : engine.getShips()) {
138                                if (curr == ship || curr.getOwner() != owner) continue;
139                                if (curr.isHulk() || curr.getOwner() == 100) continue;
140                                if (!ThreatCombatStrategyAI.isFabricator(curr)) continue;
141                                if (curr.getCurrentCR() >= 1f) continue;
142                                found = true;
143                                break;
144                        }
145                        if (found) {
146                                Global.getCombatEngine().addPlugin(new ThreatShipReclamationScript(ship, 3f));
147                        } else {
148                                ship.setCustomData(key, 0f);
149                        }
150                }
151        }
152
153
154        @Override
155        public void applyEffectsToFighterSpawnedByShip(ShipAPI fighter, ShipAPI ship, String id) {
156        }
157
158        
159        @Override
160        public boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec) {
161                return false;
162        }
163
164        @Override
165        public void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, ShipAPI ship, float width, boolean isForModSpec) {
166                float pad = 3f;
167                float opad = 10f;
168                Color h = Misc.getHighlightColor();
169                Color bad = Misc.getNegativeHighlightColor();
170                Color t = Misc.getTextColor();
171                Color g = Misc.getGrayColor();
172        
173                tooltip.addPara("Threat hulls have a number of shared properties.", opad);
174                
175                tooltip.addSectionHeading("Campaign", Alignment.MID, opad);
176                tooltip.addPara("Sensor profile reduced to %s.", opad, h, "0");
177                
178                tooltip.addSectionHeading("Combat", Alignment.MID, opad);
179                tooltip.addPara("Target leading accuracy increased to maximum for all weapons, including missiles. Effect "
180                                + "of enemy ECM rating reduced by %s.", opad, h, "" + (int) Math.round(EW_PENALTY_MULT * 100f) + "%");
181                tooltip.addPara("Weapon and engine damage taken is reduced by %s. EMP damage taken is reduced by %s. In "
182                                + "addition, repairs of damaged but functional weapons and engines can continue while they are under fire.",
183                                opad, h,
184                                "" + (int) Math.round((1f - MODULE_DAMAGE_TAKEN_MULT) * 100f) + "%",
185                                "" + (int) Math.round((1f - EMP_DAMAGE_TAKEN_MULT) * 100f) + "%");
186                
187                
188        }
189        
190        public float getTooltipWidth() {
191                return super.getTooltipWidth();
192        }
193        
194
195}