001package com.fs.starfarer.api.impl.campaign.missions.cb; 002 003import java.awt.Color; 004import java.util.ArrayList; 005import java.util.List; 006import java.util.Random; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.campaign.CampaignFleetAPI; 010import com.fs.starfarer.api.campaign.FactionAPI; 011import com.fs.starfarer.api.campaign.StarSystemAPI; 012import com.fs.starfarer.api.campaign.TextPanelAPI; 013import com.fs.starfarer.api.campaign.econ.MarketAPI; 014import com.fs.starfarer.api.characters.PersonAPI; 015import com.fs.starfarer.api.fleet.FleetMemberAPI; 016import com.fs.starfarer.api.fleet.FleetMemberType; 017import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepRewards; 018import com.fs.starfarer.api.impl.campaign.DebugFlags; 019import com.fs.starfarer.api.impl.campaign.missions.hub.BaseHubMission.Abortable; 020import com.fs.starfarer.api.impl.campaign.missions.hub.BaseHubMission.EntityAdded; 021import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithBarEvent; 022import com.fs.starfarer.api.ui.TooltipMakerAPI; 023import com.fs.starfarer.api.util.Misc; 024 025public class BaseCustomBountyCreator implements CustomBountyCreator { 026 public static float DEFAULT_FREQUENCY = 10f; 027 028 public float getBountyDays() { 029 return CBStats.DEFAULT_DAYS; 030 } 031 032 public void addTargetLocationAndDescriptionBulletPoint(TooltipMakerAPI info, 033 Color tc, float pad, HubMissionWithBarEvent mission, 034 CustomBountyData data) { 035 if (data.system != null) { 036 info.addPara("Target is in the " + data.system.getNameWithLowercaseTypeShort() + "", tc, pad); 037 } 038 } 039 040 public void addTargetLocationAndDescription(TooltipMakerAPI info, float width, float height, HubMissionWithBarEvent mission, CustomBountyData data) { 041 float opad = 10f; 042 float pad = 3f; 043 Color h = Misc.getHighlightColor(); 044 if (data.system != null) { 045 info.addPara("The target is located in the " + data.system.getNameWithLowercaseType() + ".", opad); 046 } 047 } 048 049 public void addIntelAssessment(TextPanelAPI text, HubMissionWithBarEvent mission, CustomBountyData data) { 050 float opad = 10f; 051 List<FleetMemberAPI> list = new ArrayList<FleetMemberAPI>(); 052 List<FleetMemberAPI> members = data.fleet.getFleetData().getMembersListCopy(); 053 int max = 7; 054 int cols = 7; 055 float iconSize = 440 / cols; 056 Color h = Misc.getHighlightColor(); 057 058 059 for (FleetMemberAPI member : members) { 060 if (list.size() >= max) break; 061 062 if (member.isFighterWing()) continue; 063 064 FleetMemberAPI copy = Global.getFactory().createFleetMember(FleetMemberType.SHIP, member.getVariant()); 065 if (member.isFlagship()) { 066 copy.setCaptain(data.fleet.getCommander()); 067 } 068 list.add(copy); 069 } 070 071 if (!list.isEmpty()) { 072 TooltipMakerAPI info = text.beginTooltip(); 073 info.setParaSmallInsignia(); 074 info.addPara(Misc.ucFirst(mission.getPerson().getHeOrShe()) + " taps a data pad, and " + 075 "an intel assessment shows up on your tripad.", 0f); 076 info.addShipList(cols, 1, iconSize, data.fleet.getFaction().getBaseUIColor(), list, opad); 077 078 int num = members.size() - list.size(); 079 080 if (num < 5) num = 0; 081 else if (num < 10) num = 5; 082 else if (num < 20) num = 10; 083 else num = 20; 084 085 if (num > 1) { 086 info.addPara("The assessment notes the fleet may contain upwards of %s other ships" + 087 " of lesser significance.", opad, h, "" + num); 088 } else if (num > 0) { 089 info.addPara("The assessment notes the fleet may contain several other ships" + 090 " of lesser significance.", opad); 091 } else { 092 info.addPara("It appears to contain complete information about the scope of the assignment.", opad); 093 } 094 text.addTooltip(); 095 } 096 return; 097 } 098 099 public void addFleetDescription(TooltipMakerAPI info, float width, float height, HubMissionWithBarEvent mission, CustomBountyData data) { 100// if (hideoutLocation != null) { 101// SectorEntityToken fake = hideoutLocation.getContainingLocation().createToken(0, 0); 102// fake.setOrbit(Global.getFactory().createCircularOrbit(hideoutLocation, 0, 1000, 100)); 103// 104// String loc = BreadcrumbSpecial.getLocatedString(fake); 105// loc = loc.replaceAll("orbiting", "hiding out near"); 106// loc = loc.replaceAll("located in", "hiding out in"); 107// String sheIs = "She is"; 108// if (person.getGender() == Gender.MALE) sheIs = "He is"; 109// info.addPara(sheIs + " rumored to be " + loc + ".", opad); 110// } 111 112 PersonAPI person = data.fleet.getCommander(); 113 FactionAPI faction = person.getFaction(); 114 int cols = 7; 115 float iconSize = width / cols; 116 float opad = 10f; 117 Color h = Misc.getHighlightColor(); 118 119 if (DebugFlags.PERSON_BOUNTY_DEBUG_INFO) { 120 121 } 122 boolean deflate = false; 123 if (!data.fleet.isInflated()) { 124 data.fleet.inflateIfNeeded(); 125 deflate = true; 126 } 127 128 List<FleetMemberAPI> list = new ArrayList<FleetMemberAPI>(); 129 Random random = new Random(person.getNameString().hashCode() * 170000); 130 131 List<FleetMemberAPI> members = data.fleet.getFleetData().getMembersListCopy(); 132 int max = 7; 133 for (FleetMemberAPI member : members) { 134 if (list.size() >= max) break; 135 136 if (member.isFighterWing()) continue; 137 138// float prob = (float) member.getFleetPointCost() / 20f; 139// prob += (float) max / (float) members.size(); 140// if (member.isFlagship()) prob = 1f; 141// //if (members.size() <= max) prob = 1f; 142// 143// if (random.nextFloat() > prob) continue; 144 145 FleetMemberAPI copy = Global.getFactory().createFleetMember(FleetMemberType.SHIP, member.getVariant()); 146 if (member.isFlagship()) { 147 copy.setCaptain(person); 148 } 149 list.add(copy); 150 } 151 152 if (!list.isEmpty()) { 153 info.addPara("The bounty posting contains partial intel on some of the ships in the target fleet.", opad); 154 info.addShipList(cols, 1, iconSize, faction.getBaseUIColor(), list, opad); 155 156 int num = members.size() - list.size(); 157 //num = Math.round((float)num * (1f + random.nextFloat() * 0.5f)); 158 159 if (num < 5) num = 0; 160 else if (num < 10) num = 5; 161 else if (num < 20) num = 10; 162 else num = 20; 163 164 if (num > 1) { 165 info.addPara("The intel assessment notes the fleet may contain upwards of %s other ships" + 166 " of lesser significance.", opad, h, "" + num); 167 } else if (num > 0) { 168 info.addPara("The intel assessment notes the fleet may contain several other ships" + 169 " of lesser significance.", opad); 170 } 171 } 172 173 if (deflate) { 174 data.fleet.deflate(); 175 } 176 } 177 178 public float getFrequency(HubMissionWithBarEvent mission, int difficulty) { 179 PersonAPI person = mission.getPerson(); 180 if (!isRepeatableGlobally() && getNumCompletedGlobal() > 0) return 0f; 181 if (!isRepeatablePerPerson() && getNumCompletedForPerson(person) > 0) return 0f; 182 183 float mult = 1f; 184 if (isReduceFrequencyBasedOnNumberOfCompletions()) { 185 mult = 1f / (1f + (float) getNumCompletedGlobal() * 0.5f); 186 } 187 return DEFAULT_FREQUENCY * mult; 188 } 189 190 public String getNumCompletedPerPersonKey() { 191 return "$" + getId() + "_numCompleted"; 192 } 193 public String getNumCompletedGlobalKey() { 194 return "$" + getId() + "_numCompleted"; 195 } 196 197 198 protected boolean isRepeatablePerPerson() { 199 return true; 200 } 201 protected boolean isRepeatableGlobally() { 202 return true; 203 } 204 protected boolean isReduceFrequencyBasedOnNumberOfCompletions() { 205 return false; 206 } 207 208 public String getId() { 209 return getClass().getSimpleName(); 210 } 211 212 public boolean systemMatchesRequirement(StarSystemAPI system) { 213 return true; 214 } 215 216 public float getRepFaction() { 217 return RepRewards.TINY; 218 } 219 220 public float getRepPerson() { 221 return RepRewards.MEDIUM; 222 } 223 224 protected static Object STAGE = new Object(); 225 protected void beginFleet(HubMissionWithBarEvent mission, CustomBountyData data) { 226 mission.beginStageTrigger(STAGE); 227 } 228 229 protected CampaignFleetAPI createFleet(HubMissionWithBarEvent mission, CustomBountyData data) { 230 mission.triggerMakeFleetIgnoreOtherFleetsExceptPlayer(); 231 mission.triggerFleetOnlyEngageableWhenVisibleToPlayer(); 232 mission.endTrigger(); 233 234 List<Abortable> before = new ArrayList<Abortable>(mission.getChanges()); 235 List<CampaignFleetAPI> fleets = mission.runStageTriggersReturnFleets(STAGE); 236 if (fleets.isEmpty()) return null; 237 238 CampaignFleetAPI fleet = fleets.get(0); 239 mission.getChanges().add(new EntityAdded(fleet)); // so it's removed when the mission is abort()ed 240 241 for (Abortable curr : mission.getChanges()) { 242 if (!before.contains(curr)) { 243 data.abortWhenOtherVersionAccepted.add(curr); 244 } 245 } 246 return fleet; 247 } 248 249 public void notifyCompleted(HubMissionWithBarEvent mission, CustomBountyData data) { 250 PersonAPI person = mission.getPerson(); 251 252 String key = getNumCompletedGlobalKey(); 253 Integer num = (Integer) Global.getSector().getMemoryWithoutUpdate().get(key); 254 if (num == null) num = 0; 255 num++; 256 Global.getSector().getMemoryWithoutUpdate().set(key, num); 257 258 key = getNumCompletedPerPersonKey(); 259 num = (Integer) person.getMemoryWithoutUpdate().get(key); 260 if (num == null) num = 0; 261 num++; 262 person.getMemoryWithoutUpdate().set(key, num); 263 } 264 265 public void notifyFailed(HubMissionWithBarEvent mission, CustomBountyData data) { 266 267 } 268 269 public int getNumCompletedForPerson(PersonAPI person) { 270 String key = getNumCompletedPerPersonKey(); 271 Integer num = (Integer) person.getMemoryWithoutUpdate().get(key); 272 if (num == null) num = 0; 273 return num; 274 } 275 276 public int getNumCompletedGlobal() { 277 String key = getNumCompletedGlobalKey(); 278 Integer num = (Integer) Global.getSector().getMemoryWithoutUpdate().get(key); 279 if (num == null) num = 0; 280 return num; 281 } 282 283 284 public int getMinDifficulty() { 285 return MIN_DIFFICULTY; 286 } 287 288 public int getMaxDifficulty() { 289 return MAX_DIFFICULTY; 290 } 291 292 public CustomBountyData createBounty(MarketAPI createdAt, HubMissionWithBarEvent mission, int difficulty, Object bountyStage) { 293 return null; 294 } 295 296 public void notifyAccepted(MarketAPI createdAt, HubMissionWithBarEvent mission, CustomBountyData data) { 297 298 } 299 300 public StarSystemAPI getSystemWithNoTimeLimit(CustomBountyData data) { 301 return data.system; 302 } 303 304 public String getBaseBountyName(HubMissionWithBarEvent mission, CustomBountyData data) { 305 return "Bounty"; 306 } 307 308 public String getBountyNamePostfix(HubMissionWithBarEvent mission, CustomBountyData data) { 309 return null; 310 } 311 312 public void setRepChangesBasedOnDifficulty(CustomBountyData data, int difficulty) { 313 if (difficulty <= 3) { 314 data.repPerson = RepRewards.SMALL; 315 data.repFaction = RepRewards.TINY; 316 } else if (difficulty <= 7) { 317 data.repPerson = RepRewards.MEDIUM; 318 data.repFaction = RepRewards.SMALL; 319 } else { 320 data.repPerson = RepRewards.HIGH; 321 data.repFaction = RepRewards.SMALL; 322 } 323 } 324 325 public void updateInteractionData(HubMissionWithBarEvent mission, CustomBountyData data) { 326 327 } 328 public String getIconName() { 329 return null; 330 } 331 332} 333 334 335 336