first commit

revert-856-patch-2
aap 4 years ago
commit 600bf03514

@ -0,0 +1,101 @@
# Intro
The aim of this project is to reverse GTA III for PC by replacing
parts of the game [one by one](https://en.wikipedia.org/wiki/Ship_of_Theseus)
such that we have a working game at all times.
# Strategy
A good approach is to start at the fringes of the code base,
i.e. classes that don't depend on code that we don't have reversed yet.
If a function uses only few unreversed functions that would be inconvenient
to reverse at the time, calling the original functions is acceptable.
# Progress
This is a list of some things that have been reversed to some non-trivial extent.
Not everything is listed, check the code.
```
CPool
CTxdStore
CVector
CVector2D
CMatrix
CModelInfo
CBaseModelInfo
CSimpleModelInfo
CTimeModelInfo
CClumpModelInfo
CPedModelInfo
CVehicleModelInfo
CVisibilityPlugins
CRenderer
CEntity
CPhysical
CCollision
CCullZones
CTheZones
CPathFind
```
# Low hanging fruit
There are a couple of things that have been reversed for other projects
already that could probably be put into this project without too much effort.
Again, the list is not complete:
* Animation (https://github.com/aap/iii_anim)
* File Loader (https://github.com/aap/librwgta/tree/master/tools/IIItest)
* ...
# Coding style
I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style),
but realize that this is not the most popular style, so I'm willing to compromise.
Try not to deviate too much so the code will look similar across the whole project.
To give examples, these two styles (or anything in between) are fine:
```
type
functionname(args)
{
if(a == b){
s1;
s2;
}
if(x != y)
s3;
}
type functionname(args)
{
if (a == b) {
s1;
s2;
}
if (x != y)
s3;
}
```
This one (or anything more extreme) is heavily discouraged:
```
type functionname ( args )
{
if ( a == b )
{
s1;
s2;
}
if ( x != y )
{
s3;
}
}
```
Indentation is done with TABS.

@ -0,0 +1 @@
premake5 vs2015

Binary file not shown.

@ -0,0 +1,38 @@
workspace "re3"
configurations { "Release","Debug" }
location "build"
files { "src/*.*" }
files { "src/math/*.*" }
files { "src/modelinfo/*.*" }
files { "src/entities/*.*" }
files { "src/render/*.*" }
includedirs { "src", "src/modelinfo" }
includedirs { "src", "src/entities" }
includedirs { "src", "src/render" }
includedirs { os.getenv("RWSDK33") }
project "re3"
kind "SharedLib"
language "C++"
targetname "re3"
targetdir "bin/%{cfg.buildcfg}"
targetextension ".dll"
characterset ("MBCS")
filter "configurations:Debug"
defines { "DEBUG" }
flags { "StaticRuntime" }
symbols "On"
debugdir "C:/Users/aap/games/gta3_re"
debugcommand "C:/Users/aap/games/gta3_re/gta3.exe"
postbuildcommands "copy /y \"$(TargetPath)\" \"C:\\Users\\aap\\games\\gta3_re\\plugins\\re3.dll\""
filter "configurations:Release"
defines { "NDEBUG" }
optimize "On"
flags { "StaticRuntime" }
debugdir "C:/Users/aap/games/gta3_re"
debugcommand "C:/Users/aap/games/gta3_re/gta3.exe"
postbuildcommands "copy /y \"$(TargetPath)\" \"C:\\Users\\aap\\games\\gta3_re\\plugins\\re3.dll\""

@ -0,0 +1,63 @@
#include "common.h"
#include "patcher.h"
#include "Draw.h"
#include "Camera.h"
CCamera &TheCamera = *(CCamera*)0x6FACF8;
bool
CCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)
{
RwV3d c;
c = *(RwV3d*)&center;
RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
if(c.y + radius < CDraw::GetNearClipZ()) return false;
if(c.y - radius > CDraw::GetFarClipZ()) return false;
if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > radius) return false;
if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > radius) return false;
if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > radius) return false;
if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > radius) return false;
return true;
}
bool
CCamera::IsPointVisible(const CVector &center, const CMatrix *mat)
{
RwV3d c;
c = *(RwV3d*)&center;
RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
if(c.y < CDraw::GetNearClipZ()) return false;
if(c.y > CDraw::GetFarClipZ()) return false;
if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > 0.0f) return false;
if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > 0.0f) return false;
if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > 0.0f) return false;
if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > 0.0f) return false;
return true;
}
bool
CCamera::IsBoxVisible(RwV3d *box, const CMatrix *mat)
{
int i;
int frustumTests[6] = { 0 };
RwV3dTransformPoints(box, box, 8, &mat->m_matrix);
for(i = 0; i < 8; i++){
if(box[i].y < CDraw::GetNearClipZ()) frustumTests[0]++;
if(box[i].y > CDraw::GetFarClipZ()) frustumTests[1]++;
if(box[i].x*m_vecFrustumNormals[0].x + box[i].y*m_vecFrustumNormals[0].y > 0.0f) frustumTests[2]++;
if(box[i].x*m_vecFrustumNormals[1].x + box[i].y*m_vecFrustumNormals[1].y > 0.0f) frustumTests[3]++;
// Why not test z?
// if(box[i].y*m_vecFrustumNormals[2].y + box[i].z*m_vecFrustumNormals[2].z > 0.0f) frustumTests[4]++;
// if(box[i].y*m_vecFrustumNormals[3].y + box[i].z*m_vecFrustumNormals[3].z > 0.0f) frustumTests[5]++;
}
for(i = 0; i < 6; i++)
if(frustumTests[i] == 8)
return false; // Box is completely outside of one plane
return true;
}
STARTPATCHES
InjectHook(0x42C760, &CCamera::IsSphereVisible, PATCH_JUMP);
ENDPATCHES

