From a5ba53896881ec479f9819ab0349437de4c3f4ed Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 23 Jun 2019 13:11:41 +0200 Subject: [PATCH 01/17] some Radar and Hud cleanup; fix in Physical --- src/Radar.cpp | 282 ++++++++++++++++++-------------------- src/Radar.h | 28 ++-- src/Streaming.h | 1 + src/World.cpp | 2 +- src/World.h | 2 +- src/config.h | 3 +- src/entities/Physical.cpp | 2 +- src/math/Rect.h | 16 +++ src/render/Hud.cpp | 6 +- 9 files changed, 177 insertions(+), 165 deletions(-) diff --git a/src/Radar.cpp b/src/Radar.cpp index dd94341a..2dd471f1 100644 --- a/src/Radar.cpp +++ b/src/Radar.cpp @@ -15,14 +15,12 @@ WRAPPER void CRadar::Draw3dMarkers() { EAXJMP(0x4A4C70); } WRAPPER int CRadar::ClipRadarPoly(CVector2D *out, CVector2D *in) { EAXJMP(0x4A64A0); } -WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D *out, CVector2D *in) { EAXJMP(0x4A5300); } +WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } float &CRadar::m_RadarRange = *(float*)0x8E281C; -CVector2D &CRadar::vec2DRadarOrigin = *(CVector2D*)0x6299B8; CBlip *CRadar::ms_RadarTrace = (CBlip*)0x6ED5E0; -float CRadar::cachedSin; -float CRadar::cachedCos; +CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8; int *gRadarTxdIds = (int*)0x6299C0; CSprite2d *CRadar::AsukaSprite = (CSprite2d*)0x8F1A40; @@ -70,6 +68,13 @@ CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { WeaponSprite }; +#define RADAR_NUM_TILES (8) + +#define RADAR_MIN_RANGE (120.0f) +#define RADAR_MAX_RANGE (350.0f) +#define RADAR_MIN_SPEED (0.3f) +#define RADAR_MAX_SPEED (0.9f) + #if 0 WRAPPER void CRadar::DrawMap () { EAXJMP(0x4A4200); } #else @@ -77,21 +82,19 @@ void CRadar::DrawMap() { if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { if (FindPlayerVehicle()) { - if (FindPlayerVehicle()->GetSpeed().Magnitude() > 0.3f) { - if (FindPlayerVehicle()->GetSpeed().Magnitude() > 0.9f) - CRadar::m_RadarRange = 350.0f; - else - CRadar::m_RadarRange = (FindPlayerVehicle()->GetSpeed().Magnitude() + 0.3f) * 200.0f; - } + float speed = FindPlayerSpeed().Magnitude(); + if (speed < RADAR_MIN_SPEED) + m_RadarRange = RADAR_MIN_RANGE; + else if (speed < RADAR_MAX_SPEED) + m_RadarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE; else - CRadar::m_RadarRange = 120.0f; + m_RadarRange = RADAR_MAX_RANGE; } else - CRadar::m_RadarRange = 120.0f; + m_RadarRange = RADAR_MIN_RANGE; - vec2DRadarOrigin.x = FindPlayerCentreOfWorld_NoSniperShift().x; - vec2DRadarOrigin.y = FindPlayerCentreOfWorld_NoSniperShift().y; - CRadar::DrawRadarMap(); + vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); + DrawRadarMap(); } } #endif @@ -101,7 +104,7 @@ WRAPPER void CRadar::DrawRadarMask() { EAXJMP(0x4A69C0); } #else void CRadar::DrawRadarMask() { - CVector2D vec2d[4] = { + CVector2D corners[4] = { CVector2D(1.0f, -1.0f), CVector2D(1.0f, 1.0f), CVector2D(-1.0f, 1.0f), @@ -122,19 +125,18 @@ void CRadar::DrawRadarMask() CVector2D out[8]; CVector2D in; + // Draw the shape we want to mask out from the radar in four segments for (int i = 0; i < 4; i++) { - in.x = vec2d[i].x; - in.y = vec2d[i].y; - - CRadar::TransformRadarPointToScreenSpace(out, &in); + // First point is always the corner itself + in.x = corners[i].x; + in.y = corners[i].y; + TransformRadarPointToScreenSpace(out[0], in); + // Then generate a quarter of the circle for (int j = 0; j < 7; j++) { - CRadar::cachedCos = cos(j * (PI / 2.0f / 6.0f)); - CRadar::cachedSin = sin(j * (PI / 2.0f / 6.0f)); - - in.x = vec2d[i].x * cachedCos; - in.y = vec2d[i].y * cachedSin; - CRadar::TransformRadarPointToScreenSpace(&out[j + 1], &in); + in.x = corners[i].x * cos(j * (PI / 2.0f / 6.0f)); + in.y = corners[i].y * sin(j * (PI / 2.0f / 6.0f)); + TransformRadarPointToScreenSpace(out[j + 1], in); }; CSprite2d::SetMaskVertices(8, (float *)out); @@ -163,7 +165,7 @@ void CRadar::SetRadarMarkerState(int counter, int flag) break; default: return; - }; + } if (e) e->bHasBlip = flag; @@ -176,9 +178,9 @@ WRAPPER void CRadar::ClearBlipForEntity(eBlipType type, int32 id) { EAXJMP(0x4A5 #else void CRadar::ClearBlipForEntity(eBlipType type, int32 id) { - for (int i = 0; i < 32; i++) { + for (int i = 0; i < NUMRADARBLIPS; i++) { if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) { - CRadar::SetRadarMarkerState(i, 0); + SetRadarMarkerState(i, 0); ms_RadarTrace[i].m_bInUse = 0; ms_RadarTrace[i].m_eBlipType = 0; ms_RadarTrace[i].m_eBlipDisplay = 0; @@ -200,13 +202,13 @@ void CRadar::DrawRadarSection(int x, int y) void CRadar::RequestMapSection(int x, int y) { ClipRadarTileCoords(&x, &y); - CStreaming::RequestModel(gRadarTxdIds[x + 8 * y] + 5500, 5); + CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_DEPENDENCY); } void CRadar::RemoveMapSection(int x, int y) { if (x >= 0 && x <= 7 && y >= 0 && y <= 7) - CStreaming::RemoveModel(gRadarTxdIds[x + 8 * y] + 5500); + CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]); } #if 0 @@ -214,8 +216,8 @@ WRAPPER void CRadar::StreamRadarSections(int x, int y) { EAXJMP(0x4A6100); } #else void CRadar::StreamRadarSections(int x, int y) { - for (int i = 0; i < 8; ++i) { - for (int j = 0; j < 8; ++j) { + for (int i = 0; i < RADAR_NUM_TILES; ++i) { + for (int j = 0; j < RADAR_NUM_TILES; ++j) { if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1)) RequestMapSection(i, j); else @@ -226,29 +228,31 @@ void CRadar::StreamRadarSections(int x, int y) #endif #if 0 -WRAPPER float CRadar::LimitRadarPoint(CVector2D *point) { EAXJMP(0x4A4F30); } +WRAPPER float CRadar::LimitRadarPoint(CVector2D &point) { EAXJMP(0x4A4F30); } #else -float CRadar::LimitRadarPoint(CVector2D *point) +float CRadar::LimitRadarPoint(CVector2D &point) { - float div; + float dist, invdist; - if (point->Magnitude() > 1.0f) { - div = 1.0f / point->Magnitude(); - point->x *= div; - point->y *= div; + dist = point.Magnitude(); + if (dist > 1.0f) { + invdist = 1.0f / dist; + point.x *= invdist; + point.y *= invdist; } - return point->Magnitude(); + return dist; } #endif #if 0 -WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D *out, CVector2D *in, int x, int y) { EAXJMP(0x4A5530); } +WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) { EAXJMP(0x4A5530); } #else -void CRadar::TransformRealWorldToTexCoordSpace(CVector2D *out, CVector2D *in, int x, int y) { - out->x = in->x - (x * 500.0f - WORLD_MAX_X); - out->y = -(in->y - ((8 - y) * 500.0f - WORLD_MAX_Y)); - out->x *= 0.002f; - out->y *= 0.002f; +void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) +{ + out.x = in.x - (x * 500.0f + WORLD_MIN_X); + out.y = -(in.y - ((RADAR_NUM_TILES - y) * 500.0f + WORLD_MIN_Y)); + out.x /= 500.0f; + out.y /= 500.0f; } #endif @@ -257,11 +261,11 @@ WRAPPER void CRadar::DrawRadarMap() { EAXJMP(0x4A6C20); } #else void CRadar::DrawRadarMap() { - CRadar::DrawRadarMask(); + DrawRadarMask(); - int x = floorf((WORLD_MAX_X + vec2DRadarOrigin.x) * 0.002f); - int y = round(7.0f - (WORLD_MAX_Y + vec2DRadarOrigin.y) * 0.002f); - CRadar::StreamRadarSections(x, y); + int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / 500.0f); + int y = round(7.0f - (vec2DRadarOrigin.y - WORLD_MIN_Y) / 500.0f); + StreamRadarSections(x, y); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); @@ -274,15 +278,15 @@ void CRadar::DrawRadarMap() RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE); - CRadar::DrawRadarSection(x - 1, y - 1); - CRadar::DrawRadarSection(x, y - 1); - CRadar::DrawRadarSection(x + 1, y - 1); - CRadar::DrawRadarSection(x - 1, y); - CRadar::DrawRadarSection(x, y); - CRadar::DrawRadarSection(x + 1, y); - CRadar::DrawRadarSection(x - 1, y + 1); - CRadar::DrawRadarSection(x, y + 1); - CRadar::DrawRadarSection(x + 1, y + 1); + DrawRadarSection(x - 1, y - 1); + DrawRadarSection(x, y - 1); + DrawRadarSection(x + 1, y - 1); + DrawRadarSection(x - 1, y); + DrawRadarSection(x, y); + DrawRadarSection(x + 1, y); + DrawRadarSection(x - 1, y + 1); + DrawRadarSection(x, y + 1); + DrawRadarSection(x + 1, y + 1); } #endif @@ -301,7 +305,7 @@ void CRadar::DrawBlips() CVector2D out; CVector2D in = CVector2D(0.0f, 0.0f); - CRadar::TransformRadarPointToScreenSpace(&out, &in); + TransformRadarPointToScreenSpace(out, in); float angle; if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1) @@ -309,20 +313,20 @@ void CRadar::DrawBlips() else angle = FindPlayerHeading() - (PI + atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - CRadar::DrawRotatingRadarSprite(CentreSprite, out.x, out.y, angle, 255); + DrawRotatingRadarSprite(CentreSprite, out.x, out.y, angle, 255); CVector2D vec2d; vec2d.x = vec2DRadarOrigin.x; vec2d.y = M_SQRT2 * m_RadarRange + vec2DRadarOrigin.y; - CRadar::TransformRealWorldPointToRadarSpace(&in, &vec2d); - CRadar::LimitRadarPoint(&in); - CRadar::TransformRadarPointToScreenSpace(&out, &in); - CRadar::DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255); + TransformRealWorldPointToRadarSpace(in, vec2d); + LimitRadarPoint(in); + TransformRadarPointToScreenSpace(out, in); + DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255); /* DrawEntityBlip */ - for (int i = 0; i < 32; i++) { + for (int i = 0; i < NUMRADARBLIPS; i++) { if (ms_RadarTrace[i].m_bInUse) { if (ms_RadarTrace[i].m_eBlipType <= BLIP_OBJECT) { CEntity *e = nil; @@ -341,7 +345,7 @@ void CRadar::DrawBlips() if (e) { if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { if (CTheScripts::DbgFlag) { - CRadar::ShowRadarMarker(e->GetPosition(), GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim), ms_RadarTrace->m_Radius); + ShowRadarMarker(e->GetPosition(), GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim), ms_RadarTrace->m_Radius); ms_RadarTrace[i].m_Radius = ms_RadarTrace[i].m_Radius - 0.1f; if (ms_RadarTrace[i].m_Radius >= 1.0f) @@ -350,17 +354,17 @@ void CRadar::DrawBlips() } if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { vec2d = e->GetPosition(); - CRadar::TransformRealWorldPointToRadarSpace(&in, &vec2d); - float dist = CRadar::LimitRadarPoint(&in); - int a = CRadar::CalculateBlipAlpha(dist); - CRadar::TransformRadarPointToScreenSpace(&out, &in); + TransformRealWorldPointToRadarSpace(in, vec2d); + float dist = LimitRadarPoint(in); + int a = CalculateBlipAlpha(dist); + TransformRadarPointToScreenSpace(out, in); - CRGBA col = CRadar::GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); + CRGBA col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); if (ms_RadarTrace[i].m_IconID) - CRadar::DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); + DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); else - CRadar::ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); } } } @@ -372,7 +376,7 @@ void CRadar::DrawBlips() if (ms_RadarTrace[i].m_eBlipType != BLIP_CONTACT_POINT || ms_RadarTrace[i].m_eBlipType == BLIP_CONTACT_POINT && DisplayThisBlip(i) || !CTheScripts::IsPlayerOnAMission()) { if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { if (CTheScripts::DbgFlag) { - CRadar::ShowRadarMarker(ms_RadarTrace[i].m_vecPos, CRadar::GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim), ms_RadarTrace->m_Radius); + ShowRadarMarker(ms_RadarTrace[i].m_vecPos, GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim), ms_RadarTrace->m_Radius); ms_RadarTrace[i].m_Radius = ms_RadarTrace[i].m_Radius - 0.1f; if (ms_RadarTrace[i].m_Radius >= 1.0f) ms_RadarTrace[i].m_Radius = 5.0f; @@ -380,17 +384,17 @@ void CRadar::DrawBlips() } if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { - CRadar::TransformRealWorldPointToRadarSpace(&in, &ms_RadarTrace[i].m_vec2DPos); - float dist = CRadar::LimitRadarPoint(&in); - int a = CRadar::CalculateBlipAlpha(dist); - CRadar::TransformRadarPointToScreenSpace(&out, &in); + TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[i].m_vec2DPos); + float dist = LimitRadarPoint(in); + int a = CalculateBlipAlpha(dist); + TransformRadarPointToScreenSpace(out, in); - CRGBA col = CRadar::GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); + CRGBA col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); - if (CRadar::ms_RadarTrace[i].m_IconID) - CRadar::DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); + if (ms_RadarTrace[i].m_IconID) + DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); else - CRadar::ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); } } } @@ -454,46 +458,44 @@ CRGBA CRadar::GetRadarTraceColour(uint32 color, bool bright) } } -void CRadar::TransformRadarPointToScreenSpace(CVector2D *out, CVector2D *in) +// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) +void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) { - out->x = in->x * SCREEN_SCALE_X(47.0f) + SCREEN_SCALE_X(47.0f + 20.0f); - out->y = (SCREEN_SCALE_Y(76.0f)) * 0.5f + SCREEN_HEIGHT - (SCREEN_SCALE_Y(123.0f)) - in->y * (SCREEN_SCALE_Y(76.0f)) * 0.5f; + // FIX: game doesn't scale RADAR_LEFT here + out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); + out.y = (1.0f - in.y)*0.5f*SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT); } #if 0 -WRAPPER void CRadar::TransformRealWorldPointToRadarSpace(CVector2D *out, CVector2D *in) { EAXJMP(0x4A50D0); } +WRAPPER void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A50D0); } #else -void CRadar::TransformRealWorldPointToRadarSpace(CVector2D *out, CVector2D *in) -{ - if (TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_TOPDOWN1 && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_TOPDOWNPED) { - if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { - cachedSin = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - cachedCos = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - } - else { - CVector vecCamera; +void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) +{ + float s, c; + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { + s = 0.0f; + c = 1.0f; + } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { + s = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + } else { + CVector forward; - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { - vecCamera = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->m_matrix.m_matrix.up; - vecCamera.Normalise(); - } - else - vecCamera = TheCamera.GetForward(); - - cachedSin = sin(atan2(-vecCamera.x, vecCamera.y)); - cachedCos = cos(atan2(-vecCamera.x, vecCamera.y)); - } - } - else { - cachedSin = 0.0f; - cachedCos = 1.0f; + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); + forward.Normalise(); // a bit useless... + } else + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + + s = sin(atan2(-forward.x, forward.y)); + c = cos(atan2(-forward.x, forward.y)); } - float x = (in->x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); - float y = (in->y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); + float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); + float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); - out->x = cachedSin * y + cachedCos * x; - out->y = cachedCos * y - cachedSin * x; + out.x = s * y + c * x; + out.y = c * y - s * x; } #endif @@ -501,7 +503,7 @@ void CRadar::TransformRealWorldPointToRadarSpace(CVector2D *out, CVector2D *in) WRAPPER void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) { EAXJMP(0x4A5EF0); } #else void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) -{ +{ RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); } #endif @@ -520,37 +522,25 @@ void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 gr WRAPPER void CRadar::ShowRadarMarker(CVector pos, CRGBA color, float radius) { EAXJMP(0x4A59C0); } #else void CRadar::ShowRadarMarker(CVector pos, CRGBA color, float radius) { - float z2 = pos.z + (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.at.z; - float y2 = (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.at.y + pos.y; - float x2 = (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.at.x + pos.x; - float z1 = pos.z + (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.at.z; - float y1 = (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.at.y + pos.y; - float x1 = (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.at.x + pos.x; - CTheScripts::ScriptDebugLine3D(x1, y1, z1, x2, y2, z2, color.color32, color.color32); + float f1 = radius * 0.5f; + float f2 = radius * 1.4f; + CVector p1, p2; - z2 = pos.z - (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.at.x; - y2 = pos.y - (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.at.x; - x2 = pos.x - (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.at.x; - z1 = pos.z - (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.at.x; - y1 = pos.y - (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.at.x; - x1 = pos.x - (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.at.x; - CTheScripts::ScriptDebugLine3D(x1, y1, z1, x2, y2, z2, color.color32, color.color32); + p1 = pos + TheCamera.GetUp()*f1; + p2 = pos + TheCamera.GetUp()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); - z2 = (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.right.x + pos.z; - y2 = (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.right.x + pos.y; - x2 = (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.right.x + pos.x; - z1 = (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.right.x + pos.z; - y1 = (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.right.x + pos.y; - x1 = (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.right.x + pos.x; - CTheScripts::ScriptDebugLine3D(x1, y1, z1, x2, y2, z2, color.color32, color.color32); + p1 = pos - TheCamera.GetUp()*f1; + p2 = pos - TheCamera.GetUp()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); - z2 = pos.z - (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.right.x; - y2 = pos.y - (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.right.x; - x2 = pos.x - (0.5f * color.color32) * TheCamera.m_matrix.m_matrix.right.x; - z1 = pos.z - (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.right.x; - y1 = pos.y - (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.right.x; - x1 = pos.x - (1.4f * color.color32) * TheCamera.m_matrix.m_matrix.right.x; - CTheScripts::ScriptDebugLine3D(x1, y1, z1, x2, y2, z2, color.color32, color.color32); + p1 = pos + TheCamera.GetRight()*f1; + p2 = pos + TheCamera.GetRight()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); + + p1 = pos - TheCamera.GetRight()*f1; + p2 = pos - TheCamera.GetRight()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); } #endif @@ -577,8 +567,8 @@ void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float for (uint32 i = 0; i < 4; i++) { oldPosn[i] = curPosn[i]; - curPosn[i].x = x + (oldPosn[i].x - x) * cosf(angle) + (oldPosn[i].y - y) * sinf(angle); - curPosn[i].y = y - (oldPosn[i].x - x) * sinf(angle) + (oldPosn[i].y - y) * cosf(angle); + curPosn[i].x = x + (oldPosn[i].x - x) * cosf(angle) + (oldPosn[i].y - y) * sinf(angle); + curPosn[i].y = y - (oldPosn[i].x - x) * sinf(angle) + (oldPosn[i].y - y) * cosf(angle); } sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha)); diff --git a/src/Radar.h b/src/Radar.h index 19fc9038..9e687e24 100644 --- a/src/Radar.h +++ b/src/Radar.h @@ -53,26 +53,26 @@ struct CBlip CVector2D m_vec2DPos; CVector m_vecPos; int16 m_BlipIndex; - int8 m_bDim; - int8 m_bInUse; + bool m_bDim; + bool m_bInUse; float m_Radius; int16 m_wScale; int16 m_eBlipDisplay; // eBlipDisplay int16 m_IconID; // eRadarSprite - char gap_46[2]; }; - static_assert(sizeof(CBlip) == 0x30, "CBlip: error"); +// Values for screen space +#define RADAR_LEFT (40.0f) +#define RADAR_BOTTOM (47.0f) +#define RADAR_WIDTH (94.0f) +#define RADAR_HEIGHT (76.0f) + class CRadar { - static float cachedSin; - static float cachedCos; - public: static float &m_RadarRange; - static CVector2D &vec2DRadarOrigin; - static CBlip *ms_RadarTrace; + static CBlip *ms_RadarTrace; //[NUMRADARBLIPS] static CSprite2d *AsukaSprite; static CSprite2d *BombSprite; static CSprite2d *CatSprite; @@ -101,19 +101,15 @@ public: static void DrawMap(); static void StreamRadarSections(int x, int y); static int ClipRadarPoly(CVector2D *out, CVector2D *in); - static void TransformRealWorldToTexCoordSpace(CVector2D *out, CVector2D *in, int x, int y); - static void TransformRadarPointToRealWorldSpace(CVector2D *out, CVector2D *in); static void DrawRadarSection(int x, int y); static void RequestMapSection(int x, int y); static void RemoveMapSection(int x, int y); - static void TransformRadarPointToScreenSpace(CVector2D * out, CVector2D * in); static void DrawBlips(); static int CalculateBlipAlpha(float dist); static CRGBA GetRadarTraceColour(uint32 color, bool bright); static void DrawRadarMap(); static void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha); - static void TransformRealWorldPointToRadarSpace(CVector2D *out, CVector2D *in); - static float LimitRadarPoint(CVector2D *point); + static float LimitRadarPoint(CVector2D &point); static void DrawRadarSprite(int sprite, float x, float y, int alpha); static void ShowRadarMarker(CVector pos, CRGBA color, float radius); static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha); @@ -122,4 +118,8 @@ public: static bool DisplayThisBlip(int counter); static void GetTextureCorners(int x, int y, CVector2D * out); static void ClipRadarTileCoords(int *x, int *y); + static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y); + static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in); + static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in); + static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in); }; diff --git a/src/Streaming.h b/src/Streaming.h index 93c2e73e..fc14829c 100644 --- a/src/Streaming.h +++ b/src/Streaming.h @@ -111,6 +111,7 @@ public: static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags); static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags); static void RemoveModel(int32 id); + static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); } static bool IsTxdUsedByRequestedModels(int32 txdId); static bool AddToLoadedVehiclesList(int32 modelId); diff --git a/src/World.cpp b/src/World.cpp index bc29a527..e99668ec 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -592,6 +592,6 @@ WRAPPER CPed *FindPlayerPed(void) { EAXJMP(0x4A1150); } WRAPPER CVector &FindPlayerCoors(CVector &v) { EAXJMP(0x4A1030); } WRAPPER CVehicle *FindPlayerVehicle(void) { EAXJMP(0x4A10C0); } WRAPPER CVehicle *FindPlayerTrain(void) { EAXJMP(0x4A1120); } -WRAPPER CVector FindPlayerSpeed(void) { EAXJMP(0x4A1090); } +WRAPPER CVector &FindPlayerSpeed(void) { EAXJMP(0x4A1090); } WRAPPER CVector FindPlayerCentreOfWorld_NoSniperShift(void) { EAXJMP(0x4A11C0); } WRAPPER float FindPlayerHeading(void) { EAXJMP(0x4A1220); } diff --git a/src/World.h b/src/World.h index b099583b..c8fe827d 100644 --- a/src/World.h +++ b/src/World.h @@ -111,6 +111,6 @@ CPed *FindPlayerPed(void); CVector &FindPlayerCoors(CVector &v); CVehicle *FindPlayerVehicle(void); CVehicle *FindPlayerTrain(void); -CVector FindPlayerSpeed(void); +CVector &FindPlayerSpeed(void); CVector FindPlayerCentreOfWorld_NoSniperShift(void); float FindPlayerHeading(void); diff --git a/src/config.h b/src/config.h index a8b8fe6b..7c228e60 100644 --- a/src/config.h +++ b/src/config.h @@ -57,7 +57,8 @@ enum Config { NUMCORONAS = 56, NUMPOINTLIGHTS = 32, - NUMONSCREENTIMERENTRIES = 1 + NUMONSCREENTIMERENTRIES = 1, + NUMRADARBLIPS = 32, }; #define GTA3_1_1_PATCH diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index adc53525..b35b2d11 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1504,7 +1504,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) else if(A->GetUp().z > 0.3f) adhesion = 0.0f; else - adhesion *= max(5.0f, 0.03f*impulseA + 1.0f); + adhesion *= min(5.0f, 0.03f*impulseA + 1.0f); } if(A->ApplyFriction(adhesion, aColPoints[i])) diff --git a/src/math/Rect.h b/src/math/Rect.h index d0824987..fd1bd05e 100644 --- a/src/math/Rect.h +++ b/src/math/Rect.h @@ -26,4 +26,20 @@ public: if(v.y < top) top = v.y; if(v.y > bottom) bottom = v.y; } + + void Translate(float x, float y){ + left += x; + right += x; + bottom += y; + top += y; + } + void Grow(float r){ + left -= r; + right += r; + top -= r; + bottom += r; + } + + float GetWidth(void) { return right - left; } + float GetHeight(void) { return bottom - top; } }; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 23a796e6..a17d5c2c 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -856,7 +856,11 @@ void CHud::Draw() */ if (CHud::m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || CHud::m_ItemToFlash != ITEM_RADAR) { CRadar::DrawMap(); - CHud::Sprites[HUD_RADARDISC].Draw(CRect(SCREEN_SCALE_X(16.0f), SCREEN_SCALE_FROM_BOTTOM(123.0f + 4.0f), SCREEN_SCALE_X(94.0f + 20.0f + 5.0f), SCREEN_SCALE_FROM_BOTTOM(-76.0f + 123.0f - 6.0f)), CRGBA(0, 0, 0, 255)); + CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT)); + // FIX: game doesn't scale RADAR_LEFT here + rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); + rect.Grow(4.0f); + CHud::Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); CRadar::DrawBlips(); } } From 4d84d94166772adf112652becf90f07f38e47ff4 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 23 Jun 2019 19:59:58 +0200 Subject: [PATCH 02/17] more Radar code --- src/Radar.cpp | 366 ++++++++++++++++++++++++++++++++++++++++++----- src/Radar.h | 8 +- src/RwHelper.cpp | 17 +++ src/RwHelper.h | 1 + 4 files changed, 352 insertions(+), 40 deletions(-) diff --git a/src/Radar.cpp b/src/Radar.cpp index 2dd471f1..90d27af2 100644 --- a/src/Radar.cpp +++ b/src/Radar.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "RwHelper.h" #include "Radar.h" #include "Camera.h" #include "Hud.h" @@ -14,8 +15,6 @@ #include "Streaming.h" WRAPPER void CRadar::Draw3dMarkers() { EAXJMP(0x4A4C70); } -WRAPPER int CRadar::ClipRadarPoly(CVector2D *out, CVector2D *in) { EAXJMP(0x4A64A0); } -WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } float &CRadar::m_RadarRange = *(float*)0x8E281C; CBlip *CRadar::ms_RadarTrace = (CBlip*)0x6ED5E0; @@ -69,6 +68,8 @@ CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { }; #define RADAR_NUM_TILES (8) +#define RADAR_TILE_SIZE (WORLD_SIZE_X / RADAR_NUM_TILES) +static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not a square"); #define RADAR_MIN_RANGE (120.0f) #define RADAR_MAX_RANGE (350.0f) @@ -190,18 +191,221 @@ void CRadar::ClearBlipForEntity(eBlipType type, int32 id) } #endif -#if 1 +bool +IsPointInsideRadar(const CVector2D &point) +{ + if(point.x < -1.0f || point.x > 1.0f) return false; + if(point.y < -1.0f || point.y > 1.0f) return false; + return true; +} + +// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1 +int +LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2) +{ + float d1, d2; + float t; + float x, y; + float shortest = 1.0f; + int edge = -1; + + // clip against left edge, x = -1.0 + d1 = -1.0f - p1.x; + d2 = -1.0f - p2.x; + if(d1 * d2 < 0.0f){ + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + y = (p2.y - p1.y)*t + p1.y; + if(y >= -1.0f && y <= 1.0f && t <= shortest){ + out.x = -1.0f; + out.y = y; + edge = 3; + shortest = t; + } + } + + // clip against right edge, x = 1.0 + d1 = p1.x - 1.0f; + d2 = p2.x - 1.0f; + if(d1 * d2 < 0.0f){ + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + y = (p2.y - p1.y)*t + p1.y; + if(y >= -1.0f && y <= 1.0f && t <= shortest){ + out.x = 1.0f; + out.y = y; + edge = 1; + shortest = t; + } + } + + // clip against top edge, y = -1.0 + d1 = -1.0f - p1.y; + d2 = -1.0f - p2.y; + if(d1 * d2 < 0.0f){ + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + x = (p2.x - p1.x)*t + p1.x; + if(x >= -1.0f && x <= 1.0f && t <= shortest){ + out.y = -1.0f; + out.x = x; + edge = 0; + shortest = t; + } + } + + // clip against bottom edge, y = 1.0 + d1 = p1.y - 1.0f; + d2 = p2.y - 1.0f; + if(d1 * d2 < 0.0f){ + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + x = (p2.x - p1.x)*t + p1.x; + if(x >= -1.0f && x <= 1.0f && t <= shortest){ + out.y = 1.0f; + out.x = x; + edge = 2; + shortest = t; + } + } + + return edge; +} + +#if 0 +WRAPPER int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *in) { EAXJMP(0x4A64A0); } +#else +// Why not a proper clipping algorithm? +int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) +{ + CVector2D corners[4] = { + { 1.0f, -1.0f }, // top right + { 1.0f, 1.0f }, // bottom right + { -1.0f, 1.0f }, // bottom left + { -1.0f, -1.0f }, // top left + }; + CVector2D tmp; + int i, j, n; + int laste, e, e1, e2;; + bool inside[4]; + + for(i = 0; i < 4; i++) + inside[i] = IsPointInsideRadar(rect[i]); + + laste = -1; + n = 0; + for(i = 0; i < 4; i++) + if(inside[i]){ + // point is inside, just add + poly[n++] = rect[i]; + }else{ + // point is outside but line to this point might be clipped + e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i+4-1) % 4]); + if(e1 != -1){ + laste = e1; + n++; + } + // and line from this point might be clipped as well + e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i+1) % 4]); + if(e2 != -1){ + if(e1 == -1){ + // if other line wasn't clipped, i.e. it was complete outside, + // we may have to insert another vertex if last clipped line + // was on a different edge + + // find the last intersection if we haven't seen it yet + if(laste == -1) + for(j = 3; j >= i; j--){ + // game uses an if here for j == 0 + e = LineRadarBoxCollision(tmp, rect[j], rect[(j+4-1) % 4]); + if(e != -1){ + laste = e; + break; + } + } + assert(laste != -1); + + // insert corners that were skipped + tmp = poly[n]; + for(e = laste; e != e2; e = (e+1) % 4) + poly[n++] = corners[e]; + poly[n] = tmp; + } + n++; + } + } + + if(n == 0){ + // If no points, either the rectangle is completely outside or completely surrounds the radar + // no idea what's going on here... + float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x); + if((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f){ + m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x); + if((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f){ + poly[0] = corners[0]; + poly[1] = corners[1]; + poly[2] = corners[2]; + poly[3] = corners[3]; + n = 4; + } + } + } + + return n; +} +#endif + +#if 0 WRAPPER void CRadar::DrawRadarSection(int x, int y) { EAXJMP(0x4A67E0); } #else void CRadar::DrawRadarSection(int x, int y) { - + int i; + RwTexDictionary *txd; + CVector2D worldPoly[8]; + CVector2D radarCorners[4]; + CVector2D radarPoly[8]; + CVector2D texCoords[8]; + CVector2D screenPoly[8]; + int numVertices; + RwTexture *texture = nil; + + GetTextureCorners(x, y, worldPoly); + ClipRadarTileCoords(x, y); + + assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])); + txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict; + if(txd) + texture = GetFirstTexture(txd); + if(texture == nil) + return; + + for(i = 0; i < 4; i++) + TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]); + + numVertices = ClipRadarPoly(radarPoly, radarCorners); + + // FIX: can return earlier here +// if(numVertices == 0) + if(numVertices < 3) + return; + + for(i = 0; i< numVertices; i++){ + TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]); + TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y); + TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]); + } + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); + CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); + // check done above now +// if(numVertices > 2) + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices); } #endif void CRadar::RequestMapSection(int x, int y) { - ClipRadarTileCoords(&x, &y); + ClipRadarTileCoords(x, y); CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_DEPENDENCY); } @@ -249,10 +453,10 @@ WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVe #else void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) { - out.x = in.x - (x * 500.0f + WORLD_MIN_X); - out.y = -(in.y - ((RADAR_NUM_TILES - y) * 500.0f + WORLD_MIN_Y)); - out.x /= 500.0f; - out.y /= 500.0f; + out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X); + out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y)); + out.x /= RADAR_TILE_SIZE; + out.y /= RADAR_TILE_SIZE; } #endif @@ -261,10 +465,13 @@ WRAPPER void CRadar::DrawRadarMap() { EAXJMP(0x4A6C20); } #else void CRadar::DrawRadarMap() { + // Game calculates an unused CRect here + DrawRadarMask(); - int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / 500.0f); - int y = round(7.0f - (vec2DRadarOrigin.y - WORLD_MIN_Y) / 500.0f); + // top left ist (0, 0) + int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE); + int y = ceilf((RADAR_NUM_TILES-1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE); StreamRadarSections(x, y); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); @@ -279,13 +486,13 @@ void CRadar::DrawRadarMap() RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE); DrawRadarSection(x - 1, y - 1); - DrawRadarSection(x, y - 1); + DrawRadarSection(x, y - 1); DrawRadarSection(x + 1, y - 1); DrawRadarSection(x - 1, y); - DrawRadarSection(x, y); + DrawRadarSection(x, y); DrawRadarSection(x + 1, y); DrawRadarSection(x - 1, y + 1); - DrawRadarSection(x, y + 1); + DrawRadarSection(x, y + 1); DrawRadarSection(x + 1, y + 1); } #endif @@ -490,14 +697,47 @@ void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D s = sin(atan2(-forward.x, forward.y)); c = cos(atan2(-forward.x, forward.y)); } - + float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); - + out.x = s * y + c * x; out.y = c * y - s * x; } -#endif +#endif + +#if 0 +WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } +#else +void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) +{ + float s, c; + + s = -sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { + s = 0.0f; + c = 1.0f; + } else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { + CVector forward; + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); + forward.Normalise(); // a bit useless... + } else + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + + s = -sin(atan2(-forward.x, forward.y)); + c = cos(atan2(-forward.x, forward.y)); + } + + out.x = s * in.y + c * in.x; + out.y = c * in.y - s * in.x; + + out = out*m_RadarRange + vec2DRadarOrigin; +} +#endif #if 0 WRAPPER void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) { EAXJMP(0x4A5EF0); } @@ -554,13 +794,13 @@ void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float curPosn[0].x = x - SCREEN_SCALE_X(5.6f); curPosn[0].y = y + SCREEN_SCALE_Y(5.6f); - + curPosn[1].x = x + SCREEN_SCALE_X(5.6f); curPosn[1].y = y + SCREEN_SCALE_Y(5.6f); - + curPosn[2].x = x - SCREEN_SCALE_X(5.6f); curPosn[2].y = y - SCREEN_SCALE_Y(5.6f); - + curPosn[3].x = x + SCREEN_SCALE_X(5.6f); curPosn[3].y = y - SCREEN_SCALE_Y(5.6f); @@ -590,31 +830,83 @@ bool CRadar::DisplayThisBlip(int counter) #if 0 WRAPPER void CRadar::GetTextureCorners(int x, int y, CVector2D *out) { EAXJMP(0x4A61C0); }; #else +// Transform from section indices to world coordinates void CRadar::GetTextureCorners(int x, int y, CVector2D *out) { - out[0].x = 500.0f * (x - 4); - out[0].y = 500.0f * (3 - y); - out[1].x = 500.0f * (y - 4 + 1); - out[1].y = 500.0f * (3 - y); - out[2].x = 500.0f * (y - 4 + 1); - out[2].y = 500.0f * (3 - y + 1); - out[3].x = 500.0f * (x - 4); - out[3].y = 500.0f * (3 - y + 1); + x = x - RADAR_NUM_TILES/2; + y = -(y - RADAR_NUM_TILES/2); + + // bottom left + out[0].x = RADAR_TILE_SIZE * (x); + out[0].y = RADAR_TILE_SIZE * (y - 1); + + // bottom right + out[1].x = RADAR_TILE_SIZE * (x + 1); + out[1].y = RADAR_TILE_SIZE * (y - 1); + + // top right + out[2].x = RADAR_TILE_SIZE * (x + 1); + out[2].y = RADAR_TILE_SIZE * (y); + + // top left + out[3].x = RADAR_TILE_SIZE * (x); + out[3].y = RADAR_TILE_SIZE * (y); } #endif -void CRadar::ClipRadarTileCoords(int *x, int *y) +void CRadar::ClipRadarTileCoords(int &x, int &y) { - if (*x < 0) - *x = 0; - if (*x > 7) - *x = 7; - if (*y < 0) - *y = 0; - if (*y > 7) - *y = 7; + if (x < 0) + x = 0; + if (x > RADAR_NUM_TILES-1) + x = RADAR_NUM_TILES-1; + if (y < 0) + y = 0; + if (y > RADAR_NUM_TILES-1) + y = RADAR_NUM_TILES-1; } STARTPATCHES +// InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP); +// InjectHook(0x4A3F60, CRadar::Shutdown, PATCH_JUMP); +// InjectHook(0x4A4030, CRadar::LoadTextures, PATCH_JUMP); +// InjectHook(0x4A4180, CRadar::GetNewUniqueBlipIndex, PATCH_JUMP); +// InjectHook(0x4A41C0, CRadar::GetActualBlipArrayIndex, PATCH_JUMP); + InjectHook(0x4A4200, CRadar::DrawMap, PATCH_JUMP); + InjectHook(0x4A42F0, CRadar::DrawBlips, PATCH_JUMP); +// InjectHook(0x4A4C70, CRadar::Draw3dMarkers, PATCH_JUMP); + InjectHook(0x4A4F30, CRadar::LimitRadarPoint, PATCH_JUMP); + InjectHook(0x4A4F90, CRadar::CalculateBlipAlpha, PATCH_JUMP); InjectHook(0x4A5040, CRadar::TransformRadarPointToScreenSpace, PATCH_JUMP); + InjectHook(0x4A50D0, CRadar::TransformRealWorldPointToRadarSpace, PATCH_JUMP); + InjectHook(0x4A5300, CRadar::TransformRadarPointToRealWorldSpace, PATCH_JUMP); + InjectHook(0x4A5530, CRadar::TransformRealWorldToTexCoordSpace, PATCH_JUMP); +// InjectHook(0x4A5590, CRadar::SetCoordBlip, PATCH_JUMP); +// InjectHook(0x4A5640, CRadar::SetEntityBlip, PATCH_JUMP); + InjectHook(0x4A56C0, CRadar::ClearBlipForEntity, PATCH_JUMP); +// InjectHook(0x4A5720, CRadar::ClearBlip, PATCH_JUMP); +// InjectHook(0x4A5770, CRadar::ChangeBlipColour, PATCH_JUMP); +// InjectHook(0x4A57A0, CRadar::ChangeBlipBrightness, PATCH_JUMP); +// InjectHook(0x4A57E0, CRadar::ChangeBlipScale, PATCH_JUMP); +// InjectHook(0x4A5810, CRadar::ChangeBlipDisplay, PATCH_JUMP); +// InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP); + InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP); + InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP); + InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP); + InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP); + InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP); + InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP); +// InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP); + InjectHook(0x4A6100, CRadar::StreamRadarSections, PATCH_JUMP); + InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP); + InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP); + InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP); +// InjectHook(0x4A6B60, CRadar::StreamRadarSections, PATCH_JUMP); + InjectHook(0x4A6C20, CRadar::DrawRadarMap, PATCH_JUMP); +// InjectHook(0x4A6E30, CRadar::SaveAllRadarBlips, PATCH_JUMP); +// InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP); + + InjectHook(0x4A61C0, CRadar::GetTextureCorners, PATCH_JUMP); + InjectHook(0x4A6160, IsPointInsideRadar, PATCH_JUMP); + InjectHook(0x4A6250, LineRadarBoxCollision, PATCH_JUMP); ENDPATCHES diff --git a/src/Radar.h b/src/Radar.h index 9e687e24..dec07667 100644 --- a/src/Radar.h +++ b/src/Radar.h @@ -100,7 +100,7 @@ public: static void Draw3dMarkers(); static void DrawMap(); static void StreamRadarSections(int x, int y); - static int ClipRadarPoly(CVector2D *out, CVector2D *in); + static int ClipRadarPoly(CVector2D *out, const CVector2D *in); static void DrawRadarSection(int x, int y); static void RequestMapSection(int x, int y); static void RemoveMapSection(int x, int y); @@ -116,10 +116,12 @@ public: static void DrawRadarMask(); static void SetRadarMarkerState(int counter, int flag); static bool DisplayThisBlip(int counter); - static void GetTextureCorners(int x, int y, CVector2D * out); - static void ClipRadarTileCoords(int *x, int *y); static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y); static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in); static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in); static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in); + + // no in CRadar in the game: + static void GetTextureCorners(int x, int y, CVector2D *out); + static void ClipRadarTileCoords(int &x, int &y); }; diff --git a/src/RwHelper.cpp b/src/RwHelper.cpp index 5aa31e92..3c198272 100644 --- a/src/RwHelper.cpp +++ b/src/RwHelper.cpp @@ -108,6 +108,23 @@ GetFirstAtomic(RpClump *clump) return atm; } +RwTexture* +GetFirstTextureCallback(RwTexture *tex, void *data) +{ + *(RwTexture**)data = tex; + return nil; +} + +RwTexture* +GetFirstTexture(RwTexDictionary *txd) +{ + RwTexture *tex; + + tex = nil; + RwTexDictionaryForAllTextures(txd, GetFirstTextureCallback, &tex); + return tex; +} + void CameraSize(RwCamera * camera, RwRect * rect, RwReal viewWindow, RwReal aspectRatio) diff --git a/src/RwHelper.h b/src/RwHelper.h index e0ec00a3..ef20467d 100644 --- a/src/RwHelper.h +++ b/src/RwHelper.h @@ -7,6 +7,7 @@ void DefinedState(void); RwFrame *GetFirstChild(RwFrame *frame); RwObject *GetFirstObject(RwFrame *frame); RpAtomic *GetFirstAtomic(RpClump *clump); +RwTexture *GetFirstTexture(RwTexDictionary *txd); RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream); RwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream); From db2e2575c8c1c23f153571ae1df1bb77dbe76821 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 24 Jun 2019 18:44:23 +0200 Subject: [PATCH 03/17] more CStreaming --- src/Streaming.cpp | 754 ++++++++++++++++++++++++++++++++--- src/Streaming.h | 42 +- src/modelinfo/ModelIndices.h | 2 + 3 files changed, 747 insertions(+), 51 deletions(-) diff --git a/src/Streaming.cpp b/src/Streaming.cpp index 1a5800e2..14582e0c 100644 --- a/src/Streaming.cpp +++ b/src/Streaming.cpp @@ -13,11 +13,6 @@ #include "CdStream.h" #include "Streaming.h" -/* -CStreaming::ms_channelError 0x880DB8 -CStreaming::ms_lastVehicleDeleted 0x95CBF8 -*/ - bool &CStreaming::ms_disableStreaming = *(bool*)0x95CD6E; bool &CStreaming::ms_bLoadingBigModel = *(bool*)0x95CDB0; int32 &CStreaming::ms_numModelsRequested = *(int32*)0x8E2C10; @@ -29,11 +24,13 @@ CStreamingInfo &CStreaming::ms_endRequestedList = *(CStreamingInfo*)0x940738; int32 &CStreaming::ms_oldSectorX = *(int32*)0x8F2C84; int32 &CStreaming::ms_oldSectorY = *(int32*)0x8F2C88; uint32 &CStreaming::ms_streamingBufferSize = *(uint32*)0x942FB0; -uint8 **CStreaming::ms_pStreamingBuffer = (uint8**)0x87F818; +int8 **CStreaming::ms_pStreamingBuffer = (int8**)0x87F818; int32 &CStreaming::ms_memoryUsed = *(int32*)0x940568; CStreamingChannel *CStreaming::ms_channel = (CStreamingChannel*)0x727EE0; +int32 &CStreaming::ms_channelError = *(int32*)0x880DB8; int32 &CStreaming::ms_numVehiclesLoaded = *(int32*)0x8F2C80; int32 *CStreaming::ms_vehiclesLoaded = (int32*)0x773560; +int32 &CStreaming::ms_lastVehicleDeleted = *(int32*)0x95CBF8; CDirectory *&CStreaming::ms_pExtraObjectsDir = *(CDirectory**)0x95CB90; int32 &CStreaming::ms_numPriorityRequests = *(int32*)0x8F31C4; bool &CStreaming::ms_hasLoadedLODs = *(bool*)0x95CD47; @@ -60,8 +57,8 @@ int32 &islandLODsubInd = *(int32*)0x6212D4; int32 &islandLODsubCom = *(int32*)0x6212D8; WRAPPER void CStreaming::MakeSpaceFor(int32 size) { EAXJMP(0x409B70); } -WRAPPER bool CStreaming::IsTxdUsedByRequestedModels(int32 txdId) { EAXJMP(0x4094C0); } -WRAPPER bool CStreaming::AddToLoadedVehiclesList(int32 modelId) { EAXJMP(0x40B060); } +//WRAPPER bool CStreaming::IsTxdUsedByRequestedModels(int32 txdId) { EAXJMP(0x4094C0); } +//WRAPPER bool CStreaming::AddToLoadedVehiclesList(int32 modelId) { EAXJMP(0x40B060); } void @@ -101,12 +98,12 @@ CStreaming::Init(void) // init channels - ms_channel[0].state = CHANNELSTATE_0; - ms_channel[1].state = CHANNELSTATE_0; + ms_channel[0].state = CHANNELSTATE_IDLE; + ms_channel[1].state = CHANNELSTATE_IDLE; for(i = 0; i < 4; i++){ - ms_channel[0].modelIds[i] = -1; + ms_channel[0].streamIds[i] = -1; ms_channel[0].offsets[i] = -1; - ms_channel[1].modelIds[i] = -1; + ms_channel[1].streamIds[i] = -1; ms_channel[1].offsets[i] = -1; } @@ -115,8 +112,8 @@ CStreaming::Init(void) for(i = 0; i < MODELINFOSIZE; i++){ CBaseModelInfo *mi = CModelInfo::GetModelInfo(i); if(mi && mi->GetRwObject()){ - ms_aInfoForModel[i + STREAM_OFFSET_MODEL].m_loadState = STREAMSTATE_LOADED; - ms_aInfoForModel[i + STREAM_OFFSET_MODEL].m_flags = STREAMFLAGS_DONT_REMOVE; + ms_aInfoForModel[i].m_loadState = STREAMSTATE_LOADED; + ms_aInfoForModel[i].m_flags = STREAMFLAGS_DONT_REMOVE; if(mi->IsSimple()) ((CSimpleModelInfo*)mi)->m_alpha = 255; } @@ -143,7 +140,7 @@ CStreaming::Init(void) // allocate streaming buffers if(ms_streamingBufferSize & 1) ms_streamingBufferSize++; - ms_pStreamingBuffer[0] = (uint8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); + ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); ms_streamingBufferSize /= 2; ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; debug("Streaming buffer size is %d sectors", ms_streamingBufferSize); @@ -211,6 +208,9 @@ CStreaming::LoadCdDirectory(void) ms_imageOffsets[i] = -1; ms_imageSize = GetGTA3ImgSize(); + // PS2 uses CFileMgr::GetCdFile on all IMG files to fill the array + + i = CdStreamGetNumImages(); while(i-- >= 1){ strcpy(dirname, CdStreamGetImageName(i)); @@ -245,15 +245,15 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) if(strcmp(dot+1, "DFF") == 0 || strcmp(dot+1, "dff") == 0){ if(CModelInfo::GetModelInfo(direntry.name, &modelId)){ - if(ms_aInfoForModel[modelId + STREAM_OFFSET_MODEL].GetCdPosnAndSize(posn, size)){ + if(ms_aInfoForModel[modelId].GetCdPosnAndSize(posn, size)){ debug("%s appears more than once in %s\n", direntry.name, dirname); lastID = -1; }else{ direntry.offset |= imgSelector; - ms_aInfoForModel[modelId + STREAM_OFFSET_MODEL].SetCdPosnAndSize(direntry.offset, direntry.size); + ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size); if(lastID != -1) - ms_aInfoForModel[lastID].m_nextID = modelId + STREAM_OFFSET_MODEL; - lastID = modelId + STREAM_OFFSET_MODEL; + ms_aInfoForModel[lastID].m_nextID = modelId; + lastID = modelId; } }else{ // BUG: doesn't remember which cdimage this was in @@ -300,15 +300,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) if(streamId < STREAM_OFFSET_TXD){ // Model - mi = CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL); + mi = CModelInfo::GetModelInfo(streamId); // Txd has to be loaded if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil){ debug("failed to load %s because TXD %s is not in memory\n", mi->GetName(), CTxdStore::GetTxdName(mi->GetTxdSlot())); RemoveModel(streamId); - RemoveModel(mi->GetTxdSlot() + STREAM_OFFSET_TXD); - // re-request - RequestModel(streamId, ms_aInfoForModel[streamId].m_flags); + RemoveTxd(mi->GetTxdSlot()); + ReRequestModel(streamId); RwStreamClose(stream, &mem); return false; } @@ -318,15 +317,15 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); if(mi->IsSimple()){ - success = CFileLoader::LoadAtomicFile(stream, streamId - STREAM_OFFSET_MODEL); + success = CFileLoader::LoadAtomicFile(stream, streamId); }else if(mi->m_type == MITYPE_VEHICLE){ // load vehicles in two parts - CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL)->AddRef(); - success = CFileLoader::StartLoadClumpFile(stream, streamId - STREAM_OFFSET_MODEL); + CModelInfo::GetModelInfo(streamId)->AddRef(); + success = CFileLoader::StartLoadClumpFile(stream, streamId); if(success) ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED; }else{ - success = CFileLoader::LoadClumpFile(stream, streamId - STREAM_OFFSET_MODEL); + success = CFileLoader::LoadClumpFile(stream, streamId); } UpdateMemoryUsed(); @@ -335,10 +334,9 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot()); if(!success){ - debug("Failed to load %s\n", CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL)->GetName()); + debug("Failed to load %s\n", CModelInfo::GetModelInfo(streamId)->GetName()); RemoveModel(streamId); - // re-request - RequestModel(streamId, ms_aInfoForModel[streamId].m_flags); + ReRequestModel(streamId); RwStreamClose(stream, &mem); return false; } @@ -363,8 +361,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) if(!success){ debug("Failed to load %s.txd\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD)); RemoveModel(streamId); - // re-request - RequestModel(streamId, ms_aInfoForModel[streamId].m_flags); + ReRequestModel(streamId); RwStreamClose(stream, &mem); return false; } @@ -374,7 +371,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) // We shouldn't even end up here unless load was successful if(!success){ - RequestModel(streamId, ms_aInfoForModel[streamId].m_flags); + ReRequestModel(streamId); if(streamId < STREAM_OFFSET_TXD) debug("Failed to load %s.dff\n", mi->GetName()); else @@ -415,7 +412,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) timeDiff = endTime - startTime; if(timeDiff > 5){ if(streamId < STREAM_OFFSET_TXD) - debug("model %s took %d ms\n", CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL)->GetName(), timeDiff); + debug("model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetName(), timeDiff); else debug("txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff); } @@ -437,7 +434,7 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){ if(streamId < STREAM_OFFSET_TXD) - CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL)->RemoveRef(); + CModelInfo::GetModelInfo(streamId)->RemoveRef(); return false; } @@ -447,7 +444,7 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) if(streamId < STREAM_OFFSET_TXD){ // Model - mi = CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL); + mi = CModelInfo::GetModelInfo(streamId); CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); success = CFileLoader::FinishLoadClumpFile(stream, streamId); if(success) @@ -467,8 +464,7 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) if(!success){ RemoveModel(streamId); - // re-request - RequestModel(streamId, ms_aInfoForModel[streamId].m_flags); + ReRequestModel(streamId); UpdateMemoryUsed(); return false; } @@ -479,7 +475,7 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) timeDiff = endTime - startTime; if(timeDiff > 5){ if(streamId < STREAM_OFFSET_TXD) - debug("finish model %s took %d ms\n", CModelInfo::GetModelInfo(streamId - STREAM_OFFSET_MODEL)->GetName(), timeDiff); + debug("finish model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetName(), timeDiff); else debug("finish txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff); } @@ -507,7 +503,7 @@ CStreaming::RequestModel(int32 id, int32 flags) // Already loaded, only check changed flags if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOFADE && id < STREAM_OFFSET_TXD){ - mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id - STREAM_OFFSET_MODEL); + mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); if(mi->IsSimple()) mi->m_alpha = 255; } @@ -523,7 +519,7 @@ CStreaming::RequestModel(int32 id, int32 flags) if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED){ if(id < STREAM_OFFSET_TXD) - RequestTxd(CModelInfo::GetModelInfo(id - STREAM_OFFSET_MODEL)->GetTxdSlot(), flags); + RequestTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot(), flags); ms_aInfoForModel[id].AddToList(&ms_startRequestedList); ms_numModelsRequested++; if(flags & STREAMFLAGS_PRIORITY) @@ -667,7 +663,7 @@ CStreaming::RemoveModel(int32 id) if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){ if(id < STREAM_OFFSET_TXD) - CModelInfo::GetModelInfo(id - STREAM_OFFSET_MODEL)->DeleteRwObject(); + CModelInfo::GetModelInfo(id)->DeleteRwObject(); else CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE; @@ -685,10 +681,10 @@ CStreaming::RemoveModel(int32 id) ms_aInfoForModel[id].RemoveFromList(); }else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_READING){ for(i = 0; i < 4; i++){ - if(ms_channel[0].modelIds[i] == id - STREAM_OFFSET_MODEL) - ms_channel[0].modelIds[i] = -1; - if(ms_channel[1].modelIds[i] == id - STREAM_OFFSET_MODEL) - ms_channel[1].modelIds[i] = -1; + if(ms_channel[0].streamIds[i] == id) + ms_channel[0].streamIds[i] = -1; + if(ms_channel[1].streamIds[i] == id) + ms_channel[1].streamIds[i] = -1; } } @@ -702,10 +698,646 @@ CStreaming::RemoveModel(int32 id) ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED; } +void +CStreaming::RemoveUnusedBuildings(eLevelName level) +{ + if(level != LEVEL_INDUSTRIAL) + RemoveBuildings(LEVEL_INDUSTRIAL); + if(level != LEVEL_COMMERCIAL) + RemoveBuildings(LEVEL_COMMERCIAL); + if(level != LEVEL_SUBURBAN) + RemoveBuildings(LEVEL_SUBURBAN); +} + +void +CStreaming::RemoveBuildings(eLevelName level) +{ + int i, n; + CEntity *e; + CBaseModelInfo *mi; + + n = CPools::GetBuildingPool()->GetSize(); + for(i = 0; i < n; i++){ + e = CPools::GetBuildingPool()->GetSlot(i); + if(e && e->m_level == level){ + mi = CModelInfo::GetModelInfo(e->GetModelIndex()); + if(!e->bImBeingRendered){ + e->DeleteRwObject(); + if(mi->m_refCount == 0) + RemoveModel(e->GetModelIndex()); + } + } + } + + n = CPools::GetTreadablePool()->GetSize(); + for(i = 0; i < n; i++){ + e = CPools::GetTreadablePool()->GetSlot(i); + if(e && e->m_level == level){ + mi = CModelInfo::GetModelInfo(e->GetModelIndex()); + if(!e->bImBeingRendered){ + e->DeleteRwObject(); + if(mi->m_refCount == 0) + RemoveModel(e->GetModelIndex()); + } + } + } + + n = CPools::GetObjectPool()->GetSize(); + for(i = 0; i < n; i++){ + e = CPools::GetObjectPool()->GetSlot(i); + if(e && e->m_level == level){ + mi = CModelInfo::GetModelInfo(e->GetModelIndex()); + if(!e->bImBeingRendered && ((CObject*)e)->ObjectCreatedBy == GAME_OBJECT){ + e->DeleteRwObject(); + if(mi->m_refCount == 0) + RemoveModel(e->GetModelIndex()); + } + } + } + + n = CPools::GetDummyPool()->GetSize(); + for(i = 0; i < n; i++){ + e = CPools::GetDummyPool()->GetSlot(i); + if(e && e->m_level == level){ + mi = CModelInfo::GetModelInfo(e->GetModelIndex()); + if(!e->bImBeingRendered){ + e->DeleteRwObject(); + if(mi->m_refCount == 0) + RemoveModel(e->GetModelIndex()); + } + } + } +} + +void +CStreaming::RemoveUnusedBigBuildings(eLevelName level) +{ + if(level != LEVEL_INDUSTRIAL) + RemoveBigBuildings(LEVEL_INDUSTRIAL); + if(level != LEVEL_COMMERCIAL) + RemoveBigBuildings(LEVEL_COMMERCIAL); + if(level != LEVEL_SUBURBAN) + RemoveBigBuildings(LEVEL_SUBURBAN); + RemoveIslandsNotUsed(level); +} + +void +DeleteIsland(CEntity *island) +{ + if(island == nil) + return; + if(island->bImBeingRendered) + debug("Didn't delete island because it was being rendered\n"); + else{ + island->DeleteRwObject(); + CStreaming::RemoveModel(island->GetModelIndex()); + } +} + +void +CStreaming::RemoveIslandsNotUsed(eLevelName level) +{ + switch(level){ + case LEVEL_INDUSTRIAL: + DeleteIsland(pIslandLODindustEntity); + DeleteIsland(pIslandLODcomSubEntity); + DeleteIsland(pIslandLODsubComEntity); + break; + case LEVEL_COMMERCIAL: + DeleteIsland(pIslandLODcomIndEntity); + DeleteIsland(pIslandLODcomSubEntity); + DeleteIsland(pIslandLODsubIndEntity); + break; + case LEVEL_SUBURBAN: + DeleteIsland(pIslandLODsubIndEntity); + DeleteIsland(pIslandLODsubComEntity); + DeleteIsland(pIslandLODcomIndEntity); + break; + default: + DeleteIsland(pIslandLODindustEntity); + DeleteIsland(pIslandLODcomIndEntity); + DeleteIsland(pIslandLODcomSubEntity); + DeleteIsland(pIslandLODsubIndEntity); + DeleteIsland(pIslandLODsubComEntity); + break; + } +} + +void +CStreaming::RemoveBigBuildings(eLevelName level) +{ + int i, n; + CEntity *e; + CBaseModelInfo *mi; + + n = CPools::GetBuildingPool()->GetSize(); + for(i = 0; i < n; i++){ + e = CPools::GetBuildingPool()->GetSlot(i); + if(e && e->bIsBIGBuilding && e->m_level == level){ + mi = CModelInfo::GetModelInfo(e->GetModelIndex()); + if(!e->bImBeingRendered){ + e->DeleteRwObject(); + if(mi->m_refCount == 0) + RemoveModel(e->GetModelIndex()); + } + } + } +} + +bool +CStreaming::RemoveLoadedVehicle(void) +{ + int i, id; + + for(i = 0; i < MAXVEHICLESLOADED; i++){ + ms_lastVehicleDeleted++; + if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) + ms_lastVehicleDeleted = 0; + id = ms_vehiclesLoaded[ms_lastVehicleDeleted]; + if(id != -1 && + (ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 && + CModelInfo::GetModelInfo(id)->m_refCount == 0 && + ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED) + goto found; + } + return false; +found: + RemoveModel(ms_vehiclesLoaded[ms_lastVehicleDeleted]); + ms_numVehiclesLoaded--; + ms_vehiclesLoaded[ms_lastVehicleDeleted] = -1; + return true; +} + +bool +CStreaming::RemoveLeastUsedModel(void) +{ + CStreamingInfo *si; + int streamId; + + for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){ + streamId = si - ms_aInfoForModel; + if(streamId < STREAM_OFFSET_TXD){ + if(CTxdStore::GetNumRefs(streamId - STREAM_OFFSET_TXD) == 0 && + !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){ + RemoveModel(streamId); + return true; + } + }else{ + if(CModelInfo::GetModelInfo(streamId)->m_refCount == 0){ + RemoveModel(streamId); + return true; + } + } + } + return ms_numVehiclesLoaded > 7 && RemoveLoadedVehicle(); +} + +void +CStreaming::RemoveAllUnusedModels(void) +{ + int i; + + for(i = 0; i < MAXVEHICLESLOADED; i++) + RemoveLoadedVehicle(); + + for(i = NUM_DEFAULT_MODELS; i < MODELINFOSIZE; i++){ + if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED && + ms_aInfoForModel[i].m_flags & STREAMFLAGS_DONT_REMOVE && + CModelInfo::GetModelInfo(i)->m_refCount == 0){ + RemoveModel(i); + ms_aInfoForModel[i].m_loadState = STREAMSTATE_NOTLOADED; + } + } +} + +bool +CStreaming::RemoveReferencedTxds(int32 mem) +{ + CStreamingInfo *si; + int streamId; + + for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){ + streamId = si - ms_aInfoForModel; + if(streamId >= STREAM_OFFSET_TXD && + CTxdStore::GetNumRefs(streamId-STREAM_OFFSET_TXD) == 0){ + RemoveModel(streamId); + if(ms_memoryUsed < mem) + return true; + } + } + return false; +} + +// TODO: RemoveCurrentZonesModels + +void +CStreaming::RemoveUnusedModelsInLoadedList(void) +{ + // empty +} + +bool +CStreaming::IsTxdUsedByRequestedModels(int32 txdId) +{ + CStreamingInfo *si; + int streamId; + int i; + + for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = si->m_prev){ + streamId = si - ms_aInfoForModel; + if(streamId < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId) + return true; + } + + for(i = 0; i < 4; i++){ + streamId = ms_channel[0].streamIds[i]; + if(streamId != -1 && streamId < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId) + return true; + streamId = ms_channel[1].streamIds[i]; + if(streamId != -1 && streamId < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId) + return true; + } + + return false; +} + +int32 +CStreaming::GetAvailableVehicleSlot(void) +{ + int i; + for(i = 0; i < MAXVEHICLESLOADED; i++) + if(ms_vehiclesLoaded[i] == -1) + return i; + return -1; +} + +bool +CStreaming::AddToLoadedVehiclesList(int32 modelId) +{ + int i; + int id; + + if(ms_numVehiclesLoaded < desiredNumVehiclesLoaded){ + // still room for vehicles + for(i = 0; i < MAXVEHICLESLOADED; i++){ + if(ms_vehiclesLoaded[ms_lastVehicleDeleted] == -1) + break; + ms_lastVehicleDeleted++; + if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) + ms_lastVehicleDeleted = 0; + } + assert(ms_vehiclesLoaded[ms_lastVehicleDeleted] == -1); + ms_numVehiclesLoaded++; + }else{ + // find vehicle we can remove + for(i = 0; i < MAXVEHICLESLOADED; i++){ + id = ms_vehiclesLoaded[ms_lastVehicleDeleted]; + if(id != -1 && + (ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 && + CModelInfo::GetModelInfo(id)->m_refCount == 0) + goto found; + ms_lastVehicleDeleted++; + if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) + ms_lastVehicleDeleted = 0; + } + id = -1; +found: + if(id == -1){ + // didn't find anything, try a free slot + id = GetAvailableVehicleSlot(); + if(id == -1) + return false; // still no luck + ms_lastVehicleDeleted = id; + // this is more that we wanted actually + ms_numVehiclesLoaded++; + }else + RemoveModel(id); + } + + ms_vehiclesLoaded[ms_lastVehicleDeleted++] = modelId; + if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) + ms_lastVehicleDeleted = 0; + return true; +} + +bool +CStreaming::IsObjectInCdImage(int32 id) +{ + uint32 posn, size; + return ms_aInfoForModel[id].GetCdPosnAndSize(posn, size); +} + +void +CStreaming::HaveAllBigBuildingsLoaded(eLevelName level) +{ + int i, n; + CEntity *e; + + if(ms_hasLoadedLODs) + return; + + if(level == LEVEL_INDUSTRIAL){ + if(ms_aInfoForModel[islandLODcomInd].m_loadState != STREAMSTATE_LOADED || + ms_aInfoForModel[islandLODsubInd].m_loadState != STREAMSTATE_LOADED) + return; + }else if(level == LEVEL_COMMERCIAL){ + if(ms_aInfoForModel[islandLODindust].m_loadState != STREAMSTATE_LOADED || + ms_aInfoForModel[islandLODsubCom].m_loadState != STREAMSTATE_LOADED) + return; + }else if(level == LEVEL_SUBURBAN){ + if(ms_aInfoForModel[islandLODindust].m_loadState != STREAMSTATE_LOADED || + ms_aInfoForModel[islandLODcomSub].m_loadState != STREAMSTATE_LOADED) + return; + } + + n = CPools::GetBuildingPool()->GetSize(); + for(i = 0; i < n; i++){ + e = CPools::GetBuildingPool()->GetSlot(i); + if(e && e->bIsBIGBuilding && e->m_level == level && + ms_aInfoForModel[e->GetModelIndex()].m_loadState != STREAMSTATE_LOADED) + return; + } + + RemoveUnusedBigBuildings(level); + ms_hasLoadedLODs = true; +} + +void +CStreaming::SetModelIsDeletable(int32 id) +{ + ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_DONT_REMOVE; + if(id >= STREAM_OFFSET_TXD || + CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && ms_aInfoForModel[id].m_flags & STREAMFLAGS_SCRIPTOWNED){ + if(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED) + RemoveModel(id); + else if(ms_aInfoForModel[id].m_next == nil) + ms_aInfoForModel[id].AddToList(&ms_startLoadedList); + } +} + +void +CStreaming::SetModelTxdIsDeletable(int32 id) +{ + SetModelIsDeletable(CModelInfo::GetModelInfo(id)->GetTxdSlot() + STREAM_OFFSET_TXD); +} + +void +CStreaming::SetMissionDoesntRequireModel(int32 id) +{ + ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_SCRIPTOWNED; + if(id >= STREAM_OFFSET_TXD || + CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && ms_aInfoForModel[id].m_flags & STREAMFLAGS_DONT_REMOVE){ + if(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED) + RemoveModel(id); + else if(ms_aInfoForModel[id].m_next == nil) + ms_aInfoForModel[id].AddToList(&ms_startLoadedList); + } +} + +void +CStreaming::LoadInitialPeds(void) +{ + RequestModel(MI_COP, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_TAXI_D, STREAMFLAGS_DONT_REMOVE); +} + +void +CStreaming::LoadInitialVehicles(void) +{ + int id; + + ms_numVehiclesLoaded = 0; + ms_lastVehicleDeleted = 0; + + if(CModelInfo::GetModelInfo("taxi", &id)) + RequestModel(id, STREAMFLAGS_DONT_REMOVE); + if(CModelInfo::GetModelInfo("police", &id)) + RequestModel(id, STREAMFLAGS_DONT_REMOVE); +} + + + +bool +CStreaming::ProcessLoadingChannel(int32 ch) +{ + int status; + int i, id, cdsize; + + status = CdStreamGetStatus(ch); + if(status != STREAM_NONE){ + // busy + if(status != STREAM_READING && status != STREAM_WAITING){ + ms_channelError = ch; + ms_channel[ch].state = CHANNELSTATE_ERROR; + ms_channel[ch].status = status; + } + return false; + } + + if(ms_channel[ch].state == CHANNELSTATE_STARTED){ + ms_channel[ch].state = CHANNELSTATE_IDLE; + FinishLoadingLargeFile(&ms_pStreamingBuffer[ch][ms_channel[ch].offsets[0]*CDSTREAM_SECTOR_SIZE], + ms_channel[ch].streamIds[0]); + ms_channel[ch].streamIds[0] = -1; + }else{ + ms_channel[ch].state = CHANNELSTATE_IDLE; + for(i = 0; i < 4; i++){ + id = ms_channel[ch].streamIds[i]; + if(id == -1) + continue; + + cdsize = ms_aInfoForModel[id].GetCdSize(); + if(id < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && + ms_numVehiclesLoaded >= desiredNumVehiclesLoaded && + RemoveLoadedVehicle() && + ((ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 || GetAvailableVehicleSlot() == -1)){ + // can't load vehicle + RemoveModel(id); + if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) + ReRequestModel(id); + else if(CTxdStore::GetNumRefs(CModelInfo::GetModelInfo(id)->GetTxdSlot()) == 0) + RemoveTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot()); + }else{ + MakeSpaceFor(cdsize * CDSTREAM_SECTOR_SIZE); + ConvertBufferToObject(&ms_pStreamingBuffer[ch][ms_channel[ch].offsets[i]*CDSTREAM_SECTOR_SIZE], + id); + if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){ + // queue for second part + ms_channel[ch].state = CHANNELSTATE_STARTED; + ms_channel[ch].offsets[0] = ms_channel[ch].offsets[i]; + ms_channel[ch].streamIds[0] = id; + if(i != 0) + ms_channel[ch].streamIds[i] = -1; + }else + ms_channel[ch].streamIds[i] = -1; + } + } + } + + if(ms_bLoadingBigModel && ms_channel[ch].state != CHANNELSTATE_STARTED){ + ms_bLoadingBigModel = false; + // reset channel 1 after loading a big model + for(i = 0; i < 4; i++){ + ms_channel[1].streamIds[i] = -1; + ms_channel[1].offsets[i] = -1; + } + ms_channel[1].state = CHANNELSTATE_IDLE; + } + + return true; +} + +inline bool +TxdAvailable(int32 txdId) +{ + CStreamingInfo *si = &CStreaming::ms_aInfoForModel[txdId + STREAM_OFFSET_TXD]; + return si->m_loadState == STREAMSTATE_LOADED || si->m_loadState == STREAMSTATE_READING; +} + +// Find stream id of next requested file in cdimage +int32 +CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority) +{ + CStreamingInfo *si, *next; + int streamId; + uint32 posn, size; + int streamIdFirst, streamIdNext; + uint32 posnFirst, posnNext; + + streamIdFirst = -1; + streamIdNext = -1; + posnFirst = UINT_MAX; + posnNext = UINT_MAX; + + for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){ + next = si->m_next; + streamId = si - ms_aInfoForModel; + + // only priority requests if there are any + if(priority && ms_numPriorityRequests != 0 && + (si->m_flags & STREAMFLAGS_PRIORITY) == 0) + continue; + + // request Txd if necessary + if(streamId < STREAM_OFFSET_TXD && + !TxdAvailable(CModelInfo::GetModelInfo(streamId)->GetTxdSlot())){ + ReRequestTxd(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()); + }else if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){ + if(posn < posnFirst){ + // find first requested file in image + streamIdFirst = streamId; + posnFirst = posn; + } + if(posn < posnNext && posn >= (uint32)lastPosn){ + // find first requested file after last read position + streamIdNext = streamId; + posnNext = posn; + } + }else{ + // empty file + ms_numModelsRequested--; + if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_PRIORITY){ + ms_aInfoForModel[streamId].m_flags &= ~STREAMFLAGS_PRIORITY; + ms_numPriorityRequests--; + } + si->RemoveFromList(); + si->m_loadState = STREAMSTATE_LOADED; + } + } + + // wrap around + if(streamIdNext == -1) + streamIdNext = streamIdFirst; + + if(streamIdNext == -1 && ms_numPriorityRequests){ + // try non-priority files + ms_numPriorityRequests = 0; + streamIdNext = GetNextFileOnCd(lastPosn, false); + } + + return streamIdNext; +} + +void +CStreaming::FlushChannels(void) +{ + if(ms_channel[1].state == CHANNELSTATE_STARTED) + ProcessLoadingChannel(1); + + if(ms_channel[0].state == CHANNELSTATE_UNK1){ + CdStreamSync(0); + ProcessLoadingChannel(0); + } + if(ms_channel[0].state == CHANNELSTATE_STARTED) + ProcessLoadingChannel(0); + + if(ms_channel[1].state == CHANNELSTATE_UNK1){ + CdStreamSync(1); + ProcessLoadingChannel(1); + } + if(ms_channel[1].state == CHANNELSTATE_STARTED) + ProcessLoadingChannel(1); +} + +void +CStreaming::FlushRequestList(void) +{ + CStreamingInfo *si, *next; + + for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){ + next = si->m_next; + RemoveModel(si - ms_aInfoForModel); + } + FlushChannels(); +} + +// Find starting offset of the cdimage we next want to read +// Not useful at all on PC... +int32 +CStreaming::GetCdImageOffset(int32 lastPosn) +{ + int offset, off; + int i, img; + int dist, mindist; + + img = -1; + mindist = INT_MAX; + offset = ms_imageOffsets[ms_lastImageRead]; + if(lastPosn <= offset || lastPosn > offset + ms_imageSize){ + // last read position is not in last image + for(i = 0; i < NUMCDIMAGES; i++){ + off = ms_imageOffsets[i]; + if(off == -1) continue; + if((uint32)lastPosn > (uint32)off) + // after start of image, get distance from end + // negative if before end! + dist = lastPosn - (off + ms_imageSize); + else + // before image, get offset to start + // this will never be negative + dist = off - lastPosn; + if(dist < mindist){ + img = i; + mindist = dist; + } + } + assert(img >= 0); + offset = ms_imageOffsets[img]; + ms_lastImageRead = img; + } + return offset; +} + void CStreaming::ImGonnaUseStreamingMemory(void) { + // empty } void @@ -717,10 +1349,10 @@ CStreaming::IHaveUsedStreamingMemory(void) void CStreaming::UpdateMemoryUsed(void) { + // empty } - bool CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) { @@ -770,7 +1402,35 @@ STARTPATCHES InjectHook(0x408210, CStreaming::RequestIslands, PATCH_JUMP); InjectHook(0x40A890, CStreaming::RequestSpecialModel, PATCH_JUMP); InjectHook(0x40ADA0, CStreaming::RequestSpecialChar, PATCH_JUMP); + InjectHook(0x408830, CStreaming::RemoveModel, PATCH_JUMP); + InjectHook(0x4083A0, CStreaming::RemoveUnusedBuildings, PATCH_JUMP); + InjectHook(0x4083D0, CStreaming::RemoveBuildings, PATCH_JUMP); + InjectHook(0x408640, CStreaming::RemoveUnusedBigBuildings, PATCH_JUMP); + InjectHook(0x408680, CStreaming::RemoveBigBuildings, PATCH_JUMP); + InjectHook(0x408780, CStreaming::RemoveIslandsNotUsed, PATCH_JUMP); + InjectHook(0x40B180, CStreaming::RemoveLoadedVehicle, PATCH_JUMP); + InjectHook(0x4089B0, CStreaming::RemoveLeastUsedModel, PATCH_JUMP); + InjectHook(0x408940, CStreaming::RemoveAllUnusedModels, PATCH_JUMP); + InjectHook(0x409450, CStreaming::RemoveReferencedTxds, PATCH_JUMP); + + InjectHook(0x40B160, CStreaming::GetAvailableVehicleSlot, PATCH_JUMP); + InjectHook(0x40B060, CStreaming::AddToLoadedVehiclesList, PATCH_JUMP); + InjectHook(0x4094C0, CStreaming::IsTxdUsedByRequestedModels, PATCH_JUMP); + InjectHook(0x407E70, CStreaming::IsObjectInCdImage, PATCH_JUMP); + InjectHook(0x408280, CStreaming::HaveAllBigBuildingsLoaded, PATCH_JUMP); + InjectHook(0x40A790, CStreaming::SetModelIsDeletable, PATCH_JUMP); + InjectHook(0x40A800, CStreaming::SetModelTxdIsDeletable, PATCH_JUMP); + InjectHook(0x40A820, CStreaming::SetMissionDoesntRequireModel, PATCH_JUMP); + + InjectHook(0x40AA00, CStreaming::LoadInitialPeds, PATCH_JUMP); + InjectHook(0x40ADF0, CStreaming::LoadInitialVehicles, PATCH_JUMP); + + InjectHook(0x409BE0, CStreaming::ProcessLoadingChannel, PATCH_JUMP); + InjectHook(0x40A610, CStreaming::FlushChannels, PATCH_JUMP); + InjectHook(0x40A680, CStreaming::FlushRequestList, PATCH_JUMP); + InjectHook(0x409FF0, CStreaming::GetCdImageOffset, PATCH_JUMP); + InjectHook(0x409E50, CStreaming::GetNextFileOnCd, PATCH_JUMP); InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP); InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP); diff --git a/src/Streaming.h b/src/Streaming.h index fc14829c..62d0c2fb 100644 --- a/src/Streaming.h +++ b/src/Streaming.h @@ -14,6 +14,7 @@ enum StreamFlags STREAMFLAGS_PRIORITY = 0x08, STREAMFLAGS_NOFADE = 0x10, + // TODO: this isn't named well, maybe CANT_REMOVE? STREAMFLAGS_NOT_IN_LIST = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED, STREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY, }; @@ -29,7 +30,10 @@ enum StreamLoadState enum ChannelState { - CHANNELSTATE_0 = 0, + CHANNELSTATE_IDLE = 0, + CHANNELSTATE_UNK1 = 1, + CHANNELSTATE_STARTED = 2, + CHANNELSTATE_ERROR = 3, }; class CStreamingInfo @@ -53,7 +57,7 @@ public: struct CStreamingChannel { - int32 modelIds[4]; + int32 streamIds[4]; int32 offsets[4]; int32 state; int32 field24; @@ -80,11 +84,13 @@ public: static int32 &ms_oldSectorX; static int32 &ms_oldSectorY; static uint32 &ms_streamingBufferSize; - static uint8 **ms_pStreamingBuffer; //[2] + static int8 **ms_pStreamingBuffer; //[2] static int32 &ms_memoryUsed; static CStreamingChannel *ms_channel; //[2] + static int32 &ms_channelError; static int32 &ms_numVehiclesLoaded; static int32 *ms_vehiclesLoaded; //[MAXVEHICLESLOADED] + static int32 &ms_lastVehicleDeleted; static CDirectory *&ms_pExtraObjectsDir; static int32 &ms_numPriorityRequests; static bool &ms_hasLoadedLODs; @@ -104,7 +110,9 @@ public: static bool ConvertBufferToObject(int8 *buf, int32 streamId); static bool FinishLoadingLargeFile(int8 *buf, int32 streamId); static void RequestModel(int32 model, int32 flags); + static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); } static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); } + static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); } static void RequestSubway(void); static void RequestBigBuildings(eLevelName level); static void RequestIslands(eLevelName level); @@ -112,12 +120,38 @@ public: static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags); static void RemoveModel(int32 id); static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); } - + static void RemoveUnusedBuildings(eLevelName level); + static void RemoveBuildings(eLevelName level); + static void RemoveUnusedBigBuildings(eLevelName level); + static void RemoveIslandsNotUsed(eLevelName level); + static void RemoveBigBuildings(eLevelName level); + static bool RemoveLoadedVehicle(void); + static bool RemoveLeastUsedModel(void); + static void RemoveAllUnusedModels(void); + static void RemoveUnusedModelsInLoadedList(void); + static bool RemoveReferencedTxds(int32 mem); + static int32 GetAvailableVehicleSlot(void); static bool IsTxdUsedByRequestedModels(int32 txdId); static bool AddToLoadedVehiclesList(int32 modelId); + static bool IsObjectInCdImage(int32 id); + static void HaveAllBigBuildingsLoaded(eLevelName level); + static void SetModelIsDeletable(int32 id); + static void SetModelTxdIsDeletable(int32 id); + static void SetMissionDoesntRequireModel(int32 id); + + static int32 GetNextFileOnCd(int32 position, bool priority); + static bool ProcessLoadingChannel(int32 ch); + static void RequestModelStream(int32 ch); + static void FlushChannels(void); + static void FlushRequestList(void); + static int32 GetCdImageOffset(int32 lastPosn); static void MakeSpaceFor(int32 size); static void ImGonnaUseStreamingMemory(void); static void IHaveUsedStreamingMemory(void); static void UpdateMemoryUsed(void); + + + static void LoadInitialPeds(void); + static void LoadInitialVehicles(void); }; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index be091e9b..feafcd40 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -326,6 +326,8 @@ enum MI_AIRTRAIN_VLO = 198, MI_LOPOLYGUY, + + NUM_DEFAULT_MODELS, }; void InitModelIndices(void); From 0b384356f9a8ed560dc5e59ec4a7735545099093 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 24 Jun 2019 20:01:15 +0200 Subject: [PATCH 04/17] fixed bug in CPlaceable --- src/Placeable.cpp | 71 +++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/src/Placeable.cpp b/src/Placeable.cpp index 43708d3e..b4b2a37b 100644 --- a/src/Placeable.cpp +++ b/src/Placeable.cpp @@ -20,56 +20,47 @@ CPlaceable::SetHeading(float angle) bool CPlaceable::IsWithinArea(float x1, float y1, float x2, float y2) { - float x, xmin, xmax; - float y, ymin, ymax; - xmin = x1; - xmax = x2; - ymin = y1; - ymax = y2; - if(x2 > x1){ - xmin = x2; - xmax = x1; + float tmp; + + if(x1 > x2){ + tmp = x1; + x1 = x2; + x2 = tmp; } - if(y2 > y1){ - ymin = y2; - ymax = y1; + if(y1 > y2){ + tmp = y1; + y1 = y2; + y2 = tmp; } - x = GetPosition().x; - y = GetPosition().y; - return xmin <= x && x <= xmax && - ymin <= y && y <= ymax; + + return x1 <= GetPosition().x && GetPosition().x <= x2 && + y1 <= GetPosition().y && GetPosition().y <= y2; } bool CPlaceable::IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2) { - float x, xmin, xmax; - float y, ymin, ymax; - float z, zmin, zmax; - xmin = x1; - xmax = x2; - ymin = y1; - ymax = y2; - zmin = z1; - zmax = z2; - if(x2 > x1){ - xmin = x2; - xmax = x1; + float tmp; + + if(x1 > x2){ + tmp = x1; + x1 = x2; + x2 = tmp; } - if(y2 > y1){ - ymin = y2; - ymax = y1; + if(y1 > y2){ + tmp = y1; + y1 = y2; + y2 = tmp; } - if(z2 > z1){ - zmin = z2; - zmax = z1; + if(z1 > z2){ + tmp = z1; + z1 = z2; + z2 = tmp; } - x = GetPosition().x; - y = GetPosition().y; - z = GetPosition().z; - return xmin <= x && x <= xmax && - ymin <= y && y <= ymax && - zmin <= z && z <= zmax; + + return x1 <= GetPosition().x && GetPosition().x <= x2 && + y1 <= GetPosition().y && GetPosition().y <= y2 && + z1 <= GetPosition().z && GetPosition().z <= z2; } STARTPATCHES From 3b43c0957893e06f832f2097225ae83b09f86199 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 24 Jun 2019 22:06:14 +0200 Subject: [PATCH 05/17] replaced some ctors; made PreRender call game function --- src/FileLoader.cpp | 7 ++++--- src/entities/Building.cpp | 1 + src/entities/Building.h | 2 ++ src/entities/Entity.cpp | 5 +++-- src/entities/Entity.h | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/FileLoader.cpp b/src/FileLoader.cpp index f50638b4..dd58614d 100644 --- a/src/FileLoader.cpp +++ b/src/FileLoader.cpp @@ -501,7 +501,7 @@ CFileLoader::LoadObjectTypes(const char *filename) CARS, PEDS, PATH, - TWO2FX + TWODFX }; char *line; int fd; @@ -528,7 +528,7 @@ CFileLoader::LoadObjectTypes(const char *filename) else if(strncmp(line, "cars", 4) == 0) section = CARS; else if(strncmp(line, "peds", 4) == 0) section = PEDS; else if(strncmp(line, "path", 4) == 0) section = PATH; - else if(strncmp(line, "2dfx", 4) == 0) section = TWO2FX; + else if(strncmp(line, "2dfx", 4) == 0) section = TWODFX; }else if(strncmp(line, "end", 3) == 0){ section = section == MLO ? OBJS : NONE; }else switch(section){ @@ -571,7 +571,7 @@ CFileLoader::LoadObjectTypes(const char *filename) pathIndex = -1; } break; - case TWO2FX: + case TWODFX: Load2dEffect(line); break; } @@ -848,6 +848,7 @@ CFileLoader::LoadCarPathNode(const char *line, int id, int node) ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight); } + void CFileLoader::Load2dEffect(const char *line) { diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp index 9e56b3a2..d69a65fe 100644 --- a/src/entities/Building.cpp +++ b/src/entities/Building.cpp @@ -22,5 +22,6 @@ CBuilding::ReplaceWithNewModel(int32 id) } STARTPATCHES + InjectHook(0x4057D0, &CBuilding::ctor, PATCH_JUMP); InjectHook(0x405850, &CBuilding::ReplaceWithNewModel, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Building.h b/src/entities/Building.h index 7b837f46..b1f96bae 100644 --- a/src/entities/Building.h +++ b/src/entities/Building.h @@ -15,5 +15,7 @@ public: void ReplaceWithNewModel(int32 id); virtual bool GetIsATreadable(void) { return false; } + + CBuilding *ctor(void) { return ::new (this) CBuilding(); } }; static_assert(sizeof(CBuilding) == 0x64, "CBuilding: error"); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index d2b2577d..294518c8 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -339,9 +339,9 @@ CEntity::GetBoundRect(void) return rect; } -void +WRAPPER void CEntity::PreRender(void) -{ +{ EAXJMP(0x474350); } void @@ -448,6 +448,7 @@ CEntity::PruneReferences(void) } STARTPATCHES + InjectHook(0x473C30, &CEntity::ctor, PATCH_JUMP); InjectHook(0x4742C0, (void (CEntity::*)(CVector&))&CEntity::GetBoundCentre, PATCH_JUMP); InjectHook(0x474310, &CEntity::GetBoundRadius, PATCH_JUMP); InjectHook(0x474C10, &CEntity::GetIsTouching, PATCH_JUMP); diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 0ce47428..8816e206 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -155,6 +155,7 @@ public: // to make patching virtual functions possible + CEntity *ctor(void) { return ::new (this) CEntity(); } void Add_(void) { CEntity::Add(); } void Remove_(void) { CEntity::Remove(); } void CreateRwObject_(void) { CEntity::CreateRwObject(); } From 1e09bf9c30094b4387431be4842876181a1425fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 24 Jun 2019 17:57:54 +0300 Subject: [PATCH 06/17] CPed, CVehicle, mostly entering/exiting car MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: eray orçunus --- src/animation/AnimBlendAssociation.h | 5 +- src/audio/AudioManager.cpp | 15 + src/audio/AudioManager.h | 8 + src/control/CarCtrl.cpp | 2 + src/control/CarCtrl.h | 2 + src/control/PedPlacement.cpp | 40 ++ src/control/PedPlacement.h | 8 + src/entities/Ped.cpp | 531 ++++++++++++++++++++++++++- src/entities/Ped.h | 41 ++- src/entities/Vehicle.cpp | 52 +++ src/entities/Vehicle.h | 88 ++++- src/math/Matrix.h | 24 ++ src/modelinfo/VehicleModelInfo.h | 10 +- src/weapons/Weapon.h | 3 +- 14 files changed, 789 insertions(+), 40 deletions(-) create mode 100644 src/audio/AudioManager.cpp create mode 100644 src/audio/AudioManager.h create mode 100644 src/control/PedPlacement.cpp create mode 100644 src/control/PedPlacement.h diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h index 7eec69a0..076fa810 100644 --- a/src/animation/AnimBlendAssociation.h +++ b/src/animation/AnimBlendAssociation.h @@ -2,8 +2,7 @@ #include "AnimBlendList.h" #include "AnimBlendNode.h" - -class CAnimBlendHierarchy; +#include "AnimBlendHierarchy.h" enum { // TODO @@ -78,6 +77,8 @@ public: void UpdateTime(float timeDelta, float relSpeed); bool UpdateBlend(float timeDelta); + float GetTimeLeft() { return hierarchy->totalLength - currentTime; } + static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) { return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link)); } diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp new file mode 100644 index 00000000..5da1d489 --- /dev/null +++ b/src/audio/AudioManager.cpp @@ -0,0 +1,15 @@ +#include "common.h" +#include "patcher.h" +#include "AudioManager.h" + +cAudioManager &AudioManager = *(cAudioManager*)0x880FC0; + +void +cAudioManager::PlayerJustLeftCar(void) +{ + // UNUSED: This is a perfectly empty function. +} + +STARTPATCHES + InjectHook(0x56AD20, &cAudioManager::PlayerJustLeftCar, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h new file mode 100644 index 00000000..37dd3218 --- /dev/null +++ b/src/audio/AudioManager.h @@ -0,0 +1,8 @@ +#pragma once + +class cAudioManager { +public: + void PlayerJustLeftCar(void); +}; + +extern cAudioManager &AudioManager; \ No newline at end of file diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index d59ae2d0..ff73e405 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -2,5 +2,7 @@ #include "patcher.h" #include "CarCtrl.h" +int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38; + WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } WRAPPER void CCarCtrl::AddToCarArray(int id, int vehclass) { EAXJMP(0x4182F0); } diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 1f468475..06204ddd 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -7,4 +7,6 @@ class CCarCtrl public: static void SwitchVehicleToRealPhysics(CVehicle*); static void AddToCarArray(int id, int vehclass); + + static int32 &NumLawEnforcerCars; }; diff --git a/src/control/PedPlacement.cpp b/src/control/PedPlacement.cpp new file mode 100644 index 00000000..de4cdae1 --- /dev/null +++ b/src/control/PedPlacement.cpp @@ -0,0 +1,40 @@ +#include "common.h" +#include "patcher.h" +#include "PedPlacement.h" +#include "World.h" + +void +CPedPlacement::FindZCoorForPed(CVector* pos) +{ + float zForPed; + float startZ = pos->z - 100.0f; + float foundColZ = -100.0f; + float foundColZ2 = -100.0f; + CColPoint foundCol; + CEntity* foundEnt; + + CVector vec( + pos->x, + pos->y, + pos->z + 1.0f + ); + + if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, false)) + foundColZ = foundCol.point.z; + + // Adjust coords and do a second test + vec.x += 0.1f; + vec.y += 0.1f; + + if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, false)) + foundColZ2 = foundCol.point.z; + + zForPed = max(foundColZ, foundColZ2); + + if (zForPed > -99.0f) + pos->z = 1.04f + zForPed; +} + +STARTPATCHES + InjectHook(0x4EE340, &CPedPlacement::FindZCoorForPed, PATCH_JUMP); +ENDPATCHES diff --git a/src/control/PedPlacement.h b/src/control/PedPlacement.h new file mode 100644 index 00000000..4bd48b62 --- /dev/null +++ b/src/control/PedPlacement.h @@ -0,0 +1,8 @@ +#pragma once + +class CVector; + +class CPedPlacement { +public: + static void FindZCoorForPed(CVector* pos); +}; \ No newline at end of file diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index f3e212d4..1b3e8a0e 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -10,11 +10,19 @@ #include "PlayerPed.h" #include "General.h" #include "VisibilityPlugins.h" +#include "AudioManager.h" +#include "HandlingMgr.h" +#include "Replay.h" +#include "PedPlacement.h" bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; bool &CPed::bPedCheat3 = *(bool*)0x95CD59; +CVector &CPed::offsetToOpenRegularCarDoor = *(CVector*)0x62E030; +CVector &CPed::offsetToOpenLowCarDoor = *(CVector*)0x62E03C; +CVector &CPed::offsetToOpenVanDoor = *(CVector*)0x62E048; + void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); } @@ -24,6 +32,9 @@ WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4 WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); } WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); } +WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); } +WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); } +WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); } static char ObjectiveText[34][28] = { "No Obj", @@ -183,9 +194,8 @@ static char WaitStateText[21][16] = { static RwObject* RemoveAllModelCB(RwObject *object, void *data) { - RpAtomic* atomic = (RpAtomic*)object; - if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) - { + RpAtomic *atomic = (RpAtomic*)object; + if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) { RpClumpRemoveAtomic(atomic->clump, atomic); RpAtomicDestroy(atomic); } @@ -299,6 +309,14 @@ CPed::UseGroundColModel(void) m_nPedState == PED_DEAD; } +bool +CPed::CanSetPedState(void) +{ + return m_nPedState != PED_DIE && m_nPedState != PED_ARRESTED && + m_nPedState != PED_ENTER_CAR && m_nPedState != PED_CARJACK && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_STEAL_CAR; +} + + void CPed::AddWeaponModel(int id) { @@ -398,8 +416,9 @@ CPed::RemoveBodyPart(PedNode nodeId, int8 unk) RecurseFrameChildrenVisibilityCB(frame, 0); pos.x = 0.0f; - pos.z = 0.0f; pos.y = 0.0f; + pos.z = 0.0f; + for (frame = RwFrameGetParent(frame); frame; frame = RwFrameGetParent(frame)) RwV3dTransformPoints(&pos, &pos, 1, RwFrameGetMatrix(frame)); @@ -602,7 +621,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) if (attackAssoc) { switch (attackAssoc->animId) { case ANIM_WEAPON_START_THROW: - if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1376) && ped->IsPlayer()) + if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer()) { attackAssoc->blendDelta = -1000.0; newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROWU); @@ -658,7 +677,7 @@ CPed::Attack(void) ourWeaponFire = ourWeapon->m_eWeaponFire; weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ourWeapon->m_AnimToPlay); lastReloadWasInFuture = m_ped_flagA4; - reloadAnimAssoc = 0; + reloadAnimAssoc = nil; reloadAnim = NUM_ANIMS; delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire; weaponAnim = ourWeapon->m_AnimToPlay; @@ -676,7 +695,7 @@ CPed::Attack(void) if (reloadAnimAssoc) { if (!CPed::IsPlayer() || ((CPlayerPed*)this)->field_1380) - CPed::ClearAttack(); + ClearAttack(); return; } @@ -686,12 +705,13 @@ CPed::Attack(void) lastReloadWasInFuture = true; if (!weaponAnimAssoc) { - if (ourWeapon->m_bThrow) { + weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ourWeapon->m_Anim2ToPlay); + delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire; + + // Long throw granade, molotov + if (!weaponAnimAssoc && ourWeapon->m_bThrow) { weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_WEAPON_THROWU); delayBetweenAnimAndFire = 0.2f; - } else { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ourWeapon->m_Anim2ToPlay); - delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire; } } if (weaponAnimAssoc) { @@ -742,7 +762,7 @@ CPed::Attack(void) CPed::ClearLookFlag(); CPed::ClearAimFlag(); m_ped_flagA4 = false; - m_ped_flagA8 = false; + bIsPointingGunAt = false; m_lastHitTime = CTimer::GetTimeInMilliseconds(); return; } @@ -885,7 +905,7 @@ CPed::RemoveWeaponModel(int modelId) void CPed::SetCurrentWeapon(eWeaponType weaponType) { - CWeaponInfo* weaponInfo; + CWeaponInfo *weaponInfo; if (HasWeapon(weaponType)) { weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); @@ -909,8 +929,8 @@ CPed::SelectGunIfArmed(void) if (m_weapons[i].m_nAmmoTotal > 0) { weaponType = m_weapons[i].m_eWeaponType; - // Original condition was ridiculous - // if (weaponType == WEAPONTYPE_COLT45 || weaponType < WEAPONTYPE_M16 || weaponType < WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_FLAMETHROWER) + // I GOT THAT WRONG AND SHOULD BE FIXED!! (but I don't know how) Original code was; + // if ( v3 == 2 || (unsigned int)(v3 - 3) <= 2 || (unsigned int)(v3 - 7) <= 1 || v3 == 9 ) if (weaponType < WEAPONTYPE_MOLOTOV) { SetCurrentWeapon(weaponType); return true; @@ -960,7 +980,7 @@ CPed::ClearPointGunAt(void) ClearLookFlag(); ClearAimFlag(); - m_ped_flagA8 = false; + bIsPointingGunAt = false; if (m_nPedState == PED_AIM_GUN) { RestorePreviousState(); weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); @@ -975,6 +995,478 @@ CPed::ClearPointGunAt(void) } } +void +CPed::BeingDraggedFromCar(void) +{ + CAnimBlendAssociation *animAssoc; + AnimationId enterAnim; + bool dontRunAnim = false; + PedLineUpPhase lineUpType; + + if (!m_pVehicleAnim) { + CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f); + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SIT); + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_LSIT); + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SITP); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SITPLO); + } + } + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (m_vehEnterType == VEHICLE_ENTER_FRONT_LEFT || m_vehEnterType == VEHICLE_ENTER_REAR_LEFT) { + if (m_ped_flagF10) { + enterAnim = ANIM_CAR_QJACKED; + } else if (m_pMyVehicle->bIsLow) { + enterAnim = ANIM_CAR_LJACKED_LHS; + } else { + enterAnim = ANIM_CAR_JACKED_LHS; + } + } else if (m_vehEnterType == VEHICLE_ENTER_FRONT_RIGHT || m_vehEnterType == VEHICLE_ENTER_REAR_RIGHT) { + if (m_pMyVehicle->bIsLow) + enterAnim = ANIM_CAR_LJACKED_RHS; + else + enterAnim = ANIM_CAR_JACKED_RHS; + } else + dontRunAnim = true; + + + if (!dontRunAnim) + m_pVehicleAnim = CAnimManager::AddAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, enterAnim); + + m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this); + lineUpType = LINE_UP_TO_CAR_START; + } else if (m_pVehicleAnim->currentTime <= 1.4f) { + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + lineUpType = LINE_UP_TO_CAR_START; + } else { + lineUpType = LINE_UP_TO_CAR_2; + } + + LineUpPedWithCar(lineUpType); +} + +void +CPed::RestartNonPartialAnims(void) +{ + CAnimBlendAssociation* assoc; + + for (assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject); !assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + if (!assoc->IsPartial()) + assoc->flags |= ASSOC_RUNNING; + } +} + +void +CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) +{ + CAnimBlendAssociation *quickJackedAssoc; + CVehicle *vehicle; + CPed *ped = (CPed*)arg; + eWeaponType weaponType = ped->GetWeapon()->m_eWeaponType; + + quickJackedAssoc = RpAnimBlendClumpGetAssociation((RpClump*) ped->m_rwObject, ANIM_CAR_QJACKED); + if (ped->m_nPedState != PED_ARRESTED) { + ped->m_nLastPedState = PED_NONE; + if (dragAssoc) + dragAssoc->blendDelta = -1000.0; + } + ped->RestartNonPartialAnims(); + ped->m_pVehicleAnim = nil; + ped->m_pSeekTarget = nil; + vehicle = ped->m_pMyVehicle; + + if (ped->m_vehEnterType <= VEHICLE_ENTER_REAR_LEFT) { + switch (ped->m_vehEnterType) { + case VEHICLE_ENTER_FRONT_RIGHT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FR; + break; + case VEHICLE_ENTER_REAR_RIGHT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RR; + break; + case VEHICLE_ENTER_FRONT_LEFT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FL; + break; + case VEHICLE_ENTER_REAR_LEFT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RL; + break; + default: + break; + } + } + + if (vehicle->pDriver == ped) { + vehicle->RemoveDriver(); + if (vehicle->m_nDoorLock == CARLOCK_COP_CAR) + vehicle->m_nDoorLock = CARLOCK_UNLOCKED; + + if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle()) + vehicle->ChangeLawEnforcerState(false); + } else { + for (int i = 0; i < vehicle->m_nNumMaxPassengers; i++) { + if (vehicle->pPassengers[i] == ped) { + vehicle->pPassengers[i] = nil; + vehicle->m_nNumPassengers--; + } + } + } + + ped->bInVehicle = false; + if (ped->IsPlayer()) + AudioManager.PlayerJustLeftCar(); + + if (quickJackedAssoc) { + dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped); + } else { + dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); + if (ped->CanSetPedState()) + CAnimManager::BlendAnimation((RpClump*) ped->m_rwObject, ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + } + + // Only uzi can be used on cars, so previous weapon was stored + if (ped->IsPlayer() && weaponType == WEAPONTYPE_UZI) { + if (ped->m_storedWeapon != NO_STORED_WEAPON) { + ped->SetCurrentWeapon(ped->m_storedWeapon); + ped->m_storedWeapon = NO_STORED_WEAPON; + } + } else { + ped->AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId); + } + ped->m_nStoredActionState = 0; + ped->m_ped_flagI4 = false; +} + +void +CPed::GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult) +{ + CVehicleModelInfo *vehModel; + CVector vehDoorPos; + CVector vehDoorOffset; + float seatOffset; + + vehModel = (CVehicleModelInfo*) CModelInfo::GetModelInfo(veh->m_modelIndex); + if (veh->bIsVan && (enterType == VEHICLE_ENTER_REAR_LEFT || enterType == VEHICLE_ENTER_REAR_RIGHT)) { + seatOffset = 0.0f; + vehDoorOffset = offsetToOpenVanDoor; + } else { + seatOffset = veh->m_handling->fSeatOffsetDistance * seatPosMult; + if (veh->bIsLow) { + vehDoorOffset = offsetToOpenLowCarDoor; + } else { + vehDoorOffset = offsetToOpenRegularCarDoor; + } + } + + switch (enterType) { + case VEHICLE_ENTER_FRONT_RIGHT: + if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_BOAT_RUDDER]; + else + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_FRONT_SEATS]; + + vehDoorPos.x += seatOffset; + vehDoorOffset.x = -vehDoorOffset.x; + break; + + case VEHICLE_ENTER_REAR_RIGHT: + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_REAR_SEATS]; + vehDoorPos.x += seatOffset; + vehDoorOffset.x = -vehDoorOffset.x; + break; + + case VEHICLE_ENTER_FRONT_LEFT: + if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_BOAT_RUDDER]; + else + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_FRONT_SEATS]; + + vehDoorPos.x = -(vehDoorPos.x + seatOffset); + break; + + case VEHICLE_ENTER_REAR_LEFT: + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_REAR_SEATS]; + vehDoorPos.x = -(vehDoorPos.x + seatOffset); + break; + + default: + if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_BOAT_RUDDER]; + else + vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_FRONT_SEATS]; + + vehDoorOffset = CVector(0.0f, 0.0f, 0.0f); + } + *output = vehDoorPos - vehDoorOffset; +} + +// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it. +void +CPed::GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType) +{ + CVector localPos; + CVector vehDoorPos; + + GetLocalPositionToOpenCarDoor(&localPos, veh, enterType, 1.0f); + vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition(); + +/* + // Not used. + CVector localVehDoorOffset; + + if (veh->bIsVan && (enterType == VEHICLE_ENTER_REAR_LEFT || enterType == VEHICLE_ENTER_REAR_RIGHT)) { + localVehDoorOffset = offsetToOpenVanDoor; + } else { + if (veh->bIsLow) { + localVehDoorOffset = offsetToOpenLowCarDoor; + } else { + localVehDoorOffset = offsetToOpenRegularCarDoor; + } + } + + vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition(); +*/ + *output = vehDoorPos; +} + +void +CPed::GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset) +{ + CVector doorPos; + CMatrix vehMat(veh->GetMatrix()); + + GetLocalPositionToOpenCarDoor(output, veh, enterType, offset); + doorPos = Multiply3x3(vehMat, *output); + + *output = *vehMat.GetPosition() + doorPos; +} + +void +CPed::LineUpPedWithCar(PedLineUpPhase phase) +{ + bool vehIsUpsideDown = false; + int vehAnim; + float seatPosMult = 0.0f; + float currentZ; + float adjustedTimeStep; + + if (CReplay::IsPlayingBack()) + return; + + if (!m_ped_flagC8 && phase != LINE_UP_TO_CAR_2) { + if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SIT)) { + SetPedPositionInCar(); + return; + } + if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_LSIT)) { + SetPedPositionInCar(); + return; + } + if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SITP)) { + SetPedPositionInCar(); + return; + } + if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SITPLO)) { + SetPedPositionInCar(); + return; + } + m_ped_flagC8 = 1; + } + if (phase == LINE_UP_TO_CAR_START) { + m_vecMoveSpeed.x = 0.0; + m_vecMoveSpeed.y = 0.0; + m_vecMoveSpeed.z = 0.0; + } + CVehicle *veh = m_pMyVehicle; + + // Not quite right, IsUpsideDown func. checks for <= -0.9f. + // Since that function is also used in this file, doesn't this variable indicate upsidedownness?! + if (veh->GetUp().z <= -0.8f) + vehIsUpsideDown = true; + + if (m_vehEnterType == VEHICLE_ENTER_FRONT_RIGHT || m_vehEnterType == VEHICLE_ENTER_REAR_RIGHT) { + if (vehIsUpsideDown) { + m_fRotationDest = -PI + atan2(-veh->GetForward().x, veh->GetForward().y); + } else if (veh->bIsBus) { + m_fRotationDest = 0.5 * PI + atan2(-veh->GetForward().x, veh->GetForward().y); + } else { + m_fRotationDest = atan2(-veh->GetForward().x, veh->GetForward().y); + } + } else if (m_vehEnterType == VEHICLE_ENTER_FRONT_LEFT || m_vehEnterType == VEHICLE_ENTER_REAR_LEFT) { + if (vehIsUpsideDown) { + m_fRotationDest = atan2(-veh->GetForward().x, veh->GetForward().y); + } else if (veh->bIsBus) { + m_fRotationDest = -0.5 * PI + atan2(-veh->GetForward().x, veh->GetForward().y); + } else { + m_fRotationDest = atan2(-veh->GetForward().x, veh->GetForward().y); + } + } + + if (!bInVehicle) + seatPosMult = 1.0f; + + if (m_pVehicleAnim) { + vehAnim = m_pVehicleAnim->animId; + + switch (vehAnim) { + case ANIM_CAR_JACKED_RHS: + case ANIM_CAR_LJACKED_RHS: + case ANIM_CAR_JACKED_LHS: + case ANIM_CAR_LJACKED_LHS: + case ANIM_CAR_QJACKED: + case ANIM_CAR_GETOUT_LHS: + case ANIM_CAR_GETOUT_LOW_LHS: + case ANIM_CAR_GETOUT_RHS: + case ANIM_CAR_GETOUT_LOW_RHS: + case ANIM_CAR_CRAWLOUT_RHS: + case ANIM_CAR_CRAWLOUT_RHS2: + case ANIM_VAN_GETIN_L: + case ANIM_VAN_GETOUT_L: + case ANIM_VAN_GETIN: + case ANIM_VAN_GETOUT: + seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength; + break; + case ANIM_CAR_QJACK: + case ANIM_CAR_GETIN_LHS: + case ANIM_CAR_GETIN_LOW_LHS: + case ANIM_CAR_GETIN_RHS: + case ANIM_CAR_GETIN_LOW_RHS: + case ANIM_DRIVE_BOAT: + seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength; + break; + case ANIM_CAR_CLOSEDOOR_LHS: + case ANIM_CAR_CLOSEDOOR_LOW_LHS: + case ANIM_CAR_CLOSEDOOR_RHS: + case ANIM_CAR_CLOSEDOOR_LOW_RHS: + case ANIM_CAR_SHUFFLE_RHS: + case ANIM_CAR_LSHUFFLE_RHS: + seatPosMult = 0.0f; + break; + case ANIM_CAR_CLOSE_LHS: + case ANIM_CAR_CLOSE_RHS: + case ANIM_COACH_OPEN_L: + case ANIM_COACH_OPEN_R: + case ANIM_COACH_IN_L: + case ANIM_COACH_IN_R: + case ANIM_COACH_OUT_L: + seatPosMult = 1.0f; + break; + default: + break; + } + } + + CVector neededPos; + + if (phase == LINE_UP_TO_CAR_2) { + neededPos = GetPosition(); + } else { + GetPositionToOpenCarDoor(&neededPos, veh, m_vehEnterType, seatPosMult); + } + + CVector autoZPos = neededPos; + + if (veh->bIsInWater) { + if (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown()) + autoZPos.z += 1.0f; + } else { + CPedPlacement::FindZCoorForPed(&autoZPos); + } + + if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) { + neededPos.z = GetPosition().z; + + if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) { + float vehNextZSpeed = m_vecMoveSpeed.z - 0.008f * CTimer::GetTimeStep(); + + if (neededPos.z + vehNextZSpeed > autoZPos.z) { + m_vecMoveSpeed.z = vehNextZSpeed; + veh->ApplyMoveSpeed(); + } else { + neededPos.z = autoZPos.z; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } + } + } + + if (autoZPos.z > neededPos.z) { + currentZ = GetPosition().z; + if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) { + neededPos.z = autoZPos.z; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } else if (neededPos.z < currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) { + + adjustedTimeStep = min(m_pVehicleAnim->timeStep, 0.1f); + + // Smoothly change ped position + neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep); + } + } else { + // We may need to raise up the ped + if (phase == LINE_UP_TO_CAR_START) { + currentZ = GetPosition().z; + + if (neededPos.z > currentZ) { + + if (m_pVehicleAnim && + (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim <= ANIM_CAR_GETIN_LOW_LHS + || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) { + + adjustedTimeStep = min(m_pVehicleAnim->timeStep, 0.1f); + + // Smoothly change ped position + neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ; + } else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK) { + neededPos.z = max(currentZ, autoZPos.z); + } + } + } + } + + // I hope + bool notInWater = false; + if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) + notInWater = veh->m_vehType != VEHICLE_TYPE_BOAT || m_ped_flagG10; + + if (!notInWater) { + m_fRotationCur = m_fRotationDest; + } else { + float limitedAngle = CGeneral::LimitRadianAngle(m_fRotationDest); + float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds()) / 500.0f; // * 0.0016666667f; + + m_vecOffsetSeek.z = 0.0; + if (timeUntilStateChange <= 0.0f) { + m_vecOffsetSeek.x = 0.0; + m_vecOffsetSeek.y = 0.0; + } else { + neededPos -= timeUntilStateChange * m_vecOffsetSeek; + } + + if (limitedAngle >= PI + m_fRotationCur) { + limitedAngle -= 2 * PI; + } else if (limitedAngle <= m_fRotationCur - PI) { + limitedAngle += 2 * PI; + } + m_fRotationCur -= (m_fRotationCur - limitedAngle) * (1.0f - timeUntilStateChange); + } + + if (seatPosMult > 0.2f || vehIsUpsideDown) { + GetMatrix().SetRotate(0.0f, 0.0f, m_fRotationCur); + + // It will be all 0 after rotate. + GetPosition() = neededPos; + } else { + CVector output; + CMatrix vehDoorMat(veh->GetMatrix()); + + GetLocalPositionToOpenCarDoor(&output, veh, m_vehEnterType, 0.0f); + *vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, output); + GetMatrix() = vehDoorMat; + } +} + STARTPATCHES InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP); InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP); @@ -997,4 +1489,11 @@ STARTPATCHES InjectHook(0x4E4A10, &CPed::Duck, PATCH_JUMP); InjectHook(0x4E4A30, &CPed::ClearDuck, PATCH_JUMP); InjectHook(0x4E6180, &CPed::ClearPointGunAt, PATCH_JUMP); + InjectHook(0x4E07D0, &CPed::BeingDraggedFromCar, PATCH_JUMP); + InjectHook(0x4CF000, &CPed::PedSetDraggedOutCarCB, PATCH_JUMP); + InjectHook(0x4C5D80, &CPed::RestartNonPartialAnims, PATCH_JUMP); + InjectHook(0x4E4730, &CPed::GetLocalPositionToOpenCarDoor, PATCH_JUMP); + InjectHook(0x4E4660, (void (*)(CVector*, CVehicle*, uint32, float)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); + InjectHook(0x4E1A30, (void (*)(CVector*, CVehicle*, uint32)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); + InjectHook(0x4DF940, &CPed::LineUpPedWithCar, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Ped.h b/src/entities/Ped.h index 800c5bb9..187bd08c 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -12,6 +12,19 @@ struct CPathNode; +enum { + VEHICLE_ENTER_FRONT_RIGHT = 11, + VEHICLE_ENTER_REAR_RIGHT = 12, + VEHICLE_ENTER_FRONT_LEFT = 15, + VEHICLE_ENTER_REAR_LEFT = 16, +}; + +enum PedLineUpPhase { + LINE_UP_TO_CAR_START, + LINE_UP_TO_CAR_END, + LINE_UP_TO_CAR_2 +}; + enum PedOnGroundState { NO_PED, PED_BELOW_PLAYER, @@ -102,7 +115,7 @@ public: uint8 m_ped_flagA1 : 1; uint8 m_ped_flagA2 : 1; uint8 m_ped_flagA4 : 1; // stores (CTimer::GetTimeInMilliseconds() < m_lastHitTime) - uint8 m_ped_flagA8 : 1; + uint8 bIsPointingGunAt : 1; uint8 bIsLooking : 1; uint8 m_ped_flagA20 : 1; // "look" method? - probably missing in SA uint8 bIsRestoringLook : 1; @@ -177,15 +190,15 @@ public: int32 m_pEventEntity; float m_fAngleToEvent; AnimBlendFrameData *m_pFrames[PED_NODE_MAX]; - int32 m_animGroup; - int32 m_pVehicleAnim; + AssocGroupId m_animGroup; + CAnimBlendAssociation *m_pVehicleAnim; CVector2D m_vecAnimMoveDelta; CVector m_vecOffsetSeek; CPedIK m_pedIK; uint8 stuff1[8]; uint32 m_nPedStateTimer; PedState m_nPedState; - int32 m_nLastPedState; + PedState m_nLastPedState; int32 m_nMoveState; int32 m_nStoredActionState; int32 m_nPrevActionState; @@ -207,7 +220,9 @@ public: uint8 stuff2[20]; float m_fRotationCur; float m_fRotationDest; - uint8 stuff13[6]; + uint32 m_headingRate; + uint16 m_vehEnterType; + uint16 m_walkAroundType; CEntity *m_pCurrentPhysSurface; CVector m_vecOffsetFromPhysSurface; CEntity *m_pCurSurface; @@ -222,7 +237,7 @@ public: CEntity *m_pCollidingEntity; uint8 stuff6[12]; CWeapon m_weapons[NUM_PED_WEAPONTYPES]; - int32 stuff7; + eWeaponType m_storedWeapon; uint8 m_currentWeapon; // eWeaponType uint8 m_maxWeaponTypeAllowed; // eWeaponType uint8 stuff[2]; @@ -253,6 +268,7 @@ public: bool IsPlayer(void); bool UseGroundColModel(void); + bool CanSetPedState(void); void AddWeaponModel(int id); void AimGun(void); void KillPedWithCar(CVehicle *veh, float impulse); @@ -278,14 +294,27 @@ public: void Duck(void); void ClearDuck(void); void ClearPointGunAt(void); + void BeingDraggedFromCar(void); + void RestartNonPartialAnims(void); + void LineUpPedWithCar(PedLineUpPhase phase); + void SetPedPositionInCar(void); + static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); + static void GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult); + static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType); static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data); static RwFrame *RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data); static void FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg); + static void PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg); + static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg); + static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg); bool HasWeapon(eWeaponType weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; } + static CVector &offsetToOpenRegularCarDoor; + static CVector &offsetToOpenLowCarDoor; + static CVector &offsetToOpenVanDoor; static bool &bNastyLimbsCheat; static bool &bPedCheat2; static bool &bPedCheat3; diff --git a/src/entities/Vehicle.cpp b/src/entities/Vehicle.cpp index bac05f7b..ced504a3 100644 --- a/src/entities/Vehicle.cpp +++ b/src/entities/Vehicle.cpp @@ -2,6 +2,8 @@ #include "patcher.h" #include "Vehicle.h" #include "Pools.h" +#include "CarCtrl.h" +#include "ModelIndices.h" bool &CVehicle::bWheelsOnlyCheat = *(bool *)0x95CD78; bool &CVehicle::bAllDodosCheat = *(bool *)0x95CD75; @@ -11,3 +13,53 @@ bool &CVehicle::bCheat5 = *(bool *)0x95CD64; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void CVehicle::operator delete(void *p, size_t sz) { CPools::GetVehiclePool()->Delete((CVehicle*)p); } + +bool +CVehicle::IsLawEnforcementVehicle(void) +{ + switch (m_modelIndex) { + case MI_FBICAR: + case MI_POLICE: + case MI_ENFORCER: + case MI_PREDATOR: + case MI_RHINO: + case MI_BARRACKS: + return true; + default: + return false; + } +} + +void +CVehicle::ChangeLawEnforcerState(bool enable) +{ + if (enable) { + if (!bIsLawEnforcer) { + bIsLawEnforcer = true; + CCarCtrl::NumLawEnforcerCars++; + } + } else { + if (bIsLawEnforcer) { + bIsLawEnforcer = false; + CCarCtrl::NumLawEnforcerCars--; + } + } +} + +void +CVehicle::RemoveDriver(void) +{ + m_status = STATUS_ABANDONED; + pDriver = nil; +} + +bool +CVehicle::IsUpsideDown(void) +{ + return GetUp().z <= -0.9f; +} + +STARTPATCHES + InjectHook(0x552820, &CVehicle::ChangeLawEnforcerState, PATCH_JUMP); + InjectHook(0x5520A0, &CVehicle::RemoveDriver, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/entities/Vehicle.h b/src/entities/Vehicle.h index e5d1cfb3..f11e9e97 100644 --- a/src/entities/Vehicle.h +++ b/src/entities/Vehicle.h @@ -3,23 +3,53 @@ #include "Physical.h" class CPed; +class CFire; +struct tHandlingData; + +enum { + GETTING_IN_OUT_FL = 1, + GETTING_IN_OUT_RL = 2, + GETTING_IN_OUT_FR = 4, + GETTING_IN_OUT_RR = 8 +}; + +enum eCarLock : uint8 { + CARLOCK_NOT_USED, + CARLOCK_UNLOCKED, + CARLOCK_LOCKED, + CARLOCK_LOCKOUT_PLAYER_ONLY, + CARLOCK_LOCKED_PLAYER_INSIDE, + CARLOCK_COP_CAR, + CARLOCK_FORCE_SHUT_DOORS, + CARLOCK_SKIP_SHUT_DOORS +}; class CVehicle : public CPhysical { public: // 0x128 - uint8 stuff1[116]; + tHandlingData *m_handling; + uint8 stuff1[112]; uint8 m_currentColour1; uint8 m_currentColour2; -uint8 m_extra1; -uint8 m_extra2; - int16 m_nAlarmState; + uint8 m_anExtras[2]; + int16 m_nAlarmState; // m_nWantedStarsOnEnter on DK22 + int16 m_nMissionValue; CPed *pDriver; CPed *pPassengers[8]; - uint8 stuff2[24]; + uint8 m_nNumPassengers; + int8 m_nNumGettingIn; + int8 m_nGettingInFlags; + int8 m_nGettingOutFlags; + uint8 m_nNumMaxPassengers; + char field_1CD[19]; CEntity *m_pCurSurface; - uint8 stuff3[17]; - uint8 m_veh_flagA1 : 1; + CFire *m_pCarFire; + float m_fSteerAngle; + float m_fGasPedal; + float m_fBreakPedal; + uint8 m_nCreatedBy; // eVehicleCreatedBy + uint8 bIsLawEnforcer : 1; uint8 m_veh_flagA2 : 1; uint8 m_veh_flagA4 : 1; uint8 m_veh_flagA8 : 1; @@ -27,10 +57,10 @@ uint8 m_extra2; uint8 m_veh_flagA20 : 1; uint8 m_veh_flagA40 : 1; uint8 m_veh_flagA80 : 1; - uint8 m_veh_flagB1 : 1; - uint8 m_veh_flagB2 : 1; - uint8 m_veh_flagB4 : 1; - uint8 m_veh_flagB8 : 1; + uint8 bIsVan : 1; + uint8 bIsBus : 1; + uint8 bIsBig : 1; + uint8 bIsLow : 1; uint8 m_veh_flagB10 : 1; uint8 m_veh_flagB20 : 1; uint8 m_veh_flagB40 : 1; @@ -51,8 +81,34 @@ uint8 m_extra2; uint8 m_veh_flagD20 : 1; uint8 m_veh_flagD40 : 1; uint8 m_veh_flagD80 : 1; - uint8 stuff4[139]; - int32 m_vehType; + int8 field_1F9; + uint8 m_nAmmoInClip[1]; // Used to make the guns on boat do a reload (20 by default) + int8 field_1FB; + int8 field_1FC[4]; + float m_fHealth; // 1000.0f = full health. 0 -> explode + uint8 m_nCurrentGear; + int8 field_205[3]; + int field_208; + uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats) + uint32 m_nTimeOfDeath; + int16 field_214; + int16 m_nBombTimer; // goes down with each frame + CPed *m_pWhoDetonatedMe; + float field_21C; + float field_220; + eCarLock m_nDoorLock; + int8 m_nLastWeaponDamage; // see eWeaponType, -1 if no damage + int8 m_nRadioStation; + int8 field_22A; + int8 field_22B; + uint8 m_nCarHornTimer; + int8 field_22D; + uint8 m_nSirenOrAlarm; + int8 field_22F; + CStoredCollPoly m_frontCollPoly; // poly which is under front part of car + CStoredCollPoly m_rearCollPoly; // poly which is under rear part of car + float m_fSteerRatio; + eVehicleType m_vehType; static void *operator new(size_t); static void operator delete(void*, size_t); @@ -62,6 +118,10 @@ uint8 m_extra2; bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; } bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; } bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; } + bool IsLawEnforcementVehicle(void); + void ChangeLawEnforcerState(bool enable); + void RemoveDriver(void); + bool IsUpsideDown(void); static bool &bWheelsOnlyCheat; static bool &bAllDodosCheat; @@ -69,5 +129,7 @@ uint8 m_extra2; static bool &bCheat4; static bool &bCheat5; }; + static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error"); static_assert(offsetof(CVehicle, m_pCurSurface) == 0x1E0, "CVehicle: error"); +static_assert(offsetof(CVehicle, m_nAlarmState) == 0x1A0, "CVehicle: error"); diff --git a/src/math/Matrix.h b/src/math/Matrix.h index a93de636..74e3d70d 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -145,6 +145,30 @@ public: m_matrix.pos.y = 0.0f; m_matrix.pos.z = 0.0f; } + void SetRotate(float xAngle, float yAngle, float zAngle) { + float cX = cos(xAngle); + float sX = sin(xAngle); + float cY = cos(yAngle); + float sY = sin(yAngle); + float cZ = cos(zAngle); + float sZ = sin(zAngle); + + m_matrix.right.x = cZ * cY - (sZ * sX) * sY; + m_matrix.right.y = (cZ * sX) * sY + sZ * cY; + m_matrix.right.z = -cX * sY; + + m_matrix.up.x = -sZ * cX; + m_matrix.up.y = cZ * cX; + m_matrix.up.z = sX; + + m_matrix.at.x = (sZ * sX) * cY + cZ * sY; + m_matrix.at.y = sZ * sY - (cZ * sX) * cY; + m_matrix.at.z = cX * cY; + + m_matrix.pos.x = 0.0f; + m_matrix.pos.y = 0.0f; + m_matrix.pos.z = 0.0f; + } void Reorthogonalise(void){ CVector &r = *GetRight(); CVector &f = *GetForward(); diff --git a/src/modelinfo/VehicleModelInfo.h b/src/modelinfo/VehicleModelInfo.h index 8068d359..2e2f1be2 100644 --- a/src/modelinfo/VehicleModelInfo.h +++ b/src/modelinfo/VehicleModelInfo.h @@ -3,7 +3,6 @@ #include "ClumpModelInfo.h" enum { - NUM_VEHICLE_POSITIONS = 10, NUM_FIRST_MATERIALS = 26, NUM_SECOND_MATERIALS = 26, NUM_VEHICLE_COLOURS = 8, @@ -25,7 +24,7 @@ enum { ATOMIC_FLAG_NOCULL = 0x800, }; -enum { +enum eVehicleType { VEHICLE_TYPE_CAR, VEHICLE_TYPE_BOAT, VEHICLE_TYPE_TRAIN, @@ -46,6 +45,13 @@ enum { NUM_VEHICLE_CLASSES }; +enum { + VEHICLE_DUMMY_BOAT_RUDDER = 0, + VEHICLE_DUMMY_FRONT_SEATS = 2, + VEHICLE_DUMMY_REAR_SEATS = 3, + NUM_VEHICLE_POSITIONS = 10 +}; + class CVehicleModelInfo : public CClumpModelInfo { public: diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 6009a549..aebcb2c6 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -18,7 +18,8 @@ enum eWeaponType WEAPONTYPE_DETONATOR, NUM_PED_WEAPONTYPES = 13, WEAPONTYPE_HELICANNON = 13, - NUM_WEAPONTYPES + NUM_WEAPONTYPES, + NO_STORED_WEAPON = 22 }; enum eWeaponFire { From e765dfe90a5519dc221580acf6d78fdd9c74ceab Mon Sep 17 00:00:00 2001 From: _AG Date: Tue, 25 Jun 2019 02:34:29 +0200 Subject: [PATCH 07/17] Initial commit for Frontend. Bug fixes: fix #40, fix #39, fix #38, fix #37, fix #21. Code organization and cleanup... --- src/Frontend.cpp | 1477 +++++++++++++++++++++++++++++++++++- src/Frontend.h | 177 ++++- src/PCSave.cpp | 5 + src/PCSave.h | 9 +- src/Radar.cpp | 1168 ++++++++++++++++------------ src/Radar.h | 59 +- src/audio/DMAudio.cpp | 2 + src/audio/DMAudio.h | 2 + src/audio/MusicManager.cpp | 2 + src/audio/MusicManager.h | 1 + src/config.h | 1 + src/control/Garages.cpp | 14 +- src/control/Replay.cpp | 20 +- src/main.cpp | 22 + src/render/Font.h | 24 + src/render/Hud.cpp | 43 +- src/render/Hud.h | 6 +- src/skel/win/win.cpp | 6 +- src/skel/win/win.h | 2 + 19 files changed, 2489 insertions(+), 551 deletions(-) diff --git a/src/Frontend.cpp b/src/Frontend.cpp index b8ee10f4..9b0e185d 100644 --- a/src/Frontend.cpp +++ b/src/Frontend.cpp @@ -1,6 +1,24 @@ +#define DIRECTINPUT_VERSION 0x0800 +#include #include "common.h" #include "patcher.h" +#include "win.h" #include "Frontend.h" +#include "Font.h" +#include "Pad.h" +#include "Text.h" +#include "main.h" +#include "Timer.h" +#include "Game.h" +#include "DMAudio.h" +#include "MusicManager.h" +#include "FileMgr.h" +#include "Streaming.h" +#include "TxdStore.h" +#include "General.h" +#include "PCSave.h" +#include "Script.h" +#include "Camera.h" int32 &CMenuManager::OS_Language = *(int32*)0x5F2F78; int8 &CMenuManager::m_PrefsUseVibration = *(int8*)0x95CD92; @@ -17,6 +35,7 @@ int8 &CMenuManager::m_PrefsLanguage = *(int8*)0x941238; bool &CMenuManager::m_PrefsAllowNastyGame = *(bool*)0x5F2E64; bool &CMenuManager::m_bStartUpFrontEndRequested = *(bool*)0x95CCF4; +bool &CMenuManager::m_bShutDownFrontEndRequested = *(bool*)0x95CD6A; int8 &CMenuManager::m_PrefsUseWideScreen = *(int8*)0x95CD23; int8 &CMenuManager::m_PrefsRadioStation = *(int8*)0x95CDA4; @@ -29,14 +48,1135 @@ int32 &CMenuManager::m_PrefsSfxVolume = *(int32*)0x5F2E48; CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8; -WRAPPER void CMenuManager::Process(void) { EAXJMP(0x485100); } -WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); } -WRAPPER void CMenuManager::UnloadTextures(void) { EAXJMP(0x47A440); } -WRAPPER void CMenuManager::LoadAllTextures(void) { EAXJMP(0x47A230); } -WRAPPER void CMenuManager::LoadSettings(void) { EAXJMP(0x488EE0); } -WRAPPER void CMenuManager::WaitForUserCD(void) { EAXJMP(0x48ADD0); } +const CMenuScreen aScreens[] = { + // MENU_PAGE_NONE = 0 + { "", -1, -1, 1, 0, 0, }, -int CMenuManager::FadeIn(int alpha) { + // MENU_PAGE_STATS = 1 + { "FET_STA", 0, 0, 0, 5, 2, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_NEW_GAME = 2 + { "FET_SGA", 0, 0, 0, 0, 1, + 2, "FES_SNG", 0, 10, + 22, "GMLOAD", 0, 8, + 2, "FES_DGA", 0, 9, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_BRIEFS = 3 + { "FET_BRE", 0, 0, 0, 6, 3, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_CONTROLLER_SETTINGS = 4 + { "FET_CON", 41, 41, 41, 0, 0, + + }, + + // MENU_PAGE_SOUND_SETTINGS = 5 + { "FET_AUD", 41, 41, 41, 1, 1, + 13, "FEA_MUS", 0, 5, + 14, "FEA_SFX", 0, 5, + 95, "FEA_3DH", 0, 5, + 96, "FEA_SPK", 0, 5, + 100, "FET_DAM", 0, 5, + 16, "FEA_RSS", 0, 5, + 98, "FET_DEF", 0, 5, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_GRAPHICS_SETTINGS = 6 + { "FET_DIS", 41, 41, 41, 2, 2, + 11, "FED_BRI", 0, 6, + 12, "FEM_LOD", 0, 6, + 6, "FEM_VSC", 0, 6, + 7, "FEM_FRM", 0, 6, + 8, "FED_TRA", 0, 6, + 9, "FED_SUB", 0, 6, + 10, "FED_WIS", 0, 6, + 94, "FED_RES", 0, 6, + 98, "FET_DEF", 0, 6, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_LANGUAGE_SETTINGS = 7 + { "FET_LAN", 41, 41, 41, 3, 3, + 17, "FEL_ENG", 0, 7, + 18, "FEL_FRE", 0, 7, + 19, "FEL_GER", 0, 7, + 20, "FEL_ITA", 0, 7, + 21, "FEL_SPA", 0, 7, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_CHOOSE_LOAD_SLOT = 8 + { "FET_LG", 2, 2, 2, 1, 1, + 2, "FESZ_CA", 0, 2, + 23, "FEM_SL1", 2, 11, + 23, "FEM_SL2", 3, 11, + 23, "FEM_SL3", 4, 11, + 23, "FEM_SL4", 5, 11, + 23, "FEM_SL5", 6, 11, + 23, "FEM_SL6", 7, 11, + 23, "FEM_SL7", 8, 11, + 23, "FEM_SL8", 9, 11, + }, + + // MENU_PAGE_CHOOSE_DELETE_SLOT = 9 + { "FET_DG", 2, 2, 2, 2, 2, + 2, "FESZ_CA", 0, 2, + 2, "FEM_SL1", 2, 12, + 2, "FEM_SL2", 3, 12, + 2, "FEM_SL3", 4, 12, + 2, "FEM_SL4", 5, 12, + 2, "FEM_SL5", 6, 12, + 2, "FEM_SL6", 7, 12, + 2, "FEM_SL7", 8, 12, + 2, "FEM_SL8", 9, 12, + }, + + // MENU_PAGE_NEW_GAME_RELOAD = 10 + { "FET_NG", 2, 2, 2, 0, 0, + 1, "FESZ_QR", 0, 0, + 2, "FEM_NO", 0, 2, + 25, "FEM_YES", 0, 10, + }, + + // MENU_PAGE_LOAD_SLOT_CONFIRM = 11 + { "FET_LG", 8, 8, 8, 0, 0, + 1, "FESZ_QL", 0, 0, + 2, "FEM_NO", 0, 8, + 2, "FEM_YES", 0, 14, + }, + + // MENU_PAGE_DELETE_SLOT_CONFIRM = 12 + { "FET_DG", 9, 9, 9, 0, 0, + 1, "FESZ_QD", 0, 0, + 2, "FEM_NO", 0, 9, + 2, "FEM_YES", 0, 45, + }, + + // MENU_PAGE_13 = 13 + { "FES_NOC", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_LOADING_IN_PROGRESS = 14 + { "FET_LG", -1, -1, -1, 0, 0, + 1, "FED_LDW", 0, 11, + }, + + // MENU_PAGE_DELETING_IN_PROGRESS = 15 + { "FET_DG", -1, -1, -1, 0, 0, + 1, "FEDL_WR", 0, 0, + }, + + // MENU_PAGE_16 = 16 + { "FET_LG", -1, -1, -1, 0, 0, + 1, "FES_LOE", 0, 0, + }, + + // MENU_PAGE_DELETE_FAILED = 17 + { "FET_DG", -1, -1, -1, 0, 0, + 1, "FES_DEE", 0, 0, + 2, "FEC_OKK", 0, 9, + }, + + // MENU_PAGE_DEBUG_MENU = 18 + { "FED_DBG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MEMORY_CARD_1 = 19 + { "FEM_MCM", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MEMORY_CARD_2 = 20 + { "FEM_MC2", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_MAIN = 21 + { "FET_MP", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_SAVE_FAILED_1 = 22 + { "MCDNSP", -1, -1, -1, 0, 0, + 48, "JAILB_U", 0, 0, + }, + + // MENU_PAGE_SAVE_FAILED_2 = 23 + { "MCGNSP", -1, -1, -1, 0, 0, + 48, "JAILB_U", 0, 0, + }, + + // MENU_PAGE_SAVE = 24 + { "FET_SG", -1, -1, -1, 0, 0, + 1, "FES_SCG", 0, 0, + 22, "GMSAVE", 0, 26, + 49, "FESZ_CA", 0, 0, + }, + + // MENU_PAGE_NO_MEMORY_CARD = 25 + { "FES_NOC", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CHOOSE_SAVE_SLOT = 26 + { "FET_SG", -1, -1, -1, 0, 0, + 49, "FESZ_CA", 0, 0, + 2, "FEM_SL1", 2, 27, + 2, "FEM_SL2", 3, 27, + 2, "FEM_SL3", 4, 27, + 2, "FEM_SL4", 5, 27, + 2, "FEM_SL5", 6, 27, + 2, "FEM_SL6", 7, 27, + 2, "FEM_SL7", 8, 27, + 2, "FEM_SL8", 9, 27, + }, + + // MENU_PAGE_SAVE_OVERWRITE_CONFIRM = 27 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FESZ_QO", 0, 0, + 2, "FEM_YES", 0, 43, + 2, "FEM_NO", 0, 26, + }, + + // MENU_PAGE_MULTIPLAYER_MAP = 28 + { "FET_MAP", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_CONNECTION = 29 + { "FET_CON", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_FIND_GAME = 30 + { "FET_FG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_MODE = 31 + { "FET_GT", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_CREATE = 32 + { "FET_HG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_MULTIPLAYER_START = 33 + { "FEN_STA", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_SKIN_SELECT_OLD = 34 + { "FET_PS", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC = 35 + { "FET_CTL", 41, 41, 41, 0, 0, + 99, "FET_CME", 0, 35, + 72, "FET_RDK", 0, 55, + 2, "FET_AMS", 0, 56, + 98, "FET_DEF", 0, 35, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_CONTROLLER_PC_OLD1 = 36 + { "FET_CTL", 35, 35, 35, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC_OLD2 = 37 + { "FET_CTL", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC_OLD3 = 38 + { "FET_CTL", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_PC_OLD4 = 39 + { "FET_CTL", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_CONTROLLER_DEBUG = 40 + { "FEC_DBG", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_OPTIONS = 41 + { "FET_OPT", 0, 0, 0, 1, 4, + 2, "FET_CTL", 0, 35, + 101, "FET_AUD", 0, 5, + 2, "FET_DIS", 0, 6, + 2, "FET_LAN", 0, 7, + 97, "FET_PSU", 0, 54, + 2, "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_EXIT = 42 + { "FET_QG", 0, 0, 0, 2, 5, + 1, "FEQ_SRE", 0, 0, + 93, "FEM_NO", 0, 0, + 82, "FEM_YES", 0, 0, + }, + + // MENU_PAGE_SAVING_IN_PROGRESS = 43 + { "", 26, 26, 26, 0, 0, + 1, "FES_WAR", 0, 0, + }, + + // MENU_PAGE_SAVE_SUCCESSFUL = 44 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FES_SSC", 36, 0, + 49, "FEC_OKK", 0, 26, + }, + + // MENU_PAGE_DELETING = 45 + { "FET_DG", 9, 9, 9, 0, 0, + 1, "FED_DLW", 0, 0, + }, + + // MENU_PAGE_DELETE_SUCCESS = 46 + { "FET_DG", 9, 9, 9, 0, 0, + 1, "DEL_FNM", 0, 0, + 2, "FEC_OKK", 0, 9, + }, + + // MENU_PAGE_SAVE_FAILED = 47 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FEC_SVU", 0, 0, + 2, "FEC_OKK", 0, 26, + }, + + // MENU_PAGE_LOAD_FAILED = 48 + { "FET_SG", 26, 26, 26, 0, 0, + 1, "FEC_SVU", 0, 0, + }, + + // MENU_PAGE_LOAD_FAILED_2 = 49 + { "FET_LG", 26, 26, 26, 0, 0, + 1, "FEC_LUN", 0, 0, + 2, "FEDS_TB", 0, 8, + }, + + // MENU_PAGE_FILTER_GAME = 50 + { "FIL_FLT", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_START_MENU = 51 + { "FEM_MM", -1, -1, -1, 0, 0, + 2, "FEN_STA", 0, 2, + 2, "FET_OPT", 0, 41, + 2, "FEM_QT", 0, 42 + }, + + // MENU_PAGE_PAUSE_MENU = 52 + { "FET_PAU", -1, -1, -1, 0, 0, + 92, "FEM_RES", 0, 0, + 2, "FEN_STA", 0, 2, + 2, "FEP_STA", 0, 1, + 2, "FEP_BRI", 0, 3, + 2, "FET_OPT", 0, 41, + 2, "FEM_QT", 0, 42, + }, + + // MENU_PAGE_CHOOSE_MODE = 53 + { "FEN_STA", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_SKIN_SELECT = 54 + { "FET_PSU", 41, 41, 41, 4, 4, + 35, "FEDS_TB", 0, 21, + }, + + // MENU_PAGE_KEYBOARD_CONTROLS = 55 + { "FET_STI", 35, 35, 35, 1, 1, + 35, "FEDS_TB", 0, 35, + }, + + // MENU_PAGE_MOUSE_CONTROLS = 56 + { "FET_MTI", 35, 35, 35, 2, 2, + 84, "FEC_MSH", 0, 35, + 81, "FEC_IVV", 0, 35, + 102, "FET_MST", 0, 35, + 2 , "FEDS_TB", 0, 0, + }, + + // MENU_PAGE_57 = 57 + { "", -1, -1, -1, 0, 0, + + }, + + // MENU_PAGE_58 = 58 + { "", -1, -1, -1, 0, 0, + + }, +}; + +char *FrontendFilenames[] = { + "fe2_mainpanel_ul", + "fe2_mainpanel_ur", + "fe2_mainpanel_dl", + "fe2_mainpanel_dr", + "fe2_mainpanel_dr2", + "fe2_tabactive", + "fe_iconbrief", + "fe_iconstats", + "fe_iconcontrols", + "fe_iconsave", + "fe_iconaudio", + "fe_icondisplay", + "fe_iconlanguage", + "fe_controller", + "fe_controllersh", + "fe_arrows1", + "fe_arrows2", + "fe_arrows3", + "fe_arrows4", + "fe_radio1", // HEAD_RADIO + "fe_radio2", // DOUBLE_CLEF + "fe_radio5", // JAH_RADIO + "fe_radio7", // RISE_FM + "fe_radio8", // LIPS_106 + "fe_radio3", // GAME_FM + "fe_radio4", // MSX_FM + "fe_radio6", // FLASHBACK + "fe_radio9", // CHATTERBOX +}; + +char *MenuFilenames[] = { + "connection24", + "findgame24", + "hostgame24", + "mainmenu24", + "playersetup24", + "singleplayer24", + "multiplayer24", + "dmalogo128", + "gtaLogo128", + "rockstarLogo128", + "gamespy256", + "mouse", + "mousetimer", + "mp3logo", + "downOFF", + "upOFF", + "downON", + "upON", + "gta3logo256", +}; + +#if 1 +WRAPPER void CMenuManager::BuildStatLine(char *, void *, uint16, void *) { EAXJMP(0x483870); } +#else +void CMenuManager::BuildStatLine(char *, void *, uint16, void *) +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::CentreMousePointer() { EAXJMP(0x48ACE0); } +#else +void CMenuManager::CentreMousePointer() +{ + tagPOINT Point; + + if (SCREENW * 0.5f == 0.0f && 0.0f == SCREENH * 0.5f) { + Point.x = SCREEN_WIDTH / 2; + Point.y = SCREEN_HEIGHT / 2; + ClientToScreen(PSGLOBAL(window), &Point); + SetCursorPos(Point.x, Point.y); + + PSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2; + PSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2; + } +} +#endif + +#if 1 +WRAPPER void CMenuManager::CheckCodesForControls(int, int) { EAXJMP(0x48A950); } +#else +void CMenuManager::CheckCodesForControls() +{ + +} +#endif + +#if 0 +WRAPPER bool CMenuManager::CheckHover(int, int, int, int) { EAXJMP(0x48ACA0); } +#else +bool CMenuManager::CheckHover(int x1, int x2, int y1, int y2) +{ + if (m_nMousePosX > x1 && m_nMousePosX < x2) { + if (m_nMousePosY > y1 && m_nMousePosY < y2) + return true; + } + return false; +} +#endif + +#if 1 +WRAPPER int CMenuManager::CostructStatLine(int) { EAXJMP(0x482800); } +#else +int CMenuManager::CostructStatLine(int) +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::DisplayHelperText() { EAXJMP(0x48B490); } +#else +void CMenuManager::DisplayHelperText() +{ + wchar *str = nullptr; + switch (m_nHelperTextMsgId) { + case 0: + str = TheText.Get("FET_MIG"); + break; + case 1: + str = TheText.Get("FET_APP"); + break; + case 2: + str = TheText.Get("FET_HRD"); + break; + case 3: + str = TheText.Get("FET_RSO"); + break; + case 4: + str = TheText.Get("FET_RSC"); + break; + default: + break; + }; + + CFont::SetAlignment(ALIGN_CENTER); + CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetDropColor(CRGBA(0, 0, 0, DROP_COLOR_A)); + CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_FROM_BOTTOM(120.0f), str); +} +#endif + +#if 0 +WRAPPER float CMenuManager::DisplaySlider(float, float, float, float, float, float) { EAXJMP(0x488420); } +#else +float CMenuManager::DisplaySlider(float x, float y, float leftSize, float rightSize, float rectSize, float progress) +{ + CRGBA color; + float sizeRange; + + float input = 0.0f; + int rects = 16; + for (int i = 0; i < rects; i++) { + input = i * rectSize * 0.0625f + x; + + if (i * 0.0625f + 0.03125f < progress) + color = CRGBA(255, 217, 106, FadeIn(255)); + else + color = CRGBA(185, 120, 0, FadeIn(255)); + + if (leftSize <= rightSize) + sizeRange = rightSize; + else + sizeRange = leftSize; + + float _x = i * rectSize * 0.0625f + x; + float _y = y + sizeRange - ((rects - i) * leftSize + i * rightSize) * 0.0625f; + float _w = SCREEN_SCALE_X(10.0f) + i * rectSize * 0.0625f + x; + float _h = y + sizeRange; + float _s = SCREEN_SCALE_X(2.0f); + CSprite2d::DrawRect(CRect(_x + _s, _y + _s, _w + _s, _h + _s), CRGBA(0, 0, 0, FadeIn(255))); // Shadow + CSprite2d::DrawRect(CRect(i * rectSize * 0.0625f + x, y + sizeRange - ((rects - i) * leftSize + i * rightSize) * 0.0625f, SCREEN_SCALE_X(10.0f) + i * rectSize * 0.0625f + x, y + sizeRange), color); + }; + return input; +} +#endif + +#if 1 +WRAPPER void CMenuManager::DoSettingsBeforeStartingAGame() { EAXJMP(0x48AB40); } +#else +WRAPPER void CMenuManager::DoSettingsBeforeStartingAGame() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::Draw() { EAXJMP(0x47AE00); } +#else +void CMenuManager::Draw() +{ + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetCentreOff(); + CFont::SetJustifyOn(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f)); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + + switch (m_nCurrScreen) { + case MENU_STATS: + PrintStats(); + break; + case MENU_BRIEFS: + PrintBriefs(); + break; + case MENU_CONTROLLER_DEBUG: + DrawControllerScreenExtraText(0, 350, 20); + break; + } + + // Header. + if (aScreens[m_nCurrScreen].m_ScreenName[0]) { + CFont::SetDropShadowPosition(0); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetRightJustifyOn(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetScale(SCREEN_SCALE_X(HEADER_WIDTH), SCREEN_SCALE_Y(HEADER_HEIGHT)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(HEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + } + + // Action text. + wchar *str; + if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == 1) { + switch (m_nCurrScreen) { + case MENU_LOAD_SLOT_CONFIRM: + if (m_bGameNotLoaded) + str = TheText.Get("FES_LCG"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + case MENU_SAVE_OVERWRITE_CONFIRM: + if (Slots[m_nCurrSaveSlot] == 1) + str = TheText.Get("FESZ_QZ"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + case MENU_EXIT: + if (m_bGameNotLoaded) + str = TheText.Get("FEQ_SRW"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + default: + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + }; + + CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetFontStyle(FONT_BANK); + CFont::SetScale(SCREEN_SCALE_X(ACTION_WIDTH), SCREEN_SCALE_Y(ACTION_HEIGHT)); + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_X(ACTION_POS_X), SCREEN_SCALE_Y(ACTION_POS_Y), str); + } + + for (int i = 0; i < 18; ++i) { + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != 1 && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0]) { + wchar *columnToPrint[COLUMNS] = { nullptr, nullptr }; + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot >= MENU_ACTION_SAVE_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot <= MENU_ACTION_SAVE_8) { + columnToPrint[L] = GetNameOfSavedGame(i - 1); + columnToPrint[R] = GetSavedGameDateAndTime(i - 1); + + if (!columnToPrint[L][0]) { + sprintf(gString, "FEM_SL%d", i); + columnToPrint[L] = TheText.Get(gString); + } + } + else { + columnToPrint[L] = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); + } + + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case 3: + break; + case 4: + switch (CPad::GetPad(0)->Mode) { + case 0: + columnToPrint[R] = TheText.Get("FEC_CF1"); + break; + case 1: + columnToPrint[R] = TheText.Get("FEC_CF2"); + break; + case 2: + columnToPrint[R] = TheText.Get("FEC_CF3"); + break; + case 3: + columnToPrint[R] = TheText.Get("FEC_CF4"); + break; + }; + break; + case 5: + break; + case 6: + columnToPrint[R] = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); + break; + case 7: + columnToPrint[R] = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); + break; + case 8: + columnToPrint[R] = TheText.Get(BlurOn ? "FEM_ON" : "FEM_OFF"); + break; + case 9: + columnToPrint[R] = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); + break; + case 10: + columnToPrint[R] = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); + break; + case 16: + sprintf(gString, "FEA_FM%d", m_PrefsRadioStation); + columnToPrint[R] = TheText.Get(gString); + break; + case 28: + columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); + break; + case 29: + columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); + break; + case 81: + columnToPrint[R] = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_ON" : "FEM_OFF"); + break; + case 94: + { + char *res = _psGetVideoModeList()[m_nDisplayVideoMode]; + + if (!res) + res = ""; + + AsciiToUnicode(res, gUString); + columnToPrint[R] = gUString; + } + break; + case 95: + if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) + columnToPrint[R] = TheText.Get("FEA_NAH"); + else { + char *provider = MusicManager.Get3DProviderName(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); + AsciiToUnicode(provider, gUString); + columnToPrint[R] = gUString; + } + break; + case 96: + if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) + columnToPrint[R] = TheText.Get("FEA_NAH"); + else { + switch (m_PrefsSpeakers) { + case 0: + columnToPrint[R] = TheText.Get("FEA_2SP"); + break; + case 1: + columnToPrint[R] = TheText.Get("FEA_EAR"); + break; + case 2: + columnToPrint[R] = TheText.Get("FEA_4SP"); + break; + }; + } + break; + case 99: + switch (m_ControlMethod) { + case 0: + columnToPrint[L] = TheText.Get("FET_SCN"); + break; + case 1: + columnToPrint[L] = TheText.Get("FET_CCN"); + break; + }; + break; + case 100: + columnToPrint[R] = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); + break; + case 102: + columnToPrint[R] = TheText.Get(m_bDisableMouseSteering ? "FEM_ON" : "FEM_OFF"); + break; + }; + + CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetRightJustifyWrap(-SCREEN_WIDTH); + + // Set alignment. + CVector2D vecPositions = { 0.0f, 0.0f }; + float fVerticalSpacing; + float fBarSize; + + int SavePageSlot = + m_nCurrScreen == MENU_CHOOSE_LOAD_SLOT || + m_nCurrScreen == MENU_CHOOSE_DELETE_SLOT || + m_nCurrScreen == MENU_CHOOSE_SAVE_SLOT; + + if (SavePageSlot) { + CFont::SetFontStyle(FONT_BANK); + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.7f)); + fVerticalSpacing = COLUMN_SPACING_MIN; + fBarSize = SELECT_BOX_MIN; + + vecPositions.x = SCREEN_SCALE_X(COLUMN_SAVE_X); + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_SAVE_Y); + } + else { + CFont::SetFontStyle(FONT_HEADING); + + int LeftColumn = + m_nCurrScreen == MENU_SOUND_SETTINGS || + m_nCurrScreen == MENU_GRAPHICS_SETTINGS || + m_nCurrScreen == MENU_MOUSE_CONTROLS; + + if (LeftColumn) { + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.8f)); + fVerticalSpacing = COLUMN_SPACING_MIN; + fBarSize = SELECT_BOX_MIN; + } + else { + CFont::SetAlignment(ALIGN_CENTER); + CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(0.9f)); + fVerticalSpacing = COLUMN_SPACING_MAX; + fBarSize = SELECT_BOX_MAX; + } + + // Set positions. + if (CFont::GetDetails().centre) + vecPositions.x = SCREEN_WIDTH / 2; + else + vecPositions.x = SCREEN_SCALE_X(COLUMN_POS_X); + + switch (m_nCurrScreen) { + case MENU_BRIEFS: + case MENU_STATS: + vecPositions.y = SCREEN_SCALE_FROM_BOTTOM(COLUMN_FEDS); + break; + case MENU_SOUND_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MAX_Y); + + if (i > 5) + vecPositions.y += SCREEN_SCALE_Y(FE_RADIO_ICON_H * 1.16f); + break; + case MENU_LANGUAGE_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MIN_Y); + break; + case MENU_GRAPHICS_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MAX_Y); + break; + case MENU_OPTIONS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + break; + case MENU_PAUSE_MENU: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_PAUSE_Y); + break; + case MENU_NEW_GAME: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + break; + case MENU_START_MENU: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_START_Y); + break; + default: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + break; + }; + } + + if (i > 0) + vecPositions.y += SCREEN_SCALE_Y(fVerticalSpacing * i); + + // Set color and draw selection bar. + if (i == m_nCurrOption && m_nMenuFadeAlpha >= 255) { + CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(11.0f), vecPositions.y - SCREEN_STRETCH_Y(fBarSize * 0.13f), SCREEN_STRETCH_FROM_RIGHT(11.0f), vecPositions.y + SCREEN_STRETCH_Y(fBarSize)), CRGBA(100, 200, 50, 50)); + } + else + CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + + // Draw + if (columnToPrint[L]) + CFont::PrintString(vecPositions.x, vecPositions.y, columnToPrint[L]); + + if (columnToPrint[R]) { + CFont::SetAlignment(ALIGN_RIGHT); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SavePageSlot ? COLUMN_SAVE_X : COLUMN_POS_X), vecPositions.y, columnToPrint[R]); + } + + // Mouse support. + bool bIsMouseInPosition = false; + if (m_nMenuFadeAlpha >= 255) { + CVector2D vecInputSize = { SCREEN_SCALE_X(20.0f), SCREEN_SCALE_FROM_RIGHT(20.0f) }; + if (m_bShowMouse && + ((CheckHover(vecInputSize.x, vecInputSize.y, vecPositions.y, vecPositions.y + SCREEN_STRETCH_Y(20.0f))))) + bIsMouseInPosition = true; + else + bIsMouseInPosition = false; + + if (bIsMouseInPosition) { + if (m_nCurrOption != i) { + m_nCurrOption = i; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + } + + m_nCurrentInput = m_nCurrOption; + + if (CPad::GetPad(0)->NewMouseControllerState.LMB && !CPad::GetPad(0)->OldMouseControllerState.LMB) + m_nHoverOption = IGNORE_OPTION; + else + m_nHoverOption = ACTIVATE_OPTION; + } + } + + // Sliders + // TODO: CheckHover + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case 11: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsBrightness * 0.001953125); + break; + case 12: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), (m_PrefsLOD - 0.80000001) * 1.0000001); + break; + case 13: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsMusicVolume * 0.0078125); + break; + case 14: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsSfxVolume * 0.0078125); + break; + case 84: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), TheCamera.m_fMouseAccelHorzntl * 200.0); + break; + }; + + // Radio icons. + float fIconSpacing = 59.52f; + if (m_nCurrScreen == MENU_SOUND_SETTINGS) { + for (int i = 0; i < POLICE_RADIO; i++) { + + if (i > 5 && i < 7) + fIconSpacing -= 1.5f; + + if (i < USERTRACK) + m_aFrontEndSprites[i + FE_RADIO1].Draw(SCREEN_STRETCH_X(FE_RADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(FE_RADIO_ICON_Y), SCREEN_SCALE_X(FE_RADIO_ICON_W), SCREEN_SCALE_Y(FE_RADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); + if (i > CHATTERBOX) + m_aMenuSprites[MENU_MP3LOGO].Draw(SCREEN_STRETCH_X(FE_RADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(FE_RADIO_ICON_Y), SCREEN_SCALE_X(FE_RADIO_ICON_W), SCREEN_SCALE_Y(FE_RADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, DMAudio.IsMP3RadioChannelAvailable() ? 170 : 25)); + } + } + + // Helpers + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) { + if (m_nDisplayVideoMode == m_nPrefsVideoMode) { + if (m_nHelperTextMsgId == 1) + ResetHelperText(); + } + else + SetHelperText(1); + } + else { + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + m_nDisplayVideoMode = m_nPrefsVideoMode; + SetHelperText(3); + } + } + + switch (m_nCurrScreen) { + case MENU_CONTROLLER_SETTINGS: + case MENU_SOUND_SETTINGS: + case MENU_GRAPHICS_SETTINGS: + case MENU_SKIN_SELECT: + case MENU_CONTROLLER_PC: + case MENU_MOUSE_CONTROLS: + DisplayHelperText(); + break; + }; + } + }; +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawControllerBound(int, int, int, uint8) { EAXJMP(0x489710); } +#else +void CMenuManager::DrawControllerBound(int, int, int, uint8) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawControllerScreenExtraText(int, int, int) { EAXJMP(0x4892F0); } +#else +void CMenuManager::DrawControllerScreenExtraText(int, int, int) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawControllerSetupScreen() { EAXJMP(0x481210); } +#else +void CMenuManager::DrawControllerSetupScreen() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); } +#else +void CMenuManager::DrawFrontEnd() +{ + CFont::SetAlphaFade(255.0f); + + if (!m_nCurrScreen) { + if (m_bGameNotLoaded) + m_nCurrScreen = MENU_START_MENU; + else + m_nCurrScreen = MENU_PAUSE_MENU; + } + + if (!m_nCurrOption && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == 1) + m_nCurrOption = 1; + + CMenuManager::DrawFrontEndNormal(); + CMenuManager::PrintErrorMessage(); +} +#endif + +#if 0 +WRAPPER void CMenuManager::DrawFrontEndNormal(void) { EAXJMP(0x47A5B0); } +#else +void CMenuManager::DrawFrontEndNormal() +{ + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSCLAMP); + + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + + eMenuSprites currentSprite = MENU_CONNECTION; + switch (m_nPrevScreen) { + case MENU_STATS: + case MENU_START_MENU: + case MENU_PAUSE_MENU: + currentSprite = MENU_MAINMENU; + break; + case MENU_NEW_GAME: + case MENU_CHOOSE_LOAD_SLOT: + case MENU_CHOOSE_DELETE_SLOT: + case MENU_NEW_GAME_RELOAD: + case MENU_LOAD_SLOT_CONFIRM: + case MENU_DELETE_SLOT_CONFIRM: + case MENU_EXIT: + currentSprite = MENU_SINGLEPLAYER; + break; + case MENU_MULTIPLAYER_MAIN: + currentSprite = MENU_MULTIPLAYER; + break; + case MENU_MULTIPLAYER_MAP: + case MENU_MULTIPLAYER_FIND_GAME: + case MENU_SKIN_SELECT: + case MENU_KEYBOARD_CONTROLS: + case MENU_MOUSE_CONTROLS: + currentSprite = MENU_FINDGAME; + break; + case MENU_MULTIPLAYER_CONNECTION: + case MENU_MULTIPLAYER_MODE: + currentSprite = MENU_CONNECTION; + break; + case MENU_MULTIPLAYER_CREATE: + currentSprite = MENU_HOSTGAME; + break; + case MENU_SKIN_SELECT_OLD: + case MENU_OPTIONS: + currentSprite = MENU_PLAYERSET; + break; + }; + + //CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(0, 0, 0, 255)); + + uint32 savedShade; + uint32 savedAlpha; + RwRenderStateGet(rwRENDERSTATESHADEMODE, &savedShade); + RwRenderStateSet(rwRENDERSTATESHADEMODE, reinterpret_cast(rwSHADEMODEGOURAUD)); + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &savedAlpha); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(TRUE)); + if (m_nMenuFadeAlpha >= 255) + m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, 255)); + else { + if (m_nMenuFadeAlpha != 255) + m_nMenuFadeAlpha += 0.1f * 255.0f; + + m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); + } + + // GTA LOGO + if (m_nCurrScreen == 51 || m_nCurrScreen == 52) { + if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) + m_aMenuSprites[MENU_GTA3LOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(70.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); + else + m_aMenuSprites[MENU_GTALOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(40.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); + } + RwRenderStateSet(rwRENDERSTATESHADEMODE, reinterpret_cast(savedShade)); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(savedAlpha)); + + switch (m_nCurrScreen) { + case MENU_SKIN_SELECT: + CMenuManager::DrawPlayerSetupScreen(); + break; + case MENU_KEYBOARD_CONTROLS: + CMenuManager::DrawControllerSetupScreen(); + break; + default: + CMenuManager::Draw(); + break; + }; + + CFont::DrawFonts(); + + // Draw mouse + if (m_bShowMouse) + m_aMenuSprites[MENU_MOUSE].Draw(m_nMousePosX, m_nMousePosY, SCREEN_SCALE_X(60.0f), SCREEN_SCALE_Y(60.0f), CRGBA(255, 255, 255, 255)); +} +#endif + +#if 1 +WRAPPER void CMenuManager::DrawPlayerSetupScreen() { EAXJMP(0x47F2B0); } +#else +void CMenuManager::DrawPlayerSetupScreen() +{ + +} +#endif + +#if 0 +WRAPPER int CMenuManager::FadeIn(int alpha) { EAXJMP(0x48AC60); } +#else +int CMenuManager::FadeIn(int alpha) +{ if (m_nCurrScreen == MENU_LOADING_IN_PROGRESS || m_nCurrScreen == MENU_SAVING_IN_PROGRESS || m_nCurrScreen == MENU_DELETING) @@ -47,7 +1187,328 @@ int CMenuManager::FadeIn(int alpha) { return m_nMenuFadeAlpha; } +#endif + +#if 1 +WRAPPER void CMenuManager::FilterOutColorMarkersFromString(uint16, CRGBA &) { EAXJMP(0x4889C0); } +#else +void CMenuManager::FilterOutColorMarkersFromString(uint16, CRGBA &) +{ + +} +#endif + +#if 1 +WRAPPER int CMenuManager::GetStartOptionsCntrlConfigScreens() { EAXJMP(0x489270); } +#else +int CMenuManager::GetStartOptionsCntrlConfigScreens() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::InitialiseChangedLanguageSettings() { EAXJMP(0x47A4D0); } +#else +void CMenuManager::InitialiseChangedLanguageSettings() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::LoadAllTextures() { EAXJMP(0x47A230); } +#else +void CMenuManager::LoadAllTextures() +{ + if (!m_bSpritesLoaded) { + CMenuManager::CentreMousePointer(); + DMAudio.ChangeMusicMode(0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + m_nCurrOption = 0; + m_PrefsRadioStation = DMAudio.GetRadioInCar(); + + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (CMenuManager::m_PrefsRadioStation > USERTRACK) + CMenuManager::m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; + } + else if (CMenuManager::m_PrefsRadioStation > CHATTERBOX) + CMenuManager::m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; + + CFileMgr::SetDir(""); + CTimer::Stop(); + CStreaming::MakeSpaceFor(716800); + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); + + int frontend = CTxdStore::AddTxdSlot("frontend"); + CTxdStore::LoadTxd(frontend, "MODELS/FRONTEND.TXD"); + CTxdStore::AddRef(frontend); + CTxdStore::SetCurrentTxd(frontend); + CStreaming::IHaveUsedStreamingMemory(); + CTimer::Update(); + + debug("LOAD frontend\n"); + for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + }; + + CTxdStore::PopCurrentTxd(); + + int menu = CTxdStore::AddTxdSlot("menu"); + CTxdStore::LoadTxd(menu, "MODELS/MENU.TXD"); + CTxdStore::AddRef(menu); + CTxdStore::SetCurrentTxd(menu); + + debug("LOAD sprite\n"); + for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) { + m_aMenuSprites[i].SetTexture(MenuFilenames[i]); + m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + }; + + CTxdStore::PopCurrentTxd(); + + m_bSpritesLoaded = true; + } +} +#endif + +#if 1 +WRAPPER void CMenuManager::LoadSettings() { EAXJMP(0x488EE0); } +#else +void CMenuManager::LoadSettings() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::MessageScreen(char *) { EAXJMP(0x48B7E0); } +#else +void CMenuManager::MessageScreen(char *) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::PickNewPlayerColour() { EAXJMP(0x488C40); } +#else +void CMenuManager::PickNewPlayerColour() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::PrintBriefs() { EAXJMP(0x484D60); } +#else +void CMenuManager::PrintBriefs() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::PrintErrorMessage() { EAXJMP(0x484F70); } +#else +void CMenuManager::PrintErrorMessage() +{ + if (!CPad::bDisplayNoControllerMessage && !CPad::bObsoleteControllerMessage) + return; + + CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(140.0f), SCREEN_WIDTH - SCREEN_SCALE_X(20.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(140.0f)), CRGBA(64, 16, 16, 224)); + CFont::SetFontStyle(FONT_BANK); + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetCentreOff(); + CFont::SetJustifyOn(); + CFont::SetRightJustifyOff(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetWrapx(SCREEN_WIDTH - 40.0f); + CFont::SetColor(CRGBA(165, 165, 165, 255)); + CFont::SetScale(SCREEN_SCALE_X(0.9f), SCREEN_SCALE_Y(0.9f)); + CFont::PrintString(SCREEN_SCALE_X(40.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(60.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); + CFont::DrawFonts(); +} +#endif + +#if 1 +WRAPPER void CMenuManager::PrintStats() { EAXJMP(0x482100); } +#else +void CMenuManager::PrintStats() +{ + +} +#endif + + +#if 1 +WRAPPER void CMenuManager::Process(void) { EAXJMP(0x485100); } +#else +void CMenuManager::Process(void) +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::ProcessButtonPresses() { EAXJMP(0x4856F0); } +#else +void CMenuManager::ProcessButtonPresses() +{ + +} +#endif + +#if 1 +WRAPPER void CMenuManager::ProcessOnOffMenuOptions() { EAXJMP(0x48AE60); } +#else +void CMenuManager::ProcessOnOffMenuOptions() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::RequestFrontEndShutdown() { EAXJMP(0x488750); } +#else +void CMenuManager::RequestFrontEndShutdown() +{ + m_bShutDownFrontEndRequested = true; + DMAudio.ChangeMusicMode(1); +} +#endif + +#if 0 +WRAPPER void CMenuManager::RequestFrontEndStartUp() { EAXJMP(0x488770); } +#else +void CMenuManager::RequestFrontEndStartUp() +{ + m_bStartUpFrontEndRequested = 1; +} +#endif + +#if 0 +WRAPPER void CMenuManager::ResetHelperText() { EAXJMP(0x48B470); } +#else +void CMenuManager::ResetHelperText() +{ + m_nHelperTextMsgId = 0; + m_nHelperTextAlpha = 300; +} +#endif + +#if 1 +WRAPPER void CMenuManager::SaveLoadFileError_SetUpErrorScreen() { EAXJMP(0x488930); } +#else +void CMenuManager::SaveLoadFileError_SetUpErrorScreen() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::SetHelperText() { EAXJMP(0x48B450); } +#else +void CMenuManager::SetHelperText(int text) +{ + m_nHelperTextMsgId = text; + m_nHelperTextAlpha = 300; +} +#endif + +#if 1 +WRAPPER void CMenuManager::SaveSettings() { EAXJMP(0x488CC0); } +#else +void CMenuManager::SaveSettings() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::ShutdownJustMenu() { EAXJMP(0x488920); } +#else +void CMenuManager::ShutdownJustMenu() +{ + m_bMenuActive = false; + CTimer::EndUserPause(); +} +#endif + +#if 0 +WRAPPER float CMenuManager::StretchX(float) { EAXJMP(0x48ABE0); } +#else +float CMenuManager::StretchX(float x) +{ + if (SCREENW == 640) + return x; + else + return SCREENW * x * 0.0015625f; +} +#endif + +#if 0 +WRAPPER float CMenuManager::StretchY(float) { EAXJMP(0x48AC20); } +#else +float CMenuManager::StretchY(float y) +{ + if (SCREENH == 448) + return y; + else + return SCREENH * y * 0.002232143f; +} +#endif + +#if 0 +WRAPPER void CMenuManager::SwitchMenuOnAndOff() { EAXJMP(0x488790); } +#else +void CMenuManager::SwitchMenuOnAndOff() +{ + +} +#endif + +#if 0 +WRAPPER void CMenuManager::UnloadTextures() { EAXJMP(0x47A440); } +#else +void CMenuManager::UnloadTextures() +{ + if (m_bSpritesLoaded) { + debug("Remove frontend\n"); + for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i) + m_aFrontEndSprites[i].Delete(); + + int frontend = CTxdStore::FindTxdSlot("frontend"); + CTxdStore::RemoveTxdSlot(frontend); + + debug("Remove menu textures\n"); + for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i) + m_aMenuSprites[i].Delete(); + + int menu = CTxdStore::FindTxdSlot("menu"); + CTxdStore::RemoveTxdSlot(menu); + + m_bSpritesLoaded = false; + } +} +#endif + +#if 1 +WRAPPER void CMenuManager::WaitForUserCD(void) { EAXJMP(0x48ADD0); } +#else +void CMenuManager::WaitForUserCD() +{ + +} +#endif STARTPATCHES - InjectHook(0x48AC60, &CMenuManager::FadeIn, PATCH_JUMP); + InjectHook(0x47A230, &CMenuManager::LoadAllTextures, PATCH_JUMP); + InjectHook(0x47A440, &CMenuManager::UnloadTextures, PATCH_JUMP); + + for (int i = 1; i < ARRAY_SIZE(aScreens); i++) + Patch(0x611930 + sizeof(CMenuScreen) * i, aScreens[i]); ENDPATCHES \ No newline at end of file diff --git a/src/Frontend.h b/src/Frontend.h index 2e95d582..2f68fdcd 100644 --- a/src/Frontend.h +++ b/src/Frontend.h @@ -2,6 +2,43 @@ #include "Sprite2d.h" +#define HEADER_POS_X 35.0f +#define HEADER_POS_Y 93.0f +#define HEADER_WIDTH 0.84f +#define HEADER_HEIGHT 1.6f + +#define ACTION_POS_X 20.0f +#define ACTION_POS_Y 37.5f +#define ACTION_WIDTH 0.675f +#define ACTION_HEIGHT 0.81f + +#define COLUMN_POS_X HEADER_POS_X + 16.0f +#define COLUMN_MAX_Y 149.0f +#define COLUMN_MID_Y 100.0f +#define COLUMN_MIN_Y 110.0f +#define COLUMN_PAUSE_Y 25.0f +#define COLUMN_START_Y 9.0f +#define COLUMN_FEDS 139.0f + +#define COLUMN_SAVE_X 121.0f +#define COLUMN_SAVE_Y 111.0f + +#define COLUMN_SPACING_MAX 24.0f +#define COLUMN_SPACING_MIN 20.0f + +#define SELECT_BOX_MAX 20.5f +#define SELECT_BOX_MIN 17.0f + +#define FE_RADIO_ICON_X 31.5f +#define FE_RADIO_ICON_Y 29.5f +#define FE_RADIO_ICON_W 60.0f +#define FE_RADIO_ICON_H 60.0f + +#define DROP_COLOR_A 150 +#define DROP_COLOR_SIZE -1 + +#define SLIDER_X 306.0f + enum { LANGUAGE_AMERICAN, LANGUAGE_FRENCH, @@ -10,6 +47,70 @@ enum { LANGUAGE_SPANISH, }; +enum eFrontendSprites { + FE2_MAINPANEL_UL, + FE2_MAINPANEL_UR, + FE2_MAINPANEL_DL, + FE2_MAINPANEL_DR, + FE2_MAINPANEL_DR2, + FE2_TABACTIVE, + FE_ICONBRIEF, + FE_ICONSTATS, + FE_ICONCONTROLS, + FE_ICONSAVE, + FE_ICONAUDIO, + FE_ICONDISPLAY, + FE_ICONLANGUAGE, + FE_CONTROLLER, + FE_CONTROLLERSH, + FE_ARROWS1, + FE_ARROWS2, + FE_ARROWS3, + FE_ARROWS4, + FE_RADIO1, + FE_RADIO2, + FE_RADIO3, + FE_RADIO4, + FE_RADIO5, + FE_RADIO6, + FE_RADIO7, + FE_RADIO8, + FE_RADIO9, +}; + +enum eMenuSprites { + MENU_CONNECTION, + MENU_FINDGAME, + MENU_HOSTGAME, + MENU_MAINMENU, + MENU_PLAYERSET, + MENU_SINGLEPLAYER, + MENU_MULTIPLAYER, + MENU_DMALOGO, + MENU_GTALOGO, + MENU_RSTARLOGO, + MENU_GAMESPY, + MENU_MOUSE, + MENU_MOUSET, + MENU_MP3LOGO, + MENU_DOWNOFF, + MENU_UPOFF, + MENU_DOWNON, + MENU_UPON, + MENU_GTA3LOGO, +}; + +enum eMenuActions { + MENU_ACTION_SAVE_1 = 1, + MENU_ACTION_SAVE_2, + MENU_ACTION_SAVE_3, + MENU_ACTION_SAVE_4, + MENU_ACTION_SAVE_5, + MENU_ACTION_SAVE_6, + MENU_ACTION_SAVE_7, + MENU_ACTION_SAVE_8, +}; + enum eMenuScreen { MENU_NONE = 0, MENU_STATS = 1, @@ -72,6 +173,11 @@ enum eMenuScreen { MENU_58 = 58, }; +enum eCheckHover { + ACTIVATE_OPTION = 2, + IGNORE_OPTION = 42, +}; + struct tSkinInfo { int field_0; @@ -81,6 +187,20 @@ struct tSkinInfo int field_304; }; +struct CMenuScreen { + char m_ScreenName[8]; + int32 m_PreviousPage[3]; // + int32 m_ParentEntry[2]; + + struct CMenuEntry + { + int32 m_Action; + char m_EntryName[8]; + int32 m_ActionSlot; + int32 m_TargetMenu; + } m_aEntries[18]; +}; + class CMenuManager { public: @@ -136,10 +256,10 @@ public: int m_nHelperTextAlpha; int m_nMouseOldPosX; int m_nMouseOldPosY; - int field_544; + int m_nHoverOption; int m_nCurrScreen; int m_nCurrOption; - int field_550; + int m_nCurrentInput; int m_nPrevScreen; int field_558; int m_nCurrSaveSlot; @@ -165,17 +285,56 @@ public: static int8 &m_bFrontEnd_ReloadObrTxtGxt; static int32 &m_PrefsMusicVolume; static int32 &m_PrefsSfxVolume; + static bool &m_bStartUpFrontEndRequested; + static bool &m_bShutDownFrontEndRequested; static bool &m_PrefsAllowNastyGame; - static bool &m_bStartUpFrontEndRequested; - void Process(void); - void DrawFrontEnd(void); - void UnloadTextures(void); - void LoadAllTextures(void); - void LoadSettings(void); - void WaitForUserCD(void); +private: + enum eColumns { L, R, COLUMNS, }; + +public: + void BuildStatLine(char *, void *, uint16, void *); + static void CentreMousePointer(); + void CheckCodesForControls(int, int); + bool CheckHover(int x1, int x2, int y1, int y2); + int CostructStatLine(int); + void DisplayHelperText(); + float DisplaySlider(float, float, float, float, float, float); + void DoSettingsBeforeStartingAGame(); + void Draw(); + void DrawControllerBound(int, int, int, uint8); + void DrawControllerScreenExtraText(int, int, int); + void DrawControllerSetupScreen(); + void DrawFrontEnd(); + void DrawFrontEndNormal(); + void DrawPlayerSetupScreen(); int FadeIn(int alpha); + void FilterOutColorMarkersFromString(uint16, CRGBA &); + int GetStartOptionsCntrlConfigScreens(); + static void InitialiseChangedLanguageSettings(); + void LoadAllTextures(); + void LoadSettings(); + static void MessageScreen(char *); + static void PickNewPlayerColour(); + void PrintBriefs(); + static void PrintErrorMessage(); + void PrintStats(); + void Process(); + void ProcessButtonPresses(); + void ProcessOnOffMenuOptions(); + static void RequestFrontEndShutdown(); + static void RequestFrontEndStartUp(); + void ResetHelperText(); + void SaveLoadFileError_SetUpErrorScreen(); + void SaveSettings(); + void SetHelperText(int text); + void ShutdownJustMenu(); + static float StretchX(float); + static float StretchY(float ); + void SwitchMenuOnAndOff(); + void UnloadTextures(); + void WaitForUserCD(); }; static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error"); diff --git a/src/PCSave.cpp b/src/PCSave.cpp index 2d49b23f..ae5e43b0 100644 --- a/src/PCSave.cpp +++ b/src/PCSave.cpp @@ -4,4 +4,9 @@ #include "PCSave.h" WRAPPER void C_PcSave::SetSaveDirectory(const char *path) { EAXJMP(0x591EA0); } +WRAPPER wchar *GetNameOfSavedGame(int counter) { EAXJMP(0x591B60); } +WRAPPER wchar *GetSavedGameDateAndTime(int counter) { EAXJMP(0x591B50); } +int *Slots = (int*)0x728040; +int *SlotFileName = (int*)0x6F07C8; +int *SlotSaveDate = (int*)0x72B858; diff --git a/src/PCSave.h b/src/PCSave.h index 324a3421..79202bc9 100644 --- a/src/PCSave.h +++ b/src/PCSave.h @@ -4,4 +4,11 @@ class C_PcSave { public: static void SetSaveDirectory(const char *path); -}; \ No newline at end of file +}; + +extern wchar *GetNameOfSavedGame(int counter); +extern wchar *GetSavedGameDateAndTime(int counter); + +extern int *Slots; +extern int *SlotFileName; +extern int *SlotSaveDate; diff --git a/src/Radar.cpp b/src/Radar.cpp index 90d27af2..3c2f24d3 100644 --- a/src/Radar.cpp +++ b/src/Radar.cpp @@ -14,8 +14,6 @@ #include "World.h" #include "Streaming.h" -WRAPPER void CRadar::Draw3dMarkers() { EAXJMP(0x4A4C70); } - float &CRadar::m_RadarRange = *(float*)0x8E281C; CBlip *CRadar::ms_RadarTrace = (CBlip*)0x6ED5E0; @@ -77,107 +75,69 @@ static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not #define RADAR_MAX_SPEED (0.9f) #if 0 -WRAPPER void CRadar::DrawMap () { EAXJMP(0x4A4200); } +WRAPPER void CRadar::CalculateBlipAlpha(float) { EAXJMP(0x4A4F90); } #else -void CRadar::DrawMap() +int CRadar::CalculateBlipAlpha(float dist) { - if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { - if (FindPlayerVehicle()) { - float speed = FindPlayerSpeed().Magnitude(); - if (speed < RADAR_MIN_SPEED) - m_RadarRange = RADAR_MIN_RANGE; - else if (speed < RADAR_MAX_SPEED) - m_RadarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE; - else - m_RadarRange = RADAR_MAX_RANGE; - } - else - m_RadarRange = RADAR_MIN_RANGE; + if (dist <= 1.0f) + return 255; - vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); - DrawRadarMap(); - } -} -#endif + if (dist <= 5.0f) + return (((1.0f - ((dist * 0.25f) - 0.25f)) * 255.0f) + (((dist * 0.25f) - 0.25f) * 128.0f)); -#if 0 -WRAPPER void CRadar::DrawRadarMask() { EAXJMP(0x4A69C0); } -#else -void CRadar::DrawRadarMask() -{ - CVector2D corners[4] = { - CVector2D(1.0f, -1.0f), - CVector2D(1.0f, 1.0f), - CVector2D(-1.0f, 1.0f), - CVector2D(-1.0, -1.0f) - }; - - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONALWAYS); - - CVector2D out[8]; - CVector2D in; - - // Draw the shape we want to mask out from the radar in four segments - for (int i = 0; i < 4; i++) { - // First point is always the corner itself - in.x = corners[i].x; - in.y = corners[i].y; - TransformRadarPointToScreenSpace(out[0], in); - - // Then generate a quarter of the circle - for (int j = 0; j < 7; j++) { - in.x = corners[i].x * cos(j * (PI / 2.0f / 6.0f)); - in.y = corners[i].y * sin(j * (PI / 2.0f / 6.0f)); - TransformRadarPointToScreenSpace(out[j + 1], in); - }; - - CSprite2d::SetMaskVertices(8, (float *)out); - RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8); - }; - - RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONGREATER); + return 128; } #endif -#if 0 -WRAPPER void CRadar::SetRadarMarkerState(int counter, int flag) { EAXJMP(0x4A5C60); } +#if 1 +WRAPPER void CRadar::ChangeBlipBrightness(int32, int32) { EAXJMP(0x4A57A0); } #else -void CRadar::SetRadarMarkerState(int counter, int flag) +void CRadar::ChangeBlipBrightness(int32 i, int32 bright) { - CEntity *e; - switch (ms_RadarTrace[counter].m_eBlipType) { - case BLIP_CAR: - e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); - break; - case BLIP_CHAR: - e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); - break; - case BLIP_OBJECT: - e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); - break; - default: - return; - } - if (e) - e->bHasBlip = flag; +} +#endif + +#if 1 +WRAPPER void CRadar::ChangeBlipColour(int32) { EAXJMP(0x4A5770); } +#else +void CRadar::ChangeBlipColour(int32 i) +{ + +} +#endif + +#if 1 +WRAPPER void CRadar::ChangeBlipDisplay(int32, int16) { EAXJMP(0x4A5810); } +#else +void CRadar::ChangeBlipDisplay(int32 i, int16 flag) +{ + +} +#endif + +#if 1 +WRAPPER void CRadar::ChangeBlipScale(int32, int16) { EAXJMP(0x4A57E0); } +#else +void CRadar::ChangeBlipScale(int32 i, int16 scale) +{ + +} +#endif + +#if 1 +WRAPPER void CRadar::ClearBlip(int32) { EAXJMP(0x4A5720); } +#else +void CRadar::ClearBlip(int32 i) +{ } #endif #if 0 -WRAPPER void CRadar::ClearBlipForEntity(eBlipType type, int32 id) { EAXJMP(0x4A56C0); } +WRAPPER void CRadar::ClearBlipForEntity(int16, int32) { EAXJMP(0x4A56C0); } #else -void CRadar::ClearBlipForEntity(eBlipType type, int32 id) +void CRadar::ClearBlipForEntity(int16 type, int32 id) { for (int i = 0; i < NUMRADARBLIPS; i++) { if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) { @@ -191,87 +151,6 @@ void CRadar::ClearBlipForEntity(eBlipType type, int32 id) } #endif -bool -IsPointInsideRadar(const CVector2D &point) -{ - if(point.x < -1.0f || point.x > 1.0f) return false; - if(point.y < -1.0f || point.y > 1.0f) return false; - return true; -} - -// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1 -int -LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2) -{ - float d1, d2; - float t; - float x, y; - float shortest = 1.0f; - int edge = -1; - - // clip against left edge, x = -1.0 - d1 = -1.0f - p1.x; - d2 = -1.0f - p2.x; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - y = (p2.y - p1.y)*t + p1.y; - if(y >= -1.0f && y <= 1.0f && t <= shortest){ - out.x = -1.0f; - out.y = y; - edge = 3; - shortest = t; - } - } - - // clip against right edge, x = 1.0 - d1 = p1.x - 1.0f; - d2 = p2.x - 1.0f; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - y = (p2.y - p1.y)*t + p1.y; - if(y >= -1.0f && y <= 1.0f && t <= shortest){ - out.x = 1.0f; - out.y = y; - edge = 1; - shortest = t; - } - } - - // clip against top edge, y = -1.0 - d1 = -1.0f - p1.y; - d2 = -1.0f - p2.y; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - x = (p2.x - p1.x)*t + p1.x; - if(x >= -1.0f && x <= 1.0f && t <= shortest){ - out.y = -1.0f; - out.x = x; - edge = 0; - shortest = t; - } - } - - // clip against bottom edge, y = 1.0 - d1 = p1.y - 1.0f; - d2 = p2.y - 1.0f; - if(d1 * d2 < 0.0f){ - // they are on opposite sides, get point of intersection - t = d1 / (d1 - d2); - x = (p2.x - p1.x)*t + p1.x; - if(x >= -1.0f && x <= 1.0f && t <= shortest){ - out.y = 1.0f; - out.x = x; - edge = 2; - shortest = t; - } - } - - return edge; -} - #if 0 WRAPPER int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *in) { EAXJMP(0x4A64A0); } #else @@ -289,36 +168,37 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) int laste, e, e1, e2;; bool inside[4]; - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) inside[i] = IsPointInsideRadar(rect[i]); laste = -1; n = 0; - for(i = 0; i < 4; i++) - if(inside[i]){ + for (i = 0; i < 4; i++) + if (inside[i]) { // point is inside, just add poly[n++] = rect[i]; - }else{ + } + else { // point is outside but line to this point might be clipped - e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i+4-1) % 4]); - if(e1 != -1){ + e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]); + if (e1 != -1) { laste = e1; n++; } // and line from this point might be clipped as well - e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i+1) % 4]); - if(e2 != -1){ - if(e1 == -1){ + e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]); + if (e2 != -1) { + if (e1 == -1) { // if other line wasn't clipped, i.e. it was complete outside, // we may have to insert another vertex if last clipped line // was on a different edge // find the last intersection if we haven't seen it yet - if(laste == -1) - for(j = 3; j >= i; j--){ + if (laste == -1) + for (j = 3; j >= i; j--) { // game uses an if here for j == 0 - e = LineRadarBoxCollision(tmp, rect[j], rect[(j+4-1) % 4]); - if(e != -1){ + e = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]); + if (e != -1) { laste = e; break; } @@ -327,7 +207,7 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) // insert corners that were skipped tmp = poly[n]; - for(e = laste; e != e2; e = (e+1) % 4) + for (e = laste; e != e2; e = (e + 1) % 4) poly[n++] = corners[e]; poly[n] = tmp; } @@ -335,13 +215,13 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) } } - if(n == 0){ + if (n == 0) { // If no points, either the rectangle is completely outside or completely surrounds the radar // no idea what's going on here... float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x); - if((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f){ + if ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) { m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x); - if((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f){ + if ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) { poly[0] = corners[0]; poly[1] = corners[1]; poly[2] = corners[2]; @@ -355,147 +235,27 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) } #endif -#if 0 -WRAPPER void CRadar::DrawRadarSection(int x, int y) { EAXJMP(0x4A67E0); } -#else -void CRadar::DrawRadarSection(int x, int y) +bool CRadar::DisplayThisBlip(int32 counter) { - int i; - RwTexDictionary *txd; - CVector2D worldPoly[8]; - CVector2D radarCorners[4]; - CVector2D radarPoly[8]; - CVector2D texCoords[8]; - CVector2D screenPoly[8]; - int numVertices; - RwTexture *texture = nil; - - GetTextureCorners(x, y, worldPoly); - ClipRadarTileCoords(x, y); - - assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])); - txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict; - if(txd) - texture = GetFirstTexture(txd); - if(texture == nil) - return; - - for(i = 0; i < 4; i++) - TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]); - - numVertices = ClipRadarPoly(radarPoly, radarCorners); - - // FIX: can return earlier here -// if(numVertices == 0) - if(numVertices < 3) - return; - - for(i = 0; i< numVertices; i++){ - TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]); - TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y); - TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]); + switch (ms_RadarTrace[counter].m_IconID) { + case RADAR_SPRITE_BOMB: + case RADAR_SPRITE_SPRAY: + case RADAR_SPRITE_WEAPON: + return true; + default: + return false; } - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); - CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); - // check done above now -// if(numVertices > 2) - RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices); -} -#endif - -void CRadar::RequestMapSection(int x, int y) -{ - ClipRadarTileCoords(x, y); - CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_DEPENDENCY); } -void CRadar::RemoveMapSection(int x, int y) -{ - if (x >= 0 && x <= 7 && y >= 0 && y <= 7) - CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]); -} - -#if 0 -WRAPPER void CRadar::StreamRadarSections(int x, int y) { EAXJMP(0x4A6100); } +#if 1 +WRAPPER void CRadar::Draw3dMarkers() { EAXJMP(0x4A4C70); } #else -void CRadar::StreamRadarSections(int x, int y) +void CRadar::Draw3dMarkers() { - for (int i = 0; i < RADAR_NUM_TILES; ++i) { - for (int j = 0; j < RADAR_NUM_TILES; ++j) { - if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1)) - RequestMapSection(i, j); - else - RemoveMapSection(i, j); - }; - }; + } #endif -#if 0 -WRAPPER float CRadar::LimitRadarPoint(CVector2D &point) { EAXJMP(0x4A4F30); } -#else -float CRadar::LimitRadarPoint(CVector2D &point) -{ - float dist, invdist; - - dist = point.Magnitude(); - if (dist > 1.0f) { - invdist = 1.0f / dist; - point.x *= invdist; - point.y *= invdist; - } - return dist; -} -#endif - -#if 0 -WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) { EAXJMP(0x4A5530); } -#else -void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y) -{ - out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X); - out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y)); - out.x /= RADAR_TILE_SIZE; - out.y /= RADAR_TILE_SIZE; -} -#endif - -#if 0 -WRAPPER void CRadar::DrawRadarMap() { EAXJMP(0x4A6C20); } -#else -void CRadar::DrawRadarMap() -{ - // Game calculates an unused CRect here - - DrawRadarMask(); - - // top left ist (0, 0) - int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE); - int y = ceilf((RADAR_NUM_TILES-1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE); - StreamRadarSections(x, y); - - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE); - - DrawRadarSection(x - 1, y - 1); - DrawRadarSection(x, y - 1); - DrawRadarSection(x + 1, y - 1); - DrawRadarSection(x - 1, y); - DrawRadarSection(x, y); - DrawRadarSection(x + 1, y); - DrawRadarSection(x - 1, y + 1); - DrawRadarSection(x, y + 1); - DrawRadarSection(x + 1, y + 1); -} -#endif #if 0 WRAPPER void CRadar::DrawBlips() { EAXJMP(0x4A42F0); } @@ -566,12 +326,12 @@ void CRadar::DrawBlips() int a = CalculateBlipAlpha(dist); TransformRadarPointToScreenSpace(out, in); - CRGBA col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); + int32 col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); if (ms_RadarTrace[i].m_IconID) DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, ((col >> 24)), ((col >> 16) & 0xFF), ((col >> 8)), 255); } } } @@ -596,12 +356,12 @@ void CRadar::DrawBlips() int a = CalculateBlipAlpha(dist); TransformRadarPointToScreenSpace(out, in); - CRGBA col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); + int32 col = GetRadarTraceColour(ms_RadarTrace[i].m_nColor, ms_RadarTrace[i].m_bDim); if (ms_RadarTrace[i].m_IconID) DrawRadarSprite(ms_RadarTrace[i].m_IconID, out.x, out.y, a); else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, col.r, col.g, col.b, 255); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[i].m_wScale, ((col >> 24)), ((col >> 16) & 0xFF), ((col >> 8)), 255); } } } @@ -611,183 +371,177 @@ void CRadar::DrawBlips() } #endif -int CRadar::CalculateBlipAlpha(float dist) -{ - if (dist <= 1.0f) - return 255; - - if (dist <= 5.0f) - return (((1.0f - ((dist * 0.25f) - 0.25f)) * 255.0f) + (((dist * 0.25f) - 0.25f) * 128.0f)); - - return 128; -} - -CRGBA CRadar::GetRadarTraceColour(uint32 color, bool bright) -{ - switch (color) { - case 0: - if (bright) - return CRGBA(113, 43, 73, 255); - else - return CRGBA(127, 0, 0, 255); - case 1: - if (bright) - return CRGBA(95, 160, 106, 255); - else - return CRGBA(127, 0, 255, 255); - case 2: - if (bright) - return CRGBA(128, 167, 243, 255); - else - return CRGBA(0, 127, 255, 255); - case 3: - if (bright) - return CRGBA(225, 225, 225, 255); - else - return CRGBA(127, 127, 127, 255); - case 4: - if (bright) - return CRGBA(255, 225, 0, 255); - else - return CRGBA(127, 127, 0, 255); - case 5: - if (bright) - return CRGBA(255, 0, 255, 255); - else - return CRGBA(127, 0, 127, 255); - case 6: - if (bright) - return CRGBA(255, 255, 255, 255); - else - return CRGBA(127, 127, 255, 255); - default: - return CRGBA(0, 0, 0, 255); - } -} - -// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) -void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) -{ - // FIX: game doesn't scale RADAR_LEFT here - out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); - out.y = (1.0f - in.y)*0.5f*SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT); -} #if 0 -WRAPPER void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A50D0); } +WRAPPER void CRadar::DrawMap () { EAXJMP(0x4A4200); } #else -void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) +void CRadar::DrawMap() { - float s, c; - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { - s = 0.0f; - c = 1.0f; - } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { - s = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - } else { - CVector forward; + if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { + if (FindPlayerVehicle()) { + float speed = FindPlayerSpeed().Magnitude(); + if (speed < RADAR_MIN_SPEED) + m_RadarRange = RADAR_MIN_RANGE; + else if (speed < RADAR_MAX_SPEED) + m_RadarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE; + else + m_RadarRange = RADAR_MAX_RANGE; + } + else + m_RadarRange = RADAR_MIN_RANGE; - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); - forward.Normalise(); // a bit useless... - } else - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; - - s = sin(atan2(-forward.x, forward.y)); - c = cos(atan2(-forward.x, forward.y)); + vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); + DrawRadarMap(); } +} +#endif - float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); - float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); +#if 0 +WRAPPER void CRadar::DrawRadarMap() { EAXJMP(0x4A6C20); } +#else +void CRadar::DrawRadarMap() +{ + // Game calculates an unused CRect here - out.x = s * y + c * x; - out.y = c * y - s * x; + DrawRadarMask(); + + // top left ist (0, 0) + int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE); + int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE); + StreamRadarSections(x, y); + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE); + + DrawRadarSection(x - 1, y - 1); + DrawRadarSection(x, y - 1); + DrawRadarSection(x + 1, y - 1); + DrawRadarSection(x - 1, y); + DrawRadarSection(x, y); + DrawRadarSection(x + 1, y); + DrawRadarSection(x - 1, y + 1); + DrawRadarSection(x, y + 1); + DrawRadarSection(x + 1, y + 1); } #endif #if 0 -WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } +WRAPPER void CRadar::DrawRadarMask() { EAXJMP(0x4A69C0); } #else -void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) -{ - float s, c; +void CRadar::DrawRadarMask() +{ + CVector2D corners[4] = { + CVector2D(1.0f, -1.0f), + CVector2D(1.0f, 1.0f), + CVector2D(-1.0f, 1.0f), + CVector2D(-1.0, -1.0f) + }; - s = -sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); - c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONALWAYS); - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { - s = 0.0f; - c = 1.0f; - } else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { - CVector forward; + CVector2D out[8]; + CVector2D in; - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); - forward.Normalise(); // a bit useless... - } else - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + // Draw the shape we want to mask out from the radar in four segments + for (int i = 0; i < 4; i++) { + // First point is always the corner itself + in.x = corners[i].x; + in.y = corners[i].y; + TransformRadarPointToScreenSpace(out[0], in); - s = -sin(atan2(-forward.x, forward.y)); - c = cos(atan2(-forward.x, forward.y)); - } + // Then generate a quarter of the circle + for (int j = 0; j < 7; j++) { + in.x = corners[i].x * cos(j * (PI / 2.0f / 6.0f)); + in.y = corners[i].y * sin(j * (PI / 2.0f / 6.0f)); + TransformRadarPointToScreenSpace(out[j + 1], in); + }; - out.x = s * in.y + c * in.x; - out.y = c * in.y - s * in.x; + CSprite2d::SetMaskVertices(8, (float *)out); + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8); + }; - out = out*m_RadarRange + vec2DRadarOrigin; + RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONGREATER); } #endif #if 0 -WRAPPER void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) { EAXJMP(0x4A5EF0); } +WRAPPER void CRadar::DrawRadarSection(int32, int32) { EAXJMP(0x4A67E0); } #else -void CRadar::DrawRadarSprite(int sprite, float x, float y, int alpha) +void CRadar::DrawRadarSection(int32 x, int32 y) +{ + int i; + RwTexDictionary *txd; + CVector2D worldPoly[8]; + CVector2D radarCorners[4]; + CVector2D radarPoly[8]; + CVector2D texCoords[8]; + CVector2D screenPoly[8]; + int numVertices; + RwTexture *texture = nil; + + GetTextureCorners(x, y, worldPoly); + ClipRadarTileCoords(x, y); + + assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])); + txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict; + if (txd) + texture = GetFirstTexture(txd); + if (texture == nil) + return; + + for (i = 0; i < 4; i++) + TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]); + + numVertices = ClipRadarPoly(radarPoly, radarCorners); + + // FIX: can return earlier here +// if(numVertices == 0) + if (numVertices < 3) + return; + + for (i = 0; i < numVertices; i++) { + TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]); + TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y); + TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]); + } + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); + CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); + // check done above now +// if(numVertices > 2) + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices); +} +#endif + +#if 0 +WRAPPER void CRadar::DrawRadarSprite(int32 sprite, float x, float y, int32 alpha) { EAXJMP(0x4A5EF0); } +#else +void CRadar::DrawRadarSprite(int32 sprite, float x, float y, int32 alpha) { RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); } #endif #if 0 -WRAPPER void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) { EAXJMP(0x4A5870); } +WRAPPER void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) { EAXJMP(0x4A5D10); } #else -void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) -{ - CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha)); - CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); -} -#endif - -#if 0 -WRAPPER void CRadar::ShowRadarMarker(CVector pos, CRGBA color, float radius) { EAXJMP(0x4A59C0); } -#else -void CRadar::ShowRadarMarker(CVector pos, CRGBA color, float radius) { - float f1 = radius * 0.5f; - float f2 = radius * 1.4f; - CVector p1, p2; - - p1 = pos + TheCamera.GetUp()*f1; - p2 = pos + TheCamera.GetUp()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); - - p1 = pos - TheCamera.GetUp()*f1; - p2 = pos - TheCamera.GetUp()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); - - p1 = pos + TheCamera.GetRight()*f1; - p2 = pos + TheCamera.GetRight()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); - - p1 = pos - TheCamera.GetRight()*f1; - p2 = pos - TheCamera.GetRight()*f2; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color.color32, color.color32); -} -#endif - -#if 0 -WRAPPER void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha) { EAXJMP(0x4A5D10); } -#else -void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha) +void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) { CVector curPosn[4]; CVector oldPosn[4]; @@ -809,29 +563,387 @@ void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float curPosn[i].x = x + (oldPosn[i].x - x) * cosf(angle) + (oldPosn[i].y - y) * sinf(angle); curPosn[i].y = y - (oldPosn[i].x - x) * sinf(angle) + (oldPosn[i].y - y) * cosf(angle); - } + } sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha)); } #endif -bool CRadar::DisplayThisBlip(int counter) +#if 1 +WRAPPER int32 CRadar::GetActualBlipArray(int32) { EAXJMP(0x4A41C0); } +#else +int32 CRadar::GetActualBlipArray(int32 i) { - switch (ms_RadarTrace[counter].m_IconID) { - case RADAR_SPRITE_BOMB: - case RADAR_SPRITE_SPRAY: - case RADAR_SPRITE_WEAPON: - return true; + return int32(); +} +#endif + +#if 1 +WRAPPER int32 CRadar::GetNewUniqueBlipIndex(int32) { EAXJMP(0x4A4180); } +#else +int32 CRadar::GetNewUniqueBlipIndex(int32 i) +{ + return int32(); +} +#endif + +#if 0 +WRAPPER int32 CRadar::GetRadarTraceColour(int32 color, bool bright) { EAXJMP(0x4A5BB0); } +#else +int32 CRadar::GetRadarTraceColour(int32 color, bool bright) +{ + int32 c; + switch (color) { + case 0: + if (bright) + c = 0x712B49FF; + else + c = 0x7F0000FF; + break; + case 1: + if (bright) + c = 0x5FA06AFF; + else + c = 0x7F00FF; + break; + case 2: + if (bright) + c = 0x80A7F3FF; + else + c = 0x007FFF; + break; + case 3: + if (bright) + c = 0xE1E1E1FF; + else + c = 0x7F7F7FFF; + break; + case 4: + if (bright) + c = 0xFFFF00FF; + else + c = 0x7F7F00FF; + break; + case 5: + if (bright) + c = 0xFF00FFFF; + else + c = 0x7F007FFF; + break; + case 6: + if (bright) + c = 0xFFFFFF; + else + c = 0x7F7FFF; + break; default: - return false; + c = color; + break; + }; + return c; +} +#endif + +#if 0 +WRAPPER void CRadar::Initialise() { EAXJMP(0x4A3EF0); } +#else +void CRadar::Initialise() +{ + +} +#endif + +#if 0 +WRAPPER float CRadar::LimitRadarPoint(CVector2D &point) { EAXJMP(0x4A4F30); } +#else +float CRadar::LimitRadarPoint(CVector2D &point) +{ + float dist, invdist; + + dist = point.Magnitude(); + if (dist > 1.0f) { + invdist = 1.0f / dist; + point.x *= invdist; + point.y *= invdist; } + return dist; +} +#endif + +#if 0 +WRAPPER void CRadar::LoadAllRadarBlips() { EAXJMP(0x4A6F30); } +#else +void CRadar::LoadAllRadarBlips(int32) +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::LoadTextures() { EAXJMP(0x4A4030); } +#else +void CRadar::LoadTextures() +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::RemoveRadarSections() { EAXJMP(0x00); } +#else +void CRadar::RemoveRadarSections() +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::RemoveMapSection(int32, int32) { EAXJMP(0x00); } +#else +void CRadar::RemoveMapSection(int32 x, int32 y) +{ + if (x >= 0 && x <= 7 && y >= 0 && y <= 7) + CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]); +} +#endif + +#if 0 +WRAPPER void CRadar::RequestMapSection(int32, int32) { EAXJMP(0x00); } +#else +void CRadar::RequestMapSection(int32 x, int32 y) +{ + ClipRadarTileCoords(x, y); + CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY); +} +#endif + +#if 0 +WRAPPER void CRadar::SaveAllRadarBlips(int32) { EAXJMP(0x00); } +#else +void CRadar::SaveAllRadarBlips(int32) +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::SetBlipSprite(int32, int32) { EAXJMP(0x00); } +#else +void CRadar::SetBlipSprite(int32 i, int32 icon) +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::SetCoordBlip(int32, CVector, int32) { EAXJMP(0x00); } +#else +int CRadar::SetCoordBlip(int32 type, CVector pos, int32 flag) +{ + return 0; +} +#endif + +#if 0 +WRAPPER void CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { EAXJMP(0x00); } +#else +int CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) +{ + return 0; +} +#endif + +#if 0 +WRAPPER void CRadar::SetRadarMarkerState(int32, int32) { EAXJMP(0x4A5C60); } +#else +void CRadar::SetRadarMarkerState(int32 counter, int32 flag) +{ + CEntity *e; + switch (ms_RadarTrace[counter].m_eBlipType) { + case BLIP_CAR: + e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); + break; + case BLIP_CHAR: + e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); + break; + case BLIP_OBJECT: + e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle); + break; + default: + return; + } + + if (e) + e->bHasBlip = flag; +} +#endif + +#if 0 +WRAPPER void CRadar::ShowRadarMarker(CVector pos, int16 color, float radius) { EAXJMP(0x4A59C0); } +#else +void CRadar::ShowRadarMarker(CVector pos, int16 color, float radius) { + float f1 = radius * 0.5f; + float f2 = radius * 1.4f; + CVector p1, p2; + + p1 = pos + TheCamera.GetUp()*f1; + p2 = pos + TheCamera.GetUp()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); + + p1 = pos - TheCamera.GetUp()*f1; + p2 = pos - TheCamera.GetUp()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); + + p1 = pos + TheCamera.GetRight()*f1; + p2 = pos + TheCamera.GetRight()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); + + p1 = pos - TheCamera.GetRight()*f1; + p2 = pos - TheCamera.GetRight()*f2; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color); +} +#endif + +#if 0 +WRAPPER void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) { EAXJMP(0x4A5870); } +#else +void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha) +{ + CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha)); + CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); +} +#endif + +#if 0 +WRAPPER void CRadar::Shutdown() { EAXJMP(0x4A3F60); } +#else +void CRadar::Shutdown() +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::StreamRadarSections() { EAXJMP(0x4A6B60); } +#else +void CRadar::StreamRadarSections(CVector posn) +{ + +} +#endif + +#if 0 +WRAPPER void CRadar::StreamRadarSections(int32 x, int32 y) { EAXJMP(0x4A6100); } +#else +void CRadar::StreamRadarSections(int32 x, int32 y) +{ + for (int i = 0; i < RADAR_NUM_TILES; ++i) { + for (int j = 0; j < RADAR_NUM_TILES; ++j) { + if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1)) + RequestMapSection(i, j); + else + RemoveMapSection(i, j); + }; + }; +} +#endif + +#if 0 +WRAPPER void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y) { EAXJMP(0x4A5530); } +#else +void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y) +{ + out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X); + out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y)); + out.x /= RADAR_TILE_SIZE; + out.y /= RADAR_TILE_SIZE; +} +#endif + +#if 0 +WRAPPER void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A5300); } +#else +void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) +{ + float s, c; + + s = -sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { + s = 0.0f; + c = 1.0f; + } + else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { + CVector forward; + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); + forward.Normalise(); // a bit useless... + } + else + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + + s = -sin(atan2(-forward.x, forward.y)); + c = cos(atan2(-forward.x, forward.y)); + } + + out.x = s * in.y + c * in.x; + out.y = c * in.y - s * in.x; + + out = out * m_RadarRange + vec2DRadarOrigin; +} +#endif + +// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) +void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) +{ + // FIX: game doesn't scale RADAR_LEFT here + out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); + out.y = (1.0f - in.y)*0.5f*SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT); } #if 0 -WRAPPER void CRadar::GetTextureCorners(int x, int y, CVector2D *out) { EAXJMP(0x4A61C0); }; +WRAPPER void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) { EAXJMP(0x4A50D0); } +#else +void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) +{ + float s, c; + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) { + s = 0.0f; + c = 1.0f; + } + else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { + s = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y)); + } + else { + CVector forward; + + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON) { + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); + forward.Normalise(); // a bit useless... + } + else + forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; + + s = sin(atan2(-forward.x, forward.y)); + c = cos(atan2(-forward.x, forward.y)); + } + + float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange); + float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange); + + out.x = s * y + c * x; + out.y = c * y - s * x; +} +#endif + +#if 0 +WRAPPER void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out) { EAXJMP(0x4A61C0); }; #else // Transform from section indices to world coordinates -void CRadar::GetTextureCorners(int x, int y, CVector2D *out) +void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out) { x = x - RADAR_NUM_TILES/2; y = -(y - RADAR_NUM_TILES/2); @@ -854,7 +966,10 @@ void CRadar::GetTextureCorners(int x, int y, CVector2D *out) } #endif -void CRadar::ClipRadarTileCoords(int &x, int &y) +#if 0 +WRAPPER void CRadar::ClipRadarTileCoords(int32 &, int32 &) { EAXJMP(0x00); }; +#else +void CRadar::ClipRadarTileCoords(int32 &x, int32 &y) { if (x < 0) x = 0; @@ -865,6 +980,95 @@ void CRadar::ClipRadarTileCoords(int &x, int &y) if (y > RADAR_NUM_TILES-1) y = RADAR_NUM_TILES-1; } +#endif + + +#if 0 +WRAPPER bool CRadar::IsPointInsideRadar(const CVector2D &) { EAXJMP(0x4A6160); } +#else +bool CRadar::IsPointInsideRadar(const CVector2D &point) +{ + if (point.x < -1.0f || point.x > 1.0f) return false; + if (point.y < -1.0f || point.y > 1.0f) return false; + return true; +} +#endif + +// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1 +#if 0 +WRAPPER int CRadar::LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &) { EAXJMP(0x4A6250); } +#else +int CRadar::LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2) +{ + float d1, d2; + float t; + float x, y; + float shortest = 1.0f; + int edge = -1; + + // clip against left edge, x = -1.0 + d1 = -1.0f - p1.x; + d2 = -1.0f - p2.x; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + y = (p2.y - p1.y)*t + p1.y; + if (y >= -1.0f && y <= 1.0f && t <= shortest) { + out.x = -1.0f; + out.y = y; + edge = 3; + shortest = t; + } + } + + // clip against right edge, x = 1.0 + d1 = p1.x - 1.0f; + d2 = p2.x - 1.0f; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + y = (p2.y - p1.y)*t + p1.y; + if (y >= -1.0f && y <= 1.0f && t <= shortest) { + out.x = 1.0f; + out.y = y; + edge = 1; + shortest = t; + } + } + + // clip against top edge, y = -1.0 + d1 = -1.0f - p1.y; + d2 = -1.0f - p2.y; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + x = (p2.x - p1.x)*t + p1.x; + if (x >= -1.0f && x <= 1.0f && t <= shortest) { + out.y = -1.0f; + out.x = x; + edge = 0; + shortest = t; + } + } + + // clip against bottom edge, y = 1.0 + d1 = p1.y - 1.0f; + d2 = p2.y - 1.0f; + if (d1 * d2 < 0.0f) { + // they are on opposite sides, get point of intersection + t = d1 / (d1 - d2); + x = (p2.x - p1.x)*t + p1.x; + if (x >= -1.0f && x <= 1.0f && t <= shortest) { + out.y = 1.0f; + out.x = x; + edge = 2; + shortest = t; + } + } + + return edge; +} +#endif STARTPATCHES // InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP); @@ -892,12 +1096,12 @@ STARTPATCHES // InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP); InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP); InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP); - InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP); + //InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP); InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP); InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP); InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP); // InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP); - InjectHook(0x4A6100, CRadar::StreamRadarSections, PATCH_JUMP); +// InjectHook(0x4A6100, CRadar::StreamRadarSections, PATCH_JUMP); InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP); InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP); InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP); @@ -907,6 +1111,6 @@ STARTPATCHES // InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP); InjectHook(0x4A61C0, CRadar::GetTextureCorners, PATCH_JUMP); - InjectHook(0x4A6160, IsPointInsideRadar, PATCH_JUMP); - InjectHook(0x4A6250, LineRadarBoxCollision, PATCH_JUMP); + InjectHook(0x4A6160, CRadar::IsPointInsideRadar, PATCH_JUMP); + InjectHook(0x4A6250, CRadar::LineRadarBoxCollision, PATCH_JUMP); ENDPATCHES diff --git a/src/Radar.h b/src/Radar.h index dec07667..5943498f 100644 --- a/src/Radar.h +++ b/src/Radar.h @@ -96,32 +96,51 @@ public: static CSprite2d *RadarSprites[21]; public: - static void ClearBlipForEntity(eBlipType type, int32 id); - static void Draw3dMarkers(); - static void DrawMap(); - static void StreamRadarSections(int x, int y); - static int ClipRadarPoly(CVector2D *out, const CVector2D *in); - static void DrawRadarSection(int x, int y); - static void RequestMapSection(int x, int y); - static void RemoveMapSection(int x, int y); - static void DrawBlips(); static int CalculateBlipAlpha(float dist); - static CRGBA GetRadarTraceColour(uint32 color, bool bright); + static void ChangeBlipBrightness(int32 i, int32 bright); + static void ChangeBlipColour(int32 i); + static void ChangeBlipDisplay(int32 i, int16 flag); + static void ChangeBlipScale(int32 i, int16 scale); + static void ClearBlip(int32 i); + static void ClearBlipForEntity(int16 type, int32 id); + static int ClipRadarPoly(CVector2D *out, const CVector2D *in); + static bool DisplayThisBlip(int32 i); + static void Draw3dMarkers(); + static void DrawBlips(); + static void DrawMap(); static void DrawRadarMap(); - static void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int alpha); - static float LimitRadarPoint(CVector2D &point); - static void DrawRadarSprite(int sprite, float x, float y, int alpha); - static void ShowRadarMarker(CVector pos, CRGBA color, float radius); - static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha); static void DrawRadarMask(); - static void SetRadarMarkerState(int counter, int flag); - static bool DisplayThisBlip(int counter); - static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int x, int y); + static void DrawRadarSection(int32 x, int32 y); + static void DrawRadarSprite(int32 sprite, float x, float y, int32 alpha); + static void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha); + static int32 GetActualBlipArray(int32 i); + static int32 GetNewUniqueBlipIndex(int32 i); + static int32 GetRadarTraceColour(int32 color, bool bright); + static void Initialise(); + static float LimitRadarPoint(CVector2D &point); + static void LoadAllRadarBlips(int32); + static void LoadTextures(); + static void RemoveRadarSections(); + static void RemoveMapSection(int32 x, int32 y); + static void RequestMapSection(int32 x, int32 y); + static void SaveAllRadarBlips(int32); + static void SetBlipSprite(int32 i, int32 icon); + static int SetCoordBlip(int32 type, CVector pos, int32 flag); + static int SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag); + static void SetRadarMarkerState(int32 i, int32 flag); + static void ShowRadarMarker(CVector pos, int16 color, float radius); + static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha); + static void Shutdown(); + static void StreamRadarSections(CVector posn); + static void StreamRadarSections(int32 x, int32 y); + static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y); static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in); static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in); static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in); // no in CRadar in the game: - static void GetTextureCorners(int x, int y, CVector2D *out); - static void ClipRadarTileCoords(int &x, int &y); + static void GetTextureCorners(int32 x, int32 y, CVector2D *out); + static void ClipRadarTileCoords(int32 &x, int32 &y); + static bool IsPointInsideRadar(const CVector2D &); + static int LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &); }; diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index c320ea94..b96bee01 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -18,3 +18,5 @@ WRAPPER void cDMAudio::ChangeMusicMode(uint8 mode) { EAXJMP(0x57CCF0); } WRAPPER void cDMAudio::PlayFrontEndSound(uint32, uint32) { EAXJMP(0x57CC20); } WRAPPER void cDMAudio::PlayOneShot(int, uint16, float) { EAXJMP(0x57C840); } +WRAPPER int cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); } +WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); } \ No newline at end of file diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 3ebeaad8..ad67cf13 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -189,5 +189,7 @@ public: void ChangeMusicMode(uint8 mode); void PlayFrontEndSound(uint32, uint32); void PlayOneShot(int, uint16, float); + int GetRadioInCar(); + uint8 IsMP3RadioChannelAvailable(); }; extern cDMAudio &DMAudio; diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index f9c02739..6f2d3d86 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -16,6 +16,8 @@ int32 &gNumRetunePresses = *(int32*)0x650B80; wchar *pCurrentStation = (wchar*)0x650B9C; uint8 &cDisplay = *(uint8*)0x650BA1; +WRAPPER char* cMusicManager::Get3DProviderName(char) { EAXJMP(0x57A8C0); } + bool cMusicManager::PlayerInCar() { if (!FindPlayerVehicle()) diff --git a/src/audio/MusicManager.h b/src/audio/MusicManager.h index 644c3df3..dcb34daf 100644 --- a/src/audio/MusicManager.h +++ b/src/audio/MusicManager.h @@ -264,6 +264,7 @@ public: uint8 field_2395; public: + char *Get3DProviderName(char); bool PlayerInCar(); void DisplayRadioStationName(); }; diff --git a/src/config.h b/src/config.h index 7c228e60..1cd532ee 100644 --- a/src/config.h +++ b/src/config.h @@ -69,3 +69,4 @@ enum Config { //#define NO_CDCHECK #define NO_MOVIES //#define USE_MY_DOCUMENTS +#define NASTY_GAME \ No newline at end of file diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 70a15476..d601db8e 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -68,7 +68,7 @@ WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); } #else void CGarages::PrintMessages() { - if (CTimer::GetTimeInMilliseconds() > CGarages::MessageStartTime && CTimer::GetTimeInMilliseconds() < CGarages::MessageEndTime) { + if (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) { CFont::SetScale(SCREEN_SCALE_X(1.2f / 2), SCREEN_SCALE_Y(1.5f / 2)); // BUG: game doesn't use macro here. CFont::SetPropOn(); CFont::SetJustifyOff(); @@ -77,16 +77,16 @@ void CGarages::PrintMessages() CFont::SetCentreOn(); CFont::SetFontStyle(FONT_BANK); - if (CGarages::MessageNumberInString2 < 0) { - if (CGarages::MessageNumberInString < 0) { + if (MessageNumberInString2 < 0) { + if (MessageNumberInString < 0) { CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString((SCREEN_WIDTH/ 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(CGarages::MessageIDString)); + CFont::PrintString((SCREEN_WIDTH/ 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(MessageIDString)); CFont::SetColor(CRGBA(89, 115, 150, 255)); - CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(CGarages::MessageIDString)); + CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(MessageIDString)); } else { - CMessages::InsertNumberInString(TheText.Get(CGarages::MessageIDString), CGarages::MessageNumberInString, -1, -1, -1, -1, -1, gUString); + CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f + 2.0 - 40.0f), gUString); @@ -96,7 +96,7 @@ void CGarages::PrintMessages() } } else { - CMessages::InsertNumberInString(TheText.Get(CGarages::MessageIDString), CGarages::MessageNumberInString2, -1, -1, -1, -1, -1, gUString); + CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f + 2.0 - 40.0f), gUString); diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index a8d87302..a3d8ff1b 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -11,6 +11,8 @@ #include "CutsceneMgr.h" #include "Timer.h" #include "Weather.h" +#include "Font.h" +#include "Text.h" uint8 &CReplay::Mode = *(uint8*)0x95CD5B; CAddressInReplayBuffer &CReplay::Record = *(CAddressInReplayBuffer*)0x942F7C; @@ -223,7 +225,6 @@ WRAPPER bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buf WRAPPER void CReplay::FinishPlayback(void) { EAXJMP(0x595B20); } WRAPPER void CReplay::Shutdown(void) { EAXJMP(0x595BD0); } WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); } -WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } WRAPPER void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) { EAXJMP(0x596030); } WRAPPER void CReplay::StoreStuffInMem(void) { EAXJMP(0x5961F0); } WRAPPER void CReplay::RestoreStuffFromMem(void) { EAXJMP(0x5966E0); } @@ -238,6 +239,23 @@ WRAPPER bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); } WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); } +#if 0 +WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } +#else +void CReplay::Display() +{ + if (CReplay::IsPlayingBack() && CTimer::GetFrameCounter() + 1 & 0x20) { + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetAlignment(ALIGN_LEFT); + CFont::SetColor(CRGBA(255, 255, 200, 200)); + CFont::SetFontStyle(FONT_BANK); + CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY")); + } +} +#endif + STARTPATCHES InjectHook(0x592FC0, PrintElementsInPtrList, PATCH_JUMP); InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP); diff --git a/src/main.cpp b/src/main.cpp index f9ede02d..0dadc131 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,6 +85,7 @@ extern void (*DebugMenuProcess)(void); extern void (*DebugMenuRender)(void); void DebugMenuInit(void); +void PrintGameVersion(); RwRGBA gColourTop; @@ -154,6 +155,7 @@ Idle(void *arg) } RenderMenus(); + PrintGameVersion(); DoFade(); Render2dStuffAfterFade(); CCredits::Render(); @@ -186,6 +188,7 @@ FrontendIdle(void) DefinedState(); RenderMenus(); + PrintGameVersion(); DoFade(); Render2dStuffAfterFade(); CFont::DrawFonts(); @@ -772,6 +775,25 @@ AppEventHandler(RsEvent event, void *param) } } +void PrintGameVersion() +{ + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.5f)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_BANK); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetDropShadowPosition(0); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(CRGBA(235, 170, 50, 255)); + + strcpy(gString, "RE3"); + AsciiToUnicode(gString, gUString); + CFont::PrintString(SCREEN_SCALE_X(10.5f), SCREEN_SCALE_Y(8.0f), gUString); +} + STARTPATCHES InjectHook(0x48E480, Idle, PATCH_JUMP); InjectHook(0x48E700, FrontendIdle, PATCH_JUMP); diff --git a/src/render/Font.h b/src/render/Font.h index 2e698533..11c0f8ec 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -33,6 +33,12 @@ enum { FONT_HEADING, }; +enum { + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT, +}; + class CFont { static CFontDetails &Details; @@ -56,6 +62,7 @@ public: static void DrawFonts(void); static uint16 character_code(uint8 c); + static CFontDetails GetDetails() { return Details; } static void SetScale(float x, float y) { Details.scaleX = x; Details.scaleY = y; } static void SetSlantRefPoint(float x, float y) { Details.slantRefX = x; Details.slantRefY = y; } static void SetSlant(float s) { Details.slant = s; } @@ -86,6 +93,23 @@ public: static void SetCentreOff(void) { Details.centre = false; } + static void SetAlignment(uint8 alignment) { + if (alignment == ALIGN_LEFT) { + CFont::Details.justify = true; + CFont::Details.centre = false; + CFont::Details.rightJustify = false; + } + else if (alignment == ALIGN_CENTER) { + CFont::Details.justify = false; + CFont::Details.centre = true; + CFont::Details.rightJustify = false; + } + else if (alignment == ALIGN_RIGHT) { + CFont::Details.justify = false; + CFont::Details.centre = false; + CFont::Details.rightJustify = true; + } + } static void SetWrapx(float x) { Details.wrapX = x; } static void SetCentreSize(float s) { Details.centreSize = s; } static void SetBackgroundOn(void) { Details.background = true; } diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index a17d5c2c..9243bc3a 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -53,9 +53,9 @@ wchar *CHud::m_PagerMessage = (wchar*)0x878840; bool &CHud::m_Wants_To_Draw_Hud = *(bool*)0x95CD89; bool &CHud::m_Wants_To_Draw_3dMarkers = *(bool*)0x95CD62; wchar(*CHud::m_BigMessage)[128] = (wchar(*)[128])0x664CE0; -float *CHud::BigMessageInUse = (float*)0x862140; -float *CHud::BigMessageAlpha = (float*)0x862108; -float *CHud::BigMessageX = (float*)0x773248; +float CHud::BigMessageInUse[6]; +float CHud::BigMessageAlpha[6]; +float CHud::BigMessageX[6]; float &CHud::OddJob2OffTimer = *(float*)0x942FA0; int8 &CHud::CounterOnLastFrame = *(int8*)0x95CD67; @@ -231,8 +231,8 @@ void CHud::Draw() CRect rect; float fWidescreenOffset[2] = { 0.0f, 0.0f }; - - if (CMenuManager::m_PrefsUseWideScreen) { + + if (FrontEndMenuManager.m_PrefsUseWideScreen) { fWidescreenOffset[0] = 0.0f; fWidescreenOffset[1] = SCREEN_SCALE_Y(18.0f); } @@ -362,25 +362,32 @@ void CHud::Draw() /* DrawAmmo */ + int16 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition; int32 AmmoInClip = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoInClip; int32 TotalAmmo = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal; + int32 Ammo, Clip; - if (AmmoInClip <= 1 || AmmoInClip >= 1000) { + if (AmmoAmount <= 1 || AmmoAmount >= 1000) sprintf(sTemp, "%d", TotalAmmo); - } else { if (WeaponType == WEAPONTYPE_FLAMETHROWER) { - int tot_min_clip_div_10 = (TotalAmmo - AmmoInClip) / 10; - if (tot_min_clip_div_10 > 9999) - tot_min_clip_div_10 = 9999; + Clip = AmmoInClip / 10; - sprintf(sTemp, "%d-%d", tot_min_clip_div_10, AmmoInClip / 10); + if ((TotalAmmo - AmmoInClip) / 10 <= 9999) + Ammo = (TotalAmmo - AmmoInClip) / 10; + else + Ammo = 9999; } else { - if (AmmoInClip > 9999) - AmmoInClip = 9999; - sprintf(sTemp, "%d-%d", (TotalAmmo - AmmoInClip), AmmoInClip); + Clip = AmmoInClip; + + if (TotalAmmo - AmmoInClip > 9999) + Ammo = 9999; + else + Ammo = TotalAmmo - AmmoInClip; } + + sprintf(sTemp, "%d-%d", Ammo, Clip); } AsciiToUnicode(sTemp, sPrint); @@ -580,7 +587,7 @@ void CHud::Draw() CFont::SetPropOn(); CFont::SetBackgroundOff(); - if (CMenuManager::m_PrefsLanguage == 4) + if (FrontEndMenuManager.m_PrefsLanguage == 4) CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.8f), SCREEN_SCALE_Y(1.2f)); else CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); @@ -676,7 +683,7 @@ void CHud::Draw() CFont::SetPropOn(); CFont::SetBackgroundOff(); - if (CMenuManager::m_PrefsLanguage != 3 && CMenuManager::m_PrefsLanguage != 4) + if (FrontEndMenuManager.m_PrefsLanguage != 3 && FrontEndMenuManager.m_PrefsLanguage != 4) CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); else CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f)); @@ -976,7 +983,7 @@ void CHud::Draw() DrawBigMessage */ // MissionCompleteFailedText - if (CHud::m_BigMessage[0][0]) { + if (m_BigMessage[0][0]) { if (BigMessageInUse[0] != 0.0f) { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); @@ -1251,7 +1258,7 @@ void CHud::DrawAfterFade() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - if (CGame::frenchGame || CMenuManager::m_PrefsLanguage == 4) + if (CGame::frenchGame || FrontEndMenuManager.m_PrefsLanguage == 4) CFont::SetScale(SCREEN_SCALE_X(0.884f), SCREEN_SCALE_Y(1.36f)); else CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); diff --git a/src/render/Hud.h b/src/render/Hud.h index 8f4b6fb6..260e5312 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -62,9 +62,9 @@ public: static bool &m_Wants_To_Draw_Hud; static bool &m_Wants_To_Draw_3dMarkers; static wchar(*m_BigMessage)[128]; - static float *BigMessageInUse; - static float *BigMessageAlpha; - static float *BigMessageX; + static float BigMessageInUse[6]; + static float BigMessageAlpha[6]; + static float BigMessageX[6]; static float &OddJob2OffTimer; static int8 &CounterOnLastFrame; static float &OddJob2XOffset; diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index a8abe1dd..814cac84 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -633,8 +633,10 @@ psInitialise(void) C_PcSave::SetSaveDirectory(_psGetUserFilesFolder()); - InitialiseLanguage(); - +#ifndef NASTY_GAME + InitialiseLanguage(); +#endif + FrontEndMenuManager.LoadSettings(); gGameState = GS_START_UP; diff --git a/src/skel/win/win.h b/src/skel/win/win.h index d3b0169f..371b9e44 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -78,6 +78,8 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode); void CenterVideo(void); void CloseClip(void); +RwChar **_psGetVideoModeList(); + #ifdef __cplusplus } #endif /* __cplusplus */ From 628b9a8b54766dac8b6d75c71159d68820978b92 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 25 Jun 2019 08:19:47 +0200 Subject: [PATCH 08/17] Frontend clean up --- src/Frontend.cpp | 145 +++++++++++++++++++++++------------------------ src/Frontend.h | 116 ++++++++++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 76 deletions(-) diff --git a/src/Frontend.cpp b/src/Frontend.cpp index 9b0e185d..01acb740 100644 --- a/src/Frontend.cpp +++ b/src/Frontend.cpp @@ -48,6 +48,7 @@ int32 &CMenuManager::m_PrefsSfxVolume = *(int32*)0x5F2E48; CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8; +// TODO: replace magic numbers with enums const CMenuScreen aScreens[] = { // MENU_PAGE_NONE = 0 { "", -1, -1, 1, 0, 0, }, @@ -459,25 +460,26 @@ char *FrontendFilenames[] = { }; char *MenuFilenames[] = { - "connection24", - "findgame24", - "hostgame24", - "mainmenu24", - "playersetup24", - "singleplayer24", - "multiplayer24", - "dmalogo128", - "gtaLogo128", - "rockstarLogo128", - "gamespy256", - "mouse", - "mousetimer", - "mp3logo", - "downOFF", - "upOFF", - "downON", - "upON", - "gta3logo256", + "connection24", "", + "findgame24", "", + "hostgame24", "", + "mainmenu24", "", + "Playersetup24", "", + "singleplayer24", "", + "multiplayer24", "", + "dmalogo128", "dmalogo128m", + "gtaLogo128", "gtaLogo128", + "rockstarLogo128", "rockstarlogo128m", + "gamespy256", "gamespy256a", + "mouse", "mousetimera", + "mousetimer", "mousetimera", + "mp3logo", "mp3logoA", + "downOFF", "buttonA", + "downON", "buttonA", + "upOFF", "buttonA", + "upON", "buttonA", + "gta3logo256", "gta3logo256m", + nil, nil }; #if 1 @@ -522,11 +524,8 @@ WRAPPER bool CMenuManager::CheckHover(int, int, int, int) { EAXJMP(0x48ACA0); } #else bool CMenuManager::CheckHover(int x1, int x2, int y1, int y2) { - if (m_nMousePosX > x1 && m_nMousePosX < x2) { - if (m_nMousePosY > y1 && m_nMousePosY < y2) - return true; - } - return false; + return m_nMousePosX > x1 && m_nMousePosX < x2 && + m_nMousePosY > y1 && m_nMousePosY < y2; } #endif @@ -544,7 +543,7 @@ WRAPPER void CMenuManager::DisplayHelperText() { EAXJMP(0x48B490); } #else void CMenuManager::DisplayHelperText() { - wchar *str = nullptr; + wchar *str = nil; switch (m_nHelperTextMsgId) { case 0: str = TheText.Get("FET_MIG"); @@ -585,27 +584,23 @@ float CMenuManager::DisplaySlider(float x, float y, float leftSize, float rightS float sizeRange; float input = 0.0f; - int rects = 16; - for (int i = 0; i < rects; i++) { - input = i * rectSize * 0.0625f + x; + for (int i = 0; i < 16; i++) { + input = i * rectSize/16.0f + x; - if (i * 0.0625f + 0.03125f < progress) + if (i/16.0f + 1/32.0f < progress) color = CRGBA(255, 217, 106, FadeIn(255)); else color = CRGBA(185, 120, 0, FadeIn(255)); - if (leftSize <= rightSize) - sizeRange = rightSize; - else - sizeRange = leftSize; + sizeRange = max(leftSize, rightSize); - float _x = i * rectSize * 0.0625f + x; - float _y = y + sizeRange - ((rects - i) * leftSize + i * rightSize) * 0.0625f; - float _w = SCREEN_SCALE_X(10.0f) + i * rectSize * 0.0625f + x; + float _x = i * rectSize/16.0f + x; + float _y = y + sizeRange - ((16 - i) * leftSize + i * rightSize)/16.0f; + float _w = SCREEN_SCALE_X(10.0f) + i * rectSize/16.0f + x; float _h = y + sizeRange; float _s = SCREEN_SCALE_X(2.0f); CSprite2d::DrawRect(CRect(_x + _s, _y + _s, _w + _s, _h + _s), CRGBA(0, 0, 0, FadeIn(255))); // Shadow - CSprite2d::DrawRect(CRect(i * rectSize * 0.0625f + x, y + sizeRange - ((rects - i) * leftSize + i * rightSize) * 0.0625f, SCREEN_SCALE_X(10.0f) + i * rectSize * 0.0625f + x, y + sizeRange), color); + CSprite2d::DrawRect(CRect(i * rectSize/16.0f + x, y + sizeRange - ((16 - i) * leftSize + i * rightSize)/16.0f, SCREEN_SCALE_X(10.0f) + i * rectSize/16.0f + x, y + sizeRange), color); }; return input; } @@ -693,8 +688,8 @@ void CMenuManager::Draw() } for (int i = 0; i < 18; ++i) { - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != 1 && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0]) { - wchar *columnToPrint[COLUMNS] = { nullptr, nullptr }; + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0]) { + wchar *columnToPrint[COLUMNS] = { nil, nil }; if (aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot >= MENU_ACTION_SAVE_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot <= MENU_ACTION_SAVE_8) { columnToPrint[L] = GetNameOfSavedGame(i - 1); @@ -710,9 +705,9 @@ void CMenuManager::Draw() } switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case 3: + case MENUACTION_CTRLVIBRATION: break; - case 4: + case MENUACTION_CTRLCONFIG: switch (CPad::GetPad(0)->Mode) { case 0: columnToPrint[R] = TheText.Get("FEC_CF1"); @@ -728,37 +723,37 @@ void CMenuManager::Draw() break; }; break; - case 5: + case MENUACTION_CTRLDISPLAY: break; - case 6: + case MENUACTION_FRAMESYNC: columnToPrint[R] = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); break; - case 7: + case MENUACTION_FRAMELIMIT: columnToPrint[R] = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); break; - case 8: + case MENUACTION_TRAILS: columnToPrint[R] = TheText.Get(BlurOn ? "FEM_ON" : "FEM_OFF"); break; - case 9: + case MENUACTION_SUBTITLES: columnToPrint[R] = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); break; - case 10: + case MENUACTION_WIDESCREEN: columnToPrint[R] = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); break; - case 16: + case MENUACTION_RADIO: sprintf(gString, "FEA_FM%d", m_PrefsRadioStation); columnToPrint[R] = TheText.Get(gString); break; - case 28: + case MENUACTION_SETDBGFLAG: columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); break; - case 29: + case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); break; - case 81: + case MENUACTION_INVVERT: columnToPrint[R] = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_ON" : "FEM_OFF"); break; - case 94: + case MENUACTION_SCREENRES: { char *res = _psGetVideoModeList()[m_nDisplayVideoMode]; @@ -769,7 +764,7 @@ void CMenuManager::Draw() columnToPrint[R] = gUString; } break; - case 95: + case MENUACTION_AUDIOHW: if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) columnToPrint[R] = TheText.Get("FEA_NAH"); else { @@ -778,7 +773,7 @@ void CMenuManager::Draw() columnToPrint[R] = gUString; } break; - case 96: + case MENUACTION_SPEAKERCONF: if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) columnToPrint[R] = TheText.Get("FEA_NAH"); else { @@ -795,7 +790,7 @@ void CMenuManager::Draw() }; } break; - case 99: + case MENUACTION_CTRLMETHOD: switch (m_ControlMethod) { case 0: columnToPrint[L] = TheText.Get("FET_SCN"); @@ -805,10 +800,10 @@ void CMenuManager::Draw() break; }; break; - case 100: + case MENUACTION_DYNAMICACOUSTIC: columnToPrint[R] = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); break; - case 102: + case MENUACTION_MOUSESTEER: columnToPrint[R] = TheText.Get(m_bDisableMouseSteering ? "FEM_ON" : "FEM_OFF"); break; }; @@ -949,20 +944,20 @@ void CMenuManager::Draw() // Sliders // TODO: CheckHover switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case 11: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsBrightness * 0.001953125); + case MENUACTION_BRIGHTNESS: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsBrightness/512.0f); break; - case 12: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), (m_PrefsLOD - 0.80000001) * 1.0000001); + case MENUACTION_DRAWDIST: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), (m_PrefsLOD - 0.8f) * 1.0f); break; - case 13: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsMusicVolume * 0.0078125); + case MENUACTION_MUSICVOLUME: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsMusicVolume/128.0f); break; - case 14: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsSfxVolume * 0.0078125); + case MENUACTION_SFXVOLUME: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsSfxVolume/128.0f); break; - case 84: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), TheCamera.m_fMouseAccelHorzntl * 200.0); + case MENUACTION_MOUSESENS: + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), TheCamera.m_fMouseAccelHorzntl * 200.0f); break; }; @@ -971,7 +966,7 @@ void CMenuManager::Draw() if (m_nCurrScreen == MENU_SOUND_SETTINGS) { for (int i = 0; i < POLICE_RADIO; i++) { - if (i > 5 && i < 7) + if (i == MSX_FM) fIconSpacing -= 1.5f; if (i < USERTRACK) @@ -1046,14 +1041,14 @@ void CMenuManager::DrawFrontEnd() { CFont::SetAlphaFade(255.0f); - if (!m_nCurrScreen) { + if (m_nCurrScreen == MENU_NONE) { if (m_bGameNotLoaded) m_nCurrScreen = MENU_START_MENU; else m_nCurrScreen = MENU_PAUSE_MENU; } - if (!m_nCurrOption && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == 1) + if (!m_nCurrOption && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) m_nCurrOption = 1; CMenuManager::DrawFrontEndNormal(); @@ -1077,7 +1072,7 @@ void CMenuManager::DrawFrontEndNormal() CSprite2d::InitPerFrame(); CFont::InitPerFrame(); - eMenuSprites currentSprite = MENU_CONNECTION; + eMenuSprites currentSprite = MENU_MAINMENU; switch (m_nPrevScreen) { case MENU_STATS: case MENU_START_MENU: @@ -1134,7 +1129,7 @@ void CMenuManager::DrawFrontEndNormal() } // GTA LOGO - if (m_nCurrScreen == 51 || m_nCurrScreen == 52) { + if (m_nCurrScreen == MENU_START_MENU || m_nCurrScreen == MENU_PAUSE_MENU) { if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) m_aMenuSprites[MENU_GTA3LOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(70.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); else @@ -1262,8 +1257,8 @@ void CMenuManager::LoadAllTextures() CTxdStore::SetCurrentTxd(menu); debug("LOAD sprite\n"); - for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) { - m_aMenuSprites[i].SetTexture(MenuFilenames[i]); + for (int i = 0; i < ARRAY_SIZE(MenuFilenames)/2; i++) { + m_aMenuSprites[i].SetTexture(MenuFilenames[i*2], MenuFilenames[i*2+1]); m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); }; @@ -1485,7 +1480,7 @@ void CMenuManager::UnloadTextures() CTxdStore::RemoveTxdSlot(frontend); debug("Remove menu textures\n"); - for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i) + for (int i = 0; i < ARRAY_SIZE(MenuFilenames)/2; ++i) m_aMenuSprites[i].Delete(); int menu = CTxdStore::FindTxdSlot("menu"); diff --git a/src/Frontend.h b/src/Frontend.h index 2f68fdcd..7245477f 100644 --- a/src/Frontend.h +++ b/src/Frontend.h @@ -94,8 +94,8 @@ enum eMenuSprites { MENU_MOUSET, MENU_MP3LOGO, MENU_DOWNOFF, - MENU_UPOFF, MENU_DOWNON, + MENU_UPOFF, MENU_UPON, MENU_GTA3LOGO, }; @@ -173,6 +173,120 @@ enum eMenuScreen { MENU_58 = 58, }; +enum eMenuAction { + MENUACTION_NOTHING, + MENUACTION_LABEL, + MENUACTION_CHANGEMENU, + MENUACTION_CTRLVIBRATION, + MENUACTION_CTRLCONFIG, + MENUACTION_CTRLDISPLAY, + MENUACTION_FRAMESYNC, + MENUACTION_FRAMELIMIT, + MENUACTION_TRAILS, + MENUACTION_SUBTITLES, + MENUACTION_WIDESCREEN, + MENUACTION_BRIGHTNESS, + MENUACTION_DRAWDIST, + MENUACTION_MUSICVOLUME, + MENUACTION_SFXVOLUME, + MENUACTION_UNK15, + MENUACTION_RADIO, + MENUACTION_LANG_ENG, + MENUACTION_LANG_FRE, + MENUACTION_LANG_GER, + MENUACTION_LANG_IT, + MENUACTION_LANG_SPA, + MENUACTION_UPDATESAVE, + MENUACTION_CHECKSAVE, + MENUACTION_UNK24, + MENUACTION_NEWGAME, + MENUACTION_RELOADIDE, + MENUACTION_RELOADIPL, + MENUACTION_SETDBGFLAG, + MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, + MENUACTION_PEDROADGROUPS, + MENUACTION_CARROADGROUPS, + MENUACTION_COLLISIONPOLYS, + MENUACTION_REGMEMCARD1, + MENUACTION_TESTFORMATMEMCARD1, + MENUACTION_TESTUNFORMATMEMCARD1, + MENUACTION_CREATEROOTDIR, + MENUACTION_CREATELOADICONS, + MENUACTION_FILLWITHGUFF, + MENUACTION_SAVEONLYTHEGAME, + MENUACTION_SAVEGAME, + MENUACTION_SAVEGAMEUNDERGTA, + MENUACTION_CREATECOPYPROTECTED, + MENUACTION_TESTSAVE, + MENUACTION_TESTLOAD, + MENUACTION_TESTDELETE, + MENUACTION_PARSEHEAP, + MENUACTION_SHOWCULL, + MENUACTION_MEMCARDSAVECONFIRM, + MENUACTION_UPDATEMEMCARDSAVE, + MENUACTION_UNK50, + MENUACTION_DEBUGSTREAM, + MENUACTION_MPMAP_LIBERTY, + MENUACTION_MPMAP_REDLIGHT, + MENUACTION_MPMAP_CHINATOWN, + MENUACTION_MPMAP_TOWER, + MENUACTION_MPMAP_SEWER, + MENUACTION_MPMAP_INDUSTPARK, + MENUACTION_MPMAP_DOCKS, + MENUACTION_MPMAP_STAUNTON, + MENUACTION_MPMAP_DEATHMATCH1, + MENUACTION_MPMAP_DEATHMATCH2, + MENUACTION_MPMAP_TEAMDEATH1, + MENUACTION_MPMAP_TEAMDEATH2, + MENUACTION_MPMAP_STASH, + MENUACTION_MPMAP_CAPTURE, + MENUACTION_MPMAP_RATRACE, + MENUACTION_MPMAP_DOMINATION, + MENUACTION_STARTMP, + MENUACTION_UNK69, + MENUACTION_UNK70, + MENUACTION_FINDMP, + MENUACTION_REDEFCTRL, + MENUACTION_UNK73, + MENUACTION_INITMP, + MENUACTION_MP_PLAYERCOLOR, + MENUACTION_MP_PLAYERNAME, + MENUACTION_MP_GAMENAME, + MENUACTION_GETKEY, + MENUACTION_SHOWHEADBOB, + MENUACTION_UNK80, + MENUACTION_INVVERT, + MENUACTION_CANCLEGAME, + MENUACTION_MP_PLAYERNUMBER, + MENUACTION_MOUSESENS, + MENUACTION_CHECKMPGAMES, + MENUACTION_CHECKMPPING, + MENUACTION_MP_SERVER, + MENUACTION_MP_MAP, + MENUACTION_MP_GAMETYPE, + MENUACTION_MP_LAN, + MENUACTION_MP_INTERNET, + MENUACTION_RESUME, + MENUACTION_DONTCANCLE, + MENUACTION_SCREENRES, + MENUACTION_AUDIOHW, + MENUACTION_SPEAKERCONF, + MENUACTION_PLAYERSETUP, + MENUACTION_RESTOREDEF, + MENUACTION_CTRLMETHOD, + MENUACTION_DYNAMICACOUSTIC, + MENUACTION_LOADRADIO, + MENUACTION_MOUSESTEER, + MENUACTION_UNK103, + MENUACTION_UNK104, + MENUACTION_UNK105, + MENUACTION_UNK106, + MENUACTION_UNK107, + MENUACTION_UNK108, + MENUACTION_UNK109, + MENUACTION_UNK110, +}; + enum eCheckHover { ACTIVATE_OPTION = 2, IGNORE_OPTION = 42, From e9fd2a93e0769179458af949dd64d6f53035c98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Tue, 25 Jun 2019 11:40:54 +0300 Subject: [PATCH 09/17] Fix car animations & M16 bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: eray orçunus --- src/entities/Ped.cpp | 98 ++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 1b3e8a0e..7a48cdc4 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -623,20 +623,22 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) case ANIM_WEAPON_START_THROW: if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer()) { - attackAssoc->blendDelta = -1000.0; + attackAssoc->blendDelta = -1000.0f; newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROWU); } else { - attackAssoc->blendDelta = -1000.0; + attackAssoc->blendDelta = -1000.0f; newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROW); } - newAnim->SetFinishCallback(CPed::FinishedAttackCB, ped); - break; + newAnim->SetFinishCallback(FinishedAttackCB, ped); + return; + case ANIM_FIGHT_PPUNCH: - attackAssoc->blendDelta = -8.0; + attackAssoc->blendDelta = -8.0f; attackAssoc->flags |= ASSOC_DELETEFADEDOUT; ped->ClearAttack(); - break; + return; + case ANIM_WEAPON_THROW: case ANIM_WEAPON_THROWU: if (ped->GetWeapon()->m_nAmmoTotal > 0) { @@ -645,12 +647,11 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) } break; default: - if (!ped->m_ped_flagA4) - ped->ClearAttack(); - break; } - } else if (!ped->m_ped_flagA4) + } + + if (!ped->m_ped_flagA4) ped->ClearAttack(); } @@ -759,15 +760,15 @@ CPed::Attack(void) // If reloading just began, start the animation if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS && !reloadAnimAssoc) { CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, reloadAnim, 8.0f); - CPed::ClearLookFlag(); - CPed::ClearAimFlag(); + ClearLookFlag(); + ClearAimFlag(); m_ped_flagA4 = false; bIsPointingGunAt = false; m_lastHitTime = CTimer::GetTimeInMilliseconds(); return; } } else { - if (weaponAnimAssoc->animId <= ANIM_WEAPON_BAT_V) { + if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) { DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f); } else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) { DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_PUNCH_ATTACK, 0.0f); @@ -834,24 +835,22 @@ CPed::Attack(void) CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); } } else { - CPed::ClearAimFlag(); + ClearAimFlag(); // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading) - if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < ourWeapon->m_fAnimLoopEnd) { - if (ourWeaponType < WEAPONTYPE_SNIPERRIFLE) { - switch (ourWeaponType) { - case WEAPONTYPE_UZI: - DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); - break; - case WEAPONTYPE_AK47: - DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); - break; - case WEAPONTYPE_M16: - DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); - break; - default: - break; - } + if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) { + switch (ourWeaponType) { + case WEAPONTYPE_UZI: + DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_AK47: + DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_M16: + DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); + break; + default: + break; } } @@ -929,9 +928,7 @@ CPed::SelectGunIfArmed(void) if (m_weapons[i].m_nAmmoTotal > 0) { weaponType = m_weapons[i].m_eWeaponType; - // I GOT THAT WRONG AND SHOULD BE FIXED!! (but I don't know how) Original code was; - // if ( v3 == 2 || (unsigned int)(v3 - 3) <= 2 || (unsigned int)(v3 - 7) <= 1 || v3 == 9 ) - if (weaponType < WEAPONTYPE_MOLOTOV) { + if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) { SetCurrentWeapon(weaponType); return true; } @@ -1240,7 +1237,7 @@ CPed::GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, GetLocalPositionToOpenCarDoor(output, veh, enterType, offset); doorPos = Multiply3x3(vehMat, *output); - *output = *vehMat.GetPosition() + doorPos; + *output = *veh->GetPosition() + doorPos; } void @@ -1275,9 +1272,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) m_ped_flagC8 = 1; } if (phase == LINE_UP_TO_CAR_START) { - m_vecMoveSpeed.x = 0.0; - m_vecMoveSpeed.y = 0.0; - m_vecMoveSpeed.z = 0.0; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); } CVehicle *veh = m_pMyVehicle; @@ -1361,7 +1356,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) CVector neededPos; if (phase == LINE_UP_TO_CAR_2) { - neededPos = GetPosition(); + neededPos = *GetPosition(); } else { GetPositionToOpenCarDoor(&neededPos, veh, m_vehEnterType, seatPosMult); } @@ -1378,12 +1373,16 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) { neededPos.z = GetPosition().z; + // Getting out if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) { - float vehNextZSpeed = m_vecMoveSpeed.z - 0.008f * CTimer::GetTimeStep(); + float pedZSpeedOnExit = m_vecMoveSpeed.z - 0.008f * CTimer::GetTimeStep(); - if (neededPos.z + vehNextZSpeed > autoZPos.z) { - m_vecMoveSpeed.z = vehNextZSpeed; - veh->ApplyMoveSpeed(); + // If we're not in ground at next step, apply animation + if (neededPos.z + pedZSpeedOnExit > autoZPos.z) { + m_vecMoveSpeed.z = pedZSpeedOnExit; + ApplyMoveSpeed(); + // Removing below line breaks the animation + neededPos.z = GetPosition().z; } else { neededPos.z = autoZPos.z; m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); @@ -1396,8 +1395,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) { neededPos.z = autoZPos.z; m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - } else if (neededPos.z < currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) { - + } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) { adjustedTimeStep = min(m_pVehicleAnim->timeStep, 0.1f); // Smoothly change ped position @@ -1411,9 +1409,8 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (neededPos.z > currentZ) { if (m_pVehicleAnim && - (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim <= ANIM_CAR_GETIN_LOW_LHS + (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) { - adjustedTimeStep = min(m_pVehicleAnim->timeStep, 0.1f); // Smoothly change ped position @@ -1426,15 +1423,15 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } // I hope - bool notInWater = false; + bool stillGettingInOut = false; if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) - notInWater = veh->m_vehType != VEHICLE_TYPE_BOAT || m_ped_flagG10; + stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || m_ped_flagG10; - if (!notInWater) { + if (!stillGettingInOut) { m_fRotationCur = m_fRotationDest; } else { float limitedAngle = CGeneral::LimitRadianAngle(m_fRotationDest); - float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds()) / 500.0f; // * 0.0016666667f; + float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds()) * 0.0016666667f; // changing this to 0.002 causes wrong rotation m_vecOffsetSeek.z = 0.0; if (timeUntilStateChange <= 0.0f) { @@ -1453,6 +1450,8 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } if (seatPosMult > 0.2f || vehIsUpsideDown) { + GetPosition() = neededPos; + GetMatrix().SetRotate(0.0f, 0.0f, m_fRotationCur); // It will be all 0 after rotate. @@ -1465,6 +1464,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) *vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, output); GetMatrix() = vehDoorMat; } + } STARTPATCHES From 28509e216f64a75e77ccb5d040d79001802ec594 Mon Sep 17 00:00:00 2001 From: _AG Date: Tue, 25 Jun 2019 14:25:39 +0200 Subject: [PATCH 10/17] Better organization for Frontend.cpp --- src/Frontend.cpp | 740 +++++++++++-------------------------- src/Frontend.h | 305 ++++++++------- src/MenuScreens.h | 380 +++++++++++++++++++ src/Timer.h | 3 +- src/audio/AudioManager.cpp | 2 + src/audio/AudioManager.h | 1 + src/audio/DMAudio.cpp | 6 +- src/audio/DMAudio.h | 3 + 8 files changed, 772 insertions(+), 668 deletions(-) create mode 100644 src/MenuScreens.h diff --git a/src/Frontend.cpp b/src/Frontend.cpp index 01acb740..1cac3d2b 100644 --- a/src/Frontend.cpp +++ b/src/Frontend.cpp @@ -19,6 +19,7 @@ #include "PCSave.h" #include "Script.h" #include "Camera.h" +#include "MenuScreens.h" int32 &CMenuManager::OS_Language = *(int32*)0x5F2F78; int8 &CMenuManager::m_PrefsUseVibration = *(int8*)0x95CD92; @@ -48,386 +49,6 @@ int32 &CMenuManager::m_PrefsSfxVolume = *(int32*)0x5F2E48; CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8; -// TODO: replace magic numbers with enums -const CMenuScreen aScreens[] = { - // MENU_PAGE_NONE = 0 - { "", -1, -1, 1, 0, 0, }, - - // MENU_PAGE_STATS = 1 - { "FET_STA", 0, 0, 0, 5, 2, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_NEW_GAME = 2 - { "FET_SGA", 0, 0, 0, 0, 1, - 2, "FES_SNG", 0, 10, - 22, "GMLOAD", 0, 8, - 2, "FES_DGA", 0, 9, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_BRIEFS = 3 - { "FET_BRE", 0, 0, 0, 6, 3, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_CONTROLLER_SETTINGS = 4 - { "FET_CON", 41, 41, 41, 0, 0, - - }, - - // MENU_PAGE_SOUND_SETTINGS = 5 - { "FET_AUD", 41, 41, 41, 1, 1, - 13, "FEA_MUS", 0, 5, - 14, "FEA_SFX", 0, 5, - 95, "FEA_3DH", 0, 5, - 96, "FEA_SPK", 0, 5, - 100, "FET_DAM", 0, 5, - 16, "FEA_RSS", 0, 5, - 98, "FET_DEF", 0, 5, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_GRAPHICS_SETTINGS = 6 - { "FET_DIS", 41, 41, 41, 2, 2, - 11, "FED_BRI", 0, 6, - 12, "FEM_LOD", 0, 6, - 6, "FEM_VSC", 0, 6, - 7, "FEM_FRM", 0, 6, - 8, "FED_TRA", 0, 6, - 9, "FED_SUB", 0, 6, - 10, "FED_WIS", 0, 6, - 94, "FED_RES", 0, 6, - 98, "FET_DEF", 0, 6, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_LANGUAGE_SETTINGS = 7 - { "FET_LAN", 41, 41, 41, 3, 3, - 17, "FEL_ENG", 0, 7, - 18, "FEL_FRE", 0, 7, - 19, "FEL_GER", 0, 7, - 20, "FEL_ITA", 0, 7, - 21, "FEL_SPA", 0, 7, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_CHOOSE_LOAD_SLOT = 8 - { "FET_LG", 2, 2, 2, 1, 1, - 2, "FESZ_CA", 0, 2, - 23, "FEM_SL1", 2, 11, - 23, "FEM_SL2", 3, 11, - 23, "FEM_SL3", 4, 11, - 23, "FEM_SL4", 5, 11, - 23, "FEM_SL5", 6, 11, - 23, "FEM_SL6", 7, 11, - 23, "FEM_SL7", 8, 11, - 23, "FEM_SL8", 9, 11, - }, - - // MENU_PAGE_CHOOSE_DELETE_SLOT = 9 - { "FET_DG", 2, 2, 2, 2, 2, - 2, "FESZ_CA", 0, 2, - 2, "FEM_SL1", 2, 12, - 2, "FEM_SL2", 3, 12, - 2, "FEM_SL3", 4, 12, - 2, "FEM_SL4", 5, 12, - 2, "FEM_SL5", 6, 12, - 2, "FEM_SL6", 7, 12, - 2, "FEM_SL7", 8, 12, - 2, "FEM_SL8", 9, 12, - }, - - // MENU_PAGE_NEW_GAME_RELOAD = 10 - { "FET_NG", 2, 2, 2, 0, 0, - 1, "FESZ_QR", 0, 0, - 2, "FEM_NO", 0, 2, - 25, "FEM_YES", 0, 10, - }, - - // MENU_PAGE_LOAD_SLOT_CONFIRM = 11 - { "FET_LG", 8, 8, 8, 0, 0, - 1, "FESZ_QL", 0, 0, - 2, "FEM_NO", 0, 8, - 2, "FEM_YES", 0, 14, - }, - - // MENU_PAGE_DELETE_SLOT_CONFIRM = 12 - { "FET_DG", 9, 9, 9, 0, 0, - 1, "FESZ_QD", 0, 0, - 2, "FEM_NO", 0, 9, - 2, "FEM_YES", 0, 45, - }, - - // MENU_PAGE_13 = 13 - { "FES_NOC", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_LOADING_IN_PROGRESS = 14 - { "FET_LG", -1, -1, -1, 0, 0, - 1, "FED_LDW", 0, 11, - }, - - // MENU_PAGE_DELETING_IN_PROGRESS = 15 - { "FET_DG", -1, -1, -1, 0, 0, - 1, "FEDL_WR", 0, 0, - }, - - // MENU_PAGE_16 = 16 - { "FET_LG", -1, -1, -1, 0, 0, - 1, "FES_LOE", 0, 0, - }, - - // MENU_PAGE_DELETE_FAILED = 17 - { "FET_DG", -1, -1, -1, 0, 0, - 1, "FES_DEE", 0, 0, - 2, "FEC_OKK", 0, 9, - }, - - // MENU_PAGE_DEBUG_MENU = 18 - { "FED_DBG", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MEMORY_CARD_1 = 19 - { "FEM_MCM", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MEMORY_CARD_2 = 20 - { "FEM_MC2", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MULTIPLAYER_MAIN = 21 - { "FET_MP", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_SAVE_FAILED_1 = 22 - { "MCDNSP", -1, -1, -1, 0, 0, - 48, "JAILB_U", 0, 0, - }, - - // MENU_PAGE_SAVE_FAILED_2 = 23 - { "MCGNSP", -1, -1, -1, 0, 0, - 48, "JAILB_U", 0, 0, - }, - - // MENU_PAGE_SAVE = 24 - { "FET_SG", -1, -1, -1, 0, 0, - 1, "FES_SCG", 0, 0, - 22, "GMSAVE", 0, 26, - 49, "FESZ_CA", 0, 0, - }, - - // MENU_PAGE_NO_MEMORY_CARD = 25 - { "FES_NOC", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_CHOOSE_SAVE_SLOT = 26 - { "FET_SG", -1, -1, -1, 0, 0, - 49, "FESZ_CA", 0, 0, - 2, "FEM_SL1", 2, 27, - 2, "FEM_SL2", 3, 27, - 2, "FEM_SL3", 4, 27, - 2, "FEM_SL4", 5, 27, - 2, "FEM_SL5", 6, 27, - 2, "FEM_SL6", 7, 27, - 2, "FEM_SL7", 8, 27, - 2, "FEM_SL8", 9, 27, - }, - - // MENU_PAGE_SAVE_OVERWRITE_CONFIRM = 27 - { "FET_SG", 26, 26, 26, 0, 0, - 1, "FESZ_QO", 0, 0, - 2, "FEM_YES", 0, 43, - 2, "FEM_NO", 0, 26, - }, - - // MENU_PAGE_MULTIPLAYER_MAP = 28 - { "FET_MAP", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MULTIPLAYER_CONNECTION = 29 - { "FET_CON", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MULTIPLAYER_FIND_GAME = 30 - { "FET_FG", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MULTIPLAYER_MODE = 31 - { "FET_GT", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MULTIPLAYER_CREATE = 32 - { "FET_HG", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_MULTIPLAYER_START = 33 - { "FEN_STA", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_SKIN_SELECT_OLD = 34 - { "FET_PS", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_CONTROLLER_PC = 35 - { "FET_CTL", 41, 41, 41, 0, 0, - 99, "FET_CME", 0, 35, - 72, "FET_RDK", 0, 55, - 2, "FET_AMS", 0, 56, - 98, "FET_DEF", 0, 35, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_CONTROLLER_PC_OLD1 = 36 - { "FET_CTL", 35, 35, 35, 0, 0, - - }, - - // MENU_PAGE_CONTROLLER_PC_OLD2 = 37 - { "FET_CTL", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_CONTROLLER_PC_OLD3 = 38 - { "FET_CTL", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_CONTROLLER_PC_OLD4 = 39 - { "FET_CTL", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_CONTROLLER_DEBUG = 40 - { "FEC_DBG", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_OPTIONS = 41 - { "FET_OPT", 0, 0, 0, 1, 4, - 2, "FET_CTL", 0, 35, - 101, "FET_AUD", 0, 5, - 2, "FET_DIS", 0, 6, - 2, "FET_LAN", 0, 7, - 97, "FET_PSU", 0, 54, - 2, "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_EXIT = 42 - { "FET_QG", 0, 0, 0, 2, 5, - 1, "FEQ_SRE", 0, 0, - 93, "FEM_NO", 0, 0, - 82, "FEM_YES", 0, 0, - }, - - // MENU_PAGE_SAVING_IN_PROGRESS = 43 - { "", 26, 26, 26, 0, 0, - 1, "FES_WAR", 0, 0, - }, - - // MENU_PAGE_SAVE_SUCCESSFUL = 44 - { "FET_SG", 26, 26, 26, 0, 0, - 1, "FES_SSC", 36, 0, - 49, "FEC_OKK", 0, 26, - }, - - // MENU_PAGE_DELETING = 45 - { "FET_DG", 9, 9, 9, 0, 0, - 1, "FED_DLW", 0, 0, - }, - - // MENU_PAGE_DELETE_SUCCESS = 46 - { "FET_DG", 9, 9, 9, 0, 0, - 1, "DEL_FNM", 0, 0, - 2, "FEC_OKK", 0, 9, - }, - - // MENU_PAGE_SAVE_FAILED = 47 - { "FET_SG", 26, 26, 26, 0, 0, - 1, "FEC_SVU", 0, 0, - 2, "FEC_OKK", 0, 26, - }, - - // MENU_PAGE_LOAD_FAILED = 48 - { "FET_SG", 26, 26, 26, 0, 0, - 1, "FEC_SVU", 0, 0, - }, - - // MENU_PAGE_LOAD_FAILED_2 = 49 - { "FET_LG", 26, 26, 26, 0, 0, - 1, "FEC_LUN", 0, 0, - 2, "FEDS_TB", 0, 8, - }, - - // MENU_PAGE_FILTER_GAME = 50 - { "FIL_FLT", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_START_MENU = 51 - { "FEM_MM", -1, -1, -1, 0, 0, - 2, "FEN_STA", 0, 2, - 2, "FET_OPT", 0, 41, - 2, "FEM_QT", 0, 42 - }, - - // MENU_PAGE_PAUSE_MENU = 52 - { "FET_PAU", -1, -1, -1, 0, 0, - 92, "FEM_RES", 0, 0, - 2, "FEN_STA", 0, 2, - 2, "FEP_STA", 0, 1, - 2, "FEP_BRI", 0, 3, - 2, "FET_OPT", 0, 41, - 2, "FEM_QT", 0, 42, - }, - - // MENU_PAGE_CHOOSE_MODE = 53 - { "FEN_STA", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_SKIN_SELECT = 54 - { "FET_PSU", 41, 41, 41, 4, 4, - 35, "FEDS_TB", 0, 21, - }, - - // MENU_PAGE_KEYBOARD_CONTROLS = 55 - { "FET_STI", 35, 35, 35, 1, 1, - 35, "FEDS_TB", 0, 35, - }, - - // MENU_PAGE_MOUSE_CONTROLS = 56 - { "FET_MTI", 35, 35, 35, 2, 2, - 84, "FEC_MSH", 0, 35, - 81, "FEC_IVV", 0, 35, - 102, "FET_MST", 0, 35, - 2 , "FEDS_TB", 0, 0, - }, - - // MENU_PAGE_57 = 57 - { "", -1, -1, -1, 0, 0, - - }, - - // MENU_PAGE_58 = 58 - { "", -1, -1, -1, 0, 0, - - }, -}; - char *FrontendFilenames[] = { "fe2_mainpanel_ul", "fe2_mainpanel_ur", @@ -567,8 +188,8 @@ void CMenuManager::DisplayHelperText() CFont::SetAlignment(ALIGN_CENTER); CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); CFont::SetFontStyle(FONT_HEADING); - CFont::SetDropColor(CRGBA(0, 0, 0, DROP_COLOR_A)); - CFont::SetDropShadowPosition(DROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, MENUDROP_COLOR_A)); + CFont::SetDropShadowPosition(MENUDROP_COLOR_SIZE); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_FROM_BOTTOM(120.0f), str); @@ -627,16 +248,16 @@ void CMenuManager::Draw() CFont::SetBackGroundOnlyTextOn(); CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f)); CFont::SetRightJustifyWrap(0.0f); - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(MENUDROP_COLOR_A))); switch (m_nCurrScreen) { - case MENU_STATS: + case MENUPAGE_STATS: PrintStats(); break; - case MENU_BRIEFS: + case MENUPAGE_BRIEFS: PrintBriefs(); break; - case MENU_CONTROLLER_DEBUG: + case MENUPAGE_CONTROLLER_DEBUG: DrawControllerScreenExtraText(0, 350, 20); break; } @@ -647,27 +268,27 @@ void CMenuManager::Draw() CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); - CFont::SetScale(SCREEN_SCALE_X(HEADER_WIDTH), SCREEN_SCALE_Y(HEADER_HEIGHT)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(HEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::SetScale(SCREEN_SCALE_X(MENUHEADER_WIDTH), SCREEN_SCALE_Y(MENUHEADER_HEIGHT)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); } // Action text. wchar *str; - if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == 1) { + if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) { switch (m_nCurrScreen) { - case MENU_LOAD_SLOT_CONFIRM: + case MENUPAGE_LOAD_SLOT_CONFIRM: if (m_bGameNotLoaded) str = TheText.Get("FES_LCG"); else str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; - case MENU_SAVE_OVERWRITE_CONFIRM: + case MENUPAGE_SAVE_OVERWRITE_CONFIRM: if (Slots[m_nCurrSaveSlot] == 1) str = TheText.Get("FESZ_QZ"); else str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; - case MENU_EXIT: + case MENUPAGE_EXIT: if (m_bGameNotLoaded) str = TheText.Get("FEQ_SRW"); else @@ -678,30 +299,30 @@ void CMenuManager::Draw() break; }; - CFont::SetDropShadowPosition(DROP_COLOR_SIZE); - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetDropShadowPosition(MENUDROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(MENUDROP_COLOR_A))); CFont::SetFontStyle(FONT_BANK); - CFont::SetScale(SCREEN_SCALE_X(ACTION_WIDTH), SCREEN_SCALE_Y(ACTION_HEIGHT)); + CFont::SetScale(SCREEN_SCALE_X(MENUACTION_WIDTH), SCREEN_SCALE_Y(MENUACTION_HEIGHT)); CFont::SetAlignment(ALIGN_LEFT); CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_X(ACTION_POS_X), SCREEN_SCALE_Y(ACTION_POS_Y), str); + CFont::PrintString(SCREEN_SCALE_X(MENUACTION_POS_X), SCREEN_SCALE_Y(MENUACTION_POS_Y), str); } - for (int i = 0; i < 18; ++i) { + for (int i = 0; i < MENUROWS; ++i) { if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0]) { - wchar *columnToPrint[COLUMNS] = { nil, nil }; + wchar *textToPrint[MENUCOLUMNS] = { nil, nil }; - if (aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot >= MENU_ACTION_SAVE_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_ActionSlot <= MENU_ACTION_SAVE_8) { - columnToPrint[L] = GetNameOfSavedGame(i - 1); - columnToPrint[R] = GetSavedGameDateAndTime(i - 1); + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + textToPrint[MENUCOLUMN_LEFT] = GetNameOfSavedGame(i - 1); + textToPrint[MENUCOLUMN_RIGHT] = GetSavedGameDateAndTime(i - 1); - if (!columnToPrint[L][0]) { + if (!textToPrint[MENUCOLUMN_LEFT][0]) { sprintf(gString, "FEM_SL%d", i); - columnToPrint[L] = TheText.Get(gString); + textToPrint[MENUCOLUMN_LEFT] = TheText.Get(gString); } } else { - columnToPrint[L] = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); + textToPrint[MENUCOLUMN_LEFT] = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { @@ -710,48 +331,48 @@ void CMenuManager::Draw() case MENUACTION_CTRLCONFIG: switch (CPad::GetPad(0)->Mode) { case 0: - columnToPrint[R] = TheText.Get("FEC_CF1"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF1"); break; case 1: - columnToPrint[R] = TheText.Get("FEC_CF2"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF2"); break; case 2: - columnToPrint[R] = TheText.Get("FEC_CF3"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF3"); break; case 3: - columnToPrint[R] = TheText.Get("FEC_CF4"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF4"); break; }; break; case MENUACTION_CTRLDISPLAY: break; case MENUACTION_FRAMESYNC: - columnToPrint[R] = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_FRAMELIMIT: - columnToPrint[R] = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_TRAILS: - columnToPrint[R] = TheText.Get(BlurOn ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(BlurOn ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_SUBTITLES: - columnToPrint[R] = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_WIDESCREEN: - columnToPrint[R] = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_RADIO: sprintf(gString, "FEA_FM%d", m_PrefsRadioStation); - columnToPrint[R] = TheText.Get(gString); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gString); break; case MENUACTION_SETDBGFLAG: - columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: - columnToPrint[R] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_INVVERT: - columnToPrint[R] = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_SCREENRES: { @@ -761,31 +382,31 @@ void CMenuManager::Draw() res = ""; AsciiToUnicode(res, gUString); - columnToPrint[R] = gUString; + textToPrint[MENUCOLUMN_RIGHT] = gUString; } break; case MENUACTION_AUDIOHW: if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) - columnToPrint[R] = TheText.Get("FEA_NAH"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_NAH"); else { char *provider = MusicManager.Get3DProviderName(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); AsciiToUnicode(provider, gUString); - columnToPrint[R] = gUString; + textToPrint[MENUCOLUMN_RIGHT] = gUString; } break; case MENUACTION_SPEAKERCONF: if (FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -1) - columnToPrint[R] = TheText.Get("FEA_NAH"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_NAH"); else { switch (m_PrefsSpeakers) { case 0: - columnToPrint[R] = TheText.Get("FEA_2SP"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_2SP"); break; case 1: - columnToPrint[R] = TheText.Get("FEA_EAR"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_EAR"); break; case 2: - columnToPrint[R] = TheText.Get("FEA_4SP"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_4SP"); break; }; } @@ -793,23 +414,23 @@ void CMenuManager::Draw() case MENUACTION_CTRLMETHOD: switch (m_ControlMethod) { case 0: - columnToPrint[L] = TheText.Get("FET_SCN"); + textToPrint[MENUCOLUMN_LEFT] = TheText.Get("FET_SCN"); break; case 1: - columnToPrint[L] = TheText.Get("FET_CCN"); + textToPrint[MENUCOLUMN_LEFT] = TheText.Get("FET_CCN"); break; }; break; case MENUACTION_DYNAMICACOUSTIC: - columnToPrint[R] = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); break; case MENUACTION_MOUSESTEER: - columnToPrint[R] = TheText.Get(m_bDisableMouseSteering ? "FEM_ON" : "FEM_OFF"); + textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_bDisableMouseSteering ? "FEM_ON" : "FEM_OFF"); break; }; - CFont::SetDropShadowPosition(DROP_COLOR_SIZE); - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(DROP_COLOR_A))); + CFont::SetDropShadowPosition(MENUDROP_COLOR_SIZE); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(MENUDROP_COLOR_A))); CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetWrapx(SCREEN_WIDTH); CFont::SetRightJustifyWrap(-SCREEN_WIDTH); @@ -820,78 +441,78 @@ void CMenuManager::Draw() float fBarSize; int SavePageSlot = - m_nCurrScreen == MENU_CHOOSE_LOAD_SLOT || - m_nCurrScreen == MENU_CHOOSE_DELETE_SLOT || - m_nCurrScreen == MENU_CHOOSE_SAVE_SLOT; + m_nCurrScreen == MENUPAGE_CHOOSE_LOAD_SLOT || + m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT || + m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT; if (SavePageSlot) { CFont::SetFontStyle(FONT_BANK); CFont::SetAlignment(ALIGN_LEFT); CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.7f)); - fVerticalSpacing = COLUMN_SPACING_MIN; - fBarSize = SELECT_BOX_MIN; + fVerticalSpacing = MENUCOLUMN_SPACING_MIN; + fBarSize = MENUSELECT_BOX_MIN; - vecPositions.x = SCREEN_SCALE_X(COLUMN_SAVE_X); - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_SAVE_Y); + vecPositions.x = SCREEN_SCALE_X(MENUCOLUMN_SAVE_X); + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_SAVE_Y); } else { CFont::SetFontStyle(FONT_HEADING); - int LeftColumn = - m_nCurrScreen == MENU_SOUND_SETTINGS || - m_nCurrScreen == MENU_GRAPHICS_SETTINGS || - m_nCurrScreen == MENU_MOUSE_CONTROLS; + int LeftMENUCOLUMN = + m_nCurrScreen == MENUPAGE_SOUND_SETTINGS || + m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS || + m_nCurrScreen == MENUPAGE_MOUSE_CONTROLS; - if (LeftColumn) { + if (LeftMENUCOLUMN) { CFont::SetAlignment(ALIGN_LEFT); CFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.8f)); - fVerticalSpacing = COLUMN_SPACING_MIN; - fBarSize = SELECT_BOX_MIN; + fVerticalSpacing = MENUCOLUMN_SPACING_MIN; + fBarSize = MENUSELECT_BOX_MIN; } else { CFont::SetAlignment(ALIGN_CENTER); CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(0.9f)); - fVerticalSpacing = COLUMN_SPACING_MAX; - fBarSize = SELECT_BOX_MAX; + fVerticalSpacing = MENUCOLUMN_SPACING_MAX; + fBarSize = MENUSELECT_BOX_MAX; } // Set positions. if (CFont::GetDetails().centre) vecPositions.x = SCREEN_WIDTH / 2; else - vecPositions.x = SCREEN_SCALE_X(COLUMN_POS_X); + vecPositions.x = SCREEN_SCALE_X(MENUCOLUMN_POS_X); switch (m_nCurrScreen) { - case MENU_BRIEFS: - case MENU_STATS: - vecPositions.y = SCREEN_SCALE_FROM_BOTTOM(COLUMN_FEDS); + case MENUPAGE_BRIEFS: + case MENUPAGE_STATS: + vecPositions.y = SCREEN_SCALE_FROM_BOTTOM(MENUCOLUMN_FEDS); break; - case MENU_SOUND_SETTINGS: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MAX_Y); + case MENUPAGE_SOUND_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_MAX_Y); if (i > 5) - vecPositions.y += SCREEN_SCALE_Y(FE_RADIO_ICON_H * 1.16f); + vecPositions.y += SCREEN_SCALE_Y(MENURADIO_ICON_H * 1.16f); break; - case MENU_LANGUAGE_SETTINGS: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MIN_Y); + case MENUPAGE_LANGUAGE_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_MIN_Y); break; - case MENU_GRAPHICS_SETTINGS: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MAX_Y); + case MENUPAGE_GRAPHICS_SETTINGS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_MAX_Y); break; - case MENU_OPTIONS: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + case MENUPAGE_OPTIONS: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_MID_Y); break; - case MENU_PAUSE_MENU: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_PAUSE_Y); + case MENUPAGE_PAUSE_MENU: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_PAUSE_Y); break; - case MENU_NEW_GAME: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + case MENUPAGE_NEW_GAME: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_MID_Y); break; - case MENU_START_MENU: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_START_Y); + case MENUPAGE_START_MENU: + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_START_Y); break; default: - vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(COLUMN_MID_Y); + vecPositions.y = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENUCOLUMN_MID_Y); break; }; } @@ -908,12 +529,12 @@ void CMenuManager::Draw() CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); // Draw - if (columnToPrint[L]) - CFont::PrintString(vecPositions.x, vecPositions.y, columnToPrint[L]); + if (textToPrint[MENUCOLUMN_LEFT]) + CFont::PrintString(vecPositions.x, vecPositions.y, textToPrint[MENUCOLUMN_LEFT]); - if (columnToPrint[R]) { + if (textToPrint[MENUCOLUMN_RIGHT]) { CFont::SetAlignment(ALIGN_RIGHT); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SavePageSlot ? COLUMN_SAVE_X : COLUMN_POS_X), vecPositions.y, columnToPrint[R]); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SavePageSlot ? MENUCOLUMN_SAVE_X : MENUCOLUMN_POS_X), vecPositions.y, textToPrint[MENUCOLUMN_RIGHT]); } // Mouse support. @@ -945,34 +566,34 @@ void CMenuManager::Draw() // TODO: CheckHover switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { case MENUACTION_BRIGHTNESS: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsBrightness/512.0f); + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(MENUSLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsBrightness/512.0f); break; case MENUACTION_DRAWDIST: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), (m_PrefsLOD - 0.8f) * 1.0f); + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(MENUSLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), (m_PrefsLOD - 0.8f) * 1.0f); break; case MENUACTION_MUSICVOLUME: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsMusicVolume/128.0f); + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(MENUSLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsMusicVolume/128.0f); break; case MENUACTION_SFXVOLUME: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsSfxVolume/128.0f); + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(MENUSLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), m_PrefsSfxVolume/128.0f); break; case MENUACTION_MOUSESENS: - DisplaySlider(SCREEN_SCALE_FROM_RIGHT(SLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), TheCamera.m_fMouseAccelHorzntl * 200.0f); + DisplaySlider(SCREEN_SCALE_FROM_RIGHT(MENUSLIDER_X), vecPositions.y - SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(18.0f), SCREEN_SCALE_X(256.0f), TheCamera.m_fMouseAccelHorzntl * 200.0f); break; }; // Radio icons. float fIconSpacing = 59.52f; - if (m_nCurrScreen == MENU_SOUND_SETTINGS) { + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { for (int i = 0; i < POLICE_RADIO; i++) { if (i == MSX_FM) fIconSpacing -= 1.5f; if (i < USERTRACK) - m_aFrontEndSprites[i + FE_RADIO1].Draw(SCREEN_STRETCH_X(FE_RADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(FE_RADIO_ICON_Y), SCREEN_SCALE_X(FE_RADIO_ICON_W), SCREEN_SCALE_Y(FE_RADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); + m_aFrontEndSprites[i + FE_RADIO1].Draw(SCREEN_STRETCH_X(MENURADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENURADIO_ICON_Y), SCREEN_SCALE_X(MENURADIO_ICON_W), SCREEN_SCALE_Y(MENURADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); if (i > CHATTERBOX) - m_aMenuSprites[MENU_MP3LOGO].Draw(SCREEN_STRETCH_X(FE_RADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(FE_RADIO_ICON_Y), SCREEN_SCALE_X(FE_RADIO_ICON_W), SCREEN_SCALE_Y(FE_RADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, DMAudio.IsMP3RadioChannelAvailable() ? 170 : 25)); + m_aMenuSprites[MENUSPRITE_MP3LOGO].Draw(SCREEN_STRETCH_X(MENURADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENURADIO_ICON_Y), SCREEN_SCALE_X(MENURADIO_ICON_W), SCREEN_SCALE_Y(MENURADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, DMAudio.IsMP3RadioChannelAvailable() ? 170 : 25)); } } @@ -993,12 +614,12 @@ void CMenuManager::Draw() } switch (m_nCurrScreen) { - case MENU_CONTROLLER_SETTINGS: - case MENU_SOUND_SETTINGS: - case MENU_GRAPHICS_SETTINGS: - case MENU_SKIN_SELECT: - case MENU_CONTROLLER_PC: - case MENU_MOUSE_CONTROLS: + case MENUPAGE_CONTROLLER_SETTINGS: + case MENUPAGE_SOUND_SETTINGS: + case MENUPAGE_GRAPHICS_SETTINGS: + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_CONTROLLER_PC: + case MENUPAGE_MOUSE_CONTROLS: DisplayHelperText(); break; }; @@ -1041,15 +662,17 @@ void CMenuManager::DrawFrontEnd() { CFont::SetAlphaFade(255.0f); - if (m_nCurrScreen == MENU_NONE) { + if (m_nCurrScreen == MENUPAGE_NONE) { + m_nMenuFadeAlpha = 0; + if (m_bGameNotLoaded) - m_nCurrScreen = MENU_START_MENU; + m_nCurrScreen = MENUPAGE_START_MENU; else - m_nCurrScreen = MENU_PAUSE_MENU; + m_nCurrScreen = MENUPAGE_PAUSE_MENU; } if (!m_nCurrOption && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) - m_nCurrOption = 1; + m_nCurrOption = MENUROW_1; CMenuManager::DrawFrontEndNormal(); CMenuManager::PrintErrorMessage(); @@ -1072,77 +695,128 @@ void CMenuManager::DrawFrontEndNormal() CSprite2d::InitPerFrame(); CFont::InitPerFrame(); - eMenuSprites currentSprite = MENU_MAINMENU; - switch (m_nPrevScreen) { - case MENU_STATS: - case MENU_START_MENU: - case MENU_PAUSE_MENU: - currentSprite = MENU_MAINMENU; + eMenuSprites previousSprite = MENUSPRITE_MAINMENU; + if (m_nMenuFadeAlpha < 255) { + switch (m_nPrevScreen) { + case MENUPAGE_STATS: + case MENUPAGE_START_MENU: + case MENUPAGE_PAUSE_MENU: + previousSprite = MENUSPRITE_MAINMENU; + break; + case MENUPAGE_NEW_GAME: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + case MENUPAGE_EXIT: + previousSprite = MENUSPRITE_SINGLEPLAYER; + break; + case MENUPAGE_MULTIPLAYER_MAIN: + previousSprite = MENUSPRITE_MULTIPLAYER; + break; + case MENUPAGE_MULTIPLAYER_MAP: + case MENUPAGE_MULTIPLAYER_FIND_GAME: + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_KEYBOARD_CONTROLS: + case MENUPAGE_MOUSE_CONTROLS: + previousSprite = MENUSPRITE_FINDGAME; + break; + case MENUPAGE_MULTIPLAYER_CONNECTION: + case MENUPAGE_MULTIPLAYER_MODE: + previousSprite = MENUSPRITE_CONNECTION; + break; + case MENUPAGE_MULTIPLAYER_CREATE: + previousSprite = MENUSPRITE_HOSTGAME; + break; + case MENUPAGE_SKIN_SELECT_OLD: + case MENUPAGE_OPTIONS: + previousSprite = MENUSPRITE_PLAYERSET; + break; + }; + + if (m_nPrevScreen == MENUPAGE_NONE) + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(0, 0, 0, 255)); + else + m_aMenuSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, 255)); + } + + eMenuSprites currentSprite = MENUSPRITE_MAINMENU; + switch (m_nCurrScreen) { + case MENUPAGE_STATS: + case MENUPAGE_START_MENU: + case MENUPAGE_PAUSE_MENU: + currentSprite = MENUSPRITE_MAINMENU; break; - case MENU_NEW_GAME: - case MENU_CHOOSE_LOAD_SLOT: - case MENU_CHOOSE_DELETE_SLOT: - case MENU_NEW_GAME_RELOAD: - case MENU_LOAD_SLOT_CONFIRM: - case MENU_DELETE_SLOT_CONFIRM: - case MENU_EXIT: - currentSprite = MENU_SINGLEPLAYER; + case MENUPAGE_NEW_GAME: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + case MENUPAGE_EXIT: + currentSprite = MENUSPRITE_SINGLEPLAYER; break; - case MENU_MULTIPLAYER_MAIN: - currentSprite = MENU_MULTIPLAYER; + case MENUPAGE_MULTIPLAYER_MAIN: + currentSprite = MENUSPRITE_MULTIPLAYER; break; - case MENU_MULTIPLAYER_MAP: - case MENU_MULTIPLAYER_FIND_GAME: - case MENU_SKIN_SELECT: - case MENU_KEYBOARD_CONTROLS: - case MENU_MOUSE_CONTROLS: - currentSprite = MENU_FINDGAME; + case MENUPAGE_MULTIPLAYER_MAP: + case MENUPAGE_MULTIPLAYER_FIND_GAME: + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_KEYBOARD_CONTROLS: + case MENUPAGE_MOUSE_CONTROLS: + currentSprite = MENUSPRITE_FINDGAME; break; - case MENU_MULTIPLAYER_CONNECTION: - case MENU_MULTIPLAYER_MODE: - currentSprite = MENU_CONNECTION; + case MENUPAGE_MULTIPLAYER_CONNECTION: + case MENUPAGE_MULTIPLAYER_MODE: + currentSprite = MENUSPRITE_CONNECTION; break; - case MENU_MULTIPLAYER_CREATE: - currentSprite = MENU_HOSTGAME; + case MENUPAGE_MULTIPLAYER_CREATE: + currentSprite = MENUSPRITE_HOSTGAME; break; - case MENU_SKIN_SELECT_OLD: - case MENU_OPTIONS: - currentSprite = MENU_PLAYERSET; + case MENUPAGE_SKIN_SELECT_OLD: + case MENUPAGE_OPTIONS: + currentSprite = MENUSPRITE_PLAYERSET; break; }; - //CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(0, 0, 0, 255)); - uint32 savedShade; uint32 savedAlpha; RwRenderStateGet(rwRENDERSTATESHADEMODE, &savedShade); RwRenderStateSet(rwRENDERSTATESHADEMODE, reinterpret_cast(rwSHADEMODEGOURAUD)); RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &savedAlpha); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(TRUE)); - if (m_nMenuFadeAlpha >= 255) + if (m_nMenuFadeAlpha >= 255) { m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, 255)); + } else { - if (m_nMenuFadeAlpha != 255) + if (m_nMenuFadeAlpha < 255) { m_nMenuFadeAlpha += 0.1f * 255.0f; - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); + if (m_nMenuFadeAlpha >= 255) + m_nMenuFadeAlpha = 255; + + m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); + } + else + m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), CRGBA(255, 255, 255, 255)); } // GTA LOGO - if (m_nCurrScreen == MENU_START_MENU || m_nCurrScreen == MENU_PAUSE_MENU) { + if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) { if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - m_aMenuSprites[MENU_GTA3LOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(70.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); + m_aMenuSprites[MENUSPRITE_GTA3LOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(70.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(115.0f), SCREEN_SCALE_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); else - m_aMenuSprites[MENU_GTALOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(40.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); + m_aMenuSprites[MENUSPRITE_GTALOGO].Draw(CRect((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(40.0f), (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(95.0f), SCREEN_SCALE_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); } RwRenderStateSet(rwRENDERSTATESHADEMODE, reinterpret_cast(savedShade)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(savedAlpha)); switch (m_nCurrScreen) { - case MENU_SKIN_SELECT: + case MENUPAGE_SKIN_SELECT: CMenuManager::DrawPlayerSetupScreen(); break; - case MENU_KEYBOARD_CONTROLS: + case MENUPAGE_KEYBOARD_CONTROLS: CMenuManager::DrawControllerSetupScreen(); break; default: @@ -1154,7 +828,7 @@ void CMenuManager::DrawFrontEndNormal() // Draw mouse if (m_bShowMouse) - m_aMenuSprites[MENU_MOUSE].Draw(m_nMousePosX, m_nMousePosY, SCREEN_SCALE_X(60.0f), SCREEN_SCALE_Y(60.0f), CRGBA(255, 255, 255, 255)); + m_aMenuSprites[MENUSPRITE_MOUSE].Draw(m_nMousePosX, m_nMousePosY, SCREEN_SCALE_X(60.0f), SCREEN_SCALE_Y(60.0f), CRGBA(255, 255, 255, 255)); } #endif @@ -1172,9 +846,9 @@ WRAPPER int CMenuManager::FadeIn(int alpha) { EAXJMP(0x48AC60); } #else int CMenuManager::FadeIn(int alpha) { - if (m_nCurrScreen == MENU_LOADING_IN_PROGRESS || - m_nCurrScreen == MENU_SAVING_IN_PROGRESS || - m_nCurrScreen == MENU_DELETING) + if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS || + m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS || + m_nCurrScreen == MENUPAGE_DELETING) return alpha; if (m_nMenuFadeAlpha >= alpha) @@ -1220,7 +894,7 @@ void CMenuManager::LoadAllTextures() CMenuManager::CentreMousePointer(); DMAudio.ChangeMusicMode(0); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); - m_nCurrOption = 0; + m_nCurrOption = MENUROW_0; m_PrefsRadioStation = DMAudio.GetRadioInCar(); if (DMAudio.IsMP3RadioChannelAvailable()) { diff --git a/src/Frontend.h b/src/Frontend.h index 7245477f..c515be8c 100644 --- a/src/Frontend.h +++ b/src/Frontend.h @@ -2,44 +2,45 @@ #include "Sprite2d.h" -#define HEADER_POS_X 35.0f -#define HEADER_POS_Y 93.0f -#define HEADER_WIDTH 0.84f -#define HEADER_HEIGHT 1.6f +#define MENUHEADER_POS_X 35.0f +#define MENUHEADER_POS_Y 93.0f +#define MENUHEADER_WIDTH 0.84f +#define MENUHEADER_HEIGHT 1.6f -#define ACTION_POS_X 20.0f -#define ACTION_POS_Y 37.5f -#define ACTION_WIDTH 0.675f -#define ACTION_HEIGHT 0.81f +#define MENUACTION_POS_X 20.0f +#define MENUACTION_POS_Y 37.5f +#define MENUACTION_WIDTH 0.675f +#define MENUACTION_HEIGHT 0.81f -#define COLUMN_POS_X HEADER_POS_X + 16.0f -#define COLUMN_MAX_Y 149.0f -#define COLUMN_MID_Y 100.0f -#define COLUMN_MIN_Y 110.0f -#define COLUMN_PAUSE_Y 25.0f -#define COLUMN_START_Y 9.0f -#define COLUMN_FEDS 139.0f +#define MENUCOLUMN_POS_X MENUHEADER_POS_X + 16.0f +#define MENUCOLUMN_MAX_Y 149.0f +#define MENUCOLUMN_MID_Y 100.0f +#define MENUCOLUMN_MIN_Y 110.0f +#define MENUCOLUMN_PAUSE_Y 25.0f +#define MENUCOLUMN_START_Y 9.0f +#define MENUCOLUMN_FEDS 139.0f -#define COLUMN_SAVE_X 121.0f -#define COLUMN_SAVE_Y 111.0f +#define MENUCOLUMN_SAVE_X 121.0f +#define MENUCOLUMN_SAVE_Y 111.0f -#define COLUMN_SPACING_MAX 24.0f -#define COLUMN_SPACING_MIN 20.0f +#define MENUCOLUMN_SPACING_MAX 24.0f +#define MENUCOLUMN_SPACING_MIN 20.0f -#define SELECT_BOX_MAX 20.5f -#define SELECT_BOX_MIN 17.0f +#define MENUSELECT_BOX_MAX 20.5f +#define MENUSELECT_BOX_MIN 17.0f -#define FE_RADIO_ICON_X 31.5f -#define FE_RADIO_ICON_Y 29.5f -#define FE_RADIO_ICON_W 60.0f -#define FE_RADIO_ICON_H 60.0f +#define MENURADIO_ICON_X 31.5f +#define MENURADIO_ICON_Y 29.5f +#define MENURADIO_ICON_W 60.0f +#define MENURADIO_ICON_H 60.0f -#define DROP_COLOR_A 150 -#define DROP_COLOR_SIZE -1 +#define MENUDROP_COLOR_A 150 +#define MENUDROP_COLOR_SIZE -1 -#define SLIDER_X 306.0f +#define MENUSLIDER_X 306.0f -enum { +enum eLanguages +{ LANGUAGE_AMERICAN, LANGUAGE_FRENCH, LANGUAGE_GERMAN, @@ -47,7 +48,8 @@ enum { LANGUAGE_SPANISH, }; -enum eFrontendSprites { +enum eFrontendSprites +{ FE2_MAINPANEL_UL, FE2_MAINPANEL_UR, FE2_MAINPANEL_DL, @@ -78,102 +80,110 @@ enum eFrontendSprites { FE_RADIO9, }; -enum eMenuSprites { - MENU_CONNECTION, - MENU_FINDGAME, - MENU_HOSTGAME, - MENU_MAINMENU, - MENU_PLAYERSET, - MENU_SINGLEPLAYER, - MENU_MULTIPLAYER, - MENU_DMALOGO, - MENU_GTALOGO, - MENU_RSTARLOGO, - MENU_GAMESPY, - MENU_MOUSE, - MENU_MOUSET, - MENU_MP3LOGO, - MENU_DOWNOFF, - MENU_DOWNON, - MENU_UPOFF, - MENU_UPON, - MENU_GTA3LOGO, +enum eMenuSprites +{ + MENUSPRITE_CONNECTION, + MENUSPRITE_FINDGAME, + MENUSPRITE_HOSTGAME, + MENUSPRITE_MAINMENU, + MENUSPRITE_PLAYERSET, + MENUSPRITE_SINGLEPLAYER, + MENUSPRITE_MULTIPLAYER, + MENUSPRITE_DMALOGO, + MENUSPRITE_GTALOGO, + MENUSPRITE_RSTARLOGO, + MENUSPRITE_GAMESPY, + MENUSPRITE_MOUSE, + MENUSPRITE_MOUSET, + MENUSPRITE_MP3LOGO, + MENUSPRITE_DOWNOFF, + MENUSPRITE_DOWNON, + MENUSPRITE_UPOFF, + MENUSPRITE_UPON, + MENUSPRITE_GTA3LOGO, }; -enum eMenuActions { - MENU_ACTION_SAVE_1 = 1, - MENU_ACTION_SAVE_2, - MENU_ACTION_SAVE_3, - MENU_ACTION_SAVE_4, - MENU_ACTION_SAVE_5, - MENU_ACTION_SAVE_6, - MENU_ACTION_SAVE_7, - MENU_ACTION_SAVE_8, +enum eSaveSlot +{ + SAVESLOT_NONE, + SAVESLOT_1, + SAVESLOT_2, + SAVESLOT_3, + SAVESLOT_4, + SAVESLOT_5, + SAVESLOT_6, + SAVESLOT_7, + SAVESLOT_8, + SAVESLOT_LABEL = 36 }; -enum eMenuScreen { - MENU_NONE = 0, - MENU_STATS = 1, - MENU_NEW_GAME = 2, - MENU_BRIEFS = 3, - MENU_CONTROLLER_SETTINGS = 4, - MENU_SOUND_SETTINGS = 5, - MENU_GRAPHICS_SETTINGS = 6, - MENU_LANGUAGE_SETTINGS = 7, - MENU_CHOOSE_LOAD_SLOT = 8, - MENU_CHOOSE_DELETE_SLOT = 9, - MENU_NEW_GAME_RELOAD = 10, - MENU_LOAD_SLOT_CONFIRM = 11, - MENU_DELETE_SLOT_CONFIRM = 12, - MENU_13 = 13, - MENU_LOADING_IN_PROGRESS = 14, - MENU_DELETING_IN_PROGRESS = 15, - MENU_16 = 16, - MENU_DELETE_FAILED = 17, - MENU_DEBUG_MENU = 18, - MENU_MEMORY_CARD_1 = 19, - MENU_MEMORY_CARD_2 = 20, - MENU_MULTIPLAYER_MAIN = 21, - MENU_SAVE_FAILED_1 = 22, - MENU_SAVE_FAILED_2 = 23, - MENU_SAVE = 24, - MENU_NO_MEMORY_CARD = 25, - MENU_CHOOSE_SAVE_SLOT = 26, - MENU_SAVE_OVERWRITE_CONFIRM = 27, - MENU_MULTIPLAYER_MAP = 28, - MENU_MULTIPLAYER_CONNECTION = 29, - MENU_MULTIPLAYER_FIND_GAME = 30, - MENU_MULTIPLAYER_MODE = 31, - MENU_MULTIPLAYER_CREATE = 32, - MENU_MULTIPLAYER_START = 33, - MENU_SKIN_SELECT_OLD = 34, - MENU_CONTROLLER_PC = 35, - MENU_CONTROLLER_PC_OLD1 = 36, - MENU_CONTROLLER_PC_OLD2 = 37, - MENU_CONTROLLER_PC_OLD3 = 38, - MENU_CONTROLLER_PC_OLD4 = 39, - MENU_CONTROLLER_DEBUG = 40, - MENU_OPTIONS = 41, - MENU_EXIT = 42, - MENU_SAVING_IN_PROGRESS = 43, - MENU_SAVE_SUCCESSFUL = 44, - MENU_DELETING = 45, - MENU_DELETE_SUCCESS = 46, - MENU_SAVE_FAILED = 47, - MENU_LOAD_FAILED = 48, - MENU_LOAD_FAILED_2 = 49, - MENU_FILTER_GAME = 50, - MENU_START_MENU = 51, - MENU_PAUSE_MENU = 52, - MENU_CHOOSE_MODE = 53, - MENU_SKIN_SELECT = 54, - MENU_KEYBOARD_CONTROLS = 55, - MENU_MOUSE_CONTROLS = 56, - MENU_57 = 57, - MENU_58 = 58, +enum eMenuScreen +{ + MENUPAGE_DISABLED = -1, + MENUPAGE_NONE = 0, + MENUPAGE_STATS = 1, + MENUPAGE_NEW_GAME = 2, + MENUPAGE_BRIEFS = 3, + MENUPAGE_CONTROLLER_SETTINGS = 4, + MENUPAGE_SOUND_SETTINGS = 5, + MENUPAGE_GRAPHICS_SETTINGS = 6, + MENUPAGE_LANGUAGE_SETTINGS = 7, + MENUPAGE_CHOOSE_LOAD_SLOT = 8, + MENUPAGE_CHOOSE_DELETE_SLOT = 9, + MENUPAGE_NEW_GAME_RELOAD = 10, + MENUPAGE_LOAD_SLOT_CONFIRM = 11, + MENUPAGE_DELETE_SLOT_CONFIRM = 12, + MENUPAGE_13 = 13, + MENUPAGE_LOADING_IN_PROGRESS = 14, + MENUPAGE_DELETING_IN_PROGRESS = 15, + MENUPAGE_16 = 16, + MENUPAGE_DELETE_FAILED = 17, + MENUPAGE_DEBUG_MENU = 18, + MENUPAGE_MEMORY_CARD_1 = 19, + MENUPAGE_MEMORY_CARD_2 = 20, + MENUPAGE_MULTIPLAYER_MAIN = 21, + MENUPAGE_SAVE_FAILED_1 = 22, + MENUPAGE_SAVE_FAILED_2 = 23, + MENUPAGE_SAVE = 24, + MENUPAGE_NO_MEMORY_CARD = 25, + MENUPAGE_CHOOSE_SAVE_SLOT = 26, + MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27, + MENUPAGE_MULTIPLAYER_MAP = 28, + MENUPAGE_MULTIPLAYER_CONNECTION = 29, + MENUPAGE_MULTIPLAYER_FIND_GAME = 30, + MENUPAGE_MULTIPLAYER_MODE = 31, + MENUPAGE_MULTIPLAYER_CREATE = 32, + MENUPAGE_MULTIPLAYER_START = 33, + MENUPAGE_SKIN_SELECT_OLD = 34, + MENUPAGE_CONTROLLER_PC = 35, + MENUPAGE_CONTROLLER_PC_OLD1 = 36, + MENUPAGE_CONTROLLER_PC_OLD2 = 37, + MENUPAGE_CONTROLLER_PC_OLD3 = 38, + MENUPAGE_CONTROLLER_PC_OLD4 = 39, + MENUPAGE_CONTROLLER_DEBUG = 40, + MENUPAGE_OPTIONS = 41, + MENUPAGE_EXIT = 42, + MENUPAGE_SAVING_IN_PROGRESS = 43, + MENUPAGE_SAVE_SUCCESSFUL = 44, + MENUPAGE_DELETING = 45, + MENUPAGE_DELETE_SUCCESS = 46, + MENUPAGE_SAVE_FAILED = 47, + MENUPAGE_LOAD_FAILED = 48, + MENUPAGE_LOAD_FAILED_2 = 49, + MENUPAGE_FILTER_GAME = 50, + MENUPAGE_START_MENU = 51, + MENUPAGE_PAUSE_MENU = 52, + MENUPAGE_CHOOSE_MODE = 53, + MENUPAGE_SKIN_SELECT = 54, + MENUPAGE_KEYBOARD_CONTROLS = 55, + MENUPAGE_MOUSE_CONTROLS = 56, + MENUPAGE_57 = 57, + MENUPAGE_58 = 58, + MENUPAGES }; -enum eMenuAction { +enum eMenuAction +{ MENUACTION_NOTHING, MENUACTION_LABEL, MENUACTION_CHANGEMENU, @@ -194,7 +204,7 @@ enum eMenuAction { MENUACTION_LANG_ENG, MENUACTION_LANG_FRE, MENUACTION_LANG_GER, - MENUACTION_LANG_IT, + MENUACTION_LANG_ITA, MENUACTION_LANG_SPA, MENUACTION_UPDATESAVE, MENUACTION_CHECKSAVE, @@ -287,11 +297,43 @@ enum eMenuAction { MENUACTION_UNK110, }; -enum eCheckHover { +enum eCheckHover +{ ACTIVATE_OPTION = 2, IGNORE_OPTION = 42, }; +enum eMenuColumns +{ + MENUCOLUMN_LEFT, + MENUCOLUMN_CENTER, + MENUCOLUMN_RIGHT, + MENUCOLUMNS, +}; + +enum eMenuRow +{ + MENUROW_0, + MENUROW_1, + MENUROW_2, + MENUROW_3, + MENUROW_4, + MENUROW_5, + MENUROW_6, + MENUROW_7, + MENUROW_8, + MENUROW_9, + MENUROW_10, + MENUROW_11, + MENUROW_12, + MENUROW_13, + MENUROW_14, + MENUROW_15, + MENUROW_16, + MENUROW_17, + MENUROWS, +}; + struct tSkinInfo { int field_0; @@ -301,18 +343,19 @@ struct tSkinInfo int field_304; }; -struct CMenuScreen { +struct CMenuScreen +{ char m_ScreenName[8]; - int32 m_PreviousPage[3]; // - int32 m_ParentEntry[2]; + int32 m_PreviousPage[3]; // eMenuScreen + int32 m_ParentEntry[2]; // eMenuRow struct CMenuEntry { - int32 m_Action; + int32 m_Action; // eMenuAction char m_EntryName[8]; - int32 m_ActionSlot; - int32 m_TargetMenu; - } m_aEntries[18]; + int32 m_SaveSlot; // eSaveSlot + int32 m_TargetMenu; // eMenuScreen + } m_aEntries[MENUROWS]; }; class CMenuManager @@ -401,12 +444,8 @@ public: static int32 &m_PrefsSfxVolume; static bool &m_bStartUpFrontEndRequested; static bool &m_bShutDownFrontEndRequested; - static bool &m_PrefsAllowNastyGame; -private: - enum eColumns { L, R, COLUMNS, }; - public: void BuildStatLine(char *, void *, uint16, void *); static void CentreMousePointer(); diff --git a/src/MenuScreens.h b/src/MenuScreens.h new file mode 100644 index 00000000..b9d6906e --- /dev/null +++ b/src/MenuScreens.h @@ -0,0 +1,380 @@ +#pragma once + +const CMenuScreen aScreens[] = { + // MENUPAGE_NONE = 0 + { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, }, + + // MENUPAGE_STATS = 1 + { "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_5, MENUROW_2, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_NEW_GAME = 2 + { "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_0, MENUROW_1, + MENUACTION_CHANGEMENU, "FES_SNG", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, + MENUACTION_UPDATESAVE, "GMLOAD", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, + MENUACTION_CHANGEMENU, "FES_DGA", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_BRIEFS = 3 + { "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_6, MENUROW_3, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENU_CONTROLLER_SETTINGS = 4 + { "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_SOUND_SETTINGS = 5 + { "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_1, MENUROW_1, + MENUACTION_MUSICVOLUME, "FEA_MUS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_SFXVOLUME, "FEA_SFX", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_AUDIOHW, "FEA_3DH", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_SPEAKERCONF, "FEA_SPK", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_DYNAMICACOUSTIC, "FET_DAM", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_RADIO, "FEA_RSS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + }, + + // MENUPAGE_GRAPHICS_SETTINGS = 6 + { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_2, MENUROW_2, + MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_LANGUAGE_SETTINGS = 7 + { "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_3, MENUROW_3, + MENUACTION_LANG_ENG, "FEL_ENG", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, + MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, + MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, + MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, + MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_CHOOSE_LOAD_SLOT = 8 + { "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_1, MENUROW_1, + MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, + MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + }, + + // MENUPAGE_CHOOSE_DELETE_SLOT = 9 + { "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_2, MENUROW_2, + MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, + MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + }, + + // MENUPAGE_NEW_GAME_RELOAD = 10 + { "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FESZ_QR", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NEW_GAME, + MENUACTION_NEWGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, + }, + + // MENUPAGE_LOAD_SLOT_CONFIRM = 11 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FESZ_QL", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, + MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS, + }, + + // MENUPAGE_DELETE_SLOT_CONFIRM = 12 + { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FESZ_QD", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, + MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_DELETING, + }, + + // MENUPAGE_13 = 13 + { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_LOADING_IN_PROGRESS = 14 + { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FED_LDW", SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM, + }, + + // MENUPAGE_DELETING_IN_PROGRESS = 15 + { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FEDL_WR", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_16 = 16 + { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FES_LOE", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_DELETE_FAILED = 17 + { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FES_DEE", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, + }, + + // MENUPAGE_DEBUG_MENU = 18 + { "FED_DBG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MEMORY_CARD_1 = 19 + { "FEM_MCM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MEMORY_CARD_2 = 20 + { "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MULTIPLAYER_MAIN = 21 + { "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_SAVE_FAILED_1 = 22 + { "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_SAVE_FAILED_2 = 23 + { "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_SAVE = 24 + { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FES_SCG", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_UPDATESAVE, "GMSAVE", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, + MENUACTION_UPDATEMEMCARDSAVE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_NO_MEMORY_CARD = 25 + { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_CHOOSE_SAVE_SLOT = 26 + { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_UPDATEMEMCARDSAVE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + }, + + // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FESZ_QO", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS, + MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, + }, + + // MENUPAGE_MULTIPLAYER_MAP = 28 + { "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MULTIPLAYER_CONNECTION = 29 + { "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MULTIPLAYER_FIND_GAME = 30 + { "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MULTIPLAYER_MODE = 31 + { "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MULTIPLAYER_CREATE = 32 + { "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_MULTIPLAYER_START = 33 + { "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_SKIN_SELECT_OLD = 34 + { "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_CONTROLLER_PC = 35 + { "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_0, MENUROW_0, + MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + MENUACTION_REDEFCTRL, "FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, + MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_CONTROLLER_PC_OLD1 = 36 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_CONTROLLER_PC_OLD2 = 37 + { "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_CONTROLLER_PC_OLD3 = 38 + { "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_CONTROLLER_PC_OLD4 = 39 + { "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_CONTROLLER_DEBUG = 40 + { "FEC_DBG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_OPTIONS = 41 + { "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_1, MENUROW_4, + MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + MENUACTION_LOADRADIO, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, + MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, + MENUACTION_CHANGEMENU, "FET_LAN", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, + MENUACTION_PLAYERSETUP, "FET_PSU", SAVESLOT_NONE, MENUPAGE_SKIN_SELECT, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_EXIT = 42 + { "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_2, MENUROW_5, + MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_DONTCANCLE, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CANCLEGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_SAVING_IN_PROGRESS = 43 + { "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FES_WAR", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_SAVE_SUCCESSFUL = 44 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FES_SSC", SAVESLOT_LABEL, MENUPAGE_NONE, + MENUACTION_UPDATEMEMCARDSAVE, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, + }, + + // MENUPAGE_DELETING = 45 + { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FED_DLW", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_DELETE_SUCCESS = 46 + { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "DEL_FNM", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, + }, + + // MENUPAGE_SAVE_FAILED = 47 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, + }, + + // MENUPAGE_LOAD_FAILED = 48 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_LOAD_FAILED_2 = 49 + { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0, + MENUACTION_LABEL, "FEC_LUN", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, + }, + + // MENUPAGE_FILTER_GAME = 50 + { "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_START_MENU = 51 + { "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, + MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, + MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT, + }, + + // MENUPAGE_PAUSE_MENU = 52 + { "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, + MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS, + MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS, + MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, + MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT, + }, + + // MENUPAGE_CHOOSE_MODE = 53 + { "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_SKIN_SELECT = 54 + { "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_4, MENUROW_4, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN, + }, + + // MENUPAGE_KEYBOARD_CONTROLS = 55 + { "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUROW_1, MENUROW_1, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + }, + + // MENUPAGE_MOUSE_CONTROLS = 56 + { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUROW_2, MENUROW_2, + MENUACTION_MOUSESENS, "FEC_MSH", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + MENUACTION_INVVERT, "FEC_IVV", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + MENUACTION_MOUSESTEER, "FET_MST", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, + + // MENUPAGE_57 = 57 + { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, + + // MENUPAGE_58 = 58 + { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, + + }, +}; diff --git a/src/Timer.h b/src/Timer.h index 10bb5d84..c3269d60 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -18,7 +18,8 @@ public: static void SetTimeStep(float ts) { ms_fTimeStep = ts; } static uint32 GetFrameCounter(void) { return m_FrameCounter; } static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; } - + static uint32 GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; } + static inline bool GetIsPaused() { return m_UserPause || m_CodePause; } static inline bool GetIsUserPaused() { return m_UserPause; } static inline void SetTimeScale(float ts) { ms_fTimeScale = ts; } diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 5da1d489..757ffa79 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -10,6 +10,8 @@ cAudioManager::PlayerJustLeftCar(void) // UNUSED: This is a perfectly empty function. } +WRAPPER void cAudioManager::Service() { EAXJMP(0x57A2A0); } + STARTPATCHES InjectHook(0x56AD20, &cAudioManager::PlayerJustLeftCar, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 37dd3218..9e25b0a3 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -3,6 +3,7 @@ class cAudioManager { public: void PlayerJustLeftCar(void); + void Service(); }; extern cAudioManager &AudioManager; \ No newline at end of file diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index b96bee01..bfa24ab0 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -19,4 +19,8 @@ WRAPPER void cDMAudio::ChangeMusicMode(uint8 mode) { EAXJMP(0x57CCF0); } WRAPPER void cDMAudio::PlayFrontEndSound(uint32, uint32) { EAXJMP(0x57CC20); } WRAPPER void cDMAudio::PlayOneShot(int, uint16, float) { EAXJMP(0x57C840); } WRAPPER int cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); } -WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); } \ No newline at end of file +WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); } + +WRAPPER void cDMAudio::SetEffectsFadeVol(int16) { EAXJMP(0x57C8F0); } +WRAPPER void cDMAudio::SetMusicFadeVol(int16) { EAXJMP(0x57C920); } + diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index ad67cf13..bf9b65b9 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -191,5 +191,8 @@ public: void PlayOneShot(int, uint16, float); int GetRadioInCar(); uint8 IsMP3RadioChannelAvailable(); + void SetEffectsFadeVol(int16); + void SetMusicFadeVol(int16); + }; extern cDMAudio &DMAudio; From dd1b56372047c1ffc9f356f0435f6a6cb16e3010 Mon Sep 17 00:00:00 2001 From: _AG Date: Tue, 25 Jun 2019 20:48:05 +0200 Subject: [PATCH 11/17] Little fix #52. --- src/Frontend.cpp | 4 ++-- src/Frontend.h | 1 + src/MenuScreens.h | 48 +++++++++++++++++++++++------------------------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/Frontend.cpp b/src/Frontend.cpp index 1cac3d2b..de9e8a65 100644 --- a/src/Frontend.cpp +++ b/src/Frontend.cpp @@ -458,12 +458,12 @@ void CMenuManager::Draw() else { CFont::SetFontStyle(FONT_HEADING); - int LeftMENUCOLUMN = + int LeftMenuColumn = m_nCurrScreen == MENUPAGE_SOUND_SETTINGS || m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS || m_nCurrScreen == MENUPAGE_MOUSE_CONTROLS; - if (LeftMENUCOLUMN) { + if (LeftMenuColumn) { CFont::SetAlignment(ALIGN_LEFT); CFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.8f)); fVerticalSpacing = MENUCOLUMN_SPACING_MIN; diff --git a/src/Frontend.h b/src/Frontend.h index c515be8c..dd6464b8 100644 --- a/src/Frontend.h +++ b/src/Frontend.h @@ -106,6 +106,7 @@ enum eMenuSprites enum eSaveSlot { SAVESLOT_NONE, + SAVESLOT_0, SAVESLOT_1, SAVESLOT_2, SAVESLOT_3, diff --git a/src/MenuScreens.h b/src/MenuScreens.h index b9d6906e..640952ed 100644 --- a/src/MenuScreens.h +++ b/src/MenuScreens.h @@ -66,27 +66,27 @@ const CMenuScreen aScreens[] = { // MENUPAGE_CHOOSE_LOAD_SLOT = 8 { "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_1, MENUROW_1, MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8 + 1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM, + MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM, }, // MENUPAGE_CHOOSE_DELETE_SLOT = 9 { "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_2, MENUROW_2, MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8 + 1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM, }, // MENUPAGE_NEW_GAME_RELOAD = 10 @@ -181,14 +181,14 @@ const CMenuScreen aScreens[] = { // MENUPAGE_CHOOSE_SAVE_SLOT = 26 { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, MENUACTION_UPDATEMEMCARDSAVE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8 + 1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM, }, // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27 From f5e31a45645d481a1cc156c901edfb4a31f85d02 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 26 Jun 2019 11:12:00 +0200 Subject: [PATCH 12/17] fixed PedType --- src/control/PedType.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/PedType.h b/src/control/PedType.h index 02add8f6..455d8d8d 100644 --- a/src/control/PedType.h +++ b/src/control/PedType.h @@ -22,9 +22,9 @@ enum PEDTYPE_EMERGENCY, PEDTYPE_FIREMAN, PEDTYPE_CRIMINAL, - PEDTYPE_SPECIAL, - PEDTYPE_PROSTITUTE, PEDTYPE_UNUSED1, + PEDTYPE_PROSTITUTE, + PEDTYPE_SPECIAL, PEDTYPE_UNUSED2, NUM_PEDTYPES From 8510792256948f85241d7b18bc3a37b5f1766dcf Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 26 Jun 2019 11:19:56 +0200 Subject: [PATCH 13/17] CPed cleanup --- src/entities/Ped.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 7a48cdc4..10de9fa8 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -1076,23 +1076,19 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) ped->m_pSeekTarget = nil; vehicle = ped->m_pMyVehicle; - if (ped->m_vehEnterType <= VEHICLE_ENTER_REAR_LEFT) { - switch (ped->m_vehEnterType) { - case VEHICLE_ENTER_FRONT_RIGHT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FR; - break; - case VEHICLE_ENTER_REAR_RIGHT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RR; - break; - case VEHICLE_ENTER_FRONT_LEFT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FL; - break; - case VEHICLE_ENTER_REAR_LEFT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RL; - break; - default: - break; - } + switch (ped->m_vehEnterType) { + case VEHICLE_ENTER_FRONT_RIGHT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FR; + break; + case VEHICLE_ENTER_REAR_RIGHT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RR; + break; + case VEHICLE_ENTER_FRONT_LEFT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FL; + break; + case VEHICLE_ENTER_REAR_LEFT: + vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RL; + break; } if (vehicle->pDriver == ped) { @@ -1431,7 +1427,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) m_fRotationCur = m_fRotationDest; } else { float limitedAngle = CGeneral::LimitRadianAngle(m_fRotationDest); - float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds()) * 0.0016666667f; // changing this to 0.002 causes wrong rotation + float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f; m_vecOffsetSeek.z = 0.0; if (timeUntilStateChange <= 0.0f) { From b19e1d369ce71681ac48c9e8bbce8f419261ac77 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 26 Jun 2019 11:35:34 +0200 Subject: [PATCH 14/17] fixed bug in CPed --- src/entities/Ped.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 10de9fa8..a80fc770 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -509,11 +509,11 @@ CPed::OurPedCanSeeThisOne(CEntity *target) // Check if target is behind ped if (DotProduct2D(dist, CVector2D(this->GetForward())) < 0.0f) - return 0; + return false; // Check if target is too far away - if (dist.Magnitude() < 40.0f) - return 0; + if (dist.Magnitude() >= 40.0f) + return false; // Check line of sight from head CVector headPos = this->GetPosition(); From a91f40e79daff5ecf620fe892b0ddc30da6a2895 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 26 Jun 2019 16:49:32 +0200 Subject: [PATCH 15/17] CStreaming streams --- src/Streaming.cpp | 399 ++++++++++++++++++++++++++++++++++------------ src/Streaming.h | 18 ++- 2 files changed, 307 insertions(+), 110 deletions(-) diff --git a/src/Streaming.cpp b/src/Streaming.cpp index 14582e0c..62451526 100644 --- a/src/Streaming.cpp +++ b/src/Streaming.cpp @@ -23,7 +23,7 @@ CStreamingInfo &CStreaming::ms_startRequestedList = *(CStreamingInfo*)0x8F1B3C; CStreamingInfo &CStreaming::ms_endRequestedList = *(CStreamingInfo*)0x940738; int32 &CStreaming::ms_oldSectorX = *(int32*)0x8F2C84; int32 &CStreaming::ms_oldSectorY = *(int32*)0x8F2C88; -uint32 &CStreaming::ms_streamingBufferSize = *(uint32*)0x942FB0; +int32 &CStreaming::ms_streamingBufferSize = *(int32*)0x942FB0; int8 **CStreaming::ms_pStreamingBuffer = (int8**)0x87F818; int32 &CStreaming::ms_memoryUsed = *(int32*)0x940568; CStreamingChannel *CStreaming::ms_channel = (CStreamingChannel*)0x727EE0; @@ -240,7 +240,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){ dot = strchr(direntry.name, '.'); if(dot) *dot = '\0'; - if(direntry.size > ms_streamingBufferSize) + if(direntry.size > (uint32)ms_streamingBufferSize) ms_streamingBufferSize = direntry.size; if(strcmp(dot+1, "DFF") == 0 || strcmp(dot+1, "dff") == 0){ @@ -490,7 +490,7 @@ CStreaming::RequestModel(int32 id, int32 flags) if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_INQUEUE){ // updgrade to priority - if(flags & STREAMFLAGS_PRIORITY && (ms_aInfoForModel[id].m_flags & STREAMFLAGS_PRIORITY) == 0){ + if(flags & STREAMFLAGS_PRIORITY && !ms_aInfoForModel[id].IsPriority()){ ms_numPriorityRequests++; ms_aInfoForModel[id].m_flags |= STREAMFLAGS_PRIORITY; } @@ -653,6 +653,16 @@ CStreaming::RequestSpecialChar(int32 charId, const char *modelName, int32 flags) RequestSpecialModel(charId + MI_SPECIAL01, modelName, flags); } +void +CStreaming::DecrementRef(int32 id) +{ + ms_numModelsRequested--; + if(ms_aInfoForModel[id].IsPriority()){ + ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_PRIORITY; + ms_numPriorityRequests--; + } +} + void CStreaming::RemoveModel(int32 id) { @@ -671,13 +681,8 @@ CStreaming::RemoveModel(int32 id) if(ms_aInfoForModel[id].m_next){ // Remove from list, model is neither loaded nor requested - if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_INQUEUE){ - ms_numModelsRequested--; - if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_PRIORITY){ - ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_PRIORITY; - ms_numPriorityRequests--; - } - } + if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_INQUEUE) + DecrementRef(id); ms_aInfoForModel[id].RemoveFromList(); }else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_READING){ for(i = 0; i < 4; i++){ @@ -1120,7 +1125,223 @@ CStreaming::LoadInitialVehicles(void) } +// Find starting offset of the cdimage we next want to read +// Not useful at all on PC... +int32 +CStreaming::GetCdImageOffset(int32 lastPosn) +{ + int offset, off; + int i, img; + int dist, mindist; + img = -1; + mindist = INT_MAX; + offset = ms_imageOffsets[ms_lastImageRead]; + if(lastPosn <= offset || lastPosn > offset + ms_imageSize){ + // last read position is not in last image + for(i = 0; i < NUMCDIMAGES; i++){ + off = ms_imageOffsets[i]; + if(off == -1) continue; + if((uint32)lastPosn > (uint32)off) + // after start of image, get distance from end + // negative if before end! + dist = lastPosn - (off + ms_imageSize); + else + // before image, get offset to start + // this will never be negative + dist = off - lastPosn; + if(dist < mindist){ + img = i; + mindist = dist; + } + } + assert(img >= 0); + offset = ms_imageOffsets[img]; + ms_lastImageRead = img; + } + return offset; +} + +inline bool +TxdAvailable(int32 txdId) +{ + CStreamingInfo *si = &CStreaming::ms_aInfoForModel[txdId + STREAM_OFFSET_TXD]; + return si->m_loadState == STREAMSTATE_LOADED || si->m_loadState == STREAMSTATE_READING; +} + +// Find stream id of next requested file in cdimage +int32 +CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority) +{ + CStreamingInfo *si, *next; + int streamId; + uint32 posn, size; + int streamIdFirst, streamIdNext; + uint32 posnFirst, posnNext; + + streamIdFirst = -1; + streamIdNext = -1; + posnFirst = UINT_MAX; + posnNext = UINT_MAX; + + for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){ + next = si->m_next; + streamId = si - ms_aInfoForModel; + + // only priority requests if there are any + if(priority && ms_numPriorityRequests != 0 && !si->IsPriority()) + continue; + + // request Txd if necessary + if(streamId < STREAM_OFFSET_TXD && + !TxdAvailable(CModelInfo::GetModelInfo(streamId)->GetTxdSlot())){ + ReRequestTxd(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()); + }else if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){ + if(posn < posnFirst){ + // find first requested file in image + streamIdFirst = streamId; + posnFirst = posn; + } + if(posn < posnNext && posn >= (uint32)lastPosn){ + // find first requested file after last read position + streamIdNext = streamId; + posnNext = posn; + } + }else{ + // empty file + DecrementRef(streamId); + si->RemoveFromList(); + si->m_loadState = STREAMSTATE_LOADED; + } + } + + // wrap around + if(streamIdNext == -1) + streamIdNext = streamIdFirst; + + if(streamIdNext == -1 && ms_numPriorityRequests != 0){ + // try non-priority files + ms_numPriorityRequests = 0; + streamIdNext = GetNextFileOnCd(lastPosn, false); + } + + return streamIdNext; +} + +/* + * Streaming buffer size is half of the largest file. + * Files larger than the buffer size can only be loaded by channel 0, + * which then uses both buffers, while channel 1 is idle. + * ms_bLoadingBigModel is set to true to indicate this state. + * + * TODO: two-part files + */ + +// Make channel read from disc +void +CStreaming::RequestModelStream(int32 ch) +{ + int lastPosn, imgOffset, streamId; + int totalSize; + uint32 posn, size, unused; + int i; + int haveBigFile, havePed; + + lastPosn = CdStreamGetLastPosn(); + imgOffset = GetCdImageOffset(lastPosn); + streamId = GetNextFileOnCd(lastPosn - imgOffset, true); + + if(streamId == -1) + return; + + // remove Txds that aren't requested anymore + while(streamId >= STREAM_OFFSET_TXD){ + if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY || + IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)) + break; + RemoveModel(streamId); + // so try next file + ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size); + streamId = GetNextFileOnCd(posn + size, true); + } + + if(streamId == -1) + return; + + ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size); + if(size > (uint32)ms_streamingBufferSize){ + // Can only load big models on channel 0, and 1 has to be idle + if(ch == 1 || ms_channel[1].state != CHANNELSTATE_IDLE) + return; + ms_bLoadingBigModel = true; + } + + // Load up to 4 adjacent files + haveBigFile = 0; + havePed = 0; + totalSize = 0; + for(i = 0; i < 4; i++){ + // no more files we can read + if(streamId == -1 || ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_INQUEUE) + break; + + // also stop at non-priority files + ms_aInfoForModel[streamId].GetCdPosnAndSize(unused, size); + if(ms_numPriorityRequests != 0 && !ms_aInfoForModel[streamId].IsPriority()) + break; + + // Can't load certain combinations of files together + if(streamId < STREAM_OFFSET_TXD){ + if(havePed && CModelInfo::GetModelInfo(streamId)->m_type == MITYPE_PED || + haveBigFile && CModelInfo::GetModelInfo(streamId)->m_type == MITYPE_VEHICLE || + !TxdAvailable(CModelInfo::GetModelInfo(streamId)->GetTxdSlot())) + break; + }else{ + if(haveBigFile && size > 200) + break; + } + + // Now add the file + ms_channel[ch].streamIds[i] = streamId; + ms_channel[ch].offsets[i] = totalSize; + totalSize += size; + + // To big for buffer, remove again + if(totalSize > ms_streamingBufferSize && i > 0){ + totalSize -= size; + break; + } + if(streamId < STREAM_OFFSET_TXD){ + if(CModelInfo::GetModelInfo(streamId)->m_type == MITYPE_PED) + havePed = 1; + if(CModelInfo::GetModelInfo(streamId)->m_type == MITYPE_VEHICLE) + haveBigFile = 1; + }else{ + if(size > 200) + haveBigFile = 1; + } + ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_READING; + ms_aInfoForModel[streamId].RemoveFromList(); + DecrementRef(streamId); + + streamId = ms_aInfoForModel[streamId].m_nextID; + } + + // clear remaining slots + for(; i < 4; i++) + ms_channel[ch].streamIds[i] = -1; + // Now read the data + assert(!(ms_bLoadingBigModel && ch == 1)); // this would clobber the buffer + if(CdStreamRead(ch, ms_pStreamingBuffer[ch], imgOffset+posn, totalSize) == STREAM_NONE) + debug("FUCKFUCKFUCK\n"); + ms_channel[ch].state = CHANNELSTATE_READING; + ms_channel[ch].field24 = 0; + ms_channel[ch].size = totalSize; + ms_channel[ch].position = imgOffset+posn; + ms_channel[ch].numTries = 0; +} + +// Load data previously read from disc bool CStreaming::ProcessLoadingChannel(int32 ch) { @@ -1192,75 +1413,81 @@ CStreaming::ProcessLoadingChannel(int32 ch) return true; } -inline bool -TxdAvailable(int32 txdId) +void +CStreaming::LoadRequestedModels(void) { - CStreamingInfo *si = &CStreaming::ms_aInfoForModel[txdId + STREAM_OFFSET_TXD]; - return si->m_loadState == STREAMSTATE_LOADED || si->m_loadState == STREAMSTATE_READING; + static int currentChannel = 0; + + // We can't read with channel 1 while channel 0 is using its buffer + if(ms_bLoadingBigModel) + currentChannel = 0; + + // We have data, load + if(ms_channel[currentChannel].state == CHANNELSTATE_READING || + ms_channel[currentChannel].state == CHANNELSTATE_STARTED) + ProcessLoadingChannel(currentChannel); + + if(ms_channelError == -1){ + // Channel is idle, read more data + if(ms_channel[currentChannel].state == CHANNELSTATE_IDLE) + RequestModelStream(currentChannel); + // Switch channel + if(ms_channel[currentChannel].state != CHANNELSTATE_STARTED) + currentChannel = 1 - currentChannel; + } } -// Find stream id of next requested file in cdimage -int32 -CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority) +void +CStreaming::LoadAllRequestedModels(bool priority) { - CStreamingInfo *si, *next; - int streamId; + static bool bInsideLoadAll = false; + int imgOffset, streamId, status; + int i; uint32 posn, size; - int streamIdFirst, streamIdNext; - uint32 posnFirst, posnNext; - streamIdFirst = -1; - streamIdNext = -1; - posnFirst = UINT_MAX; - posnNext = UINT_MAX; + if(bInsideLoadAll) + return; - for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){ - next = si->m_next; - streamId = si - ms_aInfoForModel; + FlushChannels(); + imgOffset = GetCdImageOffset(CdStreamGetLastPosn()); - // only priority requests if there are any - if(priority && ms_numPriorityRequests != 0 && - (si->m_flags & STREAMFLAGS_PRIORITY) == 0) - continue; + while(ms_endRequestedList.m_prev != &ms_startRequestedList){ + streamId = GetNextFileOnCd(0, priority); + if(streamId == -1) + break; - // request Txd if necessary - if(streamId < STREAM_OFFSET_TXD && - !TxdAvailable(CModelInfo::GetModelInfo(streamId)->GetTxdSlot())){ - ReRequestTxd(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()); - }else if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){ - if(posn < posnFirst){ - // find first requested file in image - streamIdFirst = streamId; - posnFirst = posn; - } - if(posn < posnNext && posn >= (uint32)lastPosn){ - // find first requested file after last read position - streamIdNext = streamId; - posnNext = posn; + ms_aInfoForModel[streamId].RemoveFromList(); + DecrementRef(streamId); + + if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){ + do + status = CdStreamRead(0, ms_pStreamingBuffer[0], imgOffset+posn, size); + while(CdStreamSync(0) || status == STREAM_NONE); + ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_READING; + + MakeSpaceFor(size * CDSTREAM_SECTOR_SIZE); + ConvertBufferToObject(ms_pStreamingBuffer[0], streamId); + if(ms_aInfoForModel[streamId].m_loadState == STREAMSTATE_STARTED) + FinishLoadingLargeFile(ms_pStreamingBuffer[0], streamId); + + if(streamId < STREAM_OFFSET_TXD){ + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamId); + if(mi->IsSimple()) + mi->m_alpha = 255; } }else{ - // empty file - ms_numModelsRequested--; - if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_PRIORITY){ - ms_aInfoForModel[streamId].m_flags &= ~STREAMFLAGS_PRIORITY; - ms_numPriorityRequests--; - } - si->RemoveFromList(); - si->m_loadState = STREAMSTATE_LOADED; + // empty + ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; } } - // wrap around - if(streamIdNext == -1) - streamIdNext = streamIdFirst; - - if(streamIdNext == -1 && ms_numPriorityRequests){ - // try non-priority files - ms_numPriorityRequests = 0; - streamIdNext = GetNextFileOnCd(lastPosn, false); + ms_bLoadingBigModel = false; + for(i = 0; i < 4; i++){ + ms_channel[1].streamIds[i] = -1; + ms_channel[1].offsets[i] = -1; } - - return streamIdNext; + ms_channel[1].state = CHANNELSTATE_IDLE; + bInsideLoadAll = false; } void @@ -1269,14 +1496,14 @@ CStreaming::FlushChannels(void) if(ms_channel[1].state == CHANNELSTATE_STARTED) ProcessLoadingChannel(1); - if(ms_channel[0].state == CHANNELSTATE_UNK1){ + if(ms_channel[0].state == CHANNELSTATE_READING){ CdStreamSync(0); ProcessLoadingChannel(0); } if(ms_channel[0].state == CHANNELSTATE_STARTED) ProcessLoadingChannel(0); - if(ms_channel[1].state == CHANNELSTATE_UNK1){ + if(ms_channel[1].state == CHANNELSTATE_READING){ CdStreamSync(1); ProcessLoadingChannel(1); } @@ -1296,43 +1523,6 @@ CStreaming::FlushRequestList(void) FlushChannels(); } -// Find starting offset of the cdimage we next want to read -// Not useful at all on PC... -int32 -CStreaming::GetCdImageOffset(int32 lastPosn) -{ - int offset, off; - int i, img; - int dist, mindist; - - img = -1; - mindist = INT_MAX; - offset = ms_imageOffsets[ms_lastImageRead]; - if(lastPosn <= offset || lastPosn > offset + ms_imageSize){ - // last read position is not in last image - for(i = 0; i < NUMCDIMAGES; i++){ - off = ms_imageOffsets[i]; - if(off == -1) continue; - if((uint32)lastPosn > (uint32)off) - // after start of image, get distance from end - // negative if before end! - dist = lastPosn - (off + ms_imageSize); - else - // before image, get offset to start - // this will never be negative - dist = off - lastPosn; - if(dist < mindist){ - img = i; - mindist = dist; - } - } - assert(img >= 0); - offset = ms_imageOffsets[img]; - ms_lastImageRead = img; - } - return offset; -} - void CStreaming::ImGonnaUseStreamingMemory(void) @@ -1431,6 +1621,9 @@ STARTPATCHES InjectHook(0x40A680, CStreaming::FlushRequestList, PATCH_JUMP); InjectHook(0x409FF0, CStreaming::GetCdImageOffset, PATCH_JUMP); InjectHook(0x409E50, CStreaming::GetNextFileOnCd, PATCH_JUMP); + InjectHook(0x40A060, CStreaming::RequestModelStream, PATCH_JUMP); + InjectHook(0x40A390, CStreaming::LoadRequestedModels, PATCH_JUMP); + InjectHook(0x40A440, CStreaming::LoadAllRequestedModels, PATCH_JUMP); InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP); InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP); diff --git a/src/Streaming.h b/src/Streaming.h index 62d0c2fb..571a7194 100644 --- a/src/Streaming.h +++ b/src/Streaming.h @@ -24,14 +24,14 @@ enum StreamLoadState STREAMSTATE_NOTLOADED = 0, STREAMSTATE_LOADED = 1, STREAMSTATE_INQUEUE = 2, - STREAMSTATE_READING = 3, // what is this? - STREAMSTATE_STARTED = 4, // first part read + STREAMSTATE_READING = 3, // channel is reading + STREAMSTATE_STARTED = 4, // first part loaded }; enum ChannelState { CHANNELSTATE_IDLE = 0, - CHANNELSTATE_UNK1 = 1, + CHANNELSTATE_READING = 1, CHANNELSTATE_STARTED = 2, CHANNELSTATE_ERROR = 3, }; @@ -53,6 +53,7 @@ public: void AddToList(CStreamingInfo *link); void RemoveFromList(void); uint32 GetCdSize(void) { return m_size; } + bool IsPriority(void) { return !!(m_flags & STREAMFLAGS_PRIORITY); } }; struct CStreamingChannel @@ -63,7 +64,7 @@ struct CStreamingChannel int32 field24; int32 position; int32 size; - int32 field30; + int32 numTries; int32 status; // from CdStream }; @@ -83,7 +84,7 @@ public: static CStreamingInfo &ms_endRequestedList; static int32 &ms_oldSectorX; static int32 &ms_oldSectorY; - static uint32 &ms_streamingBufferSize; + static int32 &ms_streamingBufferSize; static int8 **ms_pStreamingBuffer; //[2] static int32 &ms_memoryUsed; static CStreamingChannel *ms_channel; //[2] @@ -118,6 +119,7 @@ public: static void RequestIslands(eLevelName level); static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags); static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags); + static void DecrementRef(int32 id); static void RemoveModel(int32 id); static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); } static void RemoveUnusedBuildings(eLevelName level); @@ -139,12 +141,14 @@ public: static void SetModelTxdIsDeletable(int32 id); static void SetMissionDoesntRequireModel(int32 id); + static int32 GetCdImageOffset(int32 lastPosn); static int32 GetNextFileOnCd(int32 position, bool priority); - static bool ProcessLoadingChannel(int32 ch); static void RequestModelStream(int32 ch); + static bool ProcessLoadingChannel(int32 ch); + static void LoadRequestedModels(void); + static void LoadAllRequestedModels(bool priority); static void FlushChannels(void); static void FlushRequestList(void); - static int32 GetCdImageOffset(int32 lastPosn); static void MakeSpaceFor(int32 size); static void ImGonnaUseStreamingMemory(void); From d9b3c82c5e43ef3cc271800ccd0fc79ead99c7b7 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 26 Jun 2019 21:33:58 +0200 Subject: [PATCH 16/17] some more CStreaming + fixes by erorcun --- src/Streaming.cpp | 67 ++++++++++++++++++++++++++++++++++++-------- src/Streaming.h | 1 + src/Timer.h | 7 +++-- src/entities/Ped.cpp | 2 +- 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/Streaming.cpp b/src/Streaming.cpp index 62451526..0f5b7262 100644 --- a/src/Streaming.cpp +++ b/src/Streaming.cpp @@ -1,5 +1,8 @@ #include "common.h" #include "patcher.h" +#include "Pad.h" +#include "Hud.h" +#include "Text.h" #include "ModelInfo.h" #include "TxdStore.h" #include "ModelIndices.h" @@ -75,6 +78,8 @@ CStreaming::Init(void) ms_aInfoForModel[i].m_position = 0; } + ms_channelError = -1; + // init lists ms_startLoadedList.m_next = &ms_endLoadedList; @@ -882,13 +887,13 @@ CStreaming::RemoveLeastUsedModel(void) for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){ streamId = si - ms_aInfoForModel; if(streamId < STREAM_OFFSET_TXD){ - if(CTxdStore::GetNumRefs(streamId - STREAM_OFFSET_TXD) == 0 && - !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){ + if(CModelInfo::GetModelInfo(streamId)->m_refCount == 0){ RemoveModel(streamId); return true; } }else{ - if(CModelInfo::GetModelInfo(streamId)->m_refCount == 0){ + if(CTxdStore::GetNumRefs(streamId - STREAM_OFFSET_TXD) == 0 && + !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){ RemoveModel(streamId); return true; } @@ -948,7 +953,7 @@ CStreaming::IsTxdUsedByRequestedModels(int32 txdId) int streamId; int i; - for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = si->m_prev){ + for(si = ms_startRequestedList.m_next; si != &ms_startRequestedList; si = si->m_next){ streamId = si - ms_aInfoForModel; if(streamId < STREAM_OFFSET_TXD && CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId) @@ -1074,8 +1079,8 @@ void CStreaming::SetModelIsDeletable(int32 id) { ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_DONT_REMOVE; - if(id >= STREAM_OFFSET_TXD || - CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && ms_aInfoForModel[id].m_flags & STREAMFLAGS_SCRIPTOWNED){ + if((id >= STREAM_OFFSET_TXD || CModelInfo::GetModelInfo(id)->m_type != MITYPE_VEHICLE) && + (ms_aInfoForModel[id].m_flags & STREAMFLAGS_SCRIPTOWNED) == 0){ if(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED) RemoveModel(id); else if(ms_aInfoForModel[id].m_next == nil) @@ -1093,8 +1098,8 @@ void CStreaming::SetMissionDoesntRequireModel(int32 id) { ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_SCRIPTOWNED; - if(id >= STREAM_OFFSET_TXD || - CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && ms_aInfoForModel[id].m_flags & STREAMFLAGS_DONT_REMOVE){ + if((id >= STREAM_OFFSET_TXD || CModelInfo::GetModelInfo(id)->m_type != MITYPE_VEHICLE) && + (ms_aInfoForModel[id].m_flags & STREAMFLAGS_DONT_REMOVE) == 0){ if(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED) RemoveModel(id); else if(ms_aInfoForModel[id].m_next == nil) @@ -1375,7 +1380,7 @@ CStreaming::ProcessLoadingChannel(int32 ch) if(id < STREAM_OFFSET_TXD && CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && ms_numVehiclesLoaded >= desiredNumVehiclesLoaded && - RemoveLoadedVehicle() && + !RemoveLoadedVehicle() && ((ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 || GetAvailableVehicleSlot() == -1)){ // can't load vehicle RemoveModel(id); @@ -1403,16 +1408,53 @@ CStreaming::ProcessLoadingChannel(int32 ch) if(ms_bLoadingBigModel && ms_channel[ch].state != CHANNELSTATE_STARTED){ ms_bLoadingBigModel = false; // reset channel 1 after loading a big model - for(i = 0; i < 4; i++){ + for(i = 0; i < 4; i++) ms_channel[1].streamIds[i] = -1; - ms_channel[1].offsets[i] = -1; - } ms_channel[1].state = CHANNELSTATE_IDLE; } return true; } +void +CStreaming::RetryLoadFile(int32 ch) +{ + char *key; + + CPad::StopPadsShaking(); + + if(ms_channel[ch].numTries >= 3){ + switch(ms_channel[ch].status){ + case STREAM_ERROR_NOCD: key = "NOCD"; break; + case STREAM_ERROR_OPENCD: key = "OPENCD"; break; + case STREAM_ERROR_WRONGCD: key = "WRONGCD"; break; + default: key = "CDERROR"; break; + } + CHud::SetMessage(TheText.Get(key)); + CTimer::SetCodePause(true); + } + + switch(ms_channel[ch].state){ + case CHANNELSTATE_IDLE: +streamread: + CdStreamRead(ch, ms_pStreamingBuffer[ch], ms_channel[ch].position, ms_channel[ch].size); + ms_channel[ch].state = CHANNELSTATE_READING; + ms_channel[ch].field24 = -600; + break; + case CHANNELSTATE_READING: + if(ProcessLoadingChannel(ch)){ + ms_channelError = -1; + CTimer::SetCodePause(false); + } + break; + case CHANNELSTATE_ERROR: + ms_channel[ch].numTries++; + if(CdStreamGetStatus(ch) != STREAM_READING && CdStreamGetStatus(ch) != STREAM_WAITING) + goto streamread; + break; + } +} + void CStreaming::LoadRequestedModels(void) { @@ -1622,6 +1664,7 @@ STARTPATCHES InjectHook(0x409FF0, CStreaming::GetCdImageOffset, PATCH_JUMP); InjectHook(0x409E50, CStreaming::GetNextFileOnCd, PATCH_JUMP); InjectHook(0x40A060, CStreaming::RequestModelStream, PATCH_JUMP); + InjectHook(0x4077F0, CStreaming::RetryLoadFile, PATCH_JUMP); InjectHook(0x40A390, CStreaming::LoadRequestedModels, PATCH_JUMP); InjectHook(0x40A440, CStreaming::LoadAllRequestedModels, PATCH_JUMP); diff --git a/src/Streaming.h b/src/Streaming.h index 571a7194..75d53dcd 100644 --- a/src/Streaming.h +++ b/src/Streaming.h @@ -145,6 +145,7 @@ public: static int32 GetNextFileOnCd(int32 position, bool priority); static void RequestModelStream(int32 ch); static bool ProcessLoadingChannel(int32 ch); + static void RetryLoadFile(int32 ch); static void LoadRequestedModels(void); static void LoadAllRequestedModels(bool priority); static void FlushChannels(void); diff --git a/src/Timer.h b/src/Timer.h index c3269d60..ff532050 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -20,9 +20,10 @@ public: static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; } static uint32 GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; } - static inline bool GetIsPaused() { return m_UserPause || m_CodePause; } - static inline bool GetIsUserPaused() { return m_UserPause; } - static inline void SetTimeScale(float ts) { ms_fTimeScale = ts; } + static bool GetIsPaused() { return m_UserPause || m_CodePause; } + static bool GetIsUserPaused() { return m_UserPause; } + static void SetTimeScale(float ts) { ms_fTimeScale = ts; } + static void SetCodePause(bool pause) { m_CodePause = pause; } static void Initialise(void); static void Shutdown(void); diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index a80fc770..5a4c736e 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -608,7 +608,7 @@ CPed::IsPedHeadAbovePos(float zOffset) RwMatrix mat; CPedIK::GetWorldMatrix(GetNodeFrame(PED_HEAD), &mat); - return zOffset + GetPosition().z >= mat.pos.z; + return zOffset + GetPosition().z < RwMatrixGetPos(&mat)->z; } void From 50cce3e586381369cf8bbf2707574700b1d70b17 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 26 Jun 2019 21:46:55 +0200 Subject: [PATCH 17/17] bla --- src/Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Streaming.cpp b/src/Streaming.cpp index 0f5b7262..0dc64d62 100644 --- a/src/Streaming.cpp +++ b/src/Streaming.cpp @@ -953,7 +953,7 @@ CStreaming::IsTxdUsedByRequestedModels(int32 txdId) int streamId; int i; - for(si = ms_startRequestedList.m_next; si != &ms_startRequestedList; si = si->m_next){ + for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = si->m_next){ streamId = si - ms_aInfoForModel; if(streamId < STREAM_OFFSET_TXD && CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId)