001package com.fs.starfarer.api.impl.campaign.rulecmd; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Map; 006import java.util.Random; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.campaign.CampaignFleetAPI; 010import com.fs.starfarer.api.campaign.InteractionDialogAPI; 011import com.fs.starfarer.api.campaign.TextPanelAPI; 012import com.fs.starfarer.api.campaign.rules.MemoryAPI; 013import com.fs.starfarer.api.fleet.FleetMemberAPI; 014import com.fs.starfarer.api.util.Misc; 015import com.fs.starfarer.api.util.Misc.Token; 016import com.fs.starfarer.api.util.WeightedRandomPicker; 017 018/** 019 * 020 * ApplyCRDamage <fleet points> <quantity multiplier> <cr multiplier> <description string> 021 * 022 * ApplyCRDamage $entity.fleetPoints 0.2 1 "Vindictive search" 023 * The first param is the base number of fleet points for the amount of CR damage to do - 024 * so, for an inspection it's based on the fleet points of the inspecting fleet, but it 025 * could also just be a flat number, or based on the player fleet if 026 * we wanted something like "half your ships take CR damage" 027 * 028 * The second param is the multiplier for that number (basically, making up for the fact that you 029 * can't say "$fleetPoints * 0.2" in rules - so the multiplication happens inside the command. 030 * So you could have a more or less vindictive inspection by tuning this param 031 * 032 * The third param is the multiplier for the CR damage each selected ship takes; 033 * with it == 1 it's "half the recovery cost plus 1-10%" 034 * 035 * Fourth param is the description for this CR loss event in the ship's CR tooltip 036 */ 037public class ApplyCRDamage extends BaseCommandPlugin { 038 039 040 public boolean execute(String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) { 041 if (dialog == null) return false; 042 if (!(dialog.getInteractionTarget() instanceof CampaignFleetAPI)) return false; 043 044 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet(); 045 //CampaignFleetAPI other = (CampaignFleetAPI) dialog.getInteractionTarget(); 046 047 TextPanelAPI text = dialog.getTextPanel(); 048 //Color red = Misc.getNegativeHighlightColor(); 049 050 float baseFP = params.get(0).getFloat(memoryMap); 051 float fpMult = params.get(1).getFloat(memoryMap); 052 float crMult = params.get(2).getFloat(memoryMap); 053 String desc = params.get(3).getString(memoryMap); 054 055 long seed; 056 if (dialog.getInteractionTarget() != null) { 057 seed = Misc.getSalvageSeed(dialog.getInteractionTarget()); 058 seed += (ruleId == null ? 0 : ruleId.hashCode()); 059 seed /= 321L; 060 seed *= (Global.getSector().getClock().getMonth() + 10 + (baseFP * fpMult * crMult) * 10f); 061 } else { 062 seed = Misc.genRandomSeed(); 063 } 064 065 Random random = Misc.getRandom(seed, 7); 066 067 applyCRDamage(playerFleet, baseFP * fpMult, crMult, desc, text, random); 068 069 return true; 070 } 071 072 public static void applyCRDamage(CampaignFleetAPI fleet, float damageFP, float crMult, String desc, TextPanelAPI text, Random random) { 073 List<FleetMemberAPI> shipsToDamage = new ArrayList<FleetMemberAPI>(); 074 WeightedRandomPicker<FleetMemberAPI> picker = new WeightedRandomPicker<FleetMemberAPI>(random); 075 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) { 076 if (member.isMothballed() && member.getRepairTracker().getBaseCR() < 0.2f) continue; 077 picker.add(member, member.getFleetPointCost()); 078 } 079 080 float totalDamage = damageFP; 081 float picked = 0f; 082 while (picked < totalDamage && !picker.isEmpty()) { 083 FleetMemberAPI pick = picker.pickAndRemove(); 084 shipsToDamage.add(pick); 085 picked += pick.getFleetPointCost(); 086 } 087 088 089 for (FleetMemberAPI member : shipsToDamage) { 090 float crLost = Math.min(member.getRepairTracker().getBaseCR(), member.getDeployCost() * 0.5f); 091 crLost += 0.01f * (float)random.nextInt(10); 092 crLost *= crMult; 093 if (crLost > 0) { 094 member.getRepairTracker().applyCREvent(-crLost, desc); 095 if (text != null) { 096 AddRemoveCommodity.addCRLossText(member, text, crLost); 097 } 098 } 099 } 100 } 101 102} 103 104 105 106 107 108 109