From d02be5c627a71d336d471ee89c0fa53644b8a0e9 Mon Sep 17 00:00:00 2001
From: secsome <302702960@qq.com>
Date: Sat, 13 Nov 2021 19:20:37 +0800
Subject: [PATCH 1/3] Implement custom projectile trajectories
Init trajectories base class
Implement PhobosTrajactory basis
prototype of straight trajactory
Add a sample Trajactory
Refactored Trajectory system
Minor adjustment
Add comments
Make reading case insensitive
Edit the comment
And add a pusheen
docs stuff
Small refactor for read trajectory
stupid fault
Add a comment
Update the document
Fix the document
Add not recommend to use sample trajectory in the document
Rename SampleTrajectory into BombardTrajectory
Exclude SampleTrajectory from project
Adjust the inital speed value to 100
Adjust the falling detection
Fix a stupid stupid
Avoid exceeding the floats limitation
Use Z to trigger the bullet
Remove wrong whats-new
Clarified documentation.
Add a failsafe to Trajectory.Speed getter if bullet doesn't have WeaponType set
Use correct function for detonating custom trajectory projectiles
- This enables use of Cluster etc.
Documentation fixups
---
Phobos.vcxproj | 6 +
README.md | 2 +-
docs/Fixed-or-Improved-Logics.md | 4 +-
docs/New-or-Enhanced-Logics.md | 38 +++
docs/Whats-New.md | 1 +
src/Ext/Bullet/Body.cpp | 5 +
src/Ext/Bullet/Body.h | 5 +
src/Ext/Bullet/Hooks.cpp | 27 +--
.../Bullet/Trajectories/BombardTrajectory.cpp | 85 +++++++
.../Bullet/Trajectories/BombardTrajectory.h | 42 ++++
.../Bullet/Trajectories/PhobosTrajectory.cpp | 225 ++++++++++++++++++
.../Bullet/Trajectories/PhobosTrajectory.h | 136 +++++++++++
.../Bullet/Trajectories/SampleTrajectory.cpp | 84 +++++++
.../Bullet/Trajectories/SampleTrajectory.h | 49 ++++
.../Trajectories/StraightTrajectory.cpp | 53 +++++
.../Bullet/Trajectories/StraightTrajectory.h | 32 +++
src/Ext/BulletType/Body.cpp | 10 +-
src/Ext/BulletType/Body.h | 8 +-
src/Ext/WeaponType/Body.cpp | 2 +
src/Ext/WeaponType/Body.h | 2 +
20 files changed, 782 insertions(+), 34 deletions(-)
create mode 100644 src/Ext/Bullet/Trajectories/BombardTrajectory.cpp
create mode 100644 src/Ext/Bullet/Trajectories/BombardTrajectory.h
create mode 100644 src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
create mode 100644 src/Ext/Bullet/Trajectories/PhobosTrajectory.h
create mode 100644 src/Ext/Bullet/Trajectories/SampleTrajectory.cpp
create mode 100644 src/Ext/Bullet/Trajectories/SampleTrajectory.h
create mode 100644 src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
create mode 100644 src/Ext/Bullet/Trajectories/StraightTrajectory.h
diff --git a/Phobos.vcxproj b/Phobos.vcxproj
index 2db8816257..1b03ce62ae 100644
--- a/Phobos.vcxproj
+++ b/Phobos.vcxproj
@@ -21,6 +21,9 @@
+
+
+
@@ -117,6 +120,9 @@
+
+
+
diff --git a/README.md b/README.md
index 7dde1e49a0..b8db9660a0 100644
--- a/README.md
+++ b/README.md
@@ -77,7 +77,7 @@ Credits
- **Belonit (Gluk-v48)** - project author (retired)
- **Kerbiter (Metadorius)** - project co-author, current maintainer ([Patreon](http://patreon.com/kerbiter))
- **Uranusian (Thrifinesma)** - developer, CN community ambassador ([Patreon](https://www.patreon.com/uranusian), [AliPay](http://tiebapic.baidu.com/forum/w%3D580/sign=4b04b953307f9e2f70351d002f31e962/b3f89909b3de9c823bd7f23a7b81800a18d84371.jpg))
-- **secsome (SEC-SOME)** - developer ([Patreon](https://www.patreon.com/secsome))
+- **secsome (SEC-SOME)** - developer
- **Otamaa (Fahroni, BoredEXE)** - developer ([PayPal](https://paypal.me/GeneralOtama))
- **FS-21** - developer
- **Starkku** - developer
diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md
index c40dad7c58..79fd23dbb1 100644
--- a/docs/Fixed-or-Improved-Logics.md
+++ b/docs/Fixed-or-Improved-Logics.md
@@ -122,14 +122,12 @@ Grinding.Weapon= ; WeaponType
### Customizable projectile gravity
- You can now specify individual projectile gravity.
- - Set `Gravity=0` with an arcing projectile can create a straight trail.
- - Set `Gravity.HeightFix=true` allows the projectile to hit target which is not at the same height while `Gravity=0`.
+ - Setting `Gravity=0` is not recommended. It will cause the projectile unable to hit the target which is not at the same height. We'd suggest to use `Straight` Trajectory instead. See [here](New-or-Enhanced-Logics.md#projectile-trajectories).
In `rulesmd.ini`:
```ini
[SOMEPROJECTILE] ; Projectile
Gravity=6.0 ; double
-Gravity.HeightFix=false ; boolean
```
## Technos
diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md
index 74c29eb41b..a70b664dfe 100644
--- a/docs/New-or-Enhanced-Logics.md
+++ b/docs/New-or-Enhanced-Logics.md
@@ -312,6 +312,34 @@ Interceptor.EliteMinimumGuardRange=0.0 ; double
Interceptable=no ; boolean
```
+### Projectile trajectories
+
+- Projectiles can now have customizable trajectories.
+ - `Trajectory` should not be combined with original game's projectile trajectory logics (`Arcing`, `ROT` or `Inviso`).
+
+#### Straight trajectory
+
+- Self-explanatory, is a straight-shot trajectory.
+ - Initial speed is determined by weapon's `Trajectory.Speed`.
+
+In `rulesmd.ini`
+```ini
+[SOMEPROJECTILE] ; Projectile
+Trajectory=Straight ; Trajectory type
+```
+
+#### Bombard trajectory
+
+- Similar trajectory to `Straight`, but targets a coordinate above the intended target (height determined by `Trajectory.Bombard.Height`). When the projectile approaches that coordinate, it will free fall and explodes when it hits the target or ground.
+ - Initial speed is determined by weapon's `Trajectory.Speed`.
+
+In `rulesmd.ini`
+```ini
+[SOMEPROJECTILE] ; Projectile
+Trajectory=Bombard ; Trajectory type
+Trajectory.Bombard.Height=0.0 ; double
+```
+
### Shrapnel enhancement
- Shrapnel behavior can be triggered on the ground and buildings.
@@ -1240,6 +1268,16 @@ Strafing.Shots=5 ; integer
Strafing.SimulateBurst=false ; bool
```
+### Trajectory speed
+
+- This sets projectile speed used by custom [projectile trajectories](#projectile-trajectories).
+
+In `rulesmd.ini`:
+```ini
+[SOMEWEAPON] ; WeaponType
+Trajectory.Speed=100.0 ; double
+```
+
### Weapon targeting filter
- You can now specify which targets or houses a weapon can fire at. This also affects weapon selection, other than certain special cases where the selection is fixed.
diff --git a/docs/Whats-New.md b/docs/Whats-New.md
index 90398b1f11..6c3c674d6d 100644
--- a/docs/Whats-New.md
+++ b/docs/Whats-New.md
@@ -292,6 +292,7 @@ New:
- Feedback weapon (by Starkku)
- TerrainType & ore minimap color customization (by Starkku)
- Single-color weapon lasers (by Starkku)
+- Customizable projectile trajectory (by secsome)
Vanilla fixes:
- Fixed laser drawing code to allow for thicker lasers in house color draw mode (by Kerbiter, ChrisLv_CN)
diff --git a/src/Ext/Bullet/Body.cpp b/src/Ext/Bullet/Body.cpp
index 33445f0852..641022c3fb 100644
--- a/src/Ext/Bullet/Body.cpp
+++ b/src/Ext/Bullet/Body.cpp
@@ -83,6 +83,8 @@ void BulletExt::ExtData::Serialize(T& Stm)
.Process(this->ShouldIntercept)
.Process(this->LaserTrails)
;
+
+ this->Trajectory = PhobosTrajectory::ProcessFromStream(Stm, this->Trajectory);
}
void BulletExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
@@ -119,6 +121,9 @@ DEFINE_HOOK(0x4665E9, BulletClass_DTOR, 0xA)
{
GET(BulletClass*, pItem, ESI);
+ if (auto pTraj = BulletExt::ExtMap.Find(pItem)->Trajectory)
+ GameDelete(pTraj);
+
BulletExt::ExtMap.Remove(pItem);
return 0;
}
diff --git a/src/Ext/Bullet/Body.h b/src/Ext/Bullet/Body.h
index aaca396bcf..26bd7c4a00 100644
--- a/src/Ext/Bullet/Body.h
+++ b/src/Ext/Bullet/Body.h
@@ -7,6 +7,8 @@
#include
+#include "Trajectories/PhobosTrajectory.h"
+
class BulletExt
{
public:
@@ -18,11 +20,14 @@ class BulletExt
Valueable Intercepted;
Valueable ShouldIntercept;
ValueableVector> LaserTrails;
+
+ PhobosTrajectory* Trajectory;
ExtData(BulletClass* OwnerObject) : Extension(OwnerObject)
, Intercepted { false }
, ShouldIntercept { false }
, LaserTrails {}
+ , Trajectory { nullptr }
{ }
virtual ~ExtData() = default;
diff --git a/src/Ext/Bullet/Hooks.cpp b/src/Ext/Bullet/Hooks.cpp
index 079f58ff97..512d842ba7 100644
--- a/src/Ext/Bullet/Hooks.cpp
+++ b/src/Ext/Bullet/Hooks.cpp
@@ -56,7 +56,7 @@ DEFINE_HOOK(0x4666F7, BulletClass_AI, 0x6)
if (pBulletExt && pBulletExt->LaserTrails.size())
{
CoordStruct location = pThis->GetCoords();
- BulletVelocity velocity = pThis->Velocity;
+ const BulletVelocity& velocity = pThis->Velocity;
// We adjust LaserTrails to account for vanilla bug of drawing stuff one frame ahead.
// Pretty meh solution but works until we fix the bug - Kerbiter
@@ -155,31 +155,6 @@ DEFINE_HOOK(0x773087, WeaponTypeClass_GetSpeed_ApplyGravity, 0x6)
return 0x7730A3;
}
-DEFINE_HOOK(0x6FF031, TechnoClass_FireAt_ReverseVelocityWhileGravityIsZero, 0xA)
-{
- GET(BulletClass*, pBullet, EBX);
-
- auto const pData = BulletTypeExt::ExtMap.Find(pBullet->Type);
-
- if (pBullet->Type->Arcing && BulletTypeExt::GetAdjustedGravity(pBullet->Type) == 0.0)
- {
- pBullet->Velocity *= -1;
- if (pData->Gravity_HeightFix)
- {
- auto speed = pBullet->Velocity.Magnitude();
-
- pBullet->Velocity.X = static_cast(pBullet->TargetCoords.X - pBullet->SourceCoords.X);
- pBullet->Velocity.Y = static_cast(pBullet->TargetCoords.Y - pBullet->SourceCoords.Y);
- pBullet->Velocity.Z = static_cast(pBullet->TargetCoords.Z - pBullet->SourceCoords.Z);
-
- auto magnitude = pBullet->Velocity.Magnitude();
- pBullet->Velocity *= speed / magnitude;
- }
- }
-
- return 0;
-}
-
DEFINE_HOOK(0x46A3D6, BulletClass_Shrapnel_Forced, 0xA)
{
enum { Shrapnel = 0x46A40C, Skip = 0x46ADCD };
diff --git a/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp b/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp
new file mode 100644
index 0000000000..3cbc4bc54e
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp
@@ -0,0 +1,85 @@
+#include "BombardTrajectory.h"
+
+#include
+
+bool BombardTrajectoryType::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ this->PhobosTrajectoryType::Load(Stm, false);
+ Stm.Process(this->Height, false);
+ return true;
+}
+
+bool BombardTrajectoryType::Save(PhobosStreamWriter& Stm) const
+{
+ this->PhobosTrajectoryType::Save(Stm);
+ Stm.Process(this->Height);
+ return true;
+}
+
+void BombardTrajectoryType::Read(CCINIClass* const pINI, const char* pSection)
+{
+ this->Height = pINI->ReadDouble(pSection, "Trajectory.Bombard.Height", 0.0);
+}
+
+bool BombardTrajectory::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ this->PhobosTrajectory::Load(Stm, false);
+
+ Stm
+ .Process(this->IsFalling)
+ .Process(this->Height)
+ ;
+
+ return true;
+}
+
+bool BombardTrajectory::Save(PhobosStreamWriter& Stm) const
+{
+ this->PhobosTrajectory::Save(Stm);
+
+ Stm
+ .Process(this->IsFalling)
+ .Process(this->Height)
+ ;
+
+ return true;
+}
+
+void BombardTrajectory::OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity)
+{
+ this->Height = this->GetTrajectoryType(pBullet)->Height + pBullet->TargetCoords.Z;
+
+ pBullet->Velocity.X = static_cast(pBullet->TargetCoords.X - pBullet->SourceCoords.X);
+ pBullet->Velocity.Y = static_cast(pBullet->TargetCoords.Y - pBullet->SourceCoords.Y);
+ pBullet->Velocity.Z = static_cast(this->Height - pBullet->SourceCoords.Z);
+ pBullet->Velocity *= this->GetTrajectorySpeed(pBullet) / pBullet->Velocity.Magnitude();
+}
+
+void BombardTrajectory::OnAI(BulletClass* pBullet)
+{
+ // Close enough
+ if (pBullet->TargetCoords.DistanceFrom(pBullet->Location) < 100) // This value maybe adjusted?
+ {
+ pBullet->Explode(true);
+ pBullet->UnInit();
+ pBullet->LastMapCoords = CellClass::Coord2Cell(pBullet->Location);
+ }
+}
+
+void BombardTrajectory::OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition)
+{
+ if (!this->IsFalling)
+ {
+ pSpeed->Z += BulletTypeExt::GetAdjustedGravity(pBullet->Type);
+ if (pBullet->Location.Z + pBullet->Velocity.Z >= this->Height)
+ {
+ this->IsFalling = true;
+ pSpeed->X = 0.0;
+ pSpeed->Y = 0.0;
+ pSpeed->Z = 0.0;
+ pPosition->X = pBullet->TargetCoords.X;
+ pPosition->Y = pBullet->TargetCoords.Y;
+ }
+ }
+
+}
diff --git a/src/Ext/Bullet/Trajectories/BombardTrajectory.h b/src/Ext/Bullet/Trajectories/BombardTrajectory.h
new file mode 100644
index 0000000000..77aa532b26
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/BombardTrajectory.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "PhobosTrajectory.h"
+
+class BombardTrajectoryType final : public PhobosTrajectoryType
+{
+public:
+ BombardTrajectoryType() : PhobosTrajectoryType(TrajectoryFlag::Bombard)
+ , Height { 0.0 }
+ { }
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override;
+ virtual bool Save(PhobosStreamWriter& Stm) const override;
+
+ virtual void Read(CCINIClass* const pINI, const char* pSection) override;
+
+ double Height;
+};
+
+class BombardTrajectory final : public PhobosTrajectory
+{
+public:
+ BombardTrajectory() : PhobosTrajectory(TrajectoryFlag::Bombard)
+ , IsFalling { false }
+ , Height { 0.0 }
+ {}
+
+ BombardTrajectory(PhobosTrajectoryType* pType) : PhobosTrajectory(TrajectoryFlag::Bombard)
+ , IsFalling { false }
+ , Height { 0.0 }
+ {}
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override;
+ virtual bool Save(PhobosStreamWriter& Stm) const override;
+
+ virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) override;
+ virtual void OnAI(BulletClass* pBullet) override;
+ virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) override;
+
+ bool IsFalling;
+ double Height;
+};
\ No newline at end of file
diff --git a/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp b/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
new file mode 100644
index 0000000000..2e43b00c4b
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
@@ -0,0 +1,225 @@
+#include "PhobosTrajectory.h"
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "BombardTrajectory.h"
+#include "StraightTrajectory.h"
+
+bool PhobosTrajectoryType::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ Stm.Process(this->Flag, false);
+ return true;
+}
+
+bool PhobosTrajectoryType::Save(PhobosStreamWriter& Stm) const
+{
+ Stm.Process(this->Flag);
+ return true;
+}
+
+void PhobosTrajectoryType::CreateType(PhobosTrajectoryType*& pType, CCINIClass* const pINI, const char* pSection, const char* pKey)
+{
+ PhobosTrajectoryType* pNewType = nullptr;
+ bool bUpdateType = true;
+
+ pINI->ReadString(pSection, pKey, "", Phobos::readBuffer);
+ if (INIClass::IsBlank(Phobos::readBuffer))
+ pNewType = nullptr;
+ else if (_stricmp(Phobos::readBuffer, "Straight") == 0)
+ pNewType = GameCreate();
+ else if (_stricmp(Phobos::readBuffer, "Bombard") == 0)
+ pNewType = GameCreate();
+ else
+ bUpdateType = false;
+
+ if (pNewType)
+ pNewType->Read(pINI, pSection);
+
+ if (bUpdateType)
+ {
+ GameDelete(pType); // GameDelete already has if(pType) check here.
+ pType = pNewType;
+ }
+}
+
+PhobosTrajectoryType* PhobosTrajectoryType::LoadFromStream(PhobosStreamReader& Stm)
+{
+ PhobosTrajectoryType* pType = nullptr;
+ Stm.Process(pType, false);
+ if (pType)
+ {
+ Stm.Process(pType->Flag, false);
+ switch (pType->Flag)
+ {
+ case TrajectoryFlag::Straight:
+ pType = GameCreate();
+ break;
+
+ case TrajectoryFlag::Bombard:
+ pType = GameCreate();
+ break;
+
+ default:
+ return nullptr;
+ }
+ pType->Load(Stm, false);
+ }
+ return pType;
+}
+
+void PhobosTrajectoryType::WriteToStream(PhobosStreamWriter& Stm, PhobosTrajectoryType* pType)
+{
+ Stm.Process(pType);
+ if (pType)
+ {
+ Stm.Process(pType->Flag);
+ pType->Save(Stm);
+ }
+}
+
+PhobosTrajectoryType* PhobosTrajectoryType::ProcessFromStream(PhobosStreamReader& Stm, PhobosTrajectoryType* pType)
+{
+ UNREFERENCED_PARAMETER(pType);
+ return LoadFromStream(Stm);
+}
+
+PhobosTrajectoryType* PhobosTrajectoryType::ProcessFromStream(PhobosStreamWriter& Stm, PhobosTrajectoryType* pType)
+{
+ WriteToStream(Stm, pType);
+ return pType;
+}
+
+bool PhobosTrajectory::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ Stm.Process(this->Flag, false);
+ return true;
+}
+
+bool PhobosTrajectory::Save(PhobosStreamWriter& Stm) const
+{
+ Stm.Process(this->Flag);
+ return true;
+}
+
+double PhobosTrajectory::GetTrajectorySpeed(BulletClass* pBullet) const
+{
+ if (auto const pWeaponExt = WeaponTypeExt::ExtMap.Find(pBullet->WeaponType))
+ return pWeaponExt->Trajectory_Speed;
+ else
+ return 100.0;
+}
+
+PhobosTrajectory* PhobosTrajectory::CreateInstance(PhobosTrajectoryType* pType, BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity)
+{
+ PhobosTrajectory* pRet = nullptr;
+
+ switch (pType->Flag)
+ {
+ case TrajectoryFlag::Straight:
+ pRet = GameCreate(pType);
+ break;
+
+ case TrajectoryFlag::Bombard:
+ pRet = GameCreate(pType);
+ break;
+ }
+
+ if (pRet)
+ pRet->OnUnlimbo(pBullet, pCoord, pVelocity);
+
+ return pRet;
+}
+
+PhobosTrajectory* PhobosTrajectory::LoadFromStream(PhobosStreamReader& Stm)
+{
+ PhobosTrajectory* pTraj = nullptr;
+ Stm.Process(pTraj, false);
+ if (pTraj)
+ {
+ Stm.Process(pTraj->Flag, false);
+ switch (pTraj->Flag)
+ {
+ case TrajectoryFlag::Straight:
+ pTraj = GameCreate();
+ break;
+
+ case TrajectoryFlag::Bombard:
+ pTraj = GameCreate();
+ break;
+
+ default:
+ return nullptr;
+ }
+ pTraj->Load(Stm, false);
+ }
+ return pTraj;
+}
+
+void PhobosTrajectory::WriteToStream(PhobosStreamWriter& Stm, PhobosTrajectory* pTraj)
+{
+ Stm.Process(pTraj);
+ if (pTraj)
+ {
+ Stm.Process(pTraj->Flag);
+ pTraj->Save(Stm);
+ }
+}
+
+PhobosTrajectory* PhobosTrajectory::ProcessFromStream(PhobosStreamReader& Stm, PhobosTrajectory* pTraj)
+{
+ UNREFERENCED_PARAMETER(pTraj);
+ return LoadFromStream(Stm);
+}
+
+PhobosTrajectory* PhobosTrajectory::ProcessFromStream(PhobosStreamWriter& Stm, PhobosTrajectory* pTraj)
+{
+ WriteToStream(Stm, pTraj);
+ return pTraj;
+}
+
+
+DEFINE_HOOK(0x4666F7, BulletClass_AI_Trajectories, 0x6)
+{
+ GET(BulletClass*, pThis, EBP);
+
+ auto const pExt = BulletExt::ExtMap.Find(pThis);
+
+ if (auto pTraj = pExt->Trajectory)
+ pTraj->OnAI(pThis);
+
+ return 0;
+}
+
+DEFINE_HOOK(0x46745C, BulletClass_AI_Postition_Trajectories, 0x7)
+{
+ GET(BulletClass*, pThis, EBP);
+ LEA_STACK(BulletVelocity*, pSpeed, STACK_OFFS(0x1AC, 0x11C));
+ LEA_STACK(BulletVelocity*, pPosition, STACK_OFFS(0x1AC, 0x144));
+
+ auto const pExt = BulletExt::ExtMap.Find(pThis);
+
+ if (auto pTraj = pExt->Trajectory)
+ pTraj->OnAIVelocity(pThis, pSpeed, pPosition);
+
+ return 0;
+}
+
+DEFINE_HOOK(0x468B72, BulletClass_Unlimbo_Trajectories, 0x5)
+{
+ GET(BulletClass*, pThis, EBX);
+ GET_STACK(CoordStruct*, pCoord, STACK_OFFS(0x54, -0x4));
+ GET_STACK(BulletVelocity*, pVelocity, STACK_OFFS(0x54, -0x8));
+
+ auto const pData = BulletTypeExt::ExtMap.Find(pThis->Type);
+ auto const pExt = BulletExt::ExtMap.Find(pThis);
+
+ if (auto pType = pData->TrajectoryType)
+ pExt->Trajectory = PhobosTrajectory::CreateInstance(pType, pThis, pCoord, pVelocity);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/src/Ext/Bullet/Trajectories/PhobosTrajectory.h b/src/Ext/Bullet/Trajectories/PhobosTrajectory.h
new file mode 100644
index 0000000000..011c372adb
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/PhobosTrajectory.h
@@ -0,0 +1,136 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include
+
+enum class TrajectoryFlag : int
+{
+ Invalid = -1,
+ Straight = 0,
+ Bombard = 1,
+};
+
+class PhobosTrajectoryType
+{
+public:
+ PhobosTrajectoryType(noinit_t) { }
+ PhobosTrajectoryType(TrajectoryFlag flag) : Flag { flag } { }
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange);
+ virtual bool Save(PhobosStreamWriter& Stm) const;
+
+ virtual void Read(CCINIClass* const pINI, const char* pSection) = 0;
+
+ static void CreateType(PhobosTrajectoryType*& pType, CCINIClass* const pINI, const char* pSection, const char* pKey);
+
+ static PhobosTrajectoryType* LoadFromStream(PhobosStreamReader& Stm);
+ static void WriteToStream(PhobosStreamWriter& Stm, PhobosTrajectoryType* pType);
+ static PhobosTrajectoryType* ProcessFromStream(PhobosStreamReader& Stm, PhobosTrajectoryType* pType);
+ static PhobosTrajectoryType* ProcessFromStream(PhobosStreamWriter& Stm, PhobosTrajectoryType* pType);
+
+ TrajectoryFlag Flag;
+};
+
+class PhobosTrajectory
+{
+public:
+ PhobosTrajectory(noinit_t) { }
+ PhobosTrajectory(TrajectoryFlag flag) : Flag { flag } { }
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange);
+ virtual bool Save(PhobosStreamWriter& Stm) const;
+
+ virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) = 0;
+ virtual void OnAI(BulletClass* pBullet) = 0;
+ virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) = 0;
+
+ template
+ T* GetTrajectoryType(BulletClass* pBullet) const
+ {
+ return static_cast(BulletTypeExt::ExtMap.Find(pBullet->Type)->TrajectoryType);
+ }
+ double GetTrajectorySpeed(BulletClass* pBullet) const;
+
+ static PhobosTrajectory* CreateInstance(PhobosTrajectoryType* pType, BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity);
+
+ static PhobosTrajectory* LoadFromStream(PhobosStreamReader& Stm);
+ static void WriteToStream(PhobosStreamWriter& Stm, PhobosTrajectory* pTraj);
+ static PhobosTrajectory* ProcessFromStream(PhobosStreamReader& Stm, PhobosTrajectory* pTraj);
+ static PhobosTrajectory* ProcessFromStream(PhobosStreamWriter& Stm, PhobosTrajectory* pTraj);
+
+ TrajectoryFlag Flag { TrajectoryFlag::Invalid };
+};
+
+/*
+* This is a guidance to tell you how to add your trajectory here
+* Firstly, we just image the game coordinate into a 2D-plain
+*
+* ZAxis
+* | TargetCoord
+* |
+* |
+* |
+* |
+* | SourceCoord
+* O-------------------------------------XYPlain
+*
+* Then our problem just turns into:
+* Find an equation whose curve just passes both two coord
+* And the curve is just your trajectory
+*
+* Luckily, what we need to implement this is just calculate the velocity during the movement
+* So a possible way is to find out the equation and find the derivative of it, which is just the velocity
+* And the just code on it!
+*
+* There is a SampleTrajectory already, you can just copy it and do some edits.
+* Following that, you can create a fun trajectory very easily. - secsome
+*
+* ^*##^
+* *###$ *##^*#*
+* ##^ $## ^##^ ^##
+* ## ##$ ^## ^##
+* ## $#* ^^^ ^^^^^^$#* ## ^$*###################*$^
+* *#^ ^###############$ ^#######*$^ ^#*****#^ ^$*####$^
+* ^#$ $##^ ##* $##^ ^*$ #*****# ^#####*^
+* ## $#####^ *#***####$^
+* ## $###$ ^$^ ^#####* ^###^
+* *#**$ ^#^ *###$^ ^$$$$ *##
+* $$$*##### ^^ ##*
+* $#^ ^###* *$ #### $*####*^ ^##
+* ^$***$$#* $#### ## ^####^ ^**$$$*#^ ##^
+* $#***$##^ ^$^ $######^ $$ ##^
+* ## $^ ^^ ##
+* $#^ ##
+* ## $#^
+* ^#$ ##
+* *# ^#$
+* ## ##
+* #* $#
+* ^#$ ###################*^
+* $# $###^ ^#**#^ #*###*
+* $# $*** **** **$*##
+* $# $###^ *#*#^ #####$
+* $# *#**##############*$
+* $# #*
+* ^#^ ^#^
+* #$ *#
+* ## #*
+* *#^ *#
+* ## #*
+* $#^ ##
+* ## *#^
+* ^## $#$
+* ^## $#*
+* ## $#*
+* ##* *#*
+* ^##$ ##^
+* $##$ *##
+* $##*^ ^###^
+* ^## ^###**$$$$$$$$$$$ ^$$$$$$$$$$$$$$$$$$****$ *############## ^##$
+* #####$$*****#########^##*#########*#**###*****##$##$^$$$$^$$^^^^##*##
+* ^$^ *##^ *** ^$
+*
+*/
\ No newline at end of file
diff --git a/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp b/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp
new file mode 100644
index 0000000000..a24d37606e
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp
@@ -0,0 +1,84 @@
+#include "SampleTrajectory.h"
+
+#include
+
+// Save and Load
+bool SampleTrajectoryType::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ this->PhobosTrajectoryType::Load(Stm, false);
+ Stm.Process(this->ExtraHeight, false);
+ return true;
+}
+
+bool SampleTrajectoryType::Save(PhobosStreamWriter& Stm) const
+{
+ this->PhobosTrajectoryType::Save(Stm);
+ Stm.Process(this->ExtraHeight);
+ return true;
+}
+
+// INI reading stuff
+void SampleTrajectoryType::Read(CCINIClass* const pINI, const char* pSection)
+{
+ this->ExtraHeight = pINI->ReadDouble(pSection, "Trajectory.Sample.ExtraHeight", 1145.14);
+}
+
+bool SampleTrajectory::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ this->PhobosTrajectory::Load(Stm, false);
+ Stm.Process(this->IsFalling, false);
+ return true;
+}
+
+bool SampleTrajectory::Save(PhobosStreamWriter& Stm) const
+{
+ this->PhobosTrajectory::Save(Stm);
+ Stm.Process(this->IsFalling);
+ return true;
+}
+
+// Do some math here to set the initial speed of your proj
+void SampleTrajectory::OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity)
+{
+ auto extraZ = this->GetTrajectoryType(pBullet)->ExtraHeight;
+
+ pBullet->Velocity.X = static_cast(pBullet->TargetCoords.X - pBullet->SourceCoords.X);
+ pBullet->Velocity.Y = static_cast(pBullet->TargetCoords.Y - pBullet->SourceCoords.Y);
+ pBullet->Velocity.Z = static_cast(pBullet->TargetCoords.Z + extraZ - pBullet->SourceCoords.Z);
+ pBullet->Velocity *= this->GetTrajectorySpeed(pBullet) / pBullet->Velocity.Magnitude();
+}
+
+// Some early checks here
+void SampleTrajectory::OnAI(BulletClass* pBullet)
+{
+ // Close enough
+ if (pBullet->TargetCoords.DistanceFrom(pBullet->Location) < 100)
+ {
+ pBullet->Detonate(pBullet->Location);
+ pBullet->UnInit();
+ pBullet->LastMapCoords = CellClass::Coord2Cell(pBullet->Location);
+ }
+}
+
+// Where you update the speed and position
+// pSpeed: The speed of this proj in the next frame
+// pPosition: Current position of the proj, and in the next frame it will be *pSpeed + *pPosition
+void SampleTrajectory::OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition)
+{
+ if (!this->IsFalling)
+ {
+ pSpeed->Z += BulletTypeExt::GetAdjustedGravity(pBullet->Type);
+ double dx = pBullet->TargetCoords.X - pBullet->Location.X;
+ double dy = pBullet->TargetCoords.Y - pBullet->Location.Y;
+ if (dx * dx + dy * dy < pBullet->Velocity.X * pBullet->Velocity.X + pBullet->Velocity.Y * pBullet->Velocity.Y)
+ {
+ this->IsFalling = true;
+ pSpeed->X = 0.0;
+ pSpeed->Y = 0.0;
+ pSpeed->Z = 0.0;
+ pPosition->X = pBullet->TargetCoords.X;
+ pPosition->Y = pBullet->TargetCoords.Y;
+ }
+ }
+
+}
diff --git a/src/Ext/Bullet/Trajectories/SampleTrajectory.h b/src/Ext/Bullet/Trajectories/SampleTrajectory.h
new file mode 100644
index 0000000000..826017b60b
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/SampleTrajectory.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "PhobosTrajectory.h"
+
+/*
+* This is a sample class telling you how to make a new type of Trajectory
+* Author: secsome
+*/
+
+// Used in BulletTypeExt
+class SampleTrajectoryType final : public PhobosTrajectoryType
+{
+public:
+ SampleTrajectoryType() : PhobosTrajectoryType(TrajectoryFlag::Sample)
+ , ExtraHeight { 0.0 }
+ { }
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override;
+ virtual bool Save(PhobosStreamWriter& Stm) const override;
+
+ virtual void Read(CCINIClass* const pINI, const char* pSection) override;
+
+ // Your type properties
+ double ExtraHeight;
+};
+
+// Used in BulletExt
+class SampleTrajectory final : public PhobosTrajectory
+{
+public:
+ // This constructor is for Save & Load
+ SampleTrajectory() : PhobosTrajectory(TrajectoryFlag::Sample)
+ , IsFalling { false }
+ {}
+
+ SampleTrajectory(PhobosTrajectoryType* pType) : PhobosTrajectory(TrajectoryFlag::Sample)
+ , IsFalling { false }
+ {}
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override;
+ virtual bool Save(PhobosStreamWriter& Stm) const override;
+
+ virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) override;
+ virtual void OnAI(BulletClass* pBullet) override;
+ virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) override;
+
+ // Your properties
+ bool IsFalling;
+};
\ No newline at end of file
diff --git a/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp b/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
new file mode 100644
index 0000000000..8ef530f78f
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
@@ -0,0 +1,53 @@
+#include "StraightTrajectory.h"
+#include
+
+bool StraightTrajectoryType::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ this->PhobosTrajectoryType::Load(Stm, false);
+ return true;
+}
+
+bool StraightTrajectoryType::Save(PhobosStreamWriter& Stm) const
+{
+ this->PhobosTrajectoryType::Save(Stm);
+ return true;
+}
+
+
+void StraightTrajectoryType::Read(CCINIClass* const pINI, const char* pSection)
+{
+}
+
+bool StraightTrajectory::Load(PhobosStreamReader& Stm, bool RegisterForChange)
+{
+ return true;
+}
+
+bool StraightTrajectory::Save(PhobosStreamWriter& Stm) const
+{
+ return true;
+}
+
+void StraightTrajectory::OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity)
+{
+ pBullet->Velocity.X = static_cast(pBullet->TargetCoords.X - pBullet->SourceCoords.X);
+ pBullet->Velocity.Y = static_cast(pBullet->TargetCoords.Y - pBullet->SourceCoords.Y);
+ pBullet->Velocity.Z = static_cast(pBullet->TargetCoords.Z - pBullet->SourceCoords.Z);
+ pBullet->Velocity *= this->GetTrajectorySpeed(pBullet) / pBullet->Velocity.Magnitude();
+}
+
+void StraightTrajectory::OnAI(BulletClass* pBullet)
+{
+ if (pBullet->TargetCoords.DistanceFrom(pBullet->Location) < 100)
+ {
+ pBullet->Explode(true);
+ pBullet->UnInit();
+ pBullet->LastMapCoords = CellClass::Coord2Cell(pBullet->Location);
+ }
+
+}
+
+void StraightTrajectory::OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition)
+{
+ pSpeed->Z += BulletTypeExt::GetAdjustedGravity(pBullet->Type); // We don't want to take the gravity into account
+}
diff --git a/src/Ext/Bullet/Trajectories/StraightTrajectory.h b/src/Ext/Bullet/Trajectories/StraightTrajectory.h
new file mode 100644
index 0000000000..aae0692c29
--- /dev/null
+++ b/src/Ext/Bullet/Trajectories/StraightTrajectory.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "PhobosTrajectory.h"
+
+class StraightTrajectoryType final : public PhobosTrajectoryType
+{
+public:
+ StraightTrajectoryType() : PhobosTrajectoryType(TrajectoryFlag::Straight)
+ { }
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override;
+ virtual bool Save(PhobosStreamWriter& Stm) const override;
+
+ virtual void Read(CCINIClass* const pINI, const char* pSection) override;
+};
+
+class StraightTrajectory final : public PhobosTrajectory
+{
+public:
+ StraightTrajectory() : PhobosTrajectory(TrajectoryFlag::Straight)
+ { }
+
+ StraightTrajectory(PhobosTrajectoryType* pType) : PhobosTrajectory(TrajectoryFlag::Straight)
+ {}
+
+ virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override;
+ virtual bool Save(PhobosStreamWriter& Stm) const override;
+
+ virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) override;
+ virtual void OnAI(BulletClass* pBullet) override;
+ virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) override;
+};
\ No newline at end of file
diff --git a/src/Ext/BulletType/Body.cpp b/src/Ext/BulletType/Body.cpp
index a10aefe2f7..1f6da6ffa4 100644
--- a/src/Ext/BulletType/Body.cpp
+++ b/src/Ext/BulletType/Body.cpp
@@ -35,7 +35,9 @@ void BulletTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->Interceptable.Read(exINI, pSection, "Interceptable");
this->Gravity.Read(exINI, pSection, "Gravity");
- this->Gravity_HeightFix.Read(exINI, pSection, "Gravity.HeightFix");
+
+ PhobosTrajectoryType::CreateType(this->TrajectoryType, pINI, pSection, "Trajectory");
+
this->Shrapnel_AffectsGround.Read(exINI, pSection, "Shrapnel.AffectsGround");
this->Shrapnel_AffectsBuildings.Read(exINI, pSection, "Shrapnel.AffectsBuildings");
@@ -54,10 +56,11 @@ void BulletTypeExt::ExtData::Serialize(T& Stm)
.Process(this->Interceptable)
.Process(this->LaserTrail_Types)
.Process(this->Gravity)
- .Process(this->Gravity_HeightFix)
.Process(this->Shrapnel_AffectsGround)
.Process(this->Shrapnel_AffectsBuildings)
;
+
+ this->TrajectoryType = PhobosTrajectoryType::ProcessFromStream(Stm, this->TrajectoryType);
}
void BulletTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
@@ -95,6 +98,9 @@ DEFINE_HOOK(0x46C8B6, BulletTypeClass_SDDTOR, 0x6)
{
GET(BulletTypeClass*, pItem, ESI);
+ if (auto pType = BulletTypeExt::ExtMap.Find(pItem)->TrajectoryType)
+ GameDelete(pType);
+
BulletTypeExt::ExtMap.Remove(pItem);
return 0;
}
diff --git a/src/Ext/BulletType/Body.h b/src/Ext/BulletType/Body.h
index 22ac6fc8ac..97a5977b78 100644
--- a/src/Ext/BulletType/Body.h
+++ b/src/Ext/BulletType/Body.h
@@ -7,6 +7,8 @@
#include
+#include
+
class BulletTypeExt
{
public:
@@ -18,7 +20,9 @@ class BulletTypeExt
Valueable Interceptable;
ValueableIdxVector LaserTrail_Types;
Nullable Gravity;
- Valueable Gravity_HeightFix;
+
+ PhobosTrajectoryType* TrajectoryType;
+
Valueable Shrapnel_AffectsGround;
Valueable Shrapnel_AffectsBuildings;
@@ -26,7 +30,7 @@ class BulletTypeExt
, Interceptable { false }
, LaserTrail_Types {}
, Gravity {}
- , Gravity_HeightFix { false }
+ , TrajectoryType { nullptr }
, Shrapnel_AffectsGround { false }
, Shrapnel_AffectsBuildings { false }
{ }
diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp
index af7e167142..9e7994c2a3 100644
--- a/src/Ext/WeaponType/Body.cpp
+++ b/src/Ext/WeaponType/Body.cpp
@@ -47,6 +47,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->DetachedFromOwner.Read(exINI, pSection, "DetachedFromOwner");
this->FeedbackWeapon.Read(exINI, pSection, "FeedbackWeapon", true);
this->Laser_IsSingleColor.Read(exINI, pSection, "IsSingleColor");
+ this->Trajectory_Speed.Read(exINI, pSection, "Trajectory.Speed");
}
template
@@ -69,6 +70,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm)
.Process(this->DetachedFromOwner)
.Process(this->FeedbackWeapon)
.Process(this->Laser_IsSingleColor)
+ .Process(this->Trajectory_Speed)
;
};
diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h
index f197708979..b4987f2fe2 100644
--- a/src/Ext/WeaponType/Body.h
+++ b/src/Ext/WeaponType/Body.h
@@ -33,6 +33,7 @@ class WeaponTypeExt
Valueable DetachedFromOwner;
Nullable FeedbackWeapon;
Valueable Laser_IsSingleColor;
+ Valueable Trajectory_Speed;
ExtData(WeaponTypeClass* OwnerObject) : Extension(OwnerObject)
, DiskLaser_Radius { 38.2 }
@@ -51,6 +52,7 @@ class WeaponTypeExt
, DetachedFromOwner { false }
, FeedbackWeapon {}
, Laser_IsSingleColor { false }
+ , Trajectory_Speed { 100.0 }
{ }
virtual ~ExtData() = default;
From 43f0079ebc194546381b49e55b55be6140a69021 Mon Sep 17 00:00:00 2001
From: Starkku
Date: Tue, 12 Apr 2022 20:07:58 +0300
Subject: [PATCH 2/3] Disable a counterproductive collision check for custom
trajectory projectiles
---
.../Bullet/Trajectories/PhobosTrajectory.cpp | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp b/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
index 2e43b00c4b..e6260c7936 100644
--- a/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
+++ b/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
@@ -221,5 +221,22 @@ DEFINE_HOOK(0x468B72, BulletClass_Unlimbo_Trajectories, 0x5)
if (auto pType = pData->TrajectoryType)
pExt->Trajectory = PhobosTrajectory::CreateInstance(pType, pThis, pCoord, pVelocity);
+ return 0;
+}
+
+// Disables weird collision checks that alter trajectory if bullet
+// goes on a cell with enemy technos for custom Trajectory projectiles.
+DEFINE_HOOK(0x467921, BulletClass_AI_Trajectories_SkipChecks, 0x6)
+{
+ enum { SkipCheck = 0x467965 };
+
+ GET(BulletClass*, pThis, EBP);
+
+ if (auto const pExt = BulletTypeExt::ExtMap.Find(pThis->Type))
+ {
+ if (pExt->TrajectoryType != nullptr)
+ return SkipCheck;
+ }
+
return 0;
}
\ No newline at end of file
From 56a73b1ea8bfcb52f4586cf7bce06fa82553fd4c Mon Sep 17 00:00:00 2001
From: Starkku
Date: Tue, 12 Apr 2022 22:05:05 +0300
Subject: [PATCH 3/3] Add hooks for techno / target coord checks that call
trajectory class methods
---
.../Bullet/Trajectories/BombardTrajectory.cpp | 10 ++++
.../Bullet/Trajectories/BombardTrajectory.h | 2 +
.../Bullet/Trajectories/PhobosTrajectory.cpp | 54 ++++++++++++++-----
.../Bullet/Trajectories/PhobosTrajectory.h | 9 ++++
.../Bullet/Trajectories/SampleTrajectory.cpp | 17 ++++++
.../Trajectories/StraightTrajectory.cpp | 11 ++++
.../Bullet/Trajectories/StraightTrajectory.h | 2 +
7 files changed, 91 insertions(+), 14 deletions(-)
diff --git a/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp b/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp
index 3cbc4bc54e..d784d2e5d8 100644
--- a/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp
+++ b/src/Ext/Bullet/Trajectories/BombardTrajectory.cpp
@@ -83,3 +83,13 @@ void BombardTrajectory::OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpee
}
}
+
+TrajectoryCheckReturnType BombardTrajectory::OnAITargetCoordCheck(BulletClass* pBullet)
+{
+ return TrajectoryCheckReturnType::ExecuteGameCheck; // Execute game checks.
+}
+
+TrajectoryCheckReturnType BombardTrajectory::OnAITechnoCheck(BulletClass* pBullet, TechnoClass* pTechno)
+{
+ return TrajectoryCheckReturnType::SkipGameCheck; // Bypass game checks entirely.
+}
\ No newline at end of file
diff --git a/src/Ext/Bullet/Trajectories/BombardTrajectory.h b/src/Ext/Bullet/Trajectories/BombardTrajectory.h
index 77aa532b26..b269486b11 100644
--- a/src/Ext/Bullet/Trajectories/BombardTrajectory.h
+++ b/src/Ext/Bullet/Trajectories/BombardTrajectory.h
@@ -36,6 +36,8 @@ class BombardTrajectory final : public PhobosTrajectory
virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) override;
virtual void OnAI(BulletClass* pBullet) override;
virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) override;
+ virtual TrajectoryCheckReturnType OnAITargetCoordCheck(BulletClass* pBullet) override;
+ virtual TrajectoryCheckReturnType OnAITechnoCheck(BulletClass* pBullet, TechnoClass* pTechno) override;
bool IsFalling;
double Height;
diff --git a/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp b/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
index e6260c7936..7cf0608d08 100644
--- a/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
+++ b/src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
@@ -195,7 +195,7 @@ DEFINE_HOOK(0x4666F7, BulletClass_AI_Trajectories, 0x6)
return 0;
}
-DEFINE_HOOK(0x46745C, BulletClass_AI_Postition_Trajectories, 0x7)
+DEFINE_HOOK(0x46745C, BulletClass_AI_Position_Trajectories, 0x7)
{
GET(BulletClass*, pThis, EBP);
LEA_STACK(BulletVelocity*, pSpeed, STACK_OFFS(0x1AC, 0x11C));
@@ -209,34 +209,60 @@ DEFINE_HOOK(0x46745C, BulletClass_AI_Postition_Trajectories, 0x7)
return 0;
}
-DEFINE_HOOK(0x468B72, BulletClass_Unlimbo_Trajectories, 0x5)
+DEFINE_HOOK(0x4677D3, BulletClass_AI_TargetCoordCheck_Trajectories, 0x5)
{
- GET(BulletClass*, pThis, EBX);
- GET_STACK(CoordStruct*, pCoord, STACK_OFFS(0x54, -0x4));
- GET_STACK(BulletVelocity*, pVelocity, STACK_OFFS(0x54, -0x8));
+ enum { SkipCheck = 0x4678F8, ContinueAfterCheck = 0x467879 };
+
+ GET(BulletClass*, pThis, EBP);
- auto const pData = BulletTypeExt::ExtMap.Find(pThis->Type);
auto const pExt = BulletExt::ExtMap.Find(pThis);
- if (auto pType = pData->TrajectoryType)
- pExt->Trajectory = PhobosTrajectory::CreateInstance(pType, pThis, pCoord, pVelocity);
+ if (auto pTraj = pExt->Trajectory)
+ {
+ auto flag = pTraj->OnAITargetCoordCheck(pThis);
+
+ if (flag == TrajectoryCheckReturnType::SkipGameCheck)
+ return SkipCheck;
+ if (flag == TrajectoryCheckReturnType::SatisfyGameCheck)
+ return ContinueAfterCheck;
+ }
return 0;
}
-// Disables weird collision checks that alter trajectory if bullet
-// goes on a cell with enemy technos for custom Trajectory projectiles.
-DEFINE_HOOK(0x467921, BulletClass_AI_Trajectories_SkipChecks, 0x6)
+DEFINE_HOOK(0x467921, BulletClass_AI_TechnoCheck_Trajectories, 0x6)
{
- enum { SkipCheck = 0x467965 };
+ enum { SkipCheck = 0x467965, ContinueAfterCheck = 0x467514 };
GET(BulletClass*, pThis, EBP);
+ GET(TechnoClass*, pTechno, ESI);
+
+ auto const pExt = BulletExt::ExtMap.Find(pThis);
- if (auto const pExt = BulletTypeExt::ExtMap.Find(pThis->Type))
+ if (auto pTraj = pExt->Trajectory)
{
- if (pExt->TrajectoryType != nullptr)
+ auto flag = pTraj->OnAITechnoCheck(pThis, pTechno);
+
+ if (flag == TrajectoryCheckReturnType::SkipGameCheck)
return SkipCheck;
+ if (flag == TrajectoryCheckReturnType::SatisfyGameCheck)
+ return ContinueAfterCheck;
}
+ return 0;
+}
+
+DEFINE_HOOK(0x468B72, BulletClass_Unlimbo_Trajectories, 0x5)
+{
+ GET(BulletClass*, pThis, EBX);
+ GET_STACK(CoordStruct*, pCoord, STACK_OFFS(0x54, -0x4));
+ GET_STACK(BulletVelocity*, pVelocity, STACK_OFFS(0x54, -0x8));
+
+ auto const pData = BulletTypeExt::ExtMap.Find(pThis->Type);
+ auto const pExt = BulletExt::ExtMap.Find(pThis);
+
+ if (auto pType = pData->TrajectoryType)
+ pExt->Trajectory = PhobosTrajectory::CreateInstance(pType, pThis, pCoord, pVelocity);
+
return 0;
}
\ No newline at end of file
diff --git a/src/Ext/Bullet/Trajectories/PhobosTrajectory.h b/src/Ext/Bullet/Trajectories/PhobosTrajectory.h
index 011c372adb..9d1d27409b 100644
--- a/src/Ext/Bullet/Trajectories/PhobosTrajectory.h
+++ b/src/Ext/Bullet/Trajectories/PhobosTrajectory.h
@@ -13,6 +13,13 @@ enum class TrajectoryFlag : int
Bombard = 1,
};
+enum class TrajectoryCheckReturnType : int
+{
+ ExecuteGameCheck = 0,
+ SkipGameCheck = 1,
+ SatisfyGameCheck = 2,
+};
+
class PhobosTrajectoryType
{
public:
@@ -46,6 +53,8 @@ class PhobosTrajectory
virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) = 0;
virtual void OnAI(BulletClass* pBullet) = 0;
virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) = 0;
+ virtual TrajectoryCheckReturnType OnAITargetCoordCheck(BulletClass* pBullet) = 0;
+ virtual TrajectoryCheckReturnType OnAITechnoCheck(BulletClass* pBullet, TechnoClass* pTechno) = 0;
template
T* GetTrajectoryType(BulletClass* pBullet) const
diff --git a/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp b/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp
index a24d37606e..b5aa49b60a 100644
--- a/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp
+++ b/src/Ext/Bullet/Trajectories/SampleTrajectory.cpp
@@ -82,3 +82,20 @@ void SampleTrajectory::OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed
}
}
+
+// Where additional checks based on bullet reaching its target coordinate can be done.
+// Vanilla code will do additional checks regarding buildings on target coordinate and Vertical projectiles and will detonate the projectile if they pass.
+// Return value determines what is done regards to the game checks: they can be skipped, executed as normal or treated as if the condition is already satisfied.
+TrajectoryCheckReturnType SampleTrajectory::OnAITargetCoordCheck(BulletClass* pBullet)
+{
+ return TrajectoryCheckReturnType::ExecuteGameCheck; // Execute game checks.
+}
+
+// Where additional checks based on a TechnoClass instance in same cell as the bullet can be done.
+// Vanilla code will do additional trajectory alterations here if there is an enemy techno in the cell.
+// Return value determines what is done regards to the game checks: they can be skipped, executed as normal or treated as if the condition is already satisfied.
+// pTechno: TechnoClass instance in same cell as the bullet.
+TrajectoryCheckReturnType SampleTrajectory::OnAITechnoCheck(BulletClass* pBullet, TechnoClass* pTechno)
+{
+ return TrajectoryCheckReturnType::ExecuteGameCheck; // Execute game checks.
+}
diff --git a/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp b/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
index 8ef530f78f..73785153e9 100644
--- a/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
+++ b/src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
@@ -51,3 +51,14 @@ void StraightTrajectory::OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpe
{
pSpeed->Z += BulletTypeExt::GetAdjustedGravity(pBullet->Type); // We don't want to take the gravity into account
}
+
+TrajectoryCheckReturnType StraightTrajectory::OnAITargetCoordCheck(BulletClass* pBullet)
+{
+ return TrajectoryCheckReturnType::ExecuteGameCheck; // Execute game checks.
+}
+
+TrajectoryCheckReturnType StraightTrajectory::OnAITechnoCheck(BulletClass* pBullet, TechnoClass* pTechno)
+{
+ return TrajectoryCheckReturnType::SkipGameCheck; // Bypass game checks entirely.
+}
+
diff --git a/src/Ext/Bullet/Trajectories/StraightTrajectory.h b/src/Ext/Bullet/Trajectories/StraightTrajectory.h
index aae0692c29..2597639e84 100644
--- a/src/Ext/Bullet/Trajectories/StraightTrajectory.h
+++ b/src/Ext/Bullet/Trajectories/StraightTrajectory.h
@@ -29,4 +29,6 @@ class StraightTrajectory final : public PhobosTrajectory
virtual void OnUnlimbo(BulletClass* pBullet, CoordStruct* pCoord, BulletVelocity* pVelocity) override;
virtual void OnAI(BulletClass* pBullet) override;
virtual void OnAIVelocity(BulletClass* pBullet, BulletVelocity* pSpeed, BulletVelocity* pPosition) override;
+ virtual TrajectoryCheckReturnType OnAITargetCoordCheck(BulletClass* pBullet) override;
+ virtual TrajectoryCheckReturnType OnAITechnoCheck(BulletClass* pBullet, TechnoClass* pTechno) override;
};
\ No newline at end of file