Skip to content

Commit 3728a08

Browse files
NetsuNegiCrimRecyaCoronia
authored
Electric/RadBeam trail for laser tails (#1706)
- LaserTrail can now drawn as other behaviour like EBolt or RadBeam. - 激光轨迹现在可以绘制成电弧或辐射波的样式。 - You can also specific laser trail on attacheffect, the trail will disappear if attacheffect is expired. - 你也可以在AE上指定激光轨迹,这种激光轨迹将会在AE过期后消失。 [SOMETRAIL] ; LaserTrailType name DrawType=laser ; enumeration (laser | ebolt | radbeam) IsAlternateColor=false ; boolean Bolt.Color1= ; r, g, b Bolt.Disable1=false ; boolean Bolt.Color2= ; r, g, b Bolt.Disable2=false ; boolean Bolt.Color3= ; r, g, b Bolt.Disable3=false ; boolean Beam.Color= ; r, g, b Beam.Amplitude=40.0 ; double FadeDuration= ; integer, default 64 for laser, 17 for electric, 15 for radbeam [SOMEATTACHEFFECT] LaserTrail.Type= ; lasertrail type --------- Co-authored-by: CrimRecya <[email protected]> Co-authored-by: Coronia <[email protected]>
1 parent d3b814d commit 3728a08

36 files changed

+556
-157
lines changed

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ This page lists all the individual contributions to the project by their author.
416416
- Customize limit when engineer repair a building
417417
- Fix the bug that damaged particle dont disappear after building has repaired by engineer
418418
- Display banner improvement
419+
- Electric/RadBeam trail for laser tails
419420
- **Apollo** - Translucent SHP drawing patches
420421
- **ststl**:
421422
- Customizable `ShowTimer` priority of superweapons

Phobos.vcxproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
<ItemGroup>
2121
<ClCompile Include="src\Ext\Infantry\Hooks.Firing.cpp" />
2222
<ClCompile Include="src\Ext\Unit\Hooks.Firing.cpp" />
23+
<ClCompile Include="src\Ext\EBolt\Body.cpp" />
24+
<ClCompile Include="src\Ext\EBolt\Hooks.cpp" />
2325
<ClCompile Include="src\New\Type\Affiliated\CreateUnitTypeClass.cpp" />
2426
<ClCompile Include="src\Blowfish\blowfish.cpp" />
2527
<ClCompile Include="src\Blowfish\Hooks.Blowfish.cpp" />
@@ -167,7 +169,6 @@
167169
<ClCompile Include="src\Ext\VoxelAnim\Body.cpp" />
168170
<ClCompile Include="src\Ext\VoxelAnim\Hooks.cpp" />
169171
<ClCompile Include="src\Ext\WeaponType\Body.cpp" />
170-
<ClCompile Include="src\Ext\WeaponType\Hook.EBolt.cpp" />
171172
<ClCompile Include="src\Ext\WeaponType\Hooks.cpp" />
172173
<ClCompile Include="src\Ext\WeaponType\Hooks.DiskLaserRadius.cpp" />
173174
<ClCompile Include="src\Misc\BlittersFix.cpp" />
@@ -206,6 +207,7 @@
206207
<ClCompile Include="YRpp\StaticInits.cpp" />
207208
</ItemGroup>
208209
<ItemGroup>
210+
<ClInclude Include="src\Ext\EBolt\Body.h" />
209211
<ClInclude Include="src\New\Type\Affiliated\CreateUnitTypeClass.h" />
210212
<ClInclude Include="src\Blowfish\blowfish.h" />
211213
<ClInclude Include="src\Ext\Cell\Body.h" />

docs/New-or-Enhanced-Logics.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ ReflectDamage.Override= ; integer
142142
ReflectDamage.UseInvokerAsOwner=false ; boolean
143143
DisableWeapons=false ; boolean
144144
Unkillable=false ; boolean
145+
LaserTrail.Type= ; lasertrail type
145146
Groups= ; comma-separated list of strings (group IDs)
146147

147148
[SOMETECHNO] ; TechnoType
@@ -234,22 +235,36 @@ Due to performance concerns, unless any radiation type has `RadApplicationDelay.
234235

235236
- Technos, Projectiles, and VoxelAnims can now have colorful trails of different transparency, thickness and color, which are drawn via laser drawing code.
236237
- Technos, Projectiles, and VoxelAnims can have multiple laser trails. For technos each trail can have custom laser trail type and FLH offset relative to turret and body.
238+
- LaserTrail can also be drawn as EBolt or RadBeam.
237239

238240
In `artmd.ini`:
239241
```ini
240242
[LaserTrailTypes]
241243
0=SOMETRAIL
242244

243245
[SOMETRAIL] ; LaserTrailType name
244-
IsHouseColor=false ; boolean
245-
Color=255,0,0 ; integer - R,G,B
246-
FadeDuration=64 ; integer
247-
Thickness=4 ; integer
246+
DrawType=laser ; laser trail type (laser | ebolt | radbeam)
247+
FadeDuration= ; integer, default to 64 for laser, 17 for ebolt, 15 for radbeam
248248
SegmentLength=128 ; integer, minimal length of each trail segment
249249
IgnoreVertical=false ; boolean, whether the trail won't be drawn on vertical movement
250-
IsIntense=false ; boolean, whether the laser is "supported" (AKA prism forwarding)
251250
CloakVisible=false ; boolean, whether the laser is visible when the attached unit is cloaked
252251
CloakVisible.DetectedOnly=false ; boolean, whether CloakVisible=true laser is visible only to those who can detect the attached unit
252+
; laser
253+
Color=255,0,0 ; integer - R,G,B
254+
IsHouseColor=false ; boolean
255+
Thickness=4 ; integer
256+
IsIntense=false ; boolean, whether the laser is "supported" (AKA prism forwarding)
257+
; ebolt
258+
IsAlternateColor=false ; boolean
259+
Bolt.Color1= ; integer - R,G,B
260+
Bolt.Disable1=false ; boolean
261+
Bolt.Color2= ; integer - R,G,B
262+
Bolt.Disable2=false ; boolean
263+
Bolt.Color3= ; integer - R,G,B
264+
Bolt.Disable3=false ; boolean
265+
; radbeam
266+
Beam.Color= ; integer - R,G,B
267+
Beam.Amplitude=40.0 ; floating point value
253268

254269
[SOMEPROJECTILE] ; Projectile Image
255270
LaserTrail.Types=SOMETRAIL ; List of LaserTrailTypes
@@ -263,8 +278,8 @@ LaserTrailN.IsOnTurret=false ; boolean, whether the trail origin is turret
263278

264279
In `rulesmd.ini`:
265280
```ini
266-
[SOMEVOXELANIM] ; VoxelAnim
267-
LaserTrail.Types=SOMETRAIL ; List of LaserTrailTypes
281+
[SOMEVOXELANIM] ; VoxelAnim
282+
LaserTrail.Types=SOMETRAIL ; List of LaserTrailTypes
268283
```
269284

270285
```{warning}

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ New:
405405
- [Customizable debris trailer anim spawn delay](Fixed-or-Improved-Logics.md#customizable-debris-trailer-anim-spawn-delay) (by CrimRecya)
406406
- [Display banner](AI-Scripting-and-Mapping.md#display-banner) (by Morton & ststl)
407407
- Allows refineries to use multiple ActiveAnim simultaneously (by TaranDahl)
408+
- Electric/RadBeam trail for laser tails (by NetsuNegi)
408409
409410
Vanilla fixes:
410411
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)

src/Ext/Bullet/Body.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <Ext/WeaponType/Body.h>
77
#include <Ext/WarheadType/Body.h>
88
#include <Ext/Cell/Body.h>
9+
#include <Ext/EBolt/Body.h>
910
#include <Utilities/EnumFunctions.h>
1011
#include <Utilities/AresFunctions.h>
1112
#include <Misc/FlyingStrings.h>
@@ -146,9 +147,7 @@ void BulletExt::ExtData::InitializeLaserTrails()
146147
this->LaserTrails.reserve(pTypeExt->LaserTrail_Types.size());
147148

148149
for (auto const& idxTrail : pTypeExt->LaserTrail_Types)
149-
{
150-
this->LaserTrails.emplace_back(LaserTrailTypeClass::Array[idxTrail].get(), pOwner);
151-
}
150+
this->LaserTrails.emplace_back(std::make_unique<LaserTrailClass>(LaserTrailTypeClass::Array[idxTrail].get(), pOwner));
152151
}
153152

154153
static inline int SetBuildingFireAnimZAdjust(BuildingClass* pBuilding, int animY)
@@ -258,12 +257,14 @@ inline void BulletExt::SimulatedFiringElectricBolt(BulletClass* pBullet)
258257
if (!pWeapon->IsElectricBolt)
259258
return;
260259

261-
const auto pEBolt = (AresFunctions::CreateAresEBolt ? AresFunctions::CreateAresEBolt(pWeapon) : GameCreate<EBolt>());
262-
pEBolt->AlternateColor = pWeapon->IsAlternateColor;
263-
auto& weaponStruct = WeaponTypeExt::BoltWeaponMap[pEBolt];
264-
weaponStruct.Weapon = WeaponTypeExt::ExtMap.Find(pWeapon);
265-
weaponStruct.BurstIndex = 0;
266-
pEBolt->Fire(pBullet->SourceCoords, (pBullet->Type->Inviso ? pBullet->Location : pBullet->TargetCoords), 0);
260+
const auto pBolt = EBoltExt::CreateEBolt(pWeapon);
261+
pBolt->AlternateColor = pWeapon->IsAlternateColor;
262+
263+
const auto targetCoords = pBullet->Type->Inviso ? pBullet->Location : pBullet->TargetCoords;
264+
pBolt->Fire(pBullet->SourceCoords, targetCoords, 0);
265+
266+
if (const auto particle = WeaponTypeExt::ExtMap.Find(pWeapon)->Bolt_ParticleSystem.Get(RulesClass::Instance->DefaultSparkSystem))
267+
GameCreate<ParticleSystemClass>(particle, targetCoords, nullptr, nullptr, CoordStruct::Empty, nullptr);
267268
}
268269

269270
// Make sure pBullet and pBullet->WeaponType is not empty before call

src/Ext/Bullet/Body.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class BulletExt
2525
bool IsInterceptor;
2626
InterceptedStatus InterceptedStatus;
2727
bool DetonateOnInterception;
28-
std::vector<LaserTrailClass> LaserTrails;
28+
std::vector<std::unique_ptr<LaserTrailClass>> LaserTrails;
2929
bool SnappedToTarget; // Used for custom trajectory projectile target snap checks
3030
int DamageNumberOffset;
3131

src/Ext/Bullet/Hooks.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ DEFINE_HOOK(0x4666F7, BulletClass_AI, 0x6)
3737
{
3838
GET(BulletClass*, pThis, EBP);
3939

40-
auto pBulletExt = BulletExt::ExtMap.Find(pThis);
40+
const auto pBulletExt = BulletExt::ExtMap.Find(pThis);
4141
BulletAITemp::ExtData = pBulletExt;
4242
BulletAITemp::TypeExtData = pBulletExt->TypeExtData;
4343

@@ -70,7 +70,7 @@ DEFINE_HOOK(0x4666F7, BulletClass_AI, 0x6)
7070
//Let trajectories draw their own laser trails after the Trajectory's OnAI() to avoid predicting incorrect positions or pass through targets.
7171
if (!pBulletExt->Trajectory && pBulletExt->LaserTrails.size())
7272
{
73-
CoordStruct location = pThis->GetCoords();
73+
const CoordStruct location = pThis->GetCoords();
7474
const BulletVelocity& velocity = pThis->Velocity;
7575

7676
// We adjust LaserTrails to account for vanilla bug of drawing stuff one frame ahead.
@@ -82,14 +82,14 @@ DEFINE_HOOK(0x4666F7, BulletClass_AI, 0x6)
8282
(int)(location.Z + velocity.Z)
8383
};
8484

85-
for (auto& trail : pBulletExt->LaserTrails)
85+
for (const auto& pTrail : pBulletExt->LaserTrails)
8686
{
8787
// We insert initial position so the first frame of trail doesn't get skipped - Kerbiter
8888
// TODO move hack to BulletClass creation
89-
if (!trail.LastLocation.isset())
90-
trail.LastLocation = location;
89+
if (!pTrail->LastLocation.isset())
90+
pTrail->LastLocation = location;
9191

92-
trail.Update(drawnCoords);
92+
pTrail->Update(drawnCoords);
9393
}
9494

9595
}

src/Ext/Bullet/Trajectories/BombardTrajectory.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ void BombardTrajectory::PrepareForOpenFire(BulletClass* pBullet)
235235

236236
if (pExt->LaserTrails.size())
237237
{
238-
for (auto& trail : pExt->LaserTrails)
239-
trail.LastLocation = middleLocation;
238+
for (const auto& pTrail : pExt->LaserTrails)
239+
pTrail->LastLocation = middleLocation;
240240
}
241241
this->RefreshBulletLineTrail(pBullet);
242242

@@ -560,9 +560,10 @@ void BombardTrajectory::BulletVelocityChange(BulletClass* pBullet)
560560

561561
if (pExt->LaserTrails.size())
562562
{
563-
for (auto& trail : pExt->LaserTrails)
564-
trail.LastLocation = middleLocation;
563+
for (const auto& pTrail : pExt->LaserTrails)
564+
pTrail->LastLocation = middleLocation;
565565
}
566+
566567
this->RefreshBulletLineTrail(pBullet);
567568

568569
pBullet->SetLocation(middleLocation);

src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ DEFINE_HOOK(0x467E53, BulletClass_AI_PreDetonation_Trajectories, 0x6)
462462

463463
auto const pExt = BulletExt::ExtMap.Find(pThis);
464464

465-
if (auto pTraj = pExt->Trajectory.get())
465+
if (auto const pTraj = pExt->Trajectory.get())
466466
pTraj->OnAIPreDetonate(pThis);
467467

468468
return 0;
@@ -476,7 +476,7 @@ DEFINE_HOOK(0x46745C, BulletClass_AI_Position_Trajectories, 0x7)
476476

477477
auto const pExt = BulletExt::ExtMap.Find(pThis);
478478

479-
if (auto pTraj = pExt->Trajectory.get())
479+
if (auto const pTraj = pExt->Trajectory.get())
480480
pTraj->OnAIVelocity(pThis, pSpeed, pPosition);
481481

482482
// Trajectory can use Velocity only for turning Image's direction
@@ -490,12 +490,12 @@ DEFINE_HOOK(0x46745C, BulletClass_AI_Position_Trajectories, 0x7)
490490
static_cast<int>(pSpeed->Z + pPosition->Z)
491491
};
492492

493-
for (auto& trail : pExt->LaserTrails)
493+
for (const auto& pTrail : pExt->LaserTrails)
494494
{
495-
if (!trail.LastLocation.isset())
496-
trail.LastLocation = pThis->Location;
495+
if (!pTrail->LastLocation.isset())
496+
pTrail->LastLocation = pThis->Location;
497497

498-
trail.Update(futureCoords);
498+
pTrail->Update(futureCoords);
499499
}
500500
}
501501

@@ -510,7 +510,7 @@ DEFINE_HOOK(0x4677D3, BulletClass_AI_TargetCoordCheck_Trajectories, 0x5)
510510

511511
auto const pExt = BulletExt::ExtMap.Find(pThis);
512512

513-
if (auto pTraj = pExt->Trajectory.get())
513+
if (auto const pTraj = pExt->Trajectory.get())
514514
{
515515
switch (pTraj->OnAITargetCoordCheck(pThis))
516516
{
@@ -540,7 +540,7 @@ DEFINE_HOOK(0x467927, BulletClass_AI_TechnoCheck_Trajectories, 0x5)
540540

541541
auto const pExt = BulletExt::ExtMap.Find(pThis);
542542

543-
if (auto pTraj = pExt->Trajectory.get())
543+
if (auto const pTraj = pExt->Trajectory.get())
544544
{
545545
switch (pTraj->OnAITechnoCheck(pThis, pTechno))
546546
{

src/Ext/EBolt/Body.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include "Body.h"
2+
3+
#include <Ext/WeaponType/Body.h>
4+
5+
EBoltExt::ExtContainer EBoltExt::ExtMap;
6+
7+
EBolt* EBoltExt::CreateEBolt(WeaponTypeClass* pWeapon)
8+
{
9+
const auto pBolt = GameCreate<EBolt>();
10+
const auto pBoltExt = EBoltExt::ExtMap.Find(pBolt);
11+
12+
const int alternateIdx = pWeapon->IsAlternateColor ? 5 : 10;
13+
const int defaultAlternate = EBoltExt::GetDefaultColor_Int(FileSystem::PALETTE_PAL, alternateIdx);
14+
const int defaultWhite = EBoltExt::GetDefaultColor_Int(FileSystem::PALETTE_PAL, 15);
15+
const auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);
16+
17+
for (int idx = 0; idx < 3; ++idx)
18+
{
19+
if (pWeaponExt->Bolt_Disable[idx])
20+
pBoltExt->Disable[idx] = true;
21+
else if (pWeaponExt->Bolt_Color[idx].isset())
22+
pBoltExt->Color[idx] = pWeaponExt->Bolt_Color[idx].Get();
23+
else
24+
pBoltExt->Color[idx] = Drawing::Int_To_RGB(idx < 2 ? defaultAlternate : defaultWhite);
25+
}
26+
27+
pBoltExt->Arcs = pWeaponExt->Bolt_Arcs;
28+
pBolt->Lifetime = 1 << (std::clamp(pWeaponExt->Bolt_Duration.Get(), 1, 31) - 1);
29+
return pBolt;
30+
}
31+
32+
// =============================
33+
// load / save
34+
35+
template <typename T>
36+
void EBoltExt::ExtData::Serialize(T& Stm)
37+
{
38+
Stm
39+
.Process(this->Color)
40+
.Process(this->Disable)
41+
.Process(this->Arcs)
42+
.Process(this->BurstIndex)
43+
;
44+
}
45+
46+
void EBoltExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
47+
{
48+
Extension<EBolt>::LoadFromStream(Stm);
49+
this->Serialize(Stm);
50+
}
51+
52+
void EBoltExt::ExtData::SaveToStream(PhobosStreamWriter& Stm)
53+
{
54+
Extension<EBolt>::SaveToStream(Stm);
55+
this->Serialize(Stm);
56+
}
57+
58+
bool EBoltExt::LoadGlobals(PhobosStreamReader& Stm)
59+
{
60+
return Stm.Success();
61+
}
62+
63+
bool EBoltExt::SaveGlobals(PhobosStreamWriter& Stm)
64+
{
65+
return Stm.Success();
66+
}
67+
68+
void EBoltExt::ExtData::InvalidatePointer(void* ptr, bool removed)
69+
{ }
70+
71+
// =============================
72+
// container
73+
74+
EBoltExt::ExtContainer::ExtContainer() : Container("EBolt") { }
75+
EBoltExt::ExtContainer::~ExtContainer() = default;
76+
77+
bool EBoltExt::ExtContainer::InvalidateExtDataIgnorable(void* const ptr) const
78+
{
79+
return true;
80+
}
81+
82+
// =============================
83+
// container hooks
84+
85+
DEFINE_HOOK(0x4C1E42, EBolt_CTOR, 0x5)
86+
{
87+
GET(EBolt*, pItem, EAX);
88+
89+
EBoltExt::ExtMap.Allocate(pItem);
90+
91+
return 0;
92+
}
93+
94+
DEFINE_HOOK(0x4C2951, EBolt_DTOR, 0x5)
95+
{
96+
GET(EBolt*, pItem, ESI);
97+
98+
EBoltExt::ExtMap.Remove(pItem);
99+
100+
return 0;
101+
}

0 commit comments

Comments
 (0)