From 409c8b172764b8a41f108981a3b544090de20684 Mon Sep 17 00:00:00 2001 From: Dalo Lorn Date: Thu, 26 Jan 2023 22:04:05 +0100 Subject: [PATCH] [#71] Prototype implementation of lending ships to the Dread Pirate. Also, Crime Syndicates are now allied to the Dread Pirate. --- .../data/abilities/traits/LendPirateShip.txt | 7 ++ .../data/statuses/traits/CrimeSyndicate.txt | 16 ++- .../data/traits/lifestyle/CrimeSyndicate.txt | 2 + .../scripts/definitions/ABEM_races.as | 112 ++++++++++++++++++ Rising Stars/scripts/server/piracy.as | 19 ++- 5 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 Rising Stars/data/abilities/traits/LendPirateShip.txt diff --git a/Rising Stars/data/abilities/traits/LendPirateShip.txt b/Rising Stars/data/abilities/traits/LendPirateShip.txt new file mode 100644 index 00000000..5e70f72b --- /dev/null +++ b/Rising Stars/data/abilities/traits/LendPirateShip.txt @@ -0,0 +1,7 @@ +Ability: LendToPirate + Name: #ABL_LEND_TO_PIRATE + Description: #ABL_LEND_TO_PIRATE + Icon: SupplyIcon*#f00 + + ABEM_hooks::UserMustNotHaveStatus(Shadowport) + ABEM_races::AddOwnedStatusSelf(LoanedPirate, 900) diff --git a/Rising Stars/data/statuses/traits/CrimeSyndicate.txt b/Rising Stars/data/statuses/traits/CrimeSyndicate.txt index 031c1161..6017e292 100644 --- a/Rising Stars/data/statuses/traits/CrimeSyndicate.txt +++ b/Rising Stars/data/statuses/traits/CrimeSyndicate.txt @@ -7,4 +7,18 @@ Status: CrimeSyndicate IfLevel(3, ModLoyalty(-2)) IfLevel(4, ModLoyalty(-2)) IfLevel(5, ModLoyalty(-2)) - IfLevel(6, ModLoyalty(-5)) \ No newline at end of file + IfLevel(6, ModLoyalty(-5)) + +Status: CrimeSyndicateFleet + Visible To: Nobody + + GrantAbility(LendToPirate) + +Status: LoanedPirate + Name: #STATUS_PIRATESHIP + Description: #STATUS_PIRATESHIP_DESC + Icon: StatusWar * #ff0000 + + ABEM_races::MaintainFromOriginEmpire(0.2) + ABEM_races::TriggerWithOriginEmpireWhenRemoved(TakeControl()) + piracy::PirateStatus(True, True) diff --git a/Rising Stars/data/traits/lifestyle/CrimeSyndicate.txt b/Rising Stars/data/traits/lifestyle/CrimeSyndicate.txt index c6d67a94..a28fa248 100644 --- a/Rising Stars/data/traits/lifestyle/CrimeSyndicate.txt +++ b/Rising Stars/data/traits/lifestyle/CrimeSyndicate.txt @@ -26,6 +26,8 @@ Trait: CrimeSyndicate SpawnShip(Defiler, Override Disable Starting = True) SpawnShip(Shadowport, Override Disable Starting = True) AddStatusOwnedPlanets(CrimeSyndicate) + AddStatusOwnedFleets(CrimeSyndicateFleet) + ABEM_races::AllyPirates() ModAttribute(MaintainFromSpecialFunds, Add, 1) ModAttribute(SpecialFundsFactor, AddBase, 0.5) diff --git a/Rising Stars/scripts/definitions/ABEM_races.as b/Rising Stars/scripts/definitions/ABEM_races.as index 47f46515..f331b9f7 100644 --- a/Rising Stars/scripts/definitions/ABEM_races.as +++ b/Rising Stars/scripts/definitions/ABEM_races.as @@ -90,6 +90,17 @@ class AllyRemnants : TraitEffect { #section all } +class AllyPirates : TraitEffect { + Document doc("Empires with this trait cannot attack or be attacked by the Dread Pirate."); + +#section server + void postInit(Empire& emp, any@ data) const override { + Pirates.setHostile(emp, false); + emp.setHostile(Pirates, false); + } +#section all +} + class ConvertRemnants : AbilityHook { Document doc("Takes control of the target Remnant object. Also takes control of any support ships in the area."); Argument objTarg(TT_Object); @@ -1316,4 +1327,105 @@ tidy final class TriggerWithOriginEmpireWhenRemoved : StatusHook { hook.activate(obj, status.originEmpire); } #section all +}; + +class MaintainFromOriginEmpire : StatusHook { + Document doc("Deducts a maintenance fee from the status' origin empire. Only applies to ships for now."); + Argument percentage(AT_Decimal, "0", doc="How much of the object's maintenance cost to remove."); + +#section server + void onCreate(Object& obj, Status@ status, any@ data) override { + if(status.originEmpire is null) + return; + if(!obj.isShip) + return; + + data.store(0); + updateMaintenance(obj, status.originEmpire, data); + } + + void onDestroy(Object& obj, Status@ status, any@ data) override { + if(status.originEmpire is null) + return; + if(!obj.isShip) + return; + + int currentMaintenance; + data.retrieve(currentMaintenance); + Ship@ ship = cast(obj); + uint moneyType = MoT_Ships; + if(ship.blueprint.design.hasTag(ST_Station)) + moneyType = MoT_Orbitals; + emp.modMaintenance(-currentMaintenance, moneyType); + } + + bool onTick(Object& obj, Status@ status, any@ data, double time) override { + if(status.originEmpire is null) + return true; + if(!obj.isShip) + return true; + + updateMaintenance(obj, status.originEmpire, data); + return true; + } + + void updateMaintenance(Object& obj, Empire@ emp, any@ data) { + int currentMaintenance; + data.retrieve(currentMaintenance); + Ship@ ship = cast(obj); + uint moneyType = MoT_Ships; + if(ship.blueprint.design.hasTag(ST_Station)) + moneyType = MoT_Orbitals; + if(!ship.isFree) { + int maint = max(ship.blueprint.design.total(HV_MaintainCost), 0.0); + maint -= double(maint) * (emp.MaxLogistics / double(emp.LogisticsThreshold)) * double(clamp(emp.getBuiltShips(ship) - 1, 0, emp.LogisticsThreshold)); + maint = int(max(double(maint), ship.blueprint.getEfficiencySum(SV_MinimumMaintenance))); + if(maint != currentMaintenance) { + emp.modMaintenance(maint - currentMaintenance, moneyType); + data.store(maint); + } + } + } + + void save(Status@ status, any@ data, SaveFile& file) override { + int currentMaintenance; + data.retrieve(currentMaintenance); + file << currentMaintenance; + } + + void load(Status@ status, any@ data, SaveFile& file) override { + int currentMaintenance; + file >> currentMaintenance; + data.store(currentMaintenance); + } +#section all + +} + +class AddOwnedStatusSelf : AbilityHook { + Document doc("Add a status to the target object."); + Argument type(AT_Status, doc="Type of status effect to add."); + Argument duration(AT_SysVar, "-1", doc="Duration to add the status for, -1 for permanent."); + Argument duration_efficiency(AT_Boolean, "False", doc="Whether the duration added should be dependent on subsystem efficiency state. That is, a damaged subsystem will create a shorter duration status."); + Argument set_origin_object(AT_Boolean, "False", doc="Whether to record the object triggering this hook into the origin object field of the resulting status. If not set, any hooks that refer to Origin Object cannot not apply. Status effects with different origin objects set do not collapse into stacks."); + +#section server + void activate(Ability@ abl, any@ data, const Targets@ targs) const override { + Object@ target = abl.obj; + if(target is null) + return; + if(!target.hasStatuses) + return; + + Empire@ origEmp = abl.emp; + Object@ origObj = null; + if(set_origin_object.boolean) + @origObj = abl.obj; + + Object@ effObj = null; + if(duration_efficiency.boolean) + @effObj = abl.obj; + target.addStatus(uint(type.integer), duration.fromSys(abl.subsystem, efficiencyObj=effObj), originEmpire=origEmp, originObject=origObj); + } +#section all }; \ No newline at end of file diff --git a/Rising Stars/scripts/server/piracy.as b/Rising Stars/scripts/server/piracy.as index ad777ded..726dba14 100644 --- a/Rising Stars/scripts/server/piracy.as +++ b/Rising Stars/scripts/server/piracy.as @@ -4,6 +4,7 @@ import object_creation; import statuses; import settings.map_lib; import civilians; +import hooks; from game_start import getClosestSystem, getRandomSystem, systemCount, getSystem; from regions.regions import extentMin, extentMax; from statuses import StatusHook; @@ -71,6 +72,10 @@ class PirateData : Savable { }; class PirateStatus : StatusHook { + Argument originIsMaster(AT_Boolean, "False", doc="Whether to set the origin empire as being the ship's master, not the sole target."); + Argument noRespawn(AT_Boolean, "False", doc="Whether to prevent a new pirate from spawning when this ship is destroyed."); + Argument lootShare(AT_Decimal, "0.4", doc="If 'Origin Is Master' is set to true, how much of the loot should be handed out to the origin empire instead of being hoarded."); + void onCreate(Object& obj, Status@ status, any@ data) override { PirateData dat; data.store(@dat); @@ -87,7 +92,8 @@ class PirateStatus : StatusHook { if(credit !is null) credit.addBonusBudget(dat.currentStored + dat.totalCollected / 2); - spawnPirateShip(); + if(!noRespawn.boolean) + spawnPirateShip(); } bool onTick(Object& obj, Status@ status, any@ data, double time) override { @@ -108,7 +114,10 @@ class PirateStatus : StatusHook { case RESTING: { if(dat.timer <= 0.0) { //Find a new system to pillage - const SystemDesc@ targetSys = findJuicySystem(status.originEmpire); + Empire@ victim = null; + if(!originIsMaster.boolean) + @victim = status.originEmpire; + const SystemDesc@ targetSys = findJuicySystem(victim); if(targetSys is null) { dat.timer = HOARD_TIME; } @@ -148,6 +157,10 @@ class PirateStatus : StatusHook { case PILLAGING: { if(dat.chasing !is null) { if(!dat.chasing.valid) { + if(originIsMaster.boolean) { + status.originEmpire.modBonusBudget(dat.chasingAmount * lootShare.decimal); + dat.chasingAmount -= dat.chasingAmount * lootShare.decimal; + } dat.totalCollected += dat.chasingAmount; dat.currentStored += dat.chasingAmount; } @@ -278,6 +291,8 @@ const SystemDesc@ findJuicySystem(Empire@ limitEmpire = null) { continue; if(plMask & other.mask == 0) continue; + if(other.hostileMask & Pirates.hostileMask == 0) + continue; freq *= sqr(double(sys.object.getPlanetCount(other))); freq /= double(sys.object.getStrength(other) + 1); }