Skip to content

Commit

Permalink
Fix object id constructors and fixup engine damage/death files
Browse files Browse the repository at this point in the history
  • Loading branch information
Lazrius committed Nov 16, 2023
1 parent fb0a420 commit 2736e59
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 61 deletions.
6 changes: 2 additions & 4 deletions include/API/Types/ObjectId.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ class ObjectId

public:
explicit ObjectId(const uint val) : value(val) {}
ObjectId(const ObjectId& obj) : value(obj.value) {}
explicit ObjectId() = default;
virtual ~ObjectId() = default;
ObjectId(const ObjectId&) = default;
ObjectId& operator=(const ObjectId obj)
ObjectId& operator=(const ObjectId& obj)
{
value = obj.GetValue();
return *this;
}
ObjectId(ObjectId&&) = default;
ObjectId& operator=(ObjectId&&) = delete;

bool operator==(const ObjectId& next) const { return value == next.value; }
explicit virtual operator bool() const;
Expand Down
17 changes: 15 additions & 2 deletions include/Core/FLHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

class InternalApi;
class IServerImplHook;
class IEngineHook;
class StartupCache;
class ClientList;
class InfocardManager;
Expand All @@ -13,6 +14,7 @@ class FlPacket;

class FLHook final
{
friend IEngineHook;
friend IServerImplHook;
friend IClientImpl;
friend InternalApi;
Expand Down Expand Up @@ -43,8 +45,10 @@ class FLHook final
inline static CRCAntiCheatT crcAntiCheat;
inline static GetShipInspectT getShipInspect;

inline static bool g_NonGunHitsBase;
inline static float g_LastHitPts;
inline static bool nonGunHitsBase;
inline static float lastHitPts;
inline static ClientId dmgToClient;
inline static ObjectId dmgToSpaceId;

inline static CDPServer* cdpServer;
inline static CDPClientProxy** clientProxyArray;
Expand Down Expand Up @@ -146,6 +150,14 @@ class FLHook final
RemoteClient,
};

struct LastHitInformation
{
bool nonGunHitsBase;
float lastHitPts;
ClientId lastHitClient;
ObjectId lastHitObject;
};

static DWORD __stdcall Offset(BinaryType type, AddressList address);

static bool IsReady() { return instance != nullptr && instance->flhookReady; }
Expand All @@ -157,6 +169,7 @@ class FLHook final
static InfocardManager& GetInfocardManager() { return *instance->infocardManager; }
static Logger& GetLogger() { return *instance->logger; }
static TempBanManager& GetTempBanManager() { return *instance->tempbanManager; }
static LastHitInformation GetLastHitInformation() { return { nonGunHitsBase, lastHitPts, dmgToClient, dmgToSpaceId }; }

static Action<void, Error> MessageUniverse(std::wstring_view message);
};
4 changes: 2 additions & 2 deletions include/Core/IEngineHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class IEngineHook

static bool __stdcall LoadReputationFromCharacterFile(const RepDataList* savedReps, const LoadRepData* repToSave);
static void NonGunWeaponHitsBaseAfter();
static void BaseDestroyed(uint objectId, ClientId clientBy);
static void BaseDestroyed(ObjectId objectId, ClientId clientBy);
static void __stdcall DamageHit(char* ecx);
static int __stdcall GuidedHit(char* ecx, char* p1, DamageList* dmgList);
static bool __stdcall GuidedHit(char* ecx, char* p1, DamageList* dmgList);
static void __stdcall AddDamageEntry(DamageList* dmgList, unsigned short subObjId, float hitPts, DamageEntry::SubObjFate fate);
static void __stdcall NonGunWeaponHitsBaseBefore(const char* ECX, const char* p1, const DamageList* dmg);
static int __stdcall DisconnectPacketSent(ClientId client);
Expand Down
108 changes: 58 additions & 50 deletions source/Hooks/HkIEngineDamage.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#include "PCH.hpp"

#include "API/FLHook/ClientList.hpp"
#include "Core/IEngineHook.hpp"

#include <magic_enum.hpp>

using namespace magic_enum::bitwise_operators;

