diff options
Diffstat (limited to '')
-rw-r--r-- | src/control/Replay.cpp | 4 | ||||
-rw-r--r-- | src/control/Script.cpp | 305 | ||||
-rw-r--r-- | src/control/Script.h | 182 | ||||
-rw-r--r-- | src/core/config.h | 1 | ||||
-rw-r--r-- | src/core/re3.cpp | 23 | ||||
-rw-r--r-- | src/math/Matrix.h | 9 | ||||
-rw-r--r-- | src/render/Hud.cpp | 10 | ||||
-rw-r--r-- | src/vehicles/Automobile.cpp | 4 | ||||
-rw-r--r-- | src/vehicles/Automobile.h | 17 | ||||
-rw-r--r-- | src/vehicles/Door.cpp | 126 | ||||
-rw-r--r-- | src/vehicles/Door.h | 36 |
11 files changed, 643 insertions, 74 deletions
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 06995663..d0264415 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -686,8 +686,8 @@ void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressI car->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f; car->m_aWheelRotation[i] = vp->wheel_rotation[i] * M_PI / 128.0f; } - car->Doors[2].m_fAngle = car->Doors[2].m_fPreviousAngle = vp->door_angles[0] * M_PI / 127.0f; - car->Doors[3].m_fAngle = car->Doors[3].m_fPreviousAngle = vp->door_angles[1] * M_PI / 127.0f; + car->Doors[2].m_fAngle = car->Doors[2].m_fPrevAngle = vp->door_angles[0] * M_PI / 127.0f; + car->Doors[3].m_fAngle = car->Doors[3].m_fPrevAngle = vp->door_angles[1] * M_PI / 127.0f; if (vp->door_angles[0]) car->Damage.SetDoorStatus(2, 2); if (vp->door_angles[1]) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 5e7f4936..d2e27487 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -6,6 +6,7 @@ #include "Camera.h" #include "CarCtrl.h" #include "DMAudio.h" +#include "FileMgr.h" #include "Hud.h" #include "ModelIndices.h" #include "PlayerInfo.h" @@ -17,18 +18,44 @@ #include "Weather.h" #include "World.h" -uint8 (&CTheScripts::ScriptSpace)[160 * 1024] = *(uint8(*)[160 * 1024])*(uintptr*)0x74B248; -CTextLine (&CTheScripts::IntroTextLines)[2] = *(CTextLine (*)[2])*(uintptr*)0x70EA74; -CScriptRectangle (&CTheScripts::IntroRectangles)[16] = *(CScriptRectangle (*)[16])*(uintptr*)0x72D108; -CSprite2d (&CTheScripts::ScriptSprites)[16] = *(CSprite2d(*)[16])*(uintptr*)0x72B090; +uint8 (&CTheScripts::ScriptSpace)[SIZE_SCRIPT_SPACE] = *(uint8(*)[SIZE_SCRIPT_SPACE])*(uintptr*)0x74B248; +CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08; +int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200; +int32(&CTheScripts::OnAMissionForContactFlag)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x8622F0; +CTextLine (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(CTextLine (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68; +CScriptRectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(CScriptRectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108; +CSprite2d (&CTheScripts::ScriptSprites)[MAX_NUM_SCRIPT_SRPITES] = *(CSprite2d(*)[MAX_NUM_SCRIPT_SRPITES])*(uintptr*)0x72B090; +CScriptSphere(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(CScriptSphere(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60; +tCollectiveData(&CTheScripts::CollectiveArray)[MAX_NUM_COLLECTIVES] = *(tCollectiveData(*)[MAX_NUM_COLLECTIVES])*(uintptr*)0x6FA008; +tUsedObject(&CTheScripts::UsedObjectArray)[MAX_NUM_USED_OBJECTS] = *(tUsedObject(*)[MAX_NUM_USED_OBJECTS])*(uintptr*)0x6E69C8; +int32(&CTheScripts::MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS] = *(int32(*)[MAX_NUM_MISSION_SCRIPTS])*(uintptr*)0x6F0558; +tBuildingSwap(&CTheScripts::BuildingSwapArray)[MAX_NUM_BUILDING_SWAPS] = *(tBuildingSwap(*)[MAX_NUM_BUILDING_SWAPS])*(uintptr*)0x880E30; +CEntity*(&CTheScripts::InvisibilitySettingArray)[MAX_NUM_INVISIBILITY_SETTINGS] = *(CEntity*(*)[MAX_NUM_INVISIBILITY_SETTINGS])*(uintptr*)0x8620F0; bool &CTheScripts::DbgFlag = *(bool*)0x95CD87; uint32 &CTheScripts::OnAMissionFlag = *(uint32*)0x8F2A24; int32 &CTheScripts::StoreVehicleIndex = *(int32*)0x8F5F3C; bool &CTheScripts::StoreVehicleWasRandom = *(bool*)0x95CDBC; - -CMissionCleanup(&CTheScripts::MissionCleanup) = *(CMissionCleanup*)0x8F2AD8; -CUpsideDownCarCheck(&CTheScripts::UpsideDownCars) = *(CUpsideDownCarCheck*)0x6EE450; -CStuckCarCheck(&CTheScripts::StuckCars) = *(CStuckCarCheck*)0x87C588; +CRunningScript *&CTheScripts::pIdleScripts = *(CRunningScript**)0x9430D4; +CRunningScript *&CTheScripts::pActiveScripts = *(CRunningScript**)0x8E2BF4; +uint32 &CTheScripts::NextFreeCollectiveIndex = *(uint32*)0x942F98; +int32 &CTheScripts::LastRandomPedId = *(int32*)0x8F251C; +uint16 &CTheScripts::NumberOfUsedObjects = *(uint16*)0x95CC72; +bool &CTheScripts::bAlreadyRunningAMissionScript = *(bool*)0x95CDB3; +bool &CTheScripts::bUsingAMultiScriptFile = *(bool*)0x95CD55; +uint16 &CTheScripts::NumberOfMissionScripts = *(uint16*)0x95CC9A; +uint32 &CTheScripts::LargestMissionScriptSize = *(uint32*)0x9414C8; +uint32 &CTheScripts::MainScriptSize = *(uint32*)0x9405A4; +uint8 &CTheScripts::FailCurrentMission = *(uint8*)0x95CD41; +uint8 &CTheScripts::CountdownToMakePlayerUnsafe = *(uint8*)0x95CD51; +uint8 &CTheScripts::DelayMakingPlayerUnsafeThisTime = *(uint8*)0x95CD88; +uint16 &CTheScripts::NumScriptDebugLines = *(uint16*)0x95CC42; +uint16 &CTheScripts::NumberOfIntroRectanglesThisFrame = *(uint16*)0x95CC88; +uint16 &CTheScripts::NumberOfIntroTextLinesThisFrame = *(uint16*)0x95CC32; +bool &CTheScripts::UseTextCommands = *(bool*)0x95CD57; +CMissionCleanup (&CTheScripts::MissionCleanup) = *(CMissionCleanup*)0x8F2A24; +CUpsideDownCarCheck (&CTheScripts::UpsideDownCars) = *(CUpsideDownCarCheck*)0x6EE450; +CStuckCarCheck (&CTheScripts::StuckCars) = *(CStuckCarCheck*)0x87C588; +int32(&ScriptParams)[32] = *(int32(*)[32])*(uintptr*)0x6ED460; CMissionCleanup::CMissionCleanup() { @@ -277,11 +304,263 @@ bool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id) return false; } +void CRunningScript::CollectParameters(uint32* pIp, int16 total) +{ + for (int16 i = 0; i < total; i++){ + float tmp; + switch (CTheScripts::Read1ByteFromScript(pIp)) + { + case ARGUMENT_INT32: + ScriptParams[i] = CTheScripts::Read4BytesFromScript(pIp); + break; + case ARGUMENT_GLOBALVAR: + ScriptParams[i] = *((int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)]); + break; + case ARGUMENT_LOCALVAR: + ScriptParams[i] = m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)]; + break; + case ARGUMENT_INT8: + ScriptParams[i] = CTheScripts::Read1ByteFromScript(pIp); + break; + case ARGUMENT_INT16: + ScriptParams[i] = CTheScripts::Read2BytesFromScript(pIp); + break; + case ARGUMENT_FLOAT: + tmp = CTheScripts::ReadFloatFromScript(pIp); + ScriptParams[i] = *(int32*)&tmp; + break; + default: + assert(0); + break; + } + } +} + +int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip) +{ + uint32* pIp = &ip; + float tmp; + switch (CTheScripts::Read1ByteFromScript(pIp)) + { + case ARGUMENT_INT32: + return CTheScripts::Read4BytesFromScript(pIp); + case ARGUMENT_GLOBALVAR: + return *((int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)]); + case ARGUMENT_LOCALVAR: + return m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)]; + case ARGUMENT_INT8: + return CTheScripts::Read1ByteFromScript(pIp); + case ARGUMENT_INT16: + return CTheScripts::Read2BytesFromScript(pIp); + case ARGUMENT_FLOAT: + tmp = CTheScripts::ReadFloatFromScript(pIp); + return *(int32*)&tmp; + default: + assert(0); + } + return -1; +} + +void CRunningScript::StoreParameters(uint32* pIp, int16 number) +{ + for (int16 i = 0; i < number; i++){ + switch (CTheScripts::Read1ByteFromScript(pIp)) { + case ARGUMENT_GLOBALVAR: + *(int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)] = ScriptParams[i]; + break; + case ARGUMENT_LOCALVAR: + m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)] = ScriptParams[i]; + break; + default: + assert(0); + } + } +} + +int32 *CRunningScript::GetPointerToScriptVariable(uint32* pIp, int16 type) +{ + switch (CTheScripts::Read1ByteFromScript(pIp)) + { + case ARGUMENT_GLOBALVAR: + assert(type == VAR_GLOBAL); + return (int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)]; + case ARGUMENT_LOCALVAR: + assert(type == VAR_LOCAL); + return &m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)]; + default: + assert(0); + } + return nil; +} + +void CRunningScript::Init() +{ + strcpy(m_abScriptName, "noname"); + next = prev = nil; + m_nIp = 0; + for (int i = 0; i < MAX_STACK_DEPTH; i++) + m_anStack[i] = 0; + m_nStackPointer = 0; + m_nWakeTime = 0; + m_bCondResult = false; + m_bIsMissionThread = false; + m_bSkipWakeTime = false; + for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++) + m_anLocalVariables[i] = 0; + m_nAndOrState = 0; + m_bNotFlag = false; + m_bWBCheckEnabled = true; + m_bWBChecked = false; + m_bMissionFlag = false; +} + +#ifdef USE_DEBUG_SCRIPT_LOADER +int open_script() +{ + static int scriptToLoad = 1; + + if (GetAsyncKeyState('G') & 0x8000) + scriptToLoad = 0; + if (GetAsyncKeyState('R') & 0x8000) + scriptToLoad = 1; + if (GetAsyncKeyState('D') & 0x8000) + scriptToLoad = 2; + + switch (scriptToLoad) { + case 0: return CFileMgr::OpenFile("main.scm", "rb"); + case 1: return CFileMgr::OpenFile("main_freeroam.scm", "rb"); + case 2: return CFileMgr::OpenFile("main_d.scm", "rb"); + } + return CFileMgr::OpenFile("main.scm", "rb"); +} +#endif + +void CTheScripts::Init() +{ + for (int i = 0; i < SIZE_SCRIPT_SPACE; i++) + ScriptSpace[i] = 0; + pActiveScripts = pIdleScripts = nil; + for (int i = 0; i < MAX_NUM_SCRIPTS; i++){ + ScriptsArray[i].Init(); + ScriptsArray[i].AddScriptToList(&pIdleScripts); + } + MissionCleanup.Init(); + UpsideDownCars.Init(); + StuckCars.Init(); + CFileMgr::SetDir("data"); +#ifdef USE_DEBUG_SCRIPT_LOADER + int mainf = open_script(); +#else + int mainf = CFileMgr::OpenFile("main.scm", "rb"); +#endif + CFileMgr::Read(mainf, (char*)ScriptSpace, SIZE_MAIN_SCRIPT); + CFileMgr::CloseFile(mainf); + CFileMgr::SetDir(""); + StoreVehicleIndex = -1; + StoreVehicleWasRandom = true; + OnAMissionFlag = 0; + for (int i = 0; i < MAX_NUM_CONTACTS; i++){ + BaseBriefIdForContact[i] = 0; + OnAMissionForContactFlag[i] = 0; + } + for (int i = 0; i < MAX_NUM_COLLECTIVES; i++){ + CollectiveArray[i].index = -1; + CollectiveArray[i].unk_data = 0; + } + NextFreeCollectiveIndex = 0; + LastRandomPedId = -1; + for (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){ + memset(&UsedObjectArray[i].name, 0, sizeof(UsedObjectArray[i].name)); + UsedObjectArray[i].index = 0; + } + NumberOfUsedObjects = 0; + ReadObjectNamesFromScript(); + UpdateObjectIndices(); + bAlreadyRunningAMissionScript = false; + bUsingAMultiScriptFile = true; + for (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++) + MultiScriptArray[i] = 0; + NumberOfMissionScripts = 0; + LargestMissionScriptSize = 0; + MainScriptSize = 0; + ReadMultiScriptFileOffsetsFromScript(); + FailCurrentMission = 0; + CountdownToMakePlayerUnsafe = 0; + DbgFlag = 0; + DelayMakingPlayerUnsafeThisTime = 0; + NumScriptDebugLines = 0; + for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){ + ScriptSphereArray[i].m_bInUse = false; + ScriptSphereArray[i].m_Index = 1; + ScriptSphereArray[i].m_Id = 0; + ScriptSphereArray[i].m_vecCenter = CVector(0.0f, 0.0f, 0.0f); + ScriptSphereArray[i].m_fRadius = 0.0f; + } + for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++){ + IntroTextLines[i].m_fScaleX = 0.48f; + IntroTextLines[i].m_fScaleY = 1.12f; + IntroTextLines[i].m_sColor = CRGBA(225, 225, 225, 255); + IntroTextLines[i].m_bJustify = false; + IntroTextLines[i].m_bRightJustify = false; + IntroTextLines[i].m_bCentered = false; + IntroTextLines[i].m_bBackground = false; + IntroTextLines[i].m_bBackgroundOnly = false; + IntroTextLines[i].m_fWrapX = 182.0f; /* TODO: scaling as bugfix */ + IntroTextLines[i].m_fCenterSize = 640.0f; /* --||-- */ + IntroTextLines[i].m_sBackgroundColor = CRGBA(128, 128, 128, 128); + IntroTextLines[i].m_bTextProportional = true; + IntroTextLines[i].m_bTextBeforeFade = false; + IntroTextLines[i].m_nFont = 2; /* enum? */ + IntroTextLines[i].m_fAtX = 0.0f; + IntroTextLines[i].m_fAtY = 0.0f; + memset(&IntroTextLines[i].m_Text, 0, sizeof(IntroTextLines[i].m_Text)); + } + NumberOfIntroTextLinesThisFrame = 0; + UseTextCommands = false; + for (int i = 0; i < MAX_NUM_INTRO_RECTANGLES; i++){ + IntroRectangles[i].m_bIsUsed = false; + IntroRectangles[i].m_bIsAntialiased = false; + IntroRectangles[i].m_nTextureId = -1; + IntroRectangles[i].m_sRect = CRect(0.0f, 0.0f, 0.0f, 0.0f); + IntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255); + } + NumberOfIntroRectanglesThisFrame = 0; + for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){ + BuildingSwapArray[i].m_pBuilding = nil; + BuildingSwapArray[i].m_nNewModel = -1; + BuildingSwapArray[i].m_nOldModel = -1; + } + for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) + InvisibilitySettingArray[i] = nil; +} + +void CRunningScript::RemoveScriptFromList(CRunningScript** ppScript) +{ + if (prev) + prev->next = next; + else + *ppScript = next; + if (next) + next->prev = prev; +} + +void CRunningScript::AddScriptToList(CRunningScript** ppScript) +{ + next = *ppScript; + prev = nil; + if (*ppScript) + (*ppScript)->prev = this; + *ppScript = this; +} + +WRAPPER bool CTheScripts::IsPlayerOnAMission() { EAXJMP(0x439410); } +WRAPPER void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, int col, int col2) { EAXJMP(0x4534E0); } WRAPPER void CTheScripts::CleanUpThisVehicle(CVehicle*) { EAXJMP(0x4548D0); } WRAPPER void CTheScripts::CleanUpThisPed(CPed*) { EAXJMP(0x4547A0); } WRAPPER void CTheScripts::CleanUpThisObject(CObject*) { EAXJMP(0x454910); } -WRAPPER bool CTheScripts::IsPlayerOnAMission() { EAXJMP(0x439410); } -WRAPPER void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, int col, int col2) { EAXJMP(0x4534E0); } +WRAPPER void CTheScripts::ReadObjectNamesFromScript() { EAXJMP(0x454960); } +WRAPPER void CTheScripts::UpdateObjectIndices() { EAXJMP(0x454AD0); } +WRAPPER void CTheScripts::ReadMultiScriptFileOffsetsFromScript() { EAXJMP(0x454BC0); } STARTPATCHES InjectHook(0x437AE0, &CMissionCleanup::Init, PATCH_JUMP); @@ -299,4 +578,10 @@ InjectHook(0x4380A0, &CStuckCarCheck::Process, PATCH_JUMP); InjectHook(0x4381C0, &CStuckCarCheck::AddCarToCheck, PATCH_JUMP); InjectHook(0x438240, &CStuckCarCheck::RemoveCarFromCheck, PATCH_JUMP); InjectHook(0x4382A0, &CStuckCarCheck::HasCarBeenStuckForAWhile, PATCH_JUMP); +InjectHook(0x4382E0, &CRunningScript::CollectParameters, PATCH_JUMP); +InjectHook(0x438460, &CRunningScript::CollectNextParameterWithoutIncreasingPC, PATCH_JUMP); +InjectHook(0x4385A0, &CRunningScript::StoreParameters, PATCH_JUMP); +InjectHook(0x438640, &CRunningScript::GetPointerToScriptVariable, PATCH_JUMP); +InjectHook(0x4386C0, &CRunningScript::Init, PATCH_JUMP); +InjectHook(0x438790, &CTheScripts::Init, PATCH_JUMP); ENDPATCHES
\ No newline at end of file diff --git a/src/control/Script.h b/src/control/Script.h index 42e41c70..5759cf82 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -1,4 +1,6 @@ #pragma once +#include "common.h" +#include "Collision.h" #include "Ped.h" #include "Object.h" #include "Sprite2d.h" @@ -8,11 +10,17 @@ struct CScriptRectangle { bool m_bIsUsed; bool m_bIsAntialiased; - uint16 m_wTextureId; + int16 m_nTextureId; CRect m_sRect; CRGBA m_sColor; }; +static_assert(sizeof(CScriptRectangle) == 0x18, "Script.h: error"); + +enum { + SCRIPT_TEXT_MAX_LENGTH = 500 +}; + struct CTextLine { float m_fScaleX; @@ -26,33 +34,58 @@ struct CTextLine float m_fCenterSize; CRGBA m_sBackgroundColor; bool m_bTextProportional; - int32 field_29; + bool m_bTextBeforeFade; bool m_bRightJustify; - int32 field_31; int32 m_nFont; - float field_36; - float field_40; - wchar m_awText[500]; + float m_fAtX; + float m_fAtY; + wchar m_Text[SCRIPT_TEXT_MAX_LENGTH]; +}; + +static_assert(sizeof(CTextLine) == 0x414, "Script.h: error"); + +struct CScriptSphere +{ + bool m_bInUse; + uint16 m_Index; + uint32 m_Id; + CVector m_vecCenter; + float m_fRadius; +}; + +enum { + MAX_STACK_DEPTH = 6, + NUM_LOCAL_VARS = 16, + NUM_TIMERS = 2 }; -struct CRunningScript +class CRunningScript { CRunningScript *next; CRunningScript *prev; - uint8 m_abScriptName[8]; + char m_abScriptName[8]; uint32 m_nIp; - uint32 m_anStack[6]; + uint32 m_anStack[MAX_STACK_DEPTH]; uint16 m_nStackPointer; - void* m_anLocalVariables[18]; + int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS]; bool m_bCondResult; bool m_bIsMissionThread; bool m_bSkipWakeTime; uint32 m_nWakeTime; - uint16 m_wIfOp; + uint16 m_nAndOrState; bool m_bNotFlag; - bool m_bWBCheck; - bool m_bWastedOrBusted; + bool m_bWBCheckEnabled; + bool m_bWBChecked; bool m_bMissionFlag; + +public: + void CollectParameters(uint32*, int16); + int32 CollectNextParameterWithoutIncreasingPC(uint32); + int32* GetPointerToScriptVariable(uint32*, int16); + void StoreParameters(uint32*, int16); + void Init(); + void RemoveScriptFromList(CRunningScript**); + void AddScriptToList(CRunningScript**); }; enum { @@ -133,13 +166,80 @@ public: bool HasCarBeenStuckForAWhile(int32); }; +enum { + ARGUMENT_INT32 = 1, + ARGUMENT_GLOBALVAR, + ARGUMENT_LOCALVAR, + ARGUMENT_INT8, + ARGUMENT_INT16, + ARGUMENT_FLOAT +}; + +struct tCollectiveData +{ + int32 index; + uint32 unk_data; +}; + +enum { + USED_OBJECT_NAME_LENGTH = 24 +}; + +struct tUsedObject +{ + char name[USED_OBJECT_NAME_LENGTH]; + int32 index; +}; + +struct tBuildingSwap +{ + CBuilding* m_pBuilding; + int32 m_nNewModel; + int32 m_nOldModel; +}; + + +enum { + VAR_LOCAL = 1, + VAR_GLOBAL = 2, +}; + +enum { + SIZE_MAIN_SCRIPT = 128 * 1024, + SIZE_MISSION_SCRIPT = 32 * 1024, + SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT +}; + +enum { + MAX_NUM_SCRIPTS = 128, + MAX_NUM_CONTACTS = 16, + MAX_NUM_INTRO_TEXT_LINES = 2, + MAX_NUM_INTRO_RECTANGLES = 16, + MAX_NUM_SCRIPT_SRPITES = 16, + MAX_NUM_SCRIPT_SPHERES = 16, + MAX_NUM_COLLECTIVES = 32, + MAX_NUM_USED_OBJECTS = 200, + MAX_NUM_MISSION_SCRIPTS = 120, + MAX_NUM_BUILDING_SWAPS = 25, + MAX_NUM_INVISIBILITY_SETTINGS = 20 +}; + class CTheScripts { public: - static uint8(&ScriptSpace)[160 * 1024]; - static CTextLine(&IntroTextLines)[2]; - static CScriptRectangle(&IntroRectangles)[16]; - static CSprite2d(&ScriptSprites)[16]; + static uint8(&ScriptSpace)[SIZE_SCRIPT_SPACE]; + static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS]; + static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS]; + static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS]; + static CTextLine(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES]; + static CScriptRectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES]; + static CSprite2d(&ScriptSprites)[MAX_NUM_SCRIPT_SRPITES]; + static CScriptSphere(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES]; + static tCollectiveData(&CollectiveArray)[MAX_NUM_COLLECTIVES]; + static tUsedObject(&UsedObjectArray)[MAX_NUM_USED_OBJECTS]; + static int32(&MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS]; + static tBuildingSwap(&BuildingSwapArray)[MAX_NUM_BUILDING_SWAPS]; + static CEntity*(&InvisibilitySettingArray)[MAX_NUM_INVISIBILITY_SETTINGS]; static bool &DbgFlag; static uint32 &OnAMissionFlag; static CMissionCleanup &MissionCleanup; @@ -147,11 +247,57 @@ public: static CUpsideDownCarCheck &UpsideDownCars; static int32 &StoreVehicleIndex; static bool &StoreVehicleWasRandom; - + static CRunningScript *&pIdleScripts; + static CRunningScript *&pActiveScripts; + static uint32 &NextFreeCollectiveIndex; + static int32 &LastRandomPedId; + static uint16 &NumberOfUsedObjects; + static bool &bAlreadyRunningAMissionScript; + static bool &bUsingAMultiScriptFile; + static uint16 &NumberOfMissionScripts; + static uint32 &LargestMissionScriptSize; + static uint32 &MainScriptSize; + static uint8 &FailCurrentMission; + static uint8 &CountdownToMakePlayerUnsafe; + static uint8 &DelayMakingPlayerUnsafeThisTime; + static uint16 &NumScriptDebugLines; + static uint16 &NumberOfIntroRectanglesThisFrame; + static uint16 &NumberOfIntroTextLinesThisFrame; + static bool &UseTextCommands; public: static bool IsPlayerOnAMission(); static void ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, int col, int col2); static void CleanUpThisVehicle(CVehicle*); static void CleanUpThisPed(CPed*); static void CleanUpThisObject(CObject*); + static void Init(); + + static void ReadObjectNamesFromScript(); + static void UpdateObjectIndices(); + static void ReadMultiScriptFileOffsetsFromScript(); + + static int32 Read4BytesFromScript(uint32* pIp){ + int32 retval = 0; + for (int i = 0; i < 4; i++){ + retval |= ScriptSpace[(*pIp)++] << (8 * i); + } + return retval; + } + static int16 Read2BytesFromScript(uint32* pIp){ + int16 retval = 0; + for (int i = 0; i < 2; i++){ + retval |= ScriptSpace[(*pIp)++] << (8 * i); + } + return retval; + } + static int8 Read1ByteFromScript(uint32* pIp){ + int8 retval = 0; + for (int i = 0; i < 1; i++){ + retval |= ScriptSpace[(*pIp)++] << (8 * i); + } + return retval; + } + static float ReadFloatFromScript(uint32* pIp){ + return Read2BytesFromScript(pIp) / 16.0f; + } }; diff --git a/src/core/config.h b/src/core/config.h index 8cb02190..c3b66ff7 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -114,3 +114,4 @@ enum Config { #define FIX_BUGS // fix bugs in the game, TODO: use this more #define KANGAROO_CHEAT #define ASPECT_RATIO_SCALE +#define USE_DEBUG_SCRIPT_LOADER
\ No newline at end of file diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 9dc39d46..d6e81214 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -57,27 +57,6 @@ mysrand(unsigned int seed) myrand_seed = seed; } -int (*open_script_orig)(const char *path, const char *mode); -int -open_script(const char *path, const char *mode) -{ - static int scriptToLoad = 1; - - if(GetAsyncKeyState('G') & 0x8000) - scriptToLoad = 0; - if(GetAsyncKeyState('R') & 0x8000) - scriptToLoad = 1; - if(GetAsyncKeyState('D') & 0x8000) - scriptToLoad = 2; - - switch(scriptToLoad){ - case 0: return open_script_orig(path, mode); - case 1: return open_script_orig("main_freeroam.scm", mode); - case 2: return open_script_orig("main_d.scm", mode); - } - return open_script_orig(path, mode); -} - int gDbgSurf; void (*DebugMenuProcess)(void); @@ -356,7 +335,7 @@ patch() Patch<WORD>(0x5382BF, 0x0EEB); InjectHook(0x5382EC, HeadlightsFix, PATCH_JUMP); - InterceptCall(&open_script_orig, open_script, 0x438869); +// InterceptCall(&open_script_orig, open_script, 0x438869); // InterceptCall(&RsEventHandler_orig, delayedPatches10, 0x58275E); } diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 6e1001cb..5cc7d12f 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -306,6 +306,15 @@ Multiply3x3(const CMatrix &mat, const CVector &vec) mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z); } +inline CVector +Multiply3x3(const CVector &vec, const CMatrix &mat) +{ + return CVector( + mat.m_matrix.right.x * vec.x + mat.m_matrix.right.y * vec.y + mat.m_matrix.right.z * vec.z, + mat.m_matrix.up.x * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.up.z * vec.z, + mat.m_matrix.at.x * vec.x + mat.m_matrix.at.y * vec.y + mat.m_matrix.at.z * vec.z); +} + class CCompressedMatrixNotAligned { CVector m_vecPos; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 680720e0..754f4b85 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -814,8 +814,8 @@ void CHud::Draw() if (!CTimer::GetIsUserPaused()) { CTextLine* IntroText = CTheScripts::IntroTextLines; - for (int i = 0; i < 2; i++) { - if (CTheScripts::IntroTextLines[i].m_awText[0] && CTheScripts::IntroTextLines[i].field_29) { + for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) { + if (CTheScripts::IntroTextLines[i].m_Text[0] && CTheScripts::IntroTextLines[i].m_bTextBeforeFade) { CFont::SetScale(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fScaleX), SCREEN_SCALE_Y(CTheScripts::IntroTextLines[i].m_fScaleY * 0.5f)); CFont::SetColor(CTheScripts::IntroTextLines[i].m_sColor); @@ -855,7 +855,7 @@ void CHud::Draw() CFont::SetPropOff(); CFont::SetFontStyle(CTheScripts::IntroTextLines[i].m_nFont); - CFont::PrintString(SCREEN_SCALE_X(640.0f - CTheScripts::IntroTextLines[i].field_36), SCREEN_SCALE_Y(448.0f - CTheScripts::IntroTextLines[i].field_40), IntroText->m_awText); + CFont::PrintString(SCREEN_SCALE_X(640.0f - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_SCALE_Y(448.0f - CTheScripts::IntroTextLines[i].m_fAtY), IntroText->m_Text); } } @@ -863,14 +863,14 @@ void CHud::Draw() for (int i = 0; i < 16; i++) { if (CTheScripts::IntroRectangles[i].m_bIsUsed && CTheScripts::IntroRectangles[i].m_bIsAntialiased) { - if (CTheScripts::IntroRectangles[i].m_wTextureId >= 0) { + if (CTheScripts::IntroRectangles[i].m_nTextureId >= 0) { CRect rect = { CTheScripts::IntroRectangles[i].m_sRect.left, CTheScripts::IntroRectangles[i].m_sRect.bottom, CTheScripts::IntroRectangles[i].m_sRect.right, CTheScripts::IntroRectangles[i].m_sRect.bottom }; - CTheScripts::ScriptSprites[CTheScripts::IntroRectangles[i].m_wTextureId].Draw(rect, IntroRect->m_sColor); + CTheScripts::ScriptSprites[CTheScripts::IntroRectangles[i].m_nTextureId].Draw(rect, IntroRect->m_sColor); } else { CRect rect = { diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 54eed17a..80131179 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -14,5 +14,5 @@ WRAPPER void CAutomobile::SetPanelDamage(int32, uint32, bool) { EAXJMP(0x5301A0) WRAPPER void CAutomobile::SetBumperDamage(int32, uint32, bool) { EAXJMP(0x530120); } STARTPATCHES -InjectHook(0x52D170, &CAutomobile::dtor, PATCH_JUMP); -ENDPATCHES
\ No newline at end of file + InjectHook(0x52D170, &CAutomobile::dtor, PATCH_JUMP); +ENDPATCHES diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 630635c7..c20d078b 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -1,21 +1,8 @@ #pragma once -#include "DamageManager.h" #include "Vehicle.h" - -struct CDoor -{ - float m_fAngleWhenOpened; - float m_fAngleWhenClosed; - char field_8; - char field_9; - char field_10; - char field_11; - float m_fAngle; - float m_fPreviousAngle; - float m_fAngularVelocity; - CVector m_vecVelocity; -}; +#include "DamageManager.h" +#include "Door.h" class CAutomobile : public CVehicle { diff --git a/src/vehicles/Door.cpp b/src/vehicles/Door.cpp new file mode 100644 index 00000000..ec5eb223 --- /dev/null +++ b/src/vehicles/Door.cpp @@ -0,0 +1,126 @@ +#include "common.h" +#include "patcher.h" +#include "Vehicle.h" +#include "Door.h" + +CDoor::CDoor(void) +{ + memset(this, 0, sizeof(*this)); +} + +void +CDoor::Open(float ratio) +{ + float open; + + m_fPrevAngle = m_fAngle; + open = RetAngleWhenOpen(); + if(ratio < 1.0f){ + m_fAngle = open*ratio; + if(m_fAngle == 0.0f) + m_fAngVel = 0.0f; + }else{ + m_nDoorState = DOORST_OPEN; + m_fAngle = open; + } +} + +void +CDoor::Process(CVehicle *vehicle) +{ + static CVector vecOffset(1.0f, 0.0f, 0.0f); + CVector speed = vehicle->GetSpeed(vecOffset); + CVector vecSpeedDiff = speed - m_vecSpeed; + vecSpeedDiff = Multiply3x3(vecSpeedDiff, vehicle->GetMatrix()); + + // air resistance + float fSpeedDiff = 0.0f; // uninitialized in game + switch(m_nAxis){ + case 0: // x-axis + if(m_nDirn) + fSpeedDiff = vecSpeedDiff.y + vecSpeedDiff.z; + else + fSpeedDiff = -(vecSpeedDiff.y + vecSpeedDiff.z); + break; + + // we don't support y axis apparently? + + case 2: // z-axis + if(m_nDirn) + fSpeedDiff = -(vecSpeedDiff.x + vecSpeedDiff.y); + else + fSpeedDiff = vecSpeedDiff.x + vecSpeedDiff.y; + break; + } + fSpeedDiff = clamp(fSpeedDiff, -0.2f, 0.2f); + if(fabs(fSpeedDiff) > 0.002f) + m_fAngVel += fSpeedDiff; + m_fAngVel *= 0.945f; + m_fAngVel = clamp(m_fAngVel, -0.3f, 0.3f); + + m_fAngle += m_fAngVel; + m_nDoorState = DOORST_SWINGING; + if(m_fAngle > m_fMaxAngle){ + m_fAngle = m_fMaxAngle; + m_fAngVel *= -0.8f; + m_nDoorState = DOORST_OPEN; + } + if(m_fAngle < m_fMinAngle){ + m_fAngle = m_fMinAngle; + m_fAngVel *= -0.8f; + m_nDoorState = DOORST_CLOSED; + } + m_vecSpeed = speed; +} + +float +CDoor::RetAngleWhenClosed(void) +{ + if(fabs(m_fMaxAngle) < fabs(m_fMinAngle)) + return m_fMaxAngle; + else + return m_fMinAngle; +} + +float +CDoor::RetAngleWhenOpen(void) +{ + if(fabs(m_fMaxAngle) < fabs(m_fMinAngle)) + return m_fMinAngle; + else + return m_fMaxAngle; +} + +float +CDoor::GetAngleOpenRatio(void) +{ + float open = RetAngleWhenOpen(); + if(open == 0.0f) + return 0.0f; + return m_fAngle/open; +} + +bool +CDoor::IsFullyOpen(void) +{ + // why -0.5? that's around 28 deg less than fully open + if(fabs(m_fAngle) < fabs(RetAngleWhenOpen()) - 0.5f) + return false; + return true; +} + +bool +CDoor::IsClosed(void) +{ + return m_fAngle == RetAngleWhenClosed(); +} + +STARTPATCHES + InjectHook(0x545EF0, &CDoor::Open, PATCH_JUMP); + InjectHook(0x545BD0, &CDoor::Process, PATCH_JUMP); + InjectHook(0x545FE0, &CDoor::RetAngleWhenClosed, PATCH_JUMP); + InjectHook(0x546020, &CDoor::RetAngleWhenOpen, PATCH_JUMP); + InjectHook(0x545F80, &CDoor::GetAngleOpenRatio, PATCH_JUMP); + InjectHook(0x546090, &CDoor::IsFullyOpen, PATCH_JUMP); + InjectHook(0x546060, &CDoor::IsClosed, PATCH_JUMP); +ENDPATCHES diff --git a/src/vehicles/Door.h b/src/vehicles/Door.h new file mode 100644 index 00000000..fc771a40 --- /dev/null +++ b/src/vehicles/Door.h @@ -0,0 +1,36 @@ +#pragma once + +class CVehicle; + +enum eDoorState +{ + DOORST_SWINGING, + // actually wrong though, + // OPEN is really MAX_ANGLE and CLOSED is MIN_ANGLE + DOORST_OPEN, + DOORST_CLOSED +}; + +struct CDoor +{ + float m_fMaxAngle; + float m_fMinAngle; + // direction of rotation for air resistance + int8 m_nDirn; + // axis in which this door rotates + int8 m_nAxis; + int8 m_nDoorState; + float m_fAngle; + float m_fPrevAngle; + float m_fAngVel; + CVector m_vecSpeed; + + CDoor(void); + void Open(float ratio); + void Process(CVehicle *veh); + float RetAngleWhenClosed(void); + float RetAngleWhenOpen(void); + float GetAngleOpenRatio(void); + bool IsFullyOpen(void); + bool IsClosed(void); +}; |