Skip to content

Commit f55d148

Browse files
committed
Add additional draw offset logic for attached and AE animations
- Also optimize AE animation drawing logic update
1 parent 47b4713 commit f55d148

16 files changed

Lines changed: 253 additions & 34 deletions

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ This page lists all the individual contributions to the project by their author.
292292
- Fix vehicles disguised as trees incorrectly displaying veterancy insignia when they shouldn't
293293
- GapGen + SpySat desync fix
294294
- Frame CRC generation rewrite
295+
- Attached animation draw offset customizations
295296
- **Morton (MortonPL)**:
296297
- `XDrawOffset` for animations
297298
- Shield passthrough & absorption

docs/Fixed-or-Improved-Logics.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
5252

5353
- Vehicle to building deployers now keep their target when deploying with `DeployToFire`.
5454
- Effects like lasers are no longer drawn from wrong firing offset on weapons that use Burst.
55-
- Animations can now be offset on the X axis with `XDrawOffset`.
5655
- `IsSimpleDeployer` units now only play `DeploySound` and `UndeploySound` once, when done with (un)deploying instead of repeating it over duration of turning and/or `DeployingAnim`.
5756
- AITrigger can now recognize Building Upgrades as legal condition.
5857
- `EWGates` and `NSGates` now will link walls like `xxGateOne` and `xxGateTwo` do.
@@ -889,6 +888,23 @@ In `artmd.ini`:
889888
Crater.DestroyTiberium= ; boolean, default to [General] -> AnimCraterDestroyTiberium
890889
```
891890

891+
### Draw offset customization
892+
893+
- `XDrawOffset` can be used to adjust horizontal/X axis position of the animation.
894+
- `YDrawOffset.ApplyBracketHeight` makes Y axis position follow it's owner object's selection bracket height (for buildings, this is based on `Height` and `Foundation`, for others it is influenced by `PixelSelectionBracketDelta`) if it is attached to one.
895+
- By default this will only apply if the bracket position is negative e.g it is moved upwards from the object center. If `YDrawOffset.InvertBracketShift` is set to true, the opposite is true and negative shift is ignored.
896+
- The bracket-based shift can be further adjusted with offset from `YDrawOffset.BracketAdjust`, overridden by `YDrawOffset.BracketAdjust.Buildings` for buildings only.
897+
898+
In `artmd.ini`:
899+
```ini
900+
[SOMEANIM] ; AnimationType
901+
XDrawOffset=0,0 ; X,Y, pixels relative to default
902+
YDrawOffset.ApplyBracketHeight=false ; boolean
903+
YDrawOffset.InvertBracketShift=false ; boolean
904+
YDrawOffset.BracketAdjust=0,0 ; X,Y, pixels relative to default
905+
YDrawOffset.BracketAdjust.Buildings= ; X,Y, pixels relative to default
906+
```
907+
892908
### Fire animations spawned by Scorch & Flamer
893909

894910
- Tiberian Sun allowed `Scorch=true` and `Flamer=true` animations to spawn fire animations from `[AudioVisual] -> SmallFire` & `LargeFire`. This behaviour has been reimplemented and is fully customizable.

docs/New-or-Enhanced-Logics.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ This page describes all the engine features that are either new and introduced b
3131
- `Animation.TemporalAction` determines what happens to the animation when the attached object is under effect of `Temporal=true` Warhead.
3232
- `Animation.UseInvokerAsOwner` can be used to set the house and TechnoType that created the effect (e.g firer of the weapon that applied it) as the animation's owner & invoker instead of the object the effect is attached to.
3333
- `Animation.HideIfAttachedWith` contains list of other AttachEffectTypes that if attached to same techno as the current one, will hide this effect's animation.
34+
- `Animation.DrawOffsetN` (where N is integer starting from 0) can be used to define draw offset rules for the animation. These are parsed starting from index 0 until offset with value 0,0 is encountered.
35+
- `Animation.DrawOffsetN.RequiredTypes` contains list other AttachEffectTypes that need to be attached on the same techno as the current one for the draw offset rule to apply. Note that this does not currently work correctly together with `Animation.HideIfAttachedWith`, animations hidden by this may not cause drawing offset rules to be updated even if they should.
3436
- `CumulativeAnimations` can be used to declare a list of animations used for `Cumulative=true` types instead of `Animation`. An animation is picked from the list in order matching the number of active instances of the type on the object, with last listed animation used if number is higher than the number of listed animations. This animation is only displayed once and is transferred from the effect to another of same type (specifically one with longest remaining duration), if such exists, upon expiration or removal. Note that because `Cumulative.MaxCount` limits the number of effects of same type that can be applied this can cause animations to 'flicker' here as effects expire before new ones can be applied in some circumstances.
3537
- `CumulativeAnimations.RestartOnChange` determines if the animation playback is restarted when the type of animation changes, if not then playback resumes at frame at same position relative to the animation's length.
3638
- Attached effect can fire off a weapon when expired / removed / object dies by setting `ExpireWeapon`.
@@ -110,6 +112,8 @@ Animation.OfflineAction=Hides ; AttachedAnimFlag (None, Hid
110112
Animation.TemporalAction=None ; AttachedAnimFlag (None, Hides, Temporal, Paused or PausedTemporal)
111113
Animation.UseInvokerAsOwner=false ; boolean
112114
Animation.HideIfAttachedWith= ; List of AttachEffectTypes
115+
Animation.DrawOffsetN=0,0 ; X,Y, pixels relative to default
116+
Animation.DrawOffsetN.RequiredTypes= ; List of AttachEffectTypes
113117
CumulativeAnimations= ; List of AnimationTypes
114118
CumulativeAnimations.RestartOnChange=true ; boolean
115119
ExpireWeapon= ; WeaponType

docs/Whats-New.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@ New:
576576
- Customize `HarvesterLoadRate` (by Noble_Fish)
577577
- [Toggle to prevent `ShrapnelWeapon` from targeting buildings multiple times](Fixed-or-Improved-Logics.md#shrapnel-enhancements) (by Starkku)
578578
- [Laser drawing Z-adjust customization](Fixed-or-Improved-Logics.md#laser-z-adjust) (by Starkku)
579+
- [Attached animation draw offset customizations](Fixed-or-Improved-Logics.md#draw-offset-customization) (by Starkku)
580+
- [Draw offset rules for AttachEffect animations](New-or-Enhanced-Logics.md#attached-effects) by (Starkku)
579581
580582
Vanilla fixes:
581583
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)

src/Ext/Anim/Body.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ void AnimExt::ExtData::Serialize(T& Stm)
435435
.Process(this->FromWeapon)
436436
.Process(this->FromWeaponIdx)
437437
.Process(this->FromBurstIdx)
438+
.Process(this->AEDrawOffset)
438439
;
439440
}
440441

src/Ext/Anim/Body.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class AnimExt
3030
WeaponTypeClass* FromWeapon;
3131
int FromWeaponIdx;
3232
int FromBurstIdx;
33+
Point2D AEDrawOffset;
3334

3435
ExtData(AnimClass* OwnerObject) : Extension<AnimClass>(OwnerObject)
3536
, DeathUnitFacing { 0 }
@@ -47,6 +48,7 @@ class AnimExt
4748
, FromWeapon {}
4849
, FromWeaponIdx {}
4950
, FromBurstIdx {}
51+
, AEDrawOffset { Point2D::Empty }
5052
{ }
5153

5254
void SetInvoker(TechnoClass* pInvoker);

src/Ext/Anim/Hooks.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,57 @@ DEFINE_HOOK(0x424CF1, AnimClass_Start_DetachedReport, 0x6)
270270
}
271271

272272
// 0x422CD8 is in an alternate code path only used by anims with ID RING1, unused normally but covering it just because
273-
DEFINE_HOOK_AGAIN(0x422CD8, AnimClass_DrawIt_XDrawOffset, 0x6)
274-
DEFINE_HOOK(0x423122, AnimClass_DrawIt_XDrawOffset, 0x6)
273+
DEFINE_HOOK_AGAIN(0x422CD8, AnimClass_DrawIt_DrawOffset, 0x6)
274+
DEFINE_HOOK(0x423122, AnimClass_DrawIt_DrawOffset, 0x6)
275275
{
276276
GET(AnimClass* const, pThis, ESI);
277277
GET_STACK(Point2D*, pLocation, STACK_OFFSET(0x110, 0x4));
278278

279-
if (auto const pTypeExt = AnimTypeExt::ExtMap.TryFind(pThis->Type))
280-
pLocation->X += pTypeExt->XDrawOffset;
279+
auto const pTypeExt = AnimTypeExt::ExtMap.TryFind(pThis->Type);
280+
pLocation->X += pTypeExt->XDrawOffset;
281+
282+
if (pTypeExt->YDrawOffset_ApplyBracketHeight && pThis->OwnerObject && pThis->OwnerObject->AbstractFlags & AbstractFlags::Techno)
283+
{
284+
// Le magic number.
285+
constexpr int SHIELD_HEALTHBAR_OFFSET = -3;
286+
287+
auto const pTechno = static_cast<TechnoClass*>(pThis->OwnerObject);
288+
bool inverse = pTypeExt->YDrawOffset_InvertBracketShift;
289+
290+
if (auto const pBuilding = abstract_cast<BuildingClass*>(pTechno))
291+
{
292+
auto const pType = pBuilding->Type;
293+
294+
if ((pType->Height >= 0 && !inverse) || (pType->Height < 0 && inverse))
295+
{
296+
auto const pos = TechnoExt::GetBuildingSelectBracketPosition(pBuilding, BuildingSelectBracketPosition::Top);
297+
pLocation->Y = pos.Y + pTypeExt->YDrawOffset_BracketAdjust_Buildings.Get(pTypeExt->YDrawOffset_BracketAdjust);
298+
}
299+
}
300+
else
301+
{
302+
auto const pType = pTechno->GetTechnoType();
303+
304+
if ((pType->PixelSelectionBracketDelta <= 0 && !inverse) || (pType->PixelSelectionBracketDelta > 0 && inverse))
305+
{
306+
auto const pos = TechnoExt::GetFootSelectBracketPosition(pTechno, Anchor(HorizontalPosition::Left, VerticalPosition::Top));
307+
pLocation->Y = pos.Y + pType->PixelSelectionBracketDelta + pTypeExt->YDrawOffset_BracketAdjust;
308+
}
309+
}
310+
311+
if (auto const pShield = TechnoExt::ExtMap.Find(pTechno)->Shield.get())
312+
{
313+
auto const pShieldType = pShield->GetType();
314+
315+
if (pShield->IsAvailable() && !pShield->IsBrokenAndNonRespawning() && (pShield->GetHealthRatio() > 0.0 || !pShieldType->Pips_HideIfNoStrength))
316+
{
317+
if ((pShieldType->BracketDelta <= 0 && !inverse) || (pShieldType->BracketDelta > 0 && inverse))
318+
pLocation->Y += pShieldType->BracketDelta + SHIELD_HEALTHBAR_OFFSET;
319+
}
320+
}
321+
}
322+
323+
*pLocation += AnimExt::ExtMap.Find(pThis)->AEDrawOffset;
281324

282325
return 0;
283326
}

src/Ext/AnimType/Body.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ void AnimTypeExt::ExtData::LoadFromINIFile(CCINIClass* pINI)
8080

8181
this->Palette.LoadFromINI(pINI, pID, "CustomPalette");
8282
this->XDrawOffset.Read(exINI, pID, "XDrawOffset");
83+
this->YDrawOffset_ApplyBracketHeight.Read(exINI, pID, "YDrawOffset.ApplyBracketHeight");
84+
this->YDrawOffset_InvertBracketShift.Read(exINI, pID, "YDrawOffset.InvertBracketShift");
85+
this->YDrawOffset_BracketAdjust.Read(exINI, pID, "YDrawOffset.BracketAdjust");
86+
this->YDrawOffset_BracketAdjust_Buildings.Read(exINI, pID, "YDrawOffset.BracketAdjust.Buildings");
8387
this->HideIfNoOre_Threshold.Read(exINI, pID, "HideIfNoOre.Threshold");
8488
this->Layer_UseObjectLayer.Read(exINI, pID, "Layer.UseObjectLayer");
8589
this->AttachedAnimPosition.Read(exINI, pID, "AttachedAnimPosition");
@@ -139,6 +143,10 @@ void AnimTypeExt::ExtData::Serialize(T& Stm)
139143
.Process(this->Palette)
140144
.Process(this->CreateUnitType)
141145
.Process(this->XDrawOffset)
146+
.Process(this->YDrawOffset_ApplyBracketHeight)
147+
.Process(this->YDrawOffset_InvertBracketShift)
148+
.Process(this->YDrawOffset_BracketAdjust)
149+
.Process(this->YDrawOffset_BracketAdjust_Buildings)
142150
.Process(this->HideIfNoOre_Threshold)
143151
.Process(this->Layer_UseObjectLayer)
144152
.Process(this->AttachedAnimPosition)

src/Ext/AnimType/Body.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class AnimTypeExt
2828
CustomPalette Palette;
2929
std::unique_ptr<CreateUnitTypeClass> CreateUnitType;
3030
Valueable<int> XDrawOffset;
31+
Valueable<bool> YDrawOffset_ApplyBracketHeight;
32+
Valueable<bool> YDrawOffset_InvertBracketShift;
33+
Valueable<int> YDrawOffset_BracketAdjust;
34+
Nullable<int> YDrawOffset_BracketAdjust_Buildings;
3135
Valueable<int> HideIfNoOre_Threshold;
3236
Nullable<bool> Layer_UseObjectLayer;
3337
Valueable<AttachedAnimPosition> AttachedAnimPosition;
@@ -67,6 +71,8 @@ class AnimTypeExt
6771
, Palette { CustomPalette::PaletteMode::Temperate }
6872
, CreateUnitType { nullptr }
6973
, XDrawOffset { 0 }
74+
, YDrawOffset_ApplyBracketHeight { false }
75+
, YDrawOffset_InvertBracketShift { false }
7076
, HideIfNoOre_Threshold { 0 }
7177
, Layer_UseObjectLayer {}
7278
, AttachedAnimPosition { AttachedAnimPosition::Default }

src/Ext/Techno/Body.Update.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,7 +1936,10 @@ void TechnoExt::ExtData::UpdateAttachEffects()
19361936
}
19371937

19381938
if (altered)
1939+
{
19391940
this->RecalculateStatMultipliers();
1941+
this->UpdateAEAnimDrawingLogic();
1942+
}
19401943

19411944
if (markForRedraw)
19421945
pThis->MarkForRedraw();
@@ -2008,7 +2011,10 @@ void TechnoExt::ExtData::UpdateSelfOwnedAttachEffects()
20082011
const int count = AttachEffectClass::Attach(pThis, pThis->Owner, pThis, pThis, pTypeExt->AttachEffects);
20092012

20102013
if (altered && !count)
2014+
{
20112015
this->RecalculateStatMultipliers();
2016+
this->UpdateAEAnimDrawingLogic();
2017+
}
20122018
}
20132019

20142020
// Updates CumulativeAnimations AE's on techno.
@@ -2053,6 +2059,15 @@ void TechnoExt::ExtData::UpdateCumulativeAttachEffects(AttachEffectTypeClass* pA
20532059
}
20542060
}
20552061

2062+
// Update AttachEffect animation drawing logic.
2063+
void TechnoExt::ExtData::UpdateAEAnimDrawingLogic()
2064+
{
2065+
for (auto const& attachEffect : this->AttachedEffects)
2066+
{
2067+
attachEffect->UpdateConditionalAnimDrawingLogic();
2068+
}
2069+
}
2070+
20562071
// Recalculates AttachEffect stat multipliers and other bonuses.
20572072
void TechnoExt::ExtData::RecalculateStatMultipliers()
20582073
{

0 commit comments

Comments
 (0)