Skip to content

Commit

Permalink
Checkpoints arrow customization (#3550)
Browse files Browse the repository at this point in the history
Add the ability to change the color and alpha of the checkpoint marker target arrow. By default it is red with alpha 255.
  • Loading branch information
FileEX authored Jul 15, 2024
1 parent 1951a5e commit 071378e
Show file tree
Hide file tree
Showing 25 changed files with 272 additions and 1 deletion.
40 changes: 40 additions & 0 deletions Client/game_sa/CCheckpointSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "C3DMarkerSA.h"
#include "C3DMarkersSA.h"
#include "CCheckpointSA.h"
#include "CCheckpointsSA.h"
#include "CGameSA.h"

extern CGameSA* pGame;

void CCheckpointSA::SetPosition(CVector* vecPosition)
{
Expand Down Expand Up @@ -132,3 +136,39 @@ void CCheckpointSA::Remove()
GetInterface()->m_nType = 257;
GetInterface()->rwColour = 0;
}

void CCheckpointSA::SetTargetArrowData(const SColor color, float size) noexcept
{
m_targetArrowColor = color;
m_targetArrowSize = size;
}

static void __cdecl RenderTargetArrow(CCheckpointSAInterface* pCheckpoint)
{
CCheckpoint* checkpoint = pGame->GetCheckpoints()->FindMarker(pCheckpoint->m_nIdentifier);
if (!checkpoint)
return;

CVector* position = checkpoint->GetPosition();
CVector* direction = checkpoint->GetPointDirection();
SColor color = checkpoint->GetTargetArrowColor();

((void(__cdecl*)(float, float, float, float, std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t, float, float, float))C3dMarkers_DirectionArrowSet)(position->fX, position->fY, position->fZ, checkpoint->GetTargetArrowSize(), color.R, color.G, color.B, color.A, -direction->fX, -direction->fY, -direction->fZ);
}

static void _declspec(naked) HOOK_CCheckpoint__Render()
{
_asm {
pushad
push esi
call RenderTargetArrow
add esp, 4
popad
jmp RETURN_CCheckpoint__Render
}
}

void CCheckpointSA::StaticSetHooks()
{
EZHookInstall(CCheckpoint__Render);
}
13 changes: 13 additions & 0 deletions Client/game_sa/CCheckpointSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
#include <CVector.h>
#include <game/CCheckpoint.h>

#define HOOKPOS_CCheckpoint__Render 0x725E56
#define HOOKSIZE_CCheckpoint__Render 0x5
static constexpr std::uint32_t RETURN_CCheckpoint__Render = 0x725E5B;

#define C3dMarkers_DirectionArrowSet 0x721140

class CCheckpointSAInterface
{
public:
Expand All @@ -36,12 +42,16 @@ class CCheckpointSA : public CCheckpoint
{
private:
CCheckpointSAInterface* internalInterface;
SColor m_targetArrowColor{0xFFFF4040};
float m_targetArrowSize{0.625f};

public:
CCheckpointSA(CCheckpointSAInterface* checkpointInterface) { internalInterface = checkpointInterface; };

CCheckpointSAInterface* GetInterface() { return internalInterface; }

static void StaticSetHooks();

void SetPosition(CVector* vecPosition);
CVector* GetPosition();
void SetPointDirection(CVector* vecPointDirection);
Expand All @@ -62,4 +72,7 @@ class CCheckpointSA : public CCheckpoint
void SetPulseFraction(float fPulseFraction); // doesn't work propperly (not virtualed)
float GetPulseFraction();
void Remove();
SColor GetTargetArrowColor() const noexcept override { return m_targetArrowColor; };
float GetTargetArrowSize() const noexcept override { return m_targetArrowSize; };
void SetTargetArrowData(const SColor color, float size) noexcept;
};
11 changes: 11 additions & 0 deletions Client/game_sa/CCheckpointsSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,14 @@ CCheckpoint* CCheckpointsSA::FindFreeMarker()
}
return NULL;
}

