001package com.fs.starfarer.api.impl.campaign.ghosts;
002
003import org.lwjgl.util.vector.Vector2f;
004
005import com.fs.starfarer.api.Global;
006import com.fs.starfarer.api.campaign.CampaignFleetAPI;
007import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
008import com.fs.starfarer.api.campaign.SectorEntityToken;
009import com.fs.starfarer.api.characters.AbilityPlugin;
010import com.fs.starfarer.api.impl.campaign.ghosts.GBIGenerateSlipstream.GhostBehaviorWithSlipstream;
011import com.fs.starfarer.api.impl.campaign.ids.Abilities;
012import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
013import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2;
014import com.fs.starfarer.api.util.Misc;
015
016
017public class GBLeviathanCalfRun extends BaseGhostBehavior implements GhostBehaviorWithSlipstream {
018        
019        public static float SENSOR_BURST_TURN_RATE = 30f;
020        public static float PULSE_BURN_BONUS = 10;
021        public static float PULSE_BURN_BONUS_DECAY = 0.25f;
022        
023        protected boolean dirSet = false;
024        protected float dir;
025        protected float burnBonus;
026        protected int origPluginBurn;
027        protected SectorEntityToken from;
028        protected float phase = (float) Math.random();
029        protected int maxBurn;
030        protected SlipstreamTerrainPlugin2 plugin;
031        protected boolean affectedByPulse = false;
032        protected float wobbleRate;
033        protected float maxWobble;
034        
035        public GBLeviathanCalfRun(float duration, SectorEntityToken from, float wobbleRate, float maxWobble, 
036                        int maxBurn, boolean affectedByPulse) {
037                super(duration);
038                this.from = from;
039                this.wobbleRate = wobbleRate;
040                this.maxWobble = maxWobble;
041                this.maxBurn = maxBurn;
042                this.affectedByPulse = affectedByPulse;
043        }
044
045
046
047        @Override
048        public void advance(float amount, SensorGhost ghost) {
049                if (from.getContainingLocation() != ghost.getEntity().getContainingLocation() ||
050                                ghost.getEntity().getContainingLocation() == null || !from.isAlive()) {
051                        end();
052                        return;
053                }
054                super.advance(amount, ghost);
055                
056                if (!dirSet || ghost.getEntity().getVelocity().length() < 10f) {
057                        dir = Misc.getAngleInDegrees(from.getLocation(), ghost.getEntity().getLocation());
058                        dirSet = true;
059                } else {
060                        //dir = Misc.getAngleInDegrees(ghost.getEntity().getVelocity());
061                }
062                
063                float pi = (float) Math.PI;
064                float sin = (float) Math.sin(phase * pi * 2f);
065                phase += amount * wobbleRate;
066                
067                float maxAngleOffset = maxWobble;
068                float angle = dir + sin * maxAngleOffset;
069                
070//              float maxSteeringOffset = 30f;
071//              maxSteeringOffset = 0f;
072//              if (maxSteeringOffset > 0f && plugin != null && plugin.containsEntity(from)) {
073//                      float [] coords = plugin.getLengthAndWidthFractionWithinStream(from.getLocation());
074//                      if (coords != null) {
075//                              float dist = Misc.getDistance(ghost.getEntity(), from);
076//                              if (dist < 2000f) {
077//                                      float mag = (1f - Math.max(0f, dist - 1000f) / 1000f) * 
078//                                                              Math.signum(coords[1]) * Math.max(0f, Math.abs(coords[1]) - 0.3f) * 
079//                                                              maxSteeringOffset;
080//                                      angle += mag;
081//                              }
082//                      }
083//              }
084                
085                if (affectedByPulse) {
086                        checkInterdictionPulses(ghost);
087                }
088                //checkSensorBursts(ghost, amount);
089                
090                int useBonus = 0;
091                if (plugin != null) {
092                        burnBonus -= PULSE_BURN_BONUS_DECAY * amount;
093                        if (burnBonus < 0) burnBonus = 0;
094        
095                        useBonus = (int) burnBonus;
096                        plugin.getParams().burnLevel = origPluginBurn + useBonus;
097                }
098                
099                Vector2f loc = Misc.getUnitVectorAtDegreeAngle(angle);
100                loc.scale(10000f);
101                Vector2f.add(loc, ghost.getEntity().getLocation(), loc);
102                ghost.moveTo(loc, maxBurn + useBonus);
103                
104        }
105
106        public void checkInterdictionPulses(SensorGhost ghost) {
107                if (!Global.getSector().getMemoryWithoutUpdate().getBoolean(MemFlags.GLOBAL_INTERDICTION_PULSE_JUST_USED_IN_CURRENT_LOCATION)) {
108                        return;
109                }
110                CustomCampaignEntityAPI entity = ghost.getEntity();
111                if (entity == null || entity.getContainingLocation() == null || plugin == null) return;
112                for (CampaignFleetAPI fleet : entity.getContainingLocation().getFleets()) {
113//                      float range = InterdictionPulseAbility.getRange(fleet);
114//                      float dist = Misc.getDistance(fleet.getLocation(), entity.getLocation());
115//                      if (dist > range) continue;
116                        // anywhere inside the stream is fine, actually
117                        if (!plugin.containsEntity(fleet)) continue;
118                        
119                        if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.JUST_DID_INTERDICTION_PULSE)) {
120                                burnBonus = PULSE_BURN_BONUS;
121                                if (fleet.isPlayerFleet()) {
122                                        String key = "$leviathanCalvesPulsed";
123                                        int count = Global.getSector().getMemoryWithoutUpdate().getInt(key);
124                                        Global.getSector().getMemoryWithoutUpdate().set(key, count + 1);
125                                }
126                                return;
127                        }
128                }
129        }
130        public void checkSensorBursts(SensorGhost ghost, float amount) {
131                CustomCampaignEntityAPI entity = ghost.getEntity();
132                if (entity == null || entity.getContainingLocation() == null || plugin == null) return;
133                for (CampaignFleetAPI fleet : entity.getContainingLocation().getFleets()) {
134                        // anywhere inside the stream is fine, actually
135                        if (!plugin.containsEntity(fleet)) continue;
136                        
137                        AbilityPlugin asb = fleet.getAbility(Abilities.SENSOR_BURST);
138                        if (asb.isInProgress()) {// && asb.getLevel() == 1f) {
139                                float [] coords = plugin.getLengthAndWidthFractionWithinStream(fleet.getLocation());
140                                if (coords != null) {
141                                        dir += coords[1] * SENSOR_BURST_TURN_RATE * amount;
142                                        ((BaseSensorGhost)ghost).setAccelMult(1f);
143                                }
144//                              float velDir = Misc.getAngleInDegrees(entity.getVelocity());
145//                              float toFleet = Misc.getAngleInDegrees(entity.getLocation(), fleet.getLocation());
146//                              float turnDir = Misc.getClosestTurnDirection(toFleet, velDir);
147//                              dir += turnDir * SENSOR_BURST_TURN_RATE * amount;
148                        }
149                }
150        }
151
152
153        public void setSlipstream(SlipstreamTerrainPlugin2 plugin) {
154                this.plugin = plugin;
155                origPluginBurn = plugin.getParams().burnLevel;
156        }
157        
158        
159        
160}
161
162
163
164
165
166
167
168
169
170
171
172
173