001package com.fs.starfarer.api.impl.combat.threat;
002
003import com.fs.starfarer.api.EveryFrameScript;
004import com.fs.starfarer.api.Global;
005import com.fs.starfarer.api.campaign.CampaignFleetAPI;
006import com.fs.starfarer.api.campaign.FleetAssignment;
007import com.fs.starfarer.api.campaign.SectorEntityToken;
008import com.fs.starfarer.api.campaign.StarSystemAPI;
009import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
010import com.fs.starfarer.api.impl.campaign.fleets.DisposableFleetManager;
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.ids.Stats;
014import com.fs.starfarer.api.util.Misc;
015
016public class ThreatFleetBehaviorScript implements EveryFrameScript {
017
018        public static float MIN_SECONDS_TO_PURSUE_AFTER_SEEN_BY_PLAYER = 30f;
019        public static float MAX_SECONDS_TO_PURSUE_AFTER_SEEN_BY_PLAYER = 120f;
020        protected StarSystemAPI system;
021        protected CampaignFleetAPI fleet;
022        protected DisposableFleetManager manager;
023        
024        protected float seenByPlayerTimeout = 0f;
025        
026        
027        public ThreatFleetBehaviorScript(CampaignFleetAPI fleet, StarSystemAPI system) {
028                this.fleet = fleet;
029                this.system = system;
030                
031                pickNext();
032        }
033        
034        protected void pickNext() {
035                float days = 1f + 1f * (float) Math.random();
036                SectorEntityToken target = system.createToken(0, 0);
037                float distFromTarget = Misc.getDistance(fleet, target);
038                if (distFromTarget < 7000f) target = null;
039                
040                CampaignFleetAPI player = Global.getSector().getPlayerFleet();
041                if (player != null) {
042                        float distFromPlayer = Misc.getDistance(fleet, player);
043                        if (distFromPlayer < 4000f) target = null;
044                }
045                
046                fleet.addAssignment(FleetAssignment.PATROL_SYSTEM, target, days, "cruising");
047        }
048
049        public void advance(float amount) {
050                if (fleet.getCurrentAssignment() == null) {
051                        pickNext();
052                }
053                
054                seenByPlayerTimeout -= amount;
055
056                CampaignFleetAPI player = Global.getSector().getPlayerFleet();
057                if (player == null) return;
058                
059                boolean playerHasSensorMods = Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(
060                                                                        DisposableThreatFleetManager.SENSOR_MODS_KEY);
061                //playerHasSensorMods = true;
062                if (playerHasSensorMods) {
063                        fleet.getStats().getDynamic().getStat(Stats.DETECTED_BY_PLAYER_RANGE_MULT).modifyMult(
064                                        DisposableThreatFleetManager.THREAT_DETECTED_RANGE_MULT_ID, 
065                                        DisposableThreatFleetManager.ONSLAUGHT_MKI_SENSOR_MODIFICATIONS_RANGE_MULT);
066                } else {
067                        fleet.getStats().getDynamic().getStat(Stats.DETECTED_BY_PLAYER_RANGE_MULT).unmodifyMult(
068                                        DisposableThreatFleetManager.THREAT_DETECTED_RANGE_MULT_ID);
069                }
070                
071                
072                boolean visibleToPlayer = fleet.isVisibleToPlayerFleet() && player.isVisibleToSensorsOf(fleet);
073                if (!Global.getSettings().isCampaignSensorsOn() && fleet.isInCurrentLocation()) {
074                        float dist = Misc.getDistance(fleet, player);
075                        dist -= fleet.getRadius() + player.getRadius();
076                        if (playerHasSensorMods) {
077                                dist /= DisposableThreatFleetManager.ONSLAUGHT_MKI_SENSOR_MODIFICATIONS_RANGE_MULT;
078                        }
079                        boolean asb = player.getAbility(Abilities.SENSOR_BURST) != null &&
080                                        player.getAbility(Abilities.SENSOR_BURST).isActive();
081                        visibleToPlayer = dist < 150f || asb && dist < 500f; 
082                }
083                
084                
085                if (visibleToPlayer) {
086                        setSeenByPlayer();
087                }
088                if (seenByPlayerTimeout > 0f) {
089                        visibleToPlayer = true;
090                }
091                //visibleToPlayer = false;
092                
093                if (!visibleToPlayer) {
094                        if (fleet.getAI() instanceof ModularFleetAIAPI) {
095                                ModularFleetAIAPI ai = (ModularFleetAIAPI) fleet.getAI();
096                                for (int i = 0; i < 3; i++) {
097                                        ai.getNavModule().avoidEntity(player, 3000f, 5000f, 0.2f);
098                                }
099                                
100                                fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_HOSTILE, false);
101                                fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_NON_HOSTILE, true);
102                        }
103                } else {
104                        fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_HOSTILE, true);
105                        fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_NON_HOSTILE, false);
106                }
107        }
108        
109        public void setSeenByPlayer() {
110                seenByPlayerTimeout = MIN_SECONDS_TO_PURSUE_AFTER_SEEN_BY_PLAYER +
111                                (MAX_SECONDS_TO_PURSUE_AFTER_SEEN_BY_PLAYER - MIN_SECONDS_TO_PURSUE_AFTER_SEEN_BY_PLAYER) * (float) Math.random();
112        }
113
114        public boolean isDone() {
115                return false;
116        }
117
118        public boolean runWhilePaused() {
119                return false;
120        }
121        
122
123}
124
125
126
127
128
129
130
131
132
133