@ -0,0 +1,420 @@
#pragma once
#include "Placeable.h"
class CEntity;
class CPed;
class CAutomobile;
#define NUMBER_OF_VECTORS_FOR_AVERAGE 2
struct CCam
{
enum CamMode
{
MODE_TOPDOWN1 = 1,
MODE_TOPDOWN2,
MODE_BEHINDCAR,
MODE_FOLLOWPED,
MODE_AIMING,
MODE_DEBUG,
MODE_SNIPER,
MODE_ROCKET,
MODE_MODELVIEW,
MODE_BILL,
MODE_SYPHON,
MODE_CIRCLE,
MODE_CHEESYZOOM,
MODE_WHEELCAM,
MODE_FIXED,
MODE_FIRSTPERSON,
MODE_FLYBY,
MODE_CAMONASTRING,
MODE_REACTIONCAM,
MODE_FOLLOWPEDWITHBINDING,
MODE_CHRISWITHBINDINGPLUSROTATION,
MODE_BEHINDBOAT,
MODE_PLAYERFALLENWATER,
MODE_CAMONTRAINROOF,
MODE_CAMRUNNINGSIDETRAIN,
MODE_BLOODONTHETRACKS,
MODE_IMTHEPASSENGERWOOWOO,
MODE_SYPHONCRIMINFRONT,
MODE_PEDSDEADBABY,
MODE_CUSHYPILLOWSARSE,
MODE_LOOKATCARS,
MODE_ARRESTCAMONE,
MODE_ARRESTCAMTWO,
MODE_M16FIRSTPERSON_34,
MODE_SPECIALFIXEDFORSYPHON,
MODE_FIGHT,
MODE_TOPDOWNPED,
MODE_FIRSTPERSONPEDONPC_38,
MODE_FIRSTPERSONPEDONPC_39,
MODE_FIRSTPERSONPEDONPC_40,
MODE_FIRSTPERSONPEDONPC_41,
MODE_FIRSTPERSONPEDONPC_42,
MODE_EDITOR,
MODE_M16FIRSTPERSON_44
};
bool bBelowMinDist; //used for follow ped mode
bool bBehindPlayerDesired; //used for follow ped mode
bool m_bCamLookingAtVector;
bool m_bCollisionChecksOn;
bool m_bFixingBeta; //used for camera on a string
bool m_bTheHeightFixerVehicleIsATrain;
bool LookBehindCamWasInFront;
bool LookingBehind;
bool LookingLeft; // 32
bool LookingRight;
bool ResetStatics; //for interpolation type stuff to work
bool Rotating;
int16 Mode; // CameraMode
uint32 m_uiFinishTime; // 52
int m_iDoCollisionChecksOnFrameNum;
int m_iDoCollisionCheckEveryNumOfFrames;
int m_iFrameNumWereAt; // 64
int m_iRunningVectorArrayPos;
int m_iRunningVectorCounter;
int DirectionWasLooking;
float f_max_role_angle; //=DEGTORAD(5.0f);
float f_Roll; //used for adding a slight roll to the camera in the
float f_rollSpeed;
float m_fSyphonModeTargetZOffSet;
float m_unknownZOffset;
float m_fAmountFractionObscured;
float m_fAlphaSpeedOverOneFrame; // 100
float m_fBetaSpeedOverOneFrame;
float m_fBufferedTargetBeta;
float m_fBufferedTargetOrientation;
float m_fBufferedTargetOrientationSpeed;
float m_fCamBufferedHeight;
float m_fCamBufferedHeightSpeed;
float m_fCloseInPedHeightOffset;
float m_fCloseInPedHeightOffsetSpeed; // 132
float m_fCloseInCarHeightOffset;
float m_fCloseInCarHeightOffsetSpeed;
float m_fDimensionOfHighestNearCar;
float m_fDistanceBeforeChanges;
float m_fFovSpeedOverOneFrame;
float m_fMinDistAwayFromCamWhenInterPolating;
float m_fPedBetweenCameraHeightOffset;
float m_fPlayerInFrontSyphonAngleOffSet; // 164
float m_fRadiusForDead;
float m_fRealGroundDist; //used for follow ped mode
float m_fTargetBeta;
float m_fTimeElapsedFloat;
float m_fTransitionBeta;
float m_fTrueBeta;
float m_fTrueAlpha; // 200
float m_fInitialPlayerOrientation; //used for first person
float Alpha;
float AlphaSpeed;
float FOV;
float FOVSpeed;
float Beta;
float BetaSpeed;
float Distance; // 232
float DistanceSpeed;
float CA_MIN_DISTANCE;
float CA_MAX_DISTANCE;
float SpeedVar;
// ped onfoot zoom distance
float m_fTargetZoomGroundOne;
float m_fTargetZoomGroundTwo; // 256
float m_fTargetZoomGroundThree;
// ped onfoot alpha angle offset
float m_fTargetZoomOneZExtra;
float m_fTargetZoomTwoZExtra;
float m_fTargetZoomThreeZExtra;
float m_fTargetZoomZCloseIn;
float m_fMinRealGroundDist;
float m_fTargetCloseInDist;
CVector m_cvecTargetCoorsForFudgeInter; // 360
CVector m_cvecCamFixedModeVector; // 372
CVector m_cvecCamFixedModeSource; // 384
CVector m_cvecCamFixedModeUpOffSet; // 396
CVector m_vecLastAboveWaterCamPosition; //408 //helper for when the player has gone under the water
CVector m_vecBufferedPlayerBodyOffset; // 420
// The three vectors that determine this camera for this frame
CVector Front; // 432 // Direction of looking in
CVector Source; // Coors in world space
CVector SourceBeforeLookBehind;
CVector Up; // Just that
CVector m_arrPreviousVectors[NUMBER_OF_VECTORS_FOR_AVERAGE]; // used to average stuff
CEntity *CamTargetEntity;
float m_fCameraDistance;
float m_fIdealAlpha;
float m_fPlayerVelocity;
CAutomobile *m_pLastCarEntered; // So interpolation works
CPed *m_pLastPedLookedAt;// So interpolation works
bool m_bFirstPersonRunAboutActive;
void Process_Debug(float *vec, float a, float b, float c);
void Process_Kalvin(float*, float, float, float);
void GetVectorsReadyForRW(void);
};
static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size");
static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error");
static_assert(offsetof(CCam, Front) == 0x140, "CCam: error");
struct CCamPathSplines
{
float m_arr_PathData[800];
};
struct CTrainCamNode
{
CVector m_cvecCamPosition;
CVector m_cvecPointToLookAt;
CVector m_cvecMinPointInRange;
CVector m_cvecMaxPointInRange;
float m_fDesiredFOV;
float m_fNearClip;
};
struct CQueuedMode
{
int16 Mode;
float Duration;
int16 MinZoom;
int16 MaxZoom;
};
enum
{
LOOKING_BEHIND,
LOOKING_LEFT,
LOOKING_RIGHT,
LOOKING_FORWARD,
};
struct CCamera : public CPlaceable
{
bool m_bAboveGroundTrainNodesLoaded;
bool m_bBelowGroundTrainNodesLoaded;
bool m_bCamDirectlyBehind;
bool m_bCamDirectlyInFront;
bool m_bCameraJustRestored;
bool m_bcutsceneFinished;
bool m_bCullZoneChecksOn;
bool m_bFirstPersonBeingUsed;
bool m_bJustJumpedOutOf1stPersonBecauseOfTarget;
bool m_bIdleOn;
bool m_bInATunnelAndABigVehicle;
bool m_bInitialNodeFound;
bool m_bInitialNoNodeStaticsSet;
bool m_bIgnoreFadingStuffForMusic;
bool m_bPlayerIsInGarage;
bool m_bJustCameOutOfGarage;
bool m_bJustInitalised;
bool m_bJust_Switched;
bool m_bLookingAtPlayer;
bool m_bLookingAtVector;
bool m_bMoveCamToAvoidGeom;
bool m_bObbeCinematicPedCamOn;
bool m_bObbeCinematicCarCamOn;
bool m_bRestoreByJumpCut;
bool m_bUseNearClipScript;
bool m_bStartInterScript;
bool m_bStartingSpline;
bool m_bTargetJustBeenOnTrain;
bool m_bTargetJustCameOffTrain;
bool m_bUseSpecialFovTrain;
bool m_bUseTransitionBeta;
bool m_bUseScriptZoomValuePed;
bool m_bUseScriptZoomValueCar;
bool m_bWaitForInterpolToFinish;
bool m_bItsOkToLookJustAtThePlayer;
bool m_bWantsToSwitchWidescreenOff;
bool m_WideScreenOn;
bool m_1rstPersonRunCloseToAWall;
bool m_bHeadBob;
bool m_bFailedCullZoneTestPreviously;
bool m_FadeTargetIsSplashScreen;
bool WorldViewerBeingUsed;
uint8 ActiveCam;
uint32 m_uiCamShakeStart;
uint32 m_uiFirstPersonCamLastInputTime;
// where are those?
//bool m_bVehicleSuspenHigh;
//bool m_bEnable1rstPersonCamCntrlsScript;
//bool m_bAllow1rstPersonWeaponsCamera;
uint32 m_uiLongestTimeInMill;
uint32 m_uiNumberOfTrainCamNodes;
uint8 m_uiTransitionJUSTStarted;
uint8 m_uiTransitionState; // 0:one mode 1:transition
uint32 m_uiTimeLastChange;
uint32 m_uiTimeWeEnteredIdle;
uint32 m_uiTimeTransitionStart;
uint32 m_uiTransitionDuration;
int m_BlurBlue;
int m_BlurGreen;
int m_BlurRed;
int m_BlurType;
uint32 unknown;
int m_iWorkOutSpeedThisNumFrames;
int m_iNumFramesSoFar;
int m_iCurrentTrainCamNode;
int m_motionBlur;
int m_imotionBlurAddAlpha;
int m_iCheckCullZoneThisNumFrames;
int m_iZoneCullFrameNumWereAt;
int WhoIsInControlOfTheCamera;
float CamFrontXNorm;
float CamFrontYNorm;
float CarZoomIndicator;
float CarZoomValue;
float CarZoomValueSmooth;
float DistanceToWater;
float FOVDuringInter;
float LODDistMultiplier;
float GenerationDistMultiplier;
float m_fAlphaSpeedAtStartInter;
float m_fAlphaWhenInterPol;
float m_fAlphaDuringInterPol;
float m_fBetaDuringInterPol;
float m_fBetaSpeedAtStartInter;
float m_fBetaWhenInterPol;
float m_fFOVWhenInterPol;
float m_fFOVSpeedAtStartInter;
float m_fStartingBetaForInterPol;
float m_fStartingAlphaForInterPol;
float m_PedOrientForBehindOrInFront;
float m_CameraAverageSpeed;
float m_CameraSpeedSoFar;
float m_fCamShakeForce;
float m_fCarZoomValueScript;
float m_fFovForTrain;
float m_fFOV_Wide_Screen;
float m_fNearClipScript;
float m_fOldBetaDiff;
float m_fPedZoomValue;
float m_fPedZoomValueScript;
float m_fPedZoomValueSmooth;
float m_fPositionAlongSpline;
float m_ScreenReductionPercentage;
float m_ScreenReductionSpeed;
float m_AlphaForPlayerAnim1rstPerson;
float Orientation;
float PedZoomIndicator;
float PlayerExhaustion;
float SoundDistUp, SoundDistLeft, SoundDistRight;
float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead;
float SoundDistUpAsReadOld, SoundDistLeftAsReadOld, SoundDistRightAsReadOld;
float m_fWideScreenReductionAmount;
float m_fStartingFOVForInterPol;
// not static yet
float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls
float m_f3rdPersonCHairMultX;
float m_f3rdPersonCHairMultY;
CCam Cams[3];
void *pToGarageWeAreIn;
void *pToGarageWeAreInForHackAvoidFirstPerson;
CQueuedMode m_PlayerMode;
CQueuedMode PlayerWeaponMode;
CVector m_PreviousCameraPosition;
CVector m_RealPreviousCameraPosition;
CVector m_cvecAimingTargetCoors;
CVector m_vecFixedModeVector;
// one of those has to go
CVector m_vecFixedModeSource;
CVector m_vecFixedModeUpOffSet;
// CVector m_vecCutSceneOffset;
CVector m_cvecStartingSourceForInterPol;
CVector m_cvecStartingTargetForInterPol;
CVector m_cvecStartingUpForInterPol;
CVector m_cvecSourceSpeedAtStartInter;
CVector m_cvecTargetSpeedAtStartInter;
CVector m_cvecUpSpeedAtStartInter;
CVector m_vecSourceWhenInterPol;
CVector m_vecTargetWhenInterPol;
CVector m_vecUpWhenInterPol;
CVector m_vecClearGeometryVec;
CVector m_vecGameCamPos;
CVector SourceDuringInter;
CVector TargetDuringInter;
CVector UpDuringInter;
RwCamera *m_pRwCamera;
CEntity *pTargetEntity;
CCamPathSplines m_arrPathArray[4];
CTrainCamNode m_arrTrainCamNode[800];
CMatrix m_cameraMatrix;
bool m_bGarageFixedCamPositionSet;
bool m_vecDoingSpecialInterPolation;
bool m_bScriptParametersSetForInterPol;
bool m_bFading;
bool m_bMusicFading;
CMatrix m_viewMatrix;
CVector m_vecFrustumNormals[4];
CVector m_vecOldSourceForInter;
CVector m_vecOldFrontForInter;
CVector m_vecOldUpForInter;
float m_vecOldFOVForInter;
float m_fFLOATingFade;
float m_fFLOATingFadeMusic;
float m_fTimeToFadeOut;
float m_fTimeToFadeMusic;
float m_fFractionInterToStopMovingTarget;
float m_fFractionInterToStopCatchUpTarget;
float m_fGaitSwayBuffer;
float m_fScriptPercentageInterToStopMoving;
float m_fScriptPercentageInterToCatchUp;
uint32 m_fScriptTimeForInterPolation;
int16 m_iFadingDirection;
int m_iModeObbeCamIsInForCar;
int16 m_iModeToGoTo;
int16 m_iMusicFadingDirection;
int16 m_iTypeOfSwitch;
uint32 m_uiFadeTimeStarted;
uint32 m_uiFadeTimeStartedMusic;
CMatrix &GetCameraMatrix(void) { return m_cameraMatrix; }
CVector &GetGameCamPosition(void) { return m_vecGameCamPos; }
bool IsPointVisible(const CVector &center, const CMatrix *mat);
bool IsSphereVisible(const CVector &center, float radius, const CMatrix *mat);
bool IsBoxVisible(RwV3d *box, const CMatrix *mat);
};
static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error");
static_assert(offsetof(CCamera, WorldViewerBeingUsed) == 0x75, "CCamera: error");
static_assert(offsetof(CCamera, m_uiNumberOfTrainCamNodes) == 0x84, "CCamera: error");
static_assert(offsetof(CCamera, m_uiTransitionState) == 0x89, "CCamera: error");
static_assert(offsetof(CCamera, m_uiTimeTransitionStart) == 0x94, "CCamera: error");
static_assert(offsetof(CCamera, m_BlurBlue) == 0x9C, "CCamera: error");
static_assert(offsetof(CCamera, Cams) == 0x1A4, "CCamera: error");
static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size");
extern CCamera &TheCamera;

