Skip to content

Commit 15e42fb

Browse files
committed
random anims
1 parent 0455a77 commit 15e42fb

File tree

17 files changed

+97
-40
lines changed

17 files changed

+97
-40
lines changed

docs/New-or-Enhanced-Logics.md

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,10 @@ IdleAnimDamaged.ConditionYellow= ; Animation
289289
IdleAnimDamaged.ConditionRed= ; Animation
290290
IdleAnim.OfflineAction=Hides ; AttachedAnimFlag (None, Hides, Temporal, Paused or PausedTemporal)
291291
IdleAnim.TemporalAction=Hides ; AttachedAnimFlag (None, Hides, Temporal, Paused or PausedTemporal)
292-
BreakAnim= ; Animation
293-
HitAnim= ; Animation
292+
BreakAnim= ; list of Animation
293+
BreakAnims= ; list of Animation, overrides BreakAnim
294+
HitAnim= ; list of Animation
295+
HitAnims= ; list of Animation, overrides HitAnim
294296
HitFlash=false ; boolean
295297
HitFlash.FixedSize= ; integer
296298
HitFlash.Red=true ; boolean
@@ -315,8 +317,10 @@ ShieldType=SOMESHIELDTYPE ; ShieldType; none by default
315317
[SOMEWARHEAD] ; WarheadType
316318
Shield.Penetrate=false ; boolean
317319
Shield.Break=false ; boolean
318-
Shield.BreakAnim= ; Animation
319-
Shield.HitAnim= ; Animation
320+
Shield.BreakAnim= ; list of Animation
321+
Shield.BreakAnims= ; list of Animation, overrides Shield.BreakAnim
322+
Shield.HitAnim= ; list of Animation
323+
Shield.HitAnims= ; list of Animation, overrides Shield.HitAnim
320324
Shield.SkipHitAnim=false ; boolean
321325
Shield.HitFlash=true ; boolean
322326
Shield.BreakWeapon= ; WeaponType
@@ -372,8 +376,8 @@ Shield.InheritStateOnReplace=false ; boolean
372376
- `Bouncer=true` and `IsMeteor=true` animations can exhibit irregular behaviour when used as `IdleAnim` and should be avoided.
373377
- `IdleAnim.OfflineAction` indicates what happens to the animation when the shield is in a low power state.
374378
- `IdleAnim.TemporalAction` indicates what happens to the animation when the shield is attacked by temporal weapons.
375-
- `BreakAnim`, if set, will be played when the shield has been broken.
376-
- `HitAnim`, if set, will be played when the shield is attacked, similar to `WeaponNullifyAnim` for Iron Curtain.
379+
- `BreakAnim(s)`, if set, will be played when the shield has been broken. If more than one animation is listed, a random one is selected. If both are set, `BreakAnims` will override `BreakAnim`.
380+
- `HitAnim(s)`, if set, will be played when the shield is attacked, similar to `WeaponNullifyAnim` for Iron Curtain. If more than one animation is listed, a random one is selected. If both are set, `HitAnims` will override `HitAnim`.
377381
- `HitFlash`, if set to true, makes it so that a light flash is generated when the shield is attacked by a Warhead unless it has `Shield.HitFlash=false`. Size of the flash is determined by damage dealt, unless `HitFlash.FixedSize` is set to a number, in which case that value is used instead (range of values that produces visible effect are increments of 4 from 81 to 252, anything higher or below does not have effect). Color can be customized via `HitFlash.Red/Green/Blue`. If `HitFlash.Black` is set to true, the generated flash will be black regardless of other color settings.
378382
- `BreakWeapon`, if set, will be fired at the TechnoType once the shield breaks.
379383
- `AbsorbPercent` controls the percentage of damage that will be absorbed by the shield. Defaults to 1.0, meaning full damage absorption.
@@ -394,8 +398,8 @@ Shield.InheritStateOnReplace=false ; boolean
394398
- Warheads have new options that interact with shields. Note that all of these that do not by their very nature require ability to target the shield (such as modifiers like `Shield.Break` or removing / attaching) still require Warhead `Verses` to affect the target unless `EffectsRequireVerses` is set to false on the Warhead.
395399
- `Shield.Penetrate` allows the warhead ignore the shield and always deal full damage to the TechnoType itself. It also allows targeting the TechnoType as if shield doesn't exist.
396400
- `Shield.Break` allows the warhead to always break shields of TechnoTypes. This is done before damage is dealt.
397-
- `Shield.BreakAnim` will be displayed instead of ShieldType `BreakAnim` if the shield is broken by the Warhead, either through damage or `Shield.Break`.
398-
- `Shield.HitAnim` will be displayed instead of ShieldType `HitAnim` if set when Warhead hits the shield.
401+
- `Shield.BreakAnim(s)` will be displayed instead of ShieldType `BreakAnim(s)` if the shield is broken by the Warhead, either through damage or `Shield.Break`. If more than one animation is listed, a random one is selected. If both are set, `Shield.BreakAnims` will override `Shield.BreakAnim`.
402+
- `Shield.HitAnim(s)` will be displayed instead of ShieldType `HitAnim(s)` if set when Warhead hits the shield. If more than one animation is listed, a random one is selected. If both are set, `Shield.HitAnims` will override `Shield.HitAnim`.
399403
- If `Shield.SkipHitAnim` is set to true, no hit anim is shown when the Warhead damages the shield whatsoever.
400404
- `Shield.BreakWeapon` will be fired instead of ShieldType `BreakWeapon` if the shield is broken by the Warhead, either through damage or `Shield.Break`.
401405
- `Shield.AbsorbPercent` overrides the `AbsorbPercent` value set in the ShieldType that is being damaged.
@@ -431,7 +435,7 @@ Shield.InheritStateOnReplace=false ; boolean
431435
- `CreateUnit.AlwaysSpawnOnGround`, if set to true, ensures the vehicle will be created on the cell at ground level even if animation is in air. If set to false, jumpjet units spawned on ground will take off automatically after being spawned regardless.
432436
- `CreateUnit.SpawnParachutedInAir`, if set to true, makes it so that the vehicle is created with a parachute if it is spawned in air. Has no effect if `CreateUnit.AlwaysSpawnOnGround` is set to true.
433437
- `CreateUnit.ConsiderPathfinding`, if set to true, will consider whether or not the cell where the animation is located is occupied by other objects or impassable to the vehicle being created and will attempt to find a nearby cell that is not. Otherwise the vehicle will be created at the animation's location despite these obstacles if possible.
434-
- `CreateUnit.SpawnAnim` can be used to play another animation at created unit's location after it has appeared. This animation has same owner and invoker as the parent animation.
438+
- `CreateUnit.SpawnAnim(s)` can be used to play another animation at created unit's location after it has appeared. This animation has same owner and invoker as the parent animation. If more than one animation is listed, a random one is selected. If both are set, `CreateUnit.SpawnAnims` will override `CreateUnit.SpawnAnim`.
435439
- `CreateUnit.SpawnHeight` can be set to override the animation's height when determining where to spawn the created unit. Has no effect if `CreateUnit.AlwaysSpawnOnGround` is set to true.
436440

