Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ This page lists all the individual contributions to the project by their author.
- Fix the bug where landing direction cannot be correctly converted when set to a value exceeding 256
- Separately define the global default values of TerrainTypes' `IsPassable` and `CanBeBuiltOn` based on `SpawnsTiberium`
- Remove the restriction that prohibits InfantryTypes from using the InitialPayload logic
- Add `ammo`, `health`, `mission`, `landtype` and `sequence` conditions to `DiscardOn`
- **Ollerus**:
- Build limit group enhancement
- Customizable rocker amplitude
Expand Down
20 changes: 18 additions & 2 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ This page describes all the engine features that are either new and introduced b
- `selling`: Discard when the building to which the effect is attached is sold.
- `undeploying`: Discard when the building to which the effect is attached performs undeploy.
- `harvesting`: Discard when the object the effect is attached is harvesting ore. This can only be used when `DiscardOn.ConsiderHarvestingAsStationary=false`.
- `invokerdie`: Discard when the invoker of the effect is destroyed.
- `invokerdie`: Discard when the invoker of the effect is destroyed.
- `ammo`: Discard when the ammo of the object the effect is attached to is within the interval `[DiscardOn.Ammo.MinimumAmount, DiscardOn.Ammo.MaximumAmount]` (set to `-1` to ignore either bound).
- `health`: Discard when the health percentage of the object the effect is attached to is within the interval `(DiscardOn.Health.AbovePercent, DiscardOn.Health.BelowPercent]` (set to `-1` to ignore either bound).
- `mission`: Discard when the current mission of the object the effect is attached to matches any one in the `DiscardOn.Missions` list (or `DiscardOn.AIMissions` for AI-controlled objects, if set).
- `landtype`: Discard when the land type of the cell where the object the effect is attached to is currently located matches any land type in the `DiscardOn.LandTypes` list.
- `sequence`: Discard when the infantry to which the effect is attached is playing a sequence that matches any one in the `DiscardOn.Sequences` list.
- `DiscardOn.Sequences.Immediate` defines whether the `sequence` discard condition triggers immediately while the infantry is playing a matching sequence, or only when the infantry starts playing its next sequence after finishing that sequence.
- `DiscardOn.MoveBasedOnDestination` defines whether to determine the movement state according to the presence or absence of a destination. It treats Jumpjet units hovering in the air as movement, and units that have no destination but are turning as stationary.
- If used for an AE that has `DiscardOn=harvesting`, in order for it to judge correctly, this should be set to `true`.
- `DiscardOn.ConsiderHarvestingAsStationary` defines whether to treat `harvesting` as `stationary`. When this flag is set to `false`, `DiscardOn=harvesting` can be used and it will not be considered `stationary` while `harvesting`.
Expand Down Expand Up @@ -99,6 +105,7 @@ This page describes all the engine features that are either new and introduced b
In `rulesmd.ini`:
```ini
[General]
DiscardOn.Sequences.Immediate=true ; boolean
DiscardOn.MoveBasedOnDestination=false ; boolean
DiscardOn.ConsiderHarvestingAsStationary=true ; boolean
OpenTopped.UseTransportRangeModifiers=false ; boolean
Expand All @@ -114,7 +121,16 @@ Duration.ApplyArmorMultOnTarget=false ; boolean
Cumulative=false ; boolean
Cumulative.MaxCount=-1 ; integer
Powered=false ; boolean
DiscardOn=none ; List of discard condition enumeration (none|entry|move|stationary|drain|inrange|outofrange|selling|undeploying|harvesting|invokerdie)
DiscardOn=none ; List of discard condition enumeration (none|entry|move|stationary|drain|inrange|outofrange|selling|undeploying|harvesting|invokerdie|ammo|health|mission|landtype|sequence)
DiscardOn.Ammo.MinimumAmount=-1 ; integer
DiscardOn.Ammo.MaximumAmount=-1 ; integer
DiscardOn.Health.BelowPercent=-1 ; floating point value
DiscardOn.Health.AbovePercent=-1 ; floating point value
DiscardOn.Missions= ; List of MissionTypes
DiscardOn.AIMissions= ; List of MissionTypes, default to [AttachEffectType] -> DiscardOn.Missions
DiscardOn.LandTypes= ; List of LandTypes (none | clear | road | water | rock | wall | tiberium | beach | rough | ice | railroad | tunnel | weeds)
DiscardOn.Sequences= ; List of Sequences (ready | guard | prone | walk | fireup | fireprone | secondaryfire | secondaryprone | down | crawl | up | idle1 | idle2 | die1 | die2 | die3 | die4 | die5 | deploy | deployed | deployedfire | deployedidle | undeploy | paradrop | cheer | panic | shovel | carry | fly | hover | firefly | tumble | airdeathstart | airdeathfalling | airdeathfinish | tread | swim | wetattack | wetidle1 | wetidle2 | wetdie1 | wetdie2)
DiscardOn.Sequences.Immediate= ; boolean, default to [General] -> DiscardOn.Sequences.Immediate
DiscardOn.RangeOverride= ; floating point value, distance in cells
DiscardOn.MoveBasedOnDestination= ; boolean, default to [General] -> DiscardOn.MoveBasedOnDestination
DiscardOn.ConsiderHarvestingAsStationary= ; boolean, default to [General] -> DiscardOn.ConsiderHarvestingAsStationary
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ HideShakeEffects=false ; boolean
- [DeployFire supports buildings](New-or-Enhanced-Logics.md#deployfire-supports) (By FlyStar)
- `OmniFire` supports buildings with `Turret=yes` (by FlyStar)
- [Automatic conversion based on heallth](New-or-Enhanced-Logics.md#automatic-conversion-based-on-heallth) (by obsidianus)
- Add `ammo`, `health`, `mission`, `landtype` and `sequence` conditions to `DiscardOn` (by Noble_Fish)

#### Vanilla fixes:
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/Rules/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)
deploySound.Read(exINI, GameStrings::AudioVisual, "DeploySound");
pThis->DeploySound = deploySound;

this->DiscardOn_Sequences_Immediate.Read(exINI, GameStrings::General, "DiscardOn.Sequences.Immediate");
this->DiscardOn_MoveBasedOnDestination.Read(exINI, GameStrings::General, "DiscardOn.MoveBasedOnDestination");
this->DiscardOn_ConsiderHarvestingAsStationary.Read(exINI, GameStrings::General, "DiscardOn.ConsiderHarvestingAsStationary");

Expand Down Expand Up @@ -1031,6 +1032,7 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->Vertical_AircraftFix)
.Process(this->Temporal_ApplyVersus)
.Process(this->Temporal_ApplyMultiplier)
.Process(this->DiscardOn_Sequences_Immediate)
.Process(this->DiscardOn_MoveBasedOnDestination)
.Process(this->DiscardOn_ConsiderHarvestingAsStationary)
.Process(this->RemoveMindControl_Silent)
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ class RulesExt
Valueable<bool> Temporal_ApplyVersus;
Valueable<bool> Temporal_ApplyMultiplier;

Valueable<bool> DiscardOn_Sequences_Immediate;
Valueable<bool> DiscardOn_MoveBasedOnDestination;
Valueable<bool> DiscardOn_ConsiderHarvestingAsStationary;
Valueable<bool> RemoveMindControl_Silent;
Expand Down Expand Up @@ -941,6 +942,7 @@ class RulesExt
, Vertical_AircraftFix { true }
, Temporal_ApplyVersus { false }
, Temporal_ApplyMultiplier { false }
, DiscardOn_Sequences_Immediate { true }
, DiscardOn_MoveBasedOnDestination { false }
, DiscardOn_ConsiderHarvestingAsStationary { true }
, RemoveMindControl_Silent { false }
Expand Down
89 changes: 89 additions & 0 deletions src/New/Entity/AttachEffectClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ AttachEffectClass::AttachEffectClass(AttachEffectTypeClass* pType, TechnoClass*
, ShouldRecalculateStats { false }
, LastDiscardCheckFrame { -1 }
, LastDiscardCheckValue { false }
, LastSequenceCheck { Sequence::Nothing }
{
this->HasInitialized = false;

Expand Down Expand Up @@ -635,6 +636,93 @@ bool AttachEffectClass::ShouldBeDiscardedNow()
return true;
}

if ((discardOn & DiscardCondition::Ammo) != DiscardCondition::None)
{
const int min = pType->DiscardOn_Ammo_MinimumAmount;
const int max = pType->DiscardOn_Ammo_MaximumAmount;
const int ammo = pTechno->Ammo;

if ((min < 0 || ammo >= min) && (max < 0 || ammo <= max))
{
this->LastDiscardCheckValue = true;
return true;
}
}

if ((discardOn & DiscardCondition::Health) != DiscardCondition::None)
{
if (auto const pTypeData = pTechno->GetTechnoType())
{
const double min = pType->DiscardOn_Health_AbovePercent;
const double max = pType->DiscardOn_Health_BelowPercent;
if (TechnoExt::IsHealthInThreshold(pTechno, min, max))
{
this->LastDiscardCheckValue = true;
return true;
}
}
}

if ((discardOn & DiscardCondition::LandType) != DiscardCondition::None)
{
if (pType->DiscardOn_LandTypes != LandTypeFlags::None)
{
if (auto const pCell = pTechno->GetCell())
{
LandTypeFlags landFlags = pType->DiscardOn_LandTypes;
if (IsLandTypeInFlags(landFlags, pCell->LandType))
{
this->LastDiscardCheckValue = true;
return true;
}
}
}
}

if ((discardOn & DiscardCondition::Mission) != DiscardCondition::None)
{
auto const& missions = pTechno->Owner->IsControlledByHuman()
? pType->DiscardOn_Missions
: (pType->DiscardOn_AIMissions.HasValue()
? static_cast<ValueableVector<Mission>&>(pType->DiscardOn_AIMissions)
: pType->DiscardOn_Missions);

if (missions.size() > 0 && missions.Contains(pTechno->CurrentMission))
{
this->LastDiscardCheckValue = true;
return true;
}
}

if ((discardOn & DiscardCondition::Sequence) != DiscardCondition::None)
{
if (auto const pInf = abstract_cast<InfantryClass*, true>(pTechno))
{
if (pType->DiscardOn_Sequences.size() > 0)
{
if (pType->DiscardOn_Sequences_Immediate.Get(RulesExt::Global()->DiscardOn_Sequences_Immediate))
{
if (pType->DiscardOn_Sequences.Contains(pInf->SequenceAnim))
{
this->LastDiscardCheckValue = true;
return true;
}
}
else
{
if (this->LastSequenceCheck != pInf->SequenceAnim && pType->DiscardOn_Sequences.Contains(this->LastSequenceCheck))
{
this->LastDiscardCheckValue = true;
return true;
}
this->LastSequenceCheck = pInf->SequenceAnim;
}
}
}
else
this->LastSequenceCheck = Sequence::Nothing;
}

if (pTechno->Target)
{
const bool inRange = (discardOn & DiscardCondition::InRange) != DiscardCondition::None;
Expand Down Expand Up @@ -1184,6 +1272,7 @@ bool AttachEffectClass::Serialize(T& Stm)
.Process(this->LastActiveStat)
.Process(this->LaserTrail)
.Process(this->ShouldRecalculateStats)
.Process(this->LastSequenceCheck)
.Success();
}

Expand Down
1 change: 1 addition & 0 deletions src/New/Entity/AttachEffectClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class AttachEffectClass
bool LastDiscardCheckValue;
bool LastActiveStat;
LaserTrailClass* LaserTrail;
Sequence LastSequenceCheck;

public:
bool HasCumulativeAnim;
Expand Down
46 changes: 46 additions & 0 deletions src/New/Type/AttachEffectTypeClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,23 @@ void AttachEffectTypeClass::LoadFromINI(CCINIClass* pINI)
this->Cumulative_MaxCount.Read(exINI, pSection, "Cumulative.MaxCount");
this->Powered.Read(exINI, pSection, "Powered");
this->DiscardOn.Read(exINI, pSection, "DiscardOn");
this->DiscardOn_Ammo_MinimumAmount.Read(exINI, pSection, "DiscardOn.Ammo.MinimumAmount");
this->DiscardOn_Ammo_MaximumAmount.Read(exINI, pSection, "DiscardOn.Ammo.MaximumAmount");

if (this->DiscardOn_Ammo_MinimumAmount > this->DiscardOn_Ammo_MaximumAmount)
Debug::Log("[Developer warning][%s] DiscardOn.Ammo.MinimumAmount is greater than DiscardOn.Ammo.MaximumAmount, the ammo discard condition cannot be established.\n", pSection);

this->DiscardOn_Health_BelowPercent.Read(exINI, pSection, "DiscardOn.Health.BelowPercent");
this->DiscardOn_Health_AbovePercent.Read(exINI, pSection, "DiscardOn.Health.AbovePercent");

if (this->DiscardOn_Health_AbovePercent > this->DiscardOn_Health_BelowPercent)
Debug::Log("[Developer warning][%s] DiscardOn.Health.AbovePercent is greater than DiscardOn.Health.BelowPercent, the health discard condition cannot be established.\n", pSection);

this->DiscardOn_Missions.Read(exINI, pSection, "DiscardOn.Missions");
this->DiscardOn_AIMissions.Read(exINI, pSection, "DiscardOn.AIMissions");
this->DiscardOn_LandTypes.Read(exINI, pSection, "DiscardOn.LandTypes");
this->DiscardOn_Sequences.Read(exINI, pSection, "DiscardOn.Sequences");
this->DiscardOn_Sequences_Immediate.Read(exINI, pSection, "DiscardOn.Sequences.Immediate");
this->DiscardOn_RangeOverride.Read(exINI, pSection, "DiscardOn.RangeOverride");
this->DiscardOn_MoveBasedOnDestination.Read(exINI, pSection, "DiscardOn.MoveBasedOnDestination");
this->DiscardOn_ConsiderHarvestingAsStationary.Read(exINI, pSection, "DiscardOn.ConsiderHarvestingAsStationary");
Expand Down Expand Up @@ -218,6 +235,15 @@ void AttachEffectTypeClass::Serialize(T& Stm)
.Process(this->Cumulative_MaxCount)
.Process(this->Powered)
.Process(this->DiscardOn)
.Process(this->DiscardOn_Ammo_MinimumAmount)
.Process(this->DiscardOn_Ammo_MaximumAmount)
.Process(this->DiscardOn_Health_BelowPercent)
.Process(this->DiscardOn_Health_AbovePercent)
.Process(this->DiscardOn_Missions)
.Process(this->DiscardOn_AIMissions)
.Process(this->DiscardOn_LandTypes)
.Process(this->DiscardOn_Sequences)
.Process(this->DiscardOn_Sequences_Immediate)
.Process(this->DiscardOn_RangeOverride)
.Process(this->DiscardOn_MoveBasedOnDestination)
.Process(this->DiscardOn_ConsiderHarvestingAsStationary)
Expand Down Expand Up @@ -353,6 +379,26 @@ namespace detail
{
parsed |= DiscardCondition::InvokerDie;
}
else if (!_strcmpi(cur, "ammo"))
{
parsed |= DiscardCondition::Ammo;
}
else if (!_strcmpi(cur, "health"))
{
parsed |= DiscardCondition::Health;
}
else if (!_strcmpi(cur, "mission"))
{
parsed |= DiscardCondition::Mission;
}
else if (!_strcmpi(cur, "landtype"))
{
parsed |= DiscardCondition::LandType;
}
else if (!_strcmpi(cur, "sequence"))
{
parsed |= DiscardCondition::Sequence;
}
else
{
Debug::INIParseFailed(pSection, pKey, cur, "Expected a discard condition type");
Expand Down
25 changes: 24 additions & 1 deletion src/New/Type/AttachEffectTypeClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ enum class DiscardCondition : unsigned short
Selling = 0x80,
Undeploying = 0x100,
Harvesting = 0x200,
InvokerDie = 0x400
InvokerDie = 0x400,
Ammo = 0x800,
Health = 0x1000,
Mission = 0x2000,
LandType = 0x4000,
Sequence = 0x8000
};

MAKE_ENUM_FLAGS(DiscardCondition);
Expand Down Expand Up @@ -52,6 +57,15 @@ class AttachEffectTypeClass final : public Enumerable<AttachEffectTypeClass>
Valueable<int> Cumulative_MaxCount;
Valueable<bool> Powered;
Valueable<DiscardCondition> DiscardOn;
Valueable<int> DiscardOn_Ammo_MinimumAmount;
Valueable<int> DiscardOn_Ammo_MaximumAmount;
Nullable<double> DiscardOn_Health_BelowPercent;
Nullable<double> DiscardOn_Health_AbovePercent;
ValueableVector<Mission> DiscardOn_Missions;
NullableVector<Mission> DiscardOn_AIMissions;
Valueable<LandTypeFlags> DiscardOn_LandTypes;
ValueableVector<Sequence> DiscardOn_Sequences;
Nullable<bool>DiscardOn_Sequences_Immediate;
Nullable<Leptons> DiscardOn_RangeOverride;
Nullable<bool> DiscardOn_MoveBasedOnDestination;
Nullable<bool> DiscardOn_ConsiderHarvestingAsStationary;
Expand Down Expand Up @@ -122,6 +136,15 @@ class AttachEffectTypeClass final : public Enumerable<AttachEffectTypeClass>
, Cumulative_MaxCount { -1 }
, Powered { false }
, DiscardOn { DiscardCondition::None }
, DiscardOn_Ammo_MinimumAmount { -1 }
, DiscardOn_Ammo_MaximumAmount { -1 }
, DiscardOn_Health_BelowPercent { -1 }
, DiscardOn_Health_AbovePercent { -1 }
, DiscardOn_Missions {}
, DiscardOn_AIMissions {}
, DiscardOn_LandTypes { LandTypeFlags::None }
, DiscardOn_Sequences {}
, DiscardOn_Sequences_Immediate {}
, DiscardOn_RangeOverride {}
, DiscardOn_MoveBasedOnDestination {}
, DiscardOn_ConsiderHarvestingAsStationary {}
Expand Down
Loading
Loading