@ -0,0 +1,116 @@
#include "common.h"
#include "patcher.h"
#include "Timer.h"
#include "Pad.h"
#include "Clock.h"
uint8 &CClock::ms_nGameClockHours = *(uint8*)0x95CDA6;
uint8 &CClock::ms_nGameClockMinutes = *(uint8*)0x95CDC8;
uint16 &CClock::ms_nGameClockSeconds = *(uint16*)0x95CC7C;
uint8 &CClock::ms_Stored_nGameClockHours = *(uint8*)0x95CD7B;
uint8 &CClock::ms_Stored_nGameClockMinutes = *(uint8*)0x95CD9B;
uint16 &CClock::ms_Stored_nGameClockSeconds = *(uint16*)0x95CC9C;
uint32 &CClock::ms_nMillisecondsPerGameMinute = *(uint32*)0x8F2C64;
int32 &CClock::ms_nLastClockTick = *(int32*)0x9430E4;
bool &CClock::ms_bClockHasBeenStored = *(bool*)0x95CD82;
void
CClock::Initialise(uint32 scale)
{
debug("Initialising CClock...\n");
ms_nGameClockHours = 12;
ms_nGameClockMinutes = 0;
ms_nGameClockSeconds = 0;
ms_nMillisecondsPerGameMinute = scale;
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
ms_bClockHasBeenStored = false;
debug("CClock ready\n");
}
void
CClock::Update(void)
{
if(CPad::GetPad(1)->NewState.r1){
ms_nGameClockMinutes += 8;
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
if(ms_nGameClockMinutes >= 60){
ms_nGameClockHours++;
ms_nGameClockMinutes = 0;
if(ms_nGameClockHours >= 24)
ms_nGameClockHours = 0;
}
}else
if(CTimer::GetTimeInMilliseconds() - ms_nLastClockTick >
ms_nMillisecondsPerGameMinute){
ms_nGameClockMinutes++;
ms_nLastClockTick += ms_nMillisecondsPerGameMinute;
if(ms_nGameClockMinutes >= 60){
ms_nGameClockHours++;
ms_nGameClockMinutes = 0;
if(ms_nGameClockHours >= 24)
ms_nGameClockHours = 0;
// TODO: stats days passed
}
}
ms_nGameClockSeconds +=
60
* (CTimer::GetTimeInMilliseconds() - ms_nLastClockTick)
/ ms_nMillisecondsPerGameMinute;
}
void
CClock::SetGameClock(uint8 h, uint8 m)
{
ms_nGameClockHours = h;
ms_nGameClockMinutes = m;
ms_nGameClockSeconds = 0;
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
}
int32
CClock::GetGameClockMinutesUntil(uint8 h, uint8 m)
{
int32 now, then;
now = ms_nGameClockHours*60 + ms_nGameClockMinutes;
then = h*60 + m;
if(then < now)
then += 24*60;
return then-now;
}
bool
CClock::GetIsTimeInRange(uint8 h1, uint8 h2)
{
if(h1 > h2)
return ms_nGameClockHours >= h1 || ms_nGameClockHours < h2;
else
return ms_nGameClockHours >= h1 && ms_nGameClockHours < h2;
}
void
CClock::StoreClock(void)
{
ms_Stored_nGameClockHours = ms_nGameClockHours;
ms_Stored_nGameClockMinutes = ms_nGameClockMinutes;
ms_Stored_nGameClockSeconds = ms_nGameClockSeconds;
ms_bClockHasBeenStored = true;
}
void
CClock::RestoreClock(void)
{
ms_nGameClockHours = ms_Stored_nGameClockHours;
ms_nGameClockMinutes = ms_Stored_nGameClockMinutes;
ms_nGameClockSeconds = ms_Stored_nGameClockSeconds;
}
STARTPATCHES
InjectHook(0x473370, CClock::Initialise, PATCH_JUMP);
InjectHook(0x473460, CClock::Update, PATCH_JUMP);
InjectHook(0x4733C0, CClock::SetGameClock, PATCH_JUMP);
InjectHook(0x4733F0, CClock::GetGameClockMinutesUntil, PATCH_JUMP);
InjectHook(0x473420, CClock::GetIsTimeInRange, PATCH_JUMP);
InjectHook(0x473540, CClock::StoreClock, PATCH_JUMP);
InjectHook(0x473570, CClock::RestoreClock, PATCH_JUMP);
ENDPATCHES