/*
* Called when a torp/missile/mine/wasp hits a ship
* return 0 -> pass on to server.dll
* return 1 -> suppress
* return false -> pass on to server.dll
* return true -> suppress
*/
int __stdcall IEngineHook::GuidedHit(char* ecx, char* p1, DamageList* dmgList)
bool __stdcall IEngineHook::GuidedHit(char* ecx, char* p1, DamageList* dmgList)
{
uint retValue = 0;
bool retValue = false;
TryHook
{
char* p;
Expand All @@ -21,41 +26,42 @@ int __stdcall IEngineHook::GuidedHit(char* ecx, char* p1, DamageList* dmgList)
uint inflictorShip;
memcpy(&inflictorShip, p1 + 4, 4);

auto [rval, skip] = CallPlugins<bool>(&Plugin::OnGuidedHit, inflictorShip, client, spaceId, dmgList);
auto [rval, skip] = CallPlugins<bool>(&Plugin::OnGuidedHit, inflictorShip, ClientId(client), ObjectId(spaceId), dmgList);
if (skip)
{
return rval;
}

g_DmgTo = client;
g_DmgToSpaceId = spaceId;
FLHook::dmgToClient = ClientId(client);
FLHook::dmgToSpaceId = ObjectId(spaceId);
if (client)
{
// a player was hit
const auto clientInflictor = Hk::Client::GetClientIdByShip(inflictorShip).Raw();
if (clientInflictor.has_error())
if (const auto inflictorId = ShipId(inflictorShip).GetPlayer(); !inflictorId.has_value())
{
retValue = 0; // hit by npc
retValue = false; // hit by npc
}
else
{
if (!AllowPlayerDamage(clientInflictor.value(), client))
if (!AllowPlayerDamage(inflictorId.value(), ClientId(client)))
{
retValue = 1;
retValue = true;
}

if (FLHookConfig::i()->general.changeCruiseDisruptorBehaviour &&
((dmgList->get_cause() == DamageCause::CruiseDisrupter || dmgList->get_cause() == DamageCause::UnkDisrupter) &&
!ClientInfo::At(client).cruiseActivated))
ClientId(client).GetData().cruiseActivated))
{
dmgList->set_cause(DamageCause::DummyDisrupter); // change to sth else, so client won't recognize it as a disruptor
dmgList->set_cause(DamageCause::DummyDisrupter); // change to something else, so client won't recognize it as a disruptor
}
}
}

CallPlugins(&Plugin::OnGuidedHitAfter, inflictorShip, client, spaceId, dmgList);
CallPlugins(&Plugin::OnGuidedHitAfter, inflictorShip, ClientId(client), ObjectId(spaceId), dmgList);
}
CatchHook({}) return retValue;
CatchHook({});

return retValue;
}

__declspec(naked) void IEngineHook::NakedGuidedHit()
Expand All @@ -69,13 +75,13 @@ __declspec(naked) void IEngineHook::NakedGuidedHit()
push ecx
call GuidedHit
pop ecx
cmp eax, 1
test al, al
jnz go_ahead
mov edx, [esp] ; suppress
add esp, 0Ch
jmp edx
go_ahead:
jmp [g_OldGuidedHit]
jmp [oldGuidedHit]
}
}

Expand All @@ -98,18 +104,18 @@ void __stdcall IEngineHook::AddDamageEntry(DamageList* dmgList, unsigned short s
bool unk1 = false;
bool unk2 = false;
float unk;
pub::SpaceObj::GetInvincible(ClientInfo[g_DmgTo].ship, unk1, unk2, unk);
pub::SpaceObj::GetInvincible(FLHook::dmgToSpaceId.GetValue(), unk1, unk2, unk);
// if so, suppress the damage
if (unk1 && unk2)
{
return;
}
}

