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