From 88ce335afc1af81222109e922ef03051a5273dd7 Mon Sep 17 00:00:00 2001 From: guard3 Date: Thu, 4 Jul 2019 14:04:34 +0300 Subject: [PATCH] CBridge --- src/Stats.cpp | 5 +- src/Stats.h | 7 +- src/control/Bridge.cpp | 151 ++++++++++++++++++++++++++++++++++++++- src/control/Bridge.h | 25 ++++++- src/control/PathFind.cpp | 2 + src/control/PathFind.h | 2 + 6 files changed, 185 insertions(+), 7 deletions(-) diff --git a/src/Stats.cpp b/src/Stats.cpp index 5256b0cf..3c5b55e4 100644 --- a/src/Stats.cpp +++ b/src/Stats.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "Stats.h" -int32 &CStats::DaysPassed = *(int32*)0x8F2BB8; -int32 &CStats::HeadShots = *(int32*)0x8F647C; \ No newline at end of file +int32& CStats::DaysPassed = *(int32*)0x8F2BB8; +int32& CStats::HeadShots = *(int32*)0x8F647C; +bool& CStats::CommercialPassed = *(bool*)0x8F4334; \ No newline at end of file diff --git a/src/Stats.h b/src/Stats.h index e7cc3dc5..39b0e184 100644 --- a/src/Stats.h +++ b/src/Stats.h @@ -3,6 +3,7 @@ class CStats { public: - static int32 &DaysPassed; - static int32 &HeadShots; -}; + static int32& DaysPassed; + static int32& HeadShots; + static bool& CommercialPassed; +}; \ No newline at end of file diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp index 91f3c788..3215ea2d 100644 --- a/src/control/Bridge.cpp +++ b/src/control/Bridge.cpp @@ -1,5 +1,154 @@ #include "common.h" #include "patcher.h" #include "Bridge.h" +#include "Pools.h" +#include "ModelIndices.h" +#include "PathFind.h" +#include "Stats.h" -WRAPPER bool CBridge::ShouldLightsBeFlashing(void) { EAXJMP(0x413D10); } +CEntity*& CBridge::pLiftRoad = *(CEntity**)0x8E2C8C; +CEntity*& CBridge::pLiftPart = *(CEntity**)0x8E2C94; +CEntity*& CBridge::pWeight = *(CEntity**)0x8E28BC; + +int& CBridge::State = *(int*)0x8F2A1C; +int& CBridge::OldState = *(int*)0x8F2A20; + +float& CBridge::DefaultZLiftPart = *(float*)0x941430; +float& CBridge::DefaultZLiftRoad = *(float*)0x941438; +float& CBridge::DefaultZLiftWeight = *(float*)0x8F1A44; + +float& CBridge::OldLift = *(float*)0x8F6254; + +uint32& CBridge::TimeOfBridgeBecomingOperational = *(uint32*)0x8F2BC0; + +void CBridge::Init() +{ + FindBridgeEntities(); + OldLift = -1.0; + if (pLiftPart && pWeight) + { + DefaultZLiftPart = pLiftPart->GetPosition().z; + DefaultZLiftWeight = pWeight->GetPosition().z; + + if (pLiftRoad) + DefaultZLiftRoad = pLiftRoad->GetPosition().z; + + ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true); + } +} + +void CBridge::Update() +{ + if (!pLiftPart || !pWeight) + return; + + OldState = State; + + float liftHeight; + + if (CStats::CommercialPassed) + { + if (TimeOfBridgeBecomingOperational == 0) + TimeOfBridgeBecomingOperational = CTimer::GetTimeInMilliseconds(); + + // Time remaining for bridge to become operational + // uint16, so after about a minute it overflows to 0 and the cycle repeats + uint16 timeElapsed = CTimer::GetTimeInMilliseconds() - TimeOfBridgeBecomingOperational; + + // Calculate lift part height and bridge state + if (timeElapsed < 10000) + { + State = STATE_LIFT_PART_MOVING_DOWN; + liftHeight = 25.0 - timeElapsed / 10000.0 * 25.0; + } + else if (timeElapsed < 40000) + { + liftHeight = 0.0; + State = STATE_LIFT_PART_IS_DOWN; + } + else if (timeElapsed < 50000) + { + liftHeight = 0.0; + State = STATE_LIFT_PART_ABOUT_TO_MOVE_UP; + } + else if (timeElapsed < 60000) + { + State = STATE_LIFT_PART_MOVING_UP; + liftHeight = (timeElapsed - 50000) / 10000.0 * 25.0; + } + else + { + liftHeight = 25.0; + State = STATE_LIFT_PART_IS_UP; + } + + // Move bridge part + if (liftHeight != OldLift) + { + pLiftPart->GetPosition().z = DefaultZLiftPart + liftHeight; + pLiftPart->GetMatrix().UpdateRW(); + pLiftPart->UpdateRwFrame(); + if (pLiftRoad) + { + pLiftRoad->GetPosition().z = DefaultZLiftRoad + liftHeight; + pLiftRoad->GetMatrix().UpdateRW(); + pLiftRoad->UpdateRwFrame(); + } + pWeight->GetPosition().z = DefaultZLiftWeight - liftHeight; + pWeight->GetMatrix().UpdateRW(); + pWeight->UpdateRwFrame(); + + OldLift = liftHeight; + } + + if (State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP && OldState == STATE_LIFT_PART_IS_DOWN) + ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true); + else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN) + ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false); + } + else + { + liftHeight = 25.0; + TimeOfBridgeBecomingOperational = 0; + State = STATE_BRIDGE_LOCKED; + } +} + +bool CBridge::ShouldLightsBeFlashing() { return State != STATE_LIFT_PART_IS_DOWN; } + +void CBridge::FindBridgeEntities() +{ + pWeight = nil; + pLiftRoad = nil; + pLiftPart = nil; + + for (int i = 1; i < CPools::GetBuildingPool()->GetSize(); ++i) + { + CBuilding* entry = CPools::GetBuildingPool()->GetSlot(i); + if (entry) + { + if (entry->GetModelIndex() == MI_BRIDGELIFT) + pLiftPart = entry; + else if (entry->GetModelIndex() == MI_BRIDGEROADSEGMENT) + pLiftRoad = entry; + else if (entry->GetModelIndex() == MI_BRIDGEWEIGHT) + pWeight = entry; + } + } +} + +bool CBridge::ThisIsABridgeObjectMovingUp(int index) +{ + if (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT) + return false; + + return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP; +} + +STARTPATCHES + InjectHook(0x413A30, &CBridge::Init, PATCH_JUMP); + InjectHook(0x413AC0, &CBridge::Update, PATCH_JUMP); + InjectHook(0x413D10, &CBridge::ShouldLightsBeFlashing, PATCH_JUMP); + InjectHook(0x413D20, &CBridge::FindBridgeEntities, PATCH_JUMP); + InjectHook(0x413DE0, &CBridge::ThisIsABridgeObjectMovingUp, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/control/Bridge.h b/src/control/Bridge.h index 64b85c1d..52c85322 100644 --- a/src/control/Bridge.h +++ b/src/control/Bridge.h @@ -1,7 +1,30 @@ #pragma once +#include "Entity.h" class CBridge { +private: + enum bridgeStates + { + STATE_BRIDGE_LOCKED, + STATE_LIFT_PART_IS_UP, + STATE_LIFT_PART_MOVING_DOWN, + STATE_LIFT_PART_IS_DOWN, + STATE_LIFT_PART_ABOUT_TO_MOVE_UP, + STATE_LIFT_PART_MOVING_UP + }; + + + static CEntity *&pLiftRoad, *&pLiftPart, *&pWeight; + static int &State, &OldState; + static float &DefaultZLiftPart, &DefaultZLiftRoad, &DefaultZLiftWeight; + static float& OldLift; + static uint32& TimeOfBridgeBecomingOperational; + public: - static bool ShouldLightsBeFlashing(void); + static void Init(); + static void Update(); + static bool ShouldLightsBeFlashing(); + static void FindBridgeEntities(); + static bool ThisIsABridgeObjectMovingUp(int); }; diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index f511b5dc..f9ce7f35 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -626,6 +626,8 @@ CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out) *out = m_mapObjects[id]->GetMatrix() * pos; } +WRAPPER void CPathFind::SetLinksBridgeLights(float, float, float, float, bool) { EAXJMP(0x42E3B0); } + STARTPATCHES InjectHook(0x429610, &CPathFind::PreparePathData, PATCH_JUMP); InjectHook(0x429C20, &CPathFind::PreparePathDataForType, PATCH_JUMP); diff --git a/src/control/PathFind.h b/src/control/PathFind.h index cc0b0a2f..9b6be573 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -131,6 +131,8 @@ public: int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool disabled, bool betweenLevels); bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); } + + void SetLinksBridgeLights(float, float, float, float, bool); }; static_assert(sizeof(CPathFind) == 0x4c8f4, "CPathFind: error");