Skip to content

Commit f523f53

Browse files
authored
[Minor] Update on Arcing.AllowElevationInaccuracy (#1662)
The previous `Arcing.AllowElevationInaccuracy` fix will make the projectile fall and detonate at different positions, which looks awkward in many times ![a9e84132490cddd7bd7a04df3833a55a](https://github.com/user-attachments/assets/ceccddc4-e303-44f2-9f71-d59221b827d3) This fix is based on #269 and #270, which will adjust the projectile's trace to make them fall and detonate at the same elevated position, also enabled by setting `Arcing.AllowElevationInaccuracy=false`. Also includes some bullet optimizations from #1568
1 parent a212003 commit f523f53

File tree

9 files changed

+113
-78
lines changed

9 files changed

+113
-78
lines changed

CREDITS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ This page lists all the individual contributions to the project by their author.
6868
- Wall-Gate links
6969
- Ability for deployed infantry to use both weapons
7070
- Observer PCX loading screen
71+
- Original `Arcing` elevation inaccuracy fix
7172
- Official CN docs for Build#29 and previous versions
7273
- **secsome (SEC-SOME)**:
7374
- Debug info dump hotkey
@@ -95,6 +96,7 @@ This page lists all the individual contributions to the project by their author.
9596
- Vanilla map preview reading bugfix
9697
- Customizable tooltip background
9798
- Parts of Ares calling code
99+
- Original `Arcing` elevation inaccuracy fix
98100
- **Otamaa (Fahroni, BoredEXE)**:
99101
- Help with CellSpread
100102
- Ported and fixed custom RadType code
@@ -217,7 +219,7 @@ This page lists all the individual contributions to the project by their author.
217219
- `PipScale` pip size & ammo pip frame customization
218220
- Extension class optimization
219221
- Additional sync logging
220-
- `Arcing` elevation inaccuracy fix
222+
- Original `Arcing` elevation inaccuracy fix
221223
- `EMPulseCannon` projectile gravity fix
222224
- Custom palette support for wall overlays
223225
- Warhead animation improvements
@@ -391,6 +393,7 @@ This page lists all the individual contributions to the project by their author.
391393
- Fix the bug that infantry ignored `Passengers` and `SizeLimit` when entering buildings
392394
- Tiberium eater logic
393395
- Fix the bug that ships can travel on elevated bridges
396+
- `Arcing` elevation inaccuracy fix
394397
- **Apollo** - Translucent SHP drawing patches
395398
- **ststl**:
396399
- Customizable `ShowTimer` priority of superweapons

src/Ext/Bullet/Body.cpp

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,13 @@ void BulletExt::ExtData::InitializeLaserTrails()
144144

145145
auto pThis = this->OwnerObject();
146146

147-
if (auto pTypeExt = BulletTypeExt::ExtMap.Find(pThis->Type))
148-
{
149-
auto pOwner = pThis->Owner ? pThis->Owner->Owner : nullptr;
147+
auto pTypeExt = BulletTypeExt::ExtMap.Find(pThis->Type);
148+
auto pOwner = pThis->Owner ? pThis->Owner->Owner : nullptr;
149+
this->LaserTrails.reserve(pTypeExt->LaserTrail_Types.size());
150150

151-
for (auto const& idxTrail : pTypeExt->LaserTrail_Types)
152-
{
153-
this->LaserTrails.emplace_back(LaserTrailTypeClass::Array[idxTrail].get(), pOwner);
154-
}
151+
for (auto const& idxTrail : pTypeExt->LaserTrail_Types)
152+
{
153+
this->LaserTrails.emplace_back(LaserTrailTypeClass::Array[idxTrail].get(), pOwner);
155154
}
156155
}
157156

@@ -197,8 +196,8 @@ inline void BulletExt::SimulatedFiringAnim(BulletClass* pBullet, HouseClass* pHo
197196

198197
if (pAttach)
199198
{
200-
if (pAttach->WhatAmI() == AbstractType::Building)
201-
pAnim->ZAdjust = SetBuildingFireAnimZAdjust(static_cast<BuildingClass*>(pAttach), pBullet->SourceCoords.Y);
199+
if (const auto pBuilding = abstract_cast<BuildingClass*, true>(pAttach))
200+
pAnim->ZAdjust = SetBuildingFireAnimZAdjust(pBuilding, pBullet->SourceCoords.Y);
202201
else
203202
pAnim->SetOwnerObject(pAttach);
204203
}
@@ -334,13 +333,13 @@ void BulletExt::SimulatedFiringUnlimbo(BulletClass* pBullet, HouseClass* pHouse,
334333
const auto targetCoords = pBullet->Target->GetCenterCoords();
335334
const auto gravity = BulletTypeExt::GetAdjustedGravity(pType);
336335
const auto distanceCoords = targetCoords - sourceCoords;
337-
const auto horizontalDistance = Point2D{distanceCoords.X, distanceCoords.Y}.Magnitude();
336+
const auto horizontalDistance = Point2D { distanceCoords.X, distanceCoords.Y }.Magnitude();
338337
const bool lobber = pWeapon->Lobber || static_cast<int>(horizontalDistance) < distanceCoords.Z; // 0x70D590
339338
// The lower the horizontal velocity, the higher the trajectory
340339
// WW calculates the launch angle (and limits it) before calculating the velocity
341340
// Here, some magic numbers are used to directly simulate its calculation
342341
const auto speedMult = (lobber ? 0.45 : (distanceCoords.Z > 0 ? 0.68 : 1.0)); // Simulated 0x48A9D0
343-
const auto speed = static_cast<int>(speedMult * sqrt(horizontalDistance * gravity * 1.2)); // 0x48AB90
342+
const auto speed = speedMult * sqrt(horizontalDistance * gravity * 1.2); // 0x48AB90
344343

345344
// Simulate firing Arcing bullet
346345
if (horizontalDistance < 1e-10 || !speed)
@@ -390,6 +389,32 @@ void BulletExt::SimulatedFiringEffects(BulletClass* pBullet, HouseClass* pHouse,
390389
}
391390
}
392391

392+
void BulletExt::ApplyArcingFix(BulletClass* pThis, const CoordStruct& sourceCoords, const CoordStruct& targetCoords, BulletVelocity& velocity)
393+
{
394+
const auto distanceCoords = targetCoords - sourceCoords;
395+
const auto horizontalDistance = Point2D { distanceCoords.X, distanceCoords.Y }.Magnitude();
396+
const bool lobber = pThis->WeaponType->Lobber || static_cast<int>(horizontalDistance) < distanceCoords.Z; // 0x70D590
397+
// The lower the horizontal velocity, the higher the trajectory
398+
// WW calculates the launch angle (and limits it) before calculating the velocity
399+
// Here, some magic numbers are used to directly simulate its calculation
400+
const auto speedMult = (lobber ? 0.45 : (distanceCoords.Z > 0 ? 0.68 : 1.0)); // Simulated 0x48A9D0
401+
const double gravity = BulletTypeExt::GetAdjustedGravity(pThis->Type);
402+
const double speed = speedMult * sqrt(horizontalDistance * gravity * 1.2); // 0x48AB90
403+
404+
if (horizontalDistance < 1e-10 || !speed)
405+
{
406+
// No solution
407+
velocity.Z = speed;
408+
}
409+
else
410+
{
411+
const auto mult = speed / horizontalDistance;
412+
velocity.X = static_cast<double>(distanceCoords.X) * mult;
413+
velocity.Y = static_cast<double>(distanceCoords.Y) * mult;
414+
velocity.Z = (static_cast<double>(distanceCoords.Z) + velocity.Z) * mult + (gravity * horizontalDistance) / (2 * speed);
415+
}
416+
}
417+
393418
// =============================
394419
// load / save
395420

src/Ext/Bullet/Body.h

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

7070
static ExtContainer ExtMap;
7171

72+
static void ApplyArcingFix(BulletClass* pThis, const CoordStruct& sourceCoords, const CoordStruct& targetCoords, BulletVelocity& velocity);
73+
7274
static void SimulatedFiringUnlimbo(BulletClass* pBullet, HouseClass* pHouse, WeaponTypeClass* pWeapon, const CoordStruct& sourceCoords, bool randomVelocity);
7375
static void SimulatedFiringEffects(BulletClass* pBullet, HouseClass* pHouse, ObjectClass* pAttach, bool firingEffect, bool visualEffect);
7476
static inline void SimulatedFiringAnim(BulletClass* pBullet, HouseClass* pHouse, ObjectClass* pAttach);

src/Ext/Bullet/Hooks.DetonateLogics.cpp

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ DEFINE_HOOK(0x4690C1, BulletClass_Logics_DetonateOnAllMapObjects, 0x8)
6969
auto const originalLocation = pThis->Location;
7070
auto const pOriginalTarget = pThis->Target;
7171
auto const pExt = BulletExt::ExtMap.Find(pThis);
72+
auto const isFull = pWHExt->DetonateOnAllMapObjects_Full;
7273
auto pOwner = pThis->Owner ? pThis->Owner->Owner : pExt->FirerHouse;
7374

7475
auto copy_dvc = []<typename T>(const DynamicVectorClass<T>&dvc)
@@ -78,23 +79,21 @@ DEFINE_HOOK(0x4690C1, BulletClass_Logics_DetonateOnAllMapObjects, 0x8)
7879
return vec;
7980
};
8081

81-
std::function<void(TechnoClass*)> tryDetonate = [pThis, pWHExt, pOwner](TechnoClass* pTechno)
82+
auto tryDetonate = [pThis, pWHExt, pOwner, isFull](TechnoClass* pTechno)
8283
{
8384
if (pWHExt->EligibleForFullMapDetonation(pTechno, pOwner))
8485
{
85-
pThis->Target = pTechno;
86-
pThis->Location = pTechno->GetCoords();
87-
pThis->Detonate(pTechno->GetCoords());
88-
}
89-
};
90-
91-
if (!pWHExt->DetonateOnAllMapObjects_Full)
92-
tryDetonate = [pThis, pWHExt, pOwner](TechnoClass* pTechno)
93-
{
94-
if (pWHExt->EligibleForFullMapDetonation(pTechno, pOwner))
95-
{
96-
int damage = (pThis->Health * pThis->DamageMultiplier) >> 8;
97-
pWHExt->DamageAreaWithTarget(pTechno->GetCoords(), damage, pThis->Owner, pThis->WH, true, pOwner, pTechno);
86+
if (isFull)
87+
{
88+
pThis->Target = pTechno;
89+
pThis->Location = pTechno->GetCoords();
90+
pThis->Detonate(pTechno->GetCoords());
91+
}
92+
else
93+
{
94+
int damage = (pThis->Health * pThis->DamageMultiplier) >> 8;
95+
pWHExt->DamageAreaWithTarget(pTechno->GetCoords(), damage, pThis->Owner, pThis->WH, true, pOwner, pTechno);
96+
}
9897
}
9998
};
10099

@@ -164,14 +163,15 @@ DEFINE_HOOK(0x469E34, BulletClass_Logics_DebrisAnims, 0x5)
164163
enum { SkipGameCode = 0x469EBA };
165164

166165
GET(BulletClass*, pThis, ESI);
167-
GET(int, debrisCount, EBX);
168166

169167
auto const pWHExt = WarheadTypeExt::ExtMap.Find(pThis->WH);
170168
auto const debrisAnims = pWHExt->DebrisAnims.GetElements(RulesClass::Instance->MetallicDebris);
171169

172170
if (debrisAnims.size() < 1)
173171
return SkipGameCode;
174172

173+
GET(int, debrisCount, EBX);
174+
175175
while (debrisCount > 0)
176176
{
177177
int debrisIndex = ScenarioClass::Instance->Random.RandomRanged(0, debrisAnims.size() - 1);
@@ -204,19 +204,20 @@ DEFINE_HOOK(0x469C46, BulletClass_Logics_DamageAnimSelected, 0x8)
204204
{
205205
enum { SkipGameCode = 0x469C98 };
206206

207-
GET(BulletClass*, pThis, ESI);
208207
GET(AnimTypeClass*, pAnimType, EBX);
209-
LEA_STACK(CoordStruct*, coords, STACK_OFFSET(0xA4, -0x40));
210208

211209
bool createdAnim = false;
212210

213211
if (pAnimType)
214212
{
213+
GET(BulletClass*, pThis, ESI);
214+
LEA_STACK(CoordStruct*, coords, STACK_OFFSET(0xA4, -0x40));
215215
auto const pWHExt = WarheadTypeExt::ExtMap.Find(pThis->WH);
216-
int creationInterval = pWHExt->Splashed ? pWHExt->SplashList_CreationInterval : pWHExt->AnimList_CreationInterval;
216+
const bool splashed = pWHExt->Splashed;
217+
int creationInterval = splashed ? pWHExt->SplashList_CreationInterval : pWHExt->AnimList_CreationInterval;
217218
int* remainingInterval = &pWHExt->RemainingAnimCreationInterval;
218-
int scatterMin = pWHExt->Splashed ? pWHExt->SplashList_ScatterMin.Get() : pWHExt->AnimList_ScatterMin.Get();
219-
int scatterMax = pWHExt->Splashed ? pWHExt->SplashList_ScatterMax.Get() : pWHExt->AnimList_ScatterMax.Get();
219+
int scatterMin = splashed ? pWHExt->SplashList_ScatterMin.Get() : pWHExt->AnimList_ScatterMin.Get();
220+
int scatterMax = splashed ? pWHExt->SplashList_ScatterMax.Get() : pWHExt->AnimList_ScatterMax.Get();
220221
bool allowScatter = scatterMax != 0 || scatterMin != 0;
221222

222223
if (creationInterval > 0 && pThis->Owner)
@@ -229,16 +230,16 @@ DEFINE_HOOK(0x469C46, BulletClass_Logics_DamageAnimSelected, 0x8)
229230
HouseClass* pInvoker = pThis->Owner ? pThis->Owner->Owner : BulletExt::ExtMap.Find(pThis)->FirerHouse;
230231
HouseClass* pVictim = nullptr;
231232

232-
if (TechnoClass* Target = generic_cast<TechnoClass*>(pThis->Target))
233+
if (auto const Target = abstract_cast<TechnoClass*>(pThis->Target))
233234
pVictim = Target->Owner;
234235

235236
auto types = make_iterator_single(pAnimType);
236237

237-
if (pWHExt->SplashList_CreateAll && pWHExt->Splashed)
238+
if (pWHExt->SplashList_CreateAll && splashed)
238239
{
239240
types = pWHExt->SplashList.GetElements(RulesClass::Instance->SplashList);
240241
}
241-
else if (!pWHExt->Splashed)
242+
else if (!splashed)
242243
{
243244
bool createAll = pWHExt->AnimList_CreateAll;
244245

@@ -295,13 +296,13 @@ DEFINE_HOOK(0x469C46, BulletClass_Logics_DamageAnimSelected, 0x8)
295296
DEFINE_HOOK(0x469AA4, BulletClass_Logics_Extras, 0x5)
296297
{
297298
GET(BulletClass*, pThis, ESI);
298-
GET_BASE(CoordStruct*, coords, 0x8);
299299

300300
auto const pOwner = pThis->Owner ? pThis->Owner->Owner : BulletExt::ExtMap.Find(pThis)->FirerHouse;
301301

302302
// Extra warheads
303303
if (pThis->WeaponType)
304304
{
305+
GET_BASE(CoordStruct*, coords, 0x8);
305306
auto const pWeaponExt = WeaponTypeExt::ExtMap.Find(pThis->WeaponType);
306307
int defaultDamage = pThis->WeaponType->Damage;
307308

src/Ext/Bullet/Hooks.Obstacles.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,16 @@ DEFINE_HOOK(0x468C86, BulletClass_ShouldExplode_Obstacles, 0xA)
161161

162162
GET(BulletClass*, pThis, ESI);
163163

164-
BulletTypeExt::ExtData* pBulletTypeExt = BulletTypeExt::ExtMap.Find(pThis->Type);
164+
auto const pType = pThis->Type;
165+
auto pBulletTypeExt = BulletTypeExt::ExtMap.Find(pType);
165166

166-
if (BulletObstacleHelper::SubjectToObstacles(pThis->Type, pBulletTypeExt))
167+
if (BulletObstacleHelper::SubjectToObstacles(pType, pBulletTypeExt))
167168
{
168169
auto const pCellSource = MapClass::Instance.GetCellAt(pThis->SourceCoords);
169170
auto const pCellTarget = MapClass::Instance.GetCellAt(pThis->TargetCoords);
170171
auto const pCellCurrent = MapClass::Instance.GetCellAt(pThis->LastMapCoords);
171172
auto const pOwner = pThis->Owner ? pThis->Owner->Owner : BulletExt::ExtMap.Find(pThis)->FirerHouse;
172-
const auto pObstacleCell = BulletObstacleHelper::GetObstacle(pCellSource, pCellTarget, pCellCurrent, pThis->Location, pThis->Owner, pThis->Target, pOwner, pThis->Type, pBulletTypeExt, false);
173+
auto const pObstacleCell = BulletObstacleHelper::GetObstacle(pCellSource, pCellTarget, pCellCurrent, pThis->Location, pThis->Owner, pThis->Target, pOwner, pType, pBulletTypeExt, false);
173174

174175
if (pObstacleCell)
175176
return Explode;
@@ -212,17 +213,17 @@ DEFINE_HOOK(0x6F737F, TechnoClass_InRange_WeaponMinimumRange, 0x6)
212213

213214
DEFINE_HOOK(0x6F7647, TechnoClass_InRange_Obstacles, 0x5)
214215
{
215-
GET_BASE(WeaponTypeClass*, pWeapon, 0x10);
216-
GET(CoordStruct const* const, pSourceCoords, ESI);
217-
REF_STACK(CoordStruct const, targetCoords, STACK_OFFSET(0x3C, -0x1C));
218-
GET_BASE(AbstractClass* const, pTarget, 0xC);
219216
GET(CellClass*, pResult, EAX);
217+
GET(CoordStruct const* const, pSourceCoords, ESI);
220218

221219
auto pObstacleCell = pResult;
222220
auto pTechno = InRangeTemp::Techno;
223221

224222
if (!pObstacleCell)
225223
{
224+
GET_BASE(WeaponTypeClass*, pWeapon, 0x10);
225+
REF_STACK(CoordStruct const, targetCoords, STACK_OFFSET(0x3C, -0x1C));
226+
GET_BASE(AbstractClass* const, pTarget, 0xC);
226227
auto subjectToGround = BulletTypeExt::ExtMap.Find(pWeapon->Projectile)->SubjectToGround.Get();
227228
const auto newSourceCoords = subjectToGround ? BulletObstacleHelper::AddFLHToSourceCoords(*pSourceCoords, targetCoords, pTechno, pTarget, pWeapon, subjectToGround) : *pSourceCoords;
228229
pObstacleCell = BulletObstacleHelper::FindFirstImpenetrableObstacle(newSourceCoords, targetCoords, pTechno, pTarget, pTechno->Owner, pWeapon, true, subjectToGround);

src/Ext/Bullet/Hooks.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -404,19 +404,17 @@ DEFINE_HOOK(0x468D3F, BulletClass_ShouldExplode_AirTarget, 0x6)
404404
DEFINE_HOOK(0x4687F8, BulletClass_Unlimbo_FlakScatter, 0x6)
405405
{
406406
GET(BulletClass*, pThis, EBX);
407-
GET_STACK(float, mult, STACK_OFFSET(0x5C, -0x44));
408407

409408
if (pThis->WeaponType)
410409
{
411-
if (auto const pTypeExt = BulletTypeExt::ExtMap.Find(pThis->Type))
412-
{
413-
int defaultValue = RulesClass::Instance->BallisticScatter;
414-
int min = pTypeExt->BallisticScatter_Min.Get(Leptons(0));
415-
int max = pTypeExt->BallisticScatter_Max.Get(Leptons(defaultValue));
416-
417-
int result = (int)((mult * ScenarioClass::Instance->Random.RandomRanged(2 * min, 2 * max)) / pThis->WeaponType->Range);
418-
R->EAX(result);
419-
}
410+
GET_STACK(float, mult, STACK_OFFSET(0x5C, -0x44));
411+
auto const pTypeExt = BulletTypeExt::ExtMap.Find(pThis->Type);
412+
int defaultValue = RulesClass::Instance->BallisticScatter;
413+
int min = pTypeExt->BallisticScatter_Min.Get(Leptons(0));
414+
int max = pTypeExt->BallisticScatter_Max.Get(Leptons(defaultValue));
415+
416+
int result = (int)((mult * ScenarioClass::Instance->Random.RandomRanged(2 * min, 2 * max)) / pThis->WeaponType->Range);
417+
R->EAX(result);
420418
}
421419

422420
return 0;
@@ -425,37 +423,38 @@ DEFINE_HOOK(0x4687F8, BulletClass_Unlimbo_FlakScatter, 0x6)
425423
// Skip a forced detonation check for Level=true projectiles that is now handled in Hooks.Obstacles.cpp.
426424
DEFINE_JUMP(LJMP, 0x468D08, 0x468D2F);
427425

428-
DEFINE_HOOK(0x6FE657, TechnoClass_FireAt_ArcingFix, 0x6)
426+
DEFINE_HOOK(0x6FF008, TechnoClass_Fire_BeforeMoveTo, 0x8)
429427
{
430-
GET_STACK(BulletTypeClass*, pBulletType, STACK_OFFSET(0xB0, -0x48));
431-
GET(int, targetHeight, EDI);
432-
GET(int, fireHeight, EAX);
428+
GET(BulletClass*, pBullet, EBX);
429+
const auto projectile = pBullet->Type;
433430

434-
if (pBulletType->Arcing && targetHeight > fireHeight)
431+
if (projectile->Arcing && !BulletTypeExt::ExtMap.Find(projectile)->Arcing_AllowElevationInaccuracy)
435432
{
436-
auto const pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType);
433+
LEA_STACK(BulletVelocity*, velocity, STACK_OFFSET(0xB0, -0x60));
434+
LEA_STACK(CoordStruct*, crdSrc, STACK_OFFSET(0xB0, -0x6C));
437435

438-
if (!pBulletTypeExt->Arcing_AllowElevationInaccuracy)
439-
R->EAX(targetHeight);
436+
GET_STACK(CoordStruct, crdOffset, STACK_OFFSET(0xB0, -0x1C));
437+
GET_STACK(CoordStruct, fireCoords, STACK_OFFSET(0xB0, -0x6C));
438+
const auto crdTgt = crdOffset + fireCoords;
439+
440+
BulletExt::ApplyArcingFix(pBullet, *crdSrc, crdTgt, *velocity);
440441
}
441442

442443
return 0;
443444
}
444445

445-
DEFINE_HOOK(0x44D23C, BuildingClass_Mission_Missile_ArcingFix, 0x7)
446+
DEFINE_HOOK(0x44D46E, BuildingClass_Mission_Missile_BeforeMoveTo, 0x8)
446447
{
447-
GET(WeaponTypeClass*, pWeapon, EBP);
448-
GET(int, targetHeight, EBX);
449-
GET(int, fireHeight, EAX);
450-
451-
auto const pBulletType = pWeapon->Projectile;
448+
GET(BulletClass*, pBullet, EDI);
449+
const auto projectile = pBullet->Type;
452450

453-
if (pBulletType->Arcing && targetHeight > fireHeight)
451+
if (projectile->Arcing && !BulletTypeExt::ExtMap.Find(projectile)->Arcing_AllowElevationInaccuracy)
454452
{
455-
auto const pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType);
453+
LEA_STACK(BulletVelocity*, velocity, STACK_OFFSET(0xE8, -0xD0));
454+
LEA_STACK(CoordStruct*, crdSrc, STACK_OFFSET(0xE8, -0x8C));
455+
GET_STACK(CoordStruct, crdTgt, STACK_OFFSET(0xE8, -0x4C));
456456

457-
if (!pBulletTypeExt->Arcing_AllowElevationInaccuracy)
458-
R->EAX(targetHeight);
457+
BulletExt::ApplyArcingFix(pBullet, *crdSrc, crdTgt, *velocity);
459458
}
460459

461460
return 0;

src/Ext/Techno/Body.Internal.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ void TechnoExt::ExtData::InitializeLaserTrails()
1111
if (this->LaserTrails.size())
1212
return;
1313

14-
if (auto pTypeExt = this->TypeExtData)
14+
auto pTypeExt = this->TypeExtData;
15+
this->LaserTrails.reserve(pTypeExt->LaserTrailData.size());
16+
17+
for (auto const& entry : pTypeExt->LaserTrailData)
1518
{
16-
for (auto const& entry : pTypeExt->LaserTrailData)
17-
{
18-
this->LaserTrails.emplace_back(entry.GetType(), this->OwnerObject()->Owner, entry.FLH, entry.IsOnTurret);
19-
}
19+
this->LaserTrails.emplace_back(entry.GetType(), this->OwnerObject()->Owner, entry.FLH, entry.IsOnTurret);
2020
}
2121
}
2222

0 commit comments

Comments
 (0)