001package com.fs.starfarer.api.impl.campaign.intel.misc;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Set;
006
007import java.awt.Color;
008
009import org.lwjgl.util.vector.Vector2f;
010
011import com.fs.starfarer.api.Global;
012import com.fs.starfarer.api.campaign.CampaignFleetAPI;
013import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
014import com.fs.starfarer.api.campaign.FactionAPI;
015import com.fs.starfarer.api.campaign.PlanetAPI;
016import com.fs.starfarer.api.campaign.SectorEntityToken;
017import com.fs.starfarer.api.campaign.StarSystemAPI;
018import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
019import com.fs.starfarer.api.campaign.rules.MemoryAPI;
020import com.fs.starfarer.api.impl.campaign.entities.GateHaulerEntityPlugin;
021import com.fs.starfarer.api.impl.campaign.ids.Drops;
022import com.fs.starfarer.api.impl.campaign.ids.Entities;
023import com.fs.starfarer.api.impl.campaign.ids.Factions;
024import com.fs.starfarer.api.impl.campaign.ids.Tags;
025import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
026import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
027import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity;
028import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.EntityLocation;
029import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.OrbitGap;
030import com.fs.starfarer.api.impl.campaign.rulecmd.missions.GateHaulerCMD;
031import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldParams;
032import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldSource;
033import com.fs.starfarer.api.loading.Description;
034import com.fs.starfarer.api.loading.Description.Type;
035import com.fs.starfarer.api.ui.Alignment;
036import com.fs.starfarer.api.ui.SectorMapAPI;
037import com.fs.starfarer.api.ui.TooltipMakerAPI;
038import com.fs.starfarer.api.util.Misc;
039
040public class GateHaulerIntel extends BaseIntelPlugin {
041
042        public static float TRANSIT_DAYS_BASE = 100;
043        public static float TRANSIT_SPEED_LY_PER_CYCLE = 50;
044        
045        
046        public static Object UPDATE_WITNESSED_ARRIVAL = new Object();
047        
048        public static enum GateHaulerAction {
049                OUTBOUND,
050                DEEP_SPACE_TRANSIT,
051                INBOUND,
052                DEPLOYING,
053        }
054        
055        public static GateHaulerIntel get(SectorEntityToken gateHauler) {
056                for (IntelInfoPlugin p : Global.getSector().getIntelManager().getIntel(GateHaulerIntel.class)) {
057                        if (p instanceof GateHaulerIntel) {
058                                GateHaulerIntel intel = (GateHaulerIntel) p;
059                                if (intel.getGateHauler() == gateHauler) {
060                                        return intel;
061                                }
062                        }
063                }
064                return null;
065        }
066        
067        protected SectorEntityToken gateHauler;
068        protected StarSystemAPI destination;
069        protected float departureAngle;
070        protected int transitDays;
071        protected float elapsedDaysInAction;
072        protected SectorEntityToken parkingOrbit;
073        protected SectorEntityToken stableLocation;
074        protected GateHaulerAction action = null;
075        
076        //protected CampaignEntityMovementUtil movement;
077        
078        public GateHaulerIntel(SectorEntityToken gateHauler) {
079                this.gateHauler = gateHauler;
080                Global.getSector().addScript(this);
081                
082                //movement = new CampaignEntityMovementUtil(gateHauler, 0.5f, 3f, 5f, 2000f);
083        }
084        
085        @Override
086        protected void notifyEnded() {
087                super.notifyEnded();
088                Global.getSector().removeScript(this);
089        }
090
091        public void updateMemoryFlags() {
092//              MemoryAPI mem = gateHauler.getMemoryWithoutUpdate();
093//              mem.set("$state", state.name());
094//              if (state == GateHaulerState.OUTBOUND || state == GateHaulerState.INBOUND) {
095//                      mem.set("$inTransit", true);
096//              } else {
097//                      mem.unset("$inTransit");
098//              }
099        }
100        
101        public void activate() {
102                // don't actually need to do anything; all handled in the entity plugin and rules
103        }
104        
105        public int computeTransitDays(StarSystemAPI destination) {
106                //if (Global.getSettings().isDevMode()) return 1;
107                
108                if (destination == null) return 0;
109                
110                float dist = Misc.getDistanceLY(gateHauler, destination.getHyperspaceAnchor());
111                float transitDays = TRANSIT_DAYS_BASE + dist / TRANSIT_SPEED_LY_PER_CYCLE * 365f;
112                return Math.round(transitDays);
113        }
114        
115        public void initiateDeployment(SectorEntityToken stableLocation) {
116                if (stableLocation == null) return;
117
118                setAction(GateHaulerAction.DEPLOYING);
119                this.stableLocation = stableLocation;
120                
121                getPlugin().getMovement().moveToLocation(stableLocation.getLocation());
122                getPlugin().getMovement().setFaceInOppositeDirection(false);
123                getPlugin().getMovement().setTurnThenAccelerate(true);
124                getPlugin().setLongBurn(false);
125                
126                gateHauler.getMemoryWithoutUpdate().set("$deploying", true);
127                
128                
129                gateHauler.fadeOutIndicator();
130                gateHauler.addTag(Tags.NON_CLICKABLE);
131                //gateHauler.addTag(Tags.NO_ENTITY_TOOLTIP);
132                
133                stableLocation.fadeOutIndicator();
134                stableLocation.addTag(Tags.NON_CLICKABLE);
135                stableLocation.addTag(Tags.NO_ENTITY_TOOLTIP);
136        }
137        
138        public void initiateDeparture(StarSystemAPI destination) {
139                if (destination == null || destination == gateHauler.getContainingLocation()) return;
140                
141                setAction(GateHaulerAction.OUTBOUND);
142                if (parkingOrbit != null) {
143                        gateHauler.getContainingLocation().removeEntity(parkingOrbit);
144                        parkingOrbit = null;
145                }
146                
147                transitDays = computeTransitDays(destination);
148                this.destination = destination;
149
150                departureAngle = Misc.getAngleInDegrees(gateHauler.getLocationInHyperspace(), destination.getLocation());
151                
152                gateHauler.fadeOutIndicator();
153                getPlugin().getMovement().moveInDirection(departureAngle);
154                getPlugin().getMovement().setFaceInOppositeDirection(false);
155                getPlugin().getMovement().setTurnThenAccelerate(true);
156                getPlugin().setLongBurn(true);
157                
158                gateHauler.getMemoryWithoutUpdate().set("$inTransit", true);
159        }
160        
161        public void initiateArrival() {
162                if (destination == null) return; // something's badly wrong and the gate hauler is probably gone for good
163                
164                setAction(GateHaulerAction.INBOUND);
165                
166                findParkingOrbit();
167                
168                float brakeTime = GateHaulerEntityPlugin.MAX_SPEED / GateHaulerEntityPlugin.ACCELERATION; 
169                float brakeDist = GateHaulerEntityPlugin.MAX_SPEED * 0.5f * brakeTime;
170                
171                Vector2f spawnLoc = Misc.getUnitVectorAtDegreeAngle(departureAngle + 180f);
172                Vector2f spawnVel = new Vector2f(spawnLoc);
173                
174                spawnVel.scale(GateHaulerEntityPlugin.MAX_SPEED);
175                spawnVel.negate();
176                spawnLoc.scale(brakeDist * 1f + 4000f);
177                Vector2f.add(spawnLoc, parkingOrbit.getLocation(), spawnLoc);
178                
179                gateHauler.setExpired(false);
180                gateHauler.removeTag(Tags.NON_CLICKABLE);
181                gateHauler.removeTag(Tags.FADING_OUT_AND_EXPIRING);
182                gateHauler.setAlwaysUseSensorFaderBrightness(null);
183                
184                if (!destination.getAllEntities().contains(gateHauler)) {
185                        destination.addEntity(gateHauler);
186                }
187                
188                gateHauler.fadeOutIndicator();
189                
190                getPlugin().getMovement().setLocation(spawnLoc);
191                getPlugin().getMovement().setVelocity(spawnVel);
192                getPlugin().getMovement().setFacing(departureAngle + 180f);
193                
194                getPlugin().getMovement().moveToLocation(parkingOrbit.getLocation());
195                getPlugin().getMovement().setTurnThenAccelerate(true);
196                getPlugin().getMovement().setFaceInOppositeDirection(true);
197                getPlugin().setLongBurn(true);
198        }
199        
200        protected void findParkingOrbit() {
201                float minDist = 4000f;
202                float maxDist = 8000f;
203                parkingOrbit = null;
204                SectorEntityToken found = null;
205                for (SectorEntityToken curr : destination.getEntitiesWithTag(Tags.STABLE_LOCATION)) {
206                        float dist = curr.getLocation().length();
207                        if (dist >= minDist && dist <= 8000f) {
208                                found = curr;
209                                break;
210                        }
211                }
212                if (found == null) {
213                        for (PlanetAPI curr : destination.getPlanets()) {
214                                if (curr.isMoon()) continue;
215                                float dist = curr.getLocation().length();
216                                if (dist >= minDist && dist <= 8000f) {
217                                        found = curr;
218                                        break;
219                                }
220                        }
221                }
222                
223                if (found != null) {
224                        Vector2f loc = Misc.getPointAtRadius(found.getLocation(), found.getRadius() + 400f);
225                        parkingOrbit = destination.createToken(loc);
226                        float orbitRadius = found.getRadius() + 250f;
227                        float orbitDays = orbitRadius / (20f + Misc.random.nextFloat() * 5f);
228                        parkingOrbit.setCircularOrbit(found, Misc.random.nextFloat() * 360f, orbitRadius, orbitDays);
229                } else {
230                        List<OrbitGap> gaps = BaseThemeGenerator.findGaps(
231                                        destination.getCenter(), minDist, maxDist, gateHauler.getRadius() + 50f);
232                        if (!gaps.isEmpty()) {
233                                OrbitGap gap = gaps.get(0);
234                                float orbitRadius = (gap.start + gap.end) * 0.5f;
235                                Vector2f loc = Misc.getPointAtRadius(destination.getCenter().getLocation(), orbitRadius);
236                                parkingOrbit = destination.createToken(loc);
237                                
238                                if (!destination.isNebula()) {
239                                        float orbitDays = orbitRadius / (20f + Misc.random.nextFloat() * 5f);
240                                        parkingOrbit.setCircularOrbit(destination.getCenter(), Misc.random.nextFloat() * 360f, orbitRadius, orbitDays);
241                                }
242                        }
243                }
244                
245                if (parkingOrbit == null) {
246                        float orbitRadius = minDist + (maxDist - minDist) * Misc.random.nextFloat();
247                        Vector2f loc = Misc.getPointAtRadius(destination.getCenter().getLocation(), orbitRadius);
248                        parkingOrbit = destination.createToken(loc);
249                        
250                        if (!destination.isNebula()) {
251                                float orbitDays = orbitRadius / (20f + Misc.random.nextFloat() * 5f);
252                                parkingOrbit.setCircularOrbit(destination.getCenter(), Misc.random.nextFloat() * 360f, orbitRadius, orbitDays);
253                        }
254                }
255                
256                destination.addEntity(parkingOrbit);
257        }
258        
259        protected void setAction(GateHaulerAction action) {
260                this.action = action;
261                elapsedDaysInAction = 0f;
262        }
263        
264        public GateHaulerEntityPlugin getPlugin() {
265                return (GateHaulerEntityPlugin) gateHauler.getCustomPlugin();
266        }
267        
268        @Override
269        public void advance(float amount) {
270                super.advance(amount);
271                
272                if (action != null) {
273                        float days = Misc.getDays(amount);
274                        elapsedDaysInAction += days;
275                        
276                        gateHauler.fadeOutIndicator();
277                        if (action == GateHaulerAction.DEPLOYING && stableLocation != null) {
278                                stableLocation.fadeOutIndicator();
279                        }
280                }
281                
282                //System.out.println("Gate Hauler speed: " + gateHauler.getVelocity().length() + ", loc: " + gateHauler.getLocation());
283                //System.out.println("Loc: " + gateHauler.getLocation());
284                //System.out.println("Player speed: " + Global.getSector().getPlayerFleet().getVelocity().length());
285                if (action == GateHaulerAction.OUTBOUND) {
286                        float speed = gateHauler.getVelocity().length();
287                        float dist = gateHauler.getLocation().length();
288                        CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
289                        boolean nearPlayer = pf != null && gateHauler.isInCurrentLocation() &&
290                                        Misc.getDistance(pf, gateHauler) < 10000f;
291                        if (!nearPlayer && elapsedDaysInAction > 20f &&
292                                        speed >= GateHaulerEntityPlugin.MAX_SPEED * 0.95f && dist > 40000f) {
293                                Misc.fadeAndExpire(gateHauler);
294                                setAction(GateHaulerAction.DEEP_SPACE_TRANSIT);
295                                sendUpdateIfPlayerHasIntel(GateHaulerAction.DEEP_SPACE_TRANSIT, false);
296                        }
297                }
298                
299                if (action == GateHaulerAction.DEEP_SPACE_TRANSIT) {
300                        if (elapsedDaysInAction >= transitDays) {
301                                initiateArrival();
302                                sendUpdateIfPlayerHasIntel(GateHaulerAction.INBOUND, false);
303                        }
304                }
305                
306                if (action == GateHaulerAction.INBOUND) {
307                        getPlugin().getMovement().moveToLocation(parkingOrbit.getLocation());
308                        float speed = gateHauler.getVelocity().length();
309                        float dist = Misc.getDistance(parkingOrbit, gateHauler);
310                        
311                        boolean overshot = Misc.isInArc(gateHauler.getFacing(), 270f,
312                                                                        gateHauler.getLocation(), parkingOrbit.getLocation());
313                        if (overshot || dist < 700f) {
314                                getPlugin().getMovement().setTurnThenAccelerate(false);
315                                getPlugin().getMovement().setFaceInOppositeDirection(false);
316                        }
317                        boolean closeEnough = speed < 20f && dist < 100f + parkingOrbit.getRadius() + gateHauler.getRadius();
318                        if (dist < 200f + parkingOrbit.getRadius() + gateHauler.getRadius() && elapsedDaysInAction > 30f) {
319                                closeEnough = true;
320                        }
321                        if (closeEnough) {
322                                setAction(null);
323                                destination = null;
324                                gateHauler.fadeInIndicator();
325                                getPlugin().getMovement().setFaceInOppositeDirection(false);
326                                getPlugin().setLongBurn(false);
327                                float orbitAngle = Misc.getAngleInDegrees(parkingOrbit.getLocation(), gateHauler.getLocation());
328                                float orbitDays = 1000000f;
329                                gateHauler.setCircularOrbit(parkingOrbit, orbitAngle, dist, orbitDays);
330                                
331                                if (!gateHauler.isInCurrentLocation()) {
332                                        for (int i = 0; i < 10; i++) {
333                                                getPlugin().getEngineGlow().showIdling();
334                                                getPlugin().getEngineGlow().advance(1f);
335                                        }
336                                }
337                                gateHauler.getMemoryWithoutUpdate().unset("$inTransit");
338                                
339                                if (gateHauler.isInCurrentLocation()) {
340                                        String key = "$witnessedGateHaulerArrival";
341                                        MemoryAPI mem = Global.getSector().getPlayerMemoryWithoutUpdate();
342                                        if (!mem.getBoolean(key)) {
343                                                float distToPlayer = Misc.getDistance(Global.getSector().getPlayerFleet(), gateHauler);
344                                                if (distToPlayer < 2000f) {
345                                                        sendUpdateIfPlayerHasIntel(UPDATE_WITNESSED_ARRIVAL, false);
346                                                        Global.getSector().getPlayerStats().addStoryPoints(1, null, false);
347                                                        mem.set(key, true);
348                                                }
349                                        }
350                                }
351                        }
352                }
353                
354                
355                if (action == GateHaulerAction.DEPLOYING) {
356                        if (gateHauler.getOrbit() == null) {
357                                getPlugin().getMovement().moveToLocation(stableLocation.getLocation());
358                        }
359                        
360                        if (elapsedDaysInAction > 1f) {
361                                if (gateHauler.getOrbit() == null) {
362                                        float speed = gateHauler.getVelocity().length();
363                                        float dist = Misc.getDistance(stableLocation, gateHauler);
364                                        
365                                        if (dist < 1000f) {
366                                                getPlugin().getMovement().setTurnThenAccelerate(false);
367                                        }
368                                        float test = 100f;
369                                        if (!gateHauler.isInCurrentLocation()) test = 400f;
370                                        boolean closeEnough = speed < 20f && dist < test + stableLocation.getRadius() + gateHauler.getRadius();
371                                        if (dist < 500f + stableLocation.getRadius() + gateHauler.getRadius() + 
372                                                        (elapsedDaysInAction - 50f) * 50f && elapsedDaysInAction > 50f) {
373                                                closeEnough = true;
374                                        }
375                                        if (closeEnough) {
376                                                float orbitAngle = Misc.getAngleInDegrees(stableLocation.getLocation(), gateHauler.getLocation());
377                                                float orbitDays = 1000000f;
378                                                gateHauler.setCircularOrbit(stableLocation, orbitAngle, dist, orbitDays);
379                                                elapsedDaysInAction = 0f;
380                                        }
381                                } else {
382                                        // set the orbit and waited a day; deploy
383                                        setAction(null);
384        
385                                        addDebrisField();
386                                        
387                                        EntityLocation loc = new EntityLocation();
388                                        if (stableLocation.getOrbit() != null) {
389                                                loc.orbit = stableLocation.getOrbit().makeCopy();
390                                        } else {
391                                                loc.location = new Vector2f(stableLocation.getLocation());
392                                        }
393                                        stableLocation.getStarSystem().getMemoryWithoutUpdate().set("$deployedGateHaulerHere", true);
394                                        
395                                        AddedEntity added = BaseThemeGenerator.addNonSalvageEntity(
396                                                        stableLocation.getStarSystem(), loc, Entities.INACTIVE_GATE, Factions.NEUTRAL);
397                                        
398                                        gateHauler.getMemoryWithoutUpdate().unset("$deploying");
399                                        gateHauler.addTag(Tags.NO_ENTITY_TOOLTIP);
400                                        Misc.fadeAndExpire(gateHauler, 10f);
401                                        Misc.fadeAndExpire(stableLocation, 10f);
402                                        endImmediately();
403                                        
404                                        if (added.entity != null) {
405                                                Misc.fadeIn(added.entity, 3f);
406                                        }
407                                        
408                                        
409                                }
410                        }
411                }
412        }
413
414        
415        protected void addDebrisField() {
416                if (stableLocation == null) return;
417                
418                DebrisFieldParams params = new DebrisFieldParams(
419                                400f, // field radius - should not go above 1000 for performance reasons
420                                -1f, // density, visual - affects number of debris pieces
421                                3f, // duration in days 
422                                0f); // days the field will keep generating glowing pieces
423                params.source = DebrisFieldSource.MIXED;
424                params.density = 1f;
425                params.baseSalvageXP = (long) 500; // base XP for scavenging in field
426                
427                SectorEntityToken debris = (CampaignTerrainAPI) Misc.addDebrisField(
428                                                                        stableLocation.getContainingLocation(), params, null);
429                
430                debris.setDiscoverable(null);
431                debris.setDiscoveryXP(null);
432                
433                debris.addDropValue(Drops.EXTENDED, 100000);
434                
435                debris.getLocation().set(stableLocation.getLocation());
436                if (stableLocation.getOrbit() != null) {
437                        debris.setOrbit(stableLocation.getOrbit().makeCopy());
438                }
439        }
440        
441        
442        
443        protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
444                
445                Color h = Misc.getHighlightColor();
446                Color g = Misc.getGrayColor();
447                float pad = 3f;
448                float opad = 10f;
449                
450                FactionAPI faction = getFactionForUIColors();
451                Color base = faction.getBaseUIColor();
452                Color dark = faction.getDarkUIColor();
453                
454                float initPad = pad;
455                if (mode == ListInfoMode.IN_DESC) initPad = opad;
456                
457                Color tc = getBulletColorForMode(mode);
458                
459                bullet(info);
460                boolean isUpdate = getListInfoParam() != null;
461                
462                if (isUpdate) {
463                        if (getListInfoParam() == GateHaulerAction.DEEP_SPACE_TRANSIT) {
464                                info.addPara("Entered open space", tc, initPad);
465                                String dStr = "days";
466                                if (transitDays == 1) dStr = "day";
467                                info.addPara("Estimated %s " + dStr + " to complete transit", initPad, tc, 
468                                                h, "" + transitDays);
469                                return;
470                        }
471                        if (getListInfoParam() == GateHaulerAction.INBOUND) {
472                                info.addPara("Arrived at " + destination.getNameWithLowercaseType(), tc, initPad);
473                                return;
474                        }
475                        if (getListInfoParam() == UPDATE_WITNESSED_ARRIVAL) {
476                                info.addPara("Witnessed the arrival of a Gate Hauler to a star system", tc, initPad);
477                                return;
478                        }
479                }
480                
481                if (mode == ListInfoMode.INTEL) {
482                        String locStr = gateHauler.getContainingLocation().getNameWithLowercaseTypeShort();
483                        if (gateHauler.getContainingLocation() != null && gateHauler.getContainingLocation().isDeepSpace()) {
484                                locStr = "deep space";
485                        } else if (gateHauler.getContainingLocation() != null) {
486                                locStr = gateHauler.getContainingLocation().getNameWithLowercaseTypeShort();
487                        }
488                        if (getPlugin().isInTransit() && action == GateHaulerAction.DEEP_SPACE_TRANSIT) {
489                                locStr = "transiting deep space";
490                        }
491                                        
492                        info.addPara("Location: " + locStr, tc, initPad);
493                        initPad = 0f;
494                        
495                        GateHaulerEntityPlugin plugin = getPlugin();
496                        if (!plugin.isActivated()) {
497                                info.addPara("Status: dormant", tc, initPad);
498                        } else if (plugin.isActivating()) {
499                                info.addPara("Status: activating", tc, initPad);
500                        } else if (action == null) {
501                                info.addPara("Status: operational", tc, initPad);
502                        } else if (action == GateHaulerAction.OUTBOUND) {
503                                info.addPara("Departing current location", tc, initPad);
504                                
505                                String dStr = "days";
506                                if (transitDays == 1) dStr = "day";
507                                info.addPara("Estimated %s " + dStr + " for transit", initPad, tc, 
508                                                h, "" + transitDays);
509                        } else if (action == GateHaulerAction.DEEP_SPACE_TRANSIT) {
510                                String dStr = "days";
511                                int daysRemaining = (int) Math.round(transitDays - elapsedDaysInAction);
512                                if (daysRemaining < 1) daysRemaining = 1;
513                                if (daysRemaining == 1) dStr = "day";
514                                info.addPara("Estimated %s " + dStr + " to complete transit", initPad, tc, 
515                                                h, "" + daysRemaining);
516                        } else if (action == GateHaulerAction.INBOUND) {
517                                info.addPara("Arriving at " + destination.getNameWithLowercaseType(), tc, initPad);
518                        }
519                }
520                
521//              if (GateEntityPlugin.isScanned(gateHauler)) {
522//                      info.addPara("Scanned", tc, initPad);
523//                      initPad = 0f;
524//              }
525                
526                unindent(info);
527        }
528        
529        
530        @Override
531        public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
532                String pre = "";
533                String post = "";
534//              if (mode == ListInfoMode.MESSAGES && !getPlugin().isActivated()) {
535//                      pre = "Discovered: ";
536//              }
537                
538                Color c = getTitleColor(mode);
539                info.addPara(pre + getName() + post, c, 0f);
540                addBulletPoints(info, mode);
541        }
542        
543        @Override
544        public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
545                Color h = Misc.getHighlightColor();
546                Color g = Misc.getGrayColor();
547                Color tc = Misc.getTextColor();
548                float pad = 3f;
549                float opad = 10f;
550                
551                if (gateHauler.getCustomInteractionDialogImageVisual() != null) {
552                        info.addImage(gateHauler.getCustomInteractionDialogImageVisual().getSpriteName(), width, opad);
553                }
554                
555                Description desc = Global.getSettings().getDescription(gateHauler.getCustomDescriptionId(), Type.CUSTOM);
556                info.addPara(desc.getText1(), opad);
557                
558                FactionAPI faction = getFactionForUIColors();
559                Color base = faction.getBaseUIColor();
560                Color dark = faction.getDarkUIColor();
561                
562                info.addSectionHeading("Status", base, dark, Alignment.MID, opad);
563                
564                GateHaulerEntityPlugin plugin = getPlugin();
565                if (!plugin.isActivated()) {
566                        GateHaulerCMD cmd = new GateHaulerCMD();
567                        info.addPara("The gate hauler is dormant, its systems shut down to conserve power.", opad);
568                        info.showCost("Resources required to activate:", false, base, dark, opad, cmd.getResources(), cmd.getQuantities());
569                } else if (plugin.isActivating()) {
570                        info.addPara("The gate hauler is in the process of reactivating its systems and should be operational "
571                                        + "within a day.", opad);
572                } else if (action == null) {
573                        info.addPara("The gate hauler is operational and ready to travel to another star system or "
574                                        + "deploy its gate at a stable location.", opad);
575                } else if (action == GateHaulerAction.OUTBOUND) {
576                        info.addPara("The gate hauler is outbound from its current location, "
577                                        + "heading for open space and accelerating.", opad);
578                        
579                        String dStr = "days";
580                        if (transitDays == 1) dStr = "day";
581                        info.addPara("Once it's in open space, it's estimated that it will take %s " + dStr + " until it arrives "
582                                        + "to its destination, the " + destination.getNameWithLowercaseTypeShort() + ". On arrival, "
583                                        + "it will take some time to decelerate and attain a parking orbit.", opad, 
584                                        h, "" + transitDays);
585                } else if (action == GateHaulerAction.DEEP_SPACE_TRANSIT) {
586                        String dStr = "days";
587                        int daysRemaining = (int) Math.round(transitDays - elapsedDaysInAction);
588                        if (daysRemaining < 1) daysRemaining = 1;
589                        if (daysRemaining == 1) dStr = "day";
590                        info.addPara("The gate hauler is in transit, in deep space. It's estimated that it will take %s " + dStr + " until it arrives "
591                                        + "to its destination, the " + destination.getNameWithLowercaseTypeShort() + ". On arrival, "
592                                        + "it will take some time to decelerate and attain a parking orbit.", opad,
593                                        h, "" + daysRemaining);
594                } else if (action == GateHaulerAction.INBOUND) {
595                        info.addPara("The gate hauler has arrived to the " + destination.getNameWithLowercaseTypeShort() + " "
596                                        + "and is decelerating in order to attain a parking orbit.", opad);
597                } else if (action == GateHaulerAction.DEPLOYING) {
598                        info.addPara("The gate hauler has been given an order to deploy its gate.", opad);
599                }
600                        
601                
602                addLogTimestamp(info, tc, opad);
603                
604                //addBulletPoints(info, ListInfoMode.IN_DESC);
605                
606        }
607        
608        @Override
609        public String getIcon() {
610                return Global.getSettings().getSpriteName("intel", "gate_hauler");
611        }
612        
613        @Override
614        public Set<String> getIntelTags(SectorMapAPI map) {
615                Set<String> tags = super.getIntelTags(map);
616                tags.add(Tags.INTEL_GATES);
617                tags.add(Tags.INTEL_FLEET_LOG);
618                //tags.add(Tags.INTEL_EXPLORATION);
619                return tags;
620        }
621        
622        public String getSortString() {
623                if (getTagsForSort().contains(Tags.INTEL_FLEET_LOG) || getTagsForSort().contains(Tags.INTEL_EXPLORATION)) {
624                        return getSortStringNewestFirst();
625                }
626                return "AAA";
627        }
628        
629        
630        public String getName() {
631                return "Gate Hauler";
632        }
633        
634        @Override
635        public FactionAPI getFactionForUIColors() {
636                return gateHauler.getFaction();
637                //return super.getFactionForUIColors();
638        }
639
640        public String getSmallDescriptionTitle() {
641                //return getName() + " - " + gateHauler.getContainingLocation().getNameWithTypeShort();
642                return getName();
643        }
644
645        @Override
646        public SectorEntityToken getMapLocation(SectorMapAPI map) {
647                if (!gateHauler.isAlive() && destination != null) {
648                        return destination.getCenter();
649                }
650                return gateHauler;
651        }
652        
653        @Override
654        public String getCommMessageSound() {
655                return "ui_discovered_entity";
656        }
657
658        public SectorEntityToken getGateHauler() {
659                return gateHauler;
660        }
661
662        @Override
663        public List<ArrowData> getArrowData(SectorMapAPI map) {
664                if (destination == null || action == null) {
665                        return null;
666                }
667                
668                boolean showArrow = action == GateHaulerAction.OUTBOUND || action == GateHaulerAction.DEEP_SPACE_TRANSIT;
669                if (!showArrow) return null;
670                
671                if (gateHauler.getContainingLocation() == destination) {
672                        return null;
673                }
674                
675                List<ArrowData> result = new ArrayList<ArrowData>();
676                
677                ArrowData arrow = new ArrowData(gateHauler, destination.getCenter());
678                arrow.color = getFactionForUIColors().getBaseUIColor();
679                arrow.width = 20f;
680                result.add(arrow);
681                
682                return result;
683        }
684
685        public GateHaulerAction getAction() {
686                return action;
687        }
688
689}
690
691
692
693
694
695
696