@ -0,0 +1,27 @@
#pragma once
class CClock
{
static uint8 &ms_nGameClockHours;
static uint8 &ms_nGameClockMinutes;
static uint16 &ms_nGameClockSeconds;
static uint8 &ms_Stored_nGameClockHours;
static uint8 &ms_Stored_nGameClockMinutes;
static uint16 &ms_Stored_nGameClockSeconds;
static uint32 &ms_nMillisecondsPerGameMinute;
static int32 &ms_nLastClockTick;
static bool &ms_bClockHasBeenStored;
public:
static void Initialise(uint32 scale);
static void Update(void);
static void SetGameClock(uint8 h, uint8 m);
static int32 GetGameClockMinutesUntil(uint8 h, uint8 m);
static bool GetIsTimeInRange(uint8 h1, uint8 h2);
static void StoreClock(void);
static void RestoreClock(void);
static int8 GetHours(void) { return ms_nGameClockHours; }
static int8 GetMinutes(void) { return ms_nGameClockMinutes; }
static int16 GetSeconds(void) { return ms_nGameClockSeconds; }
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,152 @@
#pragma once
#include "templates.h"
#include "Game.h" // for eLevelName
struct CColSphere
{
CVector center;
float radius;
uint8 surface;
uint8 piece;
void Set(float radius, const CVector &center, uint8 surf, uint8 piece);
void Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }
};
struct CColBox
{
CVector min;
CVector max;
uint8 surface;
uint8 piece;
void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
};
struct CColLine
{
CVector p0;
int pad0;
CVector p1;
int pad1;
CColLine(void) { };
CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
void Set(const CVector &p0, const CVector &p1);
CColLine *ctor(CVector *p0, CVector *p1) { return ::new (this) CColLine(*p0, *p1); }
};
struct CColTriangle
{
uint16 a;
uint16 b;
uint16 c;
uint8 surface;
void Set(const CVector *v, int a, int b, int c, uint8 surf, uint8 piece);
};
struct CColTrianglePlane
{
CVector normal;
float dist;
uint8 dir;
void Set(const CVector *v, CColTriangle &tri);
void GetNormal(CVector &n) const { n = normal; }
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
};
struct CColPoint
{
CVector point;
int pad1;
// the surface normal on the surface of point
CVector normal;
int pad2;
uint8 surfaceA;
uint8 pieceA;
uint8 surfaceB;
uint8 pieceB;
float depth;
};
struct CStoredCollPoly
{
CVector verts[3];
bool valid;
};
struct CColModel
{
CColSphere boundingSphere;
CColBox boundingBox;
short numSpheres;
short numLines;
short numBoxes;
short numTriangles;
int level;
bool ownsCollisionVolumes;
CColSphere *spheres;
CColLine *lines;
CColBox *boxes;
CVector *vertices;
CColTriangle *triangles;
CColTrianglePlane *trianglePlanes;
CColModel(void);
~CColModel(void);
void RemoveCollisionVolumes(void);
void CalculateTrianglePlanes(void);
void RemoveTrianglePlanes(void);
CLink<CColModel*> *GetLinkPtr(void);
void SetLinkPtr(CLink<CColModel*>*);
void GetTrianglePoint(CVector &v, int i) const;
CColModel *ctor(void) { return ::new (this) CColModel(); }
void dtor(void) { this->CColModel::~CColModel(); }
};
class CCollision
{
public:
static eLevelName &ms_collisionInMemory;
static CLinkList<CColModel*> &ms_colModelCache;
static void Init(void);
static void Update(void);
static void LoadCollisionWhenINeedIt(bool changeLevel);
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
static void CalculateTrianglePlanes(CColModel *model);
// all these return true if there's a collision
static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2);
static bool TestSphereBox(const CColSphere &sph, const CColBox &box);
static bool TestLineBox(const CColLine &line, const CColBox &box);
static bool TestVerticalLineBox(const CColLine &line, const CColBox &box);
static bool TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
static bool TestSphereTriangle(const CColSphere &sphere, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineOfSight(CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSurf78);
static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
static bool ProcessVerticalLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
static bool ProcessLineTriangle(const CColLine &line , const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
static bool ProcessSphereTriangle(const CColSphere &sph, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSurf78);
static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSurf78, CStoredCollPoly *poly);
static int32 ProcessColModels(const CMatrix &matrix1, CColModel &model1, const CMatrix &matrix2, CColModel &model2, CColPoint *point1, CColPoint *point2, float *linedists);
// TODO:
// CCollision::IsStoredPolyStillValidVerticalLine
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);
};

