001package com.fs.starfarer.api.impl.campaign;
002
003import org.lwjgl.util.vector.Vector2f;
004
005import com.fs.starfarer.api.EveryFrameScript;
006import com.fs.starfarer.api.Global;
007import com.fs.starfarer.api.campaign.CampaignFleetAPI;
008import com.fs.starfarer.api.campaign.comm.CommMessageAPI.MessageClickAction;
009import com.fs.starfarer.api.impl.campaign.ids.Sounds;
010import com.fs.starfarer.api.impl.campaign.intel.MessageIntel;
011import com.fs.starfarer.api.impl.campaign.intel.events.ht.HTAbyssalLightFactor;
012import com.fs.starfarer.api.impl.campaign.intel.events.ht.HyperspaceTopographyEventIntel;
013import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
014import com.fs.starfarer.api.util.Misc;
015
016public class AbyssalLightBonus implements EveryFrameScript {
017
018        public static float BURN_BONUS_MULT = 1f;
019        public static float BURN_BONUS_FLAT = 5f;
020        public static float LIGHT_YEARS_PER_UNIT_OF_BURN_BONUS = 3f;
021        
022        public static float SENSOR_BONUS_FLAT = 1000f;
023        public static float LIGHT_YEARS_PER_UNIT_OF_SENSOR_BONUS = 3f;
024        
025        
026        public static AbyssalLightBonus get(CampaignFleetAPI fleet) {
027                for (EveryFrameScript s : fleet.getScripts()) {
028                        if (s instanceof AbyssalLightBonus) {
029                                return (AbyssalLightBonus) s;
030                        }
031                }
032                AbyssalLightBonus script = new AbyssalLightBonus(fleet);
033                fleet.addScript(script);
034                return script;
035        }
036        
037        protected CampaignFleetAPI fleet;
038        protected float burnBonus = 0f;
039        protected float sensorBonus = 0f;
040        
041        protected int framesSpentPending = 0;
042        protected float pendingBurnBonus = 0;
043        protected float pendingSensorBonus = 0;
044        protected int pendingTopographyPoints = 0;
045        protected int pendingLightsCount = 0;
046        protected Vector2f prevLoc = null;
047        
048        public AbyssalLightBonus(CampaignFleetAPI fleet) {
049                this.fleet = fleet;
050                prevLoc = new Vector2f(fleet.getLocation());
051        }
052        
053        public void advance(float amount) {
054                if (fleet.isPlayerFleet()) {
055                        checkPendingAndSendMessages();
056                }
057                
058                float depth = Misc.getAbyssalDepth(fleet);
059                if (depth < 1f) {
060                        burnBonus = 0f;
061                        sensorBonus = 0f;
062                        return;
063                }
064                
065                Vector2f loc = fleet.getLocation();
066                float distLY = Misc.getDistanceLY(loc, prevLoc);
067                prevLoc.set(fleet.getLocation());
068                
069                burnBonus -= distLY / LIGHT_YEARS_PER_UNIT_OF_BURN_BONUS;
070                sensorBonus -= distLY / LIGHT_YEARS_PER_UNIT_OF_BURN_BONUS;
071                
072                if (burnBonus < 0) burnBonus = 0;
073                if (sensorBonus < 0) sensorBonus = 0;
074                
075                if (burnBonus > 0) {
076                        if (BURN_BONUS_MULT != 1f) {
077                                float burnMult = BURN_BONUS_MULT;
078                                if (burnBonus < 1f) {
079                                        burnMult = 1f + (burnMult - 1f) * burnBonus;
080                                        if (burnMult < 1.1f) burnMult = 1.1f;
081                                }
082                                String ly = Misc.getRoundedValueOneAfterDecimalIfNotWhole(getBurnBonusLYRemaining(burnBonus));
083                                fleet.getStats().addTemporaryModMult(0.1f, "abyssalLight_1",
084                                                "Abyssal light (for " + ly + " more light-years)", burnMult, 
085                                                fleet.getStats().getFleetwideMaxBurnMod());
086                        }
087                        if (BURN_BONUS_FLAT > 0) {
088                                float burnFlat = BURN_BONUS_FLAT / HyperspaceTerrainPlugin.ABYSS_BURN_MULT;
089                                if (burnBonus < 1f / LIGHT_YEARS_PER_UNIT_OF_BURN_BONUS) {
090                                        burnFlat *= burnBonus * LIGHT_YEARS_PER_UNIT_OF_BURN_BONUS;
091                                }
092                                burnFlat = Math.round(burnFlat);
093                                if (burnFlat < 1f) burnFlat = 1f;
094                                
095                                String ly = Misc.getRoundedValueOneAfterDecimalIfNotWhole(getBurnBonusLYRemaining(burnBonus));
096                                fleet.getStats().addTemporaryModFlat(0.1f, "abyssalLight_2",
097                                                "Abyssal light (for " + ly + " more light-years)", burnFlat, 
098                                                fleet.getStats().getFleetwideMaxBurnMod());
099                        }
100                }
101                
102                if (sensorBonus > 0) {
103                        if (SENSOR_BONUS_FLAT > 0) {
104                                float sensorFlat = SENSOR_BONUS_FLAT / HyperspaceTerrainPlugin.ABYSS_SENSOR_RANGE_MULT;
105                                if (sensorBonus < 1f / LIGHT_YEARS_PER_UNIT_OF_SENSOR_BONUS) {
106                                        sensorFlat *= sensorBonus * LIGHT_YEARS_PER_UNIT_OF_SENSOR_BONUS;
107                                }
108                                sensorFlat = Math.round(sensorFlat);
109                                if (sensorFlat < 1f) sensorFlat = 1f;
110                                
111                                String ly = Misc.getRoundedValueOneAfterDecimalIfNotWhole(getSensorBonusLYRemaining(sensorBonus));
112                                fleet.getStats().addTemporaryModFlat(0.1f, "abyssalLight_3",
113                                                "Abyssal light (for " + ly + " more light-years)", sensorFlat, 
114                                                fleet.getStats().getSensorRangeMod());
115                        }
116                }
117        }
118        
119        public float getBurnBonusLYRemaining(float bonus) {
120                return bonus * LIGHT_YEARS_PER_UNIT_OF_BURN_BONUS;
121        }
122        
123        public float getSensorBonusLYRemaining(float bonus) {
124                return bonus * LIGHT_YEARS_PER_UNIT_OF_SENSOR_BONUS;
125        }
126        
127        public void addBurnBonus(float bonus) {
128                if (fleet.isPlayerFleet()) {
129                        pendingBurnBonus += bonus;
130                        framesSpentPending = 0;
131                } else {
132                        burnBonus += bonus;
133                }
134        }
135        
136        public void addSensorBonus(float bonus) {
137                if (fleet.isPlayerFleet()) {
138                        pendingSensorBonus += bonus;
139                        framesSpentPending = 0;
140                } else {
141                        sensorBonus += bonus;
142                }
143        }
144        
145        public void addTopographyPoints(int points) {
146                pendingTopographyPoints += points;
147                pendingLightsCount++;
148                framesSpentPending = 0;
149        }
150        
151        
152        public void checkPendingAndSendMessages() {
153                framesSpentPending++;
154                if (framesSpentPending > 1) {
155                        framesSpentPending = 0;
156
157                        if (pendingTopographyPoints > 0) {
158                                HyperspaceTopographyEventIntel.addFactorCreateIfNecessary(
159                                                new HTAbyssalLightFactor(pendingTopographyPoints, pendingLightsCount > 1), null);
160                                pendingTopographyPoints = 0;
161                                pendingLightsCount = 0;
162                        }
163                        if (pendingBurnBonus > 0) {
164                                MessageIntel msg = new MessageIntel();
165                                String ly = Misc.getRoundedValueOneAfterDecimalIfNotWhole(getSensorBonusLYRemaining(pendingBurnBonus));
166                                msg.addLine("Increased burn level for %s light-years", Misc.getTextColor(),
167                                                new String[] {"+" + ly}, Misc.getHighlightColor());
168                                msg.setSound(Sounds.NONE);
169                                Global.getSector().getCampaignUI().addMessage(msg, MessageClickAction.NOTHING);
170                                burnBonus += pendingBurnBonus;
171                                pendingBurnBonus = 0;
172                        }
173                        
174                        if (pendingSensorBonus > 0) {
175                                MessageIntel msg = new MessageIntel();
176                                String ly = Misc.getRoundedValueOneAfterDecimalIfNotWhole(getSensorBonusLYRemaining(pendingSensorBonus));
177                                msg.addLine("Increased sensor range for %s light-years", Misc.getTextColor(),
178                                                new String[] {"+" + ly}, Misc.getHighlightColor());
179                                msg.setSound(Sounds.NONE);
180                                Global.getSector().getCampaignUI().addMessage(msg, MessageClickAction.NOTHING);
181                                sensorBonus += pendingSensorBonus;
182                                pendingSensorBonus = 0;
183                        }
184                        
185                }
186        }
187        
188        
189        public float getBurnBonus() {
190                return burnBonus;
191        }
192
193        public void setBurnBonus(float burnBonus) {
194                this.burnBonus = burnBonus;
195        }
196
197        public float getSensorBonus() {
198                return sensorBonus;
199        }
200
201        public void setSensorBonus(float sensorBonus) {
202                this.sensorBonus = sensorBonus;
203        }
204
205        public boolean isDone() {
206                return burnBonus <= 0 && sensorBonus <= 0 && 
207                                pendingBurnBonus <= 0 && pendingSensorBonus <= 0 && pendingTopographyPoints <= 0;
208        }
209
210        public boolean runWhilePaused() {
211                return false;
212        }
213
214}