CCheckpoint* CCheckpointsSA::FindMarker(DWORD identifier)
{
for (CCheckpointSA* checkpoint : Checkpoints)
{
if (checkpoint->GetIdentifier() == identifier)
return checkpoint;
}

return nullptr;
}
1 change: 1 addition & 0 deletions Client/game_sa/CCheckpointsSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ class CCheckpointsSA : public CCheckpoints
CCheckpoint* CreateCheckpoint(DWORD Identifier, WORD wType, CVector* vecPosition, CVector* vecPointDir, float fSize, float fPulseFraction,
const SharedUtil::SColor color);
CCheckpoint* FindFreeMarker();
CCheckpoint* FindMarker(DWORD identifier);
};
2 changes: 2 additions & 0 deletions Client/game_sa/CGameSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "D3DResourceSystemSA.h"
#include "CIplStoreSA.h"
#include "CBuildingRemovalSA.h"
#include "CCheckpointSA.h"

extern CGameSA* pGame;

Expand Down Expand Up @@ -238,6 +239,7 @@ CGameSA::CGameSA()
CFileLoaderSA::StaticSetHooks();
D3DResourceSystemSA::StaticSetHooks();
CVehicleSA::StaticSetHooks();
CCheckpointSA::StaticSetHooks();
}

CGameSA::~CGameSA()
Expand Down
22 changes: 22 additions & 0 deletions Client/mods/deathmatch/logic/CClientCheckpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ CClientCheckpoint::CClientCheckpoint(CClientMarker* pThis)
m_dwType = CHECKPOINT_EMPTYTUBE;
m_vecDirection.fX = 1.0f;
m_bHasTarget = false;
m_TargetArrowColor = SColorRGBA(255, 64, 64, 255);
m_TargetArrowSize = m_fSize * 0.625f;
}

CClientCheckpoint::~CClientCheckpoint()
Expand Down Expand Up @@ -261,6 +263,8 @@ void CClientCheckpoint::SetSize(float fSize)
{
// Set the new size and recreate
m_fSize = fSize;
m_TargetArrowSize = fSize * 0.625f;

ReCreate();
}
}
Expand Down Expand Up @@ -352,6 +356,7 @@ void CClientCheckpoint::Create(unsigned long ulIdentifier)
{
// Set properties
m_pCheckpoint->SetRotateRate(0);
ApplyCheckpointTargetArrowProperties();
}
}
}
Expand Down Expand Up @@ -385,3 +390,20 @@ void CClientCheckpoint::ReCreateWithSameIdentifier()
Create(m_dwIdentifier);
}
}

void CClientCheckpoint::SetTargetArrowProperties(const SColor& arrowColor, float size) noexcept
{
if (m_TargetArrowColor == arrowColor && m_TargetArrowSize == size)
return;

m_TargetArrowColor = arrowColor;
m_TargetArrowSize = size;

ApplyCheckpointTargetArrowProperties();
}

void CClientCheckpoint::ApplyCheckpointTargetArrowProperties() noexcept
{
if (m_pCheckpoint && m_uiIcon == CClientCheckpoint::ICON_ARROW)
m_pCheckpoint->SetTargetArrowData(m_TargetArrowColor, m_TargetArrowSize);
}
7 changes: 7 additions & 0 deletions Client/mods/deathmatch/logic/CClientCheckpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class CClientCheckpoint : public CClientMarkerCommon
static bool IconToString(unsigned char ucIcon, SString& strOutString);
void ReCreateWithSameIdentifier();

SColor GetTargetArrowColor() const noexcept { return m_TargetArrowColor; };
float GetTargetArrowSize() const noexcept { return m_TargetArrowSize; };
void SetTargetArrowProperties(const SColor& arrowColor, float size) noexcept;

protected:
bool IsStreamedIn() { return m_bStreamedIn; };
void StreamIn();
Expand All @@ -83,6 +87,7 @@ class CClientCheckpoint : public CClientMarkerCommon
void Create(unsigned long ulIdentifier = 0);
void Destroy();
void ReCreate();
void ApplyCheckpointTargetArrowProperties() noexcept;

CClientMarkerPtr m_pThis;
bool m_bStreamedIn;
Expand All @@ -95,6 +100,8 @@ class CClientCheckpoint : public CClientMarkerCommon
float m_fSize;
SColor m_Color;
CCheckpoint* m_pCheckpoint;
SColor m_TargetArrowColor;
float m_TargetArrowSize;

