Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,9 @@ This page lists all the individual contributions to the project by their author.
- Add `ClampToScreen` tag for `BannerType` to control whether banner position is clamped to the visible area
- **obsidianus** - Automatic conversion based on health
- **Nuke** - Reload speed adjustment on promotion
- **frg2089 (舰队的偶像-岛风酱!)**:
- Fix `Slaved.OwnerWhenMasterKilled` not being respected when the master is sold or self-destructed
- **dh381-1** - Custom weapons to detonate your own Ivan bombs.
- **frg2089 (舰队的偶像-岛风酱!)** - Fix `Slaved.OwnerWhenMasterKilled` not being respected when the master is sold or self-destructed
- **weiyongxuan** - Extended `CanTargetHouses` to allow targeting neutral houses
- **Sovietianqi** - Customizable crew type per country
20 changes: 20 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -3789,6 +3789,26 @@ OmniFire.TurnToTarget=false ; boolean
OmniFire.TurnToTarget= ; boolean, default to [General] -> OmniFire.TurnToTarget
```

### Manually detonate Ivan bomb

![image](_static/images/IvanBombDetonate.gif)

- Now you can detonate planted Ivan bombs using custom werhead. The bomb attached to the targeted unit will explode immediately, provided that it was planted by the attacker.
- Use `IvanBomb.Detonate.InvokerOnly` to configure whether the warhead can detonate Ivan bombs from other sources.
- Use `IvanBomb.Detonate.PenetratesTransport` to configure whether the warhead can detonate Ivan bombs on a unit that is inside a transport. The bomb will explode after the unit is unloaded.
- Use `IvanBomb.Detonate.PenetratesGarrison` to configure whether the warhead can detonate Ivan bombs on a unit that is inside a building. The bomb will explode after the unit leaves the building.
- Use `IvanBomb.Detonate.AffectTypes` to configure which targets' Ivan bombs can be detonated by warhead, use empty for all types.

In `rulesmd.ini`:
```ini
[SOMEWARHEAD] ; WarheadType
IvanBomb.Detonate=true ; boolean
IvanBomb.Detonate.InvokerOnly=false ; boolean
IvanBomb.Detonate.PenetratesTransport=true ; boolean
IvanBomb.Detonate.PenetratesGarrison=true ; boolean
IvanBomb.Detonate.AffectTypes= ; List of TechnoTypes
```

### Radiation enhancements

- In addition to allowing custom radiation types, several enhancements are also available to the default radiation type defined in `[Radiation]`, such as ability to set owner & invoker or deal damage against buildings. See [Custom Radiation Types](#custom-radiation-types) for more details.
Expand Down
2 changes: 2 additions & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,8 @@ HideShakeEffects=false ; boolean
- [Disable AlphaImage during Buildup](Fixed-or-Improved-Logics.md#disable-alphaimage-during-buildup) (by Noble_Fish)
- [Reload speed adjustment on promotion](New-or-Enhanced-Logics.md#reload-speed-adjustment-on-promotion) (by Nuke)
- Allowed `(Pre)ProductionAnim` animations to use `Powered` & `PoweredLight/Effect/Special` keys (by Noble_Fish)
- [Customize ivan bomb visibility](Fixed-or-Improved-Logics.md#customize-ivan-bomb-visibility) (by NetsuNegi)
- [Customize whether warhead can detonate ivan bomb](New-or-Enhanced-Logics.md#Manually-detonate-Ivan-bomb) (by dh381)

#### Vanilla fixes:
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)
Expand Down
Binary file added docs/_static/images/IvanBombDetonate.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/Ext/Techno/Hooks.ReceiveDamage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,4 +576,4 @@ DEFINE_HOOK(0x737E6E, UnitClass_ReceiveDamage_SkipExplode, 0xA)

R->EAX(pThis->GetHeight());
return ContinueCheck;
}
}
13 changes: 13 additions & 0 deletions src/Ext/WarheadType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,12 @@ void WarheadTypeExt::LoadFromINIFile(CCINIClass* const pINI)

this->Ammo.Read(exINI, pSection, "Ammo");

this->IvanBomb_Detonate.Read(exINI, pSection, "IvanBomb.Detonate");
this->IvanBomb_Detonate_InvokerOnly.Read(exINI, pSection, "IvanBomb.Detonate.InvokerOnly");
this->IvanBomb_Detonate_AffectTypes.Read(exINI, pSection, "IvanBomb.Detonate.AffectTypes");
this->IvanBomb_Detonate_PenetratesTransport.Read(exINI, pSection, "IvanBomb.Detonate.PenetratesTransport");
this->IvanBomb_Detonate_PenetratesGarrison.Read(exINI, pSection, "IvanBomb.Detonate.PenetratesGarrison");

// Convert.From & Convert.To
TypeConvertGroup::Parse(this->Convert_Pairs, exINI, pSection, AffectedHouse::All);

Expand Down Expand Up @@ -517,6 +523,7 @@ void WarheadTypeExt::LoadFromINIFile(CCINIClass* const pINI)
|| this->PenetratesTransport_Level > 0
|| this->Taunt
|| this->Ammo
|| this->IvanBomb_Detonate
);

char tempBuffer[32];
Expand Down Expand Up @@ -822,6 +829,12 @@ void WarheadTypeExt::Serialize(T& Stm)
.Process(this->DamageAreaTarget)

.Process(this->Ammo)

.Process(this->IvanBomb_Detonate)
.Process(this->IvanBomb_Detonate_InvokerOnly)
.Process(this->IvanBomb_Detonate_AffectTypes)
.Process(this->IvanBomb_Detonate_PenetratesTransport)
.Process(this->IvanBomb_Detonate_PenetratesGarrison)
;
}

Expand Down
13 changes: 13 additions & 0 deletions src/Ext/WarheadType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ class WarheadTypeExt final : public AbstractTypeExt
Valueable<double> Damage_Deployed;
Nullable<bool> PreventScatter;

Valueable<bool> IvanBomb_Detonate;
Valueable<bool> IvanBomb_Detonate_InvokerOnly;
ValueableVector<TechnoTypeClass*> IvanBomb_Detonate_AffectTypes;
Valueable<bool> IvanBomb_Detonate_PenetratesTransport;
Valueable<bool> IvanBomb_Detonate_PenetratesGarrison;

double Crit_RandomBuffer;
double Crit_CurrentChance;
bool Crit_Active;
Expand Down Expand Up @@ -573,6 +579,12 @@ class WarheadTypeExt final : public AbstractTypeExt
, PreventOccupantEscape { false }

, Ammo { 0 }

, IvanBomb_Detonate { false }
, IvanBomb_Detonate_InvokerOnly { true }
, IvanBomb_Detonate_AffectTypes {}
, IvanBomb_Detonate_PenetratesTransport { false }
, IvanBomb_Detonate_PenetratesGarrison { false }
{ }

void ApplyConvert(HouseClass* pHouse, TechnoClass* pTarget);
Expand Down Expand Up @@ -615,6 +627,7 @@ class WarheadTypeExt final : public AbstractTypeExt
void ApplyPenetratesTransport(TechnoClass* pTarget, TechnoClass* pInvoker, HouseClass* pInvokerHouse, const CoordStruct& coords, int damage, int distance);
double GetCritChance(TechnoClass* pFirer) const;
void ApplyAmmoModifier(TechnoClass* pTarget);
void IvanBombDetonate(TechnoClass* pOwner,TechnoClass* pTarget);

public:
class ExtContainer final : public Container<WarheadTypeExt>
Expand Down
86 changes: 85 additions & 1 deletion src/Ext/WarheadType/Detonate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,10 @@ void WarheadTypeExt::DetonateOnOneUnit(HouseClass* pHouse, TechnoClass* pTarget,

if (this->Taunt && pOwner)
pTarget->Override_Mission(Mission::Attack, pOwner, nullptr);


if(this->IvanBomb_Detonate)
this->IvanBombDetonate(pOwner,pTarget);

// This might change the target's armor type
this->ApplyShieldModifiers(pTarget);

Expand Down Expand Up @@ -928,3 +931,84 @@ void WarheadTypeExt::ExtData::ApplyAmmoModifier(TechnoClass* pTarget)
newCurrentAmmo = newCurrentAmmo < 0 ? 0 : newCurrentAmmo;
pTarget->Ammo = newCurrentAmmo > maxAmmo ? maxAmmo : newCurrentAmmo;
}

void WarheadTypeExt::IvanBombDetonate(TechnoClass* pOwner,TechnoClass* pTarget)
{
if (!pOwner)
return;

if (const auto pBomb = pTarget->AttachedBomb)
{
const bool CanAffects = this->IvanBomb_Detonate_AffectTypes.empty()
|| this->IvanBomb_Detonate_AffectTypes.Contains(pTarget->GetTechnoType());

if (this->IvanBomb_Detonate_InvokerOnly)
{
if (pBomb->Owner == pOwner && CanAffects)
pBomb->DetonationFrame = Unsorted::CurrentFrame;
}
else
{
if (CanAffects)
pBomb->DetonationFrame = Unsorted::CurrentFrame;
}
}

if (this->IvanBomb_Detonate_PenetratesTransport)
{
if (auto pCurPassenger = pTarget->Passengers.FirstPassenger)
{
while (pCurPassenger)
{
auto pNextPassenger = abstract_cast<FootClass*>(pCurPassenger->NextObject);
const bool CanAffects = this->IvanBomb_Detonate_AffectTypes.empty()
|| this->IvanBomb_Detonate_AffectTypes.Contains(pCurPassenger->GetTechnoType());

if (const auto pPassengerBomb = pCurPassenger->AttachedBomb)
{
if (this->IvanBomb_Detonate_InvokerOnly)
{
if (pPassengerBomb->Owner == pOwner && CanAffects)
pPassengerBomb->DetonationFrame = Unsorted::CurrentFrame;
}
else
{
if (CanAffects)
pPassengerBomb->DetonationFrame = Unsorted::CurrentFrame;
}
}

pCurPassenger = pNextPassenger;
}
}
}

if (this->IvanBomb_Detonate_PenetratesGarrison)
{
if (pTarget->WhatAmI() != AbstractType::Building)
return;

const auto& Occupants = abstract_cast<BuildingClass*, true>(pTarget)->Occupants;

for (int i = 0; i < Occupants.Count; i++)
{
auto pOccupant = Occupants.Items[i];
const bool CanAffects = this->IvanBomb_Detonate_AffectTypes.empty()
|| this->IvanBomb_Detonate_AffectTypes.Contains(pOccupant->GetTechnoType());

if (const auto pOccupantBomb = pOccupant->AttachedBomb)
{
if (this->IvanBomb_Detonate_InvokerOnly)
{
if (pOccupantBomb->Owner == pOwner && CanAffects)
pOccupantBomb->DetonationFrame = Unsorted::CurrentFrame;
}
else
{
if (CanAffects)
pOccupantBomb->DetonationFrame = Unsorted::CurrentFrame;
}
}
}
}
}
1 change: 1 addition & 0 deletions src/Ext/WeaponType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class WeaponTypeExt final : public AbstractTypeExt
bool SkipWeaponPicking;

Nullable<bool> CylinderRangefinding;

Comment thread
NetsuNegi marked this conversation as resolved.

WeaponTypeExt(WeaponTypeClass* OwnerObject) : AbstractTypeExt(OwnerObject)
, DiskLaser_Radius { DiskLaserClass::Radius }
Expand Down