001package com.fs.starfarer.api.impl.campaign.rulecmd;
002
003import java.util.List;
004import java.util.Map;
005
006import org.lwjgl.util.vector.Vector2f;
007
008import com.fs.starfarer.api.EveryFrameScript;
009import com.fs.starfarer.api.Global;
010import com.fs.starfarer.api.Script;
011import com.fs.starfarer.api.campaign.BaseCampaignEventListenerAndScript;
012import com.fs.starfarer.api.campaign.BattleAPI;
013import com.fs.starfarer.api.campaign.CampaignClockAPI;
014import com.fs.starfarer.api.campaign.CampaignFleetAPI;
015import com.fs.starfarer.api.campaign.CampaignProgressIndicatorAPI;
016import com.fs.starfarer.api.campaign.InteractionDialogAPI;
017import com.fs.starfarer.api.campaign.SectorEntityToken;
018import com.fs.starfarer.api.campaign.rules.MemoryAPI;
019import com.fs.starfarer.api.impl.campaign.LeashScript;
020import com.fs.starfarer.api.util.RuleException;
021import com.fs.starfarer.api.util.Misc.Token;
022import com.fs.starfarer.api.util.Misc.VarAndMemory;
023
024
025public class Wait extends BaseCommandPlugin {
026        private EveryFrameScript waitScript;
027        private LeashScript leash;
028        private CampaignProgressIndicatorAPI indicator;
029        private VarAndMemory handle;
030        private VarAndMemory finished;
031        private VarAndMemory interrupted;
032        private VarAndMemory inProgress;
033        
034        //Wait $handle duration $finished $interrupted $inProgress $text
035        public boolean execute(String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
036                if (params.size() != 6) {
037                        throw new RuleException("Wait usage: Wait $handle duration $finished $interrupted $inProgress <text>");
038                }
039                
040                handle = params.get(0).getVarNameAndMemory(memoryMap);
041                final float durationDays = Float.parseFloat(params.get(1).string);
042                finished = params.get(2).getVarNameAndMemory(memoryMap);
043                interrupted = params.get(3).getVarNameAndMemory(memoryMap);
044                inProgress = params.get(4).getVarNameAndMemory(memoryMap);
045                
046                String text = "Waiting";
047                if (params.size() >= 5) {
048                        text = params.get(5).getString(memoryMap);
049                }
050                
051                //Global.getSoundPlayer().playUISound("ui_wait_start", 1, 1);
052                
053                final SectorEntityToken target = dialog.getInteractionTarget();
054                
055                final CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
056                playerFleet.setInteractionTarget(null);
057                Vector2f offset = Vector2f.sub(playerFleet.getLocation(), target.getLocation(), new Vector2f());
058//              float dir = Misc.getAngleInDegrees(offset);
059//              offset = Misc.getUnitVectorAtDegreeAngle(dir)
060                float len = offset.length();
061                float radSum = playerFleet.getRadius() + target.getRadius() - 1f;
062                if (len > 0) {
063                        offset.scale(radSum / len);
064                } else {
065                        offset.set(radSum, 0);
066                }
067                
068                indicator = Global.getFactory().createProgressIndicator(text, target, durationDays);
069                target.getContainingLocation().addEntity(indicator);
070                
071                
072                waitScript = new BaseCampaignEventListenerAndScript(durationDays + 0.1f) {
073                        private float elapsedDays = 0f;
074                        private boolean done = false;
075                        private boolean battleOccured = false;
076                        private boolean interactedWithSomethingElse = false;
077                        public boolean runWhilePaused() {
078                                return false;
079                        }
080                        public boolean isDone() {
081                                return done;
082                        }
083                        public void advance(float amount) {
084                                CampaignClockAPI clock = Global.getSector().getClock();
085                                
086                                Global.getSector().getCampaignUI().setDisallowPlayerInteractionsForOneFrame();
087                                
088                                float days = clock.convertToDays(amount);
089                                elapsedDays += days;
090                                
091                                inProgress.memory.set(inProgress.name, true);
092                                inProgress.memory.expire(inProgress.name, 0.1f);
093                                
094//                              float sinceLastBattle = clock.getElapsedDaysSince(Global.getSector().getLastPlayerBattleTimestamp());
095//                              if (sinceLastBattle <= elapsedDays) {
096                                if (battleOccured || interactedWithSomethingElse) {
097                                        done = true;
098                                        interrupted.memory.set(interrupted.name, true);
099                                        interrupted.memory.expire(interrupted.name, 2f);
100                                        handle.memory.unset(handle.name);
101                                        indicator.interrupt();
102                                        Global.getSector().removeScript(leash);
103                                        
104                                        Global.getSoundPlayer().playUISound("ui_wait_interrupt", 1, 1);
105                                } else if (elapsedDays >= durationDays && !Global.getSector().getCampaignUI().isShowingDialog()) {
106                                        done = true;
107                                        finished.memory.set(finished.name, true);
108                                        finished.memory.expire(finished.name, 0f);
109                                        
110                                        inProgress.memory.unset(inProgress.name);
111                                        handle.memory.unset(handle.name);
112                                        
113                                        Global.getSector().removeScript(leash);
114                                        indicator.getContainingLocation().removeEntity(indicator);
115                                        Global.getSector().getCampaignUI().showInteractionDialog(target);
116                                        Global.getSoundPlayer().playUISound("ui_wait_finish", 1, 1);
117                                }
118                        }
119                        @Override
120                        public void reportBattleOccurred(CampaignFleetAPI primaryWinner, BattleAPI battle) {
121                                if (battle.getSnapshotSideFor(playerFleet) != null || 
122                                                (target instanceof CampaignFleetAPI && battle.getSnapshotSideFor((CampaignFleetAPI)target) != null)) {
123                                        battleOccured = true;
124                                }
125                        }
126                        @Override
127                        public void reportShownInteractionDialog(InteractionDialogAPI dialog) {
128                                interactedWithSomethingElse |= dialog.getInteractionTarget() != target;
129                        }
130                        @Override
131                        public void reportFleetDespawned(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
132                                if (fleet == playerFleet || fleet == target) {
133                                        battleOccured = true;
134                                }
135                        }
136                        
137                };
138                
139                leash = new LeashScript(playerFleet, 50, target, offset, new Script() {
140                        public void run() {
141                                interrupted.memory.set(interrupted.name, true);
142                                interrupted.memory.expire(interrupted.name, 2f);
143//                              memory.set(keyInterrupted, true);
144//                              memory.expire(keyInterrupted, 2f);
145                                //indicator.getContainingLocation().removeEntity(indicator);
146                                handle.memory.unset(handle.name);
147                                indicator.interrupt();
148                                Global.getSector().removeScript(waitScript);
149                                Global.getSoundPlayer().playUISound("ui_wait_interrupt", 1, 1);
150                        }
151                });
152                Global.getSector().addScript(leash);
153                
154                handle.memory.set(handle.name, this);
155                
156                Global.getSector().addScript(waitScript);
157                
158                Global.getSector().setPaused(false);
159                dialog.dismiss();
160                
161                return true;
162        }
163
164        public EveryFrameScript getWaitScript() {
165                return waitScript;
166        }
167
168        public LeashScript getLeashScript() {
169                return leash;
170        }
171
172        public CampaignProgressIndicatorAPI getIndicator() {
173                return indicator;
174        }
175
176        public VarAndMemory getHandle() {
177                return handle;
178        }
179
180        public VarAndMemory getFinished() {
181                return finished;
182        }
183
184        public VarAndMemory getInProgress() {
185                return inProgress;
186        }
187
188        public VarAndMemory getInterrupted() {
189                return interrupted;
190        }
191
192}
193
194
195
196