437441
In `artmd.ini`:
@@ -449,7 +453,8 @@ CreateUnit.InheritTurretFacings=false ; boolean
449453
CreateUnit.AlwaysSpawnOnGround=false ; boolean
450454
CreateUnit.SpawnParachutedInAir=false ; boolean
451455
CreateUnit.ConsiderPathfinding=false ; boolean
452-
CreateUnit.SpawnAnim= ; Animation
456+
CreateUnit.SpawnAnim= ; list of Animation
457+
CreateUnit.SpawnAnims= ; list of Animation, overrides CreateUnit.SpawnAnim
453458
CreareUnit.SpawnHeight= ; integer, height in leptons
454459
```
455460

@@ -907,7 +912,7 @@ Spawner.AttackImmediately=false ; boolean
907912
- `PassengerDeletion.SoylentMultiplier` is a direct multiplier applied to the refunded amount of credits.
908913
- `PassengerDeletion.SoylentAllowedHouses` determines which houses passengers can belong to be eligible for refunding.
909914
- `PassengerDeletion.DisplaySoylent` can be set to true to display the amount of credits refunded on the transport. `PassengerDeletion.DisplaySoylentToHouses` determines which houses can see this and `PassengerDeletion.DisplaySoylentOffset` can be used to adjust the display offset.
910-
- `PassengerDeletion.ReportSound` and `PassengerDeletion.Anim` can be used to specify a sound and animation to play when a passenger is erased, respectively.
915+
- `PassengerDeletion.ReportSound` and `PassengerDeletion.Anim(s)` can be used to specify a sound and animation to play when a passenger is erased, respectively. If more than one animation is listed, a random one is selected. If both are set, `PassengerDeletion.Anims` will override `PassengerDeletion.Anim`.
911916

912917
In `rulesmd.ini`:
913918
```ini
@@ -926,7 +931,8 @@ PassengerDeletion.DisplaySoylent=false ; boolean
926931
PassengerDeletion.DisplaySoylentToHouses=All ; Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all)
927932
PassengerDeletion.DisplaySoylentOffset=0,0 ; X,Y, pixels relative to default
928933
PassengerDeletion.ReportSound= ; Sound
929-
PassengerDeletion.Anim= ; Animation
934+
PassengerDeletion.Anim= ; list of Animation
935+
PassengerDeletion.Anims= ; list of Animation, overrides PassengerDeletion.Anim
930936
```
931937

932938
### Automatic passenger owner change to match transport owner
@@ -1109,7 +1115,7 @@ Both `InitialStrength` and `InitialStrength.Cloning` never surpass the type's `S
11091115
- `vanish`: The object will be directly removed from the game peacefully instead of actually getting killed.
11101116
- `sell`: If the object is a **building** with buildup, it will be sold instead of destroyed.
11111117