DWORD m_dwIdentifier;
bool m_bHasTarget;
Expand Down
13 changes: 13 additions & 0 deletions Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3654,6 +3654,19 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream)
pCheckpoint->SetNextPosition(position.data.vecPosition);
pCheckpoint->SetIcon(CClientCheckpoint::ICON_ARROW);
}

if (ucType == CClientGame::MARKER_CHECKPOINT && bitStream.Can(eBitStreamVersion::SetMarkerTargetArrowProperties))
{
SColor color;
float size;
bitStream.Read(color.R);
bitStream.Read(color.G);
bitStream.Read(color.B);
bitStream.Read(color.A);
bitStream.Read(size);

pCheckpoint->SetTargetArrowProperties(color, size);
}
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4926,6 +4926,25 @@ bool CStaticFunctionDefinitions::SetMarkerIcon(CClientEntity& Entity, const char
return false;
}

bool CStaticFunctionDefinitions::SetMarkerTargetArrowProperties(CClientEntity& Entity, const SColor color, float size)
{
RUN_CHILDREN(SetMarkerTargetArrowProperties(**iter, color, size))

if (!IS_MARKER(&Entity))
return false;

CClientMarker& marker = static_cast<CClientMarker&>(Entity);
CClientCheckpoint* checkpoint = marker.GetCheckpoint();
if (!checkpoint)
return false;

if (checkpoint->GetIcon() != CClientCheckpoint::ICON_ARROW)
return false;

checkpoint->SetTargetArrowProperties(color, size);
return true;
}

bool CStaticFunctionDefinitions::GetCameraMatrix(CVector& vecPosition, CVector& vecLookAt, float& fRoll, float& fFOV)
{
m_pCamera->GetPosition(vecPosition);
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ class CStaticFunctionDefinitions
static bool SetMarkerColor(CClientEntity& Entity, const SColor color);
static bool SetMarkerTarget(CClientEntity& Entity, const CVector* pTarget);
static bool SetMarkerIcon(CClientEntity& Entity, const char* szIcon);
static bool SetMarkerTargetArrowProperties(CClientEntity& Entity, const SColor color, float size);

// Camera get funcs
static bool GetCameraMatrix(CVector& vecPosition, CVector& vecLookAt, float& fRoll, float& fFOV);
Expand Down
26 changes: 26 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ void CLuaMarkerDefs::LoadFunctions()
{"getMarkerColor", GetMarkerColor},
{"getMarkerTarget", GetMarkerTarget},
{"getMarkerIcon", GetMarkerIcon},
{"getMarkerTargetArrowProperties", ArgumentParser<GetMarkerTargetArrowProperties>},

{"setMarkerType", SetMarkerType},
{"setMarkerSize", SetMarkerSize},
{"setMarkerColor", SetMarkerColor},
{"setMarkerTarget", SetMarkerTarget},
{"setMarkerIcon", SetMarkerIcon},
{"setMarkerTargetArrowProperties", ArgumentParser<SetMarkerTargetArrowProperties>},

{"setCoronaReflectionEnabled", ArgumentParser<SetCoronaReflectionEnabled>},
{"isCoronaReflectionEnabled", ArgumentParser<IsCoronaReflectionEnabled>},
Expand Down Expand Up @@ -417,3 +419,27 @@ bool CLuaMarkerDefs::IsCoronaReflectionEnabled(CClientMarker* pMarker)

return pCorona->IsReflectionEnabled();
}

bool CLuaMarkerDefs::SetMarkerTargetArrowProperties(CClientMarker* marker, std::optional<std::uint8_t> r, std::optional<std::uint8_t> g, std::optional<std::uint8_t> b, std::optional<std::uint8_t> a, std::optional<float> size)
{
SColor color;
color.R = r.value_or(255);
color.G = g.value_or(64);
color.B = b.value_or(64);
color.A = a.value_or(255);

return CStaticFunctionDefinitions::SetMarkerTargetArrowProperties(*marker, color, size.value_or(marker->GetSize() * 0.625f));
}

