Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Phobos.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<ClCompile Include="src\Commands\Commands.cpp" />
<ClCompile Include="src\Commands\Dummy.h" />
<ClCompile Include="src\Enum\RadTypes.cpp" />
<ClCompile Include="src\Ext\Aircraft\Body.cpp" />
<ClCompile Include="src\Ext\Aircraft\Hooks.cpp" />
<ClCompile Include="src\Ext\Building\Body.cpp" />
<ClCompile Include="src\Ext\Building\Hooks.cpp" />
<ClCompile Include="src\Ext\BulletType\Body.cpp" />
Expand Down Expand Up @@ -78,6 +80,7 @@
<ClInclude Include="src\ExtraHeaders\CCToolTip.h" />
<ClInclude Include="src\ExtraHeaders\Matrix3D.h" />
<ClInclude Include="src\ExtraHeaders\Themes.h" />
<ClInclude Include="src\Ext\Aircraft\Body.h" />
<ClInclude Include="src\Ext\Building\Body.h" />
<ClInclude Include="src\Ext\BulletType\Body.h" />
<ClInclude Include="src\Ext\Bullet\Body.h" />
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Credits
- AutoGavy - interceptor logic, warhead critical damage system
- Xkein - general assistance, YRpp edits
- thomassneddon - general assistance
- Starkku - Warhead shield penetration & breaking
- Starkku - Warhead shield penetration & breaking, strafing aircraft weapon customization