1112-
If this option is not set, the self-destruction logic will not be enabled. `AutoDeath.VanishAnimation` can be set to animation to play at object's location if `vanish` behaviour is chosen.
1118+
If this option is not set, the self-destruction logic will not be enabled. `AutoDeath.VanishAnimation(s)` can be set to animation to play at object's location if `vanish` behaviour is chosen. If more than one animation is listed, a random one is selected. If both are set, `AutoDeath.VanishAnimations` will override `AutoDeath.VanishAnimation`.
11131119

11141120
```{note}
11151121
Please notice that if the object is a unit which carries passengers, they will not be released even with the `kill` option **if you are not using Ares 3.0+**.
@@ -1121,7 +1127,8 @@ In `rulesmd.ini`:
11211127
```ini
11221128
[SOMETECHNO] ; TechnoType
11231129
AutoDeath.Behavior= ; enumeration (kill | vanish | sell), default not set
1124-
AutoDeath.VanishAnimation ; Animation
1130+
AutoDeath.VanishAnimation= ; list of Animation
1131+
AutoDeath.VanishAnimations= ; list of Animation, overrides AutoDeath.VanishAnimation
11251132
AutoDeath.OnAmmoDepletion=no ; boolean
11261133
AutoDeath.AfterDelay=0 ; positive integer
11271134
AutoDeath.TechnosDontExist= ; list of TechnoType names
@@ -1279,11 +1286,13 @@ Convert.ComputerToHuman = ; TechnoType
12791286
### Destroy animation & sound
12801287

12811288
- You can now specify a destroy animation and sound for a TerrainType that are played when it is destroyed.
1289+
- If more than one animation is listed in `DestroyAnim(s)`, a random one is selected. If both are set, `DestroyAnims` will override `DestroyAnim`.
12821290