@ -0,0 +1,323 @@
#include "common.h"
#include "patcher.h"
#include "Building.h"
#include "Treadable.h"
#include "Pools.h"
#include "Timer.h"
#include "Camera.h"
#include "World.h"
#include "CullZones.h"
int32 &CCullZones::NumCullZones = *(int*)0x8F2564;
CCullZone *CCullZones::aZones = (CCullZone*)0x864750; // [NUMCULLZONES];
int32 &CCullZones::NumAttributeZones = *(int*)0x8E29D0;
CAttributeZone *CCullZones::aAttributeZones = (CAttributeZone*)0x709C60; // [NUMATTRIBZONES];
uint16 *CCullZones::aIndices = (uint16*)0x847330; // [NUMZONEINDICES];
int16 *CCullZones::aPointersToBigBuildingsForBuildings = (int16*)0x86C9D0; // [NUMBUILDINGS];
int16 *CCullZones::aPointersToBigBuildingsForTreadables = (int16*)0x8F1B8C; // [NUMTREADABLES];
int32 &CCullZones::CurrentWantedLevelDrop_Player = *(int32*)0x880DA8;
int32 &CCullZones::CurrentFlags_Camera = *(int32*)0x940718;
int32 &CCullZones::CurrentFlags_Player = *(int32*)0x9415F0;
int32 &CCullZones::OldCullZone = *(int32*)0x8E2C90;
int32 &CCullZones::EntityIndicesUsed = *(int32*)0x8F2508;
bool &CCullZones::bCurrentSubwayIsInvisible = *(bool*)0x95CDA5;
bool &CCullZones::bCullZonesDisabled = *(bool*)0x95CD4A;
void
CCullZones::Init(void)
{
int i;
NumAttributeZones = 0;
NumCullZones = 0;
CurrentWantedLevelDrop_Player = 0;
CurrentFlags_Camera = 0;
CurrentFlags_Player = 0;
OldCullZone = -1;
EntityIndicesUsed = 0;
bCurrentSubwayIsInvisible = false;
for(i = 0; i < NUMBUILDINGS; i++)
aPointersToBigBuildingsForBuildings[i] = -1;
for(i = 0; i < NUMTREADABLES; i++)
aPointersToBigBuildingsForTreadables[i] = -1;
}
void
CCullZones::Update(void)
{
bool invisible;
CVector v;
if(bCullZonesDisabled)
return;
switch(CTimer::GetFrameCounter() & 7){
case 0:
case 4:
/* Update Cull zone */
ForceCullZoneCoors(TheCamera.GetGameCamPosition());
break;
case 2:
/* Update camera attributes */
CurrentFlags_Camera = FindAttributesForCoors(TheCamera.GetGameCamPosition(), nil);
invisible = (CurrentFlags_Camera & ATTRZONE_SUBWAYVISIBLE) == 0;
if(invisible != bCurrentSubwayIsInvisible){
MarkSubwayAsInvisible(!invisible);
bCurrentSubwayIsInvisible = invisible;
}
break;
case 6:
/* Update player attributes */
CurrentFlags_Player = FindAttributesForCoors(FindPlayerCoors(v),
&CurrentWantedLevelDrop_Player);
break;
}
}
void
CCullZones::ForceCullZoneCoors(CVector coors)
{
int32 z;
z = FindCullZoneForCoors(coors);
if(z != OldCullZone){
if(OldCullZone >= 0)
aZones[OldCullZone].DoStuffLeavingZone();
if(z >= 0)
aZones[z].DoStuffEnteringZone();
OldCullZone = z;
}
}
int32
CCullZones::FindCullZoneForCoors(CVector coors)
{
int i;
for(i = 0; i < NumCullZones; i++)
if(coors.x >= aZones[i].minx && coors.x <= aZones[i].maxx &&
coors.y >= aZones[i].miny && coors.y <= aZones[i].maxy &&
coors.z >= aZones[i].minz && coors.z <= aZones[i].maxz)
return i;
return -1;
}
int32
CCullZones::FindAttributesForCoors(CVector coors, int32 *wantedLevel)
{
int i;
int32 attribs;
attribs = 0;
for(i = 0; i < NumAttributeZones; i++)
if(coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&
coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&
coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz){
attribs |= aAttributeZones[i].attributes;
if(wantedLevel && *wantedLevel <= aAttributeZones[i].wantedLevel)
*wantedLevel = aAttributeZones[i].wantedLevel;
}
return attribs;
}
CAttributeZone*
CCullZones::FindZoneWithStairsAttributeForPlayer(void)
{
int i;
CVector coors;
FindPlayerCoors(coors);
for(i = 0; i < NumAttributeZones; i++)
if(aAttributeZones[i].attributes & ATTRZONE_STAIRS &&
coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&
coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&
coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz)
return &aAttributeZones[i];
return nil;
}
WRAPPER void
CCullZones::MarkSubwayAsInvisible(bool visible)
{ EAXJMP(0x525AF0);
}
void
CCullZones::AddCullZone(CVector const &position,
float minx, float maxx,
float miny, float maxy,
float minz, float maxz,
uint16 flag, int16 wantedLevel)
{
CCullZone *cull;
CAttributeZone *attrib;
CVector v;
if((flag & ATTRZONE_NOTCULLZONE) == 0){
cull = &aZones[NumCullZones++];
v = position;
// WTF is this?
if((v-CVector(1032.14f, -624.255f, 24.93f)).Magnitude() < 1.0f)
v = CVector(1061.7f, -613.0f, 19.0f);
if((v-CVector(1029.48f, -495.757f, 21.98f)).Magnitude() < 1.0f)
v = CVector(1061.4f, -506.0f, 18.5f);
cull->position.x = clamp(v.x, minx, maxx);
cull->position.y = clamp(v.y, miny, maxy);
cull->position.z = clamp(v.z, minz, maxz);
cull->minx = minx;
cull->maxx = maxx;
cull->miny = miny;
cull->maxy = maxy;
cull->minz = minz;
cull->maxz = maxz;
cull->unk2 = 0;
cull->unk3 = 0;
cull->unk4 = 0;
cull->m_indexStart = 0;
}
if(flag & ~ATTRZONE_NOTCULLZONE){
attrib = &aAttributeZones[NumAttributeZones++];
attrib->minx = minx;
attrib->maxx = maxx;
attrib->miny = miny;
attrib->maxy = maxy;
attrib->minz = minz;
attrib->maxz = maxz;
attrib->attributes = flag;
attrib->wantedLevel = wantedLevel;
}
}
void
CCullZone::DoStuffLeavingZone(void)
{
int i;
for(i = 0; i < m_numBuildings; i++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables ; i++)
DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[m_indexStart + i]);
}
void
CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
{
int16 bb;
int j;
if(i < 6000){
CPools::GetBuildingPool()->GetSlot(i)->m_bZoneCulled = false;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = false;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
}
}
void
CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
{
int16 bb;
int j;
if(i < 6000){
CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = false;
CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled2 = false;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = false;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]);
}
}
void
CCullZone::DoStuffEnteringZone(void)
{
int i;
for(i = 0; i < m_numBuildings; i++)
DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
for(; i < m_numBuildings + m_numTreadablesPlus10m; i++)
DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[m_indexStart + i]);
for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables; i++)
DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[m_indexStart + i]);
}
void
CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
{
int16 bb;
int j;
if(i < 6000){
CPools::GetBuildingPool()->GetSlot(i)->m_bZoneCulled = true;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
}
}
void
CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
{
int16 bb;
int j;
if(i < 6000){
CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = true;;
CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled2 = true;;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
}
}
void
CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
{
int16 bb;
int j;
if(i < 6000){
CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = true;;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
}
}
STARTPATCHES
InjectHook(0x524BC0, &CCullZones::Init, PATCH_JUMP);
InjectHook(0x524F80, &CCullZones::Update, PATCH_JUMP);
InjectHook(0x525370, &CCullZones::AddCullZone, PATCH_JUMP);
InjectHook(0x5250D0, &CCullZones::ForceCullZoneCoors, PATCH_JUMP);
InjectHook(0x525130, &CCullZones::FindCullZoneForCoors, PATCH_JUMP);
InjectHook(0x5251C0, &CCullZones::FindAttributesForCoors, PATCH_JUMP);
InjectHook(0x525290, &CCullZones::FindZoneWithStairsAttributeForPlayer, PATCH_JUMP);
InjectHook(0x525610, &CCullZone::DoStuffLeavingZone, PATCH_JUMP);
InjectHook(0x525810, &CCullZone::DoStuffEnteringZone, PATCH_JUMP);
ENDPATCHES