std::variant<CLuaMultiReturn<std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t, float>, bool> CLuaMarkerDefs::GetMarkerTargetArrowProperties(CClientMarker* marker) noexcept
{
CClientCheckpoint* checkpoint = marker->GetCheckpoint();
if (!checkpoint)
return false;

if (!checkpoint->HasTarget() || marker->GetMarkerType() != CClientMarker::MARKER_CHECKPOINT)
return false;

SColor color = checkpoint->GetTargetArrowColor();
return CLuaMultiReturn<std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t, float>(color.R, color.G, color.B, color.A, checkpoint->GetTargetArrowSize());
}
4 changes: 4 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#pragma once
#include "CLuaDefs.h"
#include "lua/CLuaMultiReturn.h"

class CLuaMarkerDefs : public CLuaDefs
{
Expand All @@ -35,4 +36,7 @@ class CLuaMarkerDefs : public CLuaDefs

static bool SetCoronaReflectionEnabled(CClientMarker* pMarker, bool bEnabled);
static bool IsCoronaReflectionEnabled(CClientMarker* pMarker);

static bool SetMarkerTargetArrowProperties(CClientMarker* marker, std::optional<std::uint8_t> r, std::optional<std::uint8_t> g, std::optional<std::uint8_t> b, std::optional<std::uint8_t> a, std::optional<float> size);
static std::variant<CLuaMultiReturn<std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t, float>, bool> GetMarkerTargetArrowProperties(CClientMarker* marker) noexcept;
};
21 changes: 20 additions & 1 deletion Client/mods/deathmatch/logic/rpc/CMarkerRPCs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ void CMarkerRPCs::LoadFunctions()
AddHandler(SET_MARKER_SIZE, SetMarkerSize, "SetMarkerSize");
AddHandler(SET_MARKER_TARGET, SetMarkerTarget, "SetMarkerTarget");
AddHandler(SET_MARKER_ICON, SetMarkerIcon, "SetMarkerIcon");
AddHandler(SET_MARKER_TARGET_ARROW_PROPERTIES, SetMarkerTargetArrowProperties, "SetMarkerTargetArrowProperties");
}

void CMarkerRPCs::SetMarkerType(CClientEntity* pSource, NetBitStreamInterface& bitStream)
Expand Down Expand Up @@ -137,4 +138,22 @@ void CMarkerRPCs::SetMarkerIcon(CClientEntity* pSource, NetBitStreamInterface& b
}
}
}
}
}

void CMarkerRPCs::SetMarkerTargetArrowProperties(CClientEntity* pSource, NetBitStreamInterface& bitStream)
{
SColor color;
float size;
if (bitStream.Read(color.R) && bitStream.Read(color.G) && bitStream.Read(color.B) && bitStream.Read(color.A) && bitStream.Read(size))
{
CClientMarker* marker = m_pMarkerManager->Get(pSource->GetID());
if (!marker)
return;

CClientCheckpoint* checkpoint = marker->GetCheckpoint();
if (!checkpoint)
return;

checkpoint->SetTargetArrowProperties(color, size);
}
}
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/rpc/CMarkerRPCs.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ class CMarkerRPCs : public CRPCFunctions
DECLARE_ELEMENT_RPC(SetMarkerSize);
DECLARE_ELEMENT_RPC(SetMarkerTarget);
DECLARE_ELEMENT_RPC(SetMarkerIcon);
DECLARE_ELEMENT_RPC(SetMarkerTargetArrowProperties);
};
3 changes: 3 additions & 0 deletions Client/sdk/game/CCheckpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,7 @@ class CCheckpoint
virtual void SetCameraRange(float fCameraRange) = 0;
virtual float GetPulseFraction() = 0;
virtual void Remove() = 0;
virtual SColor GetTargetArrowColor() const noexcept = 0;
virtual float GetTargetArrowSize() const noexcept = 0;
virtual void SetTargetArrowData(const SColor arrowColo, float size) noexcept = 0;
};
1 change: 1 addition & 0 deletions Client/sdk/game/CCheckpoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ class CCheckpoints
virtual CCheckpoint* CreateCheckpoint(DWORD Identifier, WORD wType, CVector* vecPosition, CVector* vecPointDir, float fSize, float fPulseFraction,
const SharedUtil::SColor color) = 0;
virtual CCheckpoint* FindFreeMarker() = 0;
virtual CCheckpoint* FindMarker(DWORD identifier) = 0;
};
Loading

0 comments on commit 071378e

Please sign in to comment.