12831291
In `rulesmd.ini`:
12841292
```ini
12851293
[SOMETERRAINTYPE] ; TerrainType
1286-
DestroyAnim= ; Animation
1294+
DestroyAnim= ; list of Animation
1295+
DestroyAnims= ; list of Animation, overrides DestroyAnim
12871296
DestroySound= ; Sound
12881297
```
12891298

src/Ext/Anim/Hooks.AnimCreateUnit.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,17 @@ DEFINE_HOOK(0x424932, AnimClass_AI_CreateUnit_ActualAffects, 0x6)
144144

145145
if (success)
146146
{
147-
if (auto const pAnimType = pTypeExt->CreateUnit_SpawnAnim)
147+
if (!pTypeExt->CreateUnit_SpawnAnim.empty())
148148
{
149-
if (auto const pAnim = GameCreate<AnimClass>(pAnimType, location))
149+
if (auto const pAnimType = pTypeExt->CreateUnit_SpawnAnim[ScenarioClass::Instance->Random.RandomRanged(0, pTypeExt->CreateUnit_SpawnAnim.size() - 1)])
150150
{
151-
AnimExt::SetAnimOwnerHouseKind(pAnim, pInvokerHouse, nullptr, false, true);
151+
if (auto const pAnim = GameCreate<AnimClass>(pAnimType, location))
152+
{
153+
AnimExt::SetAnimOwnerHouseKind(pAnim, pInvokerHouse, nullptr, false, true);
152154

153-
if (auto const pAnimExt = AnimExt::ExtMap.Find(pAnim))
154-
pAnimExt->SetInvoker(pInvoker, pInvokerHouse);
155+
if (auto const pAnimExt = AnimExt::ExtMap.Find(pAnim))
156+
pAnimExt->SetInvoker(pInvoker, pInvokerHouse);
157+
}
155158
}
156159
}
157160

src/Ext/AnimType/Body.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ void AnimTypeExt::ExtData::LoadFromINIFile(CCINIClass* pINI)
9797
this->CreateUnit_SpawnParachutedInAir.Read(exINI, pID, "CreateUnit.SpawnParachutedInAir");
9898
this->CreateUnit_ConsiderPathfinding.Read(exINI, pID, "CreateUnit.ConsiderPathfinding");
9999
this->CreateUnit_SpawnAnim.Read(exINI, pID, "CreateUnit.SpawnAnim");
100+
this->CreateUnit_SpawnAnim.Read(exINI, pID, "CreateUnit.SpawnAnims");
100101
this->CreateUnit_SpawnHeight.Read(exINI, pID, "CreateUnit.SpawnHeight");
101102
this->XDrawOffset.Read(exINI, pID, "XDrawOffset");
102103
this->HideIfNoOre_Threshold.Read(exINI, pID, "HideIfNoOre.Threshold");

src/Ext/AnimType/Body.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class AnimTypeExt
3030
Valueable<bool> CreateUnit_AlwaysSpawnOnGround;
3131
Valueable<bool> CreateUnit_SpawnParachutedInAir;
3232
Valueable<bool> CreateUnit_ConsiderPathfinding;
33-
Valueable<AnimTypeClass*> CreateUnit_SpawnAnim;
33+
ValueableVector<AnimTypeClass*> CreateUnit_SpawnAnim;
3434
Nullable<int> CreateUnit_SpawnHeight;
3535
Valueable<int> XDrawOffset;
3636
Valueable<int> HideIfNoOre_Threshold;

src/Ext/Techno/Body.Update.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo)
136136

137137
// Self-destruction must be enabled
138138
const auto howToDie = pTypeExt->AutoDeath_Behavior.Get();
139-
const auto pVanishAnim = pTypeExt->AutoDeath_VanishAnimation;
139+
AnimTypeClass* pVanishAnim = nullptr;
140+
141+
if (!pTypeExt->AutoDeath_VanishAnimation.empty())
142+
pVanishAnim = pTypeExt->AutoDeath_VanishAnimation[ScenarioClass::Instance->Random.RandomRanged(0, pTypeExt->AutoDeath_VanishAnimation.size() - 1)];
140143

