diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/control/PathFind.cpp | 17 | ||||
-rw-r--r-- | src/control/PathFind.h | 9 | ||||
-rw-r--r-- | src/control/RoadBlocks.cpp | 34 | ||||
-rw-r--r-- | src/control/RoadBlocks.h | 4 | ||||
-rw-r--r-- | src/core/ControllerConfig.cpp | 10 | ||||
-rw-r--r-- | src/core/Debug.cpp | 85 | ||||
-rw-r--r-- | src/core/Debug.h | 13 | ||||
-rw-r--r-- | src/core/EventList.cpp | 23 | ||||
-rw-r--r-- | src/core/EventList.h | 2 | ||||
-rw-r--r-- | src/core/Frontend.cpp | 268 | ||||
-rw-r--r-- | src/core/Frontend.h | 12 | ||||
-rw-r--r-- | src/core/Timer.h | 13 | ||||
-rw-r--r-- | src/core/config.h | 7 | ||||
-rw-r--r-- | src/core/obrstr.cpp | 119 | ||||
-rw-r--r-- | src/core/obrstr.h | 9 | ||||
-rw-r--r-- | src/peds/CopPed.cpp | 287 | ||||
-rw-r--r-- | src/peds/CopPed.h | 5 | ||||
-rw-r--r-- | src/peds/Ped.cpp | 8 | ||||
-rw-r--r-- | src/peds/Population.cpp | 2 | ||||
-rw-r--r-- | src/save/GenericGameStorage.cpp | 45 | ||||
-rw-r--r-- | src/save/PCSave.cpp | 14 |
21 files changed, 796 insertions, 190 deletions
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index daa27e57..608a209a 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -11,19 +11,10 @@ CPathFind &ThePaths = *(CPathFind*)0x8F6754; WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } -enum -{ - NodeTypeExtern = 1, - NodeTypeIntern = 2, - - ObjectFlag1 = 1, - ObjectEastWest = 2, - - MAX_DIST = INT16_MAX-1 -}; +#define MAX_DIST INT16_MAX-1 // object flags: -// 1 +// 1 UseInRoadBlock // 2 east/west road(?) CPathInfoForObject *&InfoForTileCars = *(CPathInfoForObject**)0x8F1A8C; @@ -218,14 +209,14 @@ CPathFind::PreparePathData(void) if(numIntern == 1 && numExtern == 2){ if(numLanes < 4){ if((i & 7) == 4){ // WHAT? - m_objectFlags[i] |= ObjectFlag1; + m_objectFlags[i] |= UseInRoadBlock; if(maxX > maxY) m_objectFlags[i] |= ObjectEastWest; else m_objectFlags[i] &= ~ObjectEastWest; } }else{ - m_objectFlags[i] |= ObjectFlag1; + m_objectFlags[i] |= UseInRoadBlock; if(maxX > maxY) m_objectFlags[i] |= ObjectEastWest; else diff --git a/src/control/PathFind.h b/src/control/PathFind.h index d42b8bb3..c51cb7c7 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -11,6 +11,15 @@ public: enum { + NodeTypeExtern = 1, + NodeTypeIntern = 2, + + UseInRoadBlock = 1, + ObjectEastWest = 2, +}; + +enum +{ PATH_CAR = 0, PATH_PED = 1, }; diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index ed092391..e39fe481 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -1,7 +1,37 @@ #include "common.h" #include "patcher.h" #include "RoadBlocks.h" +#include "PathFind.h" + +int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34; +int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8; +bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810; -WRAPPER void CRoadBlocks::Init(void) { EAXJMP(0x436F50); } WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); } -WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); }
\ No newline at end of file +WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); } + +void +CRoadBlocks::Init(void) +{ + NumRoadBlocks = 0; + for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { + if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { + if (NumRoadBlocks < 600) { + InOrOut[NumRoadBlocks] = true; + RoadBlockObjects[NumRoadBlocks] = objId; + NumRoadBlocks++; + } else { +#ifndef MASTER + printf("Not enough room for the potential roadblocks\n"); +#endif + // FIX: Don't iterate loop after NUMROADBLOCKS + return; + } + } + } + +} + +STARTPATCHES + InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h index b1bb3589..3f5868e7 100644 --- a/src/control/RoadBlocks.h +++ b/src/control/RoadBlocks.h @@ -6,6 +6,10 @@ class CVehicle; class CRoadBlocks { public: + static int16 (&NumRoadBlocks); + static int16 (&RoadBlockObjects)[NUMROADBLOCKS]; + static bool (&InOrOut)[NUMROADBLOCKS]; + static void Init(void); static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16); static void GenerateRoadBlocks(void); diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 92c51182..541257c6 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -417,6 +417,11 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int32 button, i case 13: pad->PCTempJoyState.DPadUp = 255; break; +#ifdef REGISTER_START_BUTTON + case 12: + pad->PCTempJoyState.Start = 255; + break; +#endif case 11: pad->PCTempJoyState.RightShock = 255; break; @@ -839,6 +844,11 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonUp(int32 button, int case 13: pad->PCTempJoyState.DPadUp = 0; break; +#ifdef REGISTER_START_BUTTON + case 12: + pad->PCTempJoyState.Start = 0; + break; +#endif case 11: pad->PCTempJoyState.RightShock = 0; break; diff --git a/src/core/Debug.cpp b/src/core/Debug.cpp index b80e9959..bdcbaf04 100644 --- a/src/core/Debug.cpp +++ b/src/core/Debug.cpp @@ -1,12 +1,91 @@ +#include "common.h" #include "Debug.h" +#include "Font.h" +#include "main.h" +#include "Text.h" -int CDebug::ms_nCurrentTextLine; +bool gbDebugStuffInRelease = false; -void CDebug::DebugInitTextBuffer() +#define DEBUG_X_POS (300) +#define DEBUG_Y_POS (41) +#define DEBUG_LINE_HEIGHT (22) + +int16 CDebug::ms_nCurrentTextLine; +char CDebug::ms_aTextBuffer[MAX_LINES][MAX_STR_LEN]; + +void +CDebug::DebugInitTextBuffer() { ms_nCurrentTextLine = 0; } -void CDebug::DebugDisplayTextBuffer() +void +CDebug::DebugAddText(const char *str) +{ + int32 i = 0; + if (*str != '\0') { + while (i < MAX_STR_LEN) { + ms_aTextBuffer[ms_nCurrentTextLine][i++] = *(str++); + if (*str == '\0') + break; + } + } + + ms_aTextBuffer[ms_nCurrentTextLine++][i] = '\0'; + if (ms_nCurrentTextLine >= MAX_LINES) + ms_nCurrentTextLine = 0; +} + +void +CDebug::DebugDisplayTextBuffer() { +#ifndef MASTER + if (gbDebugStuffInRelease) + { + int32 i = 0; + int32 y = DEBUG_Y_POS; +#ifdef FIX_BUGS + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(1.0f, 1.0f); + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + CFont::SetJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_BANK); +#else + // this is not even readable + CFont::SetPropOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(1.0f, 1.0f); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_BANK); + CFont::SetPropOff(); +#endif + do { + char *line; + while (true) { + line = ms_aTextBuffer[(ms_nCurrentTextLine + i++) % MAX_LINES]; + if (*line != '\0') + break; + y += DEBUG_LINE_HEIGHT; + if (i == MAX_LINES) { + CFont::DrawFonts(); + return; + } + } + AsciiToUnicode(line, gUString); + CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::PrintString(DEBUG_X_POS, y-1, gUString); + CFont::SetColor(CRGBA(255, 128, 128, 255)); + CFont::PrintString(DEBUG_X_POS+1, y, gUString); + y += DEBUG_LINE_HEIGHT; + } while (i != MAX_LINES); + CFont::DrawFonts(); + } +#endif } diff --git a/src/core/Debug.h b/src/core/Debug.h index 395f66af..444a0cf5 100644 --- a/src/core/Debug.h +++ b/src/core/Debug.h @@ -2,10 +2,19 @@ class CDebug { - static int ms_nCurrentTextLine; + enum + { + MAX_LINES = 15, + MAX_STR_LEN = 80, + }; + + static int16 ms_nCurrentTextLine; + static char ms_aTextBuffer[MAX_LINES][MAX_STR_LEN]; public: static void DebugInitTextBuffer(); static void DebugDisplayTextBuffer(); - + static void DebugAddText(const char *str); }; + +extern bool gbDebugStuffInRelease; diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp index caf0cb3f..4364359a 100644 --- a/src/core/EventList.cpp +++ b/src/core/EventList.cpp @@ -5,10 +5,13 @@ #include "World.h" #include "Wanted.h" #include "EventList.h" +#include "Messages.h" +#include "Text.h" +#include "main.h" int32 CEventList::ms_nFirstFreeSlotIndex; -//CEvent gaEvent[NUMEVENTS]; -CEvent *gaEvent = (CEvent*)0x6EF830; +CEvent gaEvent[NUMEVENTS]; +//CEvent *gaEvent = (CEvent*)0x6EF830; enum { @@ -207,8 +210,20 @@ CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCar default: crime = CRIME_NONE; break; } - if(crime == CRIME_NONE) - return; +#ifdef VC_PED_PORTS + if (crime == CRIME_HIT_PED && ((CPed*)crimeId)->IsPointerValid() && + FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 && ((CPed*)crimeId)->m_ped_flagE2) { + + if(!((CPed*)crimeId)->DyingOrDead()) { + sprintf(gString, "$50 Good Citizen Bonus!"); + AsciiToUnicode(gString, gUString); + CMessages::AddBigMessage(gUString, 5000, 0); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 50; + } + } else +#endif + if(crime == CRIME_NONE) + return; CVector playerPedCoors = FindPlayerPed()->GetPosition(); CVector playerCoors = FindPlayerCoors(); diff --git a/src/core/EventList.h b/src/core/EventList.h index 2799fca4..1c03c9d6 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -63,4 +63,4 @@ public: static void ReportCrimeForEvent(eEventType type, int32, bool); }; -extern CEvent *gaEvent;
\ No newline at end of file +extern CEvent gaEvent[NUMEVENTS];
\ No newline at end of file diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 4c2f3afa..aff8a3ec 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -181,6 +181,7 @@ ScaleAndCenterX(float x) #endif #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS) + #ifdef PS2_LIKE_MENU #define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \ do { \ @@ -235,67 +236,100 @@ ScaleAndCenterX(float x) m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ } while(0) -#define ScrollUpListByOne() \ - do { \ - if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { \ - if (m_nFirstVisibleRowOnList > 0) { \ - m_nSelectedListRow--; \ - m_nFirstVisibleRowOnList--; \ - m_nCurListItemY -= LIST_HEIGHT / m_nTotalListRow; \ - } \ - } else { \ - m_nSelectedListRow--; \ - } \ - } while(0) +// --- Functions not in the game/inlined starts -#define ScrollDownListByOne() \ - do { \ - if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) { \ - if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { \ - m_nSelectedListRow++; \ - m_nFirstVisibleRowOnList++; \ - m_nCurListItemY += LIST_HEIGHT / m_nTotalListRow; \ - } \ - } else { \ - if (m_nSelectedListRow < m_nTotalListRow - 1) { \ - m_nSelectedListRow++; \ - } \ - } \ - } while(0) +inline void +CMenuManager::ScrollUpListByOne() +{ + if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { + if (m_nFirstVisibleRowOnList > 0) { + m_nSelectedListRow--; + m_nFirstVisibleRowOnList--; + m_nCurListItemY -= LIST_HEIGHT / m_nTotalListRow; + } + } else { + m_nSelectedListRow--; + } +} -#define PageUpList(playSoundOnSuccess) \ - do { \ - if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { \ - if (m_nFirstVisibleRowOnList > 0) { \ - if(playSoundOnSuccess) \ - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); \ - \ - m_nFirstVisibleRowOnList = max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); \ - m_nSelectedListRow = min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); \ - } else { \ - m_nFirstVisibleRowOnList = 0; \ - m_nSelectedListRow = 0; \ - } \ - m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; \ - } \ - } while(0) +inline void +CMenuManager::ScrollDownListByOne() +{ + if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) { + if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { + m_nSelectedListRow++; + m_nFirstVisibleRowOnList++; + m_nCurListItemY += LIST_HEIGHT / m_nTotalListRow; + } + } else { + if (m_nSelectedListRow < m_nTotalListRow - 1) { + m_nSelectedListRow++; + } + } +} -#define PageDownList(playSoundOnSuccess) \ - do { \ - if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { \ - if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { \ - if(playSoundOnSuccess) \ - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); \ - \ - m_nFirstVisibleRowOnList = min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); \ - m_nSelectedListRow = max(m_nSelectedListRow, m_nFirstVisibleRowOnList); \ - } else { \ - m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; \ - m_nSelectedListRow = m_nTotalListRow - 1; \ - } \ - m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; \ - } \ - } while(0) +inline void +CMenuManager::PageUpList(bool playSoundOnSuccess) +{ + if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { + if (m_nFirstVisibleRowOnList > 0) { + if(playSoundOnSuccess) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + + m_nFirstVisibleRowOnList = max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); + m_nSelectedListRow = min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); + } else { + m_nFirstVisibleRowOnList = 0; + m_nSelectedListRow = 0; + } + m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } +} + +inline void +CMenuManager::PageDownList(bool playSoundOnSuccess) +{ + if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { + if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { + if(playSoundOnSuccess) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + + m_nFirstVisibleRowOnList = min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); + m_nSelectedListRow = max(m_nSelectedListRow, m_nFirstVisibleRowOnList); + } else { + m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; + m_nSelectedListRow = m_nTotalListRow - 1; + } + m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } +} + +inline void +CMenuManager::ThingsToDoBeforeLeavingPage() +{ + if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + if (m_nPrefsAudio3DProviderIndex != -1) + m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); +#ifdef TIDY_UP_PBP + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); +#endif + } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + m_nDisplayVideoMode = m_nPrefsVideoMode; + } + + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + CPlayerSkin::EndFrontendSkinEdit(); + } + + if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { + m_nTotalListRow = 0; + } +} + +// ------ Functions not in the game/inlined ends void CMenuManager::BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2) @@ -1173,7 +1207,6 @@ void CMenuManager::DrawFrontEnd() bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT }; bbTabCount = 6; } - m_nCurrScreen = MENUPAGE_NEW_GAME; } else { if (bbTabCount != 8) { bbNames[0] = { "FEB_STA",MENUPAGE_STATS }; @@ -1186,8 +1219,8 @@ void CMenuManager::DrawFrontEnd() bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT }; bbTabCount = 8; } - m_nCurrScreen = MENUPAGE_STATS; } + m_nCurrScreen = bbNames[0].screenId; bottomBarActive = true; curBottomBarOption = 0; } @@ -1285,7 +1318,6 @@ void CMenuManager::DrawFrontEndNormal() eFrontendSprites currentSprite; switch (m_nCurrScreen) { case MENUPAGE_STATS: - case MENUPAGE_NEW_GAME: case MENUPAGE_START_MENU: case MENUPAGE_PAUSE_MENU: case MENUPAGE_EXIT: @@ -1315,7 +1347,7 @@ void CMenuManager::DrawFrontEndNormal() currentSprite = FE_ICONCONTROLS; break; default: - /* actually MENUPAGE_NEW_GAME too*/ + /*case MENUPAGE_NEW_GAME: */ /*case MENUPAGE_BRIEFS: */ currentSprite = FE_ICONBRIEF; break; @@ -1324,16 +1356,16 @@ void CMenuManager::DrawFrontEndNormal() m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); if (m_nMenuFadeAlpha < 255) { - static int LastFade = 0; + static uint32 LastFade = 0; if (m_nMenuFadeAlpha <= 0 && reverseAlpha) { reverseAlpha = false; ChangeScreen(pendingScreen, pendingOption, true, false); - } else if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ + } else { if (!reverseAlpha) - m_nMenuFadeAlpha += 20; + m_nMenuFadeAlpha += min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 20.0f; else - m_nMenuFadeAlpha = max(m_nMenuFadeAlpha - 30, 0); + m_nMenuFadeAlpha = max(0, m_nMenuFadeAlpha - min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 30.0f); LastFade = CTimer::GetTimeInMillisecondsPauseMode(); } @@ -1537,12 +1569,18 @@ void CMenuManager::DrawFrontEndNormal() } if (m_nMenuFadeAlpha < 255) { - static int LastFade = 0; + static uint32 LastFade = 0; + // Famous transparent menu bug. 33.0f = 1000.f/30.f (original frame limiter fps) +#ifdef FIX_BUGS + m_nMenuFadeAlpha += min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 20.0f; + LastFade = CTimer::GetTimeInMillisecondsPauseMode(); +#else if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ m_nMenuFadeAlpha += 20; LastFade = CTimer::GetTimeInMillisecondsPauseMode(); } +#endif if (m_nMenuFadeAlpha > 255){ m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); @@ -1950,7 +1988,7 @@ WRAPPER void CMenuManager::Process(void) { EAXJMP(0x485100); } #else void CMenuManager::Process(void) { - m_bMenuNotProcessed = false; + m_bMenuStateChanged = false; if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0) return; @@ -2701,6 +2739,8 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); bottomBarActive = false; + + // If there's a menu change with fade ongoing, finish it now if (reverseAlpha) m_nMenuFadeAlpha = 0; return; @@ -3116,51 +3156,43 @@ CMenuManager::ProcessButtonPresses(void) if (goBack) { CMenuManager::ResetHelperText(); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_EXIT, 0); - if (m_nCurrScreen == MENUPAGE_PAUSE_MENU && !m_bGameNotLoaded && !m_bMenuNotProcessed){ - if (CMenuManager::m_PrefsVsyncDisp != CMenuManager::m_PrefsVsync) { - CMenuManager::m_PrefsVsync = CMenuManager::m_PrefsVsyncDisp; - } - CMenuManager::RequestFrontEndShutDown(); - } else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT -#ifdef PS2_SAVE_DIALOG - || m_nCurrScreen == MENUPAGE_SAVE -#endif - ) { - CMenuManager::RequestFrontEndShutDown(); - } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); - } - - int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; - int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; - #ifdef PS2_LIKE_MENU - if (bottomBarActive){ - bottomBarActive = false; - if (!m_bGameNotLoaded) { + if (m_nCurrScreen == MENUPAGE_PAUSE_MENU || bottomBarActive) { +#else + if (m_nCurrScreen == MENUPAGE_PAUSE_MENU) { +#endif + if (!m_bGameNotLoaded && !m_bMenuStateChanged) { if (CMenuManager::m_PrefsVsyncDisp != CMenuManager::m_PrefsVsync) { CMenuManager::m_PrefsVsync = CMenuManager::m_PrefsVsyncDisp; } CMenuManager::RequestFrontEndShutDown(); } + + // We're already resuming, we don't need further processing. +#if defined(FIX_BUGS) || defined(PS2_LIKE_MENU) return; +#endif + } +#ifdef PS2_LIKE_MENU + else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT || m_nCurrScreen == MENUPAGE_SAVE) { +#else + else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) { +#endif + CMenuManager::RequestFrontEndShutDown(); + } + // It's now in ThingsToDoBeforeLeavingPage() +#ifndef TIDY_UP_PBP + else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); } #endif + int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; + int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; + if (oldScreen != -1) { - if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - } - if ((m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) && (m_nPrefsAudio3DProviderIndex != -1)) { - m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); - } - if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_nDisplayVideoMode = m_nPrefsVideoMode; - } - if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { - CPlayerSkin::EndFrontendSkinEdit(); - } + ThingsToDoBeforeLeavingPage(); #ifdef PS2_LIKE_MENU if (!bottomBarActive && @@ -3168,10 +3200,8 @@ CMenuManager::ProcessButtonPresses(void) bottomBarActive = true; } else #endif + { ChangeScreen(oldScreen, oldOption, true, true); - - if ((m_nPrevScreen == MENUPAGE_SKIN_SELECT) || (m_nPrevScreen == MENUPAGE_KEYBOARD_CONTROLS)) { - m_nTotalListRow = 0; } // We will go back for sure at this point, why process other things?! @@ -3512,11 +3542,16 @@ WRAPPER void CMenuManager::SwitchMenuOnAndOff() { EAXJMP(0x488790); } #else void CMenuManager::SwitchMenuOnAndOff() { - if (!!(CPad::GetPad(0)->NewState.Start && !CPad::GetPad(0)->OldState.Start) - || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { + bool menuWasActive = !!m_bMenuActive; - if (!m_bMenuActive) - m_bMenuActive = true; + // Reminder: You need REGISTER_START_BUTTON defined to make it work. + if (CPad::GetPad(0)->GetStartJustDown() +#ifdef FIX_BUGS + && !m_bGameNotLoaded +#endif + || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { + + m_bMenuActive = !m_bMenuActive; if (m_bShutDownFrontEndRequested) m_bMenuActive = false; @@ -3525,8 +3560,13 @@ void CMenuManager::SwitchMenuOnAndOff() if (m_bMenuActive) { CTimer::StartUserPause(); - } - else { + } else { +#ifdef PS2_LIKE_MENU + bottomBarActive = false; +#endif +#ifdef FIX_BUGS + ThingsToDoBeforeLeavingPage(); +#endif ShutdownJustMenu(); SaveSettings(); m_bStartUpFrontEndRequested = false; @@ -3553,7 +3593,7 @@ void CMenuManager::SwitchMenuOnAndOff() PcSaveHelper.PopulateSlotInfo(); m_nCurrOption = 0; } -/* // Unused? +/* // PS2 leftover? if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) { DMAudio.StopFrontEndTrack(); @@ -3561,8 +3601,8 @@ void CMenuManager::SwitchMenuOnAndOff() gMusicPlaying = 0; } */ - if (!m_bMenuActive) - m_bMenuNotProcessed = true; + if (m_bMenuActive != menuWasActive) + m_bMenuStateChanged = true; m_bStartUpFrontEndRequested = false; m_bShutDownFrontEndRequested = false; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 6d7327d3..3dbed164 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -403,7 +403,7 @@ public: int32 m_nHelperTextMsgId; bool m_bLanguageLoaded; bool m_bMenuActive; - bool m_bMenuNotProcessed; + bool m_bMenuStateChanged; bool m_bWaitingForNewKeyBind; bool m_bStartGameLoading; bool m_bFirstTime; @@ -540,8 +540,14 @@ public: void WaitForUserCD(); void PrintController(); - // New content: - uint8 GetNumberOfMenuOptions(); + // New (not in function or inlined in the game) + void ThingsToDoBeforeLeavingPage(); + void ScrollUpListByOne(); + void ScrollDownListByOne(); + void PageUpList(bool); + void PageDownList(bool); + + // uint8 GetNumberOfMenuOptions(); }; static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error"); diff --git a/src/core/Timer.h b/src/core/Timer.h index 89c4a430..ef525be7 100644 --- a/src/core/Timer.h +++ b/src/core/Timer.h @@ -2,7 +2,7 @@ class CTimer { -public: + static uint32 &m_snTimeInMilliseconds; static uint32 &m_snTimeInMillisecondsPauseMode; static uint32 &m_snTimeInMillisecondsNonClipped; @@ -11,19 +11,20 @@ public: static float &ms_fTimeScale; static float &ms_fTimeStep; static float &ms_fTimeStepNonClipped; +public: static bool &m_UserPause; static bool &m_CodePause; - static float GetTimeStep(void) { return ms_fTimeStep; } + static const float &GetTimeStep(void) { return ms_fTimeStep; } static void SetTimeStep(float ts) { ms_fTimeStep = ts; } static float GetTimeStepInSeconds() { return ms_fTimeStep / 50.0f; } static float GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; } - static float GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; } + static const float &GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; } static float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; } static void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; } - static uint32 GetFrameCounter(void) { return m_FrameCounter; } + static const uint32 &GetFrameCounter(void) { return m_FrameCounter; } static void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; } - static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; } + static const uint32 &GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; } static void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; } static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; } static void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; } @@ -31,7 +32,7 @@ public: static void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; } static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; } static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; } - static float GetTimeScale(void) { return ms_fTimeScale; } + static const float &GetTimeScale(void) { return ms_fTimeScale; } static void SetTimeScale(float ts) { ms_fTimeScale = ts; } static bool GetIsPaused() { return m_UserPause || m_CodePause; } diff --git a/src/core/config.h b/src/core/config.h index 9235e744..ff779946 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -101,6 +101,8 @@ enum Config { NUMPEDGROUPS = 31, NUMMODELSPERPEDGROUP = 8, + NUMROADBLOCKS = 600, + NUMVISIBLEENTITIES = 2000, NUMINVISIBLEENTITIES = 150, @@ -169,10 +171,11 @@ enum Config { #endif #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more -#define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. doesn't have too many things +#define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things // Pad #define KANGAROO_CHEAT +#define REGISTER_START_BUTTON // currently only in menu sadly. resumes the game // Hud, frontend and radar #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios @@ -199,5 +202,5 @@ enum Config { // Peds #define ANIMATE_PED_COL_MODEL #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle -#define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward +// #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward #define CANCELLABLE_CAR_ENTER diff --git a/src/core/obrstr.cpp b/src/core/obrstr.cpp new file mode 100644 index 00000000..3663d134 --- /dev/null +++ b/src/core/obrstr.cpp @@ -0,0 +1,119 @@ +#include "common.h"
+#include "Debug.h"
+#include "obrstr.h"
+
+char obrstr[128];
+char obrstr2[128];
+
+void ObrInt(int32 n1)
+{
+ IntToStr(n1, obrstr);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt2(int32 n1, int32 n2)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt3(int32 n1, int32 n2, int32 n3)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n4, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n4, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n5, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n4, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n5, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n6, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void IntToStr(int32 inNum, char *outStr)
+{
+ bool isNeg = inNum < 0;
+
+ if (isNeg) {
+ inNum = -inNum;
+ *outStr = '-';
+ }
+
+ int16 digits = 1;
+
+ if (inNum > 9) {
+ int32 _inNum = inNum;
+ do {
+ digits++;
+ _inNum /= 10;
+ } while (_inNum > 9);
+ }
+
+ int32 strSize = digits;
+ if (isNeg)
+ strSize++;
+
+ char *pStr = &outStr[strSize];
+ int32 i = 0;
+ do {
+ *(pStr-- - 1) = (inNum % 10) + '0';
+ inNum /= 10;
+ } while (++i < strSize);
+ outStr[strSize] = '\0';
+}
\ No newline at end of file diff --git a/src/core/obrstr.h b/src/core/obrstr.h new file mode 100644 index 00000000..6838afb5 --- /dev/null +++ b/src/core/obrstr.h @@ -0,0 +1,9 @@ +#pragma once
+
+void ObrInt(int32 n1);
+void ObrInt2(int32 n1, int32 n2);
+void ObrInt3(int32 n1, int32 n2, int32 n3);
+void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);
+void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5);
+void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
+void IntToStr(int32 inNum, char *outStr);
\ No newline at end of file diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 53ae1747..dae866a4 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -7,8 +7,11 @@ #include "Vehicle.h" #include "RpAnimBlend.h" #include "General.h" +#include "ZoneCull.h" +#include "PathFind.h" +#include "RoadBlocks.h" -WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); } +WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); } CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP) { @@ -58,11 +61,16 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP) m_bIsDisabledCop = false; field_1356 = 0; m_attackTimer = 0; - field_1351 = 0; + m_bBeatingSuspect = false; m_bZoneDisabledButClose = false; m_bZoneDisabled = false; field_1364 = -1; m_pPointGunAt = nil; + + // VC also initializes in here, but it keeps object +#ifdef FIX_BUGS + m_wRoadblockNode = -1; +#endif } CCopPed::~CCopPed() @@ -181,15 +189,15 @@ CCopPed::ClearPursuit(void) } } -// TO-DO: m_MaxCops in for loop may be a bug, check it out after CopAI +// TODO: I don't know why they needed that parameter. void -CCopPed::SetPursuit(bool iMayAlreadyBeInPursuit) +CCopPed::SetPursuit(bool ignoreCopLimit) { CWanted *wanted = FindPlayerPed()->m_pWanted; if (m_bIsInPursuit || !IsPedInControl()) return; - if (wanted->m_CurrentCops < wanted->m_MaxCops || iMayAlreadyBeInPursuit) { + if (wanted->m_CurrentCops < wanted->m_MaxCops || ignoreCopLimit) { for (int i = 0; i < wanted->m_MaxCops; ++i) { if (!wanted->m_pCops[i]) { m_bIsInPursuit = true; @@ -275,6 +283,274 @@ CCopPed::ScanForCrimes(void) } } +void +CCopPed::CopAI(void) +{ + CWanted *wanted = FindPlayerPed()->m_pWanted; + int wantedLevel = wanted->m_nWantedLevel; + CPhysical *playerOrHisVeh = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed(); + + if (wanted->m_bIgnoredByEveryone || wanted->m_bIgnoredByCops) { + if (m_nPedState != PED_ARREST_PLAYER) + ClearPursuit(); + + return; + } + if (CCullZones::NoPolice() && m_bIsInPursuit && !m_bIsDisabledCop) { + if (bHitSomethingLastFrame) { + m_bZoneDisabled = true; + m_bIsDisabledCop = true; +#ifdef FIX_BUGS + m_wRoadblockNode = -1; +#else + m_wRoadblockNode = 0; +#endif + bKindaStayInSamePlace = true; + bIsRunning = false; + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + SetIdle(); + ClearObjective(); + ClearPursuit(); + m_prevObjective = OBJECTIVE_NONE; + m_nLastPedState = PED_NONE; + SetAttackTimer(0); + if (m_fDistanceToTarget > 15.0f) + m_bZoneDisabledButClose = true; + } + } else if (m_bZoneDisabled && !CCullZones::NoPolice()) { + m_bZoneDisabled = false; + m_bIsDisabledCop = false; + m_bZoneDisabledButClose = false; + bKindaStayInSamePlace = false; + bCrouchWhenShooting = false; + bDuckAndCover = false; + ClearPursuit(); + } + if (wantedLevel > 0) { + if (!m_bIsDisabledCop) { + if (!m_bIsInPursuit || wanted->m_CurrentCops > wanted->m_MaxCops) { + CCopPed *copFarthestToTarget = nil; + float copFarthestToTargetDist = m_fDistanceToTarget; + + int oldCopNum = wanted->m_CurrentCops; + int maxCops = wanted->m_MaxCops; + + for (int i = 0; i < max(maxCops, oldCopNum); i++) { + CCopPed *cop = wanted->m_pCops[i]; + if (cop && cop->m_fDistanceToTarget > copFarthestToTargetDist) { + copFarthestToTargetDist = cop->m_fDistanceToTarget; + copFarthestToTarget = wanted->m_pCops[i]; + } + } + + if (m_bIsInPursuit) { + if (copFarthestToTarget && oldCopNum > maxCops) { + if (copFarthestToTarget == this && m_fDistanceToTarget > 10.0f) { + ClearPursuit(); + } else if(copFarthestToTargetDist > 10.0f) + copFarthestToTarget->ClearPursuit(); + } + } else { + if (oldCopNum < maxCops) { + SetPursuit(true); + } else { + if (m_fDistanceToTarget <= 10.0f || copFarthestToTarget && m_fDistanceToTarget < copFarthestToTargetDist) { + if (copFarthestToTarget && copFarthestToTargetDist > 10.0f) + copFarthestToTarget->ClearPursuit(); + + SetPursuit(true); + } + } + } + } else + SetPursuit(false); + + if (!m_bIsInPursuit) + return; + + if (wantedLevel > 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) + SetCurrentWeapon(WEAPONTYPE_COLT45); + else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) { + // i.e. if player is on top of car, cop will still use colt45. + SetCurrentWeapon(WEAPONTYPE_UNARMED); + } + + if (FindPlayerVehicle()) { + if (m_bBeatingSuspect) { + --wanted->m_CopsBeatingSuspect; + m_bBeatingSuspect = false; + } + if (m_fDistanceToTarget * FindPlayerSpeed().Magnitude() > 4.0f) + ClearPursuit(); + } + return; + } + float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange; + SetLookFlag(playerOrHisVeh, true); + TurnBody(); + SetCurrentWeapon(WEAPONTYPE_COLT45); + if (!bIsDucking) { + if (m_attackTimer >= CTimer::GetTimeInMilliseconds()) { + if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT && !m_bZoneDisabled) { + CVector targetDist = playerOrHisVeh->GetPosition() - GetPosition(); + if (m_fDistanceToTarget > 30.0f) { + CAnimBlendAssociation* crouchShootAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); + if (crouchShootAssoc) + crouchShootAssoc->blendDelta = -1000.0f; + + // Target is coming onto us + if (DotProduct(playerOrHisVeh->m_vecMoveSpeed, targetDist) > 0.0f) { + m_bIsDisabledCop = false; + bKindaStayInSamePlace = false; + bNotAllowedToDuck = false; + bDuckAndCover = false; + SetPursuit(false); + SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, FindPlayerPed()); + } + } else if (m_fDistanceToTarget < 5.0f + && (!FindPlayerVehicle() || FindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr() < sq(1.f/200.f))) { + m_bIsDisabledCop = false; + bKindaStayInSamePlace = false; + bNotAllowedToDuck = false; + bDuckAndCover = false; + } else { + // VC checks for != nil compared to buggy behaviour of III. I check for != -1 here. +#ifdef VC_PED_PORTS + float dotProd; + if (m_wRoadblockNode != -1) { + CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]]; + dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition()); + } else + dotProd = -1.0f; + + if(dotProd >= 0.0f) { +#else + +#ifndef FIX_BUGS + float copRoadDotProd, targetRoadDotProd; +#else + float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f; + if (m_wRoadblockNode != -1) +#endif + { + CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]]; + CVector2D roadFwd = roadBlockRoad->GetForward(); + copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd); + targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd); + } + // Roadblock may be towards road's fwd or opposite, so check both + if ((copRoadDotProd >= 0.0f || targetRoadDotProd >= 0.0f) + && (copRoadDotProd <= 0.0f || targetRoadDotProd <= 0.0f)) { +#endif + bIsPointingGunAt = true; + } else { + m_bIsDisabledCop = false; + bKindaStayInSamePlace = false; + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + bIsDucking = false; + bDuckAndCover = false; + SetPursuit(false); + } + } + } + } else { + if (m_fDistanceToTarget < weaponRange) { + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + CVector gunPos = weaponInfo->m_vecFireOffset; + for (RwFrame *i = GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) + RwV3dTransformPoints((RwV3d*)&gunPos, (RwV3d*)&gunPos, 1, RwFrameGetMatrix(i)); + + CColPoint foundCol; + CEntity *foundEnt; + if (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt, + false, true, false, false, true, false, false) + || foundEnt && foundEnt == playerOrHisVeh) { + m_pPointGunAt = playerOrHisVeh; + if (playerOrHisVeh) + playerOrHisVeh->RegisterReference((CEntity**) &m_pPointGunAt); + + SetAttack(playerOrHisVeh); + SetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000)); + } + SetAttackTimer(CGeneral::GetRandomNumberInRange(100, 300)); + } + SetMoveState(PEDMOVE_STILL); + } + } + } else { + if (!m_bIsDisabledCop || m_bZoneDisabled) { + if (m_nPedState != PED_AIM_GUN) { + if (m_bIsInPursuit) + ClearPursuit(); + + if (IsPedInControl()) { + // Entering the vehicle + if (m_pMyVehicle && !bInVehicle) { + if (m_pMyVehicle->IsLawEnforcementVehicle()) { + if (m_pMyVehicle->pDriver) { + if (m_pMyVehicle->pDriver->m_nPedType == PEDTYPE_COP) { + if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_pMyVehicle); + } else if (m_pMyVehicle->pDriver->IsPlayer()) { + FindPlayerPed()->SetWantedLevelNoDrop(1); + } + } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } + } else { + m_pMyVehicle = nil; + ClearObjective(); + SetWanderPath(CGeneral::GetRandomNumber() & 7); + } + } +#ifdef VC_PED_PORTS + else { + if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && CharCreatedBy == RANDOM_CHAR) { + for (int i = 0; i < m_numNearPeds; i++) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed->CharCreatedBy == RANDOM_CHAR) { + if ((nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->IsGangMember()) + && nearPed->IsPedInControl()) { + + bool anotherCopChasesHim = false; + if (nearPed->m_nPedState == PED_FLEE_ENTITY) { + if (nearPed->m_fleeFrom && nearPed->m_fleeFrom->IsPed() && + ((CPed*)nearPed->m_fleeFrom)->m_nPedType == PEDTYPE_COP) { + anotherCopChasesHim = true; + } + } + if (!anotherCopChasesHim) { + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, nearPed); + nearPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, this); + nearPed->m_ped_flagE2 = true; + return; + } + } + } + } + } + } +#endif + } + } + } else { + if (m_bIsInPursuit && m_nPedState != PED_AIM_GUN) + ClearPursuit(); + + m_bIsDisabledCop = false; + bKindaStayInSamePlace = false; + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + bIsDucking = false; + bDuckAndCover = false; + if (m_pMyVehicle) + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } + } +} + class CCopPed_ : public CCopPed { public: @@ -290,4 +566,5 @@ STARTPATCHES InjectHook(0x4C27D0, &CCopPed::SetPursuit, PATCH_JUMP); InjectHook(0x4C2C90, &CCopPed::ArrestPlayer, PATCH_JUMP); InjectHook(0x4C26A0, &CCopPed::ScanForCrimes, PATCH_JUMP); + InjectHook(0x4C1B50, &CCopPed::CopAI, PATCH_JUMP); ENDPATCHES diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index 7705eb12..142be56a 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -17,9 +17,9 @@ public: int8 field_1343; float m_fDistanceToTarget; int8 m_bIsInPursuit; - int8 m_bIsDisabledCop; + int8 m_bIsDisabledCop; // What disabled cop actually is? int8 field_1350; - int8 field_1351; + bool m_bBeatingSuspect; int8 m_bZoneDisabledButClose; int8 m_bZoneDisabled; int8 field_1354; @@ -40,6 +40,7 @@ public: void SetPursuit(bool); void ArrestPlayer(void); void ScanForCrimes(void); + void CopAI(void); }; static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error"); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index db6b7ee2..ae24faa3 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2720,6 +2720,10 @@ CPed::SetObjective(eObjective newObj, void *entity) return; } +#ifdef VC_PED_PORTS + SetObjectiveTimer(0); + ClearPointGunAt(); +#endif bObjectiveCompleted = false; if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) { if (m_objective != newObj) { @@ -3444,8 +3448,12 @@ CPed::ClearAll(void) m_fleeFrom = nil; m_fleeTimer = 0; bUsesCollision = true; +#ifdef VC_PED_PORTS + ClearPointGunAt(); +#else ClearAimFlag(); ClearLookFlag(); +#endif bIsPointingGunAt = false; bRenderPedInCar = true; bKnockedUpIntoAir = false; diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index d87764ff..6b674dd3 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -576,7 +576,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree } // Yeah, float float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier; - // maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse); + maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse); if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) { int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000); diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 8c851686..5288e67e 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -61,9 +61,9 @@ do {\ MakeSpaceForSizeInBufferPointer(presize, buf, postsize);\ save_func(buf, &size);\ CopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\ - if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, size + 4))\ + if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))\ return false;\ - totalSize += size;\ + totalSize += buf - work_buff;\ } while (0) bool @@ -74,7 +74,6 @@ GenericSave(int file) uint32 reserved; uint32 totalSize; - uint32 i; wchar *lastMissionPassed; wchar suffix[6]; @@ -85,13 +84,11 @@ GenericSave(int file) CheckSum = 0; buf = work_buff; reserved = 0; - totalSize = 0; // Save simple vars -INITSAVEBUF lastMissionPassed = TheText.Get(CStats::LastMissionPassedName); if (*lastMissionPassed) { - AsciiToUnicode("'...", suffix); + AsciiToUnicode("...'", suffix); TextCopy(saveName, lastMissionPassed); int len = UnicodeStrlen(saveName); saveName[len] = '\0'; @@ -104,20 +101,20 @@ INITSAVEBUF WriteDataToBufferPointer(buf, saveTime); WriteDataToBufferPointer(buf, SIZE_OF_ONE_GAME_IN_BYTES); WriteDataToBufferPointer(buf, CGame::currLevel); - WriteDataToBufferPointer(buf, TheCamera.m_matrix.m_matrix.pos.x); - WriteDataToBufferPointer(buf, TheCamera.m_matrix.m_matrix.pos.y); - WriteDataToBufferPointer(buf, TheCamera.m_matrix.m_matrix.pos.z); + WriteDataToBufferPointer(buf, TheCamera.GetPosition().x); + WriteDataToBufferPointer(buf, TheCamera.GetPosition().y); + WriteDataToBufferPointer(buf, TheCamera.GetPosition().z); WriteDataToBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute); WriteDataToBufferPointer(buf, CClock::ms_nLastClockTick); WriteDataToBufferPointer(buf, CClock::ms_nGameClockHours); WriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes); currPad = CPad::GetPad(0); WriteDataToBufferPointer(buf, currPad->Mode); - WriteDataToBufferPointer(buf, CTimer::m_snTimeInMilliseconds); - WriteDataToBufferPointer(buf, CTimer::ms_fTimeScale); - WriteDataToBufferPointer(buf, CTimer::ms_fTimeStep); - WriteDataToBufferPointer(buf, CTimer::ms_fTimeStepNonClipped); - WriteDataToBufferPointer(buf, CTimer::m_FrameCounter); + WriteDataToBufferPointer(buf, CTimer::GetTimeInMilliseconds()); + WriteDataToBufferPointer(buf, CTimer::GetTimeScale()); + WriteDataToBufferPointer(buf, CTimer::GetTimeStep()); + WriteDataToBufferPointer(buf, CTimer::GetTimeStepNonClipped()); + WriteDataToBufferPointer(buf, CTimer::GetFrameCounter()); WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep); WriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate); WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale); @@ -134,10 +131,8 @@ INITSAVEBUF WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList); WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator); WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator); -#ifdef VALIDATE_SAVE_SIZE - _saveBufCount = buf - work_buff; -#endif -VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS); + + assert(buf - work_buff == SIZE_OF_SIMPLEVARS); // Save scripts, block is nested within the same block as simple vars for some reason presize = buf; @@ -145,9 +140,10 @@ VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS); postsize = buf; CTheScripts::SaveAllScripts(buf, &size); CopySizeAndPreparePointer(presize, buf, postsize, reserved, size); - if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, size + SIZE_OF_SIMPLEVARS + 4)) + if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff)) return false; - totalSize += size + SIZE_OF_SIMPLEVARS; + + totalSize = buf - work_buff; // Save the rest WRITE_BLOCK(CPools::SavePedPool); @@ -171,8 +167,7 @@ VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS); WRITE_BLOCK(CPedType::Save); // Write padding - i = 0; - do { + for (int i = 0; i < 4; i++) { size = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4); if (size > sizeof(work_buff)) size = sizeof(work_buff); @@ -181,15 +176,15 @@ VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS); return false; totalSize += size; } - i++; - } while (i < 4); + } // Write checksum and close CFileMgr::Write(file, (const char *) &CheckSum, sizeof(CheckSum)); if (CFileMgr::GetErrorReadWrite(file)) { PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; - if (CloseFile(file)) + if (!CloseFile(file)) PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE; + return false; } diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 2702bd6e..e94db6db 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -38,7 +38,7 @@ C_PcSave::SaveSlot(int32 slot) if (file != 0) { DoGameSpecificStuffBeforeSave(); if (GenericSave(file)) { - if (CFileMgr::CloseFile(file) != 0) + if (!!CFileMgr::CloseFile(file)) nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE; return true; } @@ -55,21 +55,21 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size) CFileMgr::Write(file, (const char*)&size, sizeof(size)); if (CFileMgr::GetErrorReadWrite(file)) { nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; - strncpy(SaveFileNameJustSaved, ValidSaveName, 259); + strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1); return false; } CFileMgr::Write(file, (const char*)data, align4bytes(size)); - CheckSum += ((uint8*)&size)[0]; - CheckSum += ((uint8*)&size)[1]; - CheckSum += ((uint8*)&size)[2]; - CheckSum += ((uint8*)&size)[3]; + CheckSum += (uint8) size; + CheckSum += (uint8) (size >> 8); + CheckSum += (uint8) (size >> 16); + CheckSum += (uint8) (size >> 24); for (int i = 0; i < align4bytes(size); i++) { CheckSum += *data++; } if (CFileMgr::GetErrorReadWrite(file)) { nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; - strncpy(SaveFileNameJustSaved, ValidSaveName, 259); + strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1); return false; } |