if (g_NonGunHitsBase && dmgList->get_cause() == DamageCause::MissileTorpedo)
if (FLHook::nonGunHitsBase && dmgList->get_cause() == DamageCause::MissileTorpedo)
{
const float damage = g_LastHitPts - hitPts;
hitPts = g_LastHitPts - damage * FLHookConfig::i()->general.torpMissileBaseDamageMultiplier;
const float damage = FLHook::lastHitPts - hitPts;
hitPts = FLHook::lastHitPts - damage * FLHookConfig::i()->general.torpMissileBaseDamageMultiplier;
if (hitPts < 0)
{
hitPts = 0;
Expand All @@ -120,11 +126,11 @@ void __stdcall IEngineHook::AddDamageEntry(DamageList* dmgList, unsigned short s
{
dmgList->add_damage_entry(subObjId, hitPts, fate);
}
else if (g_DmgTo)
else if (FLHook::dmgToClient)
{
// lets see if player should do damage to other player
const auto dmgFrom = Hk::Client::GetClientIdByShip(dmgList->get_inflictor_id()).Raw();
if (dmgFrom.has_value() && AllowPlayerDamage(dmgFrom.value(), g_DmgTo))
const auto dmgFrom = ShipId(dmgList->get_inflictor_id()).GetPlayer();
if (dmgFrom.has_value() && AllowPlayerDamage(dmgFrom.value(), FLHook::dmgToClient))
{
dmgList->add_damage_entry(subObjId, hitPts, fate);
}
Expand All @@ -136,31 +142,29 @@ void __stdcall IEngineHook::AddDamageEntry(DamageList* dmgList, unsigned short s

TryHook
{
g_LastDmgList = *dmgList; // save

// check for base kill (when hull health = 0)
if (hitPts == 0 && subObjId == 1)
{
uint type;
pub::SpaceObj::GetType(g_DmgToSpaceId, type);
const auto clientKiller = Hk::Client::GetClientIdByShip(dmgList->get_inflictor_id()).Raw();
pub::SpaceObj::GetType(FLHook::dmgToSpaceId.GetValue(), type);
const auto clientKiller = ShipId(dmgList->get_inflictor_id()).GetPlayer();
if (clientKiller.has_value() && type & static_cast<uint>(ObjectType::DockingRing | ObjectType::Station | ObjectType::WeaponPlatform))
{
BaseDestroyed(g_DmgToSpaceId, clientKiller.value());
BaseDestroyed(FLHook::dmgToSpaceId, clientKiller.value());
}
}

if (g_DmgTo && subObjId == 1) // only save hits on the hull (subObjId=1)
if (FLHook::dmgToClient && subObjId == 1) // only save hits on the hull (subObjId=1)
{
ClientInfo[g_DmgTo].dmgLast = *dmgList;
FLHook::dmgToClient.GetData().dmgLast = *dmgList;
}
}
CatchHook({})
CatchHook({});

CallPlugins(&Plugin::OnAddDamageEntryAfter, dmgList, subObjId, hitPts, fate);
CallPlugins(&Plugin::OnAddDamageEntryAfter, dmgList, subObjId, hitPts, fate);

g_DmgTo = 0;
g_DmgToSpaceId = 0;
FLHook::dmgToClient = ClientId();
FLHook::dmgToSpaceId = ObjectId();
}

__declspec(naked) void IEngineHook::NakedAddDamageEntry()
Expand Down Expand Up @@ -188,12 +192,12 @@ void __stdcall IEngineHook::DamageHit(char* ecx)
uint spaceId;
memcpy(&spaceId, p + 0xB0, 4);

g_DmgTo = client;
g_DmgToSpaceId = spaceId;
FLHook::dmgToClient = ClientId(client);
FLHook::dmgToSpaceId = ObjectId(spaceId);

CallPlugins(&Plugin::OnDamageHit, client, spaceId);
}
CatchHook({})
CatchHook({});
}

__declspec(naked) void IEngineHook::NakedDamageHit()
Expand Down Expand Up @@ -230,27 +234,32 @@ bool IEngineHook::AllowPlayerDamage(ClientId client, ClientId clientTarget)

if (clientTarget)
{
auto time = TimeUtils::UnixTime<std::chrono::milliseconds>();

// anti-dockkill check
if (ClientInfo[clientTarget].spawnProtected)
if (auto& targetData = clientTarget.GetData(); targetData.spawnProtected)
{
if (TimeUtils::UnixMilliseconds() - ClientInfo[clientTarget].tmSpawnTime <= config->general.antiDockKill)
if (time - targetData.spawnTime <= config->general.antiDockKill)
{
return false; // target is protected
}
ClientInfo[clientTarget].spawnProtected = false;

targetData.spawnProtected = false;
}
if (ClientInfo::At(client).spawnProtected)

if (auto& clientData = client.GetData(); clientData.spawnProtected)
{
if (TimeUtils::UnixMilliseconds() - ClientInfo::At(client).tmSpawnTime <= config->general.antiDockKill)
if (time - clientData.spawnTime <= config->general.antiDockKill)
{
return false; // target may not shoot
}
ClientInfo::At(client).spawnProtected = false;

clientData.spawnProtected = false;
}

// no-pvp check
uint systemId;
pub::Player::GetSystem(client, systemId);
pub::Player::GetSystem(client.GetValue(), systemId);
if (std::ranges::find(config->general.noPVPSystemsHashed, systemId) != config->general.noPVPSystemsHashed.end())
{
return false;
Expand All @@ -264,12 +273,11 @@ void __stdcall IEngineHook::NonGunWeaponHitsBaseBefore(const char* ecx, [[maybe_
{
CSimple* simple;
memcpy(&simple, ecx + 0x10, 4);
g_LastHitPts = simple->get_hit_pts();

g_NonGunHitsBase = true;
FLHook::lastHitPts = simple->get_hit_pts();
FLHook::nonGunHitsBase = true;
}

void IEngineHook::NonGunWeaponHitsBaseAfter() { g_NonGunHitsBase = false; }
void IEngineHook::NonGunWeaponHitsBaseAfter() { FLHook::nonGunHitsBase = false; }

__declspec(naked) void IEngineHook::NakedNonGunWeaponHitsBase()
{
Expand Down
6 changes: 3 additions & 3 deletions source/Hooks/HkIEngineDeath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void __stdcall IEngineHook::ShipDestroyed(DamageList* dmgList, DWORD* ecx, uint
TryHook
{
auto cship = (CShip*)ecx[4];
ClientId client = ClientId(cship->GetOwnerPlayer());
auto client = ClientId(cship->GetOwnerPlayer());

CallPlugins(&Plugin::OnShipDestroyed, client, dmgList, cship);

Expand Down Expand Up @@ -278,12 +278,12 @@ __declspec(naked) void IEngineHook::NakedShipDestroyed()
}
}

void IEngineHook::BaseDestroyed(uint objectId, ClientId clientBy)
void IEngineHook::BaseDestroyed(ObjectId objectId, ClientId clientBy)
{
CallPlugins(&Plugin::OnBaseDestroyed, clientBy, objectId);

uint baseId;
pub::SpaceObj::GetDockingTarget(objectId, baseId);
pub::SpaceObj::GetDockingTarget(objectId.GetValue(), baseId);
Universe::IBase* base = Universe::get_base(baseId);

auto baseName = "";
Expand Down

0 comments on commit 2736e59

Please sign in to comment.