001package com.fs.starfarer.api.impl.campaign; 002 003import java.util.List; 004 005import com.fs.starfarer.api.EveryFrameScript; 006import com.fs.starfarer.api.Global; 007import com.fs.starfarer.api.campaign.CampaignFleetAPI; 008import com.fs.starfarer.api.campaign.FleetAssignment; 009import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel; 010import com.fs.starfarer.api.campaign.StarSystemAPI; 011import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI; 012import com.fs.starfarer.api.impl.campaign.HassleNPCScript.HassleParams; 013import com.fs.starfarer.api.impl.campaign.ids.Factions; 014import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 015import com.fs.starfarer.api.util.IntervalUtil; 016import com.fs.starfarer.api.util.Misc; 017import com.fs.starfarer.api.util.Misc.FleetFilter; 018import com.fs.starfarer.api.util.WeightedRandomPicker; 019 020public class NPCHassler implements EveryFrameScript { 021 022 protected CampaignFleetAPI fleet; 023 protected HassleParams params; 024 protected StarSystemAPI restrictTo; 025 protected IntervalUtil interval = new IntervalUtil(0.1f, 0.3f); 026 027 public NPCHassler(CampaignFleetAPI fleet) { 028 this(fleet, new HassleParams(), null); 029 } 030 public NPCHassler(CampaignFleetAPI fleet, StarSystemAPI restrictTo) { 031 this(fleet, new HassleParams(), restrictTo); 032 } 033 public NPCHassler(CampaignFleetAPI fleet, HassleParams params, StarSystemAPI restrictTo) { 034 this.fleet = fleet; 035 this.params = params; 036 this.restrictTo = restrictTo; 037 } 038 039 public HassleParams getParams() { 040 return params; 041 } 042 043 public void advance(float amount) { 044// if (!params.timeoutKey.startsWith("$")) { 045// params.timeoutKey = "$" + params.timeoutKey; 046// } 047 048 float days = Misc.getDays(amount); 049 interval.advance(days); 050 if (!interval.intervalElapsed()) return; 051 052 if (restrictTo != null && fleet.getContainingLocation() != restrictTo) return; 053 if (Global.getSector().getMemoryWithoutUpdate().contains(params.timeoutKey)) return; 054 if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.FLEET_SPECIAL_ACTION)) return; 055 056 if (fleet.getBattle() != null) return; 057 if (fleet.getAI() != null && (fleet.getAI().isFleeing() || fleet.getAI().isMaintainingContact())) { 058 return; 059 } 060 if (fleet.getCurrentAssignment() != null && 061 fleet.getCurrentAssignment().getAssignment() == FleetAssignment.ORBIT_PASSIVE) { 062 return; 063 } 064 065 066 List<CampaignFleetAPI> targets = Misc.findNearbyFleets(fleet, 1000f, new FleetFilter() { 067 public boolean accept(CampaignFleetAPI other) { 068 return isTargetAllowed(other); 069 } 070 }); 071 072 WeightedRandomPicker<CampaignFleetAPI> picker = new WeightedRandomPicker<CampaignFleetAPI>(); 073 picker.addAll(targets); 074 CampaignFleetAPI target = picker.pick(); 075 if (target != null) { 076 fleet.getContainingLocation().addScript(new HassleNPCScript(fleet, target)); 077 float globalTimeout = params.minGlobalTimeout + 078 (params.maxGlobalTimeout - params.minGlobalTimeout) * (float) Math.random(); 079 Global.getSector().getMemoryWithoutUpdate().set(params.timeoutKey, true, globalTimeout); 080 float targetTimeout = params.minTargetTimeout + 081 (params.maxTargetTimeout - params.minTargetTimeout) * (float) Math.random(); 082 target.getMemoryWithoutUpdate().set(params.timeoutKey, true, targetTimeout); 083 } 084 } 085 086 protected boolean isTargetAllowed(CampaignFleetAPI target) { 087 if (target.isPlayerFleet() || target.getAI() == null) return false; 088 if (target.isHostileTo(fleet)) return false; 089 if (target.isStationMode()) return false; 090 if (target.getBattle() != null) return false; 091 092 if (target.getFaction() == fleet.getFaction()) return false; 093 if (target.getMemoryWithoutUpdate().contains(params.timeoutKey)) return false; 094 095 if (target.getAI() instanceof ModularFleetAIAPI) { 096 ModularFleetAIAPI ai = (ModularFleetAIAPI) target.getAI(); 097 if (ai.isFleeing() || ai.isMaintainingContact()) return false; 098 if (fleet.getInteractionTarget() instanceof CampaignFleetAPI) return false; 099 } 100 101 if (!isTargetRightTypeOfFleet(target)) return false; 102 103 VisibilityLevel vis = target.getVisibilityLevelTo(fleet); 104 if (vis == VisibilityLevel.NONE) return false; 105 return true; 106 } 107 108 /** 109 * This is called in addition to the standard faction/hostility/visibility/etc checks in isTargetAllowed(). 110 * @param target 111 * @return 112 */ 113 protected boolean isTargetRightTypeOfFleet(CampaignFleetAPI target) { 114 if (Misc.isTrader(target)) return true; 115 if (Misc.isPirate(target)) return false; 116 if (Misc.isPatrol(target) && !target.getFaction().isPlayerFaction()) return false; 117 if (Misc.isWarFleet(target)) return false; 118 if (target.getFaction().getCustomBoolean(Factions.CUSTOM_DECENTRALIZED)) return true; 119 return false; 120 } 121 122 123 public boolean isDone() { 124 return false; 125 } 126 127 public boolean runWhilePaused() { 128 return false; 129 } 130}