001package com.fs.starfarer.api.impl.combat;
002
003import java.util.Iterator;
004import java.util.List;
005
006import org.lwjgl.util.vector.Vector2f;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
010import com.fs.starfarer.api.combat.CombatEntityAPI;
011import com.fs.starfarer.api.combat.ShipAPI;
012import com.fs.starfarer.api.input.InputEventAPI;
013import com.fs.starfarer.api.util.Misc;
014
015public class GravityPullEffect extends BaseEveryFrameCombatPlugin {
016        protected float maxForce;
017        protected float duration = 0.05f;
018        protected float elapsed = 0f;
019        protected CombatEntityAPI source;
020        protected float range;
021        
022        public GravityPullEffect(CombatEntityAPI source, float range, float maxForce) {
023                this.source = source;
024                this.range = range;
025                this.maxForce = maxForce;
026                duration = 0.05f;
027        }
028
029
030
031
032        @Override
033        public void advance(float amount, List<InputEventAPI> events) {
034                if (Global.getCombatEngine().isPaused()) return;
035
036                elapsed += amount;
037
038                Iterator<Object> iter = Global.getCombatEngine().getAllObjectGrid().getCheckIterator(source.getLocation(),
039                                                                                                                                        range * 2f, range * 2f);
040                
041                while (iter.hasNext()) {
042                        Object o = iter.next();
043                        if (o == source) continue;
044                        if (!(o instanceof CombatEntityAPI)) continue;
045                        if (!(o instanceof ShipAPI)) continue;
046//                      if (!(o instanceof MissileAPI)) continue;
047//                      if (!(o instanceof DamagingProjectileAPI)) continue;
048//                      if (!(o instanceof AsteroidAPI)) continue;
049                        
050                        CombatEntityAPI other = (CombatEntityAPI) o;
051                        if (other.getMass() <= 0) continue;
052                        applyForce(other, amount);
053                }
054                
055
056                if (elapsed > duration) {
057                        Global.getCombatEngine().removePlugin(this);
058                }
059        }
060        
061        protected void applyForce(CombatEntityAPI other, float amount) {
062                float dist = Misc.getDistance(source.getLocation(), other.getLocation());
063                dist -= other.getCollisionRadius();
064                if (dist > range) return;
065                
066                float fTime = 0.0f + 1f * (Math.min(1f, elapsed / duration));
067                float fDist = 0.25f + 0.75f * Math.min(1f, (1f - dist / range));
068                float fConstant = 20f;
069                
070                float acceleration = maxForce / other.getMass() * fTime * fDist * fConstant;
071                
072                Vector2f dir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(other.getLocation(), source.getLocation()));
073                dir.scale(acceleration);
074                
075                other.getVelocity().x += dir.x * amount;
076                other.getVelocity().y += dir.y * amount;
077        }
078        
079//      public class HyperStormBoost implements EveryFrameScript {
080//
081//              public static float MAX_BURN = Global.getSettings().getFloat("maxStormStrikeBurn");
082//              public static float STORM_SPEED_BURST = Global.getSettings().getSpeedPerBurnLevel() * 50f;
083//              public static float DURATION_SECONDS = 1f;
084//              
085//              protected CampaignFleetAPI fleet;
086//              protected float elapsed;
087//              protected float angle;
088//              protected CellStateTracker cell;
089//              
090//              public HyperStormBoost(CellStateTracker cell, CampaignFleetAPI fleet) {
091//                      this.cell = cell;
092//                      this.fleet = fleet;
093//                      
094//                      DURATION_SECONDS = 1.25f;
095//                      STORM_SPEED_BURST = Global.getSettings().getSpeedPerBurnLevel() * 75f;
096////                    DURATION_SECONDS = 2f;
097////                    STORM_SPEED_BURST = Global.getSettings().getSpeedPerBurnLevel() * 50f;
098//                      
099//                      if (Misc.getHyperspaceTerrain().getPlugin() instanceof HyperspaceTerrainPlugin) {
100//                              HyperspaceTerrainPlugin hyper = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin();
101//                              
102//                              float x = hyper.getEntity().getLocation().x;
103//                              float y = hyper.getEntity().getLocation().y;
104//                              float size = hyper.getTileSize();
105//                      
106//                              float w = hyper.getTiles().length * size;
107//                              float h = hyper.getTiles()[0].length * size;
108//
109//                              x -= w/2f;
110//                              y -= h/2f;
111//                      
112//                              float tx = x + cell.i * size + size/2f;
113//                              float ty = y + cell.j * size + size/2f;
114//                      
115//                              angle = Misc.getAngleInDegrees(new Vector2f(tx, ty), fleet.getLocation());
116//                              
117//                              Vector2f v = fleet.getVelocity();
118//                              float angle2 = Misc.getAngleInDegrees(v);
119//                              float speed = v.length();
120//                              if (speed < 10) angle2 = fleet.getFacing();
121//                              
122//                              float bestAngleAt = Global.getSettings().getBaseTravelSpeed() + Global.getSettings().getSpeedPerBurnLevel() * 20f;
123//                              float mult = 0.5f + 0.4f * speed / bestAngleAt;
124//                              if (mult < 0.5f) mult = 0.5f;
125//                              if (mult > 0.9f) mult = 0.9f;
126//                              
127//                              angle += Misc.getClosestTurnDirection(angle, angle2) * Misc.getAngleDiff(angle, angle2) * mult;
128//                      }
129//              }
130//
131//              public void advance(float amount) {
132//                      elapsed += amount;
133//                      
134//                      Vector2f boost = Misc.getUnitVectorAtDegreeAngle(angle);
135//                      
136//                      float mult = 1f;
137//                      mult = 1f - elapsed / DURATION_SECONDS;
138//                      mult *= Math.pow(Math.min(1f, elapsed / 0.25f), 2f);
139//                      if (mult < 0) mult = 0;
140//                      if (mult > 1) mult = 1;
141//                      boost.scale(STORM_SPEED_BURST * amount * mult);
142//                      
143//                      Vector2f v = fleet.getVelocity();
144//                      
145//                      if (fleet.getCurrBurnLevel() < MAX_BURN) {
146//                              fleet.setVelocity(v.x + boost.x, v.y + boost.y);
147//                      }
148//                      
149//                      float angleHeading = Misc.getAngleInDegrees(v);
150//                      if (v.length() < 10) angleHeading = fleet.getFacing();
151//                      
152//                      boost = Misc.getUnitVectorAtDegreeAngle(angleHeading);
153//                      boost.negate();
154//                      if (boost.length() >= 1) {
155//                              float durIn = 1f;
156//                              float durOut = 3f;
157//                              float intensity = 1f;
158//                              float sizeNormal = 5f + 30f * intensity;
159//                              String modId = "boost " + cell.i + cell.j * 100;
160//                              Color glowColor = new Color(100, 100, 255, 75);
161//                              for (FleetMemberViewAPI view : fleet.getViews()) {
162//                                      view.getWindEffectDirX().shift(modId, boost.x * sizeNormal, durIn, durOut, 1f);
163//                                      view.getWindEffectDirY().shift(modId, boost.y * sizeNormal, durIn, durOut, 1f);
164//                                      view.getWindEffectColor().shift(modId, glowColor, durIn, durOut, intensity);
165//                              }
166//                      }
167//              }
168//
169//              public boolean isDone() {
170//                      return elapsed >= DURATION_SECONDS || !fleet.isInHyperspace();
171//              }
172//
173//              public boolean runWhilePaused() {
174//                      // TODO Auto-generated method stub
175//                      return false;
176//              }
177}