diff --git a/CREDITS.md b/CREDITS.md index 092084b4a4..77d74b9d44 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -504,6 +504,7 @@ This page lists all the individual contributions to the project by their author. - Customize particle system of parasite logic - Fix an issue where parasites that have infected infantry do not provide a refund when the infected infantry enters a Grinding building - Fix the issue that `PassengerDeletion` dont consider passenger's passenger, parasite and hijacker + - New bounty logic - **Apollo** - Translucent SHP drawing patches - **ststl**: - Customizable `ShowTimer` priority of superweapons diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 83f2fafb5d..0ad3322f9c 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -58,6 +58,8 @@ This page describes all the engine features that are either new and introduced b - `DisableWeapons` can be used to disable ability to fire any and all weapons. - On TechnoTypes with `OpenTopped=true`, `OpenTopped.CheckTransportDisableWeapons` can be set to true to make passengers not be able to fire out if transport's weapons are disabled by `DisableWeapons`. - `Unkillable` can be used to prevent the techno from being killed by taken damage (minimum health will be 1). + - `Bounty` can be used to override the option with the same name in TechnoTypes, enabling it for TechnoTypes that originally did not have the Bounty Hunter ability, or conversely, disabling it. + - If multiple AEs with this setting exist simultaneously, the last AE applied and in effect shall prevail. - It is possible to set groups for attach effect types by defining strings in `Groups`. - Groups can be used instead of types for removing effects and weapon filters. @@ -149,6 +151,7 @@ ReflectDamage.Override= ; integer ReflectDamage.UseInvokerAsOwner=false ; boolean DisableWeapons=false ; boolean Unkillable=false ; boolean +Bounty= ; boolean LaserTrail.Type= ; LaserTrailType Groups= ; comma-separated list of strings (group IDs) @@ -2167,6 +2170,51 @@ TiberiumEater.Anims.Tiberium3= ; List of AnimationTypes TiberiumEater.AnimMove=true ; boolean ``` +### New bounty logic + +- Similar to [Ares' bounty logic](https://ares-developers.github.io/Ares-docs/new/bounty.html), but with more configurable options and easier to use. +- `Bounty.Enable` is the master switch for the new bounty logic; it must be turned on first to utilize the new bounty system. +- `Bounty.Enablers` specifies the TechnoTypes that grant the bounty capability, not limited to buildings. + - If this list is empty, the bounty logic is enabled without requiring any prerequisite TechnoTypes. +- `Bounty.Multiplier` is the multiplier applied to the bounty a hunter receives when a victim is killed. This is defined on the victim. +- `Bounty.Value` is the fixed amount of funds a hunter receives when a victim is killed. This is also defined on the victim. + - If `Bounty.Value` is not 0, the base value is the amount set by `Bounty.Value`; otherwise, the base bounty value is the victim's actual cost multiplied by `Bounty.Multiplier`. +- `Bounty.KillerMultiplier` is the multiplier applied to the bounty received when killing a target. This is defined on the hunter. +- `Bounty.Display` controls whether the bounty amount is shown, displayed on the hunter. + +In `rulesmd.ini`: +```ini +[General] +Bounty.Enable=false ; boolean +Bounty.Enablers= ; list of TechnoTypes +Bounty.Default=false ; boolean +Bounty.Multiplier=1.0 ; double +Bounty.KillerMultiplier=1.0 ; double + +[AudioVisual] +Bounty.Display=false ; boolean +Bounty.Display.Houses=all ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) + +[SOMETECHNO] ; TechnoType +Bounty= ; boolean, default to [General] -> Bounty.Default +Bounty.Multiplier= ; double, default to [General] -> Bounty.Multiplier +Bounty.Multiplier.Veteran= ; double, default to [TechnoType] -> Bounty.Multiplier +Bounty.Multiplier.Elite= ; double, default to [TechnoType] -> Bounty.Multiplier +Bounty.Value=0 ; integer +Bounty.Value.Veteran= ; integer, default to [TechnoType] -> Bounty.Value +Bounty.Value.Elite= ; integer, default to [TechnoType] -> Bounty.Value +Bounty.KillerMultiplier= ; double, default to [General] -> Bounty.KillerMultiplier +Bounty.KillerMultiplier.Veteran= ; double, default to [TechnoType] -> Bounty.KillerMultiplier +Bounty.KillerMultiplier.Elite= ; double, default to [TechnoType] -> Bounty.KillerMultiplier +Bounty.Display= ; boolean, default to [AudioVisual] -> Bounty.Display +Bounty.Display.Houses= ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all), default to [AudioVisual] -> Bounty.Display.Houses +Bounty.Display.Offset=0,0 ; X,Y, pixels relative to default +``` + +```{note} +Do not use this alongside Ares' bounty logic; although it will not cause a crash, the hunter will receive a bounty from each logic. +``` + ### Weapons fired on warping in / out - It is now possible to add weapons that are fired on a teleporting TechnoType when it warps in or out. They are at the same time as the appropriate animations (`WarpIn` / `WarpOut`) are displayed. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index a4eaebd6b4..224775d6ef 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -542,6 +542,7 @@ New: - Allow jumpjet climbing ignore building height (by TaranDahl) - [Allow draw SuperWeapon timer as percentage](User-Interface.md#allow-draw-superweapon-timer-as-percentage) (by NetsuNegi) - Customize particle system of parasite logic (by NetsuNegi) +- [New bounty logic](New-or-Enhanced-Logics.md#new-bounty-logic) (by NetsuNegi) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) diff --git a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po index ddf9c5ab8b..33fae98b48 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po +++ b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po @@ -1635,6 +1635,9 @@ msgid "" "passenger, parasite and hijacker" msgstr "修复了 `PassengerDeletion` 未考虑乘客的乘客、寄生者和偷车贼的问题" +msgid "New bounty logic" +msgstr "新版赏金逻辑" + msgid "**Apollo** - Translucent SHP drawing patches" msgstr "**Apollo** - 半透明 SHP 绘制补丁" diff --git a/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po b/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po index bcfa729c78..4defcc8037 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po +++ b/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po @@ -432,6 +432,19 @@ msgid "" " damage (minimum health will be 1)." msgstr "`Unkillable` 可用于防止科技类型因受到伤害而死亡(最低为 1)。" +msgid "" +"`Bounty` can be used to override the option with the same name in " +"TechnoTypes, enabling it for TechnoTypes that originally did " +"not have the Bounty Hunter ability, or conversely, disabling it." +msgstr "" +"`Bounty` 可用于覆盖科技类型上的同名设置,以使得本没有赏金猎人能力的单位可以启动它,或反过来禁用赏金猎人能力。" + +msgid "" +"If multiple AEs with this setting exist simultaneously, the last AE " +"applied and in effect shall prevail." +msgstr "" +"若同时存在多个带有该设置的 AE 则以最后赋予且处于生效状态的 AE 为准。" + msgid "" "It is possible to set groups for attach effect types by defining strings " "in `Groups`." @@ -4793,6 +4806,73 @@ msgid "" "the TechnoType." msgstr "若 `TiberiumEater.AnimMove` 设为 true 则动画会跟随单位移动。" +msgid "New bounty logic" +msgstr "新版赏金逻辑" + +msgid "" +"Similar to [Ares' bounty logic](https://ares-developers.github.io/Ares-" +"docs/new/bounty.html), but with more configurable options and easier to " +"use." +msgstr "" +"类似于 [Ares 的赏金逻辑](https://ares-developers.github.io/Ares-" +"docs/new/bounty.html),但允许更多设置项且更加易用。" + +msgid "" +"`Bounty.Enable` is the master switch for the new bounty logic; it must be" +" turned on first to utilize the new bounty system." +msgstr "" +"`Bounty.Enable` 是整个新版赏金逻辑的总开关,只有先打开它才能使用新版赏金逻辑。" + +msgid "" +"`Bounty.Enablers` specifies the TechnoTypes that grant the bounty " +"capability, not limited to buildings." +msgstr "" +"`Bounty.Enablers` 指定给予所属方赏金能力所需的科技类型,不局限于建筑。" + +msgid "" +"If this list is empty, the bounty " +"logic is enabled without requiring any prerequisite TechnoTypes." +msgstr "" +"若该列表为空,则所属方无需任何科技类型作为前提即可启动赏金逻辑。" + +msgid "" +"`Bounty.Multiplier` is the multiplier applied to the bounty a hunter " +"receives when a victim is killed. This is defined on the victim." +msgstr "" +"`Bounty.Multiplier` 用于在猎物上设置其被击杀时猎人所得赏金的倍率。" + +msgid "" +"`Bounty.Value` is the fixed amount of funds a hunter receives when a " +"victim is killed. This is also defined on the victim." +msgstr "" +"`Bounty.Value` 用于在猎物上设置其被击杀时猎人所得的固定资金额度。" + +msgid "" +"If `Bounty.Value` is not 0, the base value is the amount set by " +"`Bounty.Value`; otherwise, the base bounty value is the victim's " +"actual cost multiplied by `Bounty.Multiplier`." +msgstr "" +"若 `Bounty.Value` 非 0 则以 `Bounty.Value` 设定的值作为基准值,否则使用" +"猎物的实际造价乘以 `Bounty.Multiplier` 。" + +msgid "" +"`Bounty.KillerMultiplier` is the multiplier applied to the bounty " +"received when killing a target. This is defined on the hunter." +msgstr "" +"`Bounty.KillerMultiplier` 用于在猎人上设置击杀目标是所得赏金的倍率。" + +msgid "" +"`Bounty.Display` controls whether the bounty amount is shown, displayed " +"on the hunter." +msgstr "" +"`Bounty.Display` 控制是否在猎人身上显示赏金金额数值。" + +msgid "" +"Do not use this alongside Ares' bounty logic; although it will not cause " +"a crash, the hunter will receive a bounty from each logic." +msgstr "" +"不要和 Ares 的赏金逻辑共同使用,虽然这不会导致崩溃,但猎人会从两个逻辑各获得一份赏金。" + msgid "Weapons fired on warping in / out" msgstr "武器在传送时开火" diff --git a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po index 33b3d3b24d..fd2e217021 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po +++ b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po @@ -1713,6 +1713,11 @@ msgstr "" msgid "Customize particle system of parasite logic (by NetsuNegi)" msgstr "自定义寄生粒子系统(by NetsuNegi)" +msgid "" +"[New bounty logic](New-or-Enhanced-Logics.md#new-bounty-logic) (by " +"NetsuNegi)" +msgstr "[新版赏金逻辑](New-or-Enhanced-Logics.md#new-bounty-logic)(by NetsuNegi)" + msgid "Vanilla fixes:" msgstr "原版问题修复:" diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 228b0415ca..78a3835307 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -368,6 +368,14 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->PenetratesTransport_Level.Read(exINI, GameStrings::CombatDamage, "PenetratesTransport.Level"); + this->Bounty_Enable.Read(exINI, GameStrings::General, "Bounty.Enable"); + this->Bounty_Enablers.Read(exINI, GameStrings::General, "Bounty.Enablers"); + this->Bounty_Default.Read(exINI, GameStrings::General, "Bounty.Default"); + this->Bounty_Multiplier.Read(exINI, GameStrings::General, "Bounty.Multiplier"); + this->Bounty_KillerMultiplier.Read(exINI, GameStrings::General, "Bounty.KillerMultiplier"); + this->Bounty_Display.Read(exINI, GameStrings::AudioVisual, "Bounty.Display"); + this->Bounty_Display_Houses.Read(exINI, GameStrings::AudioVisual, "Bounty.Display.Houses"); + this->UnitsUnsellable.Read(exINI, GameStrings::General, "UnitsUnsellable"); // Section AITargetTypes @@ -672,6 +680,13 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->DefaultToGuardArea) .Process(this->CylinderRangefinding) .Process(this->PenetratesTransport_Level) + .Process(this->Bounty_Enable) + .Process(this->Bounty_Enablers) + .Process(this->Bounty_Default) + .Process(this->Bounty_Multiplier) + .Process(this->Bounty_KillerMultiplier) + .Process(this->Bounty_Display) + .Process(this->Bounty_Display_Houses) .Process(this->UnitsUnsellable) ; } diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index ca624cd9ae..741985f6a7 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -318,6 +318,14 @@ class RulesExt Valueable PenetratesTransport_Level; + Valueable Bounty_Enable; + ValueableVector Bounty_Enablers; + Valueable Bounty_Default; + Valueable Bounty_Multiplier; + Valueable Bounty_KillerMultiplier; + Valueable Bounty_Display; + Valueable Bounty_Display_Houses; + Valueable UnitsUnsellable; ExtData(RulesClass* OwnerObject) : Extension(OwnerObject) @@ -582,6 +590,14 @@ class RulesExt , PenetratesTransport_Level { 10 } + , Bounty_Enable { false } + , Bounty_Enablers {} + , Bounty_Default { false } + , Bounty_Multiplier { 1.0 } + , Bounty_KillerMultiplier { 1.0 } + , Bounty_Display { false } + , Bounty_Display_Houses { AffectedHouse::All } + , UnitsUnsellable { false } { } diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index ed4ebd3ce3..d47654174c 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include TechnoExt::ExtContainer TechnoExt::ExtMap; UnitClass* TechnoExt::Deployer = nullptr; @@ -883,6 +885,133 @@ void TechnoExt::ClickedApproachObject(FootClass* pThis, ObjectClass* pObject) event.AddEvent(); } +void TechnoExt::GiveBounty(TechnoClass* pVictim, TechnoClass* pKiller, int victimCost) +{ + if (!RulesExt::Global()->Bounty_Enable) + return; + + const auto pKillerExt = TechnoExt::ExtMap.Find(pKiller); + const auto pKillerTypeExt = pKillerExt->TypeExtData; + const auto it = std::ranges::find_if(pKillerExt->AttachedEffects, [](std::unique_ptr const& pAE) { return pAE->IsActive() && pAE->GetType()->Bounty.isset(); }); + + if (it != pKillerExt->AttachedEffects.cend()) + { + if (!(*it)->GetType()->Bounty.Get()) + return; + } + else + { + if (!pKillerTypeExt->Bounty.Get(RulesExt::Global()->Bounty_Default)) + return; + } + + const auto pKillerHouse = pKiller->Owner; + + if (pKillerHouse->IsAlliedWith(pVictim->Owner)) + return; + + const auto pKillerHouseExt = HouseExt::ExtMap.Find(pKillerHouse); + + // check that any aux techno exist and no neg techno + auto IsTechnoPresent = [pKillerHouse, pKillerHouseExt](TechnoTypeClass* pType) + { + const auto pBuildingType = abstract_cast(pType); + + if (pBuildingType && (!BuildingTypeExt::ExtMap.Find(pBuildingType)->PowersUp_Buildings.empty() || BuildingTypeClass::Find(pBuildingType->PowersUpBuilding))) + return BuildingTypeExt::GetUpgradesAmount(pBuildingType, pKillerHouse) > 0; + + return pKillerHouseExt->CountOwnedPresentAndLimboed(pType) > 0; + }; + + if (!RulesExt::Global()->Bounty_Enablers.empty() && std::ranges::none_of(RulesExt::Global()->Bounty_Enablers, IsTechnoPresent)) + return; + + const auto pVictimTypeExt = TechnoTypeExt::ExtMap.Find(pVictim->GetTechnoType()); + int value = pVictimTypeExt->Bounty_Value.Get(pVictim); + + if (!value) + { + double victimMultiplier = 1.0; + + switch (pVictim->Veterancy.GetRemainingLevel()) + { + case Rank::Elite: + if (pVictimTypeExt->Bounty_Multiplier_Elite.isset()) + { + victimMultiplier = pVictimTypeExt->Bounty_Multiplier_Elite.Get(); + break; + } + + case Rank::Veteran: + if (pVictimTypeExt->Bounty_Multiplier_Vet.isset()) + { + victimMultiplier = pVictimTypeExt->Bounty_Multiplier_Elite.Get(); + break; + } + + default: + if (pVictimTypeExt->Bounty_Multiplier.isset()) + { + victimMultiplier = pVictimTypeExt->Bounty_Multiplier.Get(); + break; + } + + victimMultiplier = RulesExt::Global()->Bounty_Multiplier; + } + + value = static_cast(std::round(victimCost * victimMultiplier)); + + if (!value) + return; + } + + double killerMultiplier = 1.0; + + switch (pKiller->Veterancy.GetRemainingLevel()) + { + case Rank::Elite: + if (pKillerTypeExt->Bounty_KillerMultiplier_Elite.isset()) + { + killerMultiplier = pKillerTypeExt->Bounty_KillerMultiplier_Elite.Get(); + break; + } + + case Rank::Veteran: + if (pKillerTypeExt->Bounty_KillerMultiplier_Vet.isset()) + { + killerMultiplier = pKillerTypeExt->Bounty_KillerMultiplier_Elite.Get(); + break; + } + + default: + if (pKillerTypeExt->Bounty_KillerMultiplier.isset()) + { + killerMultiplier = pKillerTypeExt->Bounty_KillerMultiplier.Get(); + break; + } + + killerMultiplier = RulesExt::Global()->Bounty_KillerMultiplier; + } + + value = static_cast(std::round(value * killerMultiplier)); + + if (!value || !pKillerHouse->CanTransactMoney(value)) + return; + + pKillerHouse->TransactMoney(value); + + if (pKillerTypeExt->Bounty_Display.Get(RulesExt::Global()->Bounty_Display)) + { + const auto displayTo = pKillerTypeExt->Bounty_Display_Houses.Get(RulesExt::Global()->Bounty_Display_Houses); + auto pDisplayOn = pKiller; + + if (const auto pTransporter = pKiller->Transporter) + pDisplayOn = pTransporter; + + FlyingStrings::AddMoneyString(value, pKiller, pKiller->Owner, displayTo, pDisplayOn->Location, pKillerTypeExt->Bounty_Display_Offset); + } +} + bool TechnoExt::EjectRandomly(FootClass* pEjectee, const CoordStruct& coords, int distance, bool select) { std::vector usableCoords; diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index 7f178426b4..7a41561294 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -295,6 +295,7 @@ class TechnoExt static bool SimpleDeployerAllowedToDeploy(UnitClass* pThis, bool defaultValue, bool alwaysCheckLandTypes); static void ShowPromoteAnim(TechnoClass* pThis); static void ClickedApproachObject(FootClass* pThis, ObjectClass* pObject); + static void GiveBounty(TechnoClass* pVictim, TechnoClass* pKiller, int victimCost); static bool EjectRandomly(FootClass* pEjectee, const CoordStruct& coords, int distance, bool select); static bool EjectSurvivor(FootClass* pSurvivor, CoordStruct coords, bool select); diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 7bbf1c3a11..bb37856f12 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1856,3 +1856,14 @@ DEFINE_FUNCTION_JUMP(VTABLE, 0x7F5F30, FootClass_GetThreatValue_Wrapper); // Un DEFINE_FUNCTION_JUMP(VTABLE, 0x7E417C, Building_GetThreatValue_Wrapper); // BuildingClass #pragma endregion + +DEFINE_HOOK(0x702E64, TechnoClass_RegisterDestruction_Bounty, 0x6) +{ + GET(TechnoClass*, pKiller, EDI); + GET(TechnoClass*, pVictim, ESI); + GET(int, victimCost, EBP); + + TechnoExt::GiveBounty(pVictim, pKiller, victimCost); + + return 0; +} diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 8cc82868c4..627c0db7cb 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1160,6 +1160,18 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->JumpjetClimbIgnoreBuilding.Read(exINI, pSection, "JumpjetClimbIgnoreBuilding"); + this->Bounty.Read(exINI, pSection, "Bounty"); + this->Bounty_Multiplier.Read(exINI, pSection, "Bounty.Multiplier"); + this->Bounty_Multiplier_Vet.Read(exINI, pSection, "Bounty.Multiplier.Veteran"); + this->Bounty_Multiplier_Elite.Read(exINI, pSection, "Bounty.Multiplier.Elite"); + this->Bounty_Value.Read(exINI, pSection, "Bounty.Value.%s"); + this->Bounty_KillerMultiplier.Read(exINI, pSection, "Bounty.KillerMultiplier"); + this->Bounty_KillerMultiplier_Vet.Read(exINI, pSection, "Bounty.KillerMultiplier.Veteran"); + this->Bounty_KillerMultiplier_Elite.Read(exINI, pSection, "Bounty.KillerMultiplier.Elite"); + this->Bounty_Display.Read(exINI, pSection, "Bounty.Display"); + this->Bounty_Display_Houses.Read(exINI, pSection, "Bounty.Display.Houses"); + this->Bounty_Display_Offset.Read(exINI, pSection, "Bounty.Display.Offset"); + // Ares 0.2 this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius"); @@ -1874,6 +1886,18 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->PenetratesTransport_DamageMultiplier) .Process(this->JumpjetClimbIgnoreBuilding) + + .Process(this->Bounty) + .Process(this->Bounty_Multiplier) + .Process(this->Bounty_Multiplier_Vet) + .Process(this->Bounty_Multiplier_Elite) + .Process(this->Bounty_Value) + .Process(this->Bounty_KillerMultiplier) + .Process(this->Bounty_KillerMultiplier_Vet) + .Process(this->Bounty_KillerMultiplier_Elite) + .Process(this->Bounty_Display) + .Process(this->Bounty_Display_Houses) + .Process(this->Bounty_Display_Offset) .Process(this->Unsellable) ; diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index c11729ec83..dec225fd42 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -485,6 +485,18 @@ class TechnoTypeExt Nullable JumpjetClimbIgnoreBuilding; + Nullable Bounty; + Nullable Bounty_Multiplier; + Nullable Bounty_Multiplier_Vet; + Nullable Bounty_Multiplier_Elite; + Promotable Bounty_Value; + Nullable Bounty_KillerMultiplier; + Nullable Bounty_KillerMultiplier_Vet; + Nullable Bounty_KillerMultiplier_Elite; + Nullable Bounty_Display; + Nullable Bounty_Display_Houses; + Valueable Bounty_Display_Offset; + Nullable Unsellable; // Ares 3.0 ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject) @@ -926,6 +938,18 @@ class TechnoTypeExt , JumpjetClimbIgnoreBuilding {} + , Bounty {} + , Bounty_Multiplier {} + , Bounty_Multiplier_Vet {} + , Bounty_Multiplier_Elite {} + , Bounty_Value { 0 } + , Bounty_KillerMultiplier {} + , Bounty_KillerMultiplier_Vet {} + , Bounty_KillerMultiplier_Elite {} + , Bounty_Display {} + , Bounty_Display_Houses {} + , Bounty_Display_Offset { Point2D::Empty } + , Unsellable {} { } diff --git a/src/New/Type/AttachEffectTypeClass.cpp b/src/New/Type/AttachEffectTypeClass.cpp index 02bc5abb9e..103b11b845 100644 --- a/src/New/Type/AttachEffectTypeClass.cpp +++ b/src/New/Type/AttachEffectTypeClass.cpp @@ -161,6 +161,7 @@ void AttachEffectTypeClass::LoadFromINI(CCINIClass* pINI) this->DisableWeapons.Read(exINI, pSection, "DisableWeapons"); this->Unkillable.Read(exINI, pSection, "Unkillable"); + this->Bounty.Read(exINI, pSection, "Bounty"); this->LaserTrail_Type.Read(exINI, pSection, "LaserTrail.Type"); // Groups @@ -230,6 +231,7 @@ void AttachEffectTypeClass::Serialize(T& Stm) .Process(this->ReflectDamage_UseInvokerAsOwner) .Process(this->DisableWeapons) .Process(this->Unkillable) + .Process(this->Bounty) .Process(this->LaserTrail_Type) .Process(this->Groups) ; diff --git a/src/New/Type/AttachEffectTypeClass.h b/src/New/Type/AttachEffectTypeClass.h index b0759a97c0..56dde22493 100644 --- a/src/New/Type/AttachEffectTypeClass.h +++ b/src/New/Type/AttachEffectTypeClass.h @@ -99,6 +99,7 @@ class AttachEffectTypeClass final : public Enumerable Valueable ReflectDamage_UseInvokerAsOwner; Valueable DisableWeapons; Valueable Unkillable; + Nullable Bounty; ValueableIdx LaserTrail_Type; std::vector Groups; @@ -162,6 +163,7 @@ class AttachEffectTypeClass final : public Enumerable , ReflectDamage_UseInvokerAsOwner { false } , DisableWeapons { false } , Unkillable { false } + , Bounty {} , LaserTrail_Type { -1 } , Groups {} {};