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