001package com.fs.starfarer.api.impl.campaign.intel.events; 002 003import java.util.ArrayList; 004import java.util.Collections; 005import java.util.List; 006import java.util.Random; 007import java.util.Set; 008 009import java.awt.Color; 010 011import com.fs.starfarer.api.Global; 012import com.fs.starfarer.api.campaign.InteractionDialogAPI; 013import com.fs.starfarer.api.campaign.TextPanelAPI; 014import com.fs.starfarer.api.campaign.listeners.EconomyTickListener; 015import com.fs.starfarer.api.impl.campaign.ids.Tags; 016import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin; 017import com.fs.starfarer.api.ui.Alignment; 018import com.fs.starfarer.api.ui.CustomPanelAPI; 019import com.fs.starfarer.api.ui.EventProgressBarAPI; 020import com.fs.starfarer.api.ui.SectorMapAPI; 021import com.fs.starfarer.api.ui.TooltipMakerAPI; 022import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator; 023import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipLocation; 024import com.fs.starfarer.api.ui.UIComponentAPI; 025import com.fs.starfarer.api.util.Misc; 026 027/** 028 * For capital-E "Events" with a progress bar, Outcomes, contributing factors, and so on. 029 * 030 * Large UI; takes up the map area of the intel screen. 031 * 032 * @author Alex 033 * 034 * Copyright 2022 Fractal Softworks, LLC 035 */ 036public class BaseEventIntel extends BaseIntelPlugin implements EconomyTickListener { 037 038 /** 039 * Assigned to EventStageData.rollData when no random event was rolled. 040 */ 041 public static final String RANDOM_EVENT_NONE = "random_event_none"; 042 043 public static enum StageIconSize { 044 SMALL, 045 MEDIUM, 046 LARGE, 047 } 048 public static enum RandomizedStageType { 049 GOOD, 050 BAD, 051 NEUTRAL, 052 } 053 054 /** 055 * Just a data holder for display purposes in the BaseEventIntel UI. 056 */ 057 public static class EventStageDisplayData { 058 public float size; 059 public float downLineLength; 060 public String icon; 061 public Color color; 062 public Color iconColor = Color.white; 063 public String label; 064 public Color labelColor; 065 public int importance = 0; 066 } 067 068 public static class EventStageData { 069 public Object id; 070 public int progress; 071 public boolean isOneOffEvent; 072 public boolean wasEverReached = false; 073 public boolean isRepeatable = true; 074 public boolean sendIntelUpdateOnReaching = true; 075 public boolean hideIconWhenPastStageUnlessLastActive = false; 076 public boolean keepIconBrightWhenLaterStageReached = false; 077 public StageIconSize iconSize = StageIconSize.MEDIUM; 078 079 public boolean randomized = false; 080 public RandomizedStageType randomType = RandomizedStageType.NEUTRAL; 081 public int progressToResetAt; 082 public int progressToRollAt; 083 public Object rollData; 084 085 public EventStageData(Object id, int progress, boolean isOneOffEvent) { 086 this(id, progress, isOneOffEvent, StageIconSize.MEDIUM); 087 } 088 public EventStageData(Object id, int progress, boolean isOneOffEvent, StageIconSize iconSize) { 089 this.id = id; 090 this.progress = progress; 091 this.isOneOffEvent = isOneOffEvent; 092 this.iconSize = iconSize; 093 } 094 095 public void addProgressReq(TooltipMakerAPI tooltip, float pad) { 096 tooltip.addPara("Requires %s points of event progress.", 097 pad, Misc.getHighlightColor(), "" + progress); 098 } 099 public void addResetReq(TooltipMakerAPI tooltip, float pad) { 100 addResetReq(tooltip, false, pad); 101 } 102 public void beginResetReqList(TooltipMakerAPI tooltip, boolean withAvertInfo, float initPad) { 103 beginResetReqList(tooltip, withAvertInfo, "outcome", initPad); 104 } 105 public void beginResetReqList(TooltipMakerAPI tooltip, boolean withAvertInfo, String outcome, float initPad) { 106 float opad = 10f; 107 float pad = 3f; 108 tooltip.addPara("This " + outcome + " will be averted if:", initPad); 109 tooltip.setBulletedListMode(BaseIntelPlugin.BULLET); 110 if (withAvertInfo) { 111 tooltip.addPara("Event progress is reduced to %s points or below", 112 pad, Misc.getHighlightColor(), "" + progressToResetAt); 113 } 114 115 } 116 public void endResetReqList(TooltipMakerAPI tooltip, boolean withTriggeredResetInfo) { 117 endResetReqList(tooltip, withTriggeredResetInfo, "outcome", -1, -1); 118 } 119 public void endResetReqList(TooltipMakerAPI tooltip, boolean withTriggeredResetInfo, String outcome, int min, int max) { 120 tooltip.setBulletedListMode(null); 121 if (withTriggeredResetInfo) { 122 float opad = 10f; 123 if (min < 0 || max < 0) { 124 tooltip.addPara("If this " + outcome + " is triggered, event progress will be reset to a much lower value afterwards.", 125 opad); 126 } else { 127 tooltip.addPara("If this " + outcome + " is triggered, event progress will be reset to between %s and %s points.", 128 opad, Misc.getHighlightColor(), "" + min, "" + max); 129 } 130 } 131 } 132 133 public void addResetReq(TooltipMakerAPI tooltip, boolean withResetIfTriggered, float pad) { 134 addResetReq(tooltip, withResetIfTriggered, "outcome", -1, -1, pad); 135 } 136 public void addResetReq(TooltipMakerAPI tooltip, boolean withResetIfTriggered, String outcome, int min, int max, float pad) { 137 if (withResetIfTriggered) { 138 if (min < 0 || max < 0) { 139 tooltip.addPara("This " + outcome + " will be averted if event progress is reduced to %s points or below. " 140 + "If this " + outcome + " is triggered, event progress will be reset to a lower value afterwards.", 141 pad, Misc.getHighlightColor(), "" + progressToResetAt); 142 } else { 143 tooltip.addPara("This " + outcome + " will be averted if event progress is reduced to %s points or below. " 144 + "If this " + outcome + " is triggered, event progress will be reset to between %s and %s points.", 145 pad, Misc.getHighlightColor(), "" + progressToResetAt, "" + min, "" + max); 146 } 147 } else { 148 tooltip.addPara("This " + outcome + " will be averted if event progress is reduced to %s points or below.", 149 pad, Misc.getHighlightColor(), "" + progressToResetAt); 150 } 151 } 152 } 153 154 protected int progress = 0; 155 protected int maxProgress = 1000; 156 157 //protected Object startingStage; 158 protected List<EventStageData> stages = new ArrayList<EventStageData>(); 159 protected IntelSortTier sortTier; 160 161 protected List<EventFactor> factors = new ArrayList<EventFactor>(); 162 protected Random random = new Random(); 163 164 protected float progressDeltaRemainder = 0f; 165 protected transient float uiWidth; 166 167 public BaseEventIntel() { 168 setSortTier(IntelSortTier.TIER_2); 169 170 Global.getSector().addScript(this); 171 // this needs to be done in sub-classes since it sends out an intel update 172 // and that won't have the right data because the event isn't finished 173 // being constructed here - it needs stages etc added to it 174 //Global.getSector().getIntelManager().addIntel(this); 175 Global.getSector().getListenerManager().addListener(this); 176 } 177 178 @Override 179 protected void advanceImpl(float amount) { 180 super.advanceImpl(amount); 181 182 List<EventFactor> remove = new ArrayList<EventFactor>(); 183 for (EventFactor curr : factors) { 184 if (curr.isExpired()) { 185 remove.add(curr); 186 continue; 187 } 188 189 curr.advance(amount); 190 191 if (curr.isExpired()) { 192 remove.add(curr); 193 } 194 } 195 factors.removeAll(remove); 196 for (EventFactor factor : remove) { 197 factor.notifyFactorRemoved(); 198 } 199 } 200 201 202 203 @Override 204 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) { 205 Color c = getTitleColor(mode); 206 boolean large = true; 207 if (large) info.setParaSmallInsignia(); 208 info.addPara(getName(), c, 0f); 209 //info.addPara("Hostile Activity", c, 0f); 210 if (large) info.setParaFontDefault(); 211 addBulletPoints(info, mode); 212 } 213 214 protected boolean addEventFactorBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, 215 Color tc, float initPad) { 216 if (isUpdate && getListInfoParam() instanceof EventFactor) { 217 EventFactor factor = (EventFactor) getListInfoParam(); 218 if (factor.isOneTime()) { 219 factor.addBulletPointForOneTimeFactor(this, info, tc, initPad); 220 } 221 return true; 222 } 223 return false; 224 } 225 226 227 @Override 228 public void createLargeDescription(CustomPanelAPI panel, float width, float height) { 229 230 float opad = 10f; 231 uiWidth = width; 232 233 // TODO DEBUG 234 //setProgress(900); 235 //setProgress((int) (0 + (float) Math.random() * 400)); 236 //setProgress(900); 237 //setProgress(499); 238 //setProgress(200); 239 //setProgress(0); 240 241 TooltipMakerAPI main = panel.createUIElement(width, height, true); 242 243 main.setTitleOrbitronVeryLarge(); 244 main.addTitle(getName(), Misc.getBasePlayerColor()); 245 246 EventProgressBarAPI bar = main.addEventProgressBar(this, 100f); 247 TooltipCreator barTC = getBarTooltip(); 248 if (barTC != null) { 249 main.addTooltipToPrevious(barTC, TooltipLocation.BELOW, false); 250 } 251 252 for (EventStageData curr : stages) { 253 if (curr.progress <= 0) continue; // no icon for "starting" stage 254 //if (curr.rollData == null || curr.rollData.equals(RANDOM_EVENT_NONE)) continue; 255 if (RANDOM_EVENT_NONE.equals(curr.rollData)) continue; 256 if (curr.wasEverReached && curr.isOneOffEvent && !curr.isRepeatable) continue; 257 258 if (curr.hideIconWhenPastStageUnlessLastActive && 259 curr.progress <= progress && 260 getLastActiveStage(true) != curr) { 261 continue; 262 } 263 264 EventStageDisplayData data = createDisplayData(curr.id); 265 UIComponentAPI marker = main.addEventStageMarker(data); 266 float xOff = bar.getXCoordinateForProgress(curr.progress) - bar.getPosition().getX(); 267 marker.getPosition().aboveLeft(bar, data.downLineLength).setXAlignOffset(xOff - data.size / 2f - 1); 268 269 TooltipCreator tc = getStageTooltip(curr.id); 270 if (tc != null) { 271 main.addTooltipTo(tc, marker, TooltipLocation.LEFT, false); 272 } 273 } 274 275 // progress indicator 276 { 277 UIComponentAPI marker = main.addEventProgressMarker(this); 278 float xOff = bar.getXCoordinateForProgress(progress) - bar.getPosition().getX(); 279 marker.getPosition().belowLeft(bar, -getBarProgressIndicatorHeight() * 0.5f - 2) 280 .setXAlignOffset(xOff - getBarProgressIndicatorWidth() / 2 - 1); 281 } 282 283 main.addSpacer(opad); 284 main.addSpacer(opad); 285 for (EventStageData curr : stages) { 286 if (curr.wasEverReached && curr.isOneOffEvent && !curr.isRepeatable) continue; 287 addStageDescriptionWithImage(main, curr.id); 288 } 289 290 291 afterStageDescriptions(main); 292 293 float barW = getBarWidth(); 294 float factorWidth = (barW - opad) / 2f; 295 296 if (withMonthlyFactors() != withOneTimeFactors()) { 297 //factorWidth = barW; 298 factorWidth = (int) (barW * 0.6f); 299 } 300 301 TooltipMakerAPI mFac = main.beginSubTooltip(factorWidth); 302 303 Color c = getFactionForUIColors().getBaseUIColor(); 304 Color bg = getFactionForUIColors().getDarkUIColor(); 305 mFac.addSectionHeading("Monthly factors", c, bg, Alignment.MID, opad).getPosition().setXAlignOffset(0); 306 307 float strW = 40f; 308 float rh = 20f; 309 //rh = 15f; 310 mFac.beginTable2(getFactionForUIColors(), rh, false, false, 311 "Monthly factors", factorWidth - strW - 3, 312 "Progress", strW 313 ); 314 315 for (EventFactor factor : factors) { 316 if (factor.isOneTime()) continue; 317 if (!factor.shouldShow(this)) continue; 318 319 String desc = factor.getDesc(this); 320 if (desc != null) { 321 mFac.addRowWithGlow(Alignment.LMID, factor.getDescColor(this), desc, 322 Alignment.RMID, factor.getProgressColor(this), factor.getProgressStr(this)); 323 TooltipCreator t = factor.getMainRowTooltip(this); 324 if (t != null) { 325 mFac.addTooltipToAddedRow(t, TooltipLocation.RIGHT, false); 326 } 327 } 328 factor.addExtraRows(mFac, this); 329 } 330 331 //mFac.addButton("TEST", new String(), factorWidth, 20f, opad); 332 mFac.addTable("None", -1, opad); 333 mFac.getPrev().getPosition().setXAlignOffset(-5); 334 335 main.endSubTooltip(); 336 337 TooltipMakerAPI oFac = main.beginSubTooltip(factorWidth); 338 339 oFac.addSectionHeading("Recent one-time factors", c, bg, Alignment.MID, opad).getPosition().setXAlignOffset(0); 340 341 oFac.beginTable2(getFactionForUIColors(), 20f, false, false, 342 "One-time factors", factorWidth - strW - 3, 343 "Progress", strW 344 ); 345 346 List<EventFactor> reversed = new ArrayList<EventFactor>(factors); 347 Collections.reverse(reversed); 348 for (EventFactor factor : reversed) { 349 if (!factor.isOneTime()) continue; 350 if (!factor.shouldShow(this)) continue; 351 352 String desc = factor.getDesc(this); 353 if (desc != null) { 354 oFac.addRowWithGlow(Alignment.LMID, factor.getDescColor(this), desc, 355 Alignment.RMID, factor.getProgressColor(this), factor.getProgressStr(this)); 356 TooltipCreator t = factor.getMainRowTooltip(this); 357 if (t != null) { 358 oFac.addTooltipToAddedRow(t, TooltipLocation.LEFT); 359 } 360 } 361 factor.addExtraRows(oFac, this); 362 } 363 364 oFac.addTable("None", -1, opad); 365 oFac.getPrev().getPosition().setXAlignOffset(-5); 366 main.endSubTooltip(); 367 368 369 float factorHeight = Math.max(mFac.getHeightSoFar(), oFac.getHeightSoFar()); 370 mFac.setHeightSoFar(factorHeight); 371 oFac.setHeightSoFar(factorHeight); 372 373 374 if (withMonthlyFactors() && withOneTimeFactors()) { 375 main.addCustom(mFac, opad * 2f); 376 main.addCustomDoNotSetPosition(oFac).getPosition().rightOfTop(mFac, opad); 377 } else if (withMonthlyFactors()) { 378 main.addCustom(mFac, opad * 2f); 379 } else if (withOneTimeFactors()) { 380 main.addCustom(oFac, opad * 2f); 381 } 382 383 //main.addButton("TEST", new String(), factorWidth, 20f, opad); 384 385 panel.addUIElement(main).inTL(0, 0); 386 } 387 388 public TooltipCreator getBarTooltip() { 389 return new TooltipCreator() { 390 public boolean isTooltipExpandable(Object tooltipParam) { 391 return false; 392 } 393 public float getTooltipWidth(Object tooltipParam) { 394 return 450; 395 } 396 397 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) { 398 float opad = 10f; 399 Color h = Misc.getHighlightColor(); 400 401 tooltip.addPara("Event progress: %s out of %s points.", 0f, h, "" + progress, "" + maxProgress); 402 int p = getMonthlyProgress(); 403 String pStr = "" + p; 404 if (p > 0) pStr = "+" + p; 405 tooltip.addPara("Projected monthly progress: %s points.", opad, getProgressColor(p), pStr); 406 407 tooltip.addPara("Event progress is influenced by various factors. Some of these apply over time, " 408 + "and some only apply once. As the event progresses, " 409 + "different stages and outcomes may unfold.", opad); 410 } 411 }; 412 } 413 public TooltipCreator getStageTooltip(Object stageId) { 414 final EventStageData esd = getDataFor(stageId); 415 if (esd == null || (esd.randomized && (esd.rollData == null || RANDOM_EVENT_NONE.equals(esd.rollData)))) { 416 return new TooltipCreator() { 417 public boolean isTooltipExpandable(Object tooltipParam) { 418 return false; 419 } 420 public float getTooltipWidth(Object tooltipParam) { 421 return BaseEventFactor.TOOLTIP_WIDTH; 422 } 423 424 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) { 425 float opad = 10f; 426 Color h = Misc.getHighlightColor(); 427 428 tooltip.addPara("Something might occur when event progress reaches %s points. " 429 + "What that is, if anything, will be determined when event progress reaches " 430 + "%s points.", 0f, 431 h, "" + esd.progress, "" + esd.progressToRollAt); 432 433 if (esd.isRepeatable) { 434 tooltip.addPara("This event is repeatable.", opad); 435 } else { 436 tooltip.addPara("This event is not repeatable.", opad); 437 } 438 } 439 }; 440 } 441 return getStageTooltipImpl(stageId); 442 } 443 public TooltipCreator getStageTooltipImpl(Object stageId) { 444 return null; 445 } 446 447 public float getImageSizeForStageDesc(Object stageId) { 448 return 64f; 449 } 450 public float getImageIndentForStageDesc(Object stageId) { 451 return 0f; 452 } 453 454 public void afterStageDescriptions(TooltipMakerAPI main) { 455 456 } 457 public void addStageDescriptionWithImage(TooltipMakerAPI main, Object stageId) { 458 EventStageDisplayData data = createDisplayData(stageId); 459 String icon; 460 if (data != null) { 461 icon = data.icon; 462 } else { 463 icon = getIcon(); 464 } 465 float imageSize = getImageSizeForStageDesc(stageId); 466 float opad = 10f; 467 float indent = 0; 468 indent = 10f; 469 indent += getImageIndentForStageDesc(stageId); 470 float width = getBarWidth() - indent * 2f; 471 472 473 TooltipMakerAPI info = main.beginImageWithText(icon, imageSize, width, true); 474 //TooltipMakerAPI info = main.beginImageWithText("graphics/icons/missions/ga_intro.png", 64); 475 addStageDescriptionText(info, width - imageSize - opad, stageId); 476 if (info.getHeightSoFar() > 0) { 477 main.addImageWithText(opad).getPosition().setXAlignOffset(indent); 478 main.addSpacer(0).getPosition().setXAlignOffset(-indent); 479 } 480 } 481 482 public void addStageDescriptionText(TooltipMakerAPI info, float width, Object stageId) { 483 484 } 485 486 487 public EventStageDisplayData createDisplayData(Object stageId) { 488 EventStageDisplayData data = new EventStageDisplayData(); 489 data.size = getStageIconSize(stageId); 490 data.downLineLength = getStageDownLineLength(stageId); 491 data.color = getStageColor(stageId); 492 data.icon = getStageIcon(stageId); 493 data.iconColor = getStageIconColor(stageId); 494 data.importance = getStageImportance(stageId); 495 data.label = getStageLabel(stageId); 496 data.labelColor = getStageLabelColor(stageId); 497 return data; 498 } 499 500 protected String getStageIcon(Object stageId) { 501 EventStageData esd = getDataFor(stageId); 502 if (esd == null || (esd.randomized && (esd.rollData == null || RANDOM_EVENT_NONE.equals(esd.rollData)))) { 503 if (esd.randomType == RandomizedStageType.GOOD) { 504 return Global.getSettings().getSpriteName("events", "stage_unknown_good"); 505 } else if (esd.randomType == RandomizedStageType.BAD) { 506 return Global.getSettings().getSpriteName("events", "stage_unknown_bad"); 507 } 508 return Global.getSettings().getSpriteName("events", "stage_unknown_neutral"); 509 } 510 return getStageIconImpl(stageId); 511 512 } 513 protected String getStageIconImpl(Object stageId) { 514 return Global.getSettings().getSpriteName("events", "stage_unknown"); 515 } 516 517 protected float getStageIconSize(Object stageId) { 518 EventStageData esd = getDataFor(stageId); 519 if (esd != null && esd.iconSize == StageIconSize.SMALL) return 32; 520 if (esd != null && esd.iconSize == StageIconSize.LARGE) return 48; 521 return 40; 522 //return 32; 523 } 524 525 protected float getStageDownLineLength(Object stageId) { 526 EventStageData esd = getDataFor(stageId); 527 //if (esd != null && esd.iconSize == StageIconSize.SMALL) return 24; 528 //if (esd != null && esd.iconSize == StageIconSize.SMALL) return 56; // level with top of LARGE 529 if (esd != null && esd.iconSize == StageIconSize.SMALL) return 48; // level with middle of LARGE 530 if (esd != null && esd.iconSize == StageIconSize.LARGE) return 40; 531 return 32; 532 } 533 534 535 public float getBarWidth() { 536 //return uiWidth - 200f; 537 return 750f; 538 } 539 public float getBarHeight() { 540 return 20f; 541 } 542 543 public boolean putBarProgressIndicatorLabelOnRight() { 544 float test = (float)progress / (float)maxProgress * getBarWidth(); 545 return test < 50; 546 } 547 548 public float getBarProgressIndicatorHeight() { 549 return 20f; 550 } 551 public float getBarProgressIndicatorWidth() { 552 return 20f; 553 } 554 public Color getBarProgressIndicatorLabelColor() { 555 return Misc.getHighlightColor(); 556 } 557 public Color getBarProgressIndicatorColor() { 558 return getBarColor(); 559 } 560 public Color getBarBracketColor() { 561 if (true) return Misc.getBasePlayerColor(); 562 return getBarColor(); 563 } 564 565 public Color getBarColor() { 566 Color color = Misc.getBasePlayerColor(); 567 color = Misc.interpolateColor(color, Color.black, 0.25f); 568 return color; 569 } 570 571 protected Color getBaseStageColor(Object stageId) { 572 return getBarColor(); 573 } 574 protected Color getDarkStageColor(Object stageId) { 575 Color color = getBarColor(); 576 color = Misc.interpolateColor(color, Color.black, 0.5f); 577 return color; 578 } 579 protected Color getStageColor(Object stageId) { 580 int req = getRequiredProgress(stageId); 581 582 EventStageData last = getLastActiveStage(false); 583 EventStageData esd = getDataFor(stageId); 584 boolean grayItOut = false; 585 if (last != null && esd != null && last != esd && !esd.isOneOffEvent && 586 !esd.keepIconBrightWhenLaterStageReached && 587 esd.progress < last.progress) { 588 grayItOut = true; 589 } 590 591 if (esd != null && esd.randomized && esd.rollData != null) { 592 return getBaseStageColor(stageId); 593 } 594 595 if (req > progress || grayItOut) { 596 return getDarkStageColor(stageId); 597 } 598 return getBaseStageColor(stageId); 599 } 600 protected Color getStageIconColor(Object stageId) { 601 int req = getRequiredProgress(stageId); 602 603 EventStageData last = getLastActiveStage(false); 604 EventStageData esd = getDataFor(stageId); 605 boolean grayItOut = false; 606 if (last != null && esd != null && last != esd && !esd.isOneOffEvent && 607 !esd.keepIconBrightWhenLaterStageReached && 608 esd.progress < last.progress) { 609 grayItOut = true; 610 } 611 612 if (esd != null && esd.randomized && esd.rollData != null) { 613 return Color.white; 614 } 615 616 if (req > progress || grayItOut) { 617 return new Color(255,255,255,155); 618 } 619 return Color.white; 620 } 621 protected int getStageImportance(Object stageId) { 622 return 0; 623 } 624 protected String getStageLabel(Object stageId) { 625 Object least = null; 626 int min = Integer.MAX_VALUE; 627 for (EventStageData curr : stages) { 628 int req = curr.progress; 629 if (req > progress && req < min) { 630 min = req; 631 least = curr.id; 632 } 633 } 634 if (stageId.equals(least)) { 635 return "" + getRequiredProgress(least); 636 } 637 return null; 638 } 639 protected Color getStageLabelColor(Object stageId) { 640 return Misc.getHighlightColor(); 641 } 642 643 @Override 644 public Set<String> getIntelTags(SectorMapAPI map) { 645 Set<String> tags = super.getIntelTags(map); 646 tags.add(Tags.INTEL_MAJOR_EVENT); 647 return tags; 648 } 649 650 @Override 651 public boolean hasSmallDescription() { 652 return false; 653 } 654 655 @Override 656 public boolean hasLargeDescription() { 657 return true; 658 } 659 660 public int getMaxProgress() { 661 return maxProgress; 662 } 663 664 public void setMaxProgress(int maxProgress) { 665 this.maxProgress = maxProgress; 666 } 667 668 public List<EventStageData> getStages() { 669 return stages; 670 } 671 672 673 public boolean isStageOrOneOffEventReached(Object stageId) { 674 return progress >= getRequiredProgress(stageId); 675 } 676 677 public boolean isStageActiveAndLast(Object stageId) { 678 return isStageActiveAndLast(stageId, false); 679 } 680 public boolean isStageActiveAndLast(Object stageId, boolean includeOneOffEvents) { 681 EventStageData data = getLastActiveStage(includeOneOffEvents); 682 //if (data == null) return startingStage == stageId; 683 if (data == null) return false; 684 return data.id == stageId; // assuming stageId will be enums, so == check is ok 685 } 686 687// public boolean isStageActive(Object stageId) { 688// EventStageData data = getDataFor(stageId); 689// if (data == null) return false; 690// return data.progress <= getProgress(); 691// } 692 693 694// public Object getStartingStage() { 695// return startingStage; 696// } 697// public void setStartingStage(Object startingStage) { 698// this.startingStage = startingStage; 699// } 700 701 public void addStage(Object id, int progress) { 702 addStage(id, progress, StageIconSize.MEDIUM); 703 } 704 public void addStage(Object id, int progress, StageIconSize iconSize) { 705 addStage(id, progress, false, iconSize); 706 } 707 public void addStage(Object id, int progress, boolean isOneOffEvent) { 708 addStage(id, progress, isOneOffEvent, StageIconSize.MEDIUM); 709 } 710 public void addStage(Object id, int progress, boolean isOneOffEvent, StageIconSize iconSize) { 711 stages.add(new EventStageData(id, progress, isOneOffEvent, iconSize)); 712 } 713 714 public boolean isStageActive(Object stageId) { 715 EventStageData data = getDataFor(stageId); 716 if (data == null) return false; 717 return data.progress <= getProgress(); 718 719 } 720 public EventStageData getLastActiveStage(boolean includeOneOffEvents) { 721 EventStageData last = null; 722 int max = Integer.MIN_VALUE; 723 for (EventStageData curr : stages) { 724 if (!includeOneOffEvents && curr.isOneOffEvent) continue; 725 726 int req = curr.progress; 727 if (progress >= req && req > max) { 728 max = req; 729 last = curr; 730 } 731 } 732 return last; 733 } 734 735 public EventStageData getDataFor(Object stageId) { 736 for (EventStageData curr : stages) { 737 if (stageId.equals(curr.id)) return curr; 738 } 739 return null; 740 } 741 742 public int getRequiredProgress(Object stageId) { 743 //if (stageId == startingStage) return 0; 744 EventStageData data = getDataFor(stageId); 745 return data == null ? 0 : data.progress; 746 } 747 748 public void setSortTier(IntelSortTier sortTier) { 749 this.sortTier = sortTier; 750 } 751 752 @Override 753 public IntelSortTier getSortTier() { 754 if (sortTier == null || isEnding() || isEnded()) return super.getSortTier(); 755 return sortTier; 756 } 757 758 759 @Override 760 protected void notifyEnded() { 761 super.notifyEnded(); 762 Global.getSector().removeScript(this); 763 for (EventFactor factor : factors) { 764 factor.notifyEventEnded(); 765 } 766 } 767 768 769 @Override 770 protected void notifyEnding() { 771 super.notifyEnding(); 772// for (MarketAPI curr : getAffectedMarkets()) { 773// if (curr.hasCondition(Conditions.HOSTILE_ACTIVITY)) { 774// curr.removeCondition(Conditions.HOSTILE_ACTIVITY); 775// } 776// } 777 Global.getSector().getListenerManager().removeListener(this); 778 for (EventFactor factor : factors) { 779 factor.notifyEventEnding(); 780 } 781 } 782 783 public void addFactor(EventFactor factor) { 784 addFactor(factor, null); 785 } 786 /** 787 * Adds factor's progress to event progress if it's a one-time factor. 788 * If dialog is passed in, it'll be visible to notifyStageReached() via addingFactorDialog, 789 * in case that needs to print an update there. 790 * @param factor 791 */ 792 protected transient InteractionDialogAPI addingFactorDialog = null; 793 public void addFactor(EventFactor factor, InteractionDialogAPI dialog) { 794 addingFactorDialog = dialog; 795 factors.add(factor); 796 if (factor.isOneTime()) { 797 if (factor.getProgress(this) != 0) { 798 TextPanelAPI textPanel = dialog == null ? null : dialog.getTextPanel(); 799 sendUpdateIfPlayerHasIntel(factor, textPanel); 800 } 801 setProgress(getProgress() + factor.getProgress(this)); 802 } 803 addingFactorDialog = null; 804 } 805 public TextPanelAPI getTextPanelForStageChange() { 806 if (addingFactorDialog == null) return null; 807 return addingFactorDialog.getTextPanel(); 808 } 809 810 public List<EventFactor> getFactors() { 811 return factors; 812 } 813 814 public EventFactor getFactorOfClass(Class c) { 815 for (EventFactor f : getFactors()) { 816 if (f.getClass() == c) { 817 return f; 818 } 819 } 820 return null; 821 } 822 823 public void removeFactor(EventFactor factor) { 824 factors.remove(factor); 825 factor.notifyFactorRemoved(); 826 } 827 828 public void removeFactorOfClass(Class<EventFactor> c) { 829 List<EventFactor> remove = new ArrayList<EventFactor>(); 830 for (EventFactor curr : factors) { 831 if (c.isInstance(curr)) { 832 remove.add(curr); 833 } 834 } 835 factors.removeAll(remove); 836 for (EventFactor factor : remove) { 837 factor.notifyFactorRemoved(); 838 } 839 } 840 841 public boolean isEventProgressANegativeThingForThePlayer() { 842 return false; 843 } 844 845 846 public int getMaxMonthlyProgress() { 847 return 1000000; 848 } 849 850 public int getMonthlyProgress() { 851 int total = 0; 852 float mult = 1f; 853 for (EventFactor factor : factors) { 854 if (factor.isOneTime()) continue; 855 total += factor.getProgress(this); 856 mult *= factor.getAllProgressMult(this); 857 } 858 859 if (total != 0) { 860 float sign = Math.signum(total); 861 total = Math.round(sign * Math.abs(total) * mult); 862 if (total == 0) total = (int) Math.round(1f * sign); 863 } 864 865 total = Math.min(total, getMaxMonthlyProgress()); 866 867 return total; 868 } 869 870 871 public void reportEconomyTick(int iterIndex) { 872 float delta = getMonthlyProgress(); 873 874 if (delta <= 0 && this instanceof HostileActivityEventIntel) { 875 setProgress(0); 876 return; 877 } 878 879 float numIter = Global.getSettings().getFloat("economyIterPerMonth"); 880 float f = 1f / numIter; 881 882 delta *= f; 883 delta += progressDeltaRemainder; 884 885 int apply = (int) delta; 886 887 progressDeltaRemainder = delta - (float) apply; 888 889 setProgress(progress + apply); 890 891 } 892 893 public int getProgress() { 894 return progress; 895 } 896 897 protected transient boolean prevProgressDeltaWasPositive = false; 898 public void setProgress(int progress) { 899 if (this.progress == progress) return; 900 901 if (progress < 0) progress = 0; 902 if (progress > maxProgress) progress = maxProgress; 903 904 EventStageData prev = getLastActiveStage(true); 905 prevProgressDeltaWasPositive = this.progress < progress; 906 907 //progress += 30; 908 //progress = 40; 909 //progress = 40; 910 //progress = 499; 911 912 this.progress = progress; 913 914 915 if (progress < 0) { 916 progress = 0; 917 } 918 if (progress > getMaxProgress()) { 919 progress = getMaxProgress(); 920 } 921 922 // Check to see if randomized events need to be rolled/reset 923 for (EventStageData esd : getStages()) { 924 if (esd.wasEverReached && esd.isOneOffEvent && !esd.isRepeatable) continue; 925 926 if (esd.randomized) { 927 if ((esd.rollData != null && !esd.rollData.equals(RANDOM_EVENT_NONE)) && progress <= esd.progressToResetAt) { 928 resetRandomizedStage(esd); 929 } 930 if ((esd.rollData == null || esd.rollData.equals(RANDOM_EVENT_NONE)) && progress >= esd.progressToRollAt) { 931 rollRandomizedStage(esd); 932 if (esd.rollData == null) { 933 esd.rollData = RANDOM_EVENT_NONE; 934 } 935 } 936 } 937 } 938 939 // go through all of the stages made active by the new progress value 940 // generally this'd just be one stage, but possible to have multiple for a large 941 // progress increase 942 for (EventStageData curr : getStages()) { 943 if (curr.progress <= prev.progress && !prev.wasEverReached && 944 (prev.rollData == null || prev.rollData.equals(RANDOM_EVENT_NONE))) continue; 945 //if (curr.progress > progress) continue; 946 947 // reached 948 if (curr.progress <= progress) { 949 boolean laterThanPrev = prev == null || ((Enum)prev.id).ordinal() < ((Enum)curr.id).ordinal(); 950 if (curr != null && (laterThanPrev || !prev.wasEverReached)) { 951 if (curr.sendIntelUpdateOnReaching && curr.progress > 0 && (prev == null || prev.progress < curr.progress)) { 952 sendUpdateIfPlayerHasIntel(curr, getTextPanelForStageChange()); 953 } 954 notifyStageReached(curr); 955 curr.rollData = null; 956 curr.wasEverReached = true; 957 958 progress = getProgress(); // in case it was changed by notifyStageReached() 959 } 960 } 961 } 962 } 963 964 protected String getSoundForStageReachedUpdate(Object stageId) { 965 return getSoundMajorPosting(); 966 } 967 protected String getSoundForOneTimeFactorUpdate(EventFactor factor) { 968 return null; 969 } 970 protected String getSoundForOtherUpdate(Object param) { 971 return null; 972 } 973 974 public String getCommMessageSound() { 975 if (isSendingUpdate()) { 976 if (getListInfoParam() instanceof EventStageData) { 977 EventStageData esd = (EventStageData) getListInfoParam(); 978 String sound = getSoundForStageReachedUpdate(esd.id); 979 if (sound != null) { 980 return sound; 981 } 982 } else if (getListInfoParam() instanceof EventFactor) { 983 String sound = getSoundForOneTimeFactorUpdate((EventFactor) getListInfoParam()); 984 if (sound != null) { 985 return sound; 986 } 987 } else if (getListInfoParam() != null) { 988 String sound = getSoundForOtherUpdate(getListInfoParam()); 989 if (sound != null) { 990 return sound; 991 } 992 } 993 return getSoundStandardUpdate(); 994 } 995 return getSoundStandardPosting(); 996 } 997 998 protected void notifyStageReached(EventStageData stage) { 999 1000 } 1001 1002 public void reportEconomyMonthEnd() { 1003 1004 } 1005 1006 public Color getProgressColor(int delta) { 1007 if (isEventProgressANegativeThingForThePlayer()) { 1008 if (delta < 0) { 1009 return Misc.getPositiveHighlightColor(); 1010 } 1011 } else { 1012 if (delta < 0) { 1013 return Misc.getNegativeHighlightColor(); 1014 } 1015 } 1016 return Misc.getHighlightColor(); 1017 } 1018 1019 public void setHideStageWhenPastIt(Object stageId) { 1020 EventStageData esd = getDataFor(stageId); 1021 if (esd == null) return; 1022 esd.hideIconWhenPastStageUnlessLastActive = true; 1023 } 1024 1025 public void setRandomized(Object stageId, RandomizedStageType type, int resetAt, int rollAt, boolean sendUpdateWhenReached) { 1026 setRandomized(stageId, type, resetAt, rollAt, sendUpdateWhenReached, true); 1027 } 1028 public void setRandomized(Object stageId, RandomizedStageType type, int resetAt, int rollAt, boolean sendUpdateWhenReached, boolean repeatable) { 1029 EventStageData esd = getDataFor(stageId); 1030 if (esd == null) return; 1031 esd.sendIntelUpdateOnReaching = sendUpdateWhenReached; 1032 esd.isRepeatable = repeatable; 1033 esd.isOneOffEvent = true; 1034 esd.randomized = true; 1035 esd.rollData = null; 1036 esd.progressToResetAt = resetAt; 1037 esd.progressToRollAt = rollAt; 1038 esd.randomType = type; 1039 } 1040 1041 public Random getRandom() { 1042 return random; 1043 } 1044 1045 public void setRandom(Random random) { 1046 this.random = random; 1047 } 1048 1049 public void resetRandomizedStage(EventStageData stage) { 1050 stage.rollData = null; 1051 } 1052 1053 public void rollRandomizedStage(EventStageData stage) { 1054 1055 } 1056 1057 1058 public float getProgressFraction() { 1059 float p = (float) progress / (float) maxProgress; 1060 if (p < 0) p = 0; 1061 if (p > 1) p = 1; 1062 return p; 1063 } 1064 1065 public boolean withMonthlyFactors() { 1066 return true; 1067 } 1068 public boolean withOneTimeFactors() { 1069 return true; 1070 } 1071} 1072 1073 1074 1075 1076 1077 1078 1079 1080