Thanks to everyone who uses Phobos, tests changes and reports bugs! You can show your appreciation and help project by displaying the logo (monochrome version can be found [here](https://github.com/Phobos-developers/Phobos/logo-mono.png)) in your client/launcher, contributing or donating to us via links on the right and the `Sponsor` button on top of the repo.

Expand Down
1 change: 1 addition & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
- Allowed usage of TileSet of 255 and above without making NE-SW broken bridges unrepairable.
- `TurretOffset` tag for voxel turreted technos now accepts FLH (forward, lateral, height) values like `TurretOffset=F,L` or `TurretOffset=F,L,H`, which means turret location can be adjusted in all three axes.
- `InfiniteMindControl` with `Damage=1` can now control more than 1 unit.
- Aircraft with `Fighter` set to false or those using strafing pattern (weapon projectile `ROT` is below 2) now take weapon's `Burst` into accord for all shots instead of just the first one.

![image](_static/images/remember-target-after-deploying-01.gif)
*Nod arty keeping target on attack order in [C&C: Reloaded](https://www.moddb.com/mods/cncreloaded/)*
Expand Down
16 changes: 16 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ BreaksShield=false ; boolean

## Weapons

### Strafing aircraft weapon customization

![image](_static/images/strafing-01.gif)
*Strafing aircraft weapon customization in [Project Phantom](https://www.moddb.com/mods/project-phantom)*

- Some of the behaviour of strafing aircraft weapons (weapon projectile has `ROT` below 2) can now be customized.
- `Strafing.Shots` controls the number of times the weapon is fired during a single strafe run. `Ammo` is only deducted at the end of the strafe run, regardless of the number of shots fired. Valid values range from 1 to 5, any values smaller or larger are effectively treated same as either 1 or 5, respectively. Defaults to 5.
- `Strafing.SimulateBurst` controls whether or not the shots fired during strafing simulate behaviour of `Burst`, allowing for alternating firing offset. Only takes effect if weapon has `Burst` set to 1 or undefined. Defaults to false.

In `rulesmd.ini`:
```ini
[SOMEWEAPON] ; WeaponType
Strafing.Shots=5 ; integer
Strafing.SimulateBurst=false ; bool
```

### Custom Radiation Types

![image](_static/images/radtype-01.png)
Expand Down
Binary file added docs/_static/images/strafing-01.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions src/Ext/Aircraft/Body.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "Body.h"
#include <Ext/WeaponType/Body.h>

// TODO: Implement proper extended AircraftClass.

void AircraftExt::FireBurst(AircraftClass* pThis, AbstractClass* pTarget, int shotNumber = 0)
{
int weaponIndex = pThis->SelectWeapon(pTarget);
auto weaponType = pThis->GetWeapon(weaponIndex)->WeaponType;
auto pWeaponTypeExt = WeaponTypeExt::ExtMap.Find(weaponType);

if (weaponType->Burst > 0)
{
while (pThis->CurrentBurstIndex < weaponType->Burst)
{
if (weaponType->Burst < 2 && pWeaponTypeExt->Strafing_SimulateBurst)
pThis->CurrentBurstIndex = shotNumber;

pThis->Fire(pThis->Target, weaponIndex);

if (pThis->CurrentBurstIndex == 0)
break;
}
}
}
11 changes: 11 additions & 0 deletions src/Ext/Aircraft/Body.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include <AircraftClass.h>

// TODO: Implement proper extended AircraftClass.

class AircraftExt
{
public:
static void FireBurst(AircraftClass* pThis, AbstractClass* pTarget, int shotNumber);
};

86 changes: 86 additions & 0 deletions src/Ext/Aircraft/Hooks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <AircraftClass.h>
#include <Utilities/Macro.h>
#include <Utilities/Enum.h>
#include <Ext/Aircraft/Body.h>
#include <Ext/WeaponType/Body.h>

DEFINE_HOOK(417FF1, AircraftClass_Mission_Attack_StrafeShots, 6)
{
GET(AircraftClass*, pThis, ESI);

if (pThis->MissionStatus < (int)AirAttackStatus::FireAtTarget2_Strafe
|| pThis->MissionStatus >(int)AirAttackStatus::FireAtTarget5_Strafe)
{
return 0;
}

int weaponIndex = pThis->SelectWeapon(pThis->Target);
auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pThis->GetWeapon(weaponIndex)->WeaponType);
int fireCount = pThis->MissionStatus - 4;

if (fireCount > 1 && pWeaponExt->Strafing_Shots < fireCount)
{
if (!pThis->Ammo)
pThis->unknown_bool_6D2 = false;

pThis->MissionStatus = (int)AirAttackStatus::ReturnToBase;
}

return 0;
}

DEFINE_HOOK(418409, AircraftClass_Mission_Attack_FireAtTarget_BurstFix, 0)
{
GET(AircraftClass*, pThis, ESI);

pThis->unknown_bool_6C8 = true;

AircraftExt::FireBurst(pThis, pThis->Target, 0);

return 0x418478;
}

DEFINE_HOOK(4186B6, AircraftClass_Mission_Attack_FireAtTarget2_BurstFix, 0)
{
GET(AircraftClass*, pThis, ESI);

AircraftExt::FireBurst(pThis, pThis->Target, 0);

return 0x4186D7;
}

DEFINE_HOOK(418805, AircraftClass_Mission_Attack_FireAtTarget2Strafe_BurstFix, 0)
{
GET(AircraftClass*, pThis, ESI);

AircraftExt::FireBurst(pThis, pThis->Target, 1);

return 0x418826;
}

DEFINE_HOOK(418914, AircraftClass_Mission_Attack_FireAtTarget3Strafe_BurstFix, 0)
{
GET(AircraftClass*, pThis, ESI);

AircraftExt::FireBurst(pThis, pThis->Target, 2);

return 0x418935;
}

DEFINE_HOOK(418A23, AircraftClass_Mission_Attack_FireAtTarget4Strafe_BurstFix, 0)
{
GET(AircraftClass*, pThis, ESI);

AircraftExt::FireBurst(pThis, pThis->Target, 3);

return 0x418A44;
}

DEFINE_HOOK(418B25, AircraftClass_Mission_Attack_FireAtTarget5Strafe_BurstFix, 0)
{
GET(AircraftClass*, pThis, ESI);

AircraftExt::FireBurst(pThis, pThis->Target, 4);

return 0x418B40;
}
43 changes: 29 additions & 14 deletions src/Ext/WeaponType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@
template<> const DWORD Extension<WeaponTypeClass>::Canary = 0x22222222;
WeaponTypeExt::ExtContainer WeaponTypeExt::ExtMap;

void WeaponTypeExt::ExtData::Initialize()
{

};
void WeaponTypeExt::ExtData::Initialize() { }

// =============================
// load / save

void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) {
void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
{
auto pThis = this->OwnerObject();
const char* pSection = pThis->ID;

if (!pINI->GetSection(pSection)) {
if (!pINI->GetSection(pSection))
return;
}

INI_EX exINI(pINI);

Expand All @@ -32,43 +29,57 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) {

// RadType
if (this->OwnerObject()->RadLevel > 0)
{
this->RadType.Read(pINI, pSection, "RadType");
this->Rad_NoOwner.Read(exINI, pSection, "Rad.NoOwner");
}

this->Strafing_Shots.Read(exINI, pSection, "Strafing.Shots");
this->Strafing_SimulateBurst.Read(exINI, pSection, "Strafing.SimulateBurst");
}

template <typename T>
void WeaponTypeExt::ExtData::Serialize(T& Stm) {
void WeaponTypeExt::ExtData::Serialize(T& Stm)
{
Stm
.Process(this->DiskLaser_Radius)
.Process(this->DiskLaser_Circumference)
.Process(this->Rad_NoOwner)
.Process(this->Bolt_Disable1)
.Process(this->Bolt_Disable2)
.Process(this->Bolt_Disable3)
.Process(this->Strafing_Shots)
.Process(this->Strafing_SimulateBurst)
;
};

void WeaponTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) {
void WeaponTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
{
Extension<WeaponTypeClass>::LoadFromStream(Stm);
this->Serialize(Stm);

if (this->OwnerObject()->RadLevel > 0)
this->RadType.LoadFromStream(Stm);
}

void WeaponTypeExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) {
void WeaponTypeExt::ExtData::SaveToStream(PhobosStreamWriter& Stm)
{
Extension<WeaponTypeClass>::SaveToStream(Stm);
this->Serialize(Stm);

if (this->OwnerObject()->RadLevel > 0)
this->RadType.SaveToStream(Stm);
}

bool WeaponTypeExt::LoadGlobals(PhobosStreamReader& Stm) {
bool WeaponTypeExt::LoadGlobals(PhobosStreamReader& Stm)
{
return Stm
.Process(nOldCircumference)
.Success();
}

bool WeaponTypeExt::SaveGlobals(PhobosStreamWriter& Stm) {
bool WeaponTypeExt::SaveGlobals(PhobosStreamWriter& Stm)
{
return Stm
.Process(nOldCircumference)
.Success();
Expand All @@ -77,8 +88,7 @@ bool WeaponTypeExt::SaveGlobals(PhobosStreamWriter& Stm) {
// =============================
// container

WeaponTypeExt::ExtContainer::ExtContainer() : Container("WeaponTypeClass") {
}
WeaponTypeExt::ExtContainer::ExtContainer() : Container("WeaponTypeClass") { }

WeaponTypeExt::ExtContainer::~ExtContainer() = default;

Expand All @@ -90,6 +100,7 @@ DEFINE_HOOK(771EE9, WeaponTypeClass_CTOR, 5)
GET(WeaponTypeClass*, pItem, ESI);

WeaponTypeExt::ExtMap.FindOrAllocate(pItem);

return 0;
}

Expand All @@ -98,6 +109,7 @@ DEFINE_HOOK(77311D, WeaponTypeClass_SDDTOR, 6)
GET(WeaponTypeClass*, pItem, ESI);

WeaponTypeExt::ExtMap.Remove(pItem);

return 0;
}

Expand All @@ -115,12 +127,14 @@ DEFINE_HOOK(772CD0, WeaponTypeClass_SaveLoad_Prefix, 7)
DEFINE_HOOK(772EA6, WeaponTypeClass_Load_Suffix, 6)
{
WeaponTypeExt::ExtMap.LoadStatic();

return 0;
}

DEFINE_HOOK(772F8C, WeaponTypeClass_Save, 5)
{
WeaponTypeExt::ExtMap.SaveStatic();

return 0;
}

Expand All @@ -132,5 +146,6 @@ DEFINE_HOOK(7729B0, WeaponTypeClass_LoadFromINI, 5)
GET_STACK(CCINIClass*, pINI, 0xE4);

WeaponTypeExt::ExtMap.LoadFromINI(pItem, pINI);

return 0;
}
6 changes: 5 additions & 1 deletion src/Ext/WeaponType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ class WeaponTypeExt
Valueable<bool> Bolt_Disable1;
Valueable<bool> Bolt_Disable2;
Valueable<bool> Bolt_Disable3;

Valueable<int> Strafing_Shots;
Valueable<bool> Strafing_SimulateBurst;

ExtData(WeaponTypeClass* OwnerObject) : Extension<WeaponTypeClass>(OwnerObject)
,DiskLaser_Radius(38.2)
,DiskLaser_Circumference(240)
Expand All @@ -32,6 +34,8 @@ class WeaponTypeExt
,Bolt_Disable1(false)
,Bolt_Disable2(false)
,Bolt_Disable3(false)
,Strafing_Shots(5)
,Strafing_SimulateBurst(false)
{ }

virtual ~ExtData() = default;
Expand Down
15 changes: 15 additions & 0 deletions src/Utilities/Enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@

#include "./../Phobos.h"

enum class AirAttackStatus
{
ValidateAZ = 0,
PickAttackLocation = 1,
TakeOff = 2,
FlyToPosition = 3,
FireAtTarget = 4,
FireAtTarget2 = 5,
FireAtTarget2_Strafe = 6,
FireAtTarget3_Strafe = 7,
FireAtTarget4_Strafe = 8,
FireAtTarget5_Strafe = 9,
ReturnToBase = 10
};

enum class SuperWeaponAITargetingMode {
None = 0,
Nuke = 1,
Expand Down