141144
// Death if no ammo
142145
if (pType->Ammo > 0 && pThis->Ammo <= 0 && pTypeExt->AutoDeath_OnAmmoDepletion)
@@ -283,11 +286,16 @@ void TechnoExt::ExtData::EatPassengers()
283286
if (pDelType->ReportSound >= 0)
284287
VocClass::PlayAt(pDelType->ReportSound.Get(), pThis->GetCoords(), nullptr);
285288

286-
if (const auto pAnimType = pDelType->Anim.Get())
289+
if (!pDelType->Anim.empty())
287290
{
288-
auto const pAnim = GameCreate<AnimClass>(pAnimType, pThis->Location);
289-
pAnim->SetOwnerObject(pThis);
290-
pAnim->Owner = pThis->Owner;
291+
if (auto const pAnimType = pDelType->Anim[ScenarioClass::Instance->Random.RandomRanged(0, pDelType->Anim.size() - 1)])
292+
{
293+
if (auto const pAnim = GameCreate<AnimClass>(pAnimType, pThis->Location))
294+
{
295+
pAnim->SetOwnerObject(pThis);
296+
pAnim->Owner = pThis->Owner;
297+
}
298+
}
291299
}
292300

293301
// Check if there is money refund

src/Ext/TechnoType/Body.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
164164

165165
this->AutoDeath_Behavior.Read(exINI, pSection, "AutoDeath.Behavior");
166166
this->AutoDeath_VanishAnimation.Read(exINI, pSection, "AutoDeath.VanishAnimation");
167+
this->AutoDeath_VanishAnimation.Read(exINI, pSection, "AutoDeath.VanishAnimations");
167168
this->AutoDeath_OnAmmoDepletion.Read(exINI, pSection, "AutoDeath.OnAmmoDepletion");
168169
this->AutoDeath_AfterDelay.Read(exINI, pSection, "AutoDeath.AfterDelay");
169170
this->AutoDeath_TechnosDontExist.Read(exINI, pSection, "AutoDeath.TechnosDontExist");

src/Ext/TechnoType/Body.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class TechnoTypeExt
6767
Valueable<int> Ammo_DeployUnlockMaximumAmount;
6868

6969
Nullable<AutoDeathBehavior> AutoDeath_Behavior;
70-
Valueable<AnimTypeClass*> AutoDeath_VanishAnimation;
70+
ValueableVector<AnimTypeClass*> AutoDeath_VanishAnimation;
7171
Valueable<bool> AutoDeath_OnAmmoDepletion;
7272
Valueable<int> AutoDeath_AfterDelay;
7373
ValueableVector<TechnoTypeClass*> AutoDeath_TechnosDontExist;

src/Ext/TerrainType/Body.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <TerrainClass.h>
66
#include <TerrainTypeClass.h>
77

8+
#include <Ext/Scenario/Body.h>
89
#include <Utilities/GeneralUtils.h>
910

1011
TerrainTypeExt::ExtContainer TerrainTypeExt::ExtMap;
@@ -23,8 +24,11 @@ void TerrainTypeExt::ExtData::PlayDestroyEffects(const CoordStruct& coords)
2324
{
2425
VocClass::PlayIndexAtPos(this->DestroySound, coords);
2526

26-
if (auto const pAnimType = this->DestroyAnim)
27-
GameCreate<AnimClass>(pAnimType, coords);
27+
if (!this->DestroyAnim.empty())
28+
{
29+
if (auto const pAnimType = this->DestroyAnim[ScenarioClass::Instance->Random.RandomRanged(0, this->DestroyAnim.size() - 1)])
30+
GameCreate<AnimClass>(pAnimType, coords);
31+
}
2832
}
2933

