From 188aab4196c1d9de0c1bf33be1114e7a0e11fd19 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 30 May 2019 21:24:47 +0200 Subject: implemented some higher level functions; added lots of stubs; switched top and bottom in CRect --- src/Camera.cpp | 16 ++ src/Camera.h | 11 +- src/Frontend.cpp | 8 + src/Frontend.h | 85 +++++++ src/Garages.cpp | 42 --- src/Garages.h | 7 - src/Glass.cpp | 15 -- src/Glass.h | 10 - src/MenuManager.cpp | 4 - src/MenuManager.h | 5 - src/Messages.cpp | 5 + src/Messages.h | 7 + src/Pad.cpp | 3 + src/Pad.h | 1 + src/PathFind.cpp | 594 ------------------------------------------- src/PathFind.h | 129 ---------- src/Timecycle.h | 1 - src/User.cpp | 10 + src/User.h | 28 ++ src/Weather.cpp | 3 + src/Weather.h | 2 + src/audio/MusicManager.cpp | 7 + src/audio/MusicManager.h | 8 + src/control/Darkel.cpp | 5 + src/control/Darkel.h | 7 + src/control/Garages.cpp | 44 ++++ src/control/Garages.h | 8 + src/control/PathFind.cpp | 594 +++++++++++++++++++++++++++++++++++++++++++ src/control/PathFind.h | 129 ++++++++++ src/control/Pickups.cpp | 7 + src/control/Pickups.h | 13 + src/control/Replay.cpp | 5 + src/control/Replay.h | 7 + src/entities/Entity.cpp | 28 +- src/entities/Physical.cpp | 12 +- src/main.cpp | 302 ++++++++++++++++------ src/math/Rect.h | 20 +- src/math/Vector.h | 5 + src/re3.cpp | 112 ++++++++ src/render/Coronas.cpp | 4 + src/render/Coronas.h | 3 + src/render/Draw.cpp | 5 + src/render/Draw.h | 5 + src/render/Fluff.cpp | 5 + src/render/Fluff.h | 7 + src/render/Font.cpp | 12 +- src/render/Glass.cpp | 17 ++ src/render/Glass.h | 11 + src/render/Hud.cpp | 6 + src/render/Hud.h | 8 + src/render/Lights.cpp | 2 +- src/render/Particle.cpp | 6 +- src/render/PointLights.cpp | 5 + src/render/PointLights.h | 7 + src/render/Renderer.cpp | 8 +- src/render/Rubbish.cpp | 5 + src/render/Rubbish.h | 7 + src/render/Shadows.cpp | 4 + src/render/Shadows.h | 4 +- src/render/Skidmarks.cpp | 5 + src/render/Skidmarks.h | 7 + src/render/SpecialFX.cpp | 5 + src/render/SpecialFX.h | 7 + src/render/Sprite.cpp | 12 +- src/render/Sprite2d.cpp | 28 +- src/render/WaterCannon.cpp | 5 + src/render/WaterCannon.h | 7 + src/render/WaterLevel.cpp | 5 + src/render/WaterLevel.h | 7 + src/render/WeaponEffects.cpp | 5 + src/render/WeaponEffects.h | 7 + 71 files changed, 1576 insertions(+), 954 deletions(-) create mode 100644 src/Frontend.cpp create mode 100644 src/Frontend.h delete mode 100644 src/Garages.cpp delete mode 100644 src/Garages.h delete mode 100644 src/Glass.cpp delete mode 100644 src/Glass.h delete mode 100644 src/MenuManager.cpp delete mode 100644 src/MenuManager.h create mode 100644 src/Messages.cpp create mode 100644 src/Messages.h delete mode 100644 src/PathFind.cpp delete mode 100644 src/PathFind.h create mode 100644 src/User.cpp create mode 100644 src/User.h create mode 100644 src/audio/MusicManager.cpp create mode 100644 src/audio/MusicManager.h create mode 100644 src/control/Darkel.cpp create mode 100644 src/control/Darkel.h create mode 100644 src/control/Garages.cpp create mode 100644 src/control/Garages.h create mode 100644 src/control/PathFind.cpp create mode 100644 src/control/PathFind.h create mode 100644 src/control/Pickups.cpp create mode 100644 src/control/Pickups.h create mode 100644 src/control/Replay.cpp create mode 100644 src/control/Replay.h create mode 100644 src/re3.cpp create mode 100644 src/render/Fluff.cpp create mode 100644 src/render/Fluff.h create mode 100644 src/render/Glass.cpp create mode 100644 src/render/Glass.h create mode 100644 src/render/Hud.cpp create mode 100644 src/render/Hud.h create mode 100644 src/render/PointLights.cpp create mode 100644 src/render/PointLights.h create mode 100644 src/render/Rubbish.cpp create mode 100644 src/render/Rubbish.h create mode 100644 src/render/Skidmarks.cpp create mode 100644 src/render/Skidmarks.h create mode 100644 src/render/SpecialFX.cpp create mode 100644 src/render/SpecialFX.h create mode 100644 src/render/WaterCannon.cpp create mode 100644 src/render/WaterCannon.h create mode 100644 src/render/WaterLevel.cpp create mode 100644 src/render/WaterLevel.h create mode 100644 src/render/WeaponEffects.cpp create mode 100644 src/render/WeaponEffects.h diff --git a/src/Camera.cpp b/src/Camera.cpp index ac4b287d..ed3a474c 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -14,6 +14,8 @@ const float DefaultFOV = 80.0f; // actually 70.0f CCamera &TheCamera = *(CCamera*)0x6FACF8; +WRAPPER void CCamera::DrawBordersForWideScreen(void) { EAXJMP(0x46B430); } + bool CCamera::IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat) { @@ -66,6 +68,18 @@ CCamera::IsBoxVisible(RwV3d *box, const CMatrix *mat) return true; } +WRAPPER void CCamera::Fade(float timeout, int16 direction) { EAXJMP(0x46B3A0); } +WRAPPER void CCamera::ProcessFade(void) { EAXJMP(0x46F080); } +WRAPPER void CCamera::ProcessMusicFade(void) { EAXJMP(0x46F1E0); } + +void +CCamera::SetFadeColour(uint8 r, uint8 g, uint8 b) +{ + m_FadeTargetIsSplashScreen = r == 0 && g == 0 && b == 0; + CDraw::FadeRed = r; + CDraw::FadeGreen = g; + CDraw::FadeBlue = b; +} /* * @@ -1186,6 +1200,8 @@ CCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors) STARTPATCHES InjectHook(0x42C760, &CCamera::IsSphereVisible, PATCH_JUMP); + InjectHook(0x46FD00, &CCamera::SetFadeColour, PATCH_JUMP); + InjectHook(0x456F40, WellBufferMe, PATCH_JUMP); InjectHook(0x4582F0, &CCam::GetVectorsReadyForRW, PATCH_JUMP); InjectHook(0x457710, &CCam::DoAverageOnVector, PATCH_JUMP); diff --git a/src/Camera.h b/src/Camera.h index 55b61280..21d017d7 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -49,8 +49,8 @@ struct CCam MODE_SPECIALFIXEDFORSYPHON, MODE_FIGHT, MODE_TOPDOWNPED, - MODE_FIRSTPERSONPEDONPC_38, - MODE_FIRSTPERSONPEDONPC_39, + MODE_SNIPER_RUN_AROUND, + MODE_ROCKET_RUN_AROUND, MODE_FIRSTPERSONPEDONPC_40, MODE_FIRSTPERSONPEDONPC_41, MODE_FIRSTPERSONPEDONPC_42, @@ -419,6 +419,13 @@ int m_iModeObbeCamIsInForCar; bool IsPointVisible(const CVector ¢er, const CMatrix *mat); bool IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat); bool IsBoxVisible(RwV3d *box, const CMatrix *mat); + + void Fade(float timeout, int16 direction); + void ProcessFade(void); + void ProcessMusicFade(void); + void SetFadeColour(uint8 r, uint8 g, uint8 b); + + void DrawBordersForWideScreen(void); }; static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error"); static_assert(offsetof(CCamera, WorldViewerBeingUsed) == 0x75, "CCamera: error"); diff --git a/src/Frontend.cpp b/src/Frontend.cpp new file mode 100644 index 00000000..a96b6623 --- /dev/null +++ b/src/Frontend.cpp @@ -0,0 +1,8 @@ +#include "common.h" +#include "patcher.h" +#include "Frontend.h" + +int &CMenuManager::m_PrefsBrightness = *(int*)0x5F2E50; +CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8; + +WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); } diff --git a/src/Frontend.h b/src/Frontend.h new file mode 100644 index 00000000..3d7b6914 --- /dev/null +++ b/src/Frontend.h @@ -0,0 +1,85 @@ +#pragma + +#include "Sprite2d.h" + +struct tSkinInfo +{ + int field_0; + char skinName[256]; + char currSkinName[256]; + char date[256]; + int field_304; +}; + + +class CMenuManager +{ +public: + int32 m_nPrefsVideoMode; + int32 m_nDisplayVideoMode; + int8 m_nPrefsAudio3DProviderIndex; + bool m_bKeyChangeNotProcessed; + char m_aSkinName[256]; + int32 m_nHelperTextMsgId; + bool m_bLanguageLoaded; + bool m_bMenuActive; + char field_112; + char field_113; + bool m_bStartGameLoading; + bool m_bFirstTime; + bool m_bGameNotLoaded; + int32 m_nMousePosX; + int32 m_nMousePosY; + int32 m_nMouseTempPosX; + int32 m_nMouseTempPosY; + bool m_bShowMouse; + tSkinInfo field_12C; + tSkinInfo *m_pSelectedSkin; + tSkinInfo *field_438; + float field_43C; + int field_440; + int m_nSkinsTotal; + char _unk0[4]; + int field_44C; + bool m_bSkinsFound; + bool m_bQuitGameNoCD; + char field_452; + bool m_bSaveMenuActive; + bool m_bLoadingSavedGame; + char field_455; + char field_456; + bool m_bSpritesLoaded; + CSprite2d m_aFrontEndSprites[28]; + CSprite2d m_aMenuSprites[20]; + int field_518; + int m_nMenuFadeAlpha; + char field_520; + char field_521; + char field_522; + char field_523; + char field_524; + int m_CurrCntrlAction; + char _unk1[4]; + int field_530; + char field_534; + char field_535; + int8 field_536; + int m_nHelperTextAlpha; + int m_nMouseOldPosX; + int m_nMouseOldPosY; + int field_544; + int m_nCurrScreen; + int m_nCurrOption; + int field_550; + int m_nPrevScreen; + int field_558; + int m_nCurrSaveSlot; + int m_nScreenChangeDelayTimer; + + static int &m_PrefsBrightness; + + void DrawFrontEnd(void); +}; +static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error"); + +extern CMenuManager &FrontEndMenuManager; diff --git a/src/Garages.cpp b/src/Garages.cpp deleted file mode 100644 index 42e38a3a..00000000 --- a/src/Garages.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "common.h" -#include "patcher.h" -#include "ModelIndices.h" -#include "Garages.h" - -bool -CGarages::IsModelIndexADoor(uint32 id) -{ - return id == MI_GARAGEDOOR1 || - id == MI_GARAGEDOOR2 || - id == MI_GARAGEDOOR3 || - id == MI_GARAGEDOOR4 || - id == MI_GARAGEDOOR5 || - id == MI_GARAGEDOOR6 || - id == MI_GARAGEDOOR7 || - id == MI_GARAGEDOOR9 || - id == MI_GARAGEDOOR10 || - id == MI_GARAGEDOOR11 || - id == MI_GARAGEDOOR12 || - id == MI_GARAGEDOOR13 || - id == MI_GARAGEDOOR14 || - id == MI_GARAGEDOOR15 || - id == MI_GARAGEDOOR16 || - id == MI_GARAGEDOOR17 || - id == MI_GARAGEDOOR18 || - id == MI_GARAGEDOOR19 || - id == MI_GARAGEDOOR20 || - id == MI_GARAGEDOOR21 || - id == MI_GARAGEDOOR22 || - id == MI_GARAGEDOOR23 || - id == MI_GARAGEDOOR24 || - id == MI_GARAGEDOOR25 || - id == MI_GARAGEDOOR26 || - id == MI_GARAGEDOOR27 || - id == MI_GARAGEDOOR28 || - id == MI_GARAGEDOOR29 || - id == MI_GARAGEDOOR30 || - id == MI_GARAGEDOOR31 || - id == MI_GARAGEDOOR32 || - id == MI_CRUSHERBODY || - id == MI_CRUSHERLID; -} diff --git a/src/Garages.h b/src/Garages.h deleted file mode 100644 index 70add26d..00000000 --- a/src/Garages.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class CGarages -{ -public: - static bool IsModelIndexADoor(uint32 id); -}; diff --git a/src/Glass.cpp b/src/Glass.cpp deleted file mode 100644 index 7b02cb6c..00000000 --- a/src/Glass.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "common.h" -#include "patcher.h" -#include "Glass.h" - -WRAPPER void -CGlass::WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo) -{ - EAXJMP(0x503F10); -} - -WRAPPER void -CGlass::WindowRespondsToSoftCollision(CEntity *ent, float amount) -{ - EAXJMP(0x504630); -} diff --git a/src/Glass.h b/src/Glass.h deleted file mode 100644 index 5347467b..00000000 --- a/src/Glass.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -class CEntity; - -class CGlass -{ -public: - static void WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo); - static void WindowRespondsToSoftCollision(CEntity *ent, float amount); -}; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp deleted file mode 100644 index 0e335546..00000000 --- a/src/MenuManager.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "common.h" -#include "MenuManager.h" - -int &CMenuManager::m_PrefsBrightness = *(int*)0x5F2E50; diff --git a/src/MenuManager.h b/src/MenuManager.h deleted file mode 100644 index 803e4d8d..00000000 --- a/src/MenuManager.h +++ /dev/null @@ -1,5 +0,0 @@ -class CMenuManager -{ -public: - static int &m_PrefsBrightness; -}; diff --git a/src/Messages.cpp b/src/Messages.cpp new file mode 100644 index 00000000..6754c9ae --- /dev/null +++ b/src/Messages.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Messages.h" + +WRAPPER void CMessages::Display(void) { EAXJMP(0x529800); } diff --git a/src/Messages.h b/src/Messages.h new file mode 100644 index 00000000..f7f90087 --- /dev/null +++ b/src/Messages.h @@ -0,0 +1,7 @@ +#pragma once + +class CMessages +{ +public: + static void Display(void); +}; diff --git a/src/Pad.cpp b/src/Pad.cpp index 44bde467..869c4d48 100644 --- a/src/Pad.cpp +++ b/src/Pad.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include "patcher.h" #include "Pad.h" CPad *CPad::Pads = (CPad*)0x6F0360; @@ -11,6 +12,8 @@ CMouseControllerState &CPad::OldMouseControllerState = *(CMouseControllerState*) CMouseControllerState &CPad::NewMouseControllerState = *(CMouseControllerState*)0x8809F0; CMouseControllerState &CPad::PCTempMouseControllerState = *(CMouseControllerState*)0x6F1E60; +WRAPPER void CPad::PrintErrorMessage(void) { EAXJMP(0x4942B0); } + void CControllerState::Clear(void) { diff --git a/src/Pad.h b/src/Pad.h index db035788..48e19e6f 100644 --- a/src/Pad.h +++ b/src/Pad.h @@ -121,6 +121,7 @@ public: bool GetLookRight(void); static CPad *GetPad(int n) { return &Pads[n]; } + static void PrintErrorMessage(void); }; static_assert(sizeof(CPad) == 0xFC, "CPad: error"); diff --git a/src/PathFind.cpp b/src/PathFind.cpp deleted file mode 100644 index 8857f8c9..00000000 --- a/src/PathFind.cpp +++ /dev/null @@ -1,594 +0,0 @@ -#include "common.h" -#include "patcher.h" -#include "PathFind.h" - -CPathFind &ThePaths = *(CPathFind*)0x8F6754; - -int TempListLength; - -enum -{ - NodeTypeExtern = 1, - NodeTypeIntern = 2, - - PathTypeCar = 0, - PathTypePed = 1, - - PathNodeFlag1 = 1, // used? - PathNodeFlag2 = 2, - PathNodeDeadEnd = 4, - PathNodeDisabled = 8, - PathNodeBetweenLevels = 0x10, - - ConnectionCrossRoad = 1, - ConnectionTrafficLight = 2, -}; - -// link flags: -// 1: crosses road -// 2: ped traffic light -// pathnode flags: -// 1: -// 2: -// 4: dead end -// 8: switched off -// 10: road between levels?? -// navi node flags: -// 1: bridge light -// object flags: -// 1 -// 2 east/west road(?) - -CPathInfoForObject *&InfoForTileCars = *(CPathInfoForObject**)0x8F1A8C; -CPathInfoForObject *&InfoForTilePeds = *(CPathInfoForObject**)0x8F1AE4; -// unused -CTempDetachedNode *&DetachedNodesCars = *(CTempDetachedNode**)0x8E2824; -CTempDetachedNode *&DetachedNodesPeds = *(CTempDetachedNode**)0x8E28A0; - -void -CPathFind::PreparePathData(void) -{ - int i, j, k; - int numExtern, numIntern, numLanes; - float maxX, maxY; - CTempNode *tempNodes; - - printf("PreparePathData\n"); - // UNUSED: CPathFind::LoadPathFindData - if(InfoForTileCars && InfoForTilePeds && - DetachedNodesCars && DetachedNodesPeds){ - tempNodes = new CTempNode[4000]; - - m_numConnections = 0; - for(i = 0; i < PATHNODESIZE; i++) - m_pathNodes[i].flags &= ~(PathNodeFlag1 | PathNodeFlag2); - - for(i = 0; i < PATHNODESIZE; i++){ - numExtern = 0; - numIntern = 0; - for(j = 0; j < 12; j++){ - if(InfoForTileCars[i*12 + j].type == NodeTypeExtern) - numExtern++; - if(InfoForTileCars[i*12 + j].type == NodeTypeIntern) - numIntern++; - } - if(numIntern > 1 && numExtern != 2) - printf("ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\n", i); - } - - for(i = 0; i < PATHNODESIZE; i++) - for(j = 0; j < 12; j++) - if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){ - if(InfoForTileCars[i*12 + j].numLeftLanes < 0) - printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); - if(InfoForTileCars[i*12 + j].numRightLanes < 0) - printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); - if(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0) - printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i); - } - - m_numPathNodes = 0; - PreparePathDataForType(PathTypeCar, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, 100); - m_numCarPathNodes = m_numPathNodes; - PreparePathDataForType(PathTypePed, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, 50); - m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes; - - // TODO: figure out what exactly is going on here - // Some roads seem to get a west/east flag - for(i = 0; i < m_numMapObjects; i++){ - numExtern = 0; - numIntern = 0; - numLanes = 0; - maxX = 0.0f; - maxY = 0.0f; - for(j = 0; j < 12; j++){ - k = i*12 + j; - if(InfoForTileCars[k].type == NodeTypeExtern){ - numExtern++; - if(InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes > numLanes) - numLanes = InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes; - maxX = max(maxX, fabs(InfoForTileCars[k].x)); - maxY = max(maxY, fabs(InfoForTileCars[k].y)); - }else if(InfoForTileCars[k].type == NodeTypeIntern) - numIntern++; - } - - if(numIntern == 1 && numExtern == 2){ - if(numLanes < 4){ - if((i & 7) == 4){ // WHAT? - m_objectFlags[i] |= PathNodeFlag1; - if(maxX > maxY) - m_objectFlags[i] |= PathNodeFlag2; - else - m_objectFlags[i] &= ~PathNodeFlag2; - } - }else{ - m_objectFlags[i] |= PathNodeFlag1; - if(maxX > maxY) - m_objectFlags[i] |= PathNodeFlag2; - else - m_objectFlags[i] &= ~PathNodeFlag2; - } - } - } - - delete[] tempNodes; - - CountFloodFillGroups(PathTypeCar); - CountFloodFillGroups(PathTypePed); - - delete[] InfoForTileCars; - InfoForTileCars = nil; - delete[] InfoForTilePeds; - InfoForTilePeds = nil; - delete[] DetachedNodesCars; - DetachedNodesCars = nil; - delete[] DetachedNodesPeds; - DetachedNodesPeds = nil; - } - printf("Done with PreparePathData\n"); -} - -/* String together connected nodes in a list by a flood fill algorithm */ -void -CPathFind::CountFloodFillGroups(uint8 type) -{ - int start, end; - int i, l; - uint16 n; - CPathNode *node, *prev; - - switch(type){ - case PathTypeCar: - start = 0; - end = m_numCarPathNodes; - break; - case PathTypePed: - start = m_numCarPathNodes; - end = start + m_numPedPathNodes; - break; - } - - for(i = start; i < end; i++) - m_pathNodes[i].group = 0; - - n = 0; - for(;;){ - n++; - if(n > 1500){ - for(i = start; m_pathNodes[i].group && i < end; i++); - printf("NumNodes:%d Accounted for:%d\n", end - start, i - start); - } - - // Look for unvisited node - for(i = start; m_pathNodes[i].group && i < end; i++); - if(i == end) - break; - - node = &m_pathNodes[i]; - node->next = nil; - node->group = n; - - if(node->numLinks == 0){ - if(type == PathTypeCar) - printf("Single car node: %f %f %f (%d)\n", - node->pos.x, node->pos.y, node->pos.z, - m_mapObjects[node->objectIndex]->m_modelIndex); - else - printf("Single ped node: %f %f %f\n", - node->pos.x, node->pos.y, node->pos.z); - } - - while(node){ - prev = node; - node = node->next; - for(i = 0; i < prev->numLinks; i++){ - l = m_connections[prev->firstLink + i]; - if(m_pathNodes[l].group == 0){ - m_pathNodes[l].group = n; - if(m_pathNodes[l].group == 0) - m_pathNodes[l].group = 0x80; // ??? - m_pathNodes[l].next = node; - node = &m_pathNodes[l]; - } - } - } - } - - m_numGroups[type] = n-1; - printf("GraphType:%d. FloodFill groups:%d\n", type, n); -} - -void -CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, - float maxdist, CTempDetachedNode *detachednodes, int unused) -{ - static CVector CoorsXFormed; - int i, j, k, l; - int l1, l2; - int start, typeoff; - float posx, posy; - float dx, dy, mag; - float nearestDist; - int nearestId; - int next; - int oldNumPathNodes, oldNumLinks; - CVector dist; - int iseg, jseg; - int istart, jstart; - int done, cont; - - typeoff = 12*type; - oldNumPathNodes = m_numPathNodes; - oldNumLinks = m_numConnections; - - // Initialize map objects - for(i = 0; i < m_numMapObjects; i++) - for(j = 0; j < 12; j++) - m_mapObjects[i]->m_nodeIndicesCars[typeoff + j] = -1; - - // Calculate internal nodes, store them and connect them to defining object - for(i = 0; i < m_numMapObjects; i++){ - start = 12*m_mapObjects[i]->m_modelIndex; - for(j = 0; j < 12; j++){ - if(objectpathinfo[start + j].type != NodeTypeIntern) - continue; - CalcNodeCoors( - objectpathinfo[start + j].x, - objectpathinfo[start + j].y, - objectpathinfo[start + j].z, - i, - &CoorsXFormed); - m_pathNodes[m_numPathNodes].pos = CoorsXFormed; - m_pathNodes[m_numPathNodes].objectIndex = i; - m_pathNodes[m_numPathNodes].flags |= PathNodeFlag1; - m_mapObjects[i]->m_nodeIndicesCars[typeoff + j] = m_numPathNodes++; - } - } - - // Insert external nodes into TempList - TempListLength = 0; - for(i = 0; i < m_numMapObjects; i++){ - start = 12*m_mapObjects[i]->m_modelIndex; - - for(j = 0; j < 12; j++){ - if(objectpathinfo[start + j].type != NodeTypeExtern) - continue; - CalcNodeCoors( - objectpathinfo[start + j].x, - objectpathinfo[start + j].y, - objectpathinfo[start + j].z, - i, - &CoorsXFormed); - - // find closest unconnected node - nearestId = -1; - nearestDist = maxdist; - for(k = 0; k < TempListLength; k++){ - if(tempnodes[k].linkState != 1) - continue; - dx = tempnodes[k].pos.x - CoorsXFormed.x; - if(fabs(dx) < nearestDist){ - dy = tempnodes[k].pos.y - CoorsXFormed.y; - if(fabs(dy) < nearestDist){ - nearestDist = max(fabs(dx), fabs(dy)); - nearestId = k; - } - } - } - - if(nearestId < 0){ - // None found, add this one to temp list - tempnodes[TempListLength].pos = CoorsXFormed; - next = objectpathinfo[start + j].next; - if(next < 0){ - // no link from this node, find link to this node - next = 0; - for(k = start; j != objectpathinfo[k].next; k++) - next++; - } - // link to connecting internal node - tempnodes[TempListLength].link1 = m_mapObjects[i]->m_nodeIndicesCars[typeoff + next]; - if(type == PathTypeCar){ - tempnodes[TempListLength].numLeftLanes = objectpathinfo[start + j].numLeftLanes; - tempnodes[TempListLength].numRightLanes = objectpathinfo[start + j].numRightLanes; - } - tempnodes[TempListLength++].linkState = 1; - }else{ - // Found nearest, connect it to our neighbour - next = objectpathinfo[start + j].next; - if(next < 0){ - // no link from this node, find link to this node - next = 0; - for(k = start; j != objectpathinfo[k].next; k++) - next++; - } - tempnodes[nearestId].link2 = m_mapObjects[i]->m_nodeIndicesCars[typeoff + next]; - tempnodes[nearestId].linkState = 2; - - // collapse this node with nearest we found - dx = m_pathNodes[tempnodes[nearestId].link1].pos.x - m_pathNodes[tempnodes[nearestId].link2].pos.x; - dy = m_pathNodes[tempnodes[nearestId].link1].pos.y - m_pathNodes[tempnodes[nearestId].link2].pos.y; - tempnodes[nearestId].pos = (tempnodes[nearestId].pos + CoorsXFormed)*0.5f; - mag = sqrt(dx*dx + dy*dy); - tempnodes[nearestId].dirX = dx/mag; - tempnodes[nearestId].dirY = dy/mag; - // do something when number of lanes doesn't agree - if(type == PathTypeCar) - if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 && - (objectpathinfo[start + j].numLeftLanes == 0 || objectpathinfo[start + j].numRightLanes == 0)){ - // why switch left and right here? - tempnodes[nearestId].numLeftLanes = objectpathinfo[start + j].numRightLanes; - tempnodes[nearestId].numRightLanes = objectpathinfo[start + j].numLeftLanes; - } - } - } - } - - // Loop through previously added internal nodes and link them - for(i = oldNumPathNodes; i < m_numPathNodes; i++){ - // Init link - m_pathNodes[i].numLinks = 0; - m_pathNodes[i].firstLink = m_numConnections; - - // See if node connects to external nodes - for(j = 0; j < TempListLength; j++){ - if(tempnodes[j].linkState != 2) - continue; - - // Add link to other side of the external - if(tempnodes[j].link1 == i) - m_connections[m_numConnections] = tempnodes[j].link2; - else if(tempnodes[j].link2 == i) - m_connections[m_numConnections] = tempnodes[j].link1; - else - continue; - - dist = m_pathNodes[i].pos - m_pathNodes[m_connections[m_numConnections]].pos; - m_distances[m_numConnections] = dist.Magnitude(); - m_connectionFlags[m_numConnections] = 0; - - if(type == PathTypeCar){ - // IMPROVE: use a goto here - // Find existing car path link - for(k = 0; k < m_numCarPathLinks; k++){ - if(m_carPathLinks[k].dirX == tempnodes[j].dirX && - m_carPathLinks[k].dirY == tempnodes[j].dirY && - m_carPathLinks[k].posX == tempnodes[j].pos.x && - m_carPathLinks[k].posY == tempnodes[j].pos.y){ - m_carPathConnections[m_numConnections] = k; - k = m_numCarPathLinks; - } - } - // k is m_numCarPathLinks+1 if we found one - if(k == m_numCarPathLinks){ - m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX; - m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY; - m_carPathLinks[m_numCarPathLinks].posX = tempnodes[j].pos.x; - m_carPathLinks[m_numCarPathLinks].posY = tempnodes[j].pos.y; - m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; - m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; - m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; - m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; - m_carPathConnections[m_numConnections] = m_numCarPathLinks++; - } - } - - m_pathNodes[i].numLinks++; - m_numConnections++; - } - - // Find i inside path segment - iseg = 0; - for(j = max(oldNumPathNodes, i-12); j < i; j++) - if(m_pathNodes[j].objectIndex == m_pathNodes[i].objectIndex) - iseg++; - - istart = 12*m_mapObjects[m_pathNodes[i].objectIndex]->m_modelIndex; - // Add links to other internal nodes - for(j = max(oldNumPathNodes, i-12); j < min(m_numPathNodes, i+12); j++){ - if(m_pathNodes[i].objectIndex != m_pathNodes[j].objectIndex || i == j) - continue; - // N.B.: in every path segment, the externals have to be at the end - jseg = j-i + iseg; - - jstart = 12*m_mapObjects[m_pathNodes[j].objectIndex]->m_modelIndex; - if(objectpathinfo[istart + iseg].next == jseg || - objectpathinfo[jstart + jseg].next == iseg){ - // Found a link between i and j - m_connections[m_numConnections] = j; - dist = m_pathNodes[i].pos - m_pathNodes[j].pos; - m_distances[m_numConnections] = dist.Magnitude(); - - if(type == PathTypeCar){ - posx = (m_pathNodes[i].pos.x + m_pathNodes[j].pos.x)*0.5f; - posy = (m_pathNodes[i].pos.y + m_pathNodes[j].pos.y)*0.5f; - dx = m_pathNodes[j].pos.x - m_pathNodes[i].pos.x; - dy = m_pathNodes[j].pos.y - m_pathNodes[i].pos.y; - mag = sqrt(dx*dx + dy*dy); - dx /= mag; - dy /= mag; - if(i < j){ - dx = -dx; - dy = -dy; - } - // IMPROVE: use a goto here - // Find existing car path link - for(k = 0; k < m_numCarPathLinks; k++){ - if(m_carPathLinks[k].dirX == dx && - m_carPathLinks[k].dirY == dy && - m_carPathLinks[k].posX == posx && - m_carPathLinks[k].posY == posy){ - m_carPathConnections[m_numConnections] = k; - k = m_numCarPathLinks; - } - } - // k is m_numCarPathLinks+1 if we found one - if(k == m_numCarPathLinks){ - m_carPathLinks[m_numCarPathLinks].dirX = dx; - m_carPathLinks[m_numCarPathLinks].dirY = dy; - m_carPathLinks[m_numCarPathLinks].posX = posx; - m_carPathLinks[m_numCarPathLinks].posY = posy; - m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; - m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; - m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; - m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; - m_carPathConnections[m_numConnections] = m_numCarPathLinks++; - } - }else{ - // Crosses road - if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].flag & 1 || - objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].flag & 1) - m_connectionFlags[m_numConnections] |= ConnectionCrossRoad; - else - m_connectionFlags[m_numConnections] &= ~ConnectionCrossRoad; - } - - m_pathNodes[i].numLinks++; - m_numConnections++; - } - } - } - - if(type == PathTypeCar){ - done = 0; - // Set number of lanes for all nodes somehow - // very strange code - for(k = 0; !done && k < 10; k++){ - done = 1; - for(i = 0; i < m_numPathNodes; i++){ - if(m_pathNodes[i].numLinks != 2) - continue; - l1 = m_carPathConnections[m_pathNodes[i].firstLink]; - l2 = m_carPathConnections[m_pathNodes[i].firstLink+1]; - - if(m_carPathLinks[l1].numLeftLanes == -1 && - m_carPathLinks[l2].numLeftLanes != -1){ - done = 0; - if(m_carPathLinks[l2].pathNodeIndex == i){ - // why switch left and right here? - m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numRightLanes; - m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numLeftLanes; - }else{ - m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numLeftLanes; - m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numRightLanes; - } - m_carPathLinks[l1].pathNodeIndex = i; - }else if(m_carPathLinks[l1].numLeftLanes != -1 && - m_carPathLinks[l2].numLeftLanes == -1){ - done = 0; - if(m_carPathLinks[l1].pathNodeIndex == i){ - // why switch left and right here? - m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numRightLanes; - m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numLeftLanes; - }else{ - m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numLeftLanes; - m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numRightLanes; - } - m_carPathLinks[l2].pathNodeIndex = i; - }else if(m_carPathLinks[l1].numLeftLanes == -1 && - m_carPathLinks[l2].numLeftLanes == -1) - done = 0; - } - } - - // Fall back to default values for number of lanes - for(i = 0; i < m_numPathNodes; i++) - for(j = 0; j < m_pathNodes[i].numLinks; j++){ - k = m_carPathConnections[m_pathNodes[i].firstLink + j]; - if(m_carPathLinks[k].numLeftLanes < 0) - m_carPathLinks[k].numLeftLanes = 1; - if(m_carPathLinks[k].numRightLanes < 0) - m_carPathLinks[k].numRightLanes = 1; - } - } - - // Set flags for car nodes - if(type == PathTypeCar){ - do{ - cont = 0; - for(i = 0; i < m_numPathNodes; i++){ - m_pathNodes[i].flags &= ~PathNodeDisabled; - m_pathNodes[i].flags &= ~PathNodeBetweenLevels; - // See if node is a dead end, if so, we're not done yet - if((m_pathNodes[i].flags & PathNodeDeadEnd) == 0){ - k = 0; - for(j = 0; j < m_pathNodes[i].numLinks; j++) - if((m_pathNodes[m_connections[m_pathNodes[i].firstLink + j]].flags & PathNodeDeadEnd) == 0) - k++; - if(k < 2){ - m_pathNodes[i].flags |= PathNodeDeadEnd; - cont = 1; - } - } - } - }while(cont); - } - - // Remove isolated ped nodes - if(type == PathTypePed) - for(i = oldNumPathNodes; i < m_numPathNodes; i++){ - if(m_pathNodes[i].numLinks != 0) - continue; - - // Remove node - for(j = i; j < m_numPathNodes-1; j++) - m_pathNodes[j] = m_pathNodes[j+1]; - - // Fix links - for(j = oldNumLinks; j < m_numConnections; j++) - if(m_connections[j] >= i) - m_connections[j]--; - - // Also in treadables - for(j = 0; j < m_numMapObjects; j++) - for(k = 0; k < 12; k++){ - if(m_mapObjects[j]->m_nodeIndicesPeds[k] == i){ - // remove this one - for(l = k; l < 12-1; l++) - m_mapObjects[j]->m_nodeIndicesPeds[l] = m_mapObjects[j]->m_nodeIndicesPeds[l+1]; - m_mapObjects[j]->m_nodeIndicesPeds[11] = -1; - }else if(m_mapObjects[j]->m_nodeIndicesPeds[k] > i) - m_mapObjects[j]->m_nodeIndicesPeds[k]--; - } - - i--; - m_numPathNodes--; - } -} - -void -CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out) -{ - CVector pos; - pos.x = x / 16.0f; - pos.y = y / 16.0f; - pos.z = z / 16.0f; - *out = m_mapObjects[id]->GetMatrix() * pos; -} - -STARTPATCHES - InjectHook(0x429610, &CPathFind::PreparePathData, PATCH_JUMP); - InjectHook(0x429C20, &CPathFind::PreparePathDataForType, PATCH_JUMP); - InjectHook(0x42B810, &CPathFind::CountFloodFillGroups, PATCH_JUMP); -ENDPATCHES diff --git a/src/PathFind.h b/src/PathFind.h deleted file mode 100644 index 495c4a73..00000000 --- a/src/PathFind.h +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -#include "Treadable.h" - -struct CPathNode -{ - CVector pos; - CPathNode *prev; //? - CPathNode *next; - int16 unknown; - int16 objectIndex; - int16 firstLink; - uint8 numLinks; - uint8 flags; - uint8 group; -/* VC: - int16 unk1; - int16 nextIndex; - int16 x; - int16 y; - int16 z; - int16 unknown; - int16 firstLink; - int8 width; - int8 group; - int8 numLinks : 4; - int8 bDeadEnd : 1; - int8 bTurnedOff : 1; // flag 8 in node info - int8 flagA40 : 1; // flag 20 in node info - int8 flagA80 : 1; // flag 4 in node info - int8 flagB1 : 1; // flag 10 in node info - int8 flagB2 : 1; // flag 2 in node info - int8 flagB4 : 1; - int8 speedLimit : 2; // speed limit - int8 flagB20 : 1; - int8 flagB40 : 1; - int8 flagB80 : 1; - int8 spawnRate : 4; - int8 flagsC : 4; -*/ -}; - -struct CCarPathLink -{ - float posX; - float posY; - float dirX; - float dirY; - int16 pathNodeIndex; - int8 numLeftLanes; - int8 numRightLanes; - int8 trafficLightType; - int8 field15; - // probably only padding - int8 field16; - int8 field17; -}; - -struct CPathInfoForObject -{ - int16 x; - int16 y; - int16 z; - int8 type; - int8 next; - int8 numLeftLanes; - int8 numRightLanes; - uint8 flag; -}; - -struct CTempNode -{ - CVector pos; - float dirX; - float dirY; - int16 link1; - int16 link2; - int8 numLeftLanes; - int8 numRightLanes; - int8 linkState; - // probably padding - int8 field1B; -}; - -struct CTempDetachedNode // unused -{ - uint8 foo[20]; -}; - -class CPathFind -{ -public: -/* For reference VC: - CPathNode pathNodes[9650]; - CCarPathLink m_carPathLinks[3500]; - CBuilding *m_mapObjects[1250]; - // 0x8000 is cross road flag - // 0x4000 is traffic light flag - uint16 m_connections[20400]; - uint8 m_distances[20400]; - int16 m_carPathConnections[20400]; -*/ - CPathNode m_pathNodes[4930]; - CCarPathLink m_carPathLinks[2076]; - CTreadable *m_mapObjects[1250]; - uint8 m_objectFlags[1250]; - int16 m_connections[10260]; - int16 m_distances[10260]; - uint8 m_connectionFlags[10260]; - int16 m_carPathConnections[10260]; - int32 m_numPathNodes; - int32 m_numCarPathNodes; - int32 m_numPedPathNodes; - int16 m_numMapObjects; - int16 m_numConnections; - int32 m_numCarPathLinks; - int32 h; - uint8 m_numGroups[2]; - CPathNode m_aExtraPaths[872]; - - void PreparePathData(void); - void CountFloodFillGroups(uint8 type); - void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, - float unk, CTempDetachedNode *detachednodes, int unused); - void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out); -}; -static_assert(sizeof(CPathFind) == 0x4c8f4, "CPathFind: error"); - -extern CPathFind &ThePaths; diff --git a/src/Timecycle.h b/src/Timecycle.h index 2f9e4f2f..bfbda281 100644 --- a/src/Timecycle.h +++ b/src/Timecycle.h @@ -110,5 +110,4 @@ public: static int GetFogRed(void) { return m_nCurrentFogColourRed; } static int GetFogGreen(void) { return m_nCurrentFogColourGreen; } static int GetFogBlue(void) { return m_nCurrentFogColourBlue; } - }; diff --git a/src/User.cpp b/src/User.cpp new file mode 100644 index 00000000..4cdb0f1b --- /dev/null +++ b/src/User.cpp @@ -0,0 +1,10 @@ +#include "common.h" +#include "patcher.h" +#include "User.h" + +CPlaceName &CUserDisplay::PlaceName = *(CPlaceName*)0x8F29BC; +COnscreenTimer &CUserDisplay::OnscnTimer = *(COnscreenTimer*)0x862238; +CPager &CUserDisplay::Pager = *(CPager*)0x8F2744; +CCurrentVehicle &CUserDisplay::CurrentVehicle = *(CCurrentVehicle*)0x8F5FE8; + +WRAPPER void COnscreenTimer::ProcessForDisplay(void) { EAXJMP(0x4292E0); } diff --git a/src/User.h b/src/User.h new file mode 100644 index 00000000..9717fae0 --- /dev/null +++ b/src/User.h @@ -0,0 +1,28 @@ +#pragma once + +class COnscreenTimer +{ +public: + void ProcessForDisplay(void); +}; + +class CPlaceName +{ +}; + +class CCurrentVehicle +{ +}; + +class CPager +{ +}; + +class CUserDisplay +{ +public: + static CPlaceName &PlaceName; + static COnscreenTimer &OnscnTimer; + static CPager &Pager; + static CCurrentVehicle &CurrentVehicle; +}; diff --git a/src/Weather.cpp b/src/Weather.cpp index 73421932..845ef014 100644 --- a/src/Weather.cpp +++ b/src/Weather.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include "patcher.h" #include "Weather.h" int32 &CWeather::SoundHandle = *(int32*)0x5FFBC4; @@ -25,3 +26,5 @@ float &CWeather::Rainbow = *(float*)0x940598; bool &CWeather::bScriptsForceRain = *(bool*)0x95CD7D; bool &CWeather::Stored_StateStored = *(bool*)0x95CDC1; + +WRAPPER void CWeather::RenderRainStreaks(void) { EAXJMP(0x524550); } diff --git a/src/Weather.h b/src/Weather.h index 41e07d93..63e819ff 100644 --- a/src/Weather.h +++ b/src/Weather.h @@ -32,4 +32,6 @@ public: static bool &bScriptsForceRain; static bool &Stored_StateStored; + + static void RenderRainStreaks(void); }; diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp new file mode 100644 index 00000000..0e6870de --- /dev/null +++ b/src/audio/MusicManager.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "MusicManager.h" + +cMusicManager &MusicManager = *(cMusicManager*)0x8F3964; + +WRAPPER void cMusicManager::DisplayRadioStationName(void) { EAXJMP(0x57E6D0); } diff --git a/src/audio/MusicManager.h b/src/audio/MusicManager.h new file mode 100644 index 00000000..42cc879d --- /dev/null +++ b/src/audio/MusicManager.h @@ -0,0 +1,8 @@ +#pragma once + +class cMusicManager +{ +public: + void DisplayRadioStationName(void); +}; +extern cMusicManager &MusicManager; diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp new file mode 100644 index 00000000..95f3e176 --- /dev/null +++ b/src/control/Darkel.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Darkel.h" + +WRAPPER void CDarkel::DrawMessages(void) { EAXJMP(0x420920); } diff --git a/src/control/Darkel.h b/src/control/Darkel.h new file mode 100644 index 00000000..41cc69f8 --- /dev/null +++ b/src/control/Darkel.h @@ -0,0 +1,7 @@ +#pragma once + +class CDarkel +{ +public: + static void DrawMessages(void); +}; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp new file mode 100644 index 00000000..effc13d8 --- /dev/null +++ b/src/control/Garages.cpp @@ -0,0 +1,44 @@ +#include "common.h" +#include "patcher.h" +#include "ModelIndices.h" +#include "Garages.h" + +WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); } + +bool +CGarages::IsModelIndexADoor(uint32 id) +{ + return id == MI_GARAGEDOOR1 || + id == MI_GARAGEDOOR2 || + id == MI_GARAGEDOOR3 || + id == MI_GARAGEDOOR4 || + id == MI_GARAGEDOOR5 || + id == MI_GARAGEDOOR6 || + id == MI_GARAGEDOOR7 || + id == MI_GARAGEDOOR9 || + id == MI_GARAGEDOOR10 || + id == MI_GARAGEDOOR11 || + id == MI_GARAGEDOOR12 || + id == MI_GARAGEDOOR13 || + id == MI_GARAGEDOOR14 || + id == MI_GARAGEDOOR15 || + id == MI_GARAGEDOOR16 || + id == MI_GARAGEDOOR17 || + id == MI_GARAGEDOOR18 || + id == MI_GARAGEDOOR19 || + id == MI_GARAGEDOOR20 || + id == MI_GARAGEDOOR21 || + id == MI_GARAGEDOOR22 || + id == MI_GARAGEDOOR23 || + id == MI_GARAGEDOOR24 || + id == MI_GARAGEDOOR25 || + id == MI_GARAGEDOOR26 || + id == MI_GARAGEDOOR27 || + id == MI_GARAGEDOOR28 || + id == MI_GARAGEDOOR29 || + id == MI_GARAGEDOOR30 || + id == MI_GARAGEDOOR31 || + id == MI_GARAGEDOOR32 || + id == MI_CRUSHERBODY || + id == MI_CRUSHERLID; +} diff --git a/src/control/Garages.h b/src/control/Garages.h new file mode 100644 index 00000000..87cf47fa --- /dev/null +++ b/src/control/Garages.h @@ -0,0 +1,8 @@ +#pragma once + +class CGarages +{ +public: + static bool IsModelIndexADoor(uint32 id); + static void PrintMessages(void); +}; diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp new file mode 100644 index 00000000..8857f8c9 --- /dev/null +++ b/src/control/PathFind.cpp @@ -0,0 +1,594 @@ +#include "common.h" +#include "patcher.h" +#include "PathFind.h" + +CPathFind &ThePaths = *(CPathFind*)0x8F6754; + +int TempListLength; + +enum +{ + NodeTypeExtern = 1, + NodeTypeIntern = 2, + + PathTypeCar = 0, + PathTypePed = 1, + + PathNodeFlag1 = 1, // used? + PathNodeFlag2 = 2, + PathNodeDeadEnd = 4, + PathNodeDisabled = 8, + PathNodeBetweenLevels = 0x10, + + ConnectionCrossRoad = 1, + ConnectionTrafficLight = 2, +}; + +// link flags: +// 1: crosses road +// 2: ped traffic light +// pathnode flags: +// 1: +// 2: +// 4: dead end +// 8: switched off +// 10: road between levels?? +// navi node flags: +// 1: bridge light +// object flags: +// 1 +// 2 east/west road(?) + +CPathInfoForObject *&InfoForTileCars = *(CPathInfoForObject**)0x8F1A8C; +CPathInfoForObject *&InfoForTilePeds = *(CPathInfoForObject**)0x8F1AE4; +// unused +CTempDetachedNode *&DetachedNodesCars = *(CTempDetachedNode**)0x8E2824; +CTempDetachedNode *&DetachedNodesPeds = *(CTempDetachedNode**)0x8E28A0; + +void +CPathFind::PreparePathData(void) +{ + int i, j, k; + int numExtern, numIntern, numLanes; + float maxX, maxY; + CTempNode *tempNodes; + + printf("PreparePathData\n"); + // UNUSED: CPathFind::LoadPathFindData + if(InfoForTileCars && InfoForTilePeds && + DetachedNodesCars && DetachedNodesPeds){ + tempNodes = new CTempNode[4000]; + + m_numConnections = 0; + for(i = 0; i < PATHNODESIZE; i++) + m_pathNodes[i].flags &= ~(PathNodeFlag1 | PathNodeFlag2); + + for(i = 0; i < PATHNODESIZE; i++){ + numExtern = 0; + numIntern = 0; + for(j = 0; j < 12; j++){ + if(InfoForTileCars[i*12 + j].type == NodeTypeExtern) + numExtern++; + if(InfoForTileCars[i*12 + j].type == NodeTypeIntern) + numIntern++; + } + if(numIntern > 1 && numExtern != 2) + printf("ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\n", i); + } + + for(i = 0; i < PATHNODESIZE; i++) + for(j = 0; j < 12; j++) + if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){ + if(InfoForTileCars[i*12 + j].numLeftLanes < 0) + printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); + if(InfoForTileCars[i*12 + j].numRightLanes < 0) + printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); + if(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0) + printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i); + } + + m_numPathNodes = 0; + PreparePathDataForType(PathTypeCar, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, 100); + m_numCarPathNodes = m_numPathNodes; + PreparePathDataForType(PathTypePed, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, 50); + m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes; + + // TODO: figure out what exactly is going on here + // Some roads seem to get a west/east flag + for(i = 0; i < m_numMapObjects; i++){ + numExtern = 0; + numIntern = 0; + numLanes = 0; + maxX = 0.0f; + maxY = 0.0f; + for(j = 0; j < 12; j++){ + k = i*12 + j; + if(InfoForTileCars[k].type == NodeTypeExtern){ + numExtern++; + if(InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes > numLanes) + numLanes = InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes; + maxX = max(maxX, fabs(InfoForTileCars[k].x)); + maxY = max(maxY, fabs(InfoForTileCars[k].y)); + }else if(InfoForTileCars[k].type == NodeTypeIntern) + numIntern++; + } + + if(numIntern == 1 && numExtern == 2){ + if(numLanes < 4){ + if((i & 7) == 4){ // WHAT? + m_objectFlags[i] |= PathNodeFlag1; + if(maxX > maxY) + m_objectFlags[i] |= PathNodeFlag2; + else + m_objectFlags[i] &= ~PathNodeFlag2; + } + }else{ + m_objectFlags[i] |= PathNodeFlag1; + if(maxX > maxY) + m_objectFlags[i] |= PathNodeFlag2; + else + m_objectFlags[i] &= ~PathNodeFlag2; + } + } + } + + delete[] tempNodes; + + CountFloodFillGroups(PathTypeCar); + CountFloodFillGroups(PathTypePed); + + delete[] InfoForTileCars; + InfoForTileCars = nil; + delete[] InfoForTilePeds; + InfoForTilePeds = nil; + delete[] DetachedNodesCars; + DetachedNodesCars = nil; + delete[] DetachedNodesPeds; + DetachedNodesPeds = nil; + } + printf("Done with PreparePathData\n"); +} + +/* String together connected nodes in a list by a flood fill algorithm */ +void +CPathFind::CountFloodFillGroups(uint8 type) +{ + int start, end; + int i, l; + uint16 n; + CPathNode *node, *prev; + + switch(type){ + case PathTypeCar: + start = 0; + end = m_numCarPathNodes; + break; + case PathTypePed: + start = m_numCarPathNodes; + end = start + m_numPedPathNodes; + break; + } + + for(i = start; i < end; i++) + m_pathNodes[i].group = 0; + + n = 0; + for(;;){ + n++; + if(n > 1500){ + for(i = start; m_pathNodes[i].group && i < end; i++); + printf("NumNodes:%d Accounted for:%d\n", end - start, i - start); + } + + // Look for unvisited node + for(i = start; m_pathNodes[i].group && i < end; i++); + if(i == end) + break; + + node = &m_pathNodes[i]; + node->next = nil; + node->group = n; + + if(node->numLinks == 0){ + if(type == PathTypeCar) + printf("Single car node: %f %f %f (%d)\n", + node->pos.x, node->pos.y, node->pos.z, + m_mapObjects[node->objectIndex]->m_modelIndex); + else + printf("Single ped node: %f %f %f\n", + node->pos.x, node->pos.y, node->pos.z); + } + + while(node){ + prev = node; + node = node->next; + for(i = 0; i < prev->numLinks; i++){ + l = m_connections[prev->firstLink + i]; + if(m_pathNodes[l].group == 0){ + m_pathNodes[l].group = n; + if(m_pathNodes[l].group == 0) + m_pathNodes[l].group = 0x80; // ??? + m_pathNodes[l].next = node; + node = &m_pathNodes[l]; + } + } + } + } + + m_numGroups[type] = n-1; + printf("GraphType:%d. FloodFill groups:%d\n", type, n); +} + +void +CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, + float maxdist, CTempDetachedNode *detachednodes, int unused) +{ + static CVector CoorsXFormed; + int i, j, k, l; + int l1, l2; + int start, typeoff; + float posx, posy; + float dx, dy, mag; + float nearestDist; + int nearestId; + int next; + int oldNumPathNodes, oldNumLinks; + CVector dist; + int iseg, jseg; + int istart, jstart; + int done, cont; + + typeoff = 12*type; + oldNumPathNodes = m_numPathNodes; + oldNumLinks = m_numConnections; + + // Initialize map objects + for(i = 0; i < m_numMapObjects; i++) + for(j = 0; j < 12; j++) + m_mapObjects[i]->m_nodeIndicesCars[typeoff + j] = -1; + + // Calculate internal nodes, store them and connect them to defining object + for(i = 0; i < m_numMapObjects; i++){ + start = 12*m_mapObjects[i]->m_modelIndex; + for(j = 0; j < 12; j++){ + if(objectpathinfo[start + j].type != NodeTypeIntern) + continue; + CalcNodeCoors( + objectpathinfo[start + j].x, + objectpathinfo[start + j].y, + objectpathinfo[start + j].z, + i, + &CoorsXFormed); + m_pathNodes[m_numPathNodes].pos = CoorsXFormed; + m_pathNodes[m_numPathNodes].objectIndex = i; + m_pathNodes[m_numPathNodes].flags |= PathNodeFlag1; + m_mapObjects[i]->m_nodeIndicesCars[typeoff + j] = m_numPathNodes++; + } + } + + // Insert external nodes into TempList + TempListLength = 0; + for(i = 0; i < m_numMapObjects; i++){ + start = 12*m_mapObjects[i]->m_modelIndex; + + for(j = 0; j < 12; j++){ + if(objectpathinfo[start + j].type != NodeTypeExtern) + continue; + CalcNodeCoors( + objectpathinfo[start + j].x, + objectpathinfo[start + j].y, + objectpathinfo[start + j].z, + i, + &CoorsXFormed); + + // find closest unconnected node + nearestId = -1; + nearestDist = maxdist; + for(k = 0; k < TempListLength; k++){ + if(tempnodes[k].linkState != 1) + continue; + dx = tempnodes[k].pos.x - CoorsXFormed.x; + if(fabs(dx) < nearestDist){ + dy = tempnodes[k].pos.y - CoorsXFormed.y; + if(fabs(dy) < nearestDist){ + nearestDist = max(fabs(dx), fabs(dy)); + nearestId = k; + } + } + } + + if(nearestId < 0){ + // None found, add this one to temp list + tempnodes[TempListLength].pos = CoorsXFormed; + next = objectpathinfo[start + j].next; + if(next < 0){ + // no link from this node, find link to this node + next = 0; + for(k = start; j != objectpathinfo[k].next; k++) + next++; + } + // link to connecting internal node + tempnodes[TempListLength].link1 = m_mapObjects[i]->m_nodeIndicesCars[typeoff + next]; + if(type == PathTypeCar){ + tempnodes[TempListLength].numLeftLanes = objectpathinfo[start + j].numLeftLanes; + tempnodes[TempListLength].numRightLanes = objectpathinfo[start + j].numRightLanes; + } + tempnodes[TempListLength++].linkState = 1; + }else{ + // Found nearest, connect it to our neighbour + next = objectpathinfo[start + j].next; + if(next < 0){ + // no link from this node, find link to this node + next = 0; + for(k = start; j != objectpathinfo[k].next; k++) + next++; + } + tempnodes[nearestId].link2 = m_mapObjects[i]->m_nodeIndicesCars[typeoff + next]; + tempnodes[nearestId].linkState = 2; + + // collapse this node with nearest we found + dx = m_pathNodes[tempnodes[nearestId].link1].pos.x - m_pathNodes[tempnodes[nearestId].link2].pos.x; + dy = m_pathNodes[tempnodes[nearestId].link1].pos.y - m_pathNodes[tempnodes[nearestId].link2].pos.y; + tempnodes[nearestId].pos = (tempnodes[nearestId].pos + CoorsXFormed)*0.5f; + mag = sqrt(dx*dx + dy*dy); + tempnodes[nearestId].dirX = dx/mag; + tempnodes[nearestId].dirY = dy/mag; + // do something when number of lanes doesn't agree + if(type == PathTypeCar) + if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 && + (objectpathinfo[start + j].numLeftLanes == 0 || objectpathinfo[start + j].numRightLanes == 0)){ + // why switch left and right here? + tempnodes[nearestId].numLeftLanes = objectpathinfo[start + j].numRightLanes; + tempnodes[nearestId].numRightLanes = objectpathinfo[start + j].numLeftLanes; + } + } + } + } + + // Loop through previously added internal nodes and link them + for(i = oldNumPathNodes; i < m_numPathNodes; i++){ + // Init link + m_pathNodes[i].numLinks = 0; + m_pathNodes[i].firstLink = m_numConnections; + + // See if node connects to external nodes + for(j = 0; j < TempListLength; j++){ + if(tempnodes[j].linkState != 2) + continue; + + // Add link to other side of the external + if(tempnodes[j].link1 == i) + m_connections[m_numConnections] = tempnodes[j].link2; + else if(tempnodes[j].link2 == i) + m_connections[m_numConnections] = tempnodes[j].link1; + else + continue; + + dist = m_pathNodes[i].pos - m_pathNodes[m_connections[m_numConnections]].pos; + m_distances[m_numConnections] = dist.Magnitude(); + m_connectionFlags[m_numConnections] = 0; + + if(type == PathTypeCar){ + // IMPROVE: use a goto here + // Find existing car path link + for(k = 0; k < m_numCarPathLinks; k++){ + if(m_carPathLinks[k].dirX == tempnodes[j].dirX && + m_carPathLinks[k].dirY == tempnodes[j].dirY && + m_carPathLinks[k].posX == tempnodes[j].pos.x && + m_carPathLinks[k].posY == tempnodes[j].pos.y){ + m_carPathConnections[m_numConnections] = k; + k = m_numCarPathLinks; + } + } + // k is m_numCarPathLinks+1 if we found one + if(k == m_numCarPathLinks){ + m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX; + m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY; + m_carPathLinks[m_numCarPathLinks].posX = tempnodes[j].pos.x; + m_carPathLinks[m_numCarPathLinks].posY = tempnodes[j].pos.y; + m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; + m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; + m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; + m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; + m_carPathConnections[m_numConnections] = m_numCarPathLinks++; + } + } + + m_pathNodes[i].numLinks++; + m_numConnections++; + } + + // Find i inside path segment + iseg = 0; + for(j = max(oldNumPathNodes, i-12); j < i; j++) + if(m_pathNodes[j].objectIndex == m_pathNodes[i].objectIndex) + iseg++; + + istart = 12*m_mapObjects[m_pathNodes[i].objectIndex]->m_modelIndex; + // Add links to other internal nodes + for(j = max(oldNumPathNodes, i-12); j < min(m_numPathNodes, i+12); j++){ + if(m_pathNodes[i].objectIndex != m_pathNodes[j].objectIndex || i == j) + continue; + // N.B.: in every path segment, the externals have to be at the end + jseg = j-i + iseg; + + jstart = 12*m_mapObjects[m_pathNodes[j].objectIndex]->m_modelIndex; + if(objectpathinfo[istart + iseg].next == jseg || + objectpathinfo[jstart + jseg].next == iseg){ + // Found a link between i and j + m_connections[m_numConnections] = j; + dist = m_pathNodes[i].pos - m_pathNodes[j].pos; + m_distances[m_numConnections] = dist.Magnitude(); + + if(type == PathTypeCar){ + posx = (m_pathNodes[i].pos.x + m_pathNodes[j].pos.x)*0.5f; + posy = (m_pathNodes[i].pos.y + m_pathNodes[j].pos.y)*0.5f; + dx = m_pathNodes[j].pos.x - m_pathNodes[i].pos.x; + dy = m_pathNodes[j].pos.y - m_pathNodes[i].pos.y; + mag = sqrt(dx*dx + dy*dy); + dx /= mag; + dy /= mag; + if(i < j){ + dx = -dx; + dy = -dy; + } + // IMPROVE: use a goto here + // Find existing car path link + for(k = 0; k < m_numCarPathLinks; k++){ + if(m_carPathLinks[k].dirX == dx && + m_carPathLinks[k].dirY == dy && + m_carPathLinks[k].posX == posx && + m_carPathLinks[k].posY == posy){ + m_carPathConnections[m_numConnections] = k; + k = m_numCarPathLinks; + } + } + // k is m_numCarPathLinks+1 if we found one + if(k == m_numCarPathLinks){ + m_carPathLinks[m_numCarPathLinks].dirX = dx; + m_carPathLinks[m_numCarPathLinks].dirY = dy; + m_carPathLinks[m_numCarPathLinks].posX = posx; + m_carPathLinks[m_numCarPathLinks].posY = posy; + m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; + m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; + m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; + m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; + m_carPathConnections[m_numConnections] = m_numCarPathLinks++; + } + }else{ + // Crosses road + if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].flag & 1 || + objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].flag & 1) + m_connectionFlags[m_numConnections] |= ConnectionCrossRoad; + else + m_connectionFlags[m_numConnections] &= ~ConnectionCrossRoad; + } + + m_pathNodes[i].numLinks++; + m_numConnections++; + } + } + } + + if(type == PathTypeCar){ + done = 0; + // Set number of lanes for all nodes somehow + // very strange code + for(k = 0; !done && k < 10; k++){ + done = 1; + for(i = 0; i < m_numPathNodes; i++){ + if(m_pathNodes[i].numLinks != 2) + continue; + l1 = m_carPathConnections[m_pathNodes[i].firstLink]; + l2 = m_carPathConnections[m_pathNodes[i].firstLink+1]; + + if(m_carPathLinks[l1].numLeftLanes == -1 && + m_carPathLinks[l2].numLeftLanes != -1){ + done = 0; + if(m_carPathLinks[l2].pathNodeIndex == i){ + // why switch left and right here? + m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numRightLanes; + m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numLeftLanes; + }else{ + m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numLeftLanes; + m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numRightLanes; + } + m_carPathLinks[l1].pathNodeIndex = i; + }else if(m_carPathLinks[l1].numLeftLanes != -1 && + m_carPathLinks[l2].numLeftLanes == -1){ + done = 0; + if(m_carPathLinks[l1].pathNodeIndex == i){ + // why switch left and right here? + m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numRightLanes; + m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numLeftLanes; + }else{ + m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numLeftLanes; + m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numRightLanes; + } + m_carPathLinks[l2].pathNodeIndex = i; + }else if(m_carPathLinks[l1].numLeftLanes == -1 && + m_carPathLinks[l2].numLeftLanes == -1) + done = 0; + } + } + + // Fall back to default values for number of lanes + for(i = 0; i < m_numPathNodes; i++) + for(j = 0; j < m_pathNodes[i].numLinks; j++){ + k = m_carPathConnections[m_pathNodes[i].firstLink + j]; + if(m_carPathLinks[k].numLeftLanes < 0) + m_carPathLinks[k].numLeftLanes = 1; + if(m_carPathLinks[k].numRightLanes < 0) + m_carPathLinks[k].numRightLanes = 1; + } + } + + // Set flags for car nodes + if(type == PathTypeCar){ + do{ + cont = 0; + for(i = 0; i < m_numPathNodes; i++){ + m_pathNodes[i].flags &= ~PathNodeDisabled; + m_pathNodes[i].flags &= ~PathNodeBetweenLevels; + // See if node is a dead end, if so, we're not done yet + if((m_pathNodes[i].flags & PathNodeDeadEnd) == 0){ + k = 0; + for(j = 0; j < m_pathNodes[i].numLinks; j++) + if((m_pathNodes[m_connections[m_pathNodes[i].firstLink + j]].flags & PathNodeDeadEnd) == 0) + k++; + if(k < 2){ + m_pathNodes[i].flags |= PathNodeDeadEnd; + cont = 1; + } + } + } + }while(cont); + } + + // Remove isolated ped nodes + if(type == PathTypePed) + for(i = oldNumPathNodes; i < m_numPathNodes; i++){ + if(m_pathNodes[i].numLinks != 0) + continue; + + // Remove node + for(j = i; j < m_numPathNodes-1; j++) + m_pathNodes[j] = m_pathNodes[j+1]; + + // Fix links + for(j = oldNumLinks; j < m_numConnections; j++) + if(m_connections[j] >= i) + m_connections[j]--; + + // Also in treadables + for(j = 0; j < m_numMapObjects; j++) + for(k = 0; k < 12; k++){ + if(m_mapObjects[j]->m_nodeIndicesPeds[k] == i){ + // remove this one + for(l = k; l < 12-1; l++) + m_mapObjects[j]->m_nodeIndicesPeds[l] = m_mapObjects[j]->m_nodeIndicesPeds[l+1]; + m_mapObjects[j]->m_nodeIndicesPeds[11] = -1; + }else if(m_mapObjects[j]->m_nodeIndicesPeds[k] > i) + m_mapObjects[j]->m_nodeIndicesPeds[k]--; + } + + i--; + m_numPathNodes--; + } +} + +void +CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out) +{ + CVector pos; + pos.x = x / 16.0f; + pos.y = y / 16.0f; + pos.z = z / 16.0f; + *out = m_mapObjects[id]->GetMatrix() * pos; +} + +STARTPATCHES + InjectHook(0x429610, &CPathFind::PreparePathData, PATCH_JUMP); + InjectHook(0x429C20, &CPathFind::PreparePathDataForType, PATCH_JUMP); + InjectHook(0x42B810, &CPathFind::CountFloodFillGroups, PATCH_JUMP); +ENDPATCHES diff --git a/src/control/PathFind.h b/src/control/PathFind.h new file mode 100644 index 00000000..495c4a73 --- /dev/null +++ b/src/control/PathFind.h @@ -0,0 +1,129 @@ +#pragma once + +#include "Treadable.h" + +struct CPathNode +{ + CVector pos; + CPathNode *prev; //? + CPathNode *next; + int16 unknown; + int16 objectIndex; + int16 firstLink; + uint8 numLinks; + uint8 flags; + uint8 group; +/* VC: + int16 unk1; + int16 nextIndex; + int16 x; + int16 y; + int16 z; + int16 unknown; + int16 firstLink; + int8 width; + int8 group; + int8 numLinks : 4; + int8 bDeadEnd : 1; + int8 bTurnedOff : 1; // flag 8 in node info + int8 flagA40 : 1; // flag 20 in node info + int8 flagA80 : 1; // flag 4 in node info + int8 flagB1 : 1; // flag 10 in node info + int8 flagB2 : 1; // flag 2 in node info + int8 flagB4 : 1; + int8 speedLimit : 2; // speed limit + int8 flagB20 : 1; + int8 flagB40 : 1; + int8 flagB80 : 1; + int8 spawnRate : 4; + int8 flagsC : 4; +*/ +}; + +struct CCarPathLink +{ + float posX; + float posY; + float dirX; + float dirY; + int16 pathNodeIndex; + int8 numLeftLanes; + int8 numRightLanes; + int8 trafficLightType; + int8 field15; + // probably only padding + int8 field16; + int8 field17; +}; + +struct CPathInfoForObject +{ + int16 x; + int16 y; + int16 z; + int8 type; + int8 next; + int8 numLeftLanes; + int8 numRightLanes; + uint8 flag; +}; + +struct CTempNode +{ + CVector pos; + float dirX; + float dirY; + int16 link1; + int16 link2; + int8 numLeftLanes; + int8 numRightLanes; + int8 linkState; + // probably padding + int8 field1B; +}; + +struct CTempDetachedNode // unused +{ + uint8 foo[20]; +}; + +class CPathFind +{ +public: +/* For reference VC: + CPathNode pathNodes[9650]; + CCarPathLink m_carPathLinks[3500]; + CBuilding *m_mapObjects[1250]; + // 0x8000 is cross road flag + // 0x4000 is traffic light flag + uint16 m_connections[20400]; + uint8 m_distances[20400]; + int16 m_carPathConnections[20400]; +*/ + CPathNode m_pathNodes[4930]; + CCarPathLink m_carPathLinks[2076]; + CTreadable *m_mapObjects[1250]; + uint8 m_objectFlags[1250]; + int16 m_connections[10260]; + int16 m_distances[10260]; + uint8 m_connectionFlags[10260]; + int16 m_carPathConnections[10260]; + int32 m_numPathNodes; + int32 m_numCarPathNodes; + int32 m_numPedPathNodes; + int16 m_numMapObjects; + int16 m_numConnections; + int32 m_numCarPathLinks; + int32 h; + uint8 m_numGroups[2]; + CPathNode m_aExtraPaths[872]; + + void PreparePathData(void); + void CountFloodFillGroups(uint8 type); + void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, + float unk, CTempDetachedNode *detachednodes, int unused); + void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out); +}; +static_assert(sizeof(CPathFind) == 0x4c8f4, "CPathFind: error"); + +extern CPathFind &ThePaths; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp new file mode 100644 index 00000000..63aaa08e --- /dev/null +++ b/src/control/Pickups.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "Pickups.h" + +WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); } + +WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } diff --git a/src/control/Pickups.h b/src/control/Pickups.h new file mode 100644 index 00000000..d2c3628c --- /dev/null +++ b/src/control/Pickups.h @@ -0,0 +1,13 @@ +#pragma once + +class CPickups +{ +public: + static void RenderPickUpText(void); +}; + +class CPacManPickups +{ +public: + static void Render(void); +}; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp new file mode 100644 index 00000000..32e7dc0c --- /dev/null +++ b/src/control/Replay.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Replay.h" + +WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } \ No newline at end of file diff --git a/src/control/Replay.h b/src/control/Replay.h new file mode 100644 index 00000000..77e50403 --- /dev/null +++ b/src/control/Replay.h @@ -0,0 +1,7 @@ +#pragma once + +class CReplay +{ +public: + static void Display(void); +}; diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 11fa9ab2..439d1462 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -45,28 +45,28 @@ CEntity::GetIsOnScreenComplex(void) float minz = z + colmodel->boundingBox.min.z; float maxz = z + colmodel->boundingBox.max.z; boundBox[0].x = rect.left; - boundBox[0].y = rect.top; + boundBox[0].y = rect.bottom; boundBox[0].z = minz; boundBox[1].x = rect.left; - boundBox[1].y = rect.bottom; + boundBox[1].y = rect.top; boundBox[1].z = minz; boundBox[2].x = rect.right; - boundBox[2].y = rect.top; + boundBox[2].y = rect.bottom; boundBox[2].z = minz; boundBox[3].x = rect.right; - boundBox[3].y = rect.bottom; + boundBox[3].y = rect.top; boundBox[3].z = minz; boundBox[4].x = rect.left; - boundBox[4].y = rect.top; + boundBox[4].y = rect.bottom; boundBox[4].z = maxz; boundBox[5].x = rect.left; - boundBox[5].y = rect.bottom; + boundBox[5].y = rect.top; boundBox[5].z = maxz; boundBox[6].x = rect.right; - boundBox[6].y = rect.top; + boundBox[6].y = rect.bottom; boundBox[6].z = maxz; boundBox[7].x = rect.right; - boundBox[7].y = rect.bottom; + boundBox[7].y = rect.top; boundBox[7].z = maxz; return TheCamera.IsBoxVisible(boundBox, &TheCamera.GetCameraMatrix()); @@ -84,9 +84,9 @@ CEntity::Add(void) xstart = CWorld::GetSectorIndexX(bounds.left); xend = CWorld::GetSectorIndexX(bounds.right); xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f); - ystart = CWorld::GetSectorIndexY(bounds.bottom); - yend = CWorld::GetSectorIndexY(bounds.top); - ymid = CWorld::GetSectorIndexY((bounds.bottom + bounds.top)/2.0f); + ystart = CWorld::GetSectorIndexY(bounds.top); + yend = CWorld::GetSectorIndexY(bounds.bottom); + ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f); assert(xstart >= 0); assert(xend < NUMSECTORS_X); assert(ystart >= 0); @@ -144,9 +144,9 @@ CEntity::Remove(void) xstart = CWorld::GetSectorIndexX(bounds.left); xend = CWorld::GetSectorIndexX(bounds.right); xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f); - ystart = CWorld::GetSectorIndexY(bounds.bottom); - yend = CWorld::GetSectorIndexY(bounds.top); - ymid = CWorld::GetSectorIndexY((bounds.bottom + bounds.top)/2.0f); + ystart = CWorld::GetSectorIndexY(bounds.top); + yend = CWorld::GetSectorIndexY(bounds.bottom); + ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f); assert(xstart >= 0); assert(xend < NUMSECTORS_X); assert(ystart >= 0); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index dada5072..55eab951 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -27,9 +27,9 @@ CPhysical::Add(void) xstart = CWorld::GetSectorIndexX(bounds.left); xend = CWorld::GetSectorIndexX(bounds.right); xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f); - ystart = CWorld::GetSectorIndexY(bounds.bottom); - yend = CWorld::GetSectorIndexY(bounds.top); - ymid = CWorld::GetSectorIndexY((bounds.bottom + bounds.top)/2.0f); + ystart = CWorld::GetSectorIndexY(bounds.top); + yend = CWorld::GetSectorIndexY(bounds.bottom); + ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f); assert(xstart >= 0); assert(xend < NUMSECTORS_X); assert(ystart >= 0); @@ -92,9 +92,9 @@ CPhysical::RemoveAndAdd(void) xstart = CWorld::GetSectorIndexX(bounds.left); xend = CWorld::GetSectorIndexX(bounds.right); xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f); - ystart = CWorld::GetSectorIndexY(bounds.bottom); - yend = CWorld::GetSectorIndexY(bounds.top); - ymid = CWorld::GetSectorIndexY((bounds.bottom + bounds.top)/2.0f); + ystart = CWorld::GetSectorIndexY(bounds.top); + yend = CWorld::GetSectorIndexY(bounds.bottom); + ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f); assert(xstart >= 0); assert(xend < NUMSECTORS_X); assert(ystart >= 0); diff --git a/src/main.cpp b/src/main.cpp index 4f125098..ff254a1e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,112 +1,256 @@ -#include -#include #include "common.h" #include "patcher.h" +#include "RwHelper.h" +#include "Clouds.h" +#include "Draw.h" +#include "Sprite2d.h" #include "Renderer.h" -#include "debugmenu_public.h" +#include "Coronas.h" +#include "WaterLevel.h" +#include "Weather.h" +#include "Glass.h" +#include "WaterCannon.h" +#include "SpecialFX.h" +#include "Shadows.h" +#include "Skidmarks.h" +#include "Antennas.h" +#include "Rubbish.h" +#include "Particle.h" +#include "Pickups.h" +#include "WeaponEffects.h" +#include "PointLights.h" +#include "Fluff.h" +#include "Replay.h" +#include "Camera.h" +#include "World.h" +#include "Ped.h" +#include "Font.h" +#include "Pad.h" +#include "Hud.h" +#include "User.h" +#include "Messages.h" +#include "Darkel.h" +#include "Garages.h" +#include "MusicManager.h" +#include "Frontend.h" -void **rwengine = *(void***)0x5A10E1; - -RsGlobalType &RsGlobal = *(RsGlobalType*)0x8F4360; - -GlobalScene &Scene = *(GlobalScene*)0x726768; - -DebugMenuAPI gDebugMenuAPI; - -WRAPPER void *gtanew(uint32 sz) { EAXJMP(0x5A0690); } -WRAPPER void gtadelete(void *p) { EAXJMP(0x5A07E0); } - -// overload our own new/delete with GTA's functions -void *operator new(size_t sz) { return gtanew(sz); } -void operator delete(void *ptr) noexcept { gtadelete(ptr); } - -// Use our own implementation of rand, stolen from PS2 - -unsigned __int64 myrand_seed = 1; - -int -myrand(void) +// This is certainly a very useful function +void +DoRWRenderHorizon(void) { - myrand_seed = 0x5851F42D4C957F2D * myrand_seed + 1; - return ((myrand_seed >> 32) & 0x7FFFFFFF); + CClouds::RenderHorizon(); } void -mysrand(unsigned int seed) +RenderScene(void) { - myrand_seed = seed; + CClouds::Render(); + DoRWRenderHorizon(); + CRenderer::RenderRoads(); + CCoronas::RenderReflections(); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + CRenderer::RenderEverythingBarRoads(); + CRenderer::RenderBoats(); + DefinedState(); + CWaterLevel::RenderWater(); + CRenderer::RenderFadingInEntities(); + CRenderer::RenderVehiclesButNotBoats(); + CWeather::RenderRainStreaks(); } -// platform stuff -char* -GetUserDirectory(void) +void +RenderDebugShit(void) { - static char path[MAX_PATH]; - strcpy(path, "userfiles"); - mkdir(path); - return path; + // CTheScripts::RenderTheScriptDebugLines() } - -int (*open_script_orig)(const char *path, const char *mode); -int -open_script(const char *path, const char *mode) +void +RenderEffects(void) { - if(GetAsyncKeyState('D') & 0x8000) - return open_script_orig("main_d.scm", mode); -// if(GetAsyncKeyState('R') & 0x8000) - return open_script_orig("main_freeroam.scm", mode); - return open_script_orig(path, mode); + CGlass::Render(); + CWaterCannons::Render(); + CSpecialFX::Render(); + CShadows::RenderStaticShadows(); + CShadows::RenderStoredShadows(); + CSkidmarks::Render(); + CAntennas::Render(); + CRubbish::Render(); + CCoronas::Render(); + CParticle::Render(); + CPacManPickups::Render(); + CWeaponEffects::Render(); + CPointLights::RenderFogEffect(); + CMovingThings::Render(); + CRenderer::RenderFirstPersonVehicle(); } -int gDbgSurf; - -int (*RsEventHandler_orig)(int a, int b); -int -delayedPatches10(int a, int b) +void +Render2dStuff(void) { - if(DebugMenuLoad()){ - DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil); - DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil); - DebugMenuAddVarBool8("Debug", "Show Collision Polys", (int8*)&gbShowCollisionPolys, nil); - DebugMenuAddVarBool8("Debug", "Don't render Buildings", (int8*)&gbDontRenderBuildings, nil); - DebugMenuAddVarBool8("Debug", "Don't render Big Buildings", (int8*)&gbDontRenderBigBuildings, nil); - DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); - DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); - DebugMenuAddVar("Debug", "Dbg Surface", &gDbgSurf, nil, 1, 0, 34, nil); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); + + CReplay::Display(); + CPickups::RenderPickUpText(); + + if(TheCamera.m_WideScreenOn) + TheCamera.DrawBordersForWideScreen(); + + CPed *player = FindPlayerPed(); + int weaponType = 0; + if(player) + weaponType = player->GetWeapon()->m_eWeaponType; + + bool firstPersonWeapon = false; + int cammode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if(cammode == CCam::MODE_SNIPER || + cammode == CCam::MODE_SNIPER_RUN_AROUND || + cammode == CCam::MODE_ROCKET || + cammode == CCam::MODE_ROCKET_RUN_AROUND) + firstPersonWeapon = true; + + // Draw black border for sniper and rocket launcher + if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){ + CRGBA black(0, 0, 0, 255); + + // top and bottom strips + if(weaponType == WEAPONTYPE_ROCKETLAUNCHER){ + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH/2 - SCREEN_STRETCH_Y(180)), black); + CSprite2d::DrawRect(CRect(0.0f, SCREENH/2 + SCREEN_STRETCH_Y(170), SCREENW, SCREENH), black); + }else{ + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH/2 - SCREEN_STRETCH_Y(210)), black); + CSprite2d::DrawRect(CRect(0.0f, SCREENH/2 + SCREEN_STRETCH_Y(210), SCREENW, SCREENH), black); + } + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW/2 - SCREEN_STRETCH_X(210), SCREENH), black); + CSprite2d::DrawRect(CRect(SCREENW/2 + SCREEN_STRETCH_X(210), 0.0f, SCREENW, SCREENH), black); } - return RsEventHandler_orig(a, b); + MusicManager.DisplayRadioStationName(); +// TheConsole.Display(); +/* + if(CSceneEdit::m_bEditOn) + CSceneEdit::Draw(); + else +*/ + CHud::Draw(); + CUserDisplay::OnscnTimer.ProcessForDisplay(); + CMessages::Display(); + CDarkel::DrawMessages(); + CGarages::PrintMessages(); + CPad::PrintErrorMessage(); + CFont::DrawFonts(); } void -patch() +RenderMenus(void) { - StaticPatcher::Apply(); + if(FrontEndMenuManager.m_bMenuActive) + FrontEndMenuManager.DrawFrontEnd(); +} - Patch(0x46BC61+6, 1.0f); // car distance - InjectHook(0x59E460, printf, PATCH_JUMP); +bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4; +bool &StillToFadeOut = *(bool*)0x95CD99; +int32 &TimeStartedCountingForFade = *(int32*)0x9430EC; +int32 &TimeToStayFadedBeforeFadeOut = *(int32*)0x611564; - InterceptCall(&open_script_orig, open_script, 0x438869); +void +DoFade(void) +{ + if(CTimer::GetIsPaused()) + return; - InterceptCall(&RsEventHandler_orig, delayedPatches10, 0x58275E); -} + if(JustLoadedDontFadeInYet){ + JustLoadedDontFadeInYet = false; + TimeStartedCountingForFade = CTimer::GetTimeInMilliseconds(); + } -BOOL WINAPI -DllMain(HINSTANCE hInst, DWORD reason, LPVOID) -{ - if(reason == DLL_PROCESS_ATTACH){ + if(StillToFadeOut){ + if(CTimer::GetTimeInMilliseconds() - TimeStartedCountingForFade > TimeToStayFadedBeforeFadeOut){ + StillToFadeOut = false; + TheCamera.Fade(3.0f, 1); + TheCamera.ProcessFade(); + TheCamera.ProcessMusicFade(); + }else{ + TheCamera.SetFadeColour(0, 0, 0); + TheCamera.Fade(0.0f, 0); + TheCamera.ProcessFade(); + } + } - AllocConsole(); - freopen("CONIN$", "r", stdin); - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); + if(CDraw::FadeValue != 0 || CMenuManager::m_PrefsBrightness < 256){ + // LoadSplash - if (*(DWORD*)0x5C1E75 == 0xB85548EC) // 1.0 - patch(); - else - return FALSE; + CRGBA fadeColor; + CRect rect; + int fadeValue = CDraw::FadeValue; + float brightness = min(CMenuManager::m_PrefsBrightness, 256); + if(brightness <= 50) + brightness = 50; + if(FrontEndMenuManager.m_bMenuActive) + brightness = 256; + + if(TheCamera.m_FadeTargetIsSplashScreen) + fadeValue = 0; + + float fade = fadeValue + 256 - brightness; + if(fade == 0){ + fadeColor.r = 0; + fadeColor.g = 0; + fadeColor.b = 0; + fadeColor.a = 0; + }else{ + fadeColor.r = fadeValue * CDraw::FadeRed / fade; + fadeColor.g = fadeValue * CDraw::FadeGreen / fade; + fadeColor.b = fadeValue * CDraw::FadeBlue / fade; + int alpha = 255 - brightness*(256 - fadeValue)/256; + if(alpha < 0) + alpha = 0; + fadeColor.a = alpha; + } + + if(TheCamera.m_WideScreenOn){ + // what's this? + float y = SCREENH/2 * TheCamera.m_ScreenReductionPercentage/100.0f; + rect.left = 0.0f; + rect.right = SCREENW; + rect.top = y - 8.0f; + rect.bottom = SCREENH - y - 8.0f; + }else{ + rect.left = 0.0f; + rect.right = SCREENW; + rect.top = 0.0f; + rect.bottom = SCREENH; + } + CSprite2d::DrawRect(rect, fadeColor); + + if(CDraw::FadeValue != 0 && TheCamera.m_FadeTargetIsSplashScreen){ + fadeColor.r = 255; + fadeColor.g = 255; + fadeColor.b = 255; + fadeColor.a = CDraw::FadeValue; + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH), fadeColor, fadeColor, fadeColor, fadeColor); + } } +} - return TRUE; +void +Render2dStuffAfterFade(void) +{ + CHud::DrawAfterFade(); + CFont::DrawFonts(); } + + +STARTPATCHES + InjectHook(0x48E030, RenderScene, PATCH_JUMP); + InjectHook(0x48E080, RenderDebugShit, PATCH_JUMP); + InjectHook(0x48E090, RenderEffects, PATCH_JUMP); + InjectHook(0x48E0E0, Render2dStuff, PATCH_JUMP); + InjectHook(0x48E450, RenderMenus, PATCH_JUMP); + InjectHook(0x48D120, DoFade, PATCH_JUMP); + InjectHook(0x48E470, Render2dStuffAfterFade, PATCH_JUMP); +ENDPATCHES diff --git a/src/math/Rect.h b/src/math/Rect.h index 212645fa..d0824987 100644 --- a/src/math/Rect.h +++ b/src/math/Rect.h @@ -1,31 +1,29 @@ #pragma once -#pragma once - class CRect { public: float left; // x min - float top; // y max + float bottom; // y max float right; // x max - float bottom; // y min + float top; // y min CRect(void){ left = 1000000.0f; - bottom = 1000000.0f; + top = 1000000.0f; right = -1000000.0f; - top = -1000000.0f; + bottom = -1000000.0f; } - CRect(float l, float b, float r, float t){ + CRect(float l, float t, float r, float b){ left = l; - bottom = b; - right = r; top = t; + right = r; + bottom = b; } void ContainPoint(CVector const &v){ if(v.x < left) left = v.x; if(v.x > right) right = v.x; - if(v.y < bottom) bottom = v.y; - if(v.y > top) top = v.y; + if(v.y < top) top = v.y; + if(v.y > bottom) bottom = v.y; } }; diff --git a/src/math/Vector.h b/src/math/Vector.h index 3dba07ca..d89ca375 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -101,6 +101,11 @@ inline CVector operator*(const CVector &left, float right) return CVector(left.x * right, left.y * right, left.z * right); } +inline CVector operator*(float left, const CVector &right) +{ + return CVector(left * right.x, left * right.y, left * right.z); +} + inline CVector operator/(const CVector &left, float right) { return CVector(left.x / right, left.y / right, left.z / right); diff --git a/src/re3.cpp b/src/re3.cpp new file mode 100644 index 00000000..4f125098 --- /dev/null +++ b/src/re3.cpp @@ -0,0 +1,112 @@ +#include +#include +#include "common.h" +#include "patcher.h" +#include "Renderer.h" +#include "debugmenu_public.h" + +void **rwengine = *(void***)0x5A10E1; + +RsGlobalType &RsGlobal = *(RsGlobalType*)0x8F4360; + +GlobalScene &Scene = *(GlobalScene*)0x726768; + +DebugMenuAPI gDebugMenuAPI; + +WRAPPER void *gtanew(uint32 sz) { EAXJMP(0x5A0690); } +WRAPPER void gtadelete(void *p) { EAXJMP(0x5A07E0); } + +// overload our own new/delete with GTA's functions +void *operator new(size_t sz) { return gtanew(sz); } +void operator delete(void *ptr) noexcept { gtadelete(ptr); } + +// Use our own implementation of rand, stolen from PS2 + +unsigned __int64 myrand_seed = 1; + +int +myrand(void) +{ + myrand_seed = 0x5851F42D4C957F2D * myrand_seed + 1; + return ((myrand_seed >> 32) & 0x7FFFFFFF); +} + +void +mysrand(unsigned int seed) +{ + myrand_seed = seed; +} + +// platform stuff +char* +GetUserDirectory(void) +{ + static char path[MAX_PATH]; + strcpy(path, "userfiles"); + mkdir(path); + return path; +} + + +int (*open_script_orig)(const char *path, const char *mode); +int +open_script(const char *path, const char *mode) +{ + if(GetAsyncKeyState('D') & 0x8000) + return open_script_orig("main_d.scm", mode); +// if(GetAsyncKeyState('R') & 0x8000) + return open_script_orig("main_freeroam.scm", mode); + return open_script_orig(path, mode); +} + +int gDbgSurf; + +int (*RsEventHandler_orig)(int a, int b); +int +delayedPatches10(int a, int b) +{ + if(DebugMenuLoad()){ + DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil); + DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil); + DebugMenuAddVarBool8("Debug", "Show Collision Polys", (int8*)&gbShowCollisionPolys, nil); + DebugMenuAddVarBool8("Debug", "Don't render Buildings", (int8*)&gbDontRenderBuildings, nil); + DebugMenuAddVarBool8("Debug", "Don't render Big Buildings", (int8*)&gbDontRenderBigBuildings, nil); + DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); + DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); + DebugMenuAddVar("Debug", "Dbg Surface", &gDbgSurf, nil, 1, 0, 34, nil); + } + + return RsEventHandler_orig(a, b); +} + +void +patch() +{ + StaticPatcher::Apply(); + + Patch(0x46BC61+6, 1.0f); // car distance + InjectHook(0x59E460, printf, PATCH_JUMP); + + InterceptCall(&open_script_orig, open_script, 0x438869); + + InterceptCall(&RsEventHandler_orig, delayedPatches10, 0x58275E); +} + +BOOL WINAPI +DllMain(HINSTANCE hInst, DWORD reason, LPVOID) +{ + if(reason == DLL_PROCESS_ATTACH){ + + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + + if (*(DWORD*)0x5C1E75 == 0xB85548EC) // 1.0 + patch(); + else + return FALSE; + } + + return TRUE; +} diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 39b85246..ee3f3da1 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include "patcher.h" #include "Coronas.h" RwTexture **gpCoronaTexture = (RwTexture**)0x5FAF44; //[9] @@ -8,3 +9,6 @@ float &CCoronas::SunScreenX = *(float*)0x8F4358; float &CCoronas::SunScreenY = *(float*)0x8F4354; bool &CCoronas::bSmallMoon = *(bool*)0x95CD49; bool &CCoronas::SunBlockedByClouds = *(bool*)0x95CD73; + +WRAPPER void CCoronas::Render(void) { EAXJMP(0x4F8FB0); } +WRAPPER void CCoronas::RenderReflections(void) { EAXJMP(0x4F9B40); } diff --git a/src/render/Coronas.h b/src/render/Coronas.h index 4ec7dd3b..796983bd 100644 --- a/src/render/Coronas.h +++ b/src/render/Coronas.h @@ -10,4 +10,7 @@ public: static float &SunScreenX; static bool &bSmallMoon; static bool &SunBlockedByClouds; + + static void Render(void); + static void RenderReflections(void); }; diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index 6244c3fa..7c5a48ad 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -6,6 +6,11 @@ float &CDraw::ms_fNearClipZ = *(float*)0x8E2DC4; float &CDraw::ms_fFarClipZ = *(float*)0x9434F0; float &CDraw::ms_fFOV = *(float*)0x5FBC6C; +uint8 &CDraw::FadeValue = *(uint8*)0x95CD68; +uint8 &CDraw::FadeRed = *(uint8*)0x95CD90; +uint8 &CDraw::FadeGreen = *(uint8*)0x95CD71; +uint8 &CDraw::FadeBlue = *(uint8*)0x95CD53; + static float hFov2vFov(float hfov) { float w = SCREENW; diff --git a/src/render/Draw.h b/src/render/Draw.h index 84ec7ed3..408c41b0 100644 --- a/src/render/Draw.h +++ b/src/render/Draw.h @@ -7,6 +7,11 @@ private: static float &ms_fFarClipZ; static float &ms_fFOV; public: + static uint8 &FadeValue; + static uint8 &FadeRed; + static uint8 &FadeGreen; + static uint8 &FadeBlue; + static void SetNearClipZ(float nearclip) { ms_fNearClipZ = nearclip; } static float GetNearClipZ(void) { return ms_fNearClipZ; } static void SetFarClipZ(float farclip) { ms_fFarClipZ = farclip; } diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp new file mode 100644 index 00000000..b1b8aa92 --- /dev/null +++ b/src/render/Fluff.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Fluff.h" + +WRAPPER void CMovingThings::Render(void) { EAXJMP(0x4FF210); } diff --git a/src/render/Fluff.h b/src/render/Fluff.h new file mode 100644 index 00000000..33532efa --- /dev/null +++ b/src/render/Fluff.h @@ -0,0 +1,7 @@ +#pragma once + +class CMovingThings +{ +public: + static void Render(void); +}; diff --git a/src/render/Font.cpp b/src/render/Font.cpp index b145bf38..2130fb95 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -341,22 +341,22 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, uint16 *s) if(Details.backgroundOnlyText){ rect->left = xstart - maxlength/2 - 4.0f; rect->right = xstart + maxlength/2 + 4.0f; - rect->top = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + + rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f; - rect->bottom = ystart - 2.0f; + rect->top = ystart - 2.0f; }else{ rect->left = xstart - Details.centreSize*0.5f - 4.0f; rect->right = xstart + Details.centreSize*0.5f + 4.0f; - rect->top = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + + rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f; - rect->bottom = ystart - 2.0f; + rect->top = ystart - 2.0f; } }else{ rect->left = xstart - 4.0f; rect->right = Details.wrapX; // WTF? - rect->top = ystart - 4.0f + 4.0f; - rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + + rect->bottom = ystart - 4.0f + 4.0f; + rect->top = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f + 2.0f; } } diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp new file mode 100644 index 00000000..aba8f9e0 --- /dev/null +++ b/src/render/Glass.cpp @@ -0,0 +1,17 @@ +#include "common.h" +#include "patcher.h" +#include "Glass.h" + +WRAPPER void +CGlass::WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo) +{ + EAXJMP(0x503F10); +} + +WRAPPER void +CGlass::WindowRespondsToSoftCollision(CEntity *ent, float amount) +{ + EAXJMP(0x504630); +} + +WRAPPER void CGlass::Render(void) { EAXJMP(0x502350); } diff --git a/src/render/Glass.h b/src/render/Glass.h new file mode 100644 index 00000000..460c4548 --- /dev/null +++ b/src/render/Glass.h @@ -0,0 +1,11 @@ +#pragma once + +class CEntity; + +class CGlass +{ +public: + static void WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo); + static void WindowRespondsToSoftCollision(CEntity *ent, float amount); + static void Render(void); +}; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp new file mode 100644 index 00000000..f3211fd6 --- /dev/null +++ b/src/render/Hud.cpp @@ -0,0 +1,6 @@ +#include "common.h" +#include "patcher.h" +#include "Hud.h" + +WRAPPER void CHud::Draw(void) { EAXJMP(0x5052A0); } +WRAPPER void CHud::DrawAfterFade(void) { EAXJMP(0x509030); } diff --git a/src/render/Hud.h b/src/render/Hud.h new file mode 100644 index 00000000..72d3c6ad --- /dev/null +++ b/src/render/Hud.h @@ -0,0 +1,8 @@ +#pragma once + +class CHud +{ +public: + static void Draw(void); + static void DrawAfterFade(void); +}; diff --git a/src/render/Lights.cpp b/src/render/Lights.cpp index 6962af4d..7954a07d 100644 --- a/src/render/Lights.cpp +++ b/src/render/Lights.cpp @@ -7,7 +7,7 @@ #include "Coronas.h" #include "Weather.h" #include "CullZones.h" -#include "MenuManager.h" +#include "Frontend.h" RpLight *&pAmbient = *(RpLight**)0x885B6C; RpLight *&pDirect = *(RpLight**)0x880F7C; diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index 18ea4c6c..bd4f7696 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -1853,18 +1853,18 @@ void CParticle::AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatr } STARTPATCHES +return; // causes crash, out temporarily //InjectHook(0x50C410, &CParticle::ctor, PATCH_JUMP); //InjectHook(0x50C420, &CParticle::dtor, PATCH_JUMP); InjectHook(0x50C430, CParticle::ReloadConfig, PATCH_JUMP); InjectHook(0x50C570, CParticle::Initialise, PATCH_JUMP); InjectHook(0x50CF40, CParticle::Shutdown, PATCH_JUMP); //InjectHook(0x50D140, CParticle::AddParticle, PATCH_JUMP); - InjectHook(0x50D190, (CParticle* (__cdecl *)(tParticleType, CVector const&, CVector const&, CEntity*, float, RwRGBA const&, int, int, int, int))CParticle::AddParticle, PATCH_JUMP); + InjectHook(0x50D190, (CParticle *(*)(tParticleType, CVector const&, CVector const&, CEntity*, float, RwRGBA const&, int, int, int, int))CParticle::AddParticle, PATCH_JUMP); InjectHook(0x50DCF0, CParticle::Update, PATCH_JUMP); InjectHook(0x50EE20, CParticle::Render, PATCH_JUMP); InjectHook(0x50F6E0, CParticle::RemovePSystem, PATCH_JUMP); InjectHook(0x50F720, CParticle::RemoveParticle, PATCH_JUMP); InjectHook(0x50F760, CParticle::AddJetExplosion, PATCH_JUMP); InjectHook(0x50FAA0, CParticle::AddYardieDoorSmoke, PATCH_JUMP); - -ENDPATCHES \ No newline at end of file +ENDPATCHES diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp new file mode 100644 index 00000000..8496d8aa --- /dev/null +++ b/src/render/PointLights.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "PointLights.h" + +WRAPPER void CPointLights::RenderFogEffect(void) { EAXJMP(0x510C30); } diff --git a/src/render/PointLights.h b/src/render/PointLights.h new file mode 100644 index 00000000..d20fbb7e --- /dev/null +++ b/src/render/PointLights.h @@ -0,0 +1,7 @@ +#pragma once + +class CPointLights +{ +public: + static void RenderFogEffect(void); +}; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f8703c01..70002dcf 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -602,9 +602,9 @@ CRenderer::ScanWorld(void) if(x1 < 0) x1 = 0; x2 = CWorld::GetSectorIndexX(rect.right); if(x2 >= NUMSECTORS_X-1) x2 = NUMSECTORS_X-1; - y1 = CWorld::GetSectorIndexY(rect.bottom); + y1 = CWorld::GetSectorIndexY(rect.top); if(y1 < 0) y1 = 0; - y2 = CWorld::GetSectorIndexY(rect.top); + y2 = CWorld::GetSectorIndexY(rect.bottom); if(y2 >= NUMSECTORS_Y-1) y2 = NUMSECTORS_Y-1; for(; x1 <= x2; x1++) for(int y = y1; y <= y2; y++) @@ -713,9 +713,9 @@ CRenderer::RequestObjectsInFrustum(void) if(x1 < 0) x1 = 0; x2 = CWorld::GetSectorIndexX(rect.right); if(x2 >= NUMSECTORS_X-1) x2 = NUMSECTORS_X-1; - y1 = CWorld::GetSectorIndexY(rect.bottom); + y1 = CWorld::GetSectorIndexY(rect.top); if(y1 < 0) y1 = 0; - y2 = CWorld::GetSectorIndexY(rect.top); + y2 = CWorld::GetSectorIndexY(rect.bottom); if(y2 >= NUMSECTORS_Y-1) y2 = NUMSECTORS_Y-1; for(; x1 <= x2; x1++) for(int y = y1; y <= y2; y++) diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp new file mode 100644 index 00000000..975f2554 --- /dev/null +++ b/src/render/Rubbish.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Rubbish.h" + +WRAPPER void CRubbish::Render(void) { EAXJMP(0x512190); } diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h new file mode 100644 index 00000000..f4f976e9 --- /dev/null +++ b/src/render/Rubbish.h @@ -0,0 +1,7 @@ +#pragma once + +class CRubbish +{ +public: + static void Render(void); +}; diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index ead84e92..587dda99 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -1,7 +1,11 @@ #include "common.h" +#include "patcher.h" #include "Shadows.h" void CShadows::AddPermanentShadow(unsigned char ShadowType, RwTexture* pTexture, CVector* pPosn, float fX1, float fY1, float fX2, float fY2, short nTransparency, unsigned char nRed, unsigned char nGreen, unsigned char nBlue, float fZDistance, unsigned int nTime, float fScale) { ((void (__cdecl *)(unsigned char, RwTexture*, CVector*, float, float, float, float, short, unsigned char, unsigned char, unsigned char, float, unsigned int, float))0x56EC50)(ShadowType, pTexture, pPosn, fX1, fY1, fX2, fY2, nTransparency, nRed, nGreen, nBlue, fZDistance, nTime, fScale); } + +WRAPPER void CShadows::RenderStaticShadows(void) { EAXJMP(0x5145F0); } +WRAPPER void CShadows::RenderStoredShadows(void) { EAXJMP(0x514010); } diff --git a/src/render/Shadows.h b/src/render/Shadows.h index 3c7b4981..0a475f6f 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -5,5 +5,7 @@ struct RwTexture; class CShadows { public: - static void AddPermanentShadow(unsigned char ShadowType, RwTexture* pTexture, CVector* pPosn, float fX1, float fY1, float fX2, float fY2, short nTransparency, unsigned char nRed, unsigned char nGreen, unsigned char nBlue, float fZDistance, unsigned int nTime, float fScale); + static void AddPermanentShadow(uint8 ShadowType, RwTexture* pTexture, CVector* pPosn, float fX1, float fY1, float fX2, float fY2, short nTransparency, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale); + static void RenderStaticShadows(void); + static void RenderStoredShadows(void); }; \ No newline at end of file diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp new file mode 100644 index 00000000..678e1cdc --- /dev/null +++ b/src/render/Skidmarks.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Skidmarks.h" + +WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); } diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h new file mode 100644 index 00000000..dcd61652 --- /dev/null +++ b/src/render/Skidmarks.h @@ -0,0 +1,7 @@ +#pragma once + +class CSkidmarks +{ +public: + static void Render(void); +}; diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp new file mode 100644 index 00000000..3aa60f2f --- /dev/null +++ b/src/render/SpecialFX.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "SpecialFX.h" + +WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); } diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h new file mode 100644 index 00000000..ffa2a90a --- /dev/null +++ b/src/render/SpecialFX.h @@ -0,0 +1,7 @@ +#pragma once + +class CSpecialFX +{ +public: + static void Render(void); +}; diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 900b4dba..2b669c87 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -377,7 +377,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, co recipz = m_fRecipNearClipPlane; RwIm2DVertexSetScreenX(&verts[0], r.left); - RwIm2DVertexSetScreenY(&verts[0], r.bottom); + RwIm2DVertexSetScreenY(&verts[0], r.top); RwIm2DVertexSetScreenZ(&verts[0], screenz); RwIm2DVertexSetCameraZ(&verts[0], z); RwIm2DVertexSetRecipCameraZ(&verts[0], recipz); @@ -386,7 +386,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, co RwIm2DVertexSetV(&verts[0], 0.0f, recipz); RwIm2DVertexSetScreenX(&verts[1], r.right); - RwIm2DVertexSetScreenY(&verts[1], r.bottom); + RwIm2DVertexSetScreenY(&verts[1], r.top); RwIm2DVertexSetScreenZ(&verts[1], screenz); RwIm2DVertexSetCameraZ(&verts[1], z); RwIm2DVertexSetRecipCameraZ(&verts[1], recipz); @@ -395,7 +395,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, co RwIm2DVertexSetV(&verts[1], 0.0f, recipz); RwIm2DVertexSetScreenX(&verts[2], r.right); - RwIm2DVertexSetScreenY(&verts[2], r.top); + RwIm2DVertexSetScreenY(&verts[2], r.bottom); RwIm2DVertexSetScreenZ(&verts[2], screenz); RwIm2DVertexSetCameraZ(&verts[2], z); RwIm2DVertexSetRecipCameraZ(&verts[2], recipz); @@ -404,7 +404,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, co RwIm2DVertexSetV(&verts[2], 1.0f, recipz); RwIm2DVertexSetScreenX(&verts[3], r.left); - RwIm2DVertexSetScreenY(&verts[3], r.top); + RwIm2DVertexSetScreenY(&verts[3], r.bottom); RwIm2DVertexSetScreenZ(&verts[3], screenz); RwIm2DVertexSetCameraZ(&verts[3], z); RwIm2DVertexSetRecipCameraZ(&verts[3], recipz); @@ -413,7 +413,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, co RwIm2DVertexSetV(&verts[3], 1.0f, recipz); RwIm2DVertexSetScreenX(&verts[4], r.left); - RwIm2DVertexSetScreenY(&verts[4], r.bottom); + RwIm2DVertexSetScreenY(&verts[4], r.top); RwIm2DVertexSetScreenZ(&verts[4], screenz); RwIm2DVertexSetCameraZ(&verts[4], z); RwIm2DVertexSetRecipCameraZ(&verts[4], recipz); @@ -422,7 +422,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, co RwIm2DVertexSetV(&verts[4], 0.0f, recipz); RwIm2DVertexSetScreenX(&verts[5], r.right); - RwIm2DVertexSetScreenY(&verts[5], r.top); + RwIm2DVertexSetScreenY(&verts[5], r.bottom); RwIm2DVertexSetScreenZ(&verts[5], screenz); RwIm2DVertexSetCameraZ(&verts[5], z); RwIm2DVertexSetRecipCameraZ(&verts[5], recipz); diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index ff6cd0db..3c699650 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -174,7 +174,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C // | / | // 3---2 RwIm2DVertexSetScreenX(&maVertices[0], r.left); - RwIm2DVertexSetScreenY(&maVertices[0], r.bottom); + RwIm2DVertexSetScreenY(&maVertices[0], r.top); RwIm2DVertexSetScreenZ(&maVertices[0], screenz); RwIm2DVertexSetCameraZ(&maVertices[0], z); RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz); @@ -183,7 +183,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwIm2DVertexSetV(&maVertices[0], 0.0f, recipz); RwIm2DVertexSetScreenX(&maVertices[1], r.right); - RwIm2DVertexSetScreenY(&maVertices[1], r.bottom); + RwIm2DVertexSetScreenY(&maVertices[1], r.top); RwIm2DVertexSetScreenZ(&maVertices[1], screenz); RwIm2DVertexSetCameraZ(&maVertices[1], z); RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz); @@ -192,7 +192,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwIm2DVertexSetV(&maVertices[1], 0.0f, recipz); RwIm2DVertexSetScreenX(&maVertices[2], r.right); - RwIm2DVertexSetScreenY(&maVertices[2], r.top); + RwIm2DVertexSetScreenY(&maVertices[2], r.bottom); RwIm2DVertexSetScreenZ(&maVertices[2], screenz); RwIm2DVertexSetCameraZ(&maVertices[2], z); RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz); @@ -201,7 +201,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwIm2DVertexSetV(&maVertices[2], 1.0f, recipz); RwIm2DVertexSetScreenX(&maVertices[3], r.left); - RwIm2DVertexSetScreenY(&maVertices[3], r.top); + RwIm2DVertexSetScreenY(&maVertices[3], r.bottom); RwIm2DVertexSetScreenZ(&maVertices[3], screenz); RwIm2DVertexSetCameraZ(&maVertices[3], z); RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz); @@ -225,7 +225,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C // | / | // 3---2 RwIm2DVertexSetScreenX(&maVertices[0], r.left); - RwIm2DVertexSetScreenY(&maVertices[0], r.bottom); + RwIm2DVertexSetScreenY(&maVertices[0], r.top); RwIm2DVertexSetScreenZ(&maVertices[0], screenz); RwIm2DVertexSetCameraZ(&maVertices[0], z); RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz); @@ -234,7 +234,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwIm2DVertexSetV(&maVertices[0], v0, recipz); RwIm2DVertexSetScreenX(&maVertices[1], r.right); - RwIm2DVertexSetScreenY(&maVertices[1], r.bottom); + RwIm2DVertexSetScreenY(&maVertices[1], r.top); RwIm2DVertexSetScreenZ(&maVertices[1], screenz); RwIm2DVertexSetCameraZ(&maVertices[1], z); RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz); @@ -243,7 +243,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwIm2DVertexSetV(&maVertices[1], v1, recipz); RwIm2DVertexSetScreenX(&maVertices[2], r.right); - RwIm2DVertexSetScreenY(&maVertices[2], r.top); + RwIm2DVertexSetScreenY(&maVertices[2], r.bottom); RwIm2DVertexSetScreenZ(&maVertices[2], screenz); RwIm2DVertexSetCameraZ(&maVertices[2], z); RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz); @@ -252,7 +252,7 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwIm2DVertexSetV(&maVertices[2], v2, recipz); RwIm2DVertexSetScreenX(&maVertices[3], r.left); - RwIm2DVertexSetScreenY(&maVertices[3], r.top); + RwIm2DVertexSetScreenY(&maVertices[3], r.bottom); RwIm2DVertexSetScreenZ(&maVertices[3], screenz); RwIm2DVertexSetCameraZ(&maVertices[3], z); RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz); @@ -358,7 +358,7 @@ CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, con recipz = RecipNearClip; RwIm2DVertexSetScreenX(&verts[0], r.left); - RwIm2DVertexSetScreenY(&verts[0], r.bottom); + RwIm2DVertexSetScreenY(&verts[0], r.top); RwIm2DVertexSetScreenZ(&verts[0], screenz); RwIm2DVertexSetCameraZ(&verts[0], z); RwIm2DVertexSetRecipCameraZ(&verts[0], recipz); @@ -367,7 +367,7 @@ CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, con RwIm2DVertexSetV(&verts[0], v0, recipz); RwIm2DVertexSetScreenX(&verts[1], r.left); - RwIm2DVertexSetScreenY(&verts[1], r.top); + RwIm2DVertexSetScreenY(&verts[1], r.bottom); RwIm2DVertexSetScreenZ(&verts[1], screenz); RwIm2DVertexSetCameraZ(&verts[1], z); RwIm2DVertexSetRecipCameraZ(&verts[1], recipz); @@ -376,7 +376,7 @@ CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, con RwIm2DVertexSetV(&verts[1], v2, recipz); RwIm2DVertexSetScreenX(&verts[2], r.right); - RwIm2DVertexSetScreenY(&verts[2], r.top); + RwIm2DVertexSetScreenY(&verts[2], r.bottom); RwIm2DVertexSetScreenZ(&verts[2], screenz); RwIm2DVertexSetCameraZ(&verts[2], z); RwIm2DVertexSetRecipCameraZ(&verts[2], recipz); @@ -385,7 +385,7 @@ CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, con RwIm2DVertexSetV(&verts[2], v3, recipz); RwIm2DVertexSetScreenX(&verts[3], r.left); - RwIm2DVertexSetScreenY(&verts[3], r.bottom); + RwIm2DVertexSetScreenY(&verts[3], r.top); RwIm2DVertexSetScreenZ(&verts[3], screenz); RwIm2DVertexSetCameraZ(&verts[3], z); RwIm2DVertexSetRecipCameraZ(&verts[3], recipz); @@ -394,7 +394,7 @@ CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, con RwIm2DVertexSetV(&verts[3], v0, recipz); RwIm2DVertexSetScreenX(&verts[4], r.right); - RwIm2DVertexSetScreenY(&verts[4], r.top); + RwIm2DVertexSetScreenY(&verts[4], r.bottom); RwIm2DVertexSetScreenZ(&verts[4], screenz); RwIm2DVertexSetCameraZ(&verts[4], z); RwIm2DVertexSetRecipCameraZ(&verts[4], recipz); @@ -403,7 +403,7 @@ CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, con RwIm2DVertexSetV(&verts[4], v3, recipz); RwIm2DVertexSetScreenX(&verts[5], r.right); - RwIm2DVertexSetScreenY(&verts[5], r.bottom); + RwIm2DVertexSetScreenY(&verts[5], r.top); RwIm2DVertexSetScreenZ(&verts[5], screenz); RwIm2DVertexSetCameraZ(&verts[5], z); RwIm2DVertexSetRecipCameraZ(&verts[5], recipz); diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp new file mode 100644 index 00000000..afb40f6f --- /dev/null +++ b/src/render/WaterCannon.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "WaterCannon.h" + +WRAPPER void CWaterCannons::Render(void) { EAXJMP(0x522550); } diff --git a/src/render/WaterCannon.h b/src/render/WaterCannon.h new file mode 100644 index 00000000..1a18e75f --- /dev/null +++ b/src/render/WaterCannon.h @@ -0,0 +1,7 @@ +#pragma once + +class CWaterCannons +{ +public: + static void Render(void); +}; diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp new file mode 100644 index 00000000..866847b3 --- /dev/null +++ b/src/render/WaterLevel.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "WaterLevel.h" + +WRAPPER void CWaterLevel::RenderWater(void) { EAXJMP(0x5554E0); } diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h new file mode 100644 index 00000000..70a2ba97 --- /dev/null +++ b/src/render/WaterLevel.h @@ -0,0 +1,7 @@ +#pragma once + +class CWaterLevel +{ +public: + static void RenderWater(void); +}; diff --git a/src/render/WeaponEffects.cpp b/src/render/WeaponEffects.cpp new file mode 100644 index 00000000..a1a6d25a --- /dev/null +++ b/src/render/WeaponEffects.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "WeaponEffects.h" + +WRAPPER void CWeaponEffects::Render(void) { EAXJMP(0x564D70); } diff --git a/src/render/WeaponEffects.h b/src/render/WeaponEffects.h new file mode 100644 index 00000000..63c8fd7d --- /dev/null +++ b/src/render/WeaponEffects.h @@ -0,0 +1,7 @@ +#pragma once + +class CWeaponEffects +{ +public: + static void Render(void); +}; -- cgit v1.2.3