@ -0,0 +1,93 @@
class CCullZone
{
public:
CVector position;
float minx;
float maxx;
float miny;
float maxy;
float minz;
float maxz;
// TODO: figure these out:
int32 m_indexStart;
int16 unk2;
int16 unk3;
int16 unk4;
int16 m_numBuildings;
int16 m_numTreadablesPlus10m;
int16 m_numTreadables;
void DoStuffLeavingZone(void);
static void DoStuffLeavingZone_OneBuilding(uint16 i);
static void DoStuffLeavingZone_OneTreadableBoth(uint16 i);
void DoStuffEnteringZone(void);
static void DoStuffEnteringZone_OneBuilding(uint16 i);
static void DoStuffEnteringZone_OneTreadablePlus10m(uint16 i);
static void DoStuffEnteringZone_OneTreadable(uint16 i);
};
enum eZoneAttribs
{
ATTRZONE_CAMCLOSEIN = 1,
ATTRZONE_STAIRS = 2,
ATTRZONE_1STPERSON = 4,
ATTRZONE_NORAIN = 8,
ATTRZONE_NOPOLICE = 0x10,
ATTRZONE_NOTCULLZONE = 0x20,
ATTRZONE_DOINEEDCOLLISION = 0x40,
ATTRZONE_SUBWAYVISIBLE = 0x80,
};
struct CAttributeZone
{
float minx;
float maxx;
float miny;
float maxy;
float minz;
float maxz;
int16 attributes;
int16 wantedLevel;
};
class CCullZones
{
public:
static int32 &NumCullZones;
static CCullZone *aZones; // [NUMCULLZONES];
static int32 &NumAttributeZones;
static CAttributeZone *aAttributeZones; // [NUMATTRIBZONES];
static uint16 *aIndices; // [NUMZONEINDICES];
static int16 *aPointersToBigBuildingsForBuildings; // [NUMBUILDINGS];
static int16 *aPointersToBigBuildingsForTreadables; // [NUMTREADABLES];
static int32 &CurrentWantedLevelDrop_Player;
static int32 &CurrentFlags_Camera;
static int32 &CurrentFlags_Player;
static int32 &OldCullZone;
static int32 &EntityIndicesUsed;
static bool &bCurrentSubwayIsInvisible;
static bool &bCullZonesDisabled;
static void Init(void);
static void Update(void);
static void ForceCullZoneCoors(CVector coors);
static int32 FindCullZoneForCoors(CVector coors);
static int32 FindAttributesForCoors(CVector coors, int32 *wantedLevel);
static CAttributeZone *FindZoneWithStairsAttributeForPlayer(void);
static void MarkSubwayAsInvisible(bool visible);
static void AddCullZone(CVector const &position,
float minx, float maxx,
float miny, float maxy,
float minz, float maxz,
uint16 flag, int16 wantedLevel);
static bool CamCloseInForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_CAMCLOSEIN) != 0; }
static bool CamStairsForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_STAIRS) != 0; }
static bool Cam1stPersonForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_1STPERSON) != 0; }
static bool NoPolice(void) { return (CurrentFlags_Player & ATTRZONE_NOPOLICE) != 0; }
static bool DoINeedToLoadCollision(void) { return (CurrentFlags_Player & ATTRZONE_DOINEEDCOLLISION) != 0; }
static bool PlayerNoRain(void) { return (CurrentFlags_Player & ATTRZONE_NORAIN) != 0; }
static bool CamNoRain(void) { return (CurrentFlags_Camera & ATTRZONE_NORAIN) != 0; }
static int32 GetWantedLevelDrop(void) { return CurrentWantedLevelDrop_Player; }
};