3034
void TerrainTypeExt::Remove(TerrainClass* pTerrain)
@@ -78,6 +82,7 @@ void TerrainTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
7882
this->SpawnsTiberium_CellsPerAnim.Read(exINI, pSection, "SpawnsTiberium.CellsPerAnim");
7983

8084
this->DestroyAnim.Read(exINI, pSection, "DestroyAnim");
85+
this->DestroyAnim.Read(exINI, pSection, "DestroyAnims");
8186
this->DestroySound.Read(exINI, pSection, "DestroySound");
8287

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

src/Ext/TerrainType/Body.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class TerrainTypeExt
2121
Valueable<int> SpawnsTiberium_Range;
2222
Valueable<PartialVector2D<int>> SpawnsTiberium_GrowthStage;
2323
Valueable<PartialVector2D<int>> SpawnsTiberium_CellsPerAnim;
24-
Valueable<AnimTypeClass*> DestroyAnim;
24+
ValueableVector<AnimTypeClass*> DestroyAnim;
2525
ValueableIdx<VocClass> DestroySound;
2626
Nullable<ColorStruct> MinimapColor;
2727
Valueable<bool> IsPassable;

src/Ext/WarheadType/Body.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,9 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
196196
this->Shield_Penetrate.Read(exINI, pSection, "Shield.Penetrate");
197197
this->Shield_Break.Read(exINI, pSection, "Shield.Break");
198198
this->Shield_BreakAnim.Read(exINI, pSection, "Shield.BreakAnim");
199+
this->Shield_BreakAnim.Read(exINI, pSection, "Shield.BreakAnims");
199200
this->Shield_HitAnim.Read(exINI, pSection, "Shield.HitAnim");
201+
this->Shield_HitAnim.Read(exINI, pSection, "Shield.HitAnims");
200202
this->Shield_SkipHitAnim.Read(exINI, pSection, "Shield.SkipHitAnim");
201203
this->Shield_HitFlash.Read(exINI, pSection, "Shield.HitFlash");
202204
this->Shield_BreakWeapon.Read<true>(exINI, pSection, "Shield.BreakWeapon");

src/Ext/WarheadType/Body.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ class WarheadTypeExt
6969

7070
Valueable<bool> Shield_Penetrate;
7171
Valueable<bool> Shield_Break;
72-
Valueable<AnimTypeClass*> Shield_BreakAnim;
73-
Valueable<AnimTypeClass*> Shield_HitAnim;
72+
ValueableVector<AnimTypeClass*> Shield_BreakAnim;
73+
ValueableVector<AnimTypeClass*> Shield_HitAnim;
7474
Valueable<bool> Shield_SkipHitAnim;
7575
Valueable<bool> Shield_HitFlash;
7676
Nullable<WeaponTypeClass*> Shield_BreakWeapon;

src/Ext/WarheadType/Detonate.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,14 @@ void WarheadTypeExt::ExtData::ApplyShieldModifiers(TechnoClass* pTarget, TechnoE
253253
};
254254

255255
if (this->Shield_Break && pTargetExt->Shield->IsActive() && isShieldTypeEligible(this->Shield_Break_Types.GetElements(this->Shield_AffectTypes)))
256-
pTargetExt->Shield->BreakShield(this->Shield_BreakAnim, this->Shield_BreakWeapon);
256+
{
257+
AnimTypeClass* pAnimType = nullptr;
258+
259+
if (!this->Shield_BreakAnim.empty())
260+
pAnimType = this->Shield_BreakAnim[ScenarioClass::Instance->Random.RandomRanged(0, this->Shield_BreakAnim.size() - 1)];
261+
262+
pTargetExt->Shield->BreakShield(pAnimType, this->Shield_BreakWeapon);
263+
}
257264

258265
if (this->Shield_Respawn_Duration > 0 && isShieldTypeEligible(this->Shield_Respawn_Types.GetElements(this->Shield_AffectTypes)))
259266
{

0 commit comments

Comments
 (0)