diff options
Diffstat (limited to '')
-rw-r--r-- | src/render/Clouds.cpp | 14 | ||||
-rw-r--r-- | src/render/Coronas.cpp | 4 | ||||
-rw-r--r-- | src/render/Fluff.cpp | 4 | ||||
-rw-r--r-- | src/render/Hud.cpp | 275 | ||||
-rw-r--r-- | src/render/Hud.h | 69 | ||||
-rw-r--r-- | src/render/MBlur.cpp | 3 | ||||
-rw-r--r-- | src/render/PlayerSkin.cpp (renamed from src/core/PlayerSkin.cpp) | 345 | ||||
-rw-r--r-- | src/render/PlayerSkin.h (renamed from src/core/PlayerSkin.h) | 6 | ||||
-rw-r--r-- | src/render/Renderer.h | 2 | ||||
-rw-r--r-- | src/render/Rubbish.cpp | 422 | ||||
-rw-r--r-- | src/render/Rubbish.h | 39 | ||||
-rw-r--r-- | src/render/Shadows.h | 11 | ||||
-rw-r--r-- | src/render/Skidmarks.cpp | 247 | ||||
-rw-r--r-- | src/render/Skidmarks.h | 26 | ||||
-rw-r--r-- | src/render/SpecialFX.cpp | 657 | ||||
-rw-r--r-- | src/render/SpecialFX.h | 228 | ||||
-rw-r--r-- | src/render/Sprite.cpp | 12 | ||||
-rw-r--r-- | src/render/Sprite2d.cpp | 30 | ||||
-rw-r--r-- | src/render/TexList.cpp | 41 | ||||
-rw-r--r-- | src/render/TexList.h | 14 | ||||
-rw-r--r-- | src/render/Timecycle.h | 3 | ||||
-rw-r--r-- | src/render/Weather.cpp | 470 | ||||
-rw-r--r-- | src/render/Weather.h | 22 | ||||
-rw-r--r-- | src/rw/Lights.cpp (renamed from src/render/Lights.cpp) | 0 | ||||
-rw-r--r-- | src/rw/Lights.h (renamed from src/render/Lights.h) | 0 | ||||
-rw-r--r-- | src/rw/VisibilityPlugins.cpp (renamed from src/render/VisibilityPlugins.cpp) | 2 | ||||
-rw-r--r-- | src/rw/VisibilityPlugins.h (renamed from src/render/VisibilityPlugins.h) | 0 |
27 files changed, 2469 insertions, 477 deletions
diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 2884894c..39866294 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -87,7 +87,7 @@ CClouds::Render(void) RwV3d pos = { 0.0f, -100.0f, 15.0f }; RwV3dAdd(&worldpos, &campos, &pos); if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){ - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[2]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2])); if(CCoronas::bSmallMoon){ szx *= 4.0f; szy *= 4.0f; @@ -116,7 +116,7 @@ CClouds::Render(void) static float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f }; static float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f }; int brightness = (1.0f - coverage) * starintens; - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0])); for(i = 0; i < 11; i++){ RwV3d pos = { 100.0f, 0.0f, 10.0f }; if(i >= 9) pos.x = -pos.x; @@ -132,7 +132,7 @@ CClouds::Render(void) CSprite::FlushSpriteBuffer(); // * - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0])); RwV3d pos = { 100.0f, 0.0f, 10.0f }; RwV3dAdd(&worldpos, &campos, &pos); worldpos.y -= 90.0f; @@ -156,7 +156,7 @@ CClouds::Render(void) int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity; for(int cloudtype = 0; cloudtype < 3; cloudtype++){ for(i = cloudtype; i < 12; i += 3){ - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[cloudtype]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[cloudtype])); RwV3d pos = { 800.0f*LowCloudsX[i], 800.0f*LowCloudsY[i], 60.0f*LowCloudsZ[i] }; worldpos.x = campos.x + pos.x; worldpos.y = campos.y + pos.y; @@ -202,7 +202,7 @@ CClouds::Render(void) RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[4]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[4])); for(i = 0; i < 37; i++){ RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f }; worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x; @@ -244,7 +244,7 @@ CClouds::Render(void) // Highlights RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[3]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[3])); for(i = 0; i < 37; i++){ RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f }; @@ -269,7 +269,7 @@ CClouds::Render(void) static uint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 }; static uint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 }; static uint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 }; - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0])); for(i = 0; i < 6; i++){ RwV3d pos = { i*1.5f, 100.0f, 5.0f }; RwV3dAdd(&worldpos, &campos, &pos); diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index c934540b..68994b0b 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -320,7 +320,7 @@ CCoronas::Render(void) CSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z, spritew * aCoronas[i].size * wscale, - spriteh * SCREEN_SCALE_AR2(aCoronas[i].size * fogscale * hscale), + spriteh * aCoronas[i].size * fogscale * hscale, CCoronas::aCoronas[i].red / fogscale, CCoronas::aCoronas[i].green / fogscale, CCoronas::aCoronas[i].blue / fogscale, @@ -331,7 +331,7 @@ CCoronas::Render(void) CSprite::RenderOneXLUSprite_Rotate_Aspect( spriteCoors.x, spriteCoors.y, spriteCoors.z, spritew * aCoronas[i].size * fogscale, - spriteh * SCREEN_SCALE_AR2(aCoronas[i].size * fogscale), + spriteh * aCoronas[i].size * fogscale, CCoronas::aCoronas[i].red / fogscale, CCoronas::aCoronas[i].green / fogscale, CCoronas::aCoronas[i].blue / fogscale, diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 8d7fad92..e2899532 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -755,14 +755,14 @@ void CTowerClock::Render() &TempV[1], m_Position.x + Sin(angleMinute) * m_fScale * m_Size.x, m_Position.y + Sin(angleMinute) * m_fScale * m_Size.y, - m_Position.z + Cos(angleMinute) * m_fScale; + m_Position.z + Cos(angleMinute) * m_fScale ); RwIm3DVertexSetPos(&TempV[2], m_Position.x, m_Position.y, m_Position.z); RwIm3DVertexSetPos( &TempV[3], m_Position.x + Sin(angleHour) * 0.75f * m_fScale * m_Size.x, m_Position.y + Sin(angleHour) * 0.75f * m_fScale * m_Size.y, - m_Position.z + Cos(angleHour) * 0.75f * m_fScale; + m_Position.z + Cos(angleHour) * 0.75f * m_fScale ); LittleTest(); diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 3c07039c..56a024a7 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -23,55 +23,47 @@ //wchar *CHud::m_HelpMessage = (wchar*)0x86B888; //wchar *CHud::m_LastHelpMessage = (wchar*)0x6E8F28; -wchar CHud::m_HelpMessage[256]; -wchar CHud::m_LastHelpMessage[256]; - -int32 &CHud::m_HelpMessageState = *(int32*)0x880E1C; -int32 &CHud::m_HelpMessageTimer = *(int32*)0x880FA4; -int32 &CHud::m_HelpMessageFadeTimer = *(int32*)0x8F6258; -wchar *CHud::m_HelpMessageToPrint = (wchar*)0x664480; -float &CHud::m_HelpMessageDisplayTime = *(float*)0x8E2C28; -float &CHud::m_fTextBoxNumLines = *(float*)0x8E2C28; -float &CHud::m_fHelpMessageTime = *(float *)0x8E2C28; -bool &CHud::m_HelpMessageQuick = *(bool *)0x95CCF7; -int32 CHud::m_ZoneState = *(int32*)0x8F29AC; +wchar CHud::m_HelpMessageToPrint[256]; // = (wchar*)0x664480; +float CHud::m_fHelpMessageTime; // *(float *)0x8E2C28; +bool CHud::m_HelpMessageQuick; // = *(bool*)0x95CCF7; +uint32 CHud::m_ZoneState; // = *(int32*)0x8F29AC; int32 CHud::m_ZoneFadeTimer; -int32 CHud::m_ZoneNameTimer = *(int32*)0x8F1A50; -wchar *&CHud::m_pZoneName = *(wchar **)0x8E2C2C; -wchar *CHud::m_pLastZoneName = (wchar*)0x8F432C; +uint32 CHud::m_ZoneNameTimer; // = *(int32*)0x8F1A50; +wchar *CHud::m_pZoneName; // = *(wchar**)0x8E2C2C; +wchar *CHud::m_pLastZoneName; // = (wchar*)0x8F432C; wchar *CHud::m_ZoneToPrint; -int32 CHud::m_VehicleState = *(int32*)0x940560; +uint32 CHud::m_VehicleState; // = *(int32*)0x940560; int32 CHud::m_VehicleFadeTimer; -int32 CHud::m_VehicleNameTimer = *(int32*)0x8F2A14; -wchar *&CHud::m_VehicleName = *(wchar **)0x942FB4; -wchar *CHud::m_pLastVehicleName = *(wchar **)0x8E2DD8; +uint32 CHud::m_VehicleNameTimer; // = *(int32*)0x8F2A14; +wchar *CHud::m_VehicleName; // = *(wchar**)0x942FB4; +wchar *CHud::m_pLastVehicleName; // = *(wchar**)0x8E2DD8; wchar *CHud::m_pVehicleNameToPrint; -wchar *CHud::m_Message = (wchar*)0x72E318; -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)[6][128] = *(wchar(*)[6][128])*(uintptr*)0x664CE0; -int16 &CHud::m_ItemToFlash = *(int16*)0x95CC82; +wchar CHud::m_Message[256];// = (wchar*)0x72E318; +wchar CHud::m_PagerMessage[256]; // = (wchar*)0x878840; +bool CHud::m_Wants_To_Draw_Hud; // (bool*)0x95CD89; +bool CHud::m_Wants_To_Draw_3dMarkers; // = *(bool*)0x95CD62; +wchar CHud::m_BigMessage[6][128]; // = *(wchar(*)[6][128]) * (uintptr*)0x664CE0; +int16 CHud::m_ItemToFlash; // = *(int16*)0x95CC82; // These aren't really in CHud float CHud::BigMessageInUse[6]; float CHud::BigMessageAlpha[6]; float CHud::BigMessageX[6]; -float &CHud::OddJob2OffTimer = *(float*)0x942FA0; -int8 &CHud::CounterOnLastFrame = *(int8*)0x95CD67; -float &CHud::OddJob2XOffset = *(float*)0x8F1B5C; -int16 &CHud::CounterFlashTimer = *(int16*)0x95CC20; -int16 &CHud::OddJob2Timer = *(int16*)0x95CC52; -int8 &CHud::TimerOnLastFrame = *(int8*)0x95CDA7; -int16 &CHud::OddJob2On = *(int16*)0x95CC78; -int16 &CHud::TimerFlashTimer = *(int16*)0x95CC6C; -int16 &CHud::PagerSoundPlayed = *(int16*)0x95CC4A; -int32 &CHud::SpriteBrightness = *(int32*)0x95CC54; -float &CHud::PagerXOffset = *(float*)0x941590; -int16 &CHud::PagerTimer = *(int16*)0x95CC3A; -int16 &CHud::PagerOn = *(int16*)0x95CCA0; - -CSprite2d *CHud::Sprites = (CSprite2d*)0x95CB9C; +float CHud::OddJob2OffTimer; // = *(float*)0x942FA0; +bool CHud::CounterOnLastFrame; // = *(int8*)0x95CD67; +float CHud::OddJob2XOffset; // = *(float*)0x8F1B5C; +uint16 CHud::CounterFlashTimer; // = *(int16*)0x95CC20; +uint16 CHud::OddJob2Timer; // = *(int16*)0x95CC52; +bool CHud::TimerOnLastFrame; //= *(int8*)0x95CDA7; +int16 CHud::OddJob2On; //= *(int16*)0x95CC78; +uint16 CHud::TimerFlashTimer; //= *(int16*)0x95CC6C; +int16 CHud::PagerSoundPlayed; //= *(int16*)0x95CC4A; +int32 CHud::SpriteBrightness; //= *(int32*)0x95CC54; +float CHud::PagerXOffset; //= *(float*)0x941590; +int16 CHud::PagerTimer; //= *(int16*)0x95CC3A; +int16 CHud::PagerOn; //= *(int16*)0x95CCA0; + +CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; // = (CSprite2d*)0x95CB9C; struct { @@ -93,14 +85,14 @@ struct {"detonator", "detonator_mask"}, {"", ""}, {"", ""}, - {"radardisc", "radardiscm"}, + {"radardisc", "radardisc"}, {"pager", "pagerm"}, {"", ""}, {"", ""}, {"bleeder", ""}, {"sitesniper", "sitesniperm"}, {"siteM16", "siteM16m"}, - {"siterocket", "siterocketm"} + {"siterocket", "siterocket"} }; RwTexture *&gpSniperSightTex = *(RwTexture**)0x8F5834; @@ -418,7 +410,7 @@ void CHud::Draw() DrawZoneName */ if (m_pZoneName) { - float fZoneAlpha = 0.0f; + float fZoneAlpha = 255.0f; if (m_pZoneName != m_pLastZoneName) { switch (m_ZoneState) { @@ -432,7 +424,7 @@ void CHud::Draw() case 2: case 3: case 4: - m_ZoneNameTimer = 0; + m_ZoneNameTimer = 5; m_ZoneState = 4; break; default: @@ -444,6 +436,7 @@ void CHud::Draw() if (m_ZoneState) { switch (m_ZoneState) { case 1: + m_ZoneFadeTimer = 1000; if (m_ZoneNameTimer > 10000) { m_ZoneFadeTimer = 1000; m_ZoneState = 3; @@ -471,7 +464,6 @@ void CHud::Draw() if (m_ZoneFadeTimer < 0) { m_ZoneFadeTimer = 0; m_ZoneToPrint = m_pLastZoneName; - m_ZoneNameTimer = 0; m_ZoneState = 2; } fZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f; @@ -503,12 +495,6 @@ void CHud::Draw() } } } - /*else { - m_pLastZoneName = nil; - m_ZoneState = 0; - m_ZoneFadeTimer = 0; - m_ZoneNameTimer = 0; - }*/ /* DrawVehicleName @@ -636,9 +622,9 @@ void CHud::Draw() wchar sTimer[16]; if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) - TimerOnLastFrame = 0; + TimerOnLastFrame = false; if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed) - CounterOnLastFrame = 0; + CounterOnLastFrame = false; #ifdef FIX_BUGS #define TIMER_RIGHT_OFFSET 34.0f // Taken from VC frenzy timer @@ -650,7 +636,7 @@ void CHud::Draw() if (!TimerOnLastFrame) TimerFlashTimer = 1; - TimerOnLastFrame = 1; + TimerOnLastFrame = true; if (TimerFlashTimer) { if (++TimerFlashTimer > 50) @@ -688,7 +674,7 @@ void CHud::Draw() if (!CounterOnLastFrame) CounterFlashTimer = 1; - CounterOnLastFrame = 1; + CounterOnLastFrame = true; if (CounterFlashTimer) { if (++CounterFlashTimer > 50) @@ -742,11 +728,9 @@ void CHud::Draw() /* DrawPager */ - if (!m_PagerMessage[0]) { - if (PagerOn == 1) { - PagerSoundPlayed = false; - PagerOn = 2; - } + if (!m_PagerMessage[0] && PagerOn == 1) { + PagerSoundPlayed = false; + PagerOn = 2; } if (m_PagerMessage[0] || PagerOn == 2) { if (!PagerOn) { @@ -755,7 +739,7 @@ void CHud::Draw() } if (PagerOn == 1) { if (PagerXOffset > 0.0f) { - float fStep = PagerXOffset * 0.05f; + float fStep = PagerXOffset * 0.1f; if (fStep > 10.0f) fStep = 10.0f; PagerXOffset -= fStep * CTimer::GetTimeStep(); @@ -766,10 +750,10 @@ void CHud::Draw() } } else if (PagerOn == 2) { - float fStep = PagerXOffset * 0.05f; + float fStep = PagerXOffset * 0.1f; if (fStep < 2.0f) fStep = 2.0f; - PagerXOffset += fStep * CTimer::GetTimeStep(); + PagerXOffset += fStep; if (PagerXOffset > 150.0f) { PagerXOffset = 150.0f; PagerOn = 0; @@ -818,9 +802,7 @@ void CHud::Draw() DrawScriptText */ if (!CTimer::GetIsUserPaused()) { - CTextLine* IntroText = CTheScripts::IntroTextLines; - - for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) { + for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) { if (CTheScripts::IntroTextLines[i].m_Text[0] && CTheScripts::IntroTextLines[i].m_bTextBeforeFade) { CFont::SetScale(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fScaleX), SCREEN_SCALE_Y(CTheScripts::IntroTextLines[i].m_fScaleY * 0.5f)); CFont::SetColor(CTheScripts::IntroTextLines[i].m_sColor); @@ -861,31 +843,31 @@ void CHud::Draw() CFont::SetPropOff(); CFont::SetFontStyle(FONTJAP(CTheScripts::IntroTextLines[i].m_nFont)); - CFont::PrintString(SCREEN_SCALE_X(640.0f - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_SCALE_Y(448.0f - CTheScripts::IntroTextLines[i].m_fAtY), IntroText->m_Text); + CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text); } } + for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) { + intro_script_rectangle &IntroRect = CTheScripts::IntroRectangles[i]; - CScriptRectangle* IntroRect = CTheScripts::IntroRectangles; - - for (int i = 0; i < 16; i++) { - if (CTheScripts::IntroRectangles[i].m_bIsUsed && CTheScripts::IntroRectangles[i].m_bBeforeFade) { - if (CTheScripts::IntroRectangles[i].m_nTextureId >= 0) { + // Yeah, top and bottom changed place. R* vision + if (IntroRect.m_bIsUsed && IntroRect.m_bBeforeFade) { + if (IntroRect.m_nTextureId >= 0) { CRect rect = { - CTheScripts::IntroRectangles[i].m_sRect.left, - CTheScripts::IntroRectangles[i].m_sRect.bottom, - CTheScripts::IntroRectangles[i].m_sRect.right, - CTheScripts::IntroRectangles[i].m_sRect.bottom }; + IntroRect.m_sRect.left, + IntroRect.m_sRect.top, + IntroRect.m_sRect.right, + IntroRect.m_sRect.bottom }; - CTheScripts::ScriptSprites[CTheScripts::IntroRectangles[i].m_nTextureId].Draw(rect, IntroRect->m_sColor); + CTheScripts::ScriptSprites[IntroRect.m_nTextureId].Draw(rect, IntroRect.m_sColor); } else { CRect rect = { - CTheScripts::IntroRectangles[i].m_sRect.left, - CTheScripts::IntroRectangles[i].m_sRect.bottom, - CTheScripts::IntroRectangles[i].m_sRect.right, - CTheScripts::IntroRectangles[i].m_sRect.bottom }; + IntroRect.m_sRect.left, + IntroRect.m_sRect.top, + IntroRect.m_sRect.right, + IntroRect.m_sRect.bottom }; - CSprite2d::DrawRect(rect, IntroRect->m_sColor); + CSprite2d::DrawRect(rect, IntroRect.m_sColor); } } } @@ -931,7 +913,7 @@ void CHud::Draw() CFont::SetCentreSize(SCREEN_SCALE_X(615.0f)); CFont::SetFontStyle(FONT_HEADING); - if (BigMessageX[0] >= (SCREEN_WIDTH - 20)) { + if (BigMessageX[0] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { BigMessageInUse[0] += CTimer::GetTimeStep(); if (BigMessageInUse[0] >= 120.0f) { @@ -948,7 +930,7 @@ void CHud::Draw() BigMessageX[0] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); BigMessageAlpha[0] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); - if (BigMessageAlpha[0] >= 255.0f) + if (BigMessageAlpha[0] > 255.0f) BigMessageAlpha[0] = 255.0f; } @@ -992,7 +974,7 @@ void CHud::Draw() CFont::SetFontStyle(FONT_HEADING); CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f + 4.0f), SCREEN_SCALE_FROM_BOTTOM(78.0f), m_BigMessage[2]); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f - 4.0f), SCREEN_SCALE_FROM_BOTTOM(78.0f), m_BigMessage[2]); CFont::SetColor(CRGBA(170, 123, 87, BigMessageAlpha[2])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]); @@ -1021,7 +1003,7 @@ void CHud::DrawAfterFade() m_HelpMessageState = 2; m_HelpMessageTimer = 0; CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256); - m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; + m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; if (TheCamera.m_ScreenReductionPercentage == 0.0f) DMAudio.PlayFrontEndSound(SOUND_A0, 0); @@ -1039,14 +1021,14 @@ void CHud::DrawAfterFade() CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); } - float fAlpha = 255.0f; + float fAlpha = 225.0f; - if (m_HelpMessageState) { + if (m_HelpMessageState != 0) { switch (m_HelpMessageState) { case 1: - fAlpha = 255.0f; + fAlpha = 225.0f; m_HelpMessageFadeTimer = 600; - if (m_HelpMessageTimer > m_fHelpMessageTime * 1000 || m_HelpMessageQuick && m_HelpMessageTimer > 1500) { + if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { m_HelpMessageFadeTimer = 600; m_HelpMessageState = 3; } @@ -1057,24 +1039,24 @@ void CHud::DrawAfterFade() m_HelpMessageState = 1; m_HelpMessageFadeTimer = 0; } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 255.0f; + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; break; case 3: m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer >= 0) { + if (m_HelpMessageFadeTimer < 0) { m_HelpMessageState = 0; m_HelpMessageFadeTimer = 0; } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 255.0f; + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; break; case 4: m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer >= 0) { + if (m_HelpMessageFadeTimer < 0) { m_HelpMessageState = 2; m_HelpMessageFadeTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 400); + CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256); } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 255.0f; + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; break; default: break; @@ -1093,6 +1075,7 @@ void CHud::DrawAfterFade() else CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); + CFont::SetColor(CRGBA(175, 175, 175, 255)); CFont::SetJustifyOff(); if (CFont::LanguageSet == FONT_LANGSET_JAPANESE) CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 26.0f - 4.0f)); @@ -1101,14 +1084,69 @@ void CHud::DrawAfterFade() CFont::SetFontStyle(FONTJAP(FONT_BANK)); CFont::SetBackgroundOn(); CFont::SetBackGroundOnlyTextOff(); - CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.8f)); - CFont::SetColor(CRGBA(175, 175, 175, 255)); + CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f)); CFont::PrintString(SCREEN_SCALE_X(26.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), CHud::m_HelpMessageToPrint); CFont::SetAlphaFade(255.0f); } } - else - m_HelpMessageState = 0; + + for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) { + intro_text_line &line = CTheScripts::IntroTextLines[i]; + if (line.m_Text[0] != '\0' && !line.m_bTextBeforeFade) { + CFont::SetScale(SCREEN_SCALE_X(line.m_fScaleX), SCREEN_SCALE_Y(line.m_fScaleY) / 2); + + CFont::SetColor(line.m_sColor); + if (line.m_bJustify) + CFont::SetJustifyOn(); + else + CFont::SetJustifyOff(); + + if (line.m_bRightJustify) + CFont::SetRightJustifyOn(); + else + CFont::SetRightJustifyOff(); + + if (line.m_bCentered) + CFont::SetCentreOn(); + else + CFont::SetCentreOff(); + + CFont::SetWrapx(SCREEN_SCALE_X(line.m_fWrapX)); + CFont::SetCentreSize(SCREEN_SCALE_X(line.m_fCenterSize)); + if (line.m_bBackground) + CFont::SetBackgroundOn(); + else + CFont::SetBackgroundOff(); + + CFont::SetBackgroundColor(line.m_sBackgroundColor); + if (line.m_bBackgroundOnly) + CFont::SetBackGroundOnlyTextOn(); + else + CFont::SetBackGroundOnlyTextOff(); + + if (line.m_bTextProportional) + CFont::SetPropOn(); + else + CFont::SetPropOff(); + + CFont::SetFontStyle(line.m_nFont); + CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text); + } + } + for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) { + intro_script_rectangle &rectangle = CTheScripts::IntroRectangles[i]; + if (rectangle.m_bIsUsed && !rectangle.m_bBeforeFade) { + + // Yeah, top and bottom changed place. R* vision + if (rectangle.m_nTextureId >= 0) { + CTheScripts::ScriptSprites[rectangle.m_nTextureId].Draw(CRect(rectangle.m_sRect.left, rectangle.m_sRect.bottom, + rectangle.m_sRect.right, rectangle.m_sRect.top), rectangle.m_sColor); + } else { + CSprite2d::DrawRect(CRect(rectangle.m_sRect.left, rectangle.m_sRect.bottom, + rectangle.m_sRect.right, rectangle.m_sRect.top), rectangle.m_sColor); + } + } + } /* DrawBigMessage2 @@ -1150,10 +1188,9 @@ void CHud::DrawAfterFade() if (OddJob2OffTimer > 0) OddJob2OffTimer -= CTimer::GetTimeStepInMilliseconds(); - static float fStep; + float fStep; if (m_BigMessage[5][0] && OddJob2OffTimer <= 0.0f) { - if (OddJob2On <= 3) { - switch (OddJob2On) { + switch (OddJob2On) { case 0: OddJob2On = 1; OddJob2XOffset = 380.0f; @@ -1164,9 +1201,7 @@ void CHud::DrawAfterFade() OddJob2On = 2; } else { - fStep = 40.0f; - if ((OddJob2XOffset / 6.0f) <= 40.0f) - fStep = OddJob2XOffset / 6.0f; + fStep = min(40.0f, OddJob2XOffset / 6.0f); OddJob2XOffset = OddJob2XOffset - fStep; } break; @@ -1177,9 +1212,7 @@ void CHud::DrawAfterFade() } break; case 3: - fStep = 30.0f; - if ((OddJob2XOffset / 5.0f) >= 30.0f) - fStep = OddJob2XOffset / 5.0f; + fStep = max(30.0f, OddJob2XOffset / 5.0f); OddJob2XOffset = OddJob2XOffset - fStep; @@ -1190,7 +1223,6 @@ void CHud::DrawAfterFade() break; default: break; - } } if (!m_BigMessage[1][0]) { @@ -1224,10 +1256,10 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); CFont::SetPropOn(); - CFont::SetRightJustifyWrap(-500.0f); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(-500.0f)); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); - if (BigMessageX[1] >= (SCREEN_WIDTH - 20)) { + if (BigMessageX[1] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { BigMessageInUse[1] += CTimer::GetTimeStep(); if (BigMessageInUse[1] >= 120.0f) { @@ -1238,12 +1270,11 @@ void CHud::DrawAfterFade() m_BigMessage[1][0] = 0; BigMessageAlpha[1] = 0.0f; } - } - else { + } else { BigMessageX[1] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); BigMessageAlpha[1] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); - if (BigMessageAlpha[1] >= 255.0f) + if (BigMessageAlpha[1] > 255.0f) BigMessageAlpha[1] = 255.0f; } @@ -1281,7 +1312,7 @@ void CHud::GetRidOfAllHudMessages() m_HelpMessageFadeTimer = 0; m_HelpMessageState = 0; m_HelpMessageQuick = 0; - m_HelpMessageDisplayTime = 1.0f; + m_fHelpMessageTime = 1.0f; m_VehicleName = nil; m_pLastVehicleName = nil; m_pVehicleNameToPrint = nil; @@ -1311,7 +1342,7 @@ void CHud::Initialise() CTxdStore::PopCurrentTxd(); CTxdStore::SetCurrentTxd(HudTXD); - for (int i = 0; i < ARRAY_SIZE(WeaponFilenames); i++) { + for (int i = 0; i < NUM_HUD_SPRITES; i++) { Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); } @@ -1322,14 +1353,14 @@ void CHud::Initialise() if (gpRocketSightTex == nil) gpRocketSightTex = RwTextureRead("siterocket", nil); - CounterOnLastFrame = 0; + CounterOnLastFrame = false; m_ItemToFlash = ITEM_NONE; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; OddJob2XOffset = 0.0f; CounterFlashTimer = 0; - TimerOnLastFrame = 0; + TimerOnLastFrame = false; TimerFlashTimer = 0; SpriteBrightness = 0; PagerOn = 0; @@ -1346,14 +1377,14 @@ void CHud::ReInitialise() { GetRidOfAllHudMessages(); - CounterOnLastFrame = 0; + CounterOnLastFrame = false; m_ItemToFlash = ITEM_NONE; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; OddJob2XOffset = 0.0f; CounterFlashTimer = 0; - TimerOnLastFrame = 0; + TimerOnLastFrame = false; TimerFlashTimer = 0; SpriteBrightness = 0; PagerOn = 0; @@ -1443,7 +1474,7 @@ void CHud::SetZoneName(wchar *name) void CHud::Shutdown() { - for (int i = 0; i < ARRAY_SIZE(WeaponFilenames); ++i) { + for (int i = 0; i < NUM_HUD_SPRITES; ++i) { Sprites[i].Delete(); } diff --git a/src/render/Hud.h b/src/render/Hud.h index dad3a58d..701e47e2 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -27,59 +27,60 @@ enum eSprites HUD_RADARDISC = 15, HUD_PAGER = 16, HUD_SITESNIPER = 20, - HUD_SITEM16 = 21 + HUD_SITEM16, + HUD_SITEROCKET, + NUM_HUD_SPRITES, }; class CHud { public: - static CSprite2d *Sprites; - static int32 &SpriteBrightness; + static CSprite2d Sprites[NUM_HUD_SPRITES]; static wchar m_HelpMessage[256]; static wchar m_LastHelpMessage[256]; - static int32 &m_HelpMessageState; - static int32 &m_HelpMessageTimer; - static int32 &m_HelpMessageFadeTimer; - static wchar *m_HelpMessageToPrint; + static uint32 m_HelpMessageState; + static uint32 m_HelpMessageTimer; + static int32 m_HelpMessageFadeTimer; + static wchar m_HelpMessageToPrint[256]; static float &m_HelpMessageDisplayTime; - static float &m_fTextBoxNumLines; - static float &m_fHelpMessageTime; - static bool &m_HelpMessageQuick; - static int32 m_ZoneState; + static float m_fHelpMessageTime; + static bool m_HelpMessageQuick; + static uint32 m_ZoneState; static int32 m_ZoneFadeTimer; - static int32 m_ZoneNameTimer; - static wchar *&m_pZoneName; + static uint32 m_ZoneNameTimer; + static wchar *m_pZoneName; static wchar *m_pLastZoneName; static wchar *m_ZoneToPrint; - static wchar *&m_VehicleName; + static wchar *m_VehicleName; static wchar *m_pLastVehicleName; static wchar *m_pVehicleNameToPrint; - static int32 m_VehicleState; + static uint32 m_VehicleState; static int32 m_VehicleFadeTimer; - static int32 m_VehicleNameTimer; - static wchar *m_Message; - static wchar *m_PagerMessage; - static bool &m_Wants_To_Draw_Hud; - static bool &m_Wants_To_Draw_3dMarkers; - static wchar(&m_BigMessage)[6][128]; - static int16 &m_ItemToFlash; + static uint32 m_VehicleNameTimer; + static wchar m_Message[256]; + static wchar m_PagerMessage[256]; + static bool m_Wants_To_Draw_Hud; + static bool m_Wants_To_Draw_3dMarkers; + static wchar m_BigMessage[6][128]; + static int16 m_ItemToFlash; // These aren't really in CHud static float BigMessageInUse[6]; static float BigMessageAlpha[6]; static float BigMessageX[6]; - static float &OddJob2OffTimer; - static int8 &CounterOnLastFrame; - static float &OddJob2XOffset; - static int16 &CounterFlashTimer; - static int16 &OddJob2Timer; - static int8 &TimerOnLastFrame; - static int16 &OddJob2On; - static int16 &TimerFlashTimer; - static int16 &PagerSoundPlayed; - static float &PagerXOffset; - static int16 &PagerTimer; - static int16 &PagerOn; + static float OddJob2OffTimer; + static bool CounterOnLastFrame; + static float OddJob2XOffset; + static uint16 CounterFlashTimer; + static uint16 OddJob2Timer; + static bool TimerOnLastFrame; + static int16 OddJob2On; + static uint16 TimerFlashTimer; + static int16 PagerSoundPlayed; + static int32 SpriteBrightness; + static float PagerXOffset; + static int16 PagerTimer; + static int16 PagerOn; public: static void Draw(); diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index 1cf27ee0..d28671fa 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -4,12 +4,13 @@ #include "Camera.h" #include "MBlur.h" +// Originally taken from RW example 'mblur' + RwRaster *&CMBlur::pFrontBuffer = *(RwRaster**)0x8E2C48; bool &CMBlur::ms_bJustInitialised = *(bool*)0x95CDAB; bool &CMBlur::BlurOn = *(bool*)0x95CDAD; static RwIm2DVertex Vertex[4]; -//static RwIm2DVertex *Vertex = (RwIm2DVertex*)0x62F780; static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 }; void diff --git a/src/core/PlayerSkin.cpp b/src/render/PlayerSkin.cpp index 4f730b90..2cba45fe 100644 --- a/src/core/PlayerSkin.cpp +++ b/src/render/PlayerSkin.cpp @@ -1,173 +1,174 @@ -#include "common.h"
-#include "patcher.h"
-#include "main.h"
-#include "PlayerSkin.h"
-#include "TxdStore.h"
-#include "rtbmp.h"
-#include "ClumpModelInfo.h"
-#include "VisibilityPlugins.h"
-#include "World.h"
-#include "PlayerInfo.h"
-#include "CdStream.h"
-#include "FileMgr.h"
-#include "Directory.h"
-#include "RwHelper.h"
-#include "Timer.h"
-#include "Lights.h"
-
-int CPlayerSkin::m_txdSlot;
-
-void
-FindPlayerDff(uint32 &offset, uint32 &size)
-{
- int file;
- CDirectory::DirectoryInfo info;
-
- file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
-
- do {
- if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
- return;
- } while (strcasecmp("player.dff", info.name) != 0);
-
- offset = info.offset;
- size = info.size;
-}
-
-void
-LoadPlayerDff(void)
-{
- RwStream *stream;
- RwMemory mem;
- uint32 offset, size;
- uint8 *buffer;
- bool streamWasAdded = false;
-
- if (CdStreamGetNumImages() == 0) {
- CdStreamAddImage("models\\gta3.img");
- streamWasAdded = true;
- }
-
- FindPlayerDff(offset, size);
- buffer = (uint8*)RwMallocAlign(size << 11, 2048);
- CdStreamRead(0, buffer, offset, size);
- CdStreamSync(0);
-
- mem.start = buffer;
- mem.length = size << 11;
- stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
-
- if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
- gpPlayerClump = RpClumpStreamRead(stream);
-
- RwStreamClose(stream, &mem);
- RwFreeAlign(buffer);
-
- if (streamWasAdded)
- CdStreamRemoveImages();
-}
-
-void
-CPlayerSkin::Initialise(void)
-{
- m_txdSlot = CTxdStore::AddTxdSlot("skin");
- CTxdStore::Create(m_txdSlot);
- CTxdStore::AddRef(m_txdSlot);
-}
-
-void
-CPlayerSkin::Shutdown(void)
-{
- CTxdStore::RemoveTxdSlot(m_txdSlot);
-}
-
-RwTexture *
-CPlayerSkin::GetSkinTexture(const char *texName)
-{
- RwTexture *tex;
- RwRaster *raster;
- int32 width, height, depth, format;
-
- CTxdStore::PushCurrentTxd();
- CTxdStore::SetCurrentTxd(m_txdSlot);
- tex = RwTextureRead(texName, NULL);
- CTxdStore::PopCurrentTxd();
- if (tex) return tex;
-
- if (strcmp(DEFAULT_SKIN_NAME, texName) == 0)
- sprintf(gString, "models\\generic\\player.bmp");
- else
- sprintf(gString, "skins\\%s.bmp", texName);
-
- if (RwImage *image = RtBMPImageRead(gString)) {
- RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
- raster = RwRasterCreate(width, height, depth, format);
- RwRasterSetFromImage(raster, image);
-
- tex = RwTextureCreate(raster);
- RwTextureSetName(tex, texName);
- RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
- RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
-
- RwImageDestroy(image);
- }
- return tex;
-}
-
-void
-CPlayerSkin::BeginFrontendSkinEdit(void)
-{
- LoadPlayerDff();
- RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
- CWorld::Players[0].LoadPlayerSkin();
- gOldFov = CDraw::GetFOV();
- CDraw::SetFOV(30.0f);
-}
-
-void
-CPlayerSkin::EndFrontendSkinEdit(void)
-{
- RpClumpDestroy(gpPlayerClump);
- gpPlayerClump = NULL;
- CDraw::SetFOV(gOldFov);
-}
-
-void
-CPlayerSkin::RenderFrontendSkinEdit(void)
-{
- static float rotation = 0.0f;
- RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
- RwV3d pos = { 1.35f, 0.35f, 7.725f };
- const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
- const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
- static uint32 LastFlash = 0;
-
-#ifdef ASPECT_RATIO_SCALE
- pos.x = 1.35f * (SCREEN_ASPECT_RATIO / DEFAULT_ASPECT_RATIO);
-#endif
-
- RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
-
- if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
- rotation += 2.0f;
- if (rotation > 360.0f)
- rotation -= 360.0f;
- LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
- }
- RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
- RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
- RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
- RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
- RwFrameUpdateObjects(frame);
- SetAmbientColours(&AmbientColor);
- RpClumpRender(gpPlayerClump);
-}
-
-STARTPATCHES
-InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP);
-InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP);
-InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP);
-InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP);
-InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP);
-InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP);
+#include "common.h" +#include "patcher.h" +#include "main.h" +#include "PlayerSkin.h" +#include "TxdStore.h" +#include "rtbmp.h" +#include "ClumpModelInfo.h" +#include "VisibilityPlugins.h" +#include "World.h" +#include "PlayerInfo.h" +#include "CdStream.h" +#include "FileMgr.h" +#include "Directory.h" +#include "RwHelper.h" +#include "Timer.h" +#include "Lights.h" + +RpClump *gpPlayerClump; +float gOldFov; + +int CPlayerSkin::m_txdSlot; + +void +FindPlayerDff(uint32 &offset, uint32 &size) +{ + int file; + CDirectory::DirectoryInfo info; + + file = CFileMgr::OpenFile("models\\gta3.dir", "rb"); + + do { + if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo))) + return; + } while (strcasecmp("player.dff", info.name) != 0); + + offset = info.offset; + size = info.size; +} + +void +LoadPlayerDff(void) +{ + RwStream *stream; + RwMemory mem; + uint32 offset, size; + uint8 *buffer; + bool streamWasAdded = false; + + if (CdStreamGetNumImages() == 0) { + CdStreamAddImage("models\\gta3.img"); + streamWasAdded = true; + } + + FindPlayerDff(offset, size); + buffer = (uint8*)RwMallocAlign(size << 11, 2048); + CdStreamRead(0, buffer, offset, size); + CdStreamSync(0); + + mem.start = buffer; + mem.length = size << 11; + stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem); + + if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) + gpPlayerClump = RpClumpStreamRead(stream); + + RwStreamClose(stream, &mem); + RwFreeAlign(buffer); + + if (streamWasAdded) + CdStreamRemoveImages(); +} + +void +CPlayerSkin::Initialise(void) +{ + m_txdSlot = CTxdStore::AddTxdSlot("skin"); + CTxdStore::Create(m_txdSlot); + CTxdStore::AddRef(m_txdSlot); +} + +void +CPlayerSkin::Shutdown(void) +{ + CTxdStore::RemoveTxdSlot(m_txdSlot); +} + +RwTexture * +CPlayerSkin::GetSkinTexture(const char *texName) +{ + RwTexture *tex; + RwRaster *raster; + int32 width, height, depth, format; + + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(m_txdSlot); + tex = RwTextureRead(texName, NULL); + CTxdStore::PopCurrentTxd(); + if (tex != nil) return tex; + + if (strcmp(DEFAULT_SKIN_NAME, texName) == 0) + sprintf(gString, "models\\generic\\player.bmp"); + else + sprintf(gString, "skins\\%s.bmp", texName); + + if (RwImage *image = RtBMPImageRead(gString)) { + RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format); + raster = RwRasterCreate(width, height, depth, format); + RwRasterSetFromImage(raster, image); + + tex = RwTextureCreate(raster); + RwTextureSetName(tex, texName); +#ifdef FIX_BUGS + RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC +#endif + RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex); + + RwImageDestroy(image); + } + return tex; +} + +void +CPlayerSkin::BeginFrontendSkinEdit(void) +{ + LoadPlayerDff(); + RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB); + CWorld::Players[0].LoadPlayerSkin(); + gOldFov = CDraw::GetFOV(); + CDraw::SetFOV(30.0f); +} + +void +CPlayerSkin::EndFrontendSkinEdit(void) +{ + RpClumpDestroy(gpPlayerClump); + gpPlayerClump = NULL; + CDraw::SetFOV(gOldFov); +} + +void +CPlayerSkin::RenderFrontendSkinEdit(void) +{ + static float rotation = 0.0f; + RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f }; + const RwV3d pos = { 1.35f, 0.35f, 7.725f }; + const RwV3d axis1 = { 1.0f, 0.0f, 0.0f }; + const RwV3d axis2 = { 0.0f, 0.0f, 1.0f }; + static uint32 LastFlash = 0; + + RwFrame *frame = RpClumpGetFrame(gpPlayerClump); + + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) { + rotation += 2.0f; + if (rotation > 360.0f) + rotation -= 360.0f; + LastFlash = CTimer::GetTimeInMillisecondsPauseMode(); + } + RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE); + RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT); + RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT); + RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT); + RwFrameUpdateObjects(frame); + SetAmbientColours(&AmbientColor); + RpClumpRender(gpPlayerClump); +} + +STARTPATCHES +InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP); +InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP); +InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP); +InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP); +InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP); +InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP); ENDPATCHES
\ No newline at end of file diff --git a/src/core/PlayerSkin.h b/src/render/PlayerSkin.h index 2d82ec12..e0214ce0 100644 --- a/src/core/PlayerSkin.h +++ b/src/render/PlayerSkin.h @@ -2,12 +2,6 @@ #define DEFAULT_SKIN_NAME "$$\"\"" -static RpClump *gpPlayerClump;// = *(RpClump**)0x660FF8; -static float gOldFov;// = *(float*)0x660FFC; - -void LoadPlayerDff(void); -void FindPlayerDff(uint32 &offset, uint32 &size); - class CPlayerSkin { static int m_txdSlot; diff --git a/src/render/Renderer.h b/src/render/Renderer.h index 89fc23cb..42c154ec 100644 --- a/src/render/Renderer.h +++ b/src/render/Renderer.h @@ -29,7 +29,7 @@ class CRenderer static CVehicle *&m_pFirstPersonVehicle; public: - static float &ms_lodDistScale; // defined in Frontend.cpp + static float ms_lodDistScale; // defined in Frontend.cpp static bool &m_loadingPriority; static void Init(void); diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp index a52e59a0..65d8b2dd 100644 --- a/src/render/Rubbish.cpp +++ b/src/render/Rubbish.cpp @@ -1,10 +1,420 @@ #include "common.h" +#include "main.h" #include "patcher.h" +#include "General.h" +#include "Timer.h" +#include "Weather.h" +#include "Camera.h" +#include "World.h" +#include "Vehicle.h" +#include "ZoneCull.h" +#include "TxdStore.h" +#include "RenderBuffer.h" #include "Rubbish.h" -WRAPPER void CRubbish::Render(void) { EAXJMP(0x512190); } -WRAPPER void CRubbish::StirUp(CVehicle *veh) { EAXJMP(0x512690); } -WRAPPER void CRubbish::Update(void) { EAXJMP(0x511B90); } -WRAPPER void CRubbish::SetVisibility(bool) { EAXJMP(0x512AA0); } -WRAPPER void CRubbish::Init(void) { EAXJMP(0x511940); } -WRAPPER void CRubbish::Shutdown(void) { EAXJMP(0x511B50); } +#define RUBBISH_MAX_DIST (18.0f) +#define RUBBISH_FADE_DIST (16.5f) + +RwTexture *gpRubbishTexture[4]; +RwImVertexIndex RubbishIndexList[6]; +RwImVertexIndex RubbishIndexList2[6]; // unused +RwIm3DVertex RubbishVertices[4]; +bool CRubbish::bRubbishInvisible; +int CRubbish::RubbishVisibility; +COneSheet CRubbish::aSheets[NUM_RUBBISH_SHEETS]; +COneSheet CRubbish::StartEmptyList; +COneSheet CRubbish::EndEmptyList; +COneSheet CRubbish::StartStaticsList; +COneSheet CRubbish::EndStaticsList; +COneSheet CRubbish::StartMoversList; +COneSheet CRubbish::EndMoversList; + + +void +COneSheet::AddToList(COneSheet *list) +{ + this->m_next = list->m_next; + this->m_prev = list; + list->m_next = this; + this->m_next->m_prev = this; +} + +void +COneSheet::RemoveFromList(void) +{ + m_next->m_prev = m_prev; + m_prev->m_next = m_next; +} + + +void +CRubbish::Render(void) +{ + int type; + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + + for(type = 0; type < 4; type++){ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type])); + + TempBufferIndicesStored = 0; + TempBufferVerticesStored = 0; + + COneSheet *sheet; + for(sheet = &aSheets[type*NUM_RUBBISH_SHEETS / 4]; + sheet < &aSheets[(type+1)*NUM_RUBBISH_SHEETS / 4]; + sheet++){ + if(sheet->m_state == 0) + continue; + + uint32 alpha = 128; + CVector pos; + if(sheet->m_state == 1){ + pos = sheet->m_basePos; + if(!sheet->m_isVisible) + alpha = 0; + }else{ + pos = sheet->m_animatedPos; + // Not fully visible during animation, calculate current alpha + if(!sheet->m_isVisible || !sheet->m_targetIsVisible){ + float t = (float)(CTimer::GetTimeInMilliseconds() - sheet->m_moveStart)/sheet->m_moveDuration; + float f1 = sheet->m_isVisible ? 1.0f-t : 0.0f; + float f2 = sheet->m_targetIsVisible ? t : 0.0f; + alpha = 128 * (f1+f2); + } + } + + float camDist = (pos - TheCamera.GetPosition()).Magnitude2D(); + if(camDist < RUBBISH_MAX_DIST){ + if(camDist >= RUBBISH_FADE_DIST) + alpha -= alpha*(camDist-RUBBISH_FADE_DIST)/(RUBBISH_MAX_DIST-RUBBISH_FADE_DIST); + alpha = (RubbishVisibility*alpha)/256; + + float vx = Sin(sheet->m_angle) * 0.4f; + float vy = Cos(sheet->m_angle) * 0.4f; + + int v = TempBufferVerticesStored; + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx, pos.y + vy, pos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x - vy, pos.y + vx, pos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x + vy, pos.y - vx, pos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx, pos.y - vy, pos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], 255, 255, 255, alpha); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], 0.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+1], 1.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+1], 0.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+2], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+2], 1.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+3], 1.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+3], 1.0f); + + int i = TempBufferIndicesStored; + TempBufferRenderIndexList[i+0] = RubbishIndexList[0] + TempBufferVerticesStored; + TempBufferRenderIndexList[i+1] = RubbishIndexList[1] + TempBufferVerticesStored; + TempBufferRenderIndexList[i+2] = RubbishIndexList[2] + TempBufferVerticesStored; + TempBufferRenderIndexList[i+3] = RubbishIndexList[3] + TempBufferVerticesStored; + TempBufferRenderIndexList[i+4] = RubbishIndexList[4] + TempBufferVerticesStored; + TempBufferRenderIndexList[i+5] = RubbishIndexList[5] + TempBufferVerticesStored; + TempBufferVerticesStored += 4; + TempBufferIndicesStored += 6; + } + } + + if(TempBufferIndicesStored != 0){ + LittleTest(); + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); + RwIm3DEnd(); + } + } + } + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); +} + +void +CRubbish::StirUp(CVehicle *veh) +{ + if((CTimer::GetFrameCounter() ^ (veh->m_randomSeed&3)) == 0) + return; + + if(Abs(veh->GetPosition().x - TheCamera.GetPosition().x) < 20.0f && + Abs(veh->GetPosition().y - TheCamera.GetPosition().y) < 20.0f) + if(Abs(veh->GetMoveSpeed().x) > 0.05f || Abs(veh->GetMoveSpeed().y) > 0.05f){ + float speed = veh->GetMoveSpeed().Magnitude2D(); + if(speed > 0.05f){ + bool movingForward = DotProduct2D(veh->GetMoveSpeed(), veh->GetForward()) > 0.0f; + COneSheet *sheet = StartStaticsList.m_next; + CVector2D size = veh->GetColModel()->boundingBox.max; + + // Check all static sheets + while(sheet != &EndStaticsList){ + COneSheet *next = sheet->m_next; + CVector2D carToSheet = sheet->m_basePos - veh->GetPosition(); + float distFwd = DotProduct2D(carToSheet, veh->GetForward()); + + // sheet has to be a bit behind car + if(movingForward && distFwd < -0.5f*size.y && distFwd > -1.5f*size.y || + !movingForward && distFwd > 0.5f*size.y && distFwd < 1.5f*size.y){ + float distSide = Abs(DotProduct2D(carToSheet, veh->GetRight())); + if(distSide < 1.5*size.x){ + // Check with higher speed for sheet directly behind car + float speedToCheck = distSide < size.x ? speed : speed*0.5f; + if(speedToCheck > 0.05f){ + sheet->m_state = 2; + if(speedToCheck > 0.15f) + sheet->m_animationType = 2; + else + sheet->m_animationType = 1; + sheet->m_moveDuration = 2000; + sheet->m_xDist = veh->GetMoveSpeed().x; + sheet->m_yDist = veh->GetMoveSpeed().y; + float dist = Sqrt(SQR(sheet->m_xDist)+SQR(sheet->m_yDist)); + sheet->m_xDist *= 25.0f*speed/dist; + sheet->m_yDist *= 25.0f*speed/dist; + sheet->m_animHeight = 3.0f*speed; + sheet->m_moveStart = CTimer::GetTimeInMilliseconds(); + float tx = sheet->m_basePos.x + sheet->m_xDist; + float ty = sheet->m_basePos.y + sheet->m_yDist; + float tz = sheet->m_basePos.z + 3.0f; + sheet->m_targetZ = CWorld::FindGroundZFor3DCoord(tx, ty, tz, nil) + 0.1f; + sheet->RemoveFromList(); + sheet->AddToList(&StartMoversList); + } + } + } + + sheet = next; + } + } + } +} + +static float aAnimations[3][34] = { + { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, + + // Normal move + { 0.0f, 0.05f, 0.12f, 0.25f, 0.42f, 0.57f, 0.68f, 0.8f, 0.86f, 0.9f, 0.93f, 0.95f, 0.96f, 0.97f, 0.98f, 0.99f, 1.0f, // XY movemnt + 0.15f, 0.35f, 0.6f, 0.9f, 1.2f, 1.25f, 1.3f, 1.2f, 1.1f, 0.95f, 0.8f, 0.6f, 0.45f, 0.3f, 0.2f, 0.1f, 0 }, // Z movement + + // Stirred up by fast vehicle + { 0.0f, 0.05f, 0.12f, 0.25f, 0.42f, 0.57f, 0.68f, 0.8f, 0.95f, 1.1f, 1.15f, 1.18f, 1.15f, 1.1f, 1.05f, 1.03f, 1.0f, + 0.15f, 0.35f, 0.6f, 0.9f, 1.2f, 1.25f, 1.3f, 1.2f, 1.1f, 0.95f, 0.8f, 0.6f, 0.45f, 0.3f, 0.2f, 0.1f, 0 } +}; + +void +CRubbish::Update(void) +{ + bool foundGround; + + // FRAMETIME + if(bRubbishInvisible) + RubbishVisibility = max(RubbishVisibility-5, 0); + else + RubbishVisibility = min(RubbishVisibility+5, 255); + + // Spawn a new sheet + COneSheet *sheet = StartEmptyList.m_next; + if(sheet != &EndEmptyList){ + float spawnDist; + float spawnAngle; + + spawnDist = (CGeneral::GetRandomNumber()&0xFF)/256.0f + RUBBISH_MAX_DIST; + uint8 r = CGeneral::GetRandomNumber(); + if(r&1) + spawnAngle = (CGeneral::GetRandomNumber()&0xFF)/256.0f * 6.28f; + else + spawnAngle = (r-128)/160.0f + TheCamera.Orientation; + sheet->m_basePos.x = TheCamera.GetPosition().x + spawnDist*Sin(spawnAngle); + sheet->m_basePos.y = TheCamera.GetPosition().y + spawnDist*Cos(spawnAngle); + sheet->m_basePos.z = CWorld::FindGroundZFor3DCoord(sheet->m_basePos.x, sheet->m_basePos.y, TheCamera.GetPosition().z, &foundGround) + 0.1f; + if(foundGround){ + // Found ground, so add to statics list + sheet->m_angle = (CGeneral::GetRandomNumber()&0xFF)/256.0f * 6.28f; + sheet->m_state = 1; + if(CCullZones::FindAttributesForCoors(sheet->m_basePos, nil) & ATTRZONE_NORAIN) + sheet->m_isVisible = false; + else + sheet->m_isVisible = true; + sheet->RemoveFromList(); + sheet->AddToList(&StartStaticsList); + } + } + + // Process animation + sheet = StartMoversList.m_next; + while(sheet != &EndMoversList){ + uint32 currentTime = CTimer::GetTimeInMilliseconds() - sheet->m_moveStart; + if(currentTime < sheet->m_moveDuration){ + // Animation + int step = 16 * currentTime / sheet->m_moveDuration; // 16 steps in animation + int stepTime = sheet->m_moveDuration/16; // time in each step + float s = (float)(currentTime - stepTime*step) / stepTime; // position on step + float t = (float)currentTime / sheet->m_moveDuration; // position on total animation + // factors for xy and z-movment + float fxy = aAnimations[sheet->m_animationType][step]*(1.0f-s) + aAnimations[sheet->m_animationType][step+1]*s; + float fz = aAnimations[sheet->m_animationType][step+17]*(1.0f-s) + aAnimations[sheet->m_animationType][step+1+17]*s; + sheet->m_animatedPos.x = sheet->m_basePos.x + fxy*sheet->m_xDist; + sheet->m_animatedPos.y = sheet->m_basePos.y + fxy*sheet->m_yDist; + sheet->m_animatedPos.z = (1.0f-t)*sheet->m_basePos.z + t*sheet->m_targetZ + fz*sheet->m_animHeight; + sheet->m_angle += CTimer::GetTimeStep()*0.04f; + if(sheet->m_angle > 6.28f) + sheet->m_angle -= 6.28f; + sheet = sheet->m_next; + }else{ + // End of animation, back into statics list + sheet->m_basePos.x += sheet->m_xDist; + sheet->m_basePos.y += sheet->m_yDist; + sheet->m_basePos.z = sheet->m_targetZ; + sheet->m_state = 1; + sheet->m_isVisible = sheet->m_targetIsVisible; + + COneSheet *next = sheet->m_next; + sheet->RemoveFromList(); + sheet->AddToList(&StartStaticsList); + sheet = next; + } + } + + // Stir up a sheet by wind + // FRAMETIME + int freq; + if(CWeather::Wind < 0.1f) + freq = 31; + else if(CWeather::Wind < 0.4f) + freq = 7; + else if(CWeather::Wind < 0.7f) + freq = 1; + else + freq = 0; + if((CTimer::GetFrameCounter() & freq) == 0){ + // Pick a random sheet and set animation state if static + int i = CGeneral::GetRandomNumber() % NUM_RUBBISH_SHEETS; + if(aSheets[i].m_state == 1){ + aSheets[i].m_moveStart = CTimer::GetTimeInMilliseconds(); + aSheets[i].m_moveDuration = CWeather::Wind*1500.0f + 1000.0f; + aSheets[i].m_animHeight = 0.2f; + aSheets[i].m_xDist = 3.0f*CWeather::Wind; + aSheets[i].m_yDist = 3.0f*CWeather::Wind; + // Check if target position is ok + float tx = aSheets[i].m_basePos.x + aSheets[i].m_xDist; + float ty = aSheets[i].m_basePos.y + aSheets[i].m_yDist; + float tz = aSheets[i].m_basePos.z + 3.0f; + aSheets[i].m_targetZ = CWorld::FindGroundZFor3DCoord(tx, ty, tz, &foundGround) + 0.1f; + if(CCullZones::FindAttributesForCoors(CVector(tx, ty, aSheets[i].m_targetZ), nil) & ATTRZONE_NORAIN) + aSheets[i].m_targetIsVisible = false; + else + aSheets[i].m_targetIsVisible = true; + if(foundGround){ + // start animation + aSheets[i].m_state = 2; + aSheets[i].m_animationType = 1; + aSheets[i].RemoveFromList(); + aSheets[i].AddToList(&StartMoversList); + } + } + } + + // Remove sheets that are too far away + int i = (CTimer::GetFrameCounter()%(NUM_RUBBISH_SHEETS/4))*4; + int last = ((CTimer::GetFrameCounter()%(NUM_RUBBISH_SHEETS/4)) + 1)*4; + for(; i < last; i++){ + if(aSheets[i].m_state == 1 && + (aSheets[i].m_basePos - TheCamera.GetPosition()).MagnitudeSqr2D() > SQR(RUBBISH_MAX_DIST+1.0f)){ + aSheets[i].m_state = 0; + aSheets[i].RemoveFromList(); + aSheets[i].AddToList(&StartEmptyList); + } + } +} + +void +CRubbish::SetVisibility(bool visible) +{ + bRubbishInvisible = !visible; +} + +void +CRubbish::Init(void) +{ + int i; + for(i = 0; i < NUM_RUBBISH_SHEETS; i++){ + aSheets[i].m_state = 0; + if(i < NUM_RUBBISH_SHEETS-1) + aSheets[i].m_next = &aSheets[i+1]; + else + aSheets[i].m_next = &EndEmptyList; + if(i > 0) + aSheets[i].m_prev = &aSheets[i-1]; + else + aSheets[i].m_prev = &StartEmptyList; + } + + StartEmptyList.m_next = &aSheets[0]; + StartEmptyList.m_prev = nil; + EndEmptyList.m_next = nil; + EndEmptyList.m_prev = &aSheets[NUM_RUBBISH_SHEETS-1]; + + StartStaticsList.m_next = &EndStaticsList; + StartStaticsList.m_prev = nil; + EndStaticsList.m_next = nil; + EndStaticsList.m_prev = &StartStaticsList; + + StartMoversList.m_next = &EndMoversList; + StartMoversList.m_prev = nil; + EndMoversList.m_next = nil; + EndMoversList.m_prev = &StartMoversList; + + // unused + RwIm3DVertexSetU(&RubbishVertices[0], 0.0f); + RwIm3DVertexSetV(&RubbishVertices[0], 0.0f); + RwIm3DVertexSetU(&RubbishVertices[1], 1.0f); + RwIm3DVertexSetV(&RubbishVertices[1], 0.0f); + RwIm3DVertexSetU(&RubbishVertices[2], 0.0f); + RwIm3DVertexSetV(&RubbishVertices[2], 1.0f); + RwIm3DVertexSetU(&RubbishVertices[3], 1.0f); + RwIm3DVertexSetV(&RubbishVertices[3], 1.0f); + + // unused + RubbishIndexList2[0] = 0; + RubbishIndexList2[1] = 2; + RubbishIndexList2[2] = 1; + RubbishIndexList2[3] = 1; + RubbishIndexList2[4] = 2; + RubbishIndexList2[5] = 3; + + RubbishIndexList[0] = 0; + RubbishIndexList[1] = 1; + RubbishIndexList[2] = 2; + RubbishIndexList[3] = 1; + RubbishIndexList[4] = 3; + RubbishIndexList[5] = 2; + + CTxdStore::PushCurrentTxd(); + int slot = CTxdStore::FindTxdSlot("particle"); + CTxdStore::SetCurrentTxd(slot); + gpRubbishTexture[0] = RwTextureRead("gameleaf01_64", nil); + gpRubbishTexture[1] = RwTextureRead("gameleaf02_64", nil); + gpRubbishTexture[2] = RwTextureRead("newspaper01_64", nil); + gpRubbishTexture[3] = RwTextureRead("newspaper02_64", nil); + CTxdStore::PopCurrentTxd(); + RubbishVisibility = 255; + bRubbishInvisible = false; +} + +void +CRubbish::Shutdown(void) +{ + RwTextureDestroy(gpRubbishTexture[0]); + RwTextureDestroy(gpRubbishTexture[1]); + RwTextureDestroy(gpRubbishTexture[2]); + RwTextureDestroy(gpRubbishTexture[3]); +} diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h index 17323694..2be592fe 100644 --- a/src/render/Rubbish.h +++ b/src/render/Rubbish.h @@ -2,13 +2,50 @@ class CVehicle; +enum { + // NB: not all values are allowed, check the code + NUM_RUBBISH_SHEETS = 64 +}; + +class COneSheet +{ +public: + CVector m_basePos; + CVector m_animatedPos; + float m_targetZ; + int8 m_state; + int8 m_animationType; + uint32 m_moveStart; + uint32 m_moveDuration; + float m_animHeight; + float m_xDist; + float m_yDist; + float m_angle; + bool m_isVisible; + bool m_targetIsVisible; + COneSheet *m_next; + COneSheet *m_prev; + + void AddToList(COneSheet *list); + void RemoveFromList(void); +}; + class CRubbish { + static bool bRubbishInvisible; + static int RubbishVisibility; + static COneSheet aSheets[NUM_RUBBISH_SHEETS]; + static COneSheet StartEmptyList; + static COneSheet EndEmptyList; + static COneSheet StartStaticsList; + static COneSheet EndStaticsList; + static COneSheet StartMoversList; + static COneSheet EndMoversList; public: static void Render(void); static void StirUp(CVehicle *veh); // CAutomobile on PS2 static void Update(void); - static void SetVisibility(bool); + static void SetVisibility(bool visible); static void Init(void); static void Shutdown(void); }; diff --git a/src/render/Shadows.h b/src/render/Shadows.h index 982cc463..fb41ebbc 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -175,11 +175,18 @@ public: static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity); }; -extern RwTexture *&gpBloodPoolTex; +extern RwTexture *&gpShadowCarTex; +extern RwTexture *&gpShadowPedTex; +extern RwTexture *&gpShadowHeliTex; extern RwTexture *&gpShadowExplosionTex; extern RwTexture *&gpShadowHeadLightsTex; -extern RwTexture *&gpGoalTex; extern RwTexture *&gpOutline1Tex; extern RwTexture *&gpOutline2Tex; extern RwTexture *&gpOutline3Tex; +extern RwTexture *&gpBloodPoolTex; +extern RwTexture *&gpReflectionTex; +extern RwTexture *&gpGoalMarkerTex; +extern RwTexture *&gpWalkDontTex; extern RwTexture *&gpCrackedGlassTex; +extern RwTexture *&gpPostShadowTex; +extern RwTexture *&gpGoalTex; diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index c2725ed6..41ee5d1d 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -1,12 +1,247 @@ #include "common.h" #include "patcher.h" +#include "main.h" +#include "TxdStore.h" +#include "Timer.h" +#include "Replay.h" #include "Skidmarks.h" -WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); } -WRAPPER void CSkidmarks::Update() { EAXJMP(0x518200); } +CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS]; -WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); } -WRAPPER void CSkidmarks::RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy) { EAXJMP(0x5185C0); } +RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6]; +RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2]; +RwTexture *gpSkidTex; +RwTexture *gpSkidBloodTex; +RwTexture *gpSkidMudTex; -WRAPPER void CSkidmarks::Init(void) { EAXJMP(0x517D70); } -WRAPPER void CSkidmarks::Shutdown(void) { EAXJMP(0x518100); } +void +CSkidmarks::Init(void) +{ + int i, ix, slot; + CTxdStore::PushCurrentTxd(); + slot = CTxdStore::FindTxdSlot("particle"); + CTxdStore::SetCurrentTxd(slot); + gpSkidTex = RwTextureRead("particleskid", nil); + gpSkidBloodTex = RwTextureRead("particleskidblood", nil); + gpSkidMudTex = RwTextureRead("particleskidmud", nil); + CTxdStore::PopCurrentTxd(); + + for(i = 0; i < NUMSKIDMARKS; i++){ + aSkidmarks[i].m_state = 0; + aSkidmarks[i].m_wasUpdated = false; + } + + ix = 0; + for(i = 0; i < SKIDMARK_LENGTH; i++){ + SkidmarkIndexList[i*6+0] = ix+0; + SkidmarkIndexList[i*6+1] = ix+2; + SkidmarkIndexList[i*6+2] = ix+1; + SkidmarkIndexList[i*6+3] = ix+1; + SkidmarkIndexList[i*6+4] = ix+2; + SkidmarkIndexList[i*6+5] = ix+3; + ix += 2; + } + + for(i = 0; i < SKIDMARK_LENGTH; i++){ + RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 0], 0.0f); + RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 0], i*5.01f); + RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 1], 1.0f); + RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 1], i*5.01f); + } +} + +void +CSkidmarks::Shutdown(void) +{ + RwTextureDestroy(gpSkidTex); + RwTextureDestroy(gpSkidBloodTex); + RwTextureDestroy(gpSkidMudTex); +} + +void +CSkidmarks::Clear(void) +{ + int i; + for(i = 0; i < NUMSKIDMARKS; i++){ + aSkidmarks[i].m_state = 0; + aSkidmarks[i].m_wasUpdated = false; + } +} + +void +CSkidmarks::Update(void) +{ + int i; + uint32 t1 = CTimer::GetTimeInMilliseconds() + 2500; + uint32 t2 = CTimer::GetTimeInMilliseconds() + 5000; + uint32 t3 = CTimer::GetTimeInMilliseconds() + 10000; + uint32 t4 = CTimer::GetTimeInMilliseconds() + 20000; + for(i = 0; i < NUMSKIDMARKS; i++){ + switch(aSkidmarks[i].m_state){ + case 1: + if(!aSkidmarks[i].m_wasUpdated){ + // Didn't continue this one last time, so finish it and set fade times + aSkidmarks[i].m_state = 2; + if(aSkidmarks[i].m_last < 4){ + aSkidmarks[i].m_fadeStart = t1; + aSkidmarks[i].m_fadeEnd = t2; + }else if(aSkidmarks[i].m_last < 9){ + aSkidmarks[i].m_fadeStart = t2; + aSkidmarks[i].m_fadeEnd = t3; + }else{ + aSkidmarks[i].m_fadeStart = t3; + aSkidmarks[i].m_fadeEnd = t4; + } + } + break; + case 2: + if(CTimer::GetTimeInMilliseconds() > aSkidmarks[i].m_fadeEnd) + aSkidmarks[i].m_state = 0; + break; + } + aSkidmarks[i].m_wasUpdated = false; + } +} + +void +CSkidmarks::Render(void) +{ + int i, j; + RwTexture *lastTex = nil; + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + + for(i = 0; i < NUMSKIDMARKS; i++){ + if(aSkidmarks[i].m_state == 0 || aSkidmarks[i].m_last < 1) + continue; + + if(aSkidmarks[i].m_isBloody){ + if(lastTex != gpSkidBloodTex){ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidBloodTex)); + lastTex = gpSkidBloodTex; + } + }else if(aSkidmarks[i].m_isMuddy){ + if(lastTex != gpSkidMudTex){ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidMudTex)); + lastTex = gpSkidMudTex; + } + }else{ + if(lastTex != gpSkidTex){ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex)); + lastTex = gpSkidTex; + } + } + + uint32 fade, alpha; + if(aSkidmarks[i].m_state == 1 || CTimer::GetTimeInMilliseconds() < aSkidmarks[i].m_fadeStart) + fade = 255; + else + fade = 255*(aSkidmarks[i].m_fadeEnd - CTimer::GetTimeInMilliseconds()) / (aSkidmarks[i].m_fadeEnd - aSkidmarks[i].m_fadeStart); + + for(j = 0; j <= aSkidmarks[i].m_last; j++){ + alpha = 128; + if(j == 0 || j == aSkidmarks[i].m_last && aSkidmarks[i].m_state == 2) + alpha = 0; + alpha = alpha*fade/256; + + CVector p1 = aSkidmarks[i].m_pos[j] + aSkidmarks[i].m_side[j]; + CVector p2 = aSkidmarks[i].m_pos[j] - aSkidmarks[i].m_side[j]; + RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f); + RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f); + } + + LittleTest(); + if(RwIm3DTransform(SkidmarkVertices, 2*(aSkidmarks[i].m_last+1), nil, rwIM3D_VERTEXUV)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, SkidmarkIndexList, 6*aSkidmarks[i].m_last); + RwIm3DEnd(); + } + } + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); +} + +void +CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody) +{ + int i; + CVector2D fwd(fwdX, fwdY); + + if(CReplay::IsPlayingBack()) + return; + + // Find a skidmark to continue + for(i = 0; i < NUMSKIDMARKS; i++) + if(aSkidmarks[i].m_state == 1 && aSkidmarks[i].m_id == id) + break; + + if(i < NUMSKIDMARKS){ + // Continue this one + + if(aSkidmarks[i].m_isBloody != *isBloody){ + // Blood-status changed, end this one + aSkidmarks[i].m_state = 2; + aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000; + aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000; + return; + } + + aSkidmarks[i].m_wasUpdated = true; + + if(CTimer::GetTimeInMilliseconds() - aSkidmarks[i].m_lastUpdate <= 100){ + // Last update was recently, just change last coords + aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos; + return; + } + aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds(); + + if(aSkidmarks[i].m_last >= SKIDMARK_LENGTH-1){ + // No space to continue, end it + aSkidmarks[i].m_state = 2; + aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000; + aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000; + *isBloody = false; // stpo blood marks at end + return; + } + aSkidmarks[i].m_last++; + + aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos; + + CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1]; + dist.Normalise(); + CVector2D right(dist.y, -dist.x); + float turn = DotProduct2D(fwd, right); + turn = Abs(turn) + 1.0f; + aSkidmarks[i].m_side[aSkidmarks[i].m_last] = CVector(right.x, right.y, 0.0f) * turn * 0.125f; + if(aSkidmarks[i].m_last == 1) + aSkidmarks[i].m_side[0] = aSkidmarks[i].m_side[1]; + + if(aSkidmarks[i].m_last > 8) + *isBloody = false; // stop blood marks after 8 + return; + } + + // Start a new one + for(i = 0; i < NUMSKIDMARKS; i++) + if(aSkidmarks[i].m_state == 0) + break; + if(i < NUMSKIDMARKS){ + // Found a free slot + aSkidmarks[i].m_state = 1; + aSkidmarks[i].m_id = id; + aSkidmarks[i].m_pos[0] = pos; + aSkidmarks[i].m_side[0] = CVector(0.0f, 0.0f, 0.0f); + aSkidmarks[i].m_wasUpdated = true; + aSkidmarks[i].m_last = 0; + aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds() - 1000; + aSkidmarks[i].m_isBloody = *isBloody; + aSkidmarks[i].m_isMuddy = *isMuddy; + }else + *isBloody = false; // stop blood marks if no space +} diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h index bf2da7e4..085b4c6d 100644 --- a/src/render/Skidmarks.h +++ b/src/render/Skidmarks.h @@ -1,12 +1,32 @@ #pragma once +enum { SKIDMARK_LENGTH = 16 }; + +class CSkidmark +{ +public: + uint8 m_state; + bool m_wasUpdated; + bool m_isBloody; + bool m_isMuddy; + uintptr m_id; + int16 m_last; + uint32 m_lastUpdate;; + uint32 m_fadeStart; + uint32 m_fadeEnd; + CVector m_pos[SKIDMARK_LENGTH]; + CVector m_side[SKIDMARK_LENGTH]; +}; + class CSkidmarks { + static CSkidmark aSkidmarks[NUMSKIDMARKS]; public: + + static void Init(void); + static void Shutdown(void); static void Clear(void); static void Update(void); static void Render(void); - static void RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy); - static void Init(void); - static void Shutdown(void); + static void RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody); }; diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 301ae265..9189a7c2 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "patcher.h" #include "SpecialFX.h" +#include "RenderBuffer.h" #include "Timer.h" #include "Sprite.h" #include "Font.h" @@ -8,26 +9,260 @@ #include "TxdStore.h" #include "FileMgr.h" #include "FileLoader.h" +#include "Timecycle.h" #include "Lights.h" +#include "ModelIndices.h" #include "VisibilityPlugins.h" #include "World.h" +#include "PlayerPed.h" #include "Particle.h" +#include "Shadows.h" #include "General.h" #include "Camera.h" #include "Shadows.h" #include "main.h" -WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); } -WRAPPER void CSpecialFX::Update(void) { EAXJMP(0x518D40); } -WRAPPER void CSpecialFX::Init(void) { EAXJMP(0x5189E0); } -WRAPPER void CSpecialFX::Shutdown(void) { EAXJMP(0x518BE0); } +RwIm3DVertex StreakVertices[4]; +RwImVertexIndex StreakIndexList[12]; + +RwIm3DVertex TraceVertices[6]; +RwImVertexIndex TraceIndexList[12]; + + +void +CSpecialFX::Init(void) +{ + CBulletTraces::Init(); + + RwIm3DVertexSetU(&StreakVertices[0], 0.0f); + RwIm3DVertexSetV(&StreakVertices[0], 0.0f); + RwIm3DVertexSetU(&StreakVertices[1], 1.0f); + RwIm3DVertexSetV(&StreakVertices[1], 0.0f); + RwIm3DVertexSetU(&StreakVertices[2], 0.0f); + RwIm3DVertexSetV(&StreakVertices[2], 0.0f); + RwIm3DVertexSetU(&StreakVertices[3], 1.0f); + RwIm3DVertexSetV(&StreakVertices[3], 0.0f); + + StreakIndexList[0] = 0; + StreakIndexList[1] = 1; + StreakIndexList[2] = 2; + StreakIndexList[3] = 1; + StreakIndexList[4] = 3; + StreakIndexList[5] = 2; + StreakIndexList[6] = 0; + StreakIndexList[7] = 2; + StreakIndexList[8] = 1; + StreakIndexList[9] = 1; + StreakIndexList[10] = 2; + StreakIndexList[11] = 3; + + RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255); + RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255); + RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255); + RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255); + RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255); + RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255); + RwIm3DVertexSetU(&TraceVertices[0], 0.0); + RwIm3DVertexSetV(&TraceVertices[0], 0.0); + RwIm3DVertexSetU(&TraceVertices[1], 1.0); + RwIm3DVertexSetV(&TraceVertices[1], 0.0); + RwIm3DVertexSetU(&TraceVertices[2], 0.0); + RwIm3DVertexSetV(&TraceVertices[2], 0.5); + RwIm3DVertexSetU(&TraceVertices[3], 1.0); + RwIm3DVertexSetV(&TraceVertices[3], 0.5); + RwIm3DVertexSetU(&TraceVertices[4], 0.0); + RwIm3DVertexSetV(&TraceVertices[4], 1.0); + RwIm3DVertexSetU(&TraceVertices[5], 1.0); + RwIm3DVertexSetV(&TraceVertices[5], 1.0); + + TraceIndexList[0] = 0; + TraceIndexList[1] = 2; + TraceIndexList[2] = 1; + TraceIndexList[3] = 1; + TraceIndexList[4] = 2; + TraceIndexList[5] = 3; + TraceIndexList[6] = 2; + TraceIndexList[7] = 4; + TraceIndexList[8] = 3; + TraceIndexList[9] = 3; + TraceIndexList[10] = 4; + TraceIndexList[11] = 5; + + CMotionBlurStreaks::Init(); + CBrightLights::Init(); + CShinyTexts::Init(); + CMoneyMessages::Init(); + C3dMarkers::Init(); +} + +RwObject* +LookForBatCB(RwObject *object, void *data) +{ + static CMatrix MatLTM; + + if(CVisibilityPlugins::GetAtomicModelInfo((RpAtomic*)object) == (CSimpleModelInfo*)data){ + MatLTM = CMatrix(RwFrameGetLTM(RpAtomicGetFrame((RpAtomic*)object))); + CVector p1 = MatLTM * CVector(0.02f, 0.05f, 0.07f); + CVector p2 = MatLTM * CVector(0.246f, 0.0325f, 0.796f); + CMotionBlurStreaks::RegisterStreak((uintptr)object, 100, 100, 100, p1, p2); + } + return nil; +} + +void +CSpecialFX::Update(void) +{ + CMotionBlurStreaks::Update(); + CBulletTraces::Update(); + + if(FindPlayerPed() && + FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && + FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING) + RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); +} + +void +CSpecialFX::Shutdown(void) +{ + C3dMarkers::Shutdown(); +} + +void +CSpecialFX::Render(void) +{ + CMotionBlurStreaks::Render(); + CBulletTraces::Render(); + CBrightLights::Render(); + CShinyTexts::Render(); + CMoneyMessages::Render(); + C3dMarkers::Render(); +} + +CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS]; + +void +CRegisteredMotionBlurStreak::Update(void) +{ + int i; + bool wasUpdated; + bool lastWasUpdated = false; + for(i = 2; i > 0; i--){ + m_pos1[i] = m_pos1[i-1]; + m_pos2[i] = m_pos2[i-1]; + m_isValid[i] = m_isValid[i-1]; + wasUpdated = true; + if(!lastWasUpdated && !m_isValid[i]) + wasUpdated = false; + lastWasUpdated = wasUpdated; + } + m_isValid[0] = false; + if(!wasUpdated) + m_id = 0; +} + +void +CRegisteredMotionBlurStreak::Render(void) +{ + int i; + int a1, a2; + for(i = 0; i < 2; i++) + if(m_isValid[i] && m_isValid[i+1]){ + a1 = (255/3)*(3-i)/3; + RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1); + RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1); + a2 = (255/3)*(3-(i+1))/3; + RwIm3DVertexSetRGBA(&StreakVertices[2], m_red, m_green, m_blue, a2); + RwIm3DVertexSetRGBA(&StreakVertices[3], m_red, m_green, m_blue, a2); + RwIm3DVertexSetPos(&StreakVertices[0], m_pos1[i].x, m_pos1[i].y, m_pos1[i].z); + RwIm3DVertexSetPos(&StreakVertices[1], m_pos2[i].x, m_pos2[i].y, m_pos2[i].z); + RwIm3DVertexSetPos(&StreakVertices[2], m_pos1[i+1].x, m_pos1[i+1].y, m_pos1[i+1].z); + RwIm3DVertexSetPos(&StreakVertices[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z); + LittleTest(); + if(RwIm3DTransform(StreakVertices, 4, nil, rwIM3D_VERTEXUV)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, StreakIndexList, 12); + RwIm3DEnd(); + } + } +} + +void +CMotionBlurStreaks::Init(void) +{ + int i; + for(i = 0; i < NUMMBLURSTREAKS; i++) + aStreaks[i].m_id = 0; +} + +void +CMotionBlurStreaks::Update(void) +{ + int i; + for(i = 0; i < NUMMBLURSTREAKS; i++) + if(aStreaks[i].m_id) + aStreaks[i].Update(); +} + +void +CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) +{ + int i; + for(i = 0; i < NUMMBLURSTREAKS; i++){ + if(aStreaks[i].m_id == id){ + // Found a streak from last frame, update + aStreaks[i].m_red = r; + aStreaks[i].m_green = g; + aStreaks[i].m_blue = b; + aStreaks[i].m_pos1[0] = p1; + aStreaks[i].m_pos2[0] = p2; + aStreaks[i].m_isValid[0] = true; + return; + } + } + // Find free slot + for(i = 0; aStreaks[i].m_id; i++) + if(i == NUMMBLURSTREAKS-1) + return; + // Create a new streak + aStreaks[i].m_id = id; + aStreaks[i].m_red = r; + aStreaks[i].m_green = g; + aStreaks[i].m_blue = b; + aStreaks[i].m_pos1[0] = p1; + aStreaks[i].m_pos2[0] = p2; + aStreaks[i].m_isValid[0] = true; + aStreaks[i].m_isValid[1] = false; + aStreaks[i].m_isValid[2] = false; +} -WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { EAXJMP(0x519460); } +void +CMotionBlurStreaks::Render(void) +{ + bool setRenderStates = false; + int i; + for(i = 0; i < NUMMBLURSTREAKS; i++) + if(aStreaks[i].m_id){ + if(!setRenderStates){ + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGCOLOR, + (void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); + setRenderStates = true; + } + aStreaks[i].Render(); + } + if(setRenderStates){ + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE); + } +} -CBulletTrace (&CBulletTraces::aTraces)[NUMBULLETTRACES] = *(CBulletTrace(*)[NUMBULLETTRACES])*(uintptr*)0x72B1B8; -RxObjSpace3DVertex (&TraceVertices)[6] = *(RxObjSpace3DVertex(*)[6])*(uintptr*)0x649884;
-RwImVertexIndex (&TraceIndexList)[12] = *(RwImVertexIndex(*)[12])*(uintptr*)0x64986C; +CBulletTrace CBulletTraces::aTraces[NUMBULLETTRACES]; void CBulletTraces::Init(void) { @@ -56,10 +291,10 @@ void CBulletTraces::Render(void) for (int i = 0; i < NUMBULLETTRACES; i++) { if (!aTraces[i].m_bInUse) continue; - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpShadowExplosionTex->raster); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex)); CVector inf = aTraces[i].m_vecCurrentPos; CVector sup = aTraces[i].m_vecTargetPos; CVector center = (inf + sup) / 2; @@ -81,9 +316,9 @@ void CBulletTraces::Render(void) RwIm3DEnd(); } } - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); } void CBulletTraces::Update(void) @@ -115,8 +350,6 @@ void CBulletTrace::Update(void) m_framesInUse++; } -WRAPPER void CBrightLights::RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1, uint8 unk2, uint8 unk3) { EAXJMP(0x51A410); } - RpAtomic * MarkerAtomicCB(RpAtomic *atomic, void *data) { @@ -181,8 +414,7 @@ C3dMarker::Render() { if (m_pAtomic == nil) return; - RwRGBA *color = RpMaterialGetColor(m_pMaterial); - *color = m_Color; + RpMaterialSetColor(m_pMaterial, &m_Color); m_Matrix.UpdateRW(); @@ -201,9 +433,9 @@ C3dMarker::Render() ReSetAmbientAndDirectionalColours(); } -C3dMarker(&C3dMarkers::m_aMarkerArray)[NUM3DMARKERS] = *(C3dMarker(*)[NUM3DMARKERS])*(uintptr*)0x72D408; -int32 &C3dMarkers::NumActiveMarkers = *(int32*)0x8F2A08; -RpClump* (&C3dMarkers::m_pRpClumpArray)[NUMMARKERTYPES] = *(RpClump*(*)[NUMMARKERTYPES])*(uintptr*)0x8E2888; +C3dMarker C3dMarkers::m_aMarkerArray[NUM3DMARKERS]; +int32 C3dMarkers::NumActiveMarkers; +RpClump* C3dMarkers::m_pRpClumpArray[NUMMARKERTYPES]; void C3dMarkers::Init() @@ -402,6 +634,377 @@ C3dMarkers::Update() { } + +#define BRIGHTLIGHTS_MAX_DIST (60.0f) // invisible beyond this +#define BRIGHTLIGHTS_FADE_DIST (45.0f) // strongest between these two +#define CARLIGHTS_MAX_DIST (30.0f) +#define CARLIGHTS_FADE_DIST (15.0f) // 31 for close lights + +int CBrightLights::NumBrightLights; +CBrightLight CBrightLights::aBrightLights[NUMBRIGHTLIGHTS]; + +void +CBrightLights::Init(void) +{ + NumBrightLights = 0; +} + +void +CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front, + uint8 type, uint8 red, uint8 green, uint8 blue) +{ + if(NumBrightLights >= NUMBRIGHTLIGHTS) + return; + + aBrightLights[NumBrightLights].m_camDist = (pos - TheCamera.GetPosition()).Magnitude(); + if(aBrightLights[NumBrightLights].m_camDist > BRIGHTLIGHTS_MAX_DIST) + return; + + aBrightLights[NumBrightLights].m_pos = pos; + aBrightLights[NumBrightLights].m_up = up; + aBrightLights[NumBrightLights].m_side = side; + aBrightLights[NumBrightLights].m_front = front; + aBrightLights[NumBrightLights].m_type = type; + aBrightLights[NumBrightLights].m_red = red; + aBrightLights[NumBrightLights].m_green = green; + aBrightLights[NumBrightLights].m_blue = blue; + + NumBrightLights++; +} + +static float TrafficLightsSide[6] = { -0.09f, 0.09f, 0.162f, 0.09f, -0.09f, -0.162f }; +static float TrafficLightsUp[6] = { 0.162f, 0.162f, 0.0f, -0.162f, -0.162f, 0.0f }; +static float LongCarHeadLightsSide[8] = { -0.2f, 0.2f, -0.2f, 0.2f, -0.2f, 0.2f, -0.2f, 0.2f }; +static float LongCarHeadLightsFront[8] = { 0.1f, 0.1f, -0.1f, -0.1f, 0.1f, 0.1f, -0.1f, -0.1f }; +static float LongCarHeadLightsUp[8] = { 0.1f, 0.1f, 0.1f, 0.1f, -0.1f, -0.1f, -0.1f, -0.1f }; +static float SmallCarHeadLightsSide[8] = { -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f }; +static float SmallCarHeadLightsFront[8] = { 0.08f, 0.08f, -0.08f, -0.08f, 0.08f, 0.08f, -0.08f, -0.08f }; +static float SmallCarHeadLightsUp[8] = { 0.08f, 0.08f, 0.08f, 0.08f, -0.08f, -0.08f, -0.08f, -0.08f }; +static float BigCarHeadLightsSide[8] = { -0.15f, 0.15f, -0.15f, 0.15f, -0.15f, 0.15f, -0.15f, 0.15f }; +static float BigCarHeadLightsFront[8] = { 0.15f, 0.15f, -0.15f, -0.15f, 0.15f, 0.15f, -0.15f, -0.15f }; +static float BigCarHeadLightsUp[8] = { 0.15f, 0.15f, 0.15f, 0.15f, -0.15f, -0.15f, -0.15f, -0.15f }; +static float TallCarHeadLightsSide[8] = { -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f }; +static float TallCarHeadLightsFront[8] = { 0.08f, 0.08f, -0.08f, -0.08f, 0.08f, 0.08f, -0.08f, -0.08f }; +static float TallCarHeadLightsUp[8] = { 0.2f, 0.2f, 0.2f, 0.2f, -0.2f, -0.2f, -0.2f, -0.2f }; +static float SirenLightsSide[6] = { -0.04f, 0.04f, 0.06f, 0.04f, -0.04f, -0.06f }; +static float SirenLightsUp[6] = { 0.06f, 0.06f, 0.0f, -0.06f, -0.06f, 0.0f }; +static RwImVertexIndex TrafficLightIndices[4*3] = { 0, 1, 5, 1, 2, 3, 1, 3, 4, 1, 4, 5 }; +static RwImVertexIndex CubeIndices[12*3] = { + 0, 2, 1, 1, 2, 3, 3, 5, 1, 3, 7, 5, + 2, 7, 3, 2, 6, 7, 4, 0, 1, 4, 1, 5, + 6, 0, 4, 6, 2, 0, 6, 5, 7, 6, 4, 5 +}; + +void +CBrightLights::Render(void) +{ + int i, j; + CVector pos; + + if(NumBrightLights == 0) + return; + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + for(i = 0; i < NumBrightLights; i++){ + if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40) + RenderOutGeometryBuffer(); + + int r, g, b, a; + float flicker = (CGeneral::GetRandomNumber()&0xFF) * 0.2f; + switch(aBrightLights[i].m_type){ + case BRIGHTLIGHT_TRAFFIC_GREEN: + r = flicker; g = 255; b = flicker; + break; + case BRIGHTLIGHT_TRAFFIC_YELLOW: + r = 255; g = 128; b = flicker; + break; + case BRIGHTLIGHT_TRAFFIC_RED: + r = 255; g = flicker; b = flicker; + break; + + case BRIGHTLIGHT_FRONT_LONG: + case BRIGHTLIGHT_FRONT_SMALL: + case BRIGHTLIGHT_FRONT_BIG: + case BRIGHTLIGHT_FRONT_TALL: + r = 255; g = 255; b = 255; + break; + + case BRIGHTLIGHT_REAR_LONG: + case BRIGHTLIGHT_REAR_SMALL: + case BRIGHTLIGHT_REAR_BIG: + case BRIGHTLIGHT_REAR_TALL: + r = 255; g = flicker; b = flicker; + break; + + case BRIGHTLIGHT_SIREN: + r = aBrightLights[i].m_red; + g = aBrightLights[i].m_green; + b = aBrightLights[i].m_blue; + break; + } + + if(aBrightLights[i].m_camDist < BRIGHTLIGHTS_FADE_DIST) + a = 255; + else + a = 255*(1.0f - (aBrightLights[i].m_camDist-BRIGHTLIGHTS_FADE_DIST)/(BRIGHTLIGHTS_MAX_DIST-BRIGHTLIGHTS_FADE_DIST)); + // fade car lights down to 31 as they come near + if(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){ + if(aBrightLights[i].m_camDist < CARLIGHTS_FADE_DIST) + a = 31; + else if(aBrightLights[i].m_camDist < CARLIGHTS_MAX_DIST) + a = 31 + (255-31)*((aBrightLights[i].m_camDist-CARLIGHTS_FADE_DIST)/(CARLIGHTS_MAX_DIST-CARLIGHTS_FADE_DIST)); + } + + switch(aBrightLights[i].m_type){ + case BRIGHTLIGHT_TRAFFIC_GREEN: + case BRIGHTLIGHT_TRAFFIC_YELLOW: + case BRIGHTLIGHT_TRAFFIC_RED: + for(j = 0; j < 6; j++){ + pos = TrafficLightsSide[j]*aBrightLights[i].m_side + + TrafficLightsUp[j]*aBrightLights[i].m_up + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z); + } + for(j = 0; j < 4*3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored+j] = TrafficLightIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 6; + TempBufferIndicesStored += 4*3; + break; + + case BRIGHTLIGHT_FRONT_LONG: + case BRIGHTLIGHT_REAR_LONG: + for(j = 0; j < 8; j++){ + pos = LongCarHeadLightsSide[j]*aBrightLights[i].m_side + + LongCarHeadLightsUp[j]*aBrightLights[i].m_up + + LongCarHeadLightsFront[j]*aBrightLights[i].m_front + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z); + } + for(j = 0; j < 12*3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored+j] = CubeIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 8; + TempBufferIndicesStored += 12*3; + break; + + case BRIGHTLIGHT_FRONT_SMALL: + case BRIGHTLIGHT_REAR_SMALL: + for(j = 0; j < 8; j++){ + pos = SmallCarHeadLightsSide[j]*aBrightLights[i].m_side + + SmallCarHeadLightsUp[j]*aBrightLights[i].m_up + + SmallCarHeadLightsFront[j]*aBrightLights[i].m_front + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z); + } + for(j = 0; j < 12*3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored+j] = CubeIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 8; + TempBufferIndicesStored += 12*3; + break; + + case BRIGHTLIGHT_FRONT_TALL: + case BRIGHTLIGHT_REAR_TALL: + for(j = 0; j < 8; j++){ + pos = TallCarHeadLightsSide[j]*aBrightLights[i].m_side + + TallCarHeadLightsUp[j]*aBrightLights[i].m_up + + TallCarHeadLightsFront[j]*aBrightLights[i].m_front + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z); + } + for(j = 0; j < 12*3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored+j] = CubeIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 8; + TempBufferIndicesStored += 12*3; + break; + + case BRIGHTLIGHT_SIREN: + for(j = 0; j < 6; j++){ + pos = SirenLightsSide[j]*aBrightLights[i].m_side + + SirenLightsUp[j]*aBrightLights[i].m_up + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z); + } + for(j = 0; j < 4*3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored+j] = TrafficLightIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 6; + TempBufferIndicesStored += 4*3; + break; + + } + } + + RenderOutGeometryBuffer(); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + NumBrightLights = 0; +} + +void +CBrightLights::RenderOutGeometryBuffer(void) +{ + if(TempBufferIndicesStored != 0){ + LittleTest(); + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); + RwIm3DEnd(); + } + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + } +} + +int CShinyTexts::NumShinyTexts; +CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS]; + +void +CShinyTexts::Init(void) +{ + NumShinyTexts = 0; +} + +void +CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, + float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, + uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist) +{ + if(NumShinyTexts >= NUMSHINYTEXTS) + return; + + aShinyTexts[NumShinyTexts].m_camDist = (p0 - TheCamera.GetPosition()).Magnitude(); + if(aShinyTexts[NumShinyTexts].m_camDist > maxDist) + return; + aShinyTexts[NumShinyTexts].m_verts[0] = p0; + aShinyTexts[NumShinyTexts].m_verts[1] = p1; + aShinyTexts[NumShinyTexts].m_verts[2] = p2; + aShinyTexts[NumShinyTexts].m_verts[3] = p3; + aShinyTexts[NumShinyTexts].m_texCoords[0].x = u0; + aShinyTexts[NumShinyTexts].m_texCoords[0].y = v0; + aShinyTexts[NumShinyTexts].m_texCoords[1].x = u1; + aShinyTexts[NumShinyTexts].m_texCoords[1].y = v1; + aShinyTexts[NumShinyTexts].m_texCoords[2].x = u2; + aShinyTexts[NumShinyTexts].m_texCoords[2].y = v2; + aShinyTexts[NumShinyTexts].m_texCoords[3].x = u3; + aShinyTexts[NumShinyTexts].m_texCoords[3].y = v3; + aShinyTexts[NumShinyTexts].m_type = type; + aShinyTexts[NumShinyTexts].m_red = red; + aShinyTexts[NumShinyTexts].m_green = green; + aShinyTexts[NumShinyTexts].m_blue = blue; + // Fade out at half the max dist + float halfDist = maxDist*0.5f; + if(aShinyTexts[NumShinyTexts].m_camDist > halfDist){ + float f = 1.0f - (aShinyTexts[NumShinyTexts].m_camDist - halfDist)/halfDist; + aShinyTexts[NumShinyTexts].m_red *= f; + aShinyTexts[NumShinyTexts].m_green *= f; + aShinyTexts[NumShinyTexts].m_blue *= f; + } + + NumShinyTexts++; +} + +void +CShinyTexts::Render(void) +{ + int i, ix, v; + RwTexture *lastTex = nil; + + if(NumShinyTexts == 0) + return; + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + + for(i = 0; i < NumShinyTexts; i++){ + if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-64 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-62) + RenderOutGeometryBuffer(); + + uint8 r = aShinyTexts[i].m_red; + uint8 g = aShinyTexts[i].m_green; + uint8 b = aShinyTexts[i].m_blue; + + switch(aShinyTexts[i].m_type){ + case SHINYTEXT_WALK: + if(lastTex != gpWalkDontTex){ + RenderOutGeometryBuffer(); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpWalkDontTex)); + lastTex = gpWalkDontTex; + } + quad: + v = TempBufferVerticesStored; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_verts[0].x, aShinyTexts[i].m_verts[0].y, aShinyTexts[i].m_verts[0].z); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].x); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].y); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_verts[1].x, aShinyTexts[i].m_verts[1].y, aShinyTexts[i].m_verts[1].z); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].x); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].y); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_verts[2].x, aShinyTexts[i].m_verts[2].y, aShinyTexts[i].m_verts[2].z); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].x); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].y); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_verts[3].x, aShinyTexts[i].m_verts[3].y, aShinyTexts[i].m_verts[3].z); + RwIm3DVertexSetU(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].x); + RwIm3DVertexSetV(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].y); + ix = TempBufferIndicesStored; + TempBufferRenderIndexList[ix+0] = 0 + TempBufferVerticesStored; + TempBufferRenderIndexList[ix+1] = 1 + TempBufferVerticesStored; + TempBufferRenderIndexList[ix+2] = 2 + TempBufferVerticesStored; + TempBufferRenderIndexList[ix+3] = 2 + TempBufferVerticesStored; + TempBufferRenderIndexList[ix+4] = 1 + TempBufferVerticesStored; + TempBufferRenderIndexList[ix+5] = 3 + TempBufferVerticesStored; + TempBufferVerticesStored += 4; + TempBufferIndicesStored += 6; + break; + + case SHINYTEXT_FLAT: + if(lastTex != nil){ + RenderOutGeometryBuffer(); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + lastTex = nil; + } + goto quad; + } + } + + RenderOutGeometryBuffer(); + NumShinyTexts = 0; + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); +} + +void +CShinyTexts::RenderOutGeometryBuffer(void) +{ + if(TempBufferIndicesStored != 0){ + LittleTest(); + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); + RwIm3DEnd(); + } + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + } +} + + + #define MONEY_MESSAGE_LIFETIME_MS 2000 CMoneyMessage CMoneyMessages::aMoneyMessages[NUMMONEYMESSAGES]; @@ -564,6 +1167,16 @@ STARTPATCHES InjectHook(0x51B400, C3dMarkers::Render, PATCH_JUMP); InjectHook(0x51B3B0, C3dMarkers::Shutdown, PATCH_JUMP); + InjectHook(0x5197A0, CBrightLights::Init, PATCH_JUMP); + InjectHook(0x51A410, CBrightLights::RegisterOne, PATCH_JUMP); + InjectHook(0x5197B0, CBrightLights::Render, PATCH_JUMP); + InjectHook(0x51A3B0, CBrightLights::RenderOutGeometryBuffer, PATCH_JUMP); + + InjectHook(0x51A5A0, CShinyTexts::Init, PATCH_JUMP); + InjectHook(0x51AAB0, CShinyTexts::RegisterOne, PATCH_JUMP); + InjectHook(0x51A5B0, CShinyTexts::Render, PATCH_JUMP); + InjectHook(0x51AA50, CShinyTexts::RenderOutGeometryBuffer, PATCH_JUMP); + InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP); InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP); ENDPATCHES diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h index fc155a53..2d9f18b1 100644 --- a/src/render/SpecialFX.h +++ b/src/render/SpecialFX.h @@ -9,10 +9,29 @@ public: static void Shutdown(void); }; +class CRegisteredMotionBlurStreak +{ +public: + uintptr m_id; + uint8 m_red; + uint8 m_green; + uint8 m_blue; + CVector m_pos1[3]; + CVector m_pos2[3]; + bool m_isValid[3]; + + void Update(void); + void Render(void); +}; + class CMotionBlurStreaks { + static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS]; public: - static void RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2); + static void Init(void); + static void Update(void); + static void RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2); + static void Render(void); }; struct CBulletTrace @@ -29,7 +48,7 @@ struct CBulletTrace class CBulletTraces { public: - static CBulletTrace (&aTraces)[NUMBULLETTRACES]; + static CBulletTrace aTraces[NUMBULLETTRACES]; static void Init(void); static void AddTrace(CVector*, CVector*); @@ -37,12 +56,6 @@ public: static void Update(void); }; -class CBrightLights -{ -public: - static void RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1 = 0, uint8 unk2 = 0, uint8 unk3 = 0); -}; - enum { MARKERTYPE_0 = 0, @@ -57,27 +70,27 @@ enum class C3dMarker -{
-public:
- CMatrix m_Matrix;
- RpAtomic *m_pAtomic;
- RpMaterial *m_pMaterial;
- uint16 m_nType;
- bool m_bIsUsed;
- uint32 m_nIdentifier;
- RwRGBA m_Color;
- uint16 m_nPulsePeriod;
- int16 m_nRotateRate;
- uint32 m_nStartTime;
- float m_fPulseFraction;
- float m_fStdSize;
- float m_fSize;
- float m_fBrightness;
- float m_fCameraRange;
-
- bool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
- void DeleteMarkerObject();
- void Render();
+{ +public: + CMatrix m_Matrix; + RpAtomic *m_pAtomic; + RpMaterial *m_pMaterial; + uint16 m_nType; + bool m_bIsUsed; + uint32 m_nIdentifier; + RwRGBA m_Color; + uint16 m_nPulsePeriod; + int16 m_nRotateRate; + uint32 m_nStartTime; + float m_fPulseFraction; + float m_fStdSize; + float m_fSize; + float m_fBrightness; + float m_fCameraRange; + + bool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate); + void DeleteMarkerObject(); + void Render(); }; class C3dMarkers @@ -87,42 +100,125 @@ public: static void Shutdown(); static C3dMarker *PlaceMarker(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate); static void PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate); - static void Render();
+ static void Render(); static void Update(); - static C3dMarker(&m_aMarkerArray)[NUM3DMARKERS]; - static int32 &NumActiveMarkers; - static RpClump* (&m_pRpClumpArray)[NUMMARKERTYPES]; -};
-
-class CMoneyMessage
-{
- friend class CMoneyMessages;
-
- uint32 m_nTimeRegistered;
- CVector m_vecPosition;
- wchar m_aText[16];
- CRGBA m_Colour;
- float m_fSize;
- float m_fOpacity;
-public:
- void Render();
-};
-
-class CMoneyMessages
-{
- static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];
-public:
- static void Init();
- static void Render();
- static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
-};
-
-class CSpecialParticleStuff
-{
- static uint32 BoatFromStart;
-public:
- static void CreateFoamAroundObject(CMatrix*, float, float, float, int32);
- static void StartBoatFoamAnimation();
- static void UpdateBoatFoamAnimation(CMatrix*);
-};
+ static C3dMarker m_aMarkerArray[NUM3DMARKERS]; + static int32 NumActiveMarkers; + static RpClump* m_pRpClumpArray[NUMMARKERTYPES]; +}; + +enum +{ + BRIGHTLIGHT_INVALID, + BRIGHTLIGHT_TRAFFIC_GREEN, + BRIGHTLIGHT_TRAFFIC_YELLOW, + BRIGHTLIGHT_TRAFFIC_RED, + + // white + BRIGHTLIGHT_FRONT_LONG, + BRIGHTLIGHT_FRONT_SMALL, + BRIGHTLIGHT_FRONT_BIG, + BRIGHTLIGHT_FRONT_TALL, + + // red + BRIGHTLIGHT_REAR_LONG, + BRIGHTLIGHT_REAR_SMALL, + BRIGHTLIGHT_REAR_BIG, + BRIGHTLIGHT_REAR_TALL, + + BRIGHTLIGHT_SIREN, // unused + + BRIGHTLIGHT_FRONT = BRIGHTLIGHT_FRONT_LONG, + BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG, +}; + +class CBrightLight +{ +public: + CVector m_pos; + CVector m_up; + CVector m_side; + CVector m_front; + float m_camDist; + uint8 m_type; + uint8 m_red; + uint8 m_green; + uint8 m_blue; +}; + +class CBrightLights +{ + static int NumBrightLights; + static CBrightLight aBrightLights[NUMBRIGHTLIGHTS]; +public: + static void Init(void); + static void RegisterOne(CVector pos, CVector up, CVector side, CVector front, + uint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0); + static void Render(void); + static void RenderOutGeometryBuffer(void); +}; + + +enum +{ + SHINYTEXT_WALK = 1, + SHINYTEXT_FLAT +}; + +class CShinyText +{ +public: + CVector m_verts[4]; + CVector2D m_texCoords[4]; + float m_camDist; + uint8 m_type; + uint8 m_red; + uint8 m_green; + uint8 m_blue; +}; + +class CShinyTexts +{ + static int NumShinyTexts; + static CShinyText aShinyTexts[NUMSHINYTEXTS]; +public: + static void Init(void); + static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, + float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, + uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); + static void Render(void); + static void RenderOutGeometryBuffer(void); +}; + +class CMoneyMessage +{ + friend class CMoneyMessages; + + uint32 m_nTimeRegistered; + CVector m_vecPosition; + wchar m_aText[16]; + CRGBA m_Colour; + float m_fSize; + float m_fOpacity; +public: + void Render(); +}; + +class CMoneyMessages +{ + static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES]; +public: + static void Init(); + static void Render(); + static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity); +}; + +class CSpecialParticleStuff +{ + static uint32 BoatFromStart; +public: + static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); + static void StartBoatFoamAnimation(); + static void UpdateBoatFoamAnimation(CMatrix*); +}; diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 24577f41..8ac2315f 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -30,10 +30,12 @@ CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, out->x *= SCREEN_WIDTH * recip; out->y *= SCREEN_HEIGHT * recip; // What is this? size? - *outw = 70.0f/CDraw::GetFOV(); - *outh = 70.0f/CDraw::GetFOV(); - *outw *= SCREEN_WIDTH * recip; - *outh *= SCREEN_HEIGHT * recip; + *outw = 70.0f/CDraw::GetFOV() * SCREEN_WIDTH * recip; +#ifdef ASPECT_RATIO_SCALE + *outh = 70.0f/CDraw::GetFOV() / (DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO) * SCREEN_HEIGHT * recip; +#else + *outh = 70.0f/CDraw::GetFOV() * SCREEN_HEIGHT * recip; +#endif return true; } @@ -432,6 +434,7 @@ void CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { float screenz, recipz; + float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game screenz = m_f2DNearScreenZ; recipz = m_fRecipNearClipPlane; @@ -496,6 +499,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, float x1, float y1, float x2, float const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { float screenz, recipz; + float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game screenz = m_f2DNearScreenZ; recipz = m_fRecipNearClipPlane; diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index c4dbcdaa..3f21516a 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -267,6 +267,7 @@ CSprite2d::SetVertices(float x1, float y1, float x2, float y2, float x3, float y const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { float screenz, recipz; + float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game screenz = RwIm2DGetNearScreenZ(); recipz = RecipNearClip; @@ -312,10 +313,11 @@ void CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col) { int i; - float screenz, recipz; + float screenz, recipz, z; screenz = RwIm2DGetNearScreenZ(); recipz = RecipNearClip; + z = RwCameraGetNearClipPlane(Scene.camera); // not done by game for(i = 0; i < n; i++){ @@ -334,10 +336,11 @@ void CSprite2d::SetMaskVertices(int n, float *positions) { int i; - float screenz, recipz; + float screenz, recipz, z; screenz = RwIm2DGetNearScreenZ(); recipz = RecipNearClip; + z = RwCameraGetNearClipPlane(Scene.camera); // not done by game for(i = 0; i < n; i++){ RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]); @@ -345,7 +348,7 @@ CSprite2d::SetMaskVertices(int n, float *positions) RwIm2DVertexSetScreenZ(&maVertices[i], screenz); RwIm2DVertexSetCameraZ(&maVertices[i], z); RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz); - RwIm2DVertexSetIntRGBA(&maVertices[i], 0, 0, 0, 0); + RwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255); // 0, 0, 0, 0 on PC } } @@ -353,10 +356,11 @@ void CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2) { - float screenz, recipz; + float screenz, recipz, z; screenz = RwIm2DGetNearScreenZ(); recipz = RecipNearClip; + z = RwCameraGetNearClipPlane(Scene.camera); // not done by game RwIm2DVertexSetScreenX(&verts[0], r.left); RwIm2DVertexSetScreenY(&verts[0], r.top); @@ -459,15 +463,15 @@ CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color) { - SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255)); + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); } diff --git a/src/render/TexList.cpp b/src/render/TexList.cpp new file mode 100644 index 00000000..1689837f --- /dev/null +++ b/src/render/TexList.cpp @@ -0,0 +1,41 @@ +#include "common.h" +#include "TexList.h" +#include "rtbmp.h" +#include "FileMgr.h" + +bool CTexList::ms_nTexUsed[MAX_TEXUSED]; + +void +CTexList::Initialise() +{} + +void +CTexList::Shutdown() +{} + +RwTexture * +CTexList::SetTexture(int32 slot, char *name) +{ + return nil; +} + +int32 +CTexList::GetFirstFreeTexture() +{ + for (int32 i = 0; i < MAX_TEXUSED; i++) + if (!ms_nTexUsed[i]) + return i; + return -1; +} + +RwTexture * +CTexList::LoadFileNameTexture(char *name) +{ + return SetTexture(GetFirstFreeTexture(), name); +} + +void +CTexList::LoadGlobalTextureList() +{ + CFileMgr::SetDir("TEXTURES"); +}
\ No newline at end of file diff --git a/src/render/TexList.h b/src/render/TexList.h new file mode 100644 index 00000000..7e042211 --- /dev/null +++ b/src/render/TexList.h @@ -0,0 +1,14 @@ +#pragma once + +class CTexList +{ + enum { MAX_TEXUSED = 400, }; + static bool ms_nTexUsed[MAX_TEXUSED]; +public: + static void Initialise(); + static void Shutdown(); + static RwTexture *SetTexture(int32 slot, char *name); + static int32 GetFirstFreeTexture(); + static RwTexture *LoadFileNameTexture(char *name); + static void LoadGlobalTextureList(); +};
\ No newline at end of file diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index 235d559c..ed4a026b 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -119,8 +119,10 @@ public: static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; } static float GetSunSize(void) { return m_fCurrentSunSize; } static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; } + static float GetSpriteSize(void) { return m_fCurrentSpriteSize; } static int GetShadowStrength(void) { return m_nCurrentShadowStrength; } static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; } + static int GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; } static float GetFarClip(void) { return m_fCurrentFarClip; } static float GetFogStart(void) { return m_fCurrentFogStart; } @@ -136,6 +138,7 @@ public: static int GetFogRed(void) { return m_nCurrentFogColourRed; } static int GetFogGreen(void) { return m_nCurrentFogColourGreen; } static int GetFogBlue(void) { return m_nCurrentFogColourBlue; } + static int GetFogReduction(void) { return m_FogReduction; } static void Initialise(void); static void Update(void); diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index c1988ab4..b440e77c 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -2,6 +2,22 @@ #include "patcher.h" #include "Weather.h" +#include "Camera.h" +#include "Clock.h" +#include "CutsceneMgr.h" +#include "DMAudio.h" +#include "General.h" +#include "Pad.h" +#include "Particle.h" +#include "RenderBuffer.h" +#include "Stats.h" +#include "Shadows.h" +#include "Timecycle.h" +#include "Timer.h" +#include "Vehicle.h" +#include "World.h" +#include "ZoneCull.h" + int32 &CWeather::SoundHandle = *(int32*)0x5FFBC4; int32 &CWeather::WeatherTypeInList = *(int32*)0x8F626C; @@ -32,13 +48,203 @@ int16 &CWeather::Stored_OldWeatherType = *(int16*)0x95CC68; int16 &CWeather::Stored_NewWeatherType = *(int16*)0x95CCAE; float &CWeather::Stored_Rain = *(float*)0x885B4C; -WRAPPER void CWeather::RenderRainStreaks(void) { EAXJMP(0x524550); } -WRAPPER void CWeather::Update(void) { EAXJMP(0x522C10); } -WRAPPER void CWeather::Init(void) { EAXJMP(0x522BA0); } +tRainStreak Streaks[NUM_RAIN_STREAKS]; -void CWeather::ReleaseWeather() +const int16 WeatherTypesList[] = { + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY, + WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_CLOUDY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_CLOUDY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, WEATHER_CLOUDY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY, + WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_RAINY, WEATHER_CLOUDY, +}; + +const float Windiness[] = { + 0.0f, // WEATHER_SUNNY + 0.7f, // WEATHER_CLOUDY + 1.0f, // WEATHER_RAINY + 0.5f // WEATHER_FOGGY +}; + +#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50) + +#define RAIN_CHANGE_SPEED (0.003f) + +#define DROPLETS_LEFT_OFFSET (10.0f) +#define DROPLETS_RIGHT_OFFSET (10.0f) +#define DROPLETS_TOP_OFFSET (10.0f) +#define DROPLETS_BOTTOM_OFFSET (10.0f) + +#define STREAK_U (10.0f) +#define STREAK_V (18.0f) +#define LARGE_STREAK_COEFFICIENT (1.23f) +#define STREAK_MIN_DISTANCE (8.0f) +#define STREAK_MAX_DISTANCE (16.0f) + +#define SPLASH_CHECK_RADIUS (7.0f) +#define SPLASH_OFFSET_RADIUS (2.0f) + +#define STREAK_LIFETIME (4.0f) +#define STREAK_INTEROLATION_TIME (0.3f) + +#define RAIN_COLOUR_R (200) +#define RAIN_COLOUR_G (200) +#define RAIN_COLOUR_B (256) +#define RAIN_ALPHA (255) + +void CWeather::Init(void) { - ForcedWeatherType = -1; + NewWeatherType = WEATHER_SUNNY; + bScriptsForceRain = false; + OldWeatherType = WEATHER_CLOUDY; + Stored_StateStored = false; + InterpolationValue = 0.0f; + WhenToPlayLightningSound = 0; + WeatherTypeInList = 0; + ForcedWeatherType = WEATHER_RANDOM; + SoundHandle = DMAudio.CreateEntity(AUDIOTYPE_WEATHER, (void*)1); + if (SoundHandle >= 0) + DMAudio.SetEntityStatus(SoundHandle, 1); +} + +void CWeather::Update(void) +{ + float fNewInterpolation = CClock::GetMinutes() * 1.0f / 60; + if (fNewInterpolation < InterpolationValue) { + // new hour + OldWeatherType = NewWeatherType; + if (ForcedWeatherType >= 0) + NewWeatherType = ForcedWeatherType; + else { + WeatherTypeInList = (WeatherTypeInList + 1) % ARRAYSIZE(WeatherTypesList); + NewWeatherType = WeatherTypesList[WeatherTypeInList]; +#ifdef FIX_BUGS + } + if (NewWeatherType == WEATHER_RAINY) + CStats::mmRain += CGeneral::GetRandomNumber() & 7; +#else + if (NewWeatherType == WEATHER_RAINY) + CStats::mmRain += CGeneral::GetRandomNumber() & 7; + } +#endif + } + InterpolationValue = fNewInterpolation; + if (CPad::GetPad(1)->GetRightShockJustDown()) { + NewWeatherType = (NewWeatherType + 1) % WEATHER_TOTAL; + OldWeatherType = NewWeatherType; + } + + // Lightning + if (NewWeatherType != WEATHER_RAINY || OldWeatherType != WEATHER_RAINY) { + LightningFlash = false; + LightningBurst = false; + } + else{ + if (LightningBurst) { + if ((CGeneral::GetRandomNumber() & 255) >= 32) { + // 0.875 probability + if (CTimer::GetTimeInMilliseconds() - LightningFlashLastChange > MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES) { + bool bOldLightningFlash = LightningFlash; + LightningFlash = CGeneral::GetRandomTrueFalse(); + if (LightningFlash != bOldLightningFlash) + LightningFlashLastChange = CTimer::GetTimeInMilliseconds(); + } + } + else { + // 0.125 probability + LightningBurst = false; + LightningDuration = min(CTimer::GetFrameCounter() - LightningStart, 20); + LightningFlash = false; + WhenToPlayLightningSound = CTimer::GetTimeInMilliseconds() + 150 * (20 - LightningDuration); + } + } + else { + if (CGeneral::GetRandomNumber() >= 200) { + // lower probability on PC due to randomness bug + LightningFlash = false; + } + else { + LightningBurst = true; + LightningStart = CTimer::GetFrameCounter(); + LightningFlashLastChange = CTimer::GetTimeInMilliseconds(); + LightningFlash = true; + } + } + } + if (WhenToPlayLightningSound && CTimer::GetTimeInMilliseconds() > WhenToPlayLightningSound) { + DMAudio.PlayOneShot(SoundHandle, SOUND_LIGHTNING, LightningDuration); + CPad::GetPad(0)->StartShake(40 * LightningDuration + 100, 2 * LightningDuration + 80); + WhenToPlayLightningSound = 0; + } + + // Wet roads + if (OldWeatherType == WEATHER_RAINY) { + if (NewWeatherType == WEATHER_RAINY) + WetRoads = 1.0f; + else + WetRoads = 1.0f - InterpolationValue; + } + else { + if (NewWeatherType == WEATHER_RAINY) + WetRoads = InterpolationValue; + else + WetRoads = 0.0f; + } + + // Rain + float fNewRain; + if (NewWeatherType == WEATHER_RAINY) { + // if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s + fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f; + if (OldWeatherType != WEATHER_RAINY) { + if (InterpolationValue < 0.4f) + // if rain has just started (<24 minutes), always 0.5 + fNewRain = 0.5f; + else + // if rain is ongoing for >24 minutes, values: 0.25, 0.5, 0.75, 1.0, switching every ~16.5s + fNewRain = 0.25f + ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.25f; + } + } + else + fNewRain = 0.0f; + if (Rain != fNewRain) { // ok to use comparasion + if (Rain < fNewRain) + Rain = min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); + else + Rain = max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); + } + + // Clouds + if (OldWeatherType != WEATHER_SUNNY) + CloudCoverage = 1.0f - InterpolationValue; + else + CloudCoverage = 0.0f; + if (NewWeatherType != WEATHER_SUNNY) + CloudCoverage += InterpolationValue; + + // Fog + if (OldWeatherType == WEATHER_FOGGY) + Foggyness = 1.0f - InterpolationValue; + else + Foggyness = 0.0f; + if (NewWeatherType == WEATHER_FOGGY) + Foggyness += InterpolationValue; + if (OldWeatherType == WEATHER_RAINY && NewWeatherType == WEATHER_SUNNY && InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21) + Rainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f; + else + Rainbow = 0.0f; + Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType]; + AddRain(); } void CWeather::ForceWeather(int16 weather) @@ -53,6 +259,258 @@ void CWeather::ForceWeatherNow(int16 weather) ForcedWeatherType = weather; } +void CWeather::ReleaseWeather() +{ + ForcedWeatherType = -1; +} + +void CWeather::AddRain() +{ + if (CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) + return; + if (TheCamera.GetLookingLRBFirstPerson()) { + CVehicle* pVehicle = FindPlayerVehicle(); + if (pVehicle && pVehicle->CarHasRoof()) { + CParticle::RemovePSystem(PARTICLE_RAINDROP_2D); + return; + } + } + if (Rain <= 0.1f) + return; + static RwRGBA colour; + float screen_width = RsGlobal.width; + float screen_height = RsGlobal.height; + int cur_frame = (int)(3 * Rain) & 3; + int num_drops = (int)(2 * Rain) + 2; + static int STATIC_RAIN_ANGLE = -45; + static int count = 1500; + static int add_angle = 1; + if (--count == 0) { + count = 1; + if (add_angle) { + STATIC_RAIN_ANGLE += 12; + if (STATIC_RAIN_ANGLE > 45) { + count = 1500; + add_angle = !add_angle; + } + } + else { + STATIC_RAIN_ANGLE -= 12; + if (STATIC_RAIN_ANGLE < -45) { + count = 1500; + add_angle = !add_angle; + } + } + } + float rain_angle = DEGTORAD(STATIC_RAIN_ANGLE + ((STATIC_RAIN_ANGLE < 0) ? 360 : 0)); + float sin_angle = Sin(rain_angle); + float cos_angle = Cos(rain_angle); + float base_x = 0.0f * cos_angle - 1.0f * sin_angle; + float base_y = 1.0f * cos_angle + 0.0f * sin_angle; + CVector xpos(0.0f, 0.0f, 0.0f); + for (int i = 0; i < 2 * num_drops; i++) { + CVector dir; + dir.x = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_x) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f); + dir.y = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_y) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f); + dir.z = 0; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, xpos, dir, nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f), + colour, 0, rain_angle + CGeneral::GetRandomNumberInRange(-10, 10), cur_frame); + xpos.x += screen_width / (2 * num_drops); + xpos.x += CGeneral::GetRandomNumberInRange(-25.0f, 25.0f); + } + CVector ypos(0.0f, 0.0f, 0.0f); + for (int i = 0; i < num_drops; i++) { + CVector dir; + dir.x = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_x) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f); + dir.y = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_y) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f); + dir.z = 0; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, ypos, dir, nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f), + colour, 0, rain_angle + CGeneral::GetRandomNumberInRange(-10, 10), cur_frame); + ypos.y += screen_width / num_drops; + ypos.y += CGeneral::GetRandomNumberInRange(-25.0f, 25.0f); + } + CVector ypos2(0.0f, 0.0f, 0.0f); + for (int i = 0; i < num_drops; i++) { + CVector dir; + dir.x = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_x) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f); + dir.y = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_y) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f); + dir.z = 0; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, ypos2, dir, nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f), + colour, 0, rain_angle + CGeneral::GetRandomNumberInRange(-10, 10), cur_frame); + ypos2.y += screen_width / num_drops; + ypos2.y += CGeneral::GetRandomNumberInRange(-25.0f, 25.0f); + } + for (int i = 0; i < num_drops; i++) { + CVector pos; + pos.x = CGeneral::GetRandomNumberInRange(DROPLETS_LEFT_OFFSET, screen_width - DROPLETS_RIGHT_OFFSET); + pos.y = CGeneral::GetRandomNumberInRange(DROPLETS_TOP_OFFSET, screen_height - DROPLETS_TOP_OFFSET); + pos.z = 0.0f; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f), + colour, CGeneral::GetRandomNumberInRange(-10, 10), 360 - rain_angle + CGeneral::GetRandomNumberInRange(-30, 30), cur_frame, 0); + } + int num_splash_attempts = (int)(3 * Rain) + 1; + int num_splashes = (int)(3 * Rain) + 4; + CVector splash_points[4]; + splash_points[0] = CVector(-RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) * + RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude(); + splash_points[1] = CVector(RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) * + RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude(); + splash_points[2] = 4.0f * CVector(-RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) * + RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude(); + splash_points[3] = 4.0f * CVector(RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) * + RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude(); + RwV3dTransformPoints((RwV3d*)splash_points, (RwV3d*)splash_points, 4, RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera))); + CVector fp = (splash_points[0] + splash_points[1] + splash_points[2] + splash_points[3]) / 4; + for (int i = 0; i < num_splash_attempts; i++) { + CColPoint point; + CEntity* entity; + CVector np = fp + CVector(CGeneral::GetRandomNumberInRange(-SPLASH_CHECK_RADIUS, SPLASH_CHECK_RADIUS), CGeneral::GetRandomNumberInRange(-SPLASH_CHECK_RADIUS, SPLASH_CHECK_RADIUS), 0.0f); + if (CWorld::ProcessVerticalLine(np + CVector(0.0f, 0.0f, 40.0f), -40.0f, point, entity, true, false, false, false, true, false, nil)) { + for (int j = 0; j < num_splashes; j++) + CParticle::AddParticle((CGeneral::GetRandomTrueFalse() ? PARTICLE_RAIN_SPLASH : PARTICLE_RAIN_SPLASHUP), + CVector( + np.x + CGeneral::GetRandomNumberInRange(-SPLASH_OFFSET_RADIUS, SPLASH_OFFSET_RADIUS), + np.y + CGeneral::GetRandomNumberInRange(-SPLASH_OFFSET_RADIUS, SPLASH_OFFSET_RADIUS), + point.point.z + 0.1f), + CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour); + } + } +} + +void RenderOneRainStreak(CVector pos, CVector unused, int intensity, bool scale, float distance) +{ + static float RandomTex; + static float RandomTexX; + static float RandomTexY; + TempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored + 1; + TempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored + 3; + TempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[TempBufferIndicesStored + 6] = TempBufferVerticesStored + 1; + TempBufferRenderIndexList[TempBufferIndicesStored + 7] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[TempBufferIndicesStored + 8] = TempBufferVerticesStored + 4; + TempBufferRenderIndexList[TempBufferIndicesStored + 9] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[TempBufferIndicesStored + 10] = TempBufferVerticesStored + 3; + TempBufferRenderIndexList[TempBufferIndicesStored + 11] = TempBufferVerticesStored + 4; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0, 0, 0, 0); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 0], pos.x + 11.0f * TheCamera.GetUp().x, pos.y + 11.0f * TheCamera.GetUp().y, pos.z + 11.0f * TheCamera.GetUp().z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 1], 0, 0, 0, 0); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 1], pos.x - 9.0f * TheCamera.GetRight().x, pos.y - 9.0f * TheCamera.GetRight().y, pos.z - 9.0f * TheCamera.GetUp().z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RAIN_COLOUR_R * intensity / 256, RAIN_COLOUR_G * intensity / 256, RAIN_COLOUR_B * intensity / 256, RAIN_ALPHA); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 2], pos.x, pos.y, pos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 3], 0, 0, 0, 0); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 3], pos.x + 9.0f * TheCamera.GetRight().x, pos.y + 9.0f * TheCamera.GetRight().y, pos.z + 9.0f * TheCamera.GetUp().z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0, 0, 0, 0); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 4], pos.x - 11.0f * TheCamera.GetUp().x, pos.y - 11.0f * TheCamera.GetUp().y, pos.z - 11.0f * TheCamera.GetUp().z); + float u = STREAK_U; + float v = STREAK_V; + if (scale) { + u *= LARGE_STREAK_COEFFICIENT; + v *= LARGE_STREAK_COEFFICIENT; + } + float distance_coefficient; + if (distance < STREAK_MIN_DISTANCE) + distance_coefficient = 1.0f; + else if (distance > STREAK_MAX_DISTANCE) + distance_coefficient = 0.5f; + else + distance_coefficient = 1.0f - 0.5f * (distance - STREAK_MIN_DISTANCE) / (STREAK_MAX_DISTANCE - STREAK_MIN_DISTANCE); + u *= distance_coefficient; + v *= distance_coefficient; + if (!CTimer::GetIsPaused()) { + RandomTex = ((CGeneral::GetRandomNumber() & 255) - 128) * 0.01f; + RandomTexX = (CGeneral::GetRandomNumber() & 127) * 0.01f; + RandomTexY = (CGeneral::GetRandomNumber() & 127) * 0.01f; + } + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0.5f * u - RandomTex + RandomTexX); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 0], -v * 0.5f + RandomTexY); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexX); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexY); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 2], 0.5f * u + RandomTexX); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RandomTexY); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 3], u + RandomTexX); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 3], RandomTexY); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0.5f * u + RandomTex + RandomTexX); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 5], 0.5f * v + RandomTexY); + TempBufferIndicesStored += 12; + TempBufferVerticesStored += 5; +} + +void CWeather::RenderRainStreaks(void) +{ + if (CTimer::GetIsCodePaused()) + return; + int base_intensity = (64.0f - CTimeCycle::GetFogReduction()) / 64.0f * int(255 * Rain); + if (base_intensity == 0) + return; + TempBufferIndicesStored = 0; + TempBufferVerticesStored = 0; + for (int i = 0; i < NUM_RAIN_STREAKS; i++) { + if (Streaks[i].timer) { + float secondsElapsed = (CTimer::GetTimeInMilliseconds() - Streaks[i].timer) / 1024.0f; + if (secondsElapsed > STREAK_LIFETIME) + Streaks[i].timer = 0; + else{ + int intensity; + if (secondsElapsed < STREAK_INTEROLATION_TIME) + intensity = base_intensity * 0.5f * secondsElapsed / STREAK_INTEROLATION_TIME; + else if (secondsElapsed > (STREAK_LIFETIME - STREAK_INTEROLATION_TIME)) + intensity = (STREAK_LIFETIME - secondsElapsed) * 0.5f * base_intensity / STREAK_INTEROLATION_TIME; + else + intensity = base_intensity * 0.5f; + CVector dir = Streaks[i].direction; + dir.Normalise(); + CVector pos = Streaks[i].position + secondsElapsed * Streaks[i].direction; + RenderOneRainStreak(pos, dir, intensity, false, (pos - TheCamera.GetPosition()).Magnitude()); +#ifndef FIX_BUGS // remove useless code + if (secondsElapsed > 1.0f && secondsElapsed < STREAK_LIFETIME - 1.0f) { + CGeneral::GetRandomNumber(), CGeneral::GetRandomNumber(); + } +#endif + } + } + else if ((CGeneral::GetRandomNumber() & 0xF00) == 0){ + // 1/16 probability + Streaks[i].direction = CVector(4.0f, 4.0f, -4.0f); + Streaks[i].position = 6.0f * TheCamera.GetForward() + TheCamera.GetPosition() + CVector(-1.8f * Streaks[i].direction.x, -1.8f * Streaks[i].direction.y, 8.0f); + if (!CCutsceneMgr::IsRunning()) { + Streaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f; + Streaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f; + } + else + Streaks[i].position += (TheCamera.GetPosition() - TheCamera.m_RealPreviousCameraPosition) * 20.0f; + Streaks[i].position.x += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.08f; + Streaks[i].position.y += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.08f; + Streaks[i].timer = CTimer::GetTimeInMilliseconds(); + } + } + if (TempBufferIndicesStored){ + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex[3])); + if (RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 1)) + { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); + RwIm3DEnd(); + } + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + } + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; +} + void CWeather::StoreWeatherState() { Stored_StateStored = true; @@ -71,4 +529,4 @@ void CWeather::RestoreWeatherState() Rain = Stored_Rain; NewWeatherType = Stored_NewWeatherType; OldWeatherType = Stored_OldWeatherType; -}
\ No newline at end of file +} diff --git a/src/render/Weather.h b/src/render/Weather.h index 63def9b9..9e4ea378 100644 --- a/src/render/Weather.h +++ b/src/render/Weather.h @@ -8,6 +8,14 @@ enum { class CWeather { public: + enum { + WEATHER_RANDOM = -1, + WEATHER_SUNNY = 0, + WEATHER_CLOUDY = 1, + WEATHER_RAINY = 2, + WEATHER_FOGGY = 3, + WEATHER_TOTAL = 4 + }; static int32 &SoundHandle; static int32 &WeatherTypeInList; @@ -46,4 +54,18 @@ public: static void ForceWeatherNow(int16); static void StoreWeatherState(); static void RestoreWeatherState(); + static void AddRain(); }; + +enum { + NUM_RAIN_STREAKS = 35 +}; + +struct tRainStreak +{ + CVector position; + CVector direction; + uint32 timer; +}; + +extern RwTexture* (&gpRainDropTex)[4];
\ No newline at end of file diff --git a/src/render/Lights.cpp b/src/rw/Lights.cpp index cd83a898..cd83a898 100644 --- a/src/render/Lights.cpp +++ b/src/rw/Lights.cpp diff --git a/src/render/Lights.h b/src/rw/Lights.h index 6fdd51de..6fdd51de 100644 --- a/src/render/Lights.h +++ b/src/rw/Lights.h diff --git a/src/render/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 74cd2590..f8b1f6b2 100644 --- a/src/render/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -117,7 +117,7 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera) RpMaterial* SetAlphaCB(RpMaterial *material, void *data) { - material->color.alpha = (uint8)(uint32)data; + ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uint32)data; return material; } diff --git a/src/render/VisibilityPlugins.h b/src/rw/VisibilityPlugins.h index 65d2675a..65d2675a 100644 --- a/src/render/VisibilityPlugins.h +++ b/src/rw/VisibilityPlugins.h |