@ -0,0 +1,5 @@
#include "common.h"
#include "patcher.h"
#include "Game.h"
int &CGame::currLevel = *(int*)0x941514;

@ -0,0 +1,15 @@
#pragma once
enum eLevelName
{
LEVEL_NONE = 0,
LEVEL_INDUSTRIAL,
LEVEL_COMMERCIAL,
LEVEL_SUBURBAN
};
class CGame
{
public:
static int &currLevel;
};

@ -0,0 +1,15 @@
class CGeneral
{
public:
static float GetATanOfXY(float x, float y){
if(y >= 0.0f) return atan2(x, y);
return atan2(x, y) + 2*M_PI;
}
// not too sure about all these...
static uint16 GetRandomNumber(void)
{ return myrand() & 0xFFFF; }
// Probably don't want to ever reach high
static float GetRandomNumberInRange(float low, float high)
{ return low + (high - low)*(GetRandomNumber()/65536.0f); }
};

@ -0,0 +1,15 @@
#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);
}

@ -0,0 +1,10 @@
#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);
};

@ -0,0 +1,26 @@
#include "common.h"
#include "Pools.h"
#include "Lists.h"
void*
CPtrNode::operator new(size_t){
CPtrNode *node = CPools::GetPtrNodePool()->New();
assert(node);
return node;
}
void
CPtrNode::operator delete(void *p, size_t){
CPools::GetPtrNodePool()->Delete((CPtrNode*)p);
}
void*
CEntryInfoNode::operator new(size_t){
CEntryInfoNode *node = CPools::GetEntryInfoNodePool()->New();
assert(node);
return node;
}
void
CEntryInfoNode::operator delete(void *p, size_t){
CPools::GetEntryInfoNodePool()->Delete((CEntryInfoNode*)p);
}

@ -0,0 +1,130 @@
#pragma once
class CPtrNode
{
public:
void *item;
CPtrNode *prev;
CPtrNode *next;
void *operator new(size_t);
void operator delete(void *p, size_t);
};
class CPtrList
{
public:
CPtrNode *first;
CPtrList(void) { first = nil; }
~CPtrList(void) { Flush(); }
CPtrNode *FindItem(void *item){
CPtrNode *node;
for(node = first; node; node = node->next)
if(node->item == item)
return node;
return nil;
}
CPtrNode *InsertNode(CPtrNode *node){
node->prev = nil;
node->next = first;
if(first)
first->prev = node;
first = node;
return node;
}
CPtrNode *InsertItem(void *item){
CPtrNode *node = new CPtrNode;
node->item = item;
InsertNode(node);