2019-05-30 19:24:47 +00:00
|
|
|
#include "common.h"
|
|
|
|
#include "patcher.h"
|
|
|
|
#include "SpecialFX.h"
|
2020-04-07 10:33:14 +00:00
|
|
|
#include "RenderBuffer.h"
|
2019-10-10 16:17:35 +00:00
|
|
|
#include "Timer.h"
|
|
|
|
#include "Sprite.h"
|
|
|
|
#include "Font.h"
|
|
|
|
#include "Text.h"
|
2019-10-16 23:22:39 +00:00
|
|
|
#include "TxdStore.h"
|
|
|
|
#include "FileMgr.h"
|
|
|
|
#include "FileLoader.h"
|
|
|
|
#include "Lights.h"
|
|
|
|
#include "VisibilityPlugins.h"
|
|
|
|
#include "World.h"
|
2020-02-16 20:08:54 +00:00
|
|
|
#include "Particle.h"
|
2020-04-07 10:33:14 +00:00
|
|
|
#include "Shadows.h"
|
2020-02-16 20:08:54 +00:00
|
|
|
#include "General.h"
|
|
|
|
#include "Camera.h"
|
2020-03-21 17:14:29 +00:00
|
|
|
#include "Shadows.h"
|
|
|
|
#include "main.h"
|
2019-05-30 19:24:47 +00:00
|
|
|
|
|
|
|
WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); }
|
2019-10-18 22:23:40 +00:00
|
|
|
WRAPPER void CSpecialFX::Update(void) { EAXJMP(0x518D40); }
|
2020-03-22 14:23:40 +00:00
|
|
|
WRAPPER void CSpecialFX::Init(void) { EAXJMP(0x5189E0); }
|
2020-03-28 20:55:23 +00:00
|
|
|
WRAPPER void CSpecialFX::Shutdown(void) { EAXJMP(0x518BE0); }
|
2019-06-30 19:06:55 +00:00
|
|
|
|
|
|
|
WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { EAXJMP(0x519460); }
|
2019-06-30 20:55:48 +00:00
|
|
|
|
|
|
|
|
2020-03-22 10:20:36 +00:00
|
|
|
CBulletTrace (&CBulletTraces::aTraces)[NUMBULLETTRACES] = *(CBulletTrace(*)[NUMBULLETTRACES])*(uintptr*)0x72B1B8;
|
2020-04-07 10:33:14 +00:00
|
|
|
RxObjSpace3DVertex (&TraceVertices)[6] = *(RxObjSpace3DVertex(*)[6])*(uintptr*)0x649884;
|
2020-03-21 17:14:29 +00:00
|
|
|
RwImVertexIndex (&TraceIndexList)[12] = *(RwImVertexIndex(*)[12])*(uintptr*)0x64986C;
|
2019-06-30 20:55:48 +00:00
|
|
|
|
2020-03-21 17:14:29 +00:00
|
|
|
void CBulletTraces::Init(void)
|
|
|
|
{
|
2020-03-22 10:20:36 +00:00
|
|
|
for (int i = 0; i < NUMBULLETTRACES; i++)
|
2020-03-21 17:14:29 +00:00
|
|
|
aTraces[i].m_bInUse = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBulletTraces::AddTrace(CVector* vecStart, CVector* vecTarget)
|
|
|
|
{
|
|
|
|
int index;
|
2020-03-22 10:20:36 +00:00
|
|
|
for (index = 0; index < NUMBULLETTRACES; index++) {
|
2020-03-21 17:14:29 +00:00
|
|
|
if (!aTraces[index].m_bInUse)
|
|
|
|
break;
|
|
|
|
}
|
2020-03-22 10:20:36 +00:00
|
|
|
if (index == NUMBULLETTRACES)
|
2020-03-21 17:14:29 +00:00
|
|
|
return;
|
|
|
|
aTraces[index].m_vecCurrentPos = *vecStart;
|
|
|
|
aTraces[index].m_vecTargetPos = *vecTarget;
|
|
|
|
aTraces[index].m_bInUse = true;
|
|
|
|
aTraces[index].m_framesInUse = 0;
|
|
|
|
aTraces[index].m_lifeTime = 25 + CGeneral::GetRandomNumber() % 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBulletTraces::Render(void)
|
|
|
|
{
|
2020-03-22 10:20:36 +00:00
|
|
|
for (int i = 0; i < NUMBULLETTRACES; i++) {
|
2020-03-21 17:14:29 +00:00
|
|
|
if (!aTraces[i].m_bInUse)
|
|
|
|
continue;
|
|
|
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0);
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2);
|
|
|
|
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpShadowExplosionTex->raster);
|
|
|
|
CVector inf = aTraces[i].m_vecCurrentPos;
|
|
|
|
CVector sup = aTraces[i].m_vecTargetPos;
|
|
|
|
CVector center = (inf + sup) / 2;
|
2020-03-22 10:20:36 +00:00
|
|
|
CVector width = CrossProduct(TheCamera.GetForward(), (sup - inf));
|
|
|
|
width.Normalise();
|
|
|
|
width /= 20;
|
2020-03-21 17:14:29 +00:00
|
|
|
uint8 intensity = aTraces[i].m_lifeTime;
|
2020-03-22 10:20:36 +00:00
|
|
|
for (int i = 0; i < ARRAY_SIZE(TraceVertices); i++)
|
|
|
|
RwIm3DVertexSetRGBA(&TraceVertices[i], intensity, intensity, intensity, 0xFF);
|
|
|
|
RwIm3DVertexSetPos(&TraceVertices[0], inf.x + width.x, inf.y + width.y, inf.z + width.z);
|
|
|
|
RwIm3DVertexSetPos(&TraceVertices[1], inf.x - width.x, inf.y - width.y, inf.z - width.z);
|
|
|
|
RwIm3DVertexSetPos(&TraceVertices[2], center.x + width.x, center.y + width.y, center.z + width.z);
|
|
|
|
RwIm3DVertexSetPos(&TraceVertices[3], center.x - width.x, center.y - width.y, center.z - width.z);
|
|
|
|
RwIm3DVertexSetPos(&TraceVertices[4], sup.x + width.x, sup.y + width.y, sup.z + width.z);
|
|
|
|
RwIm3DVertexSetPos(&TraceVertices[5], sup.x - width.x, sup.y - width.y, sup.z - width.z);
|
2020-03-21 17:14:29 +00:00
|
|
|
LittleTest();
|
|
|
|
if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, 1)) {
|
|
|
|
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList));
|
|
|
|
RwIm3DEnd();
|
|
|
|
}
|
|
|
|
}
|
2020-04-07 10:33:14 +00:00
|
|
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
|
2020-03-21 17:14:29 +00:00
|
|
|
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBulletTraces::Update(void)
|
|
|
|
{
|
2020-03-22 10:20:36 +00:00
|
|
|
for (int i = 0; i < NUMBULLETTRACES; i++) {
|
2020-03-21 17:14:29 +00:00
|
|
|
if (aTraces[i].m_bInUse)
|
|
|
|
aTraces[i].Update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBulletTrace::Update(void)
|
|
|
|
{
|
|
|
|
if (m_framesInUse == 0) {
|
|
|
|
m_framesInUse++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_framesInUse > 60) {
|
|
|
|
m_bInUse = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CVector diff = m_vecCurrentPos - m_vecTargetPos;
|
|
|
|
float remaining = diff.Magnitude();
|
|
|
|
if (remaining > 0.8f)
|
|
|
|
m_vecCurrentPos = m_vecTargetPos + (remaining - 0.8f) / remaining * diff;
|
|
|
|
else
|
|
|
|
m_bInUse = false;
|
|
|
|
if (--m_lifeTime == 0)
|
|
|
|
m_bInUse = false;
|
|
|
|
m_framesInUse++;
|
|
|
|
}
|
2019-07-24 16:55:43 +00:00
|
|
|
|
2019-07-28 11:14:08 +00:00
|
|
|
WRAPPER void CBrightLights::RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1, uint8 unk2, uint8 unk3) { EAXJMP(0x51A410); }
|
2019-07-24 16:55:43 +00:00
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
RpAtomic *
|
|
|
|
MarkerAtomicCB(RpAtomic *atomic, void *data)
|
|
|
|
{
|
|
|
|
*(RpAtomic**)data = atomic;
|
|
|
|
return atomic;
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
bool
|
|
|
|
C3dMarker::AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
|
|
|
|
{
|
|
|
|
m_nIdentifier = identifier;
|
|
|
|
|
|
|
|
m_Matrix.SetUnity();
|
|
|
|
|
|
|
|
RpAtomic *origAtomic;
|
|
|
|
origAtomic = nil;
|
|
|
|
RpClumpForAllAtomics(C3dMarkers::m_pRpClumpArray[type], MarkerAtomicCB, &origAtomic);
|
|
|
|
|
|
|
|
RpAtomic *atomic = RpAtomicClone(origAtomic);
|
|
|
|
RwFrame *frame = RwFrameCreate();
|
|
|
|
RpAtomicSetFrame(atomic, frame);
|
|
|
|
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
|
|
|
|
|
|
|
RpGeometry *geometry = RpAtomicGetGeometry(atomic);
|
|
|
|
RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
|
|
|
|
|
|
|
|
m_pAtomic = atomic;
|
|
|
|
m_Matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));
|
|
|
|
m_pMaterial = RpGeometryGetMaterial(geometry, 0);
|
|
|
|
m_fSize = fSize;
|
|
|
|
m_fStdSize = m_fSize;
|
|
|
|
m_Color.red = r;
|
|
|
|
m_Color.green = g;
|
|
|
|
m_Color.blue = b;
|
|
|
|
m_Color.alpha = a;
|
|
|
|
m_nPulsePeriod = pulsePeriod;
|
|
|
|
m_fPulseFraction = pulseFraction;
|
|
|
|
m_nRotateRate = rotateRate;
|
|
|
|
m_nStartTime = CTimer::GetTimeInMilliseconds();
|
|
|
|
m_nType = type;
|
|
|
|
return m_pAtomic != nil;
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
C3dMarker::DeleteMarkerObject()
|
|
|
|
{
|
|
|
|
RwFrame *frame;
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
m_nIdentifier = 0;
|
|
|
|
m_nStartTime = 0;
|
|
|
|
m_bIsUsed = false;
|
|
|
|
m_nType = MARKERTYPE_INVALID;
|
|
|
|
|
|
|
|
frame = RpAtomicGetFrame(m_pAtomic);
|
|
|
|
RpAtomicDestroy(m_pAtomic);
|
|
|
|
RwFrameDestroy(frame);
|
2019-10-16 23:22:39 +00:00
|
|
|
m_pAtomic = nil;
|
|
|
|
}
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
void
|
|
|
|
C3dMarker::Render()
|
|
|
|
{
|
|
|
|
if (m_pAtomic == nil) return;
|
|
|
|
|
|
|
|
RwRGBA *color = RpMaterialGetColor(m_pMaterial);
|
|
|
|
*color = m_Color;
|
|
|
|
|
|
|
|
m_Matrix.UpdateRW();
|
|
|
|
|
|
|
|
CMatrix matrix;
|
|
|
|
matrix.Attach(m_Matrix.m_attachment);
|
|
|
|
matrix.Scale(m_fSize);
|
|
|
|
matrix.UpdateRW();
|
|
|
|
|
|
|
|
RwFrameUpdateObjects(RpAtomicGetFrame(m_pAtomic));
|
|
|
|
SetBrightMarkerColours(m_fBrightness);
|
|
|
|
if (m_nType != MARKERTYPE_ARROW)
|
|
|
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
|
|
|
|
RpAtomicRender(m_pAtomic);
|
|
|
|
if (m_nType != MARKERTYPE_ARROW)
|
|
|
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
|
|
|
ReSetAmbientAndDirectionalColours();
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
C3dMarker(&C3dMarkers::m_aMarkerArray)[NUM3DMARKERS] = *(C3dMarker(*)[NUM3DMARKERS])*(uintptr*)0x72D408;
|
|
|
|
int32 &C3dMarkers::NumActiveMarkers = *(int32*)0x8F2A08;
|
|
|
|
RpClump* (&C3dMarkers::m_pRpClumpArray)[NUMMARKERTYPES] = *(RpClump*(*)[NUMMARKERTYPES])*(uintptr*)0x8E2888;
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
void
|
|
|
|
C3dMarkers::Init()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < NUM3DMARKERS; i++) {
|
|
|
|
m_aMarkerArray[i].m_pAtomic = nil;
|
|
|
|
m_aMarkerArray[i].m_nType = MARKERTYPE_INVALID;
|
|
|
|
m_aMarkerArray[i].m_bIsUsed = false;
|
|
|
|
m_aMarkerArray[i].m_nIdentifier = 0;
|
|
|
|
m_aMarkerArray[i].m_Color.red = 255;
|
|
|
|
m_aMarkerArray[i].m_Color.green = 255;
|
|
|
|
m_aMarkerArray[i].m_Color.blue = 255;
|
|
|
|
m_aMarkerArray[i].m_Color.alpha = 255;
|
|
|
|
m_aMarkerArray[i].m_nPulsePeriod = 1024;
|
|
|
|
m_aMarkerArray[i].m_nRotateRate = 5;
|
|
|
|
m_aMarkerArray[i].m_nStartTime = 0;
|
|
|
|
m_aMarkerArray[i].m_fPulseFraction = 0.25f;
|
|
|
|
m_aMarkerArray[i].m_fStdSize = 1.0f;
|
|
|
|
m_aMarkerArray[i].m_fSize = 1.0f;
|
|
|
|
m_aMarkerArray[i].m_fBrightness = 1.0f;
|
|
|
|
m_aMarkerArray[i].m_fCameraRange = 0.0f;
|
|
|
|
}
|
|
|
|
NumActiveMarkers = 0;
|
|
|
|
int txdSlot = CTxdStore::FindTxdSlot("particle");
|
|
|
|
CTxdStore::PushCurrentTxd();
|
|
|
|
CTxdStore::SetCurrentTxd(txdSlot);
|
|
|
|
CFileMgr::ChangeDir("\\");
|
|
|
|
m_pRpClumpArray[MARKERTYPE_ARROW] = CFileLoader::LoadAtomicFile2Return("models/generic/arrow.dff");
|
|
|
|
m_pRpClumpArray[MARKERTYPE_CYLINDER] = CFileLoader::LoadAtomicFile2Return("models/generic/zonecylb.dff");
|
|
|
|
CTxdStore::PopCurrentTxd();
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
void
|
|
|
|
C3dMarkers::Shutdown()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < NUM3DMARKERS; i++) {
|
|
|
|
if (m_aMarkerArray[i].m_pAtomic != nil)
|
|
|
|
m_aMarkerArray[i].DeleteMarkerObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < NUMMARKERTYPES; i++) {
|
|
|
|
if (m_pRpClumpArray[i] != nil)
|
|
|
|
RpClumpDestroy(m_pRpClumpArray[i]);
|
|
|
|
}
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
2019-10-10 16:17:35 +00:00
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
void
|
|
|
|
C3dMarkers::Render()
|
|
|
|
{
|
|
|
|
NumActiveMarkers = 0;
|
|
|
|
ActivateDirectional();
|
|
|
|
for (int i = 0; i < NUM3DMARKERS; i++) {
|
|
|
|
if (m_aMarkerArray[i].m_bIsUsed) {
|
|
|
|
if (m_aMarkerArray[i].m_fCameraRange < 120.0f)
|
|
|
|
m_aMarkerArray[i].Render();
|
|
|
|
NumActiveMarkers++;
|
|
|
|
m_aMarkerArray[i].m_bIsUsed = false;
|
|
|
|
} else if (m_aMarkerArray[i].m_pAtomic != nil) {
|
|
|
|
m_aMarkerArray[i].DeleteMarkerObject();
|
|
|
|
}
|
|
|
|
}
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
2019-10-10 16:17:35 +00:00
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
C3dMarker *
|
2019-10-16 23:22:39 +00:00
|
|
|
C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
|
|
|
|
{
|
2020-02-25 19:01:56 +00:00
|
|
|
C3dMarker *pMarker;
|
|
|
|
|
|
|
|
pMarker = nil;
|
|
|
|
float dist = Sqrt((pos.x - FindPlayerCentreOfWorld(0).x) * (pos.x - FindPlayerCentreOfWorld(0).x) + (pos.y - FindPlayerCentreOfWorld(0).y) * (pos.y - FindPlayerCentreOfWorld(0).y));
|
|
|
|
|
|
|
|
if (type != MARKERTYPE_ARROW && type != MARKERTYPE_CYLINDER) return nil;
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM3DMARKERS; i++) {
|
|
|
|
if (!m_aMarkerArray[i].m_bIsUsed && m_aMarkerArray[i].m_nIdentifier == identifier) {
|
|
|
|
pMarker = &m_aMarkerArray[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMarker == nil) {
|
|
|
|
for (int i = 0; i < NUM3DMARKERS; i++) {
|
|
|
|
if (m_aMarkerArray[i].m_nType == MARKERTYPE_INVALID) {
|
|
|
|
pMarker = &m_aMarkerArray[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMarker == nil && type == MARKERTYPE_ARROW) {
|
|
|
|
for (int i = 0; i < NUM3DMARKERS; i++) {
|
|
|
|
if (dist < m_aMarkerArray[i].m_fCameraRange && m_aMarkerArray[i].m_nType == MARKERTYPE_ARROW && (pMarker == nil || m_aMarkerArray[i].m_fCameraRange > pMarker->m_fCameraRange)) {
|
|
|
|
pMarker = &m_aMarkerArray[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMarker != nil)
|
|
|
|
pMarker->m_nType = MARKERTYPE_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMarker == nil) return pMarker;
|
|
|
|
|
|
|
|
pMarker->m_fCameraRange = dist;
|
|
|
|
if (pMarker->m_nIdentifier == identifier && pMarker->m_nType == type) {
|
|
|
|
if (type == MARKERTYPE_ARROW) {
|
|
|
|
if (dist < 25.0f) {
|
|
|
|
if (dist > 5.0f)
|
|
|
|
pMarker->m_fStdSize = size - (25.0f - dist) * (0.3f * size) / 20.0f;
|
|
|
|
else
|
|
|
|
pMarker->m_fStdSize = size - 0.3f * size;
|
|
|
|
} else {
|
|
|
|
pMarker->m_fStdSize = size;
|
|
|
|
}
|
|
|
|
} else if (type == MARKERTYPE_CYLINDER) {
|
|
|
|
if (dist < size + 12.0f) {
|
|
|
|
if (dist > size + 1.0f)
|
|
|
|
pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a;
|
|
|
|
else
|
|
|
|
pMarker->m_Color.alpha = (float)a * 0.3f;
|
|
|
|
} else {
|
|
|
|
pMarker->m_Color.alpha = a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
float someSin = Sin(TWOPI * (float)((pMarker->m_nPulsePeriod - 1) & (CTimer::GetTimeInMilliseconds() - pMarker->m_nStartTime)) / (float)pMarker->m_nPulsePeriod);
|
|
|
|
pMarker->m_fSize = pMarker->m_fStdSize - pulseFraction * pMarker->m_fStdSize * someSin;
|
|
|
|
|
|
|
|
if (type == MARKERTYPE_ARROW) {
|
|
|
|
pos.z += 0.25f * pMarker->m_fStdSize * someSin;
|
|
|
|
} else if (type == MARKERTYPE_0) {
|
|
|
|
if (someSin > 0.0f)
|
|
|
|
pMarker->m_Color.alpha = (float)a * 0.7f * someSin + a;
|
|
|
|
else
|
|
|
|
pMarker->m_Color.alpha = (float)a * 0.4f * someSin + a;
|
|
|
|
}
|
|
|
|
if (pMarker->m_nRotateRate) {
|
|
|
|
RwV3d pos = pMarker->m_Matrix.m_matrix.pos;
|
|
|
|
pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep()));
|
|
|
|
pMarker->m_Matrix.GetPosition() = pos;
|
|
|
|
}
|
|
|
|
if (type == MARKERTYPE_ARROW)
|
|
|
|
pMarker->m_Matrix.GetPosition() = pos;
|
|
|
|
pMarker->m_bIsUsed = true;
|
|
|
|
return pMarker;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMarker->m_nIdentifier != 0)
|
|
|
|
pMarker->DeleteMarkerObject();
|
|
|
|
|
|
|
|
pMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate);
|
|
|
|
if (type == MARKERTYPE_CYLINDER || type == MARKERTYPE_0 || type == MARKERTYPE_2) {
|
|
|
|
float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);
|
|
|
|
if (z != 0.0f)
|
|
|
|
pos.z = z - 0.05f * size;
|
|
|
|
}
|
|
|
|
pMarker->m_Matrix.SetTranslate(pos.x, pos.y, pos.z);
|
|
|
|
if (type == MARKERTYPE_2) {
|
|
|
|
pMarker->m_Matrix.RotateX(PI);
|
|
|
|
pMarker->m_Matrix.GetPosition() = pos;
|
|
|
|
}
|
|
|
|
pMarker->m_Matrix.UpdateRW();
|
|
|
|
if (type == MARKERTYPE_ARROW) {
|
|
|
|
if (dist < 25.0f) {
|
|
|
|
if (dist > 5.0f)
|
|
|
|
pMarker->m_fStdSize = size - (25.0f - dist) * (0.3f * size) / 20.0f;
|
|
|
|
else
|
|
|
|
pMarker->m_fStdSize = size - 0.3f * size;
|
|
|
|
} else {
|
|
|
|
pMarker->m_fStdSize = size;
|
|
|
|
}
|
|
|
|
} else if (type == MARKERTYPE_CYLINDER) {
|
|
|
|
if (dist < size + 12.0f) {
|
|
|
|
if (dist > size + 1.0f)
|
|
|
|
pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a;
|
|
|
|
else
|
|
|
|
pMarker->m_Color.alpha = (float)a * 0.3f;
|
|
|
|
} else {
|
|
|
|
pMarker->m_Color.alpha = a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pMarker->m_bIsUsed = true;
|
2019-10-16 23:22:39 +00:00
|
|
|
return pMarker;
|
|
|
|
}
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
void
|
|
|
|
C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)
|
|
|
|
{
|
|
|
|
PlaceMarker(id, type, pos, size, r, g, b, a, pulsePeriod, pulseFraction, 1);
|
|
|
|
PlaceMarker(id, type, pos, size * 0.93f, r, g, b, a, pulsePeriod, pulseFraction, 2);
|
|
|
|
PlaceMarker(id, type, pos, size * 0.86f, r, g, b, a, pulsePeriod, pulseFraction, -1);
|
2019-10-16 23:22:39 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
|
2019-10-16 23:22:39 +00:00
|
|
|
void
|
|
|
|
C3dMarkers::Update()
|
|
|
|
{
|
|
|
|
}
|
2019-10-10 16:17:35 +00:00
|
|
|
|
2020-04-07 10:33:14 +00:00
|
|
|
|
|
|
|
int CShinyTexts::NumShinyTexts;
|
|
|
|
CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS];
|
|
|
|
|
|
|
|
void
|
|
|
|
CShinyTexts::Init(void)
|
|
|
|
{
|
|
|
|
NumShinyTexts = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
|
|
|
|
float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
|
|
|
|
uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist)
|
|
|
|
{
|
|
|
|
if(NumShinyTexts >= NUMSHINYTEXTS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
aShinyTexts[NumShinyTexts].m_camDist = (p0 - TheCamera.GetPosition()).Magnitude();
|
|
|
|
if(aShinyTexts[NumShinyTexts].m_camDist > maxDist)
|
|
|
|
return;
|
|
|
|
aShinyTexts[NumShinyTexts].m_verts[0] = p0;
|
|
|
|
aShinyTexts[NumShinyTexts].m_verts[1] = p1;
|
|
|
|
aShinyTexts[NumShinyTexts].m_verts[2] = p2;
|
|
|
|
aShinyTexts[NumShinyTexts].m_verts[3] = p3;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[0].x = u0;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[0].y = v0;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[1].x = u1;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[1].y = v1;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[2].x = u2;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[2].y = v2;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[3].x = u3;
|
|
|
|
aShinyTexts[NumShinyTexts].m_texCoords[3].y = v3;
|
|
|
|
aShinyTexts[NumShinyTexts].m_type = type;
|
|
|
|
aShinyTexts[NumShinyTexts].m_red = red;
|
|
|
|
aShinyTexts[NumShinyTexts].m_green = green;
|
|
|
|
aShinyTexts[NumShinyTexts].m_blue = blue;
|
|
|
|
// Fade out at half the max dist
|
|
|
|
float halfDist = maxDist*0.5f;
|
|
|
|
if(aShinyTexts[NumShinyTexts].m_camDist > halfDist){
|
|
|
|
float f = 1.0f - (aShinyTexts[NumShinyTexts].m_camDist - halfDist)/halfDist;
|
|
|
|
aShinyTexts[NumShinyTexts].m_red *= f;
|
|
|
|
aShinyTexts[NumShinyTexts].m_green *= f;
|
|
|
|
aShinyTexts[NumShinyTexts].m_blue *= f;
|
|
|
|
}
|
|
|
|
|
|
|
|
NumShinyTexts++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CShinyTexts::Render(void)
|
|
|
|
{
|
|
|
|
int i, ix, v;
|
|
|
|
RwTexture *lastTex = nil;
|
|
|
|
|
|
|
|
if(NumShinyTexts == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
|
|
|
|
|
|
|
TempBufferVerticesStored = 0;
|
|
|
|
TempBufferIndicesStored = 0;
|
|
|
|
|
|
|
|
for(i = 0; i < NumShinyTexts; i++){
|
|
|
|
if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-64 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-62)
|
|
|
|
RenderOutGeometryBuffer();
|
|
|
|
|
|
|
|
uint8 r = aShinyTexts[i].m_red;
|
|
|
|
uint8 g = aShinyTexts[i].m_green;
|
|
|
|
uint8 b = aShinyTexts[i].m_blue;
|
|
|
|
|
|
|
|
switch(aShinyTexts[i].m_type){
|
|
|
|
case SHINYTEXT_WALK:
|
|
|
|
if(lastTex != gpWalkDontTex){
|
|
|
|
RenderOutGeometryBuffer();
|
|
|
|
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpWalkDontTex));
|
|
|
|
lastTex = gpWalkDontTex;
|
|
|
|
}
|
|
|
|
quad:
|
|
|
|
v = TempBufferVerticesStored;
|
|
|
|
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], r, g, b, 255);
|
|
|
|
RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_verts[0].x, aShinyTexts[i].m_verts[0].y, aShinyTexts[i].m_verts[0].z);
|
|
|
|
RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].x);
|
|
|
|
RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].y);
|
|
|
|
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], r, g, b, 255);
|
|
|
|
RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_verts[1].x, aShinyTexts[i].m_verts[1].y, aShinyTexts[i].m_verts[1].z);
|
|
|
|
RwIm3DVertexSetU(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].x);
|
|
|
|
RwIm3DVertexSetV(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].y);
|
|
|
|
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], r, g, b, 255);
|
|
|
|
RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_verts[2].x, aShinyTexts[i].m_verts[2].y, aShinyTexts[i].m_verts[2].z);
|
|
|
|
RwIm3DVertexSetU(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].x);
|
|
|
|
RwIm3DVertexSetV(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].y);
|
|
|
|
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], r, g, b, 255);
|
|
|
|
RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_verts[3].x, aShinyTexts[i].m_verts[3].y, aShinyTexts[i].m_verts[3].z);
|
|
|
|
RwIm3DVertexSetU(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].x);
|
|
|
|
RwIm3DVertexSetV(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].y);
|
|
|
|
ix = TempBufferIndicesStored;
|
|
|
|
TempBufferRenderIndexList[ix+0] = 0 + TempBufferVerticesStored;
|
|
|
|
TempBufferRenderIndexList[ix+1] = 1 + TempBufferVerticesStored;
|
|
|
|
TempBufferRenderIndexList[ix+2] = 2 + TempBufferVerticesStored;
|
|
|
|
TempBufferRenderIndexList[ix+3] = 2 + TempBufferVerticesStored;
|
|
|
|
TempBufferRenderIndexList[ix+4] = 1 + TempBufferVerticesStored;
|
|
|
|
TempBufferRenderIndexList[ix+5] = 3 + TempBufferVerticesStored;
|
|
|
|
TempBufferVerticesStored += 4;
|
|
|
|
TempBufferIndicesStored += 6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SHINYTEXT_FLAT:
|
|
|
|
if(lastTex != nil){
|
|
|
|
RenderOutGeometryBuffer();
|
|
|
|
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
|
|
|
|
lastTex = nil;
|
|
|
|
}
|
|
|
|
goto quad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderOutGeometryBuffer();
|
|
|
|
NumShinyTexts = 0;
|
|
|
|
|
|
|
|
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CShinyTexts::RenderOutGeometryBuffer(void)
|
|
|
|
{
|
|
|
|
if(TempBufferIndicesStored != 0){
|
|
|
|
LittleTest();
|
|
|
|
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
|
|
|
|
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
|
|
|
|
RwIm3DEnd();
|
|
|
|
}
|
|
|
|
TempBufferVerticesStored = 0;
|
|
|
|
TempBufferIndicesStored = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-10 16:17:35 +00:00
|
|
|
#define MONEY_MESSAGE_LIFETIME_MS 2000
|
|
|
|
|
2020-02-25 19:01:56 +00:00
|
|
|
CMoneyMessage CMoneyMessages::aMoneyMessages[NUMMONEYMESSAGES];
|
|
|
|
|
|
|
|
void
|
|
|
|
CMoneyMessage::Render()
|
|
|
|
{
|
|
|
|
const float MAX_SCALE = 4.0f;
|
|
|
|
uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered;
|
|
|
|
if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) m_nTimeRegistered = 0;
|
|
|
|
else {
|
|
|
|
float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS;
|
|
|
|
RwV3d vecOut;
|
|
|
|
float fDistX, fDistY;
|
|
|
|
if (CSprite::CalcScreenCoors(m_vecPosition + CVector(0.0f, 0.0f, fLifeTime), &vecOut, &fDistX, &fDistY, true)) {
|
|
|
|
fDistX *= (0.7 * fLifeTime + 2.0) * m_fSize;
|
|
|
|
fDistY *= (0.7 * fLifeTime + 2.0) * m_fSize;
|
|
|
|
CFont::SetPropOn();
|
|
|
|
CFont::SetBackgroundOff();
|
|
|
|
|
|
|
|
float fScaleY = fDistY / 100.0f;
|
|
|
|
if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
|
|
|
|
|
|
|
|
float fScaleX = fDistX / 100.0f;
|
|
|
|
if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
|
|
|
|
|
|
|
|
CFont::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here?
|
|
|
|
CFont::SetCentreOn();
|
|
|
|
CFont::SetCentreSize(SCREEN_WIDTH);
|
|
|
|
CFont::SetJustifyOff();
|
|
|
|
CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity));
|
|
|
|
CFont::SetBackGroundOnlyTextOff();
|
|
|
|
CFont::SetFontStyle(FONT_BANK);
|
|
|
|
CFont::PrintString(vecOut.x, vecOut.y, m_aText);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMoneyMessages::Init()
|
|
|
|
{
|
|
|
|
for (int32 i = 0; i < NUMMONEYMESSAGES; i++)
|
|
|
|
aMoneyMessages[i].m_nTimeRegistered = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMoneyMessages::Render()
|
|
|
|
{
|
|
|
|
for (int32 i = 0; i < NUMMONEYMESSAGES; i++) {
|
|
|
|
if (aMoneyMessages[i].m_nTimeRegistered != 0)
|
|
|
|
aMoneyMessages[i].Render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMoneyMessages::RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity)
|
|
|
|
{
|
|
|
|
uint32 nIndex = 0;
|
|
|
|
while (aMoneyMessages[nIndex].m_nTimeRegistered != 0) {
|
|
|
|
if (++nIndex >= NUMMONEYMESSAGES) return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add data of this money message to the array
|
|
|
|
AsciiToUnicode(pText, aMoneyMessages[nIndex].m_aText);
|
|
|
|
|
|
|
|
aMoneyMessages[nIndex].m_nTimeRegistered = CTimer::GetTimeInMilliseconds();
|
|
|
|
aMoneyMessages[nIndex].m_vecPosition = vecPos;
|
|
|
|
aMoneyMessages[nIndex].m_Colour.red = bRed;
|
|
|
|
aMoneyMessages[nIndex].m_Colour.green = bGreen;
|
|
|
|
aMoneyMessages[nIndex].m_Colour.blue = bBlue;
|
|
|
|
aMoneyMessages[nIndex].m_fSize = fSize;
|
|
|
|
aMoneyMessages[nIndex].m_fOpacity = fOpacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
CRGBA FoamColour(255, 255, 255, 255);
|
|
|
|
unsigned int CSpecialParticleStuff::BoatFromStart;
|
|
|
|
|
|
|
|
void
|
|
|
|
CSpecialParticleStuff::CreateFoamAroundObject(CMatrix* pMatrix, float innerFw, float innerRg, float innerUp, int32 particles)
|
|
|
|
{
|
|
|
|
float outerFw = innerFw + 5.0f;
|
|
|
|
float outerRg = innerRg + 5.0f;
|
|
|
|
float outerUp = innerUp + 5.0f;
|
|
|
|
for (int attempts = 0; particles > 0 && attempts < 1000; attempts++) {
|
|
|
|
CVector pos;
|
|
|
|
int rnd = CGeneral::GetRandomNumber();
|
|
|
|
pos.x = (int8)(rnd - 128) * innerFw / 110.0f;
|
|
|
|
pos.y = (int8)((rnd >> 8) - 128) * innerFw / 110.0f;
|
|
|
|
pos.z = 0.0f;
|
|
|
|
if (DotProduct2D(pos, TheCamera.GetForward()) >= 0)
|
|
|
|
continue;
|
|
|
|
// was there any point in adding it here?
|
|
|
|
pos += pMatrix->GetPosition();
|
|
|
|
pos.z = 2.0f;
|
|
|
|
float fw = Abs(DotProduct(pMatrix->GetForward(), pos - pMatrix->GetPosition()));
|
|
|
|
if (fw >= outerFw)
|
|
|
|
continue;
|
|
|
|
float rg = Abs(DotProduct(pMatrix->GetRight(), pos - pMatrix->GetPosition()));
|
|
|
|
if (rg >= outerRg)
|
|
|
|
continue;
|
|
|
|
float up = Abs(DotProduct(pMatrix->GetUp(), pos - pMatrix->GetPosition()));
|
|
|
|
if (up >= outerUp)
|
|
|
|
continue;
|
|
|
|
if (fw > innerFw || rg > innerRg || up > innerUp) {
|
|
|
|
CParticle::AddParticle(PARTICLE_STEAM2, pos, CVector(0.0f, 0.0f, 0.0f), nil, 4.0f, FoamColour, 1, 0, 0, 0);
|
|
|
|
particles--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CSpecialParticleStuff::StartBoatFoamAnimation()
|
|
|
|
{
|
|
|
|
BoatFromStart = CTimer::GetTimeInMilliseconds();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CSpecialParticleStuff::UpdateBoatFoamAnimation(CMatrix* pMatrix)
|
|
|
|
{
|
|
|
|
static int32 FrameInAnimation = 0;
|
|
|
|
static float X, Y, Z, dX, dY, dZ;
|
|
|
|
CreateFoamAroundObject(pMatrix, 107.0f, 24.1f, 30.5f, 2);
|
|
|
|
uint32 prev = CTimer::GetPreviousTimeInMilliseconds();
|
|
|
|
uint32 cur = CTimer::GetTimeInMilliseconds();
|
|
|
|
if (FrameInAnimation != 0) {
|
|
|
|
X += dX;
|
|
|
|
Y += dY;
|
|
|
|
Z += dZ;
|
|
|
|
CVector pos = *pMatrix * CVector(X, Y, Z);
|
|
|
|
CParticle::AddParticle(PARTICLE_STEAM_NY, pos, CVector(0.0f, 0.0f, 0.0f),
|
|
|
|
nil, FrameInAnimation * 0.5f + 2.0f, FoamColour, 1, 0, 0, 0);
|
|
|
|
if (++FrameInAnimation > 15)
|
|
|
|
FrameInAnimation = 0;
|
|
|
|
}
|
|
|
|
if ((cur & 0x3FF) < (prev & 0x3FF)) {
|
|
|
|
FrameInAnimation = 1;
|
|
|
|
int rnd = CGeneral::GetRandomNumber();
|
|
|
|
X = (int8)(rnd - 128) * 0.2f;
|
|
|
|
Y = (int8)((rnd >> 8) - 128) * 0.2f;
|
|
|
|
Z = 10.0f;
|
|
|
|
rnd = CGeneral::GetRandomNumber();
|
|
|
|
dX = (int8)(rnd - 128) * 0.02f;
|
|
|
|
dY = (int8)((rnd >> 8) - 128) * 0.02f;
|
|
|
|
dZ = 2.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:17:35 +00:00
|
|
|
STARTPATCHES
|
2020-03-21 17:14:29 +00:00
|
|
|
InjectHook(0x518DE0, &CBulletTraces::Init, PATCH_JUMP);
|
|
|
|
InjectHook(0x518E90, &CBulletTraces::AddTrace, PATCH_JUMP);
|
|
|
|
InjectHook(0x518F20, &CBulletTraces::Render, PATCH_JUMP);
|
|
|
|
InjectHook(0x519240, &CBulletTraces::Update, PATCH_JUMP);
|
|
|
|
|
2019-10-16 23:22:39 +00:00
|
|
|
InjectHook(0x51B070, &C3dMarker::AddMarker, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B170, &C3dMarker::DeleteMarkerObject, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B1B0, &C3dMarker::Render, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B2B0, C3dMarkers::Init, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B480, C3dMarkers::PlaceMarker, PATCH_JUMP);
|
|
|
|
InjectHook(0x51BB80, C3dMarkers::PlaceMarkerSet, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B400, C3dMarkers::Render, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B3B0, C3dMarkers::Shutdown, PATCH_JUMP);
|
|
|
|
|
2020-04-07 10:33:14 +00:00
|
|
|
InjectHook(0x51A5A0, CShinyTexts::Init, PATCH_JUMP);
|
|
|
|
InjectHook(0x51AAB0, CShinyTexts::RegisterOne, PATCH_JUMP);
|
|
|
|
InjectHook(0x51A5B0, CShinyTexts::Render, PATCH_JUMP);
|
|
|
|
InjectHook(0x51AA50, CShinyTexts::RenderOutGeometryBuffer, PATCH_JUMP);
|
|
|
|
|
2019-10-10 16:17:35 +00:00
|
|
|
InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP);
|
|
|
|
InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP);
|
|
|
|
ENDPATCHES
|