diff options
Diffstat (limited to '')
60 files changed, 11633 insertions, 3651 deletions
diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index 628d64c2..8ad2b946 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -3,7 +3,9 @@ enum { EFFECT_LIGHT, EFFECT_PARTICLE, - EFFECT_ATTRACTOR + EFFECT_ATTRACTOR, + EFFECT_PED_ATTRACTOR, + EFFECT_SUNGLARE }; enum { @@ -34,6 +36,8 @@ enum { // same order as CPointLights flags, must start at 2 LIGHTFLAG_FOG_NORMAL = 2, // can have light and fog LIGHTFLAG_FOG_ALWAYS = 4, // fog only + LIGHTFLAG_HIDE_OBJECT = 8, // hide the object instead of rendering light (???) + LIGHTFLAG_LONG_DIST = 16, LIGHTFLAG_FOG = (LIGHTFLAG_FOG_NORMAL|LIGHTFLAG_FOG_ALWAYS) }; @@ -63,6 +67,11 @@ public: int8 type; uint8 probability; }; + struct PedAttractor { + CVector queueDir; + CVector useDir; + int8 type; + }; CVector pos; CRGBA col; @@ -71,6 +80,7 @@ public: Light light; Particle particle; Attractor attractor; + PedAttractor pedattr; }; C2dEffect(void) {} @@ -78,14 +88,10 @@ public: if(type == EFFECT_LIGHT){ if(light.corona) RwTextureDestroy(light.corona); -#ifdef GTA3_1_1_PATCH light.corona = nil; -#endif if(light.shadow) RwTextureDestroy(light.shadow); -#ifdef GTA3_1_1_PATCH light.shadow = nil; -#endif } } }; diff --git a/src/render/Antennas.cpp b/src/render/Antennas.cpp index 452069a0..b9da95cb 100644 --- a/src/render/Antennas.cpp +++ b/src/render/Antennas.cpp @@ -2,6 +2,8 @@ #include "Antennas.h" +//--MIAMI: file done + CAntenna CAntennas::aAntennas[NUMANTENNAS]; void diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 05ddbcdc..15bae90b 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -3,6 +3,7 @@ #include "Sprite.h" #include "Sprite2d.h" #include "General.h" +#include "Game.h" #include "Coronas.h" #include "Camera.h" #include "TxdStore.h" @@ -23,8 +24,10 @@ uint32 CClouds::IndividualRotation; float CClouds::ms_cameraRoll; float CClouds::ms_horizonZ; +float CClouds::ms_HorizonTilt; CRGBA CClouds::ms_colourTop; CRGBA CClouds::ms_colourBottom; +CRGBA CClouds::ms_colourBkGrd; void CClouds::Init(void) @@ -44,25 +47,15 @@ void CClouds::Shutdown(void) { RwTextureDestroy(gpCloudTex[0]); -#ifdef GTA3_1_1_PATCH gpCloudTex[0] = nil; -#endif RwTextureDestroy(gpCloudTex[1]); -#ifdef GTA3_1_1_PATCH gpCloudTex[1] = nil; -#endif RwTextureDestroy(gpCloudTex[2]); -#ifdef GTA3_1_1_PATCH gpCloudTex[2] = nil; -#endif RwTextureDestroy(gpCloudTex[3]); -#ifdef GTA3_1_1_PATCH gpCloudTex[3] = nil; -#endif RwTextureDestroy(gpCloudTex[4]); -#ifdef GTA3_1_1_PATCH gpCloudTex[4] = nil; -#endif } void @@ -70,15 +63,15 @@ CClouds::Update(void) { float s = Sin(TheCamera.Orientation - 0.85f); #ifdef FIX_BUGS - CloudRotation += CWeather::Wind*s*0.0025f*CTimer::GetTimeStepFix(); - IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f*CTimer::GetTimeStepFix()) * 60.0f; + CloudRotation += CWeather::Wind*s*0.001f*CTimer::GetTimeStepFix(); + IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f*CTimer::GetTimeStepFix()) * 60.0f; #else - CloudRotation += CWeather::Wind*s*0.0025f; - IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f) * 60.0f; + CloudRotation += CWeather::Wind*s*0.001f; + IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f; #endif } -float StarCoorsX[9] = { 0.0f, 0.05f, 0.12f, 0.5f, 0.8f, 0.6f, 0.27f, 0.55f, 0.75f }; +float StarCoorsX[9] = { 0.0f, 0.05f, 0.13f, 0.4f, 0.7f, 0.6f, 0.27f, 0.55f, 0.75f }; float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f }; float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f }; @@ -123,6 +116,9 @@ CClouds::Render(void) RwV3d screenpos; RwV3d worldpos; + if(!CGame::CanSeeOutSideFromCurrArea()) + return; + CCoronas::SunBlockedByClouds = false; RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -132,25 +128,20 @@ CClouds::Render(void) RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); CSprite::InitSpriteBuffer(); - int minute = CClock::GetHours()*60 + CClock::GetMinutes(); + float minute = CClock::GetHours()*60 + CClock::GetMinutes() + CClock::GetSeconds()/60.0f; RwV3d campos = *(RwV3d*)&TheCamera.GetPosition(); // Moon - int moonfadeout = Abs(minute - 180); // fully visible at 3AM - if(moonfadeout < 180){ // fade in/out 3 hours + float moonfadeout = Abs(minute - 180.0f); // fully visible at 3AM + if((int)moonfadeout < 180){ // fade in/out 3 hours float coverage = Max(CWeather::Foggyness, CWeather::CloudCoverage); - int brightness = (1.0f - coverage) * (180 - moonfadeout); + int brightness = (1.0f - coverage) * (180 - (int)moonfadeout); RwV3d pos = { 0.0f, -100.0f, 15.0f }; RwV3dAdd(&worldpos, &campos, &pos); if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2])); - if(CCoronas::bSmallMoon){ - szx *= 4.0f; - szy *= 4.0f; - }else{ - szx *= 10.0f; - szy *= 10.0f; - } + szx *= CCoronas::MoonSize*2.0f + 4.0f; + szy *= CCoronas::MoonSize*2.0f + 4.0f; CSprite::RenderOneXLUSprite(screenpos.x, screenpos.y, screenpos.z, szx, szy, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255); } @@ -199,7 +190,7 @@ CClouds::Render(void) } // Low clouds - float lowcloudintensity = 1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage); + float lowcloudintensity = 1.0f - Max(Max(CWeather::Foggyness, CWeather::CloudCoverage), CWeather::ExtraSunnyness); int r = CTimeCycle::GetLowCloudsRed() * lowcloudintensity; int g = CTimeCycle::GetLowCloudsGreen() * lowcloudintensity; int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity; @@ -220,10 +211,10 @@ CClouds::Render(void) // Fluffy clouds float rot_sin = Sin(CloudRotation); float rot_cos = Cos(CloudRotation); - int fluffyalpha = 160 * (1.0f - CWeather::Foggyness); + int fluffyalpha = 160 * (1.0f - Max(CWeather::Foggyness, CWeather::ExtraSunnyness)); if(fluffyalpha != 0){ static bool bCloudOnScreen[37]; - float hilight; + float sundist, hilight; RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); @@ -235,15 +226,16 @@ CClouds::Render(void) worldpos.z = pos.z; if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){ - float sundist = Sqrt(sq(screenpos.x-CCoronas::SunScreenX) + sq(screenpos.y-CCoronas::SunScreenY)); + sundist = Sqrt(sq(screenpos.x-CCoronas::SunScreenX) + sq(screenpos.y-CCoronas::SunScreenY)); int tr = CTimeCycle::GetFluffyCloudsTopRed(); int tg = CTimeCycle::GetFluffyCloudsTopGreen(); int tb = CTimeCycle::GetFluffyCloudsTopBlue(); int br = CTimeCycle::GetFluffyCloudsBottomRed(); int bg = CTimeCycle::GetFluffyCloudsBottomGreen(); int bb = CTimeCycle::GetFluffyCloudsBottomBlue(); - if(sundist < SCREEN_WIDTH/2){ - hilight = (1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage)) * (1.0f - sundist/(SCREEN_WIDTH/2)); + int distLimit = (3*SCREEN_WIDTH)/4; + if(sundist < distLimit){ + hilight = (1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage)) * (1.0f - sundist/(float)distLimit); tr = tr*(1.0f-hilight) + 255*hilight; tg = tg*(1.0f-hilight) + 190*hilight; tb = tb*(1.0f-hilight) + 190*hilight; @@ -277,8 +269,7 @@ CClouds::Render(void) worldpos.y = campos.x*rot_sin + campos.y*rot_cos + pos.y; worldpos.z = pos.z; if(bCloudOnScreen[i] && CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){ - // BUG: this is stupid....would have to do this for each cloud individually - if(hilight > 0.0f){ + if(sundist < SCREEN_WIDTH/3){ CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(screenpos.x, screenpos.y, screenpos.z, szx*30.0f, szy*30.0f, 200*hilight, 0, 0, 255, 1.0f/screenpos.z, @@ -322,14 +313,17 @@ void CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue, int16 botred, int16 botgreen, int16 botblue, int16 alpha) { - CVector left = TheCamera.GetRight(); - float c = left.Magnitude2D(); + CVector right = CrossProduct(TheCamera.GetUp(), TheCamera.GetForward()); + right.Normalise(); + float c = right.Magnitude2D(); if(c > 1.0f) c = 1.0f; ms_cameraRoll = Acos(c); - if(left.z < 0.0f) + if(right.z < 0.0f) ms_cameraRoll = -ms_cameraRoll; + ms_HorizonTilt = SCREEN_WIDTH/2.0f * Tan(ms_cameraRoll); + if(UseDarkBackground()){ ms_colourTop.r = 50; ms_colourTop.g = 50; @@ -352,75 +346,74 @@ CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue, }else{ ms_horizonZ = CSprite::CalcHorizonCoors(); + int fogr = (topred + 2 * botred) / 3; + int fogg = (topgreen + 2 * botgreen) / 3; + int fogb = (topblue + 2 * botblue) / 3; + // Draw top/bottom gradient float gradheight = SCREEN_HEIGHT/2.0f; - float topedge = ms_horizonZ - gradheight; - float botpos, toppos; - if(ms_horizonZ > 0.0f && topedge < SCREEN_HEIGHT){ - ms_colourTop.r = topred; - ms_colourTop.g = topgreen; - ms_colourTop.b = topblue; - ms_colourTop.a = alpha; - ms_colourBottom.r = botred; - ms_colourBottom.g = botgreen; - ms_colourBottom.b = botblue; - ms_colourBottom.a = alpha; - - if(ms_horizonZ < SCREEN_HEIGHT) - botpos = ms_horizonZ; - else{ - float f = (ms_horizonZ - SCREEN_HEIGHT)/gradheight; - ms_colourBottom.r = topred*f + (1.0f-f)*botred; - ms_colourBottom.g = topgreen*f + (1.0f-f)*botgreen; - ms_colourBottom.b = topblue*f + (1.0f-f)*botblue; - botpos = SCREEN_HEIGHT; - } - if(topedge >= 0.0f) - toppos = topedge; - else{ - float f = (0.0f - topedge)/gradheight; - ms_colourTop.r = botred*f + (1.0f-f)*topred; - ms_colourTop.g = botgreen*f + (1.0f-f)*topgreen; - ms_colourTop.b = botblue*f + (1.0f-f)*topblue; - toppos = 0.0f; - } - CSprite2d::DrawRect(CRect(0, toppos, SCREEN_WIDTH, botpos), - ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); - } + + ms_colourTop.r = topred; + ms_colourTop.g = topgreen; + ms_colourTop.b = topblue; + ms_colourTop.a = alpha; + ms_colourBottom.r = botred; + ms_colourBottom.g = botgreen; + ms_colourBottom.b = botblue; + ms_colourBottom.a = alpha; + + float botright = ms_horizonZ - ms_HorizonTilt; + float botleft = ms_horizonZ + ms_HorizonTilt; + float topright = botright - gradheight; + float topleft = botleft - gradheight; + + CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright, + ms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom); // draw the small stripe (whatever it's supposed to be) - if(ms_horizonZ > -SMALLSTRIPHEIGHT && ms_horizonZ < SCREEN_HEIGHT){ - // Same colour as fog - ms_colourTop.r = (topred + 2 * botred) / 3; - ms_colourTop.g = (topgreen + 2 * botgreen) / 3; - ms_colourTop.b = (topblue + 2 * botblue) / 3; - CSprite2d::DrawRect(CRect(0, ms_horizonZ, SCREEN_WIDTH, ms_horizonZ+SMALLSTRIPHEIGHT), - ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop); - } + ms_colourTop.r = fogr; + ms_colourTop.g = fogg; + ms_colourTop.b = fogb; + ms_colourTop.a = alpha; + topright = ms_horizonZ - ms_HorizonTilt; + topleft = ms_horizonZ + ms_HorizonTilt; + botright = topright + SMALLSTRIPHEIGHT; + botleft = topleft + SMALLSTRIPHEIGHT; + CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright, + ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop); // Only top - if(topedge > 0.0f){ + if(ms_horizonZ + ms_HorizonTilt - gradheight > 0.0f || + ms_horizonZ - ms_HorizonTilt - gradheight > 0.0f){ ms_colourTop.r = topred; ms_colourTop.g = topgreen; ms_colourTop.b = topblue; ms_colourTop.a = alpha; - ms_colourBottom.r = topred; - ms_colourBottom.g = topgreen; - ms_colourBottom.b = topblue; - ms_colourBottom.a = alpha; - - botpos = Min(SCREEN_HEIGHT, topedge); - CSprite2d::DrawRect(CRect(0, 0, SCREEN_WIDTH, botpos), - ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); + + if(ms_horizonZ - Abs(ms_HorizonTilt) - gradheight > SCREEN_HEIGHT){ + // only top is visible + topleft = 0.0f; + topright = 0.0f; + botleft = SCREEN_HEIGHT; + botright = SCREEN_HEIGHT; + }else{ + botright = ms_horizonZ - ms_HorizonTilt - gradheight; + botleft = ms_horizonZ + ms_HorizonTilt - gradheight; + topright = Min(ms_horizonZ - ms_HorizonTilt - 2*SCREEN_HEIGHT, 0.0f); + topleft = Min(ms_horizonZ + ms_HorizonTilt - 2*SCREEN_HEIGHT, 0.0f); + } + + CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright, + ms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop); } // Set both to fog colour for RenderHorizon - ms_colourTop.r = (topred + 2 * botred) / 3; - ms_colourTop.g = (topgreen + 2 * botgreen) / 3; - ms_colourTop.b = (topblue + 2 * botblue) / 3; - ms_colourBottom.r = (topred + 2 * botred) / 3; - ms_colourBottom.g = (topgreen + 2 * botgreen) / 3; - ms_colourBottom.b = (topblue + 2 * botblue) / 3; + ms_colourTop.r = fogr; + ms_colourTop.g = fogg; + ms_colourTop.b = fogb; + ms_colourBottom.r = fogr; + ms_colourBottom.g = fogg; + ms_colourBottom.b = fogb; } } @@ -433,21 +426,35 @@ CClouds::RenderHorizon(void) ms_colourBottom.a = 230; ms_colourTop.a = 80; - if(ms_horizonZ > SCREEN_HEIGHT) - return; + float topright = ms_horizonZ - ms_HorizonTilt; + float topleft = ms_horizonZ + ms_HorizonTilt; + float botright = topright + SMALLSTRIPHEIGHT; + float botleft = topleft + SMALLSTRIPHEIGHT; + + CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright, + ms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom); + + + ms_colourBkGrd.r = 128.0f*CTimeCycle::GetAmbientRed(); + ms_colourBkGrd.g = 128.0f*CTimeCycle::GetAmbientGreen(); + ms_colourBkGrd.b = 128.0f*CTimeCycle::GetAmbientBlue(); + ms_colourBkGrd.a = 255; + + float horzstrip = SCREEN_STRETCH_Y(HORIZSTRIPHEIGHT); + topright = botright; + topleft = botleft; + botright = topright + horzstrip; + botleft = topleft + horzstrip; + + CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright, + ms_colourBottom, ms_colourBottom, ms_colourBkGrd, ms_colourBkGrd); + + + topright = botright; + topleft = botleft; + botright = Max(topright, SCREEN_HEIGHT); + botleft = Max(topleft, SCREEN_HEIGHT); - float z1 = Min(ms_horizonZ + SMALLSTRIPHEIGHT, SCREEN_HEIGHT); - CSprite2d::DrawRectXLU(CRect(0, ms_horizonZ, SCREEN_WIDTH, z1), - ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); - - // This is just weird - float a = SCREEN_HEIGHT/400.0f * HORIZSTRIPHEIGHT + - SCREEN_HEIGHT/300.0f * Max(TheCamera.GetPosition().z, 0.0f); - float b = TheCamera.GetUp().z < 0.0f ? - SCREEN_HEIGHT : - SCREEN_HEIGHT * Abs(TheCamera.GetRight().z); - float z2 = z1 + (a + b)*TheCamera.LODDistMultiplier; - z2 = Min(z2, SCREEN_HEIGHT); - CSprite2d::DrawRect(CRect(0, z1, SCREEN_WIDTH, z2), - ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); + CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright, + ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd); } diff --git a/src/render/Clouds.h b/src/render/Clouds.h index 4d8cd2c8..ef33030b 100644 --- a/src/render/Clouds.h +++ b/src/render/Clouds.h @@ -8,8 +8,10 @@ public: static float ms_cameraRoll; static float ms_horizonZ; + static float ms_HorizonTilt; static CRGBA ms_colourTop; static CRGBA ms_colourBottom; + static CRGBA ms_colourBkGrd; static void Init(void); static void Shutdown(void); diff --git a/src/render/Console.cpp b/src/render/Console.cpp index 8ea5b7a3..244bfb17 100644 --- a/src/render/Console.cpp +++ b/src/render/Console.cpp @@ -63,7 +63,7 @@ CConsole::Display() CFont::SetJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); #ifndef FIX_BUGS CFont::SetPropOff(); // not sure why this is here anyway #endif diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 33c3f4bf..c40577d7 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -2,6 +2,7 @@ #include "main.h" #include "General.h" +#include "RenderBuffer.h" #include "TxdStore.h" #include "Camera.h" #include "Sprite.h" @@ -12,6 +13,8 @@ #include "Timecycle.h" #include "Coronas.h" +//--MIAMI: file done + struct FlareDef { float position; @@ -53,7 +56,7 @@ RwTexture *gpCoronaTexture[9] = { nil, nil, nil, nil, nil, nil, nil, nil, nil }; float CCoronas::LightsMult = 1.0f; float CCoronas::SunScreenX; float CCoronas::SunScreenY; -bool CCoronas::bSmallMoon; +int CCoronas::MoonSize; bool CCoronas::SunBlockedByClouds; int CCoronas::bChangeBrightnessImmediately; @@ -129,13 +132,22 @@ CCoronas::Update(void) void CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, const CVector &coors, float size, float drawDist, RwTexture *tex, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle) + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool useNearDist, float nearDist) { int i; if(sq(drawDist) < (TheCamera.GetPosition() - coors).MagnitudeSqr2D()) return; + if(useNearDist){ + float dist = (TheCamera.GetPosition() - coors).Magnitude(); + if(dist < 35.0f) + return; + if(dist < 50.0f) + alpha *= (dist - 35.0f)/(50.0f - 35.0f); + } + for(i = 0; i < NUMCORONAS; i++) if(aCoronas[i].id == id) break; @@ -188,15 +200,19 @@ CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 al aCoronas[i].reflection = reflection; aCoronas[i].LOScheck = LOScheck; aCoronas[i].drawStreak = drawStreak; + aCoronas[i].useNearDist = useNearDist; + aCoronas[i].nearDist = nearDist; } void CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, - const CVector &coors, float size, float drawDist, uint8 type, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle) + const CVector &coors, float size, float drawDist, uint8 type, + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool useNearDist, float nearDist) { RegisterCorona(id, red, green, blue, alpha, coors, size, drawDist, - gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle); + gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle, + useNearDist, nearDist); } void @@ -309,7 +325,7 @@ CCoronas::Render(void) if(CCoronas::aCoronas[i].id == SUN_CORE) spriteCoors.z = 0.95f * RwCameraGetFarClipPlane(Scene.camera); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aCoronas[i].texture)); - spriteCoors.z -= 1.5f; + spriteCoors.z -= aCoronas[i].nearDist; if(aCoronas[i].texture == gpCoronaTexture[8]){ // what's this? @@ -371,7 +387,7 @@ CCoronas::Render(void) } } - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); @@ -423,9 +439,7 @@ CCoronas::RenderReflections(void) CEntity *entity; if(CWeather::WetRoads > 0.0f){ -#ifdef FIX_BUGS CSprite::InitSpriteBuffer(); -#endif RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -506,6 +520,130 @@ CCoronas::RenderReflections(void) } } +void +CCoronas::RenderSunReflection(void) +{ + float sunZDir = CTimeCycle::GetSunDirection().z; + if(sunZDir > -0.05f){ + float intensity = (0.3f - Abs(sunZDir - 0.25f))/0.3f * + (1.0f - CWeather::CloudCoverage) * + (1.0f - CWeather::Foggyness) * + (1.0f - CWeather::Wind); + if(intensity > 0.0f){ + int r = (CTimeCycle::GetSunCoreRed() + CTimeCycle::GetSunCoronaRed())*intensity*0.25f; + int g = (CTimeCycle::GetSunCoreGreen() + CTimeCycle::GetSunCoronaGreen())*intensity*0.25f; + int b = (CTimeCycle::GetSunCoreBlue() + CTimeCycle::GetSunCoronaBlue())*intensity*0.25f; + + CVector sunPos = 40.0f*CTimeCycle::GetSunDirection() + TheCamera.GetPosition(); + sunPos.z = 0.5f*CWeather::Wind + 6.1f; + CVector sunDir = CTimeCycle::GetSunDirection(); + sunDir.z = 0.0; + sunDir.Normalise(); + + TempBufferIndicesStored = 6; + TempBufferRenderIndexList[0] = 2; + TempBufferRenderIndexList[1] = 1; + TempBufferRenderIndexList[2] = 0; + TempBufferRenderIndexList[3] = 2; + TempBufferRenderIndexList[4] = 3; + TempBufferRenderIndexList[5] = 1; + + // 60 unit square in sun direction + TempBufferVerticesStored = 4; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[0], + sunPos.x + 30.0f*sunDir.y, + sunPos.y - 30.0f*sunDir.x, + sunPos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[1], + sunPos.x - 30.0f*sunDir.y, + sunPos.y + 30.0f*sunDir.x, + sunPos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[2], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[2], + sunPos.x + 60.0f*sunDir.x + 30.0f*sunDir.y, + sunPos.y + 60.0f*sunDir.y - 30.0f*sunDir.x, + sunPos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[3], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[3], + sunPos.x + 60.0f*sunDir.x - 30.0f*sunDir.y, + sunPos.y + 60.0f*sunDir.y + 30.0f*sunDir.x, + sunPos.z); + + RwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[0], 1.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[1], 1.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[2], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[2], 0.5f); + RwIm3DVertexSetU(&TempBufferRenderVertices[3], 1.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[3], 0.5f); + + int timeInc = 0; + int sideInc = 0; + int fwdInc = 0; + for(int i = 0; i < 20; i++){ + TempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored; + TempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored-1; + TempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored-2; + TempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored; + TempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored+1; + TempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored-1; + TempBufferIndicesStored += 6; + + // What a weird way to do it... + float fwdLen = fwdInc/20 + 60; + float sideLen = sideInc/20 + 30; + sideLen += 10.0f*Sin((float)(CTimer::GetTimeInMilliseconds()+timeInc & 0x7FF)/0x800*TWOPI); + timeInc += 900; + sideInc += 970; + fwdInc += 1440; + + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0], + sunPos.x + fwdLen*sunDir.x + sideLen*sunDir.y, + sunPos.y + fwdLen*sunDir.y - sideLen*sunDir.x, + sunPos.z); + + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], r, g, b, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1], + sunPos.x + fwdLen*sunDir.x - sideLen*sunDir.y, + sunPos.y + fwdLen*sunDir.y + sideLen*sunDir.x, + sunPos.z); + + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.5f); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 0.5f); + TempBufferVerticesStored += 2; + } + + + 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(gpCoronaTexture[4])); + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){ + 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 CCoronas::DoSunAndMoon(void) { @@ -522,7 +660,7 @@ CCoronas::DoSunAndMoon(void) 255, sunCoors, size, 999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f); - if(CTimeCycle::GetSunDirection().z > 0.0f) + if(CTimeCycle::GetSunDirection().z > 0.0f && !CGame::IsInInterior()) RegisterCorona(SUN_CORONA, CTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(), 255, sunCoors, 25.0f * CTimeCycle::GetSunSize(), diff --git a/src/render/Coronas.h b/src/render/Coronas.h index 46eb4315..45f027d8 100644 --- a/src/render/Coronas.h +++ b/src/render/Coronas.h @@ -4,19 +4,21 @@ extern RwTexture *gpCoronaTexture[9]; struct CRegisteredCorona { + CVector coors; uint32 id; uint32 lastLOScheck; RwTexture *texture; + float size; + float someAngle; + float drawDist; + float nearDist; + float heightAboveRoad; uint8 red; uint8 green; uint8 blue; uint8 alpha; // alpha when fully visible uint8 fadeAlpha; // actual value used for rendering, faded - CVector coors; - float size; - float someAngle; bool registeredThisFrame; - float drawDist; int8 flareType; int8 reflection; @@ -25,12 +27,11 @@ struct CRegisteredCorona uint8 firstUpdate : 1; uint8 drawStreak : 1; uint8 sightClear : 1; + uint8 useNearDist : 1; + uint8 renderReflection : 1; - bool renderReflection; - float heightAboveRoad; - - float prevX[6]; - float prevY[6]; + int16 prevX[6]; + int16 prevY[6]; uint8 prevRed[6]; uint8 prevGreen[6]; uint8 prevBlue[6]; @@ -39,7 +40,7 @@ struct CRegisteredCorona void Update(void); }; -VALIDATE_SIZE(CRegisteredCorona, 0x80); +VALIDATE_SIZE(CRegisteredCorona, 0x68); class CCoronas { @@ -81,7 +82,7 @@ public: static float LightsMult; static float SunScreenY; static float SunScreenX; - static bool bSmallMoon; + static int MoonSize; static bool SunBlockedByClouds; static int bChangeBrightnessImmediately; @@ -90,12 +91,15 @@ public: static void Update(void); static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, const CVector &coors, float size, float drawDist, RwTexture *tex, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle); + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool useNearDist = false, float nearDist = 1.5f); static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, const CVector &coors, float size, float drawDist, uint8 type, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle); + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool useNearDist = false, float nearDist = 1.5f); static void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle); static void Render(void); static void RenderReflections(void); + static void RenderSunReflection(void); static void DoSunAndMoon(void); }; diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index 6b28ff04..75342bad 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -7,6 +7,9 @@ #include "Camera.h" #include "Text.h" #include "Credits.h" +#include "Pad.h" + +// --MIAMI: file done bool CCredits::bCreditsGoing; uint32 CCredits::CreditsStartTime; @@ -39,13 +42,21 @@ CCredits::PrintCreditSpace(float space, uint32 &line) void CCredits::PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset) { - float start = DEFAULT_SCREEN_HEIGHT + 50.0f; - float y = lineoffset + start - scrolloffset; - if(y > -50.0f && y < start){ - CFont::SetScale(SCREEN_SCALE_X(scaleX), SCREEN_SCALE_Y(scaleY)); - CFont::PrintString(SCREEN_WIDTH/2.0f, SCREEN_SCALE_Y(y), (uint16*)text); + CPad::UpdatePads(); + if (CPad::GetPad(0)->GetCrossJustDown()) + bCreditsGoing = false; + else { + float start = DEFAULT_SCREEN_HEIGHT + 20.0f; + float y = lineoffset + start - scrolloffset; + if (y > 20.0f && DEFAULT_SCREEN_HEIGHT - 20.0f > y) { + CFont::SetScale(SCREEN_SCALE_X(scaleX), SCREEN_SCALE_Y(scaleY)); + CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::PrintString(SCREEN_WIDTH / 2.0f, SCREEN_SCALE_Y(y), (uint16*)text); + CFont::SetColor(CRGBA(220, 220, 220, 220)); + CFont::PrintString(SCREEN_WIDTH / 2.0f - SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(y - 1.0f), (uint16*)text); + } + lineoffset += scaleY*25.0f; } - lineoffset += scaleY*25.0f; } void @@ -62,430 +73,733 @@ CCredits::Render(void) scrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f; CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - 20)); + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.75f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetColor(CRGBA(220, 220, 220, 220)); - CFont::SetFontStyle(FONT_HEADING); - - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED002"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED003"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED004"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED005"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED006"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED007"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED008"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED009"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED010"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED011"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED012"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED013"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED014"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED015"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED016"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED017"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED018"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED019"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED020"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED021"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED022"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED245"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED023"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED024"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED025"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED026"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED027"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED028"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED257"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED029"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED030"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED031"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED032"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED033"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED244"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED034"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED035"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED247"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED036"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED037"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED038"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED039"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED040"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED041"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED042"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED043"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED044"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED045"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED046"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED047"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED048"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED049"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED050"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRD050A"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED051"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED052"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED053"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED054"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED055"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED056"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED248"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED249"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED250"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED251"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED252"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED253"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED057"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED058"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED059"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED254"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED255"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED060"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED061"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED062"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED063"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED064"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED065"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED066"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED067"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED068"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED069"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED070"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED071"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED072"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED073"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED074"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED075"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED076"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED077"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED078"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED079"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED080"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED081"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED082"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED083"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED084"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED242"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED259"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED260"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED261"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED262"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED085"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED086"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED087"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED088"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED089"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED090"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED091"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED094"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED095"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED096"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED097"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED098"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED099"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED263"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED264"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED265"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED267"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED270"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED266"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED100"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED101"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED102"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED103"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED104"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED105"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED106"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED268"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED269"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED107"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED108"), lineoffset, scrolloffset); - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED109"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED110"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED111"), lineoffset, scrolloffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED112"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED113"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED114"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED115"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED116"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED117"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED118"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED119"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED120"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED121"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED122"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED123"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED124"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED125"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED126"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED127"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED128"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED129"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED130"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED131"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED132"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED133"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED134"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED135"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED136"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD136A"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED137"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD137A"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED138"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD138A"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD138B"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED139"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.7f, 1.0f, TheText.Get("CRED140"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140A"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140B"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140C"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140D"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140E"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED141"), lineoffset, scrolloffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED142"), lineoffset, scrolloffset); - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED143"), lineoffset, scrolloffset); - PrintCreditSpace(1.0f, lineoffset); - PrintCreditText(1.0f, 1.0f, TheText.Get("CRED144"), lineoffset, scrolloffset); - PrintCreditSpace(1.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED145"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED146"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED147"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED148"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED149"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED150"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED151"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED152"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED153"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED154"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED155"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED156"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED157"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED158"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED159"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED160"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED161"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED162"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED163"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED164"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED165"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED166"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED167"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED168"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED169"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED170"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED171"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED172"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED173"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED174"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED175"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED176"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED177"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED178"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED179"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED180"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED181"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED182"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED183"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED184"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED185"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED186"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED187"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED188"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED189"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED190"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED191"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED192"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED193"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED194"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED195"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED196"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED197"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED198"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED199"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED200"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED201"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED202"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED203"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED204"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED205"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED206"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED207"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED208"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED209"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED210"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED211"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED212"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED213"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED214"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED215"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED216"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED241"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED217"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED218"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD218A"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRD218B"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED219"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED220"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED221"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED222"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED223"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED224"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED225"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED226"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED227"), lineoffset, scrolloffset); - PrintCreditSpace(1.5f, lineoffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED228"), lineoffset, scrolloffset); - PrintCreditText(1.7f, 1.7f, TheText.Get("CRED229"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.4f, 0.82f, TheText.Get("CRED230"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED231"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED232"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED233"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED234"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED235"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED236"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED237"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED238"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED239"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED240"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("LITTLE"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("NICK"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED243"), lineoffset, scrolloffset); - PrintCreditText(1.4f, 1.4f, TheText.Get("CRED244"), lineoffset, scrolloffset); - PrintCreditSpace(2.0f, lineoffset); - PrintCreditSpace(2.0f, lineoffset); - - - CFont::DrawFonts(); + CFont::SetFontStyle(FONT_STANDARD); + + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED001"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED002"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED003"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED004"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED005"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED006"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED007"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED008"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED025"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED026"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED027"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED028"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED029"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED030"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED031"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031C"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD031D"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD031E"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD024A"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED024"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED023"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD023A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD023B"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED018"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED019"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD018A"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD019A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD019B"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED020"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED021"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD022A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED022"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD022B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD022C"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED032"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED033"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD032A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED034"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED035"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED036"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED037"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD037A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD037B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD037C"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD041B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED042"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED039"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED044"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED040"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD042A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED142"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD142A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED009"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED010"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED011"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED012"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED013"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD013A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD013B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD013C"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED089"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED090"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED347"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED047"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED048"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED049"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED348"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED050"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED051"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED052"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED053"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED054"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED055"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED056"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056C"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD056D"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED349"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED350"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED351"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED352"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED353"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED354"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED355"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED356"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED357"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED359"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED360"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED361"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED362"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED363"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED364"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED365"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED366"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED367"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED368"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED369"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED370"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED371"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED372"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED373"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED256"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED257"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED258"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED057"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED058"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD057A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED059"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD060A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD060B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD060C"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD002A"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED003"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD001A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD001B"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED060"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED061"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED062"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED063"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED064"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED069"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED070"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED065"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED066"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED067"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED068"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD071A"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD072A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED091"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED094"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED095"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED097"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED098"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD098A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD098B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD098C"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED099"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED096"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED273"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD092A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED092"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD092B"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED073"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED074"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED076"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED075"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED077"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED078"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED081"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED082"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED079"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED080"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED083"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED084"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084C"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD084D"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD084E"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED085"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED086"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD086A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED087"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED088"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088A"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088B"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088C"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088D"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088E"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088F"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD088G"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED107"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED108"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED109"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED110"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD110A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED111"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED112"), lineoffset, scrolloffset); + + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED113"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED114"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED115"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED116"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED117"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED118"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED119"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED120"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED121"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED122"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED123"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED124"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED125"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED126"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED127"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED128"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED129"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.8f)); + + PrintCreditText(1.1f, 0.8f, TheText.Get("CRD111A"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED130"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED131"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED132"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED133"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED134"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134A"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134B"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134C"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134D"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134E"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134F"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134G"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134H"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD134I"), lineoffset, scrolloffset); + + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.7f)); + + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED135"), lineoffset, scrolloffset); + + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD136A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD137A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED138"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED066"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD138B"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED139"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.1f, 0.8f, TheText.Get("CRED140"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH) + PrintCreditSpace(0.5f, lineoffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140A"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140B"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140C"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140D"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140E"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140F"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140G"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140H"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140I"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140J"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140K"), lineoffset, scrolloffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD140L"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.85f)); + + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED259"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED260"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED261"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED262"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED263"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED264"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED265"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED266"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED141"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD141A"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD141B"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED143"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED144"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED145"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED146"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED147"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED148"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED149"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED150"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED151"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED152"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED153"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED154"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED155"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED156"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED157"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED158"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED159"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED160"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED161"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED162"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED163"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED164"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED165"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED166"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED167"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED168"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED169"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED170"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED171"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED172"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.75f)); + + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED217"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED218"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRD218A"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED219"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED220"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED221"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED222"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED223"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.1f, 1.1f, TheText.Get("CRED224"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED227"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED228"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED229"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD229A"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD229B"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED274"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED275"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED276"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED277"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED278"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED279"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED280"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED281"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED282"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED283"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED284"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED285"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED286"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED287"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED288"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED289"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED290"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED291"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED292"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED293"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED294"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED295"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED296"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED297"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED298"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED299"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED300"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED301"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED302"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED303"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED304"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED305"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED306"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED307"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED308"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED309"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED310"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED314"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED315"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED316"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED317"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED318"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED319"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED320"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED321"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED322"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED323"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED324"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED325"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED326"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED327"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED328"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED329"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED330"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED331"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED332"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.8f)); + + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED333"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED334"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED335"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED336"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED337"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED338"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED339"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED340"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED341"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED342"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD344A"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED344"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED345"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRD345A"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED346"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(1.0f, lineoffset); + + PrintCreditSpace(1.5f, lineoffset); + + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH * 0.75f)); + + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED267"), lineoffset, scrolloffset); + PrintCreditSpace(0.5f, lineoffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED268"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED269"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED270"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED271"), lineoffset, scrolloffset); + PrintCreditText(0.65f, 0.65f, TheText.Get("CRED272"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(0.95f, 0.7f, TheText.Get("CRED230"), lineoffset, scrolloffset); + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) + PrintCreditSpace(0.5f, lineoffset); + + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED231"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED232"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED233"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED234"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED235"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED236"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED237"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED238"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED239"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED240"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED241"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED242"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED243"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED244"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED245"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED246"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED247"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED248"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED249"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED358"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED250"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED251"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED252"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRD251A"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRD252A"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED253"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED254"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED374"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED375"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED376"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED377"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED378"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED379"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED380"), lineoffset, scrolloffset); + PrintCreditText(0.95f, 0.95f, TheText.Get("CRED381"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditSpace(1.5f, lineoffset); + CFont::DrawFonts(); if(TheCamera.m_WideScreenOn) TheCamera.DrawBordersForWideScreen(); diff --git a/src/render/CutsceneShadow.cpp b/src/render/CutsceneShadow.cpp new file mode 100644 index 00000000..8cb33896 --- /dev/null +++ b/src/render/CutsceneShadow.cpp @@ -0,0 +1,269 @@ +#include "common.h" +#include "main.h" +#include "rwcore.h" +#include "rwplcore.h" +#include "CutsceneShadow.h" +#include "RwHelper.h" + +#define DLIGHT_VALUE 0.8f /* Directional light intensity */ + + +CCutsceneShadow::CCutsceneShadow() +{ + m_pAtomic = nil; + m_nRwObjectType = -1; + m_pLight = nil; + m_nBlurPasses = 0; + m_bResample = false; + m_bGradient = false; +} + +CCutsceneShadow::~CCutsceneShadow() +{ + Destroy(); +} + +bool +CCutsceneShadow::Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient) +{ + ASSERT(object != nil); + + RwRGBAReal color; + RwFrame *frame; + + if (!object) + return false; + + m_pLight = RpLightCreate(rpLIGHTDIRECTIONAL); + ASSERT(m_pLight != nil); + + if (!m_pLight) + return false; + + color.red = color.green = color.blue = DLIGHT_VALUE; + color.alpha = 0.0f; + + RpLightSetColor(m_pLight, &color); + + frame = RwFrameCreate(); + ASSERT(frame != nil); + + RpLightSetFrame(m_pLight, frame); + + SetLightProperties(180.0f, 90.0f, false); + + m_pObject = object; + m_nRwObjectType = RwObjectGetType(m_pObject); + + switch ( m_nRwObjectType ) + { + case rpCLUMP: + { + RpClumpGetBoundingSphere(m_pClump, &m_BoundingSphere, 1); + m_BaseSphere.radius = m_BoundingSphere.radius; + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump))); + break; + } + + case rpATOMIC: + { + m_BoundingSphere = *RpAtomicGetBoundingSphere(m_pAtomic); + m_BaseSphere.radius = m_BoundingSphere.radius; + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic))); + break; + } + + default: + { + Destroy(); + return false; + break; + } + } + + if ( !m_Camera.Create(rasterSize) ) + { + Destroy(); + return false; + } + + m_nBlurPasses = blurPasses; + m_bResample = resample; + m_bGradient = gradient; + + if ( m_bResample && !m_ResampleCamera.Create(rasterSize - 1) ) + { + Destroy(); + return false; + } + + if ( m_nBlurPasses != 0 ) + { + if ( !m_BlurCamera.Create(resample ? rasterSize - 1 : rasterSize) ) + { + Destroy(); + return false; + } + } + + if ( m_bGradient ) + { + if ( !m_GradientCamera.Create(resample ? rasterSize - 1 : rasterSize) ) + { + Destroy(); + return false; + } + + m_GradientCamera.MakeGradientRaster(); + } + + m_Camera.SetLight(m_pLight); + + switch ( m_nRwObjectType ) + { + case rpATOMIC: + m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius); + break; + + case rpCLUMP: + m_Camera.SetFrustum(1.1f * m_BoundingSphere.radius); + break; + } + + m_Camera.SetCenter(&m_BaseSphere.center); + return true; +} + +RwFrame * +CCutsceneShadow::SetLightProperties(float angleY, float angleX, bool setLight) +{ + ASSERT(m_pLight != nil); + + RwFrame *frame; + static RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; + static RwV3d Yaxis = { 0.0f, 1.0f, 0.0f }; + + frame = RpLightGetFrame(m_pLight); + ASSERT(frame != nil); + + if ( !frame ) + return nil; + + RwFrameRotate(frame, &Yaxis, angleY, rwCOMBINEREPLACE); + RwFrameRotate(frame, &Xaxis, angleX, rwCOMBINEPOSTCONCAT); + + if ( setLight ) + m_Camera.SetLight(m_pLight); + + return frame; +} + +bool +CCutsceneShadow::IsInitialized() +{ + return m_pObject != nil; +} + +void +CCutsceneShadow::Destroy() +{ + m_Camera.Destroy(); + m_ResampleCamera.Destroy(); + m_BlurCamera.Destroy(); + m_GradientCamera.Destroy(); + + m_pAtomic = nil; + + m_nRwObjectType = -1; + + if (m_pLight) + { + RwFrame *frame = RpLightGetFrame(m_pLight); + RpLightSetFrame(m_pLight, nil); + RwFrameDestroy(frame); + RpLightDestroy(m_pLight); + m_pLight = nil; + } +} + +RwRaster * +CCutsceneShadow::Update() +{ + switch ( m_nRwObjectType ) + { + case rpCLUMP: + ASSERT(m_pClump != nil); + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump))); + break; + + case rpATOMIC: + ASSERT(m_pAtomic != nil); + RwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic))); + break; + } + + m_Camera.SetCenter(&m_BaseSphere.center); + + switch ( m_nRwObjectType ) + { + case rpCLUMP: + m_Camera.Update(m_pClump); + break; + + case rpATOMIC: + m_Camera.Update(m_pAtomic); + break; + } + + RwRaster *raster = m_Camera.GetRwRenderRaster(); + ASSERT(raster != nil); + + if ( m_bResample ) + return m_ResampleCamera.RasterResample(raster); + + if ( m_nBlurPasses ) + return m_BlurCamera.RasterBlur(raster, m_nBlurPasses); + + if ( m_bGradient ) + return m_GradientCamera.RasterGradient(raster); + + return raster; +} + +RwTexture * +CCutsceneShadow::UpdateForCutscene() +{ + Update(); + return GetShadowRwTexture(); +} + +CShadowCamera * +CCutsceneShadow::GetShadowCamera(int32 camType) +{ + switch ( camType ) + { + case RESAMPLE: return &m_ResampleCamera; + case BLUR: return &m_BlurCamera; + case GRADIENT: return &m_GradientCamera; + } + + return &m_Camera; +} + +RwTexture * +CCutsceneShadow::GetShadowRwTexture() +{ + if ( m_bResample ) + return m_ResampleCamera.GetRwRenderTexture(); + else + return m_Camera.GetRwRenderTexture(); +} + +void +CCutsceneShadow::DrawBorderAroundTexture(RwRGBA const& color) +{ + if ( m_bResample ) + m_ResampleCamera.DrawOutlineBorder(color); + else + m_Camera.DrawOutlineBorder(color); +}
\ No newline at end of file diff --git a/src/render/CutsceneShadow.h b/src/render/CutsceneShadow.h new file mode 100644 index 00000000..a59fe78f --- /dev/null +++ b/src/render/CutsceneShadow.h @@ -0,0 +1,52 @@ +#pragma once +#include "ShadowCamera.h" + +class CCutsceneShadow +{ +public: + enum + { + RASTER = 0, + RESAMPLE, + BLUR, + GRADIENT, + }; + + CShadowCamera m_Camera; + bool m_bResample; + CShadowCamera m_ResampleCamera; + int32 m_nBlurPasses; + CShadowCamera m_BlurCamera; + bool m_bGradient; + CShadowCamera m_GradientCamera; + + union + { + RwObject *m_pObject; + RpAtomic *m_pAtomic; + RpClump *m_pClump; + }; + + int32 m_nRwObjectType; + RpLight *m_pLight; + RwSphere m_BoundingSphere; + RwSphere m_BaseSphere; + + CCutsceneShadow(); + ~CCutsceneShadow(); + + RwSphere GetBaseSphere() + { + return m_BaseSphere; + } + + bool Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient); + RwFrame *SetLightProperties(float angleY, float angleX, bool setLight); + bool IsInitialized(); + void Destroy(); + RwRaster *Update(); + RwTexture *UpdateForCutscene(); + CShadowCamera *GetShadowCamera(int32 camType = RASTER); + RwTexture *GetShadowRwTexture(); + void DrawBorderAroundTexture(RwRGBA const& color); +}; diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index 4e323ec2..912399c9 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -21,24 +21,28 @@ uint8 CDraw::FadeGreen; uint8 CDraw::FadeBlue; float -CDraw::FindAspectRatio(void) +CDraw::CalculateAspectRatio(void) { -#ifndef ASPECT_RATIO_SCALE - if(FrontEndMenuManager.m_PrefsUseWideScreen) - return 16.0f/9.0f; - else - return 4.0f/3.0f; + if (FrontEndMenuManager.m_PrefsUseWideScreen) { +#ifdef ASPECT_RATIO_SCALE + if (TheCamera.m_WideScreenOn) + CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? + (5.f / 3.f) * (SCREEN_WIDTH / SCREEN_HEIGHT) / (16.f / 9.f) : + 5.f / 3.f; // It's used on theatrical showings according to Wiki + else + CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? SCREEN_WIDTH / SCREEN_HEIGHT : 16.f / 9.f; #else - switch (FrontEndMenuManager.m_PrefsUseWideScreen) { - case AR_AUTO: - return SCREEN_WIDTH / SCREEN_HEIGHT; - default: - case AR_4_3: - return 4.0f / 3.0f; - case AR_16_9: - return 16.0f / 9.0f; - }; + if (TheCamera.m_WideScreenOn) + CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki + else + CDraw::ms_fAspectRatio = 16.f / 9.f; #endif + } else if (TheCamera.m_WideScreenOn) { + CDraw::ms_fAspectRatio = 5.f/4.f; + } else { + CDraw::ms_fAspectRatio = 4.f/3.f; + } + return CDraw::ms_fAspectRatio; } #ifdef ASPECT_RATIO_SCALE @@ -80,4 +84,4 @@ ScaleAndCenterX(float x) else return (SCREEN_WIDTH - SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)) / 2 + SCREEN_SCALE_X(x); } -#endif
\ No newline at end of file +#endif
\ No newline at end of file diff --git a/src/render/Draw.h b/src/render/Draw.h index 5c4f95b1..2976dc34 100644 --- a/src/render/Draw.h +++ b/src/render/Draw.h @@ -44,12 +44,10 @@ public: static float GetScaledFOV(void) { return ms_fFOV; } #endif - static float FindAspectRatio(void); + static float CalculateAspectRatio(void); #ifdef ASPECT_RATIO_SCALE static float ConvertFOV(float fov); +#endif static float GetAspectRatio(void) { return ms_fAspectRatio; } static void SetAspectRatio(float ratio) { ms_fAspectRatio = ratio; } -#else - static float GetAspectRatio(void) { return FindAspectRatio(); } -#endif }; diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 690a1d3f..19a172fb 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -1,11 +1,15 @@ #include "common.h" #include "main.h" +#include "RenderBuffer.h" #include "Entity.h" #include "Fluff.h" #include "Camera.h" #include "Sprite.h" #include "Coronas.h" +#include "PointLights.h" +#include "Rubbish.h" +#include "Timecycle.h" #include "General.h" #include "Timer.h" #include "Clock.h" @@ -13,6 +17,292 @@ #include "Stats.h" #include "maths.h" #include "Frontend.h" +#include "CutsceneMgr.h" +#include "PlayerPed.h" +#include "Bones.h" +#include "World.h" +#include "Replay.h" + +CPlaneTrail CPlaneTrails::aArray[6]; +RwImVertexIndex TrailIndices[32] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 +}; + +void +CPlaneTrail::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(m_time); i++) + m_time[i] = 0; +} + +void +CPlaneTrail::Render(float visibility) +{ + int i; + int numVerts = 0; + if(!TheCamera.IsSphereVisible(m_pos[0], 1000.0f)) + return; + + int alpha = visibility*110.0f; + if(alpha == 0) + return; + + for(i = 0; i < ARRAY_SIZE(m_pos); i++){ + int32 time = CTimer::GetTimeInMilliseconds() - m_time[i]; + if(time > 30000) + m_time[i] = 0; + if(m_time[i] != 0){ + float fade = (30000.0f - time) / 10000.0f; + fade = Min(fade, 1.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[numVerts], 255, 255, 255, (int)(alpha*fade)); + RwIm3DVertexSetPos(&TempBufferRenderVertices[numVerts], m_pos[i].x, m_pos[i].y, m_pos[i].z); + numVerts++; + } + } + if(numVerts > 1){ + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + if(RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, TrailIndices, (numVerts-1)*2); + RwIm3DEnd(); + } + } +} + +void +CPlaneTrail::RegisterPoint(CVector pos) +{ + int i; + bool bNewPoint = false; + if(m_time[0] != 0 && CTimer::GetTimeInMilliseconds() - m_time[0] > 2000){ + bNewPoint = true; + for(i = ARRAY_SIZE(m_pos)-1; i > 0; i--){ + m_pos[i] = m_pos[i-1]; + m_time[i] = m_time[i-1]; + } + } + m_pos[0] = pos; + if(bNewPoint || m_time[0] == 0) + m_time[0] = CTimer::GetTimeInMilliseconds(); +} + +void +CPlaneTrails::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Init(); +} + +void +CPlaneTrails::Update(void) +{ + CVector planePos; + + planePos.x = 1590.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.y = 1200.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.z = 550.0f; + RegisterPoint(planePos, 3); + if(CClock::GetHours() > 22 || CClock::GetHours() < 7){ + if(CTimer::GetTimeInMilliseconds() & 0x200) + CCoronas::RegisterCorona(101, 255, 0, 0, 255, planePos, 5.0f, 2000.0f, + CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::UpdateCoronaCoors(101, planePos, 2000.0f, 0.0f); + } + + planePos.x = 1000.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.y = -1600.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.z = 500.0f; + RegisterPoint(planePos, 4); + if(CClock::GetHours() > 22 || CClock::GetHours() < 7){ + if(CTimer::GetTimeInMilliseconds() & 0x200) + CCoronas::RegisterCorona(102, 255, 0, 0, 255, planePos, 5.0f, 2000.0f, + CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::UpdateCoronaCoors(102, planePos, 2000.0f, 0.0f); + } + + planePos.x = 1100.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.y = 700.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.z = 600.0f; + RegisterPoint(planePos, 5); + if(CClock::GetHours() > 22 || CClock::GetHours() < 7){ + if(CTimer::GetTimeInMilliseconds() & 0x200) + CCoronas::RegisterCorona(103, 255, 0, 0, 255, planePos, 5.0f, 2000.0f, + CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::UpdateCoronaCoors(103, planePos, 2000.0f, 0.0f); + } +} + +void +CPlaneTrails::Render(void) +{ + int i; + float visibility = Min(1.0f-CWeather::Foggyness, 1.0f-CWeather::CloudCoverage); + visibility = Min(visibility, 1.0f-CWeather::Rain); + visibility = Min(Max(Max(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen()), CTimeCycle::GetSkyTopBlue())/256.0f, visibility); + if(visibility > 0.0001f) + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Render(visibility); +} + +void +CPlaneTrails::RegisterPoint(CVector pos, uint32 id) +{ + aArray[id].RegisterPoint(pos); +} + + + +CPlaneBanner CPlaneBanners::aArray[5]; + +void +CPlaneBanner::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(m_pos); i++){ + m_pos[i].x = i; + m_pos[i].y = 0.0f; + m_pos[i].z = -60.0f; + } +} + +void +CPlaneBanner::Update(void) +{ + int i; + if(m_pos[0].z > -50.0f){ + m_pos[0].z -= 0.05f*CTimer::GetTimeStep(); + m_pos[0].z = Max(m_pos[0].z, -100.0f); + for(i = 1; i < ARRAY_SIZE(m_pos); i++){ + CVector dist = m_pos[i] - m_pos[i-1]; + float len = dist.Magnitude(); + if(len > 8.0f) + m_pos[i] = m_pos[i-1] + dist/len*8.0f; + } + } +} + +void +CPlaneBanner::Render(void) +{ + int i; + if(m_pos[0].z > -50.0f){ + float camDist = (TheCamera.GetPosition() - m_pos[0]).Magnitude(); + if(TheCamera.IsSphereVisible(m_pos[4], 32.0f) && camDist < 300.0f){ + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + int alpha = camDist < 250.0f ? 160 : (300.0f-camDist)/(300.0f-250.0f)*160; + + TempBufferVerticesStored += 2; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, alpha); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[0], m_pos[2].x, m_pos[2].y, m_pos[2].z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[1], m_pos[2].x, m_pos[2].y, m_pos[2].z - 4.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[0], 0.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[1], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f); + for(i = 2; i < 8; i++){ + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], 255, 255, 255, alpha); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0], m_pos[i].x, m_pos[i].y, m_pos[i].z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1], m_pos[i].x, m_pos[i].y, m_pos[i].z - 4.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], (i-2)/5.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], (i-2)/5.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f); + TempBufferRenderIndexList[TempBufferIndicesStored+0] = TempBufferVerticesStored-2; + TempBufferRenderIndexList[TempBufferIndicesStored+1] = TempBufferVerticesStored-1; + TempBufferRenderIndexList[TempBufferIndicesStored+2] = TempBufferVerticesStored+1; + TempBufferRenderIndexList[TempBufferIndicesStored+3] = TempBufferVerticesStored-2; + TempBufferRenderIndexList[TempBufferIndicesStored+4] = TempBufferVerticesStored+1; + TempBufferRenderIndexList[TempBufferIndicesStored+5] = TempBufferVerticesStored; + TempBufferVerticesStored += 2; + TempBufferIndicesStored += 6; + } + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[2])); + +#ifdef FIX_BUGS + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV|rwIM3D_VERTEXRGBA)){ +#else + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 0)){ +#endif + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); + RwIm3DEnd(); + } + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + } + } +} + +void +CPlaneBanner::RegisterPoint(CVector pos) +{ + m_pos[0] = pos; +} + +void +CPlaneBanners::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Init(); +} + +void +CPlaneBanners::Update(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Update(); +} + +void +CPlaneBanners::Render(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Render(); +} + +void +CPlaneBanners::RegisterPoint(CVector pos, uint32 id) +{ + aArray[id].RegisterPoint(pos); +} + +bool CSmokeTrails::CigOn = false; +CSmokeTrail CSmokeTrails::aSmoke[3]; + +RwImVertexIndex SmokeTrailIndices[32] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, +9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 }; + +float RandomSmoke[16] = { 10.0f, 5.0f, -1.0f, -9.0f, -7.0f, -1.0f, 0.0f, 3.0f, 6.0f, 7.0f, 4.0f, 2.0f, +5.0f, 7.0f }; uint8 ScrollCharSet[59][5] = { { 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' ' @@ -96,15 +386,25 @@ CMovingThing CMovingThings::StartCloseList; CMovingThing CMovingThings::EndCloseList; int16 CMovingThings::Num; CMovingThing CMovingThings::aMovingThings[NUMMOVINGTHINGS]; + +int32 CScrollBar::TonightsEvent; void CMovingThings::Init() { + CPlaneTrails::Init(); + CSmokeTrails::Init(); + CPlaneBanners::Init(); + CPointLights::Init(); + StartCloseList.m_pNext = &CMovingThings::EndCloseList; StartCloseList.m_pPrev = nil; EndCloseList.m_pNext = nil; EndCloseList.m_pPrev = &CMovingThings::StartCloseList; Num = 0; - + + CEscalators::Init(); + +#ifndef MIAMI // something is still used here actually // Initialize scroll bars aScrollBars[0].Init(CVector( 228.3f, -669.0f, 39.0f ), SCROLL_BUSINESS, 0.0f, 0.5f, 0.5f, 255, 128, 0, 0.3f); aScrollBars[1].Init(CVector( 772.0f, 164.0f, -9.5f ), SCROLL_TRAFFIC, 0.0f, 0.5f, 0.25f, 128, 255, 0, 0.3f); @@ -137,6 +437,7 @@ void CMovingThings::Init() CVector(58.145f - sz.y * 0.05f - sz.x * 0.3f, -1079.268f + sz.x * 0.05f - sz.y * 0.3f, 32.803f), -sz.x, -sz.y, 0, 255, 0, 100.0f, 0.8f ); +#endif } void CMovingThings::Shutdown() @@ -144,18 +445,25 @@ void CMovingThings::Shutdown() int i; for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i) aScrollBars[i].SetVisibility(false); +/* for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i) aTowerClocks[i].SetVisibility(false); for (i = 0; i < ARRAY_SIZE(aDigitalClocks); ++i) aDigitalClocks[i].SetVisibility(false); +*/ + CEscalators::Shutdown(); } void CMovingThings::Update() { - int16 i; -#ifndef SQUEEZE_PERFORMANCE + CPlaneBanners::Update(); + CPlaneTrails::Update(); + CEscalators::Update(); + const int TIME_SPAN = 64; // frames to process all aMovingThings + int16 i; + int block = CTimer::GetFrameCounter() % TIME_SPAN; for (i = (block * NUMMOVINGTHINGS) / TIME_SPAN; i < ((block + 1) * NUMMOVINGTHINGS) / TIME_SPAN; i++) { @@ -167,8 +475,7 @@ void CMovingThings::Update() if (aMovingThings[i].m_nHidden == 0) aMovingThings[i].Update(); } -#endif - + /* I don't think these are done yet? for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i) { if (aScrollBars[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0) @@ -184,16 +491,20 @@ void CMovingThings::Update() if (aDigitalClocks[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0) aDigitalClocks[i].Update(); } + */ } void CMovingThings::Render() { + CSmokeTrails::Update(); + int i; for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i) { if (aScrollBars[i].IsVisible()) aScrollBars[i].Render(); } +/* for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i) { if (aTowerClocks[i].IsVisible()) @@ -204,6 +515,11 @@ void CMovingThings::Render() if (aDigitalClocks[i].IsVisible()) aDigitalClocks[i].Render(); } +*/ + + CPlaneTrails::Render(); + CSmokeTrails::Render(); + CPlaneBanners::Render(); } // ---------- CMovingThing ---------- @@ -382,7 +698,7 @@ void CScrollBar::Update() m_pMessage = FindTimeMessage(); break; case 6: - if (CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN) + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN) m_pMessage = FindTimeMessage(); else m_pMessage = "WWW.GRANDTHEFTAUTO3.COM "; @@ -602,7 +918,7 @@ void CScrollBar::Update() m_pMessage = "FREE FLUFFY DICE WITH ALL PURCHASES. . ."; break; case 9: - if (CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN) + if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN) m_pMessage = "QUICK, TAKE A LOOK AT OUR CURRENT STOCK )CAUSE THESE AUTOS ARE MOVIN) FAST . . . "; else m_pMessage = "HTTP:((ROCKSTARGAMES.COM(GRANDTHEFTAUTO3(CAPITALAUTOS "; @@ -866,3 +1182,537 @@ void CDigitalClock::Render() CSprite::FlushSpriteBuffer(); } } + +void +CSmokeTrail::RegisterPoint(CVector regPosition, float opacity) { + bool bAddedNewPoint = false; + + if (m_time[0] && CTimer::GetTimeInMilliseconds() - m_time[0] > 150) { + bAddedNewPoint = true; + for (int32 i = 15; i > 0; i--) { + m_pos[i] = m_pos[i - 1]; + m_time[i] = m_time[i - 1]; + m_opacity[i] = m_opacity[i - 1]; + } + ++m_seed; + } + m_pos[0] = regPosition; + + if (bAddedNewPoint || !m_time[0]) { + m_time[0] = CTimer::GetTimeInMilliseconds(); + float density = 0.1f / (m_pos[1] - m_pos[2]).Magnitude(); + m_opacity[1] = opacity * Min(density, 1.0f); + } + m_opacity[0] = 0.0f; +} + +void +CSmokeTrail::Init(int num) { + for (int32 i = 0; i < 16; i++) + m_time[i] = 0; + m_seed = num * 2; +} + +void +CSmokeTrails::Init(void) { + for (int32 i = 0; i < 3; i++) + aSmoke[i].Init(i); +} + +void +CSmokeTrails::Render(void) { + for (int32 i = 0; i < 3; i++) + aSmoke[i].Render(); +} + +void +CSmokeTrail::Render(void) { + int numVerts = 0; + + if (TheCamera.IsSphereVisible(m_pos[0], 10.0f)) { + for (int32 i = 0; i < 16; i++) { + int timeSinceSpawned = CTimer::GetTimeInMilliseconds() - m_time[i]; + + if (timeSinceSpawned > 2250) + m_time[i] = 0; + + if (m_time[i]) { + int alpha = (1.0f - timeSinceSpawned / 2250.0f) * 110.0f * m_opacity[i]; + float offset = timeSinceSpawned * CWeather::Wind * 0.0001f; + float posX = (m_pos[i].x + timeSinceSpawned * RandomSmoke[(i - m_seed) & 0xF] * 0.00001f) - offset; + float posY = (m_pos[i].y + timeSinceSpawned * RandomSmoke[(i - m_seed + 5) & 0xF] * 0.00001f) - offset; + float posZ = m_pos[i].z + timeSinceSpawned * 0.0004f; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 200, 200, 200, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[i], posX, posY, posZ); + numVerts++; + } + } + } + + if (numVerts > 1) { + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + if (RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2 * (numVerts - 1)); + RwIm3DEnd(); + } + } +} + +void +CSmokeTrails::Update(void) { + + if (!CSmokeTrails::CigOn || TheCamera.Using1stPersonWeaponMode() || !FindPlayerPed() || + FindPlayerVehicle() || CCutsceneMgr::IsRunning() || !FindPlayerPed()->GetClump()) + return; + + RwV3d startPos = { 0.026f, 0.15f, 0.02f }; + RwV3d endPos = { 0.026f, 0.05f, 0.02f }; + + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(FindPlayerPed()->GetClump()); + int32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD)); + RwMatrix *head = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwV3dTransformPoints(&startPos, &startPos, 1, head); + RwV3dTransformPoints(&endPos, &endPos, 1, head); + + aSmoke[0].RegisterPoint(startPos, 1.0f); + aSmoke[1].RegisterPoint(startPos, 0.75f); + aSmoke[2].RegisterPoint(startPos, 0.5f); + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[0], startPos.x, startPos.y, startPos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[1], endPos.x, endPos.y, endPos.z); + + if (RwIm3DTransform(TempBufferRenderVertices, 2, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2); + RwIm3DEnd(); + } +} + +CEscalator CEscalators::aEscalators[NUM_ESCALATORS]; +int32 CEscalators::NumEscalators; + +CEscalator::CEscalator() { + m_bIsActive = false; + + for (int i = 0; i < 24; i++) { + m_pSteps[i] = nil; + } +} + +void +CEscalator::AddThisOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown) { + m_pos0 = pos0; + m_pos1 = pos1; + m_pos2 = pos2; + m_pos3 = pos3; + + float escalatorStepHeight = CModelInfo::GetModelInfo(MI_ESCALATORSTEP)->GetColModel()->boundingBox.max.z; + m_pos0.z -= escalatorStepHeight; + m_pos1.z -= escalatorStepHeight; + m_pos2.z -= escalatorStepHeight; + m_pos3.z -= escalatorStepHeight; + + float magnitudes[3]; + magnitudes[0] = (m_pos0 - m_pos1).Magnitude(); + magnitudes[1] = (m_pos1 - m_pos2).Magnitude(); + magnitudes[2] = (m_pos2 - m_pos3).Magnitude(); + + float length = magnitudes[0] + magnitudes[1] + magnitudes[2]; + + m_lowerEnd = magnitudes[0] / length; + m_upperEnd = (magnitudes[0] + magnitudes[1]) / length; + + m_stepsCount = Max(24.0f, length / 0.6f); + + CVector direction(m_pos0.x - m_pos1.x, m_pos0.y - m_pos1.y, 0.0f); + direction.Normalise(); + + m_matrix.GetUp() = CVector(0.0f, 0.0f, 1.0f); + m_matrix.GetForward() = CVector(direction.x, direction.y, 0.0f); + m_matrix.GetRight() = CVector(direction.y, -direction.x, 0.0f); + m_matrix.GetPosition() = CVector(0.0f, 0.0f, 0.0f); + + m_bIsMovingDown = b_isMovingDown; + + m_midPoint = (m_pos0 + m_pos3) / 2.0f; + + m_radius = (m_pos0 - m_midPoint).Magnitude(); +} + +void +CEscalator::Update(void) { + if (!m_bIsActive) { + if ((TheCamera.GetPosition() - m_midPoint).Magnitude() < 25.0f) { + if (TheCamera.IsSphereVisible(m_midPoint, m_radius) && (m_stepsCount + 10 < CPools::GetObjectPool()->GetNoOfFreeSpaces())) { + m_bIsActive = true; + for (int i = 0; i < m_stepsCount; i++) { + m_pSteps[i] = new CObject(MI_ESCALATORSTEP, TRUE); + if (m_pSteps[i]) { + m_pSteps[i]->SetPosition(m_pos1); + CWorld::Add(m_pSteps[i]); + m_pSteps[i]->ObjectCreatedBy = CONTROLLED_SUB_OBJECT; + } + } + } + } + } + + if (m_bIsActive) { + float time = (CTimer::GetTimeInMilliseconds() % 16384) / 16384.0f; + for (int i = 0; i < m_stepsCount; i++) { + if (m_pSteps[i]) { + float t = i / (float)m_stepsCount + time; + + if (t > 1.0f) + t -= 1.0f; + + if (m_bIsMovingDown) + t = 1.0f - t; + + CVector oldPosition = m_pSteps[i]->GetPosition(); + m_pSteps[i]->GetMatrix() = m_matrix; + + CVector newPosition; + if (t < m_lowerEnd) { + float ratio = t / m_lowerEnd; + newPosition = (ratio * m_pos1) + ((1.0f - ratio) * m_pos0); + } + else if (t < m_upperEnd) { + float ratio = (t - m_lowerEnd) / (m_upperEnd - m_lowerEnd); + newPosition = (ratio * m_pos2) + ((1.0f - ratio) * m_pos1); + } + else { + float ratio = (t - m_upperEnd) / (1.0f - m_upperEnd); + newPosition = (ratio * m_pos3) + ((1.0f - ratio) * m_pos2); + } + + m_pSteps[i]->SetPosition(newPosition); + m_pSteps[i]->m_vecMoveSpeed = (newPosition - oldPosition) / Max(CTimer::GetTimeStep(), 1.0f); + m_pSteps[i]->GetMatrix().UpdateRW(); + m_pSteps[i]->UpdateRwFrame(); + } + if ((TheCamera.GetPosition() - m_midPoint).Magnitude() > 28.0f || !TheCamera.IsSphereVisible(m_midPoint, m_radius)) + SwitchOff(); + } + } +} + +bool deletingEscalator; + +void +CEscalator::SwitchOff(void) { + if (m_bIsActive) { + for (int i = 0; i < m_stepsCount; i++) { + if (m_pSteps[i]) { + CWorld::Remove(m_pSteps[i]); + deletingEscalator = true; + delete m_pSteps[i]; + m_pSteps[i] = nil; + deletingEscalator = false; + } + } + m_bIsActive = false; + } +} + +void +CEscalators::AddOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown) { + aEscalators[NumEscalators++].AddThisOne(pos0, pos1, pos2, pos3, b_isMovingDown); +} + +void +CEscalators::Init(void) { + Shutdown(); + NumEscalators = 0; + + AddOne(CVector(-9.82999f, -938.04498f, 9.4219f), CVector(-8.573f, -938.04498f, 9.4219f), + CVector(-0.747f, -938.045f, 15.065f), CVector(0.88f, -938.045f, 15.065f), TRUE); + + AddOne(CVector(-9.83f, -939.966f, 9.422f), CVector(-8.573f, -939.966f, 9.422f), + CVector(-0.747f, -939.966f, 15.065f), CVector(0.880f, -939.966f, 15.065f), FALSE); + + AddOne(CVector(408.116f, 1058.36f, 18.261f), CVector(408.094f, 1057.04f, 18.261f), + CVector(408.116f, 1048.0f, 24.765f), CVector(408.094f, 1046.57f, 24.799f), TRUE); + + AddOne(CVector(406.195f, 1058.36f, 18.261f), CVector(406.173f, 1057.04f, 18.261f), + CVector(406.195f, 1048.0f, 24.729f), CVector(406.173f, 1046.57f, 24.79f), FALSE); + + AddOne(CVector(421.729f, 1058.3789f, 18.075f), CVector(421.707f, 1057.052f, 18.099f), + CVector(421.729f, 1048.016f, 24.604f), CVector(421.707f, 1046.589f, 24.637f), TRUE); + + AddOne(CVector(419.808f, 1058.378f, 18.099f), CVector(419.786f, 1057.052f, 18.099f), + CVector(419.808f, 1048.016f, 24.568f), CVector(419.786f, 1046.589f, 24.637f), FALSE); + + AddOne(CVector(412.69901f, 1102.729f, 17.569f), CVector(412.72198f, 1104.057f, 17.57f), + CVector(412.69901f, 1113.092f, 24.073f), CVector(412.72198f, 1114.3201f, 24.108f), TRUE); + + AddOne(CVector(414.62f, 1102.729f, 17.569f), CVector(414.64301f, 1104.057f, 17.57f), + CVector(414.62f, 1113.092f, 24.037001f), CVector(414.64301f, 1114.3201f, 24.099001f), FALSE); + + AddOne(CVector(414.64301f, 1145.589f, 17.57f), CVector(414.62f, 1144.261f, 17.569f), + CVector(414.64301f, 1135.226f, 24.073999f), CVector(414.62f, 1133.798f, 24.107f), TRUE); + + AddOne(CVector(412.72198f, 1145.589f, 17.57f), CVector(412.69901f, 1144.261f, 17.569f), + CVector(412.72198f, 1135.226f, 24.038f), CVector(412.69901f, 1133.798f, 24.098f), FALSE); + + AddOne(CVector(406.05099f, 1193.4771f, 18.016001f), CVector(406.07401f, 1194.8051f, 18.017f), + CVector(406.05099f, 1203.84f, 24.52f), CVector(406.07401f, 1205.2679f, 24.555f), TRUE); + + AddOne(CVector(407.97198f, 1193.4771f, 18.016001f), CVector(407.995f, 1194.8051f, 18.017f), + CVector(407.97198f, 1203.84f, 24.483999f), CVector(407.995f, 1205.2679f, 24.546f), FALSE); + + AddOne(CVector(419.659f, 1193.479f, 17.979f), CVector(419.68201f, 1194.807f, 17.98f), + CVector(419.659f, 1203.842f, 24.483f), CVector(419.68201f, 1205.27f, 24.518f), TRUE); + + AddOne(CVector(421.57999f, 1193.479f, 17.979f), CVector(421.603f, 1194.807f, 17.98f), + CVector(421.57999f, 1203.842f, 24.447001f), CVector(421.603f, 1205.27f, 24.509001f), FALSE); + + AddOne(CVector(406.23199f, 1022.857f, 17.917f), CVector(406.23199f, 1024.1851f, 17.917f), + CVector(406.23199f, 1033.22f, 24.521f), CVector(406.23199f, 1034.647f, 24.555f), TRUE); + + AddOne(CVector(408.15302f, 1022.857f, 17.917f), CVector(408.15302f, 1024.1851f, 17.916f), + CVector(408.15302f, 1033.22f, 24.486f), CVector(408.15302f, 1034.647f, 24.52f), FALSE); + + AddOne(CVector(-1506.39f, -813.13f, 13.834f), CVector(-1506.177f, -814.51703f, 13.834f), + CVector(-1504.566f, -823.20898f, 19.836f), CVector(-1504.329f, -824.48499f, 19.837f), FALSE); + + AddOne(CVector(-1481.951f, -859.05402f, 13.834f), CVector(-1482.7791f, -858.22498f, 13.834f), + CVector(-1489.03f, -851.974f, 19.836f), CVector(-1489.948f, -851.05701f, 19.837f), TRUE); + + AddOne(CVector(-1461.743f, -871.35901f, 13.834f), CVector(-1460.62f, -871.69202f, 13.834f), + CVector(-1452.144f, -874.20203f, 19.836f), CVector(-1450.9f, -874.57098f, 19.837f), FALSE); + + AddOne(CVector(-1409.889f, -871.41498f, 13.834f), CVector(-1411.0129f, -871.74701f, 13.834f), + CVector(-1419.489f, -874.258f, 19.836f), CVector(-1420.733f, -874.62701f, 19.837f), TRUE); + + AddOne(CVector(-1389.577f, -858.89301f, 13.834f), CVector(-1388.7271f, -858.08698f, 13.834f), + CVector(-1382.314f, -852.00201f, 19.836f), CVector(-1381.373f, -851.10797f, 19.837f), FALSE); + + AddOne(CVector(-1364.981f, -813.13f, 13.834f), CVector(-1365.204f, -814.28003f, 13.834f), + CVector(-1366.891f, -822.95801f, 19.83f), CVector(-1367.139f, -824.23199f, 19.837f), TRUE); + + for (int i = 0; i < NUM_ESCALATORS; i++) { + aEscalators[i].SwitchOff(); + } +} + +void +CEscalators::Update(void) { + if (CReplay::IsPlayingBack()) + return; + + for (int i = 0; i < NUM_ESCALATORS; i++) { + aEscalators[i].Update(); + } +} + +void +CEscalators::Shutdown(void) { + for (int i = 0; i < NUM_ESCALATORS; i++) { + aEscalators[i].SwitchOff(); + } + NumEscalators = 0; +} + + +CScriptPath CScriptPaths::aArray[3]; + +void CScriptPath::FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ) +{ + int32 i; + for (i = 0; m_pNode[i + 1].t < t; i++) + if (i == m_numNodes - 1) { + // don't go beyond last node + *pX = m_pNode[m_numNodes - 1].p.x; + *pY = m_pNode[m_numNodes - 1].p.y; + *pZ = m_pNode[m_numNodes - 1].p.z; + return; + } + float f = (t - m_pNode[i].t) / (m_pNode[i + 1].t - m_pNode[i].t); + *pX = (1.0f - f)*m_pNode[i].p.x + f*m_pNode[i + 1].p.x; + *pY = (1.0f - f)*m_pNode[i].p.y + f*m_pNode[i + 1].p.y; + *pZ = (1.0f - f)*m_pNode[i].p.z + f*m_pNode[i + 1].p.z; +} + +void CScriptPath::Update(void) { + if (m_state != SCRIPT_PATH_ACTIVE) + return; + + m_fPosition += m_fSpeed * CTimer::GetTimeStepInSeconds(); + m_fPosition = clamp(m_fPosition, 0.0f, m_fTotalLength); + + if (m_pObjects[0] || m_pObjects[1] || m_pObjects[2] || m_pObjects[3] + || m_pObjects[4] || m_pObjects[5]) { + + float t1, t2; + CVector pos1, pos2; + + t1 = Max(m_fPosition - m_fObjectLength / 2.0f, 0.0f); + FindCoorsFromDistanceOnPath(t1, &pos1.x, &pos1.y, &pos1.z); + t2 = Min(m_fPosition + m_fObjectLength / 2.0f, m_fTotalLength); + FindCoorsFromDistanceOnPath(t2, &pos2.x, &pos2.y, &pos2.z); + + CVector newForward, newUp(0.0f, 0.0f, 1.0f), newRight; + + newForward = pos2 - pos1; + newForward.Normalise(); + newRight = CrossProduct(newForward, newUp); + newRight.Normalise(); + newUp = CrossProduct(newRight, newForward); + + for (int i = 0; i < 6; i++) { + if (m_pObjects[i]) { + CMatrix prevMat(m_pObjects[i]->GetMatrix()); + CVector prevPosition = m_pObjects[i]->GetPosition(); + + m_pObjects[i]->SetPosition((pos1 + pos2) / 2.0f); + m_pObjects[i]->GetRight() = newRight; + m_pObjects[i]->GetUp() = newUp; + m_pObjects[i]->GetForward() = newForward; + m_pObjects[i]->GetMatrix().UpdateRW(); + m_pObjects[i]->UpdateRwFrame(); + + if (!m_pObjects[i]->bIsBIGBuilding && prevPosition != m_pObjects[i]->GetPosition()) + m_pObjects[i]->RemoveAndAdd(); + + m_pObjects[i]->GetMatrix().UpdateRW(); + m_pObjects[i]->UpdateRwFrame(); + + m_pObjects[i]->m_vecMoveSpeed = (m_pObjects[i]->GetPosition() - prevMat.GetPosition()) / CTimer::GetTimeStep(); + + float deltaAngle = m_pObjects[i]->GetForward().Heading() - prevMat.GetForward().Heading(); + while (deltaAngle < (float)PI) deltaAngle += (float)TWOPI; + while (deltaAngle > (float)PI) deltaAngle -= (float)TWOPI; + float zTurnSpeed = deltaAngle / CTimer::GetTimeStep(); + + m_pObjects[i]->m_vecTurnSpeed = CVector(0.0f, 0.0f, zTurnSpeed); + m_pObjects[i]->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); + m_pObjects[i]->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f); + } + } + } +} + +void CScriptPath::Clear(void) { + if (m_pNode) + delete[] m_pNode; + m_pNode = nil; + m_numNodes = 0; + for (int i = 0; i < 6; i++) + m_pObjects[i] = nil; + m_state = SCRIPT_PATH_DISABLED; +} + +void CScriptPath::InitialiseOne(int32 numNodes, float length) { + char Dest[32]; + sprintf(Dest, "data\\paths\\spath%d.dat", numNodes); + m_pNode = CPlane::LoadPath(Dest, m_numNodes, m_fTotalLength, false); + m_fSpeed = 1.0f; + m_fPosition = 0.0f; + m_fObjectLength = length; + m_state = SCRIPT_PATH_INITIALIZED; +} + +void CScriptPath::SetObjectToControl(CObject *pObj) { + int32 i = 0; + while (i < 6 && m_pObjects[i]) + i++; + m_pObjects[i] = pObj; + pObj->RegisterReference((CEntity**)&m_pObjects[i]); + pObj->m_phy_flagA08 = false; + m_state = SCRIPT_PATH_ACTIVE; +} + +void CScriptPaths::Init(void) { + for (int i = 0; i < 3; i++) + aArray[i].Clear(); +} + +void CScriptPaths::Shutdown(void) { + for (int i = 0; i < 3; i++) + aArray[i].Clear(); +} + +void CScriptPaths::Update(void) { + for (int i = 0; i < 3; i++) + aArray[i].Update(); +} + +bool CScriptPaths::IsOneActive(void) { + for (int i = 0; i < 3; i++) + if (aArray[i].m_state == SCRIPT_PATH_ACTIVE && aArray[i].m_fSpeed != 0.0f) + return true; + + return false; +} + +void CScriptPaths::Load(uint8 *buf, uint32 size) { +INITSAVEBUF + for (int32 i = 0; i < 3; i++) + aArray[i].Clear(); + + for (int32 i = 0; i < 3; i++) { + aArray[i] = ReadSaveBuf<CScriptPath>(buf); + + for (int32 j = 0; j < 6; j++) { + CScriptPath *pPath = &aArray[i]; + if (pPath->m_pObjects[j] != nil) { + pPath->m_pObjects[j] = CPools::GetObjectPool()->GetSlot((uintptr)pPath->m_pObjects[j] - 1); + pPath->m_pObjects[j]->m_phy_flagA08 = false; + } + } + + aArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes]; + for (int32 j = 0; j < aArray[i].m_numNodes; j++) { + aArray[i].m_pNode[j] = ReadSaveBuf<CPlaneNode>(buf); + } + } +VALIDATESAVEBUF(size) +} + +void CScriptPaths::Save(uint8 *buf, uint32 *size) { + *size = sizeof(aArray); +INITSAVEBUF + for (int32 i = 0; i < 3; i++) { + CScriptPath *pPath = WriteSaveBuf(buf, aArray[i]); + + for (int32 j = 0; j < 6; j++) { + if (pPath->m_pObjects[j] != nil) + pPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex(pPath->m_pObjects[j]) + 1); + } + + for (int32 j = 0; j < aArray[i].m_numNodes; j++) { + WriteSaveBuf(buf, aArray[i].m_pNode[j]); + *size += sizeof(aArray[i].m_pNode[j]); + } + } +VALIDATESAVEBUF(*size); +} + +CObject *g_pScriptPathObjects[18]; + +void CScriptPaths::Load_ForReplay(void) { + for (int i = 0; i < 3; i++) { + for (int32 j = 0; j < 6; j++) { + aArray[i].m_pObjects[j] = g_pScriptPathObjects[6 * i + j]; + } + } +} + +void CScriptPaths::Save_ForReplay(void) { + for (int i = 0; i < 3; i++) { + for (int32 j = 0; j < 6; j++) { + g_pScriptPathObjects[6 * i + j] = aArray[i].m_pObjects[j]; + } + } +} diff --git a/src/render/Fluff.h b/src/render/Fluff.h index fe3ab256..f61da350 100644 --- a/src/render/Fluff.h +++ b/src/render/Fluff.h @@ -1,6 +1,123 @@ #pragma once #include "common.h" #include "Vector.h" +#include "Object.h" +#include "Plane.h" + +enum { + SCRIPT_PATH_DISABLED = 0, + SCRIPT_PATH_INITIALIZED, + SCRIPT_PATH_ACTIVE +}; + +class CScriptPath +{ +public: + int32 m_numNodes; + CPlaneNode *m_pNode; + float m_fTotalLength; + float m_fSpeed; + float m_fPosition; + float m_fObjectLength; + int32 m_state; + CObject *m_pObjects[6]; + + void Clear(void); + void Update(void); + void InitialiseOne(int32 numNodes, float length); + void FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ); + void SetObjectToControl(CObject *pObj); +}; + +class CScriptPaths +{ +public: + static CScriptPath aArray[3]; + static void Init(void); + static void Shutdown(void); + static void Update(void); + static bool IsOneActive(void); + static void Save(uint8 *buf, uint32 *size); + static void Load(uint8 *buf, uint32 size); + static void Save_ForReplay(); + static void Load_ForReplay(); +}; + +class CPlaneTrail +{ + CVector m_pos[16]; + int32 m_time[16]; +public: + void Init(void); + void Render(float visibility); + void RegisterPoint(CVector pos); +}; + +class CPlaneTrails +{ + static CPlaneTrail aArray[6]; // NB: 3 CPlanes and 3 hardcoded far away ones +public: + static void Init(void); + static void Update(void); + static void Render(void); + static void RegisterPoint(CVector pos, uint32 id); +}; + +class CPlaneBanner +{ + CVector m_pos[8]; +public: + void Init(void); + void Update(void); + void Render(void); + void RegisterPoint(CVector pos); +}; + +class CPlaneBanners +{ + static CPlaneBanner aArray[5]; +public: + static void Init(void); + static void Update(void); + static void Render(void); + static void RegisterPoint(CVector pos, uint32 id); +}; + +class CEscalator +{ + CVector m_pos0; + CVector m_pos1; + CVector m_pos2; + CVector m_pos3; + CMatrix m_matrix; + bool m_bIsActive; + bool m_bIsMovingDown; + int32 m_stepsCount; + float m_lowerEnd; + float m_upperEnd; + CVector m_midPoint; + float m_radius; + CObject *m_pSteps[24]; +public: + CEscalator(); + void Update(void); + void SwitchOff(void); + void AddThisOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown); + bool IsActive() const { return m_bIsActive; }; + const CVector& GetPosition() const { return m_midPoint; }; +}; + +class CEscalators +{ + static CEscalator aEscalators[NUM_ESCALATORS]; +public: + static int32 NumEscalators; + static void Init(void); + static void Update(void); + static void AddOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown); + static void Shutdown(void); + static const CEscalator& GetEscalator(int ind) { return aEscalators[ind]; }; +}; class CMovingThing { @@ -53,6 +170,9 @@ private: float m_fScale; public: + static int TonightsEvent; + +public: void SetVisibility(bool visible) { m_bVisible = visible; } bool IsVisible() { return m_bVisible; } @@ -103,4 +223,25 @@ public: void Init(CVector, float, float, uint8, uint8, uint8, float, float); void Update(); void Render(); +}; + +class CSmokeTrail { + CVector m_pos[16]; + float m_opacity[16]; + int m_time[16]; + char m_unused[536]; + int m_seed; +public: + void Render(void); + void RegisterPoint(CVector position, float a); + void Init(int num); +}; + +class CSmokeTrails { + static CSmokeTrail aSmoke[3]; +public: + static bool CigOn; + static void Update(void); + static void Render(void); + static void Init(void); };
\ No newline at end of file diff --git a/src/render/Font.cpp b/src/render/Font.cpp index d0b554dd..f14e45cd 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -3,6 +3,7 @@ #include "Sprite2d.h" #include "TxdStore.h" #include "Font.h" +#include "Timer.h" void AsciiToUnicode(const char *src, wchar *dst) @@ -30,67 +31,51 @@ UnicodeStrlen(const wchar *str) return len; } +void +UnicodeMakeUpperCase(wchar *dst, const wchar *src) //idk what to do with it, seems to be incorrect implementation by R* +{ + while (*src != '\0') { + if (*src < 'a' || *src > 'z') + *dst = *src; + else + *dst = *src - 32; + dst++; + src++; + } + *dst = '\0'; +} + CFontDetails CFont::Details; int16 CFont::NewLine; CSprite2d CFont::Sprite[MAX_FONTS]; +CFontRenderState CFont::RenderState; #ifdef MORE_LANGUAGES uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS; int32 CFont::Slot = -1; #define JAP_TERMINATION (0x8000 | '~') -int16 CFont::Size[LANGSET_MAX][MAX_FONTS][193] = { +int16 CFont::Size[LANGSET_MAX][MAX_FONTS][210] = { { #else -int16 CFont::Size[MAX_FONTS][193] = { +int16 CFont::Size[MAX_FONTS][210] = { #endif - { - 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31, - 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26, - 30, 26, 24, 23, 24, 22, 21, 24, 26, 10, 20, 26, 22, 29, 26, 25, - 23, 25, 24, 24, 22, 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37, - 35, 21, 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21, 21, - 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 33, 33, 33, 33, 35, - 27, 27, 27, 27, 32, 24, 23, 23, 23, 23, 11, 11, 11, 11, 26, 26, - 26, 26, 26, 26, 26, 25, 26, 21, 21, 21, 21, 32, 23, 22, 22, 22, - 22, 11, 11, 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 26, 21, 24, - 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 20 - }, - - { - 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11, 17, 13, 33, - 28, 14, 22, 21, 24, 23, 23, 21, 23, 22, 10, 35, 13, 35, 13, 33, - 5, 25, 22, 23, 24, 21, 21, 24, 24, 9, 20, 24, 21, 27, 25, 25, - 22, 25, 23, 20, 23, 23, 23, 31, 23, 23, 23, 37, 33, 37, 35, 37, - 35, 21, 19, 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21, - 20, 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33, 33, 35, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 16 - }, - - { - 15, 14, 16, 25, 19, 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27, - 19, 18, 19, 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35, - 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29, 19, 20, - 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 33, 31, 39, 37, 39, - 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23, 23, - 20, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35, 35, 35, 35, 37, - 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 30, 19, 19, 19, 19, - 19, 10, 10, 10, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 35, - 12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19 - } + { + 12, 9, 22, 17, 19, 19, 25, 4, 33, 33, 25, 35, 11, 10, 6, 33, 18, 10, 17, 17, 17, 17, 17, 15, 12, 16, 5, 30, 30, 30, 30, 30, 12, 16, 19, + 16, 19, 18, 18, 17, 22, 11, 17, 18, 18, 30, 22, 19, 22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 19, 19, 12, 14, 11, 11, 16, 11, + 12, 14, 14, 10, 13, 12, 10, 19, 18, 12, 16, 13, 13, 11, 12, 15, 12, 15, 13, 12, 12, 37, 33, 37, 35, 37, 16, 16, 16, 16, 33, 17, 18, 18, 18, + 18, 11, 11, 11, 11, 19, 19, 19, 19, 19, 19, 19, 19, 15, 14, 14, 14, 14, 20, 14, 11, 11, 11, 11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15, + 15, 24, 18, 21, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16 + }, + { + 15, 7, 31, 25, 20, 23, 21, 7, 11, 10, 26, 14, 6, 12, 6, 26, 20, 7, 20, 20, 21, 20, 20, 19, 21, 20, 8, 30, 24, 30, 24, 19, 20, 22, 22, 21, 22, 18, 18, 22, + 22, 9, 14, 21, 18, 27, 21, 24, 22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30, 10, 19, 10, 17, 17, 16, 17, 17, 11, 17, 17, 7, 7, 18, 7, 25, 17, + 17, 17, 17, 11, 17, 11, 17, 18, 25, 19, 18, 17, 28, 26, 20, 15, 15, 20, 20, 20, 20, 29, 22, 19, 19, 19, 19, 9, 9, 9, 9, 23, 23, 23, 23, 24, 24, 24, 24, + 20, 19, 17, 17, 17, 30, 16, 17, 17, 17, 17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 19, 20, 20, 20, 18, 19, 19, 21, 19, 19, 19, 19, 19, 16, 19, + 19, 19, 20, 19, 16, 19, 19, 9, 19, 20, 14, 29, 19, 19, 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, 10, 9, 10, 20 + } #ifdef MORE_LANGUAGES }, { @@ -224,6 +209,21 @@ wchar foreign_table[128] = { 0, 174, 165, 166, 167, 0, 168, 0, 0, 169, 170, 171, 172, 0, 0, 0, }; +union tFontRenderStatePointer +{ + CFontRenderState *pRenderState; + wchar *pStr; + + void Align() + { + if ((uintptr)pStr % 4) + pStr++; + } +}; + +tFontRenderStatePointer FontRenderStatePointer; +uint8 FontRenderStateBuf[1024]; + void CFont::Initialise(void) { @@ -254,16 +254,14 @@ CFont::Initialise(void) CTxdStore::AddRef(slot); CTxdStore::PushCurrentTxd(); CTxdStore::SetCurrentTxd(slot); - Sprite[0].SetTexture("font2", "font2_mask"); + Sprite[0].SetTexture("font2", "font2m"); #ifdef MORE_LANGUAGES if (IsJapanese()) { Sprite[1].SetTexture("FONTJAP", "FONTJAP_mask"); Sprite[3].SetTexture("FONTJAP", "FONTJAP_mask"); } - else #endif // MORE_LANGUAGES - Sprite[1].SetTexture("pager", "pager_mask"); - Sprite[2].SetTexture("font1", "font1_mask"); + Sprite[1].SetTexture("font1", "font1m"); SetScale(1.0f, 1.0f); SetSlantRefPoint(SCREEN_WIDTH, 0.0f); SetSlant(0.0f); @@ -331,7 +329,6 @@ CFont::Shutdown(void) { Sprite[0].Delete(); Sprite[1].Delete(); - Sprite[2].Delete(); #ifdef MORE_LANGUAGES if (IsJapanese()) Sprite[3].Delete(); @@ -345,13 +342,9 @@ CFont::Shutdown(void) void CFont::InitPerFrame(void) { - Details.bank = CSprite2d::GetBank(30, Sprite[0].m_pTexture); - CSprite2d::GetBank(15, Sprite[1].m_pTexture); - CSprite2d::GetBank(15, Sprite[2].m_pTexture); -#ifdef MORE_LANGUAGES - if (IsJapanese()) - CSprite2d::GetBank(15, Sprite[3].m_pTexture); -#endif + RenderState.style = -1; + Details.anonymous_25 = 0; + FontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf; SetDropShadowPosition(0); NewLine = 0; } @@ -359,11 +352,15 @@ CFont::InitPerFrame(void) void CFont::PrintChar(float x, float y, wchar c) { + bool bDontPrint = false; if(x <= 0.0f || x > SCREEN_WIDTH || y <= 0.0f || y > SCREEN_HEIGHT) // BUG: game uses SCREENW again return; + bDontPrint = c == '\0'; float w = GetCharacterWidth(c) / 32.0f; + if (Details.bFontHalfTexture && c == 208) + c = '\0'; float xoff = c % 16; float yoff = c / 16; #ifdef MORE_LANGUAGES @@ -374,28 +371,40 @@ CFont::PrintChar(float x, float y, wchar c) } #endif - if(Details.style == FONT_BANK || Details.style == FONT_HEADING){ - if(Details.dropShadowPosition != 0){ - CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank - CRect(x + SCREEN_SCALE_X(Details.dropShadowPosition), - y + SCREEN_SCALE_Y(Details.dropShadowPosition), - x + SCREEN_SCALE_X(Details.dropShadowPosition) + 32.0f * Details.scaleX * 1.0f, - y + SCREEN_SCALE_Y(Details.dropShadowPosition) + 40.0f * Details.scaleY * 0.5f), - Details.dropColor, - xoff/16.0f, yoff/12.8f, - (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f, - xoff/16.0f, (yoff+1.0f)/12.8f, - (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.0001f); - } - CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank - CRect(x, y, - x + 32.0f * Details.scaleX * 1.0f, - y + 40.0f * Details.scaleY * 0.5f), - Details.color, - xoff/16.0f, yoff/12.8f, - (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f, - xoff/16.0f, (yoff+1.0f)/12.8f - 0.002f, - (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.002f); + if(Details.style == FONT_BANK || Details.style == FONT_STANDARD){ + if (bDontPrint) return; + if (RenderState.slant == 0.0f) { + if (c < 193) { + CSprite2d::AddToBuffer( + CRect(x, y, + x + 32.0f * RenderState.scaleX * 1.0f, + y + 40.0f * RenderState.scaleY * 0.5f), + RenderState.color, + xoff / 16.0f, yoff / 12.8f + 0.0021f, + (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f, + xoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.0021f, + (xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.0021f); + } else { + CSprite2d::AddToBuffer( + CRect(x, y, + x + 32.0f * RenderState.scaleX * 1.0f, + y + 33.0f * RenderState.scaleY * 0.5f), + RenderState.color, + xoff / 16.0f, yoff / 12.8f, + (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f - 0.017f, + xoff / 16.0f, (yoff + 1.0f) / 12.8f, + (xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.017f); + } + } else + CSprite2d::AddToBuffer( + CRect(x, y, + x + 32.0f * RenderState.scaleX * 1.0f, + y + 40.0f * RenderState.scaleY * 0.5f), + RenderState.color, + xoff / 16.0f, yoff / 12.8f + 0.00055f, + (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f + 0.01f, + xoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.009f, + (xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.0021f + 0.01f); #ifdef MORE_LANGUAGES }else if (IsJapaneseFont()) { if (Details.dropShadowPosition != 0) { @@ -420,16 +429,18 @@ CFont::PrintChar(float x, float y, wchar c) xoff * w / 1024.0f, (yoff + 1.0f) / 25.6f - 0.002f, xoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, (yoff + 1.0f) / 25.6f - 0.0001f); #endif - }else - CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank + } else { + if (bDontPrint) return; + CSprite2d::AddToBuffer( CRect(x, y, - x + 32.0f * Details.scaleX * w, - y + 32.0f * Details.scaleY * 0.5f), - Details.color, - xoff/16.0f, yoff/16.0f, - (xoff+w)/16.0f, yoff/16.0f, - xoff/16.0f, (yoff+1.0f)/16.0f, - (xoff+w)/16.0f - 0.0001f, (yoff+1.0f)/16.0f - 0.0001f); + x + 32.0f * RenderState.scaleX * w, + y + 32.0f * RenderState.scaleY * 0.5f), + RenderState.color, + xoff / 16.0f, yoff / 16.0f, + (xoff + w) / 16.0f, yoff / 16.0f, + xoff / 16.0f, (yoff + 1.0f) / 16.0f, + (xoff + w) / 16.0f - 0.0001f, (yoff + 1.0f) / 16.0f - 0.0001f); + } } #ifdef MORE_LANGUAGES @@ -510,7 +521,7 @@ CFont::PrintString(float xstart, float ystart, wchar *s) #ifdef MORE_LANGUAGES PrintString(xleft, y, start, s, spaceWidth, xstart); #else - PrintString(xleft, y, start, s, spaceWidth); + PrintString(xleft, y, Details.anonymous_25, start, s, spaceWidth); #endif // reset things lineLength = 0.0f; @@ -590,7 +601,7 @@ CFont::PrintString(float xstart, float ystart, wchar *s) lineLength = 0.0f; } #else - PrintString(xleft, y, start, s, 0.0f); + PrintString(xleft, y, Details.anonymous_25, start, s, 0.0f); #endif } } @@ -831,24 +842,81 @@ CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, f } #else void -CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth) +CFont::PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth) { - wchar *s, c, unused; + wchar *s; - for(s = start; s < end; s++){ - if(*s == '~') - s = ParseToken(s, &unused); - c = *s - ' '; - if(Details.slant != 0.0f) - y = (Details.slantRefX - x)*Details.slant + Details.slantRefY; - PrintChar(x, y, c); - x += GetCharacterSize(c); - if(c == 0) // space - x += spwidth; + if (RenderState.style != Details.style) { + RenderFontBuffer(); + RenderState.style = Details.style; } + + float dropShadowPosition = Details.dropShadowPosition; + if (dropShadowPosition != 0.0f && (Details.style == FONT_BANK || Details.style == FONT_STANDARD)) { + CRGBA color = Details.color; + Details.color = Details.dropColor; + Details.dropShadowPosition = 0; + Details.bIsShadow = true; + if (Details.slant != 0.0f) { + Details.slantRefX += SCREEN_SCALE_X(dropShadowPosition); + Details.slantRefY += SCREEN_SCALE_Y(dropShadowPosition); + PrintString(SCREEN_SCALE_X(dropShadowPosition) + x, SCREEN_SCALE_Y(dropShadowPosition) + y, Details.anonymous_25, start, end, spwidth); + Details.slantRefX -= SCREEN_SCALE_X(dropShadowPosition); + Details.slantRefY -= SCREEN_SCALE_Y(dropShadowPosition); + } else { + PrintString(SCREEN_SCALE_X(dropShadowPosition) + x, SCREEN_SCALE_Y(dropShadowPosition) + y, Details.anonymous_25, start, end, spwidth); + } + Details.color = color; + Details.dropShadowPosition = dropShadowPosition; + Details.bIsShadow = false; + } + if (FontRenderStatePointer.pStr >= (wchar*)&FontRenderStateBuf[ARRAY_SIZE(FontRenderStateBuf)] - (end - start + 26)) // why 26? + RenderFontBuffer(); + CFontRenderState *pRenderState = FontRenderStatePointer.pRenderState; + pRenderState->fTextPosX = x; + pRenderState->fTextPosY = y; + pRenderState->scaleX = Details.scaleX; + pRenderState->scaleY = Details.scaleY; + pRenderState->color = Details.color; + pRenderState->fExtraSpace = spwidth; + pRenderState->slant = Details.slant; + pRenderState->slantRefX = Details.slantRefX; + pRenderState->slantRefY = Details.slantRefY; + pRenderState->bFontHalfTexture = Details.bFontHalfTexture; + pRenderState->proportional = Details.proportional; + pRenderState->style = Details.style; + pRenderState->bIsShadow = Details.bIsShadow; + FontRenderStatePointer.pRenderState++; + + for(s = start; s < end;){ + if (*s == '~') { + for (wchar *i = ParseToken(s); s != i; FontRenderStatePointer.pStr++) { + *FontRenderStatePointer.pStr = *(s++); + } + if (Details.bFlash) { + if (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) { + Details.bFlashState = !Details.bFlashState; + Details.nFlashTimer = CTimer::GetTimeInMilliseconds(); + } + Details.color.a = Details.bFlashState ? 0 : 255; + } + } else + *(FontRenderStatePointer.pStr++) = *(s++); + } + *(FontRenderStatePointer.pStr++) = '\0'; + FontRenderStatePointer.Align(); } #endif +void +CFont::PrintStringFromBottom(float x, float y, wchar *str) +{ + y -= (32.0f * Details.scaleY / 2.0f + 2.0f * Details.scaleY) * GetNumberLines(x, y, str); + if (Details.slant == 0.0f) + y -= ((Details.slantRefX - x) * Details.slant + Details.slantRefY); + PrintString(x, y, str); +} + float CFont::GetCharacterWidth(wchar c) { @@ -889,7 +957,7 @@ CFont::GetCharacterWidth(wchar c) if (Details.proportional) return Size[Details.style][c]; else - return Size[Details.style][192]; + return Size[Details.style][209]; #endif // MORE_LANGUAGES } @@ -901,7 +969,7 @@ CFont::GetCharacterSize(wchar c) if (IsJapanese()) { if (!Details.proportional) - return Size[0][Details.style][192] * Details.scaleX; + return Size[0][Details.style][209] * Details.scaleX; if (c <= 94 || Details.style == FONT_HEADING || Details.style == FONT_BANK) { switch (Details.style) { @@ -929,12 +997,14 @@ CFont::GetCharacterSize(wchar c) else if(Details.proportional) return Size[LanguageSet][Details.style][c] * Details.scaleX; else - return Size[LanguageSet][Details.style][192] * Details.scaleX; + return Size[LanguageSet][Details.style][209] * Details.scaleX; #else + if (Details.bFontHalfTexture) + c = FindNewCharacter(c); if (Details.proportional) return Size[Details.style][c] * Details.scaleX; else - return Size[Details.style][192] * Details.scaleX; + return Size[Details.style][209] * Details.scaleX; #endif // MORE_LANGUAGES } @@ -964,15 +1034,16 @@ CFont::GetStringWidth(wchar *s, bool spaces) } else #endif { - for (; (*s != ' ' || spaces) && *s != '\0'; s++) { - if (*s == '~') { - s++; - while (*s != '~') s++; + for (wchar c = *s; (c != ' ' || spaces) && c != '\0'; c = *(++s)) { + if (c == '~') { s++; - if (*s == ' ' && !spaces) - break; + while (*s != '~') { + s++; + } + } + else { + w += GetCharacterSize(c - ' '); } - w += GetCharacterSize(*s - ' '); } } return w; @@ -1026,9 +1097,6 @@ CFont::GetNextSpace(wchar *s) if(*s == '~'){ s++; while(*s != '~') s++; - s++; - if(*s == ' ') - break; } } return s; @@ -1036,7 +1104,7 @@ CFont::GetNextSpace(wchar *s) #ifdef MORE_LANGUAGES wchar* -CFont::ParseToken(wchar *s, wchar*, bool japShit) +CFont::ParseToken(wchar *s, bool japShit) { s++; if ((Details.color.r || Details.color.g || Details.color.b) && !japShit) { @@ -1066,39 +1134,245 @@ CFont::ParseToken(wchar *s, wchar*, bool japShit) } #else wchar* -CFont::ParseToken(wchar *s, wchar*) +CFont::ParseToken(wchar *s) { + Details.anonymous_23 = false; s++; if(Details.color.r || Details.color.g || Details.color.b) switch(*s){ + case 'B': + Details.bBold = !Details.bBold; + break; case 'N': case 'n': NewLine = 1; break; - case 'b': SetColor(CRGBA(0x80, 0xA7, 0xF3, 0xFF)); break; - case 'g': SetColor(CRGBA(0x5F, 0xA0, 0x6A, 0xFF)); break; - case 'h': SetColor(CRGBA(0xE1, 0xE1, 0xE1, 0xFF)); break; - case 'l': SetColor(CRGBA(0x00, 0x00, 0x00, 0xFF)); break; - case 'p': SetColor(CRGBA(0xA8, 0x6E, 0xFC, 0xFF)); break; - case 'r': SetColor(CRGBA(0x71, 0x2B, 0x49, 0xFF)); break; - case 'w': SetColor(CRGBA(0xAF, 0xAF, 0xAF, 0xFF)); break; - case 'y': SetColor(CRGBA(0xD2, 0xC4, 0x6A, 0xFF)); break; + case 'b': SetColor(CRGBA(27, 89, 130, 255)); Details.anonymous_23 = true; break; + case 'f': + Details.bFlash = !Details.bFlash; + if (!Details.bFlash) + Details.color.a = 255; + break; + case 'g': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break; + case 'h': SetColor(CRGBA(225, 225, 225, 255)); Details.anonymous_23 = true; break; + case 'l': SetColor(CRGBA(0, 0, 0, 255)); Details.anonymous_23 = true; break; + case 'o': SetColor(CRGBA(229, 125, 126, 255)); Details.anonymous_23 = true; break; + case 'p': SetColor(CRGBA(168, 110, 252, 255)); Details.anonymous_23 = true; break; + case 'q': SetColor(CRGBA(199, 144, 203, 255)); Details.anonymous_23 = true; break; + case 'r': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break; + case 't': SetColor(CRGBA(86, 212, 146, 255)); Details.anonymous_23 = true; break; + case 'w': SetColor(CRGBA(175, 175, 175, 255)); Details.anonymous_23 = true; break; +#ifdef FIX_BUGS + case 'x': SetColor(CRGBA(0, 255, 255, 255)); Details.anonymous_23 = true; break; +#else + case 'x': SetColor(CRGBA(132, 146, 197, 255)); Details.anonymous_23 = true; break; +#endif + case 'y': SetColor(CRGBA(255, 227, 79, 255)); Details.anonymous_23 = true; break; } while(*s != '~') s++; - return s+1; + if (*(++s) == '~') + s = ParseToken(s); + return s; } #endif +wchar* +CFont::ParseToken(wchar* str, CRGBA &color, bool &flash, bool &bold) +{ + Details.anonymous_23 = false; + wchar *s = str + 1; + if (Details.color.r || Details.color.g || Details.color.b) + { + switch (*s) + { + case 'B': + bold = !bold; + break; + case 'b': + color.r = 27; + color.g = 89; + color.b = 130; + break; + case 'f': + flash = !flash; + break; + case 'g': + color.r = 255; + color.g = 150; + color.b = 225; + break; + case 'h': + color.r = 225; + color.g = 225; + color.b = 225; + break; + case 'l': + color.r = 0; + color.g = 0; + color.b = 0; + break; + case 'o': + color.r = 229; + color.g = 125; + color.b = 126; + break; + case 'p': + color.r = 168; + color.g = 110; + color.b = 252; + break; + case 'q': + color.r = 199; + color.g = 144; + color.b = 203; + break; + case 'r': + color.r = 255; + color.g = 150; + color.b = 225; + break; + case 't': + color.r = 86; + color.g = 212; + color.b = 146; + break; + case 'w': + color.r = 175; + color.g = 175; + color.b = 175; + break; +#ifdef FIX_BUGS + case 'x': + color.r = 0; + color.g = 255; + color.b = 255; + break; +#else + case 'x': + color.r = 132; + color.g = 146; + color.b = 197; + break; +#endif + case 'y': + color.r = 255; + color.g = 227; + color.b = 79; + break; + default: + break; + } + } + while (*s != '~') + ++s; + if (*(++s) == '~') + s = ParseToken(s, color, flash, bold); + return s; +} + void CFont::DrawFonts(void) { - CSprite2d::DrawBank(Details.bank); - CSprite2d::DrawBank(Details.bank+1); - CSprite2d::DrawBank(Details.bank+2); -#ifdef MORE_LANGUAGES - if (IsJapanese()) - CSprite2d::DrawBank(Details.bank+3); -#endif + RenderFontBuffer(); +} + +void +CFont::RenderFontBuffer() +{ + if (FontRenderStatePointer.pRenderState == (CFontRenderState*)FontRenderStateBuf) return; + + float textPosX; + float textPosY; + CRGBA color; + bool bBold = false; + bool bFlash = false; + + Sprite[RenderState.style].SetRenderState(); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RenderState = *(CFontRenderState*)&FontRenderStateBuf[0]; + textPosX = RenderState.fTextPosX; + textPosY = RenderState.fTextPosY; + tFontRenderStatePointer pRenderStateBufPointer; + pRenderStateBufPointer.pRenderState = (CFontRenderState*)&FontRenderStateBuf[0]; + for (++pRenderStateBufPointer.pRenderState; pRenderStateBufPointer.pStr < FontRenderStatePointer.pStr; pRenderStateBufPointer.pStr++) { + if (*pRenderStateBufPointer.pStr == '\0') { + tFontRenderStatePointer tmpPointer = pRenderStateBufPointer; + tmpPointer.pStr++; + tmpPointer.Align(); + if (tmpPointer.pStr >= FontRenderStatePointer.pStr) + break; + + RenderState = *(tmpPointer.pRenderState++); + + pRenderStateBufPointer = tmpPointer; + + textPosX = RenderState.fTextPosX; + textPosY = RenderState.fTextPosY; + color = RenderState.color; + } + if (*pRenderStateBufPointer.pStr == '~') { + pRenderStateBufPointer.pStr = ParseToken(pRenderStateBufPointer.pStr, color, bFlash, bBold); + if (bFlash) { + if (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) { + Details.bFlashState = !Details.bFlashState; + Details.nFlashTimer = CTimer::GetTimeInMilliseconds(); + } + Details.color.alpha = Details.bFlashState ? 0 : 255; + } + if (!RenderState.bIsShadow) + RenderState.color = color; + } + wchar c = *pRenderStateBufPointer.pStr; + c -= ' '; + if (RenderState.bFontHalfTexture) + c = FindNewCharacter(c); + else if (c > 155) + c = 0; + + if (RenderState.slant != 0.0f) + textPosY = (RenderState.slantRefX - textPosX) * RenderState.slant + RenderState.slantRefY; + PrintChar(textPosX, textPosY, c); + if (bBold) { + PrintChar(textPosX + 1.0f, textPosY, c); + PrintChar(textPosX + 2.0f, textPosY, c); + textPosX += 2.0f; + } + textPosX += RenderState.scaleX * (RenderState.proportional ? Size[RenderState.style][c] : Size[RenderState.style][209]); + if (c == '\0') + textPosX += RenderState.fExtraSpace; + } + CSprite2d::RenderVertexBuffer(); + FontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf; +} + + +void +CFont::SetFontStyle(int16 style) +{ + if (style == FONT_HEADING) { + Details.style = FONT_STANDARD; + Details.bFontHalfTexture = true; + } else { + Details.style = style; + Details.bFontHalfTexture = false; + } +} + +wchar CFont::FindNewCharacter(wchar c) +{ + if (c >= 16 && c <= 26) return c + 128; + if (c >= 8 && c <= 9) return c + 86; + if (c == 4) return c + 89; + if (c == 7) return 206; + if (c == 14) return 207; + if (c >= 33 && c <= 58) return c + 122; + if (c >= 65 && c <= 90) return c + 90; + if (c >= 96 && c <= 118) return c + 85; + if (c >= 119 && c <= 140) return c + 62; + if (c >= 141 && c <= 142) return 204; + if (c == 143) return 205; + if (c == 1) return 208; + return c; } wchar diff --git a/src/render/Font.h b/src/render/Font.h index 51035601..47a39f73 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -4,6 +4,7 @@ void AsciiToUnicode(const char *src, wchar *dst); void UnicodeStrcpy(wchar *dst, const wchar *src); void UnicodeStrcat(wchar *dst, wchar *append); int UnicodeStrlen(const wchar *str); +void UnicodeMakeUpperCase(wchar *dst, const wchar *src); struct CFontDetails { @@ -19,27 +20,54 @@ struct CFontDetails bool background; bool backgroundOnlyText; bool proportional; + bool bIsShadow; + bool bFlash; + bool bBold; float alphaFade; CRGBA backgroundColor; float wrapX; float centreSize; float rightJustifyWrap; int16 style; - int32 bank; + bool bFontHalfTexture; + uint32 bank; int16 dropShadowPosition; CRGBA dropColor; + bool bFlashState; + int nFlashTimer; + bool anonymous_23; + uint32 anonymous_25; +}; + +struct CFontRenderState +{ + uint32 anonymous_0; + float fTextPosX; + float fTextPosY; + float scaleX; + float scaleY; + CRGBA color; + float fExtraSpace; + float slant; + float slantRefX; + float slantRefY; + bool bIsShadow; + bool bFontHalfTexture; + bool proportional; + bool anonymous_14; + int16 style; }; class CSprite2d; enum { FONT_BANK, - FONT_PAGER, + FONT_STANDARD, FONT_HEADING, #ifdef MORE_LANGUAGES FONT_JAPANESE, #endif - MAX_FONTS + MAX_FONTS = FONT_HEADING }; enum { @@ -70,12 +98,13 @@ class CFont static uint8 LanguageSet; static int32 Slot; #else - static int16 Size[MAX_FONTS][193]; + static int16 Size[MAX_FONTS][210]; #endif static int16 NewLine; public: static CSprite2d Sprite[MAX_FONTS]; static CFontDetails Details; + static CFontRenderState RenderState; static void Initialise(void); static void Shutdown(void); @@ -87,8 +116,9 @@ public: #ifdef MORE_LANGUAGES static bool PrintString(float x, float y, wchar *start, wchar* &end, float spwidth, float japX); #else - static void PrintString(float x, float y, wchar *start, wchar *end, float spwidth); + static void PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth); #endif + static void PrintStringFromBottom(float x, float y, wchar *str); static float GetCharacterWidth(wchar c); static float GetCharacterSize(wchar c); static float GetStringWidth(wchar *s, bool spaces = false); @@ -97,11 +127,13 @@ public: #endif static uint16 *GetNextSpace(wchar *s); #ifdef MORE_LANGUAGES - static uint16 *ParseToken(wchar *s, wchar*, bool japShit = false); + static uint16 *ParseToken(wchar *s, bool japShit = false); #else - static uint16 *ParseToken(wchar *s, wchar*); + static uint16 *ParseToken(wchar *s); + static uint16* ParseToken(wchar *s, CRGBA &color, bool &flash, bool &bold); #endif static void DrawFonts(void); + static void RenderFontBuffer(void); static uint16 character_code(uint8 c); static CFontDetails GetDetails() { return Details; } @@ -160,14 +192,14 @@ public: static void SetBackGroundOnlyTextOff(void) { Details.backgroundOnlyText = false; } static void SetPropOn(void) { Details.proportional = true; } static void SetPropOff(void) { Details.proportional = false; } - static void SetFontStyle(int16 style) { Details.style = style; } + static void SetFontStyle(int16 style); static void SetRightJustifyWrap(float wrap) { Details.rightJustifyWrap = wrap; } static void SetAlphaFade(float fade) { Details.alphaFade = fade; } static void SetDropShadowPosition(int16 pos) { Details.dropShadowPosition = pos; } static void SetBackgroundColor(CRGBA col); static void SetColor(CRGBA col); static void SetDropColor(CRGBA col); - + static wchar FindNewCharacter(wchar c); #ifdef MORE_LANGUAGES static void ReloadFonts(uint8 set); diff --git a/src/render/Glass.h b/src/render/Glass.h index 51c5aae9..937ab6a9 100644 --- a/src/render/Glass.h +++ b/src/render/Glass.h @@ -1,6 +1,7 @@ #pragma once class CEntity; +class CVehicle; class CFallingGlassPane : public CMatrix { @@ -49,4 +50,8 @@ public: static void WindowRespondsToSoftCollision(CEntity *entity, float amount); static void WasGlassHitByBullet(CEntity *entity, CVector point); static void WindowRespondsToExplosion(CEntity *entity, CVector point); + +//TODO(MIAMI) + static void CarWindscreenShatters(CVehicle *vehicle, bool unk) {} + static void BreakGlassPhysically(CVector, float) {} };
\ No newline at end of file diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 63bf0b06..3ea756fa 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -20,34 +20,43 @@ #include "TxdStore.h" #include "User.h" #include "World.h" +#include "CutsceneMgr.h" +#include "Stats.h" +#include "main.h" +#include "General.h" + +// --MIAMI: file done // Game has colors inlined in code. // For easier modification we collect them here: -CRGBA MONEY_COLOR(89, 115, 150, 255); -CRGBA AMMO_COLOR(0, 0, 0, 255); -CRGBA HEALTH_COLOR(186, 101, 50, 255); -CRGBA ARMOUR_COLOR(124, 140, 95, 255); -CRGBA WANTED_COLOR(193, 164, 120, 255); -CRGBA ZONE_COLOR(152, 154, 82, 255); -CRGBA VEHICLE_COLOR(194, 165, 120, 255); -CRGBA CLOCK_COLOR(194, 165, 120, 255); -CRGBA TIMER_COLOR(186, 101, 50, 255); -CRGBA COUNTER_COLOR(0, 106, 164, 255); +CRGBA MONEY_COLOR(0, 207, 133, 255); +CRGBA AMMO_COLOR(255, 150, 225, 255); +CRGBA HEALTH_COLOR(255, 150, 225, 255); +CRGBA ARMOUR_COLOR(185, 185, 185, 255); +CRGBA NOTWANTED_COLOR(27, 89, 130, 255); +CRGBA WANTED_COLOR_FLASH(62, 141, 181, 255); +CRGBA WANTED_COLOR(97, 194, 247, 255); +CRGBA ZONE_COLOR(45, 155, 90, 255); +CRGBA VEHICLE_COLOR(97, 194, 247, 255); +CRGBA CLOCK_COLOR(97, 194, 247, 255); +CRGBA TIMER_COLOR(97, 194, 247, 255); +CRGBA COUNTER_COLOR(97, 194, 247, 255); CRGBA PAGER_COLOR(32, 162, 66, 205); -CRGBA RADARDISC_COLOR(0, 0, 0, 255); -CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255); -CRGBA WASTEDBUSTED_COLOR(170, 123, 87, 255); -CRGBA ODDJOB_COLOR(89, 115, 150, 255); -CRGBA ODDJOB2_COLOR(156, 91, 40, 255); +CRGBA RADARDISC_COLOR(255, 255, 255, 255); +CRGBA BIGMESSAGE_COLOR(255, 150, 225, 255); +CRGBA WASTEDBUSTED_COLOR(0, 207, 133, 255); +CRGBA ODDJOB_COLOR(0, 207, 133, 255); +CRGBA ODDJOB2_COLOR(97, 194, 247, 255); CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); -wchar CHud::m_HelpMessage[256]; -wchar CHud::m_LastHelpMessage[256]; +wchar CHud::m_HelpMessage[HELP_MSG_LENGTH]; +wchar CHud::m_LastHelpMessage[HELP_MSG_LENGTH]; uint32 CHud::m_HelpMessageState; uint32 CHud::m_HelpMessageTimer; int32 CHud::m_HelpMessageFadeTimer; -wchar CHud::m_HelpMessageToPrint[256]; -float CHud::m_fHelpMessageTime; +wchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH]; +float CHud::m_HelpMessageDisplayTime; +bool CHud::m_HelpMessageDisplayForever; bool CHud::m_HelpMessageQuick; uint32 CHud::m_ZoneState; int32 CHud::m_ZoneFadeTimer; @@ -67,15 +76,17 @@ bool CHud::m_Wants_To_Draw_Hud; bool CHud::m_Wants_To_Draw_3dMarkers; wchar CHud::m_BigMessage[6][128]; int16 CHud::m_ItemToFlash; +bool CHud::m_HideRadar; +int32 CHud::m_ClockState; // These aren't really in CHud float CHud::BigMessageInUse[6]; float CHud::BigMessageAlpha[6]; float CHud::BigMessageX[6]; float CHud::OddJob2OffTimer; -bool CHud::CounterOnLastFrame; +bool CHud::CounterOnLastFrame[NUMONSCREENCOUNTERS]; float CHud::OddJob2XOffset; -uint16 CHud::CounterFlashTimer; +uint16 CHud::CounterFlashTimer[NUMONSCREENCOUNTERS]; uint16 CHud::OddJob2Timer; bool CHud::TimerOnLastFrame; int16 CHud::OddJob2On; @@ -86,6 +97,26 @@ float CHud::PagerXOffset; int16 CHud::PagerTimer; int16 CHud::PagerOn; +wchar *prevChaseString; + +uint32 CHud::m_WantedFadeTimer; +uint32 CHud::m_WantedState; +uint32 CHud::m_WantedTimer; +uint32 CHud::m_EnergyLostFadeTimer; +uint32 CHud::m_EnergyLostState; +uint32 CHud::m_EnergyLostTimer; +uint32 CHud::m_DisplayScoreFadeTimer; +uint32 CHud::m_DisplayScoreState; +uint32 CHud::m_DisplayScoreTimer; +uint32 CHud::m_WeaponFadeTimer; +uint32 CHud::m_WeaponState; +uint32 CHud::m_WeaponTimer; + +uint32 CHud::m_LastDisplayScore; +uint32 CHud::m_LastWanted; +uint32 CHud::m_LastWeapon; +uint32 CHud::m_LastTimeEnergyLost; + CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; struct @@ -93,36 +124,89 @@ struct const char *name; const char *mask; } WeaponFilenames[] = { - {"fist", "fistm"}, - {"bat", "batm"}, - {"pistol", "pistolm" }, - {"uzi", "uzim"}, - {"shotgun", "shotgunm"}, - {"ak47", "ak47m"}, - {"m16", "m16m"}, - {"sniper", "sniperm"}, - {"rocket", "rocketm"}, - {"flame", "flamem"}, - {"molotov", "molotovm"}, - {"grenade", "grenadem"}, - {"detonator", "detonator_mask"}, - {"", ""}, - {"", ""}, - {"radardisc", "radardisc"}, - {"pager", "pagerm"}, - {"", ""}, - {"", ""}, - {"bleeder", ""}, - {"sitesniper", "sitesniperm"}, - {"siteM16", "siteM16m"}, - {"siterocket", "siterocket"} + { "fist", "fistm" }, + { "brassk", "brasskA" }, + { "screw", "screwA" }, + { "golf", "golfA" }, + { "nightstick", "nightstickA" }, + { "knife", "knifeA" }, + { "bat", "batm" }, + { "hammer", "hammerA" }, + { "cleaver", "cleaverA" }, + { "machete", "macheteA" }, + { "sword", "swordA" }, + { "chainsaw", "chainsawA" }, + { "grenade", "grenadeA" }, + { "grenade", "grenadeA" }, + { "teargas", "teargasA" }, + { "molotov", "molotovA" }, + { "rocket", "rocketA" }, + { "handGun1", "handGun1A" }, + { "", "" }, + { "python", "pythonA" }, + { "chromegun", "chromegunA" }, + { "spasshotGun", "spasshotGunA" }, + { "stubshotGun", "stubshotGunA" }, + { "tec9", "tec9A" }, + { "uzi1", "uzi1A" }, + { "uzi2", "uzi2A" }, + { "mp5", "mp5A" }, + { "", "" }, + { "m4", "m4A" }, + { "ruger", "rugerA" }, + { "sniper", "sniperA" }, + { "laserscope", "laserscopeA" }, + { "", "" }, + { "rocket", "rocketA" }, + { "flamer", "flamerA" }, + { "m60", "m60A" }, + { "minigun", "minigunA" }, + { "bomb", "bombA" }, + { "", "" }, + { "camera", "cameraA" }, + { "", "" }, + { "siterocket", "siterocket" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "radardisc", "radardisc" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "sitesniper", "sitesniperm" }, + { "siteM16", "siteM16m" }, + { "sitelaser", "sitelaserm" }, + { "laserdot", "laserdotm" }, + { "viewfinder_128", "viewfinder_128m" }, + { "bleeder", "" } }; RwTexture *gpSniperSightTex; RwTexture *gpRocketSightTex; +RwTexture *gpLaserSightTex; +RwTexture *gpLaserDotTex; +RwTexture *gpViewFinderTex; void CHud::Draw() { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + // disable hud via second controller if (CPad::GetPad(1)->GetStartJustDown()) m_Wants_To_Draw_Hud = !m_Wants_To_Draw_Hud; @@ -131,25 +215,32 @@ void CHud::Draw() return; if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) { + // unused statics in here bool DrawCrossHair = false; + bool CrossHairHidesHud = false; bool DrawCrossHairPC = false; - int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType; + CPlayerPed *playerPed = FindPlayerPed(); + eWeaponType WeaponType = playerPed->GetWeapon()->m_eWeaponType; int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON) + if ((Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON || Mode == CCam::MODE_CAMERA) + && playerPed && !playerPed->GetWeapon()->IsTypeMelee()) DrawCrossHair = true; + if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT) DrawCrossHairPC = true; - - /* - Draw Crosshairs - */ - if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && - (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) { - if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) { - if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER) - DrawCrossHairPC = true; + if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) + || Mode == CCam::MODE_1STPERSON_RUNABOUT) { + if (playerPed) { + if (playerPed->m_nPedState != PED_ENTER_CAR && playerPed->m_nPedState != PED_CARJACK) { + + if (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_RUGER + || WeaponType == WEAPONTYPE_M60 || WeaponType == WEAPONTYPE_MINIGUN + || WeaponType == WEAPONTYPE_FLAMETHROWER) { + DrawCrossHairPC = 1; + } + } } } @@ -169,7 +260,7 @@ void CHud::Draw() #ifdef ASPECT_RATIO_SCALE f3rdY -= SCREEN_SCALE_Y(2.0f); #endif - if (FindPlayerPed() && WeaponType == WEAPONTYPE_M16) { + if (playerPed && (WeaponType == WEAPONTYPE_M4 || WeaponType == WEAPONTYPE_RUGER || WeaponType == WEAPONTYPE_M60)) { rect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.6f); rect.top = f3rdY - SCREEN_SCALE_Y(32.0f * 0.6f); rect.right = f3rdX + SCREEN_SCALE_X(32.0f * 0.6f); @@ -187,8 +278,7 @@ void CHud::Draw() Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); } - } - else { + } else { if (Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_HELICANNON_1STPERSON) { @@ -198,7 +288,6 @@ void CHud::Draw() rect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f); Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); - } else if (Mode == CCam::MODE_1STPERSON_RUNABOUT) { rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f); @@ -218,229 +307,380 @@ void CHud::Draw() RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex)); CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); } else { - // Sniper - rect.left = SCREEN_WIDTH/2 - SCREEN_SCALE_X(210.0f); - rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f); + int sprite = HUD_SITESNIPER; + float xOffset = SCREEN_SCALE_X(210.0f); + float yOffset = SCREEN_SCALE_Y(210.0f); + + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE) + sprite = HUD_SITELASER; + + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_CAMERA) { + sprite = HUD_VIEWFINDER; + CrossHairHidesHud = true; + xOffset = SCREEN_SCALE_X(256.0f); + yOffset = SCREEN_SCALE_Y(192.0f); + } + + rect.left = SCREEN_WIDTH/2 - xOffset; + rect.top = SCREEN_HEIGHT/2 - yOffset; rect.right = SCREEN_WIDTH/2; rect.bottom = SCREEN_HEIGHT/2; - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.01f, 0.01f, 1.0f, 0.0f, 0.01f, 1.0f, 1.0f, 1.0f); rect.left = SCREEN_WIDTH/2; - rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f); - rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); + rect.top = SCREEN_HEIGHT/2 - yOffset; + rect.right = SCREEN_WIDTH/2 + xOffset; rect.bottom = SCREEN_HEIGHT/2; - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.99f, 0.0f, 0.01f, 0.01f, 0.99f, 1.0f, 0.01f, 1.0f); - rect.left = SCREEN_WIDTH/2 - SCREEN_SCALE_X(210.0f); + rect.left = SCREEN_WIDTH/2 - xOffset; rect.top = SCREEN_HEIGHT/2; rect.right = SCREEN_WIDTH/2; - rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + rect.bottom = SCREEN_HEIGHT/2 + yOffset; + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.01f, 0.99f, 1.0f, 0.99f, 0.01f, 0.01f, 1.0f, 0.01f); rect.left = SCREEN_WIDTH/2; rect.top = SCREEN_HEIGHT/2; - rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); - rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + rect.right = SCREEN_WIDTH/2 + xOffset; + rect.bottom = SCREEN_HEIGHT/2 + yOffset; + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.99f, 0.99f, 0.01f, 0.99f, 0.99f, 0.01f, 0.1f, 0.01f); + + CVector dotPos; + float size = 25.0f; + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE && FindPlayerPed()->GetWeapon()->LaserScopeDot(&dotPos, &size)) { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpLaserDotTex)); +#ifdef FIX_BUGS + int intensity = CGeneral::GetRandomNumberInRange(0, 37); +#else + int intensity = CGeneral::GetRandomNumberInRange(0, 35); +#endif + CSprite::RenderOneXLUSprite(dotPos.x, dotPos.y, dotPos.z, + SCREEN_SCALE_X(size), SCREEN_SCALE_Y(size), intensity - 36, 0, 0, intensity - 36, 1.0f, 127); + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + } } } - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); } else { SpriteBrightness = 0; } + if (CrossHairHidesHud) + return; + /* DrawMoneyCounter */ + wchar sPrint[16]; wchar sPrintIcon[16]; char sTemp[16]; + float alpha; - sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); - AsciiToUnicode(sTemp, sPrint); - - CFont::SetPropOff(); - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetPropOff(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); + if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) { + alpha = DrawFadeState(HUD_SCORE_FADING, 0); + } else { + alpha = DrawFadeState(HUD_SCORE_FADING, 1); + m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + } + if (m_DisplayScoreState != FADED_OUT) { + sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); + AsciiToUnicode(sTemp, sPrint); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(43.0f + 2.0f), sPrint); + CFont::SetPropOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetPropOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, alpha)); + MONEY_COLOR.a = alpha; + CFont::SetColor(MONEY_COLOR); - CFont::SetColor(MONEY_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); + if (FrontEndMenuManager.m_PrefsShowHud) { + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); + } + } /* DrawAmmo */ - uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition; - uint32 AmmoInClip = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoInClip; - uint32 TotalAmmo = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoTotal; - uint32 Ammo, Clip; + if (m_LastWeapon == playerPed->GetWeapon()->m_eWeaponType) { + alpha = CHud::DrawFadeState(HUD_WEAPON_FADING, 0); + } else { + alpha = CHud::DrawFadeState(HUD_WEAPON_FADING, 1); + m_LastWeapon = playerPed->GetWeapon()->m_eWeaponType; + } + if (m_WeaponState != FADED_OUT) { + CWeapon *weapon = playerPed->GetWeapon(); + uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType)->m_nAmountofAmmunition; + uint32 AmmoInClip = weapon->m_nAmmoInClip; + uint32 TotalAmmo = weapon->m_nAmmoTotal; + uint32 Ammo, Clip; + + if (AmmoAmount <= 1 || AmmoAmount >= 1000) + sprintf(sTemp, "%d", TotalAmmo); + else { + if (WeaponType == WEAPONTYPE_FLAMETHROWER) { + Clip = AmmoInClip / 10; - if (AmmoAmount <= 1 || AmmoAmount >= 1000) - sprintf(sTemp, "%d", TotalAmmo); - else { - if (WeaponType == WEAPONTYPE_FLAMETHROWER) { - Clip = AmmoInClip / 10; + Ammo = Min((TotalAmmo - AmmoInClip) / 10, 9999); + } else { + Clip = AmmoInClip; - if ((TotalAmmo - AmmoInClip) / 10 <= 9999) - Ammo = (TotalAmmo - AmmoInClip) / 10; - else - Ammo = 9999; - } - else { - Clip = AmmoInClip; + Ammo = Min(TotalAmmo - AmmoInClip, 9999); + } - if ((TotalAmmo - AmmoInClip) > 9999) - Ammo = 9999; - else - Ammo = TotalAmmo - AmmoInClip; + sprintf(sTemp, "%d-%d", Ammo, Clip); } - sprintf(sTemp, "%d-%d", Ammo, Clip); - } + AsciiToUnicode(sTemp, sPrint); + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType); + /* + DrawWeaponIcon + */ + + if (FrontEndMenuManager.m_PrefsShowHud) { + if (weaponInfo->m_nModelId <= 0) { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + if (FrontEndMenuManager.m_PrefsShowHud) + Sprites[WeaponType].Draw( + CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)), + CRGBA(255, 255, 255, alpha), + 0.015f, + 0.015f, + 1.0f, + 0.0f, + 0.015f, + 1.0f, + 1.0f, + 1.0f); + } else { + CBaseModelInfo *weaponModel = CModelInfo::GetModelInfo(weaponInfo->m_nModelId); + RwTexDictionary *weaponTxd = CTxdStore::GetSlot(weaponModel->GetTxdSlot())->texDict; + if (weaponTxd) { + RwTexture *weaponIcon = RwTexDictionaryFindNamedTexture(weaponTxd, weaponModel->GetName()); + if (weaponIcon) { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon)); + const float xSize = SCREEN_SCALE_X(64.0f / 2.0f); + const float ySize = SCREEN_SCALE_X(64.0f / 2.0f); + CSprite::RenderOneXLUSprite(SCREEN_SCALE_FROM_RIGHT(99.0f) + xSize, SCREEN_SCALE_Y(25.0f) + ySize, 1.0f, xSize, ySize, + 255, 255, 255, 255, 1.0f, 255); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + } + } + } - AsciiToUnicode(sTemp, sPrint); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f)); + CFont::SetJustifyOff(); + CFont::SetCentreOn(); + CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetPropOn(); + CFont::SetDropShadowPosition(0); + CFont::SetFontStyle(FONT_STANDARD); + + if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, alpha)); + AMMO_COLOR.a = alpha; + CFont::SetColor(AMMO_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint); + CFont::SetDropShadowPosition(0); + } + } + } /* - DrawWeaponIcon + DrawHealth */ - Sprites[WeaponType].Draw( - CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)), - CRGBA(255, 255, 255, 255), - 0.015f, - 0.015f, - 1.0f, - 0.0f, - 0.015f, - 1.0f, - 1.0f, - 1.0f); + if ( m_LastTimeEnergyLost == CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss ) { + CHud::DrawFadeState(HUD_ENERGY_FADING, 0); + } else { + CHud::DrawFadeState(HUD_ENERGY_FADING, 1); + m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss; + } - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); - CFont::SetJustifyOff(); - CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_WIDTH); - CFont::SetPropOn(); - CFont::SetFontStyle(FONT_BANK); + if (m_EnergyLostState != FADED_OUT) { + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetJustifyOff(); + CFont::SetCentreOff(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetRightJustifyOn(); + CFont::SetPropOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - if (!CDarkel::FrenzyOnGoing() && WeaponType != WEAPONTYPE_UNARMED && WeaponType != WEAPONTYPE_BASEBALLBAT) { - CFont::SetColor(AMMO_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(73.0f), sPrint); - } + if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8 + || m_ItemToFlash != ITEM_HEALTH + || playerPed->m_fHealth < 10 + && CTimer::GetFrameCounter() & 8) { + if (playerPed->m_fHealth >= 10 + || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { - /* - DrawHealth - */ - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetJustifyOff(); - CFont::SetCentreOff(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetRightJustifyOn(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_HEADING); - - if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8 - || m_ItemToFlash != ITEM_HEALTH - || FindPlayerPed()->m_fHealth < 10 - && CTimer::GetFrameCounter() & 8) { - if (FindPlayerPed()->m_fHealth >= 10 - || FindPlayerPed()->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { - - AsciiToUnicode("{", sPrintIcon); + AsciiToUnicode("{", sPrintIcon); #ifdef FIX_BUGS - sprintf(sTemp, "%03d", int32(FindPlayerPed()->m_fHealth + 0.5f)); + sprintf(sTemp, "%03d", int32(playerPed->m_fHealth + 0.5f)); #else - sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fHealth); + sprintf(sTemp, "%03d", (int32)playerPed->m_fHealth); #endif - AsciiToUnicode(sTemp, sPrint); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrint); + CFont::SetColor(HEALTH_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) { + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(164.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon); + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { + // CFont::SetColor(HEALTH_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 54.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } + } } - CFont::SetColor(HEALTH_COLOR); + } + + /* + DrawArmour + */ + if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) { + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + if (playerPed->m_fArmour > 1.0f) { + AsciiToUnicode("<", sPrintIcon); +#ifdef FIX_BUGS + sprintf(sTemp, "%03d", int32(playerPed->m_fArmour + 0.5f)); +#else + sprintf(sTemp, "%03d", (int32)playerPed->m_fArmour); +#endif + AsciiToUnicode(sTemp, sPrint); + + CFont::SetColor(ARMOUR_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(164.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 1) { + // CFont::SetColor(ARMOUR_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } + } } } } /* - DrawArmour + DrawWantedLevel */ - if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) { - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - if (FindPlayerPed()->m_fArmour > 1.0f) { - AsciiToUnicode("[", sPrintIcon); -#ifdef FIX_BUGS - sprintf(sTemp, "%03d", int32(FindPlayerPed()->m_fArmour + 0.5f)); -#else - sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fArmour); -#endif - AsciiToUnicode(sTemp, sPrint); + if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel) { + alpha = DrawFadeState(HUD_WANTED_FADING, 0); + } else { + alpha = DrawFadeState(HUD_WANTED_FADING, 1); + m_LastWanted = playerPed->m_pWanted->m_nWantedLevel; + } - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrint); + if (m_WantedState != FADED_OUT) { + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetJustifyOff(); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetPropOn(); + CFont::SetFontStyle(FONT_STANDARD); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 4) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(234.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon); - } + AsciiToUnicode(">", sPrintIcon); - CFont::SetColor(ARMOUR_COLOR); + for (int i = 0; i < 6; i++) { + if (FrontEndMenuManager.m_PrefsShowHud) { + if (playerPed->m_pWanted->m_nWantedLevel > i + && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange + + 2000 || CTimer::GetFrameCounter() & 4)) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); + WANTED_COLOR.a = alpha; + CFont::SetColor(WANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 1) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(234.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } else if (playerPed->m_pWanted->m_nMinWantedLevel > i && CTimer::GetFrameCounter() & 4) { + WANTED_COLOR_FLASH.a = alpha; + CFont::SetColor(WANTED_COLOR_FLASH); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + + } else if (playerPed->m_pWanted->m_nWantedLevel <= i) { + NOTWANTED_COLOR.a = alpha; + CFont::SetColor(NOTWANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + } } } } - /* - DrawWantedLevel - */ - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetJustifyOff(); - CFont::SetCentreOff(); - CFont::SetRightJustifyOff(); - CFont::SetPropOn(); - CFont::SetFontStyle(FONT_HEADING); - - AsciiToUnicode("]", sPrintIcon); + static int32 nMediaLevelCounter = 0; + if (CStats::ShowChaseStatOnScreen != 0) { + float fCurAttentionLevel = CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention; + if (0.7f * CStats::HighestChaseValue > fCurAttentionLevel + || fCurAttentionLevel <= 40.0f || CTheScripts::IsPlayerOnAMission()) { + nMediaLevelCounter = 0; + } + else { + if (fCurAttentionLevel == CStats::HighestChaseValue) { + sprintf(gString, "%s %d", UnicodeToAscii(TheText.Get("CHSE")), (int32)fCurAttentionLevel); + } + else { + sprintf(gString, "%s %d" "-%d-", UnicodeToAscii(TheText.Get("CHSE")), (int32)fCurAttentionLevel, (int32)CStats::HighestChaseValue); + } + AsciiToUnicode(gString, gUString); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetPropOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - for (int i = 0; i < 6; i++) { - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(2.0f + SCREEN_SCALE_FROM_RIGHT(60.0f - 2.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f + 2.0f), sPrintIcon); - if (FindPlayerPed()->m_pWanted->m_nWantedLevel > i - && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange - + 2000 || CTimer::GetFrameCounter() & 4)) { + CRGBA colour; + if (CTimer::GetTimeInMilliseconds() & 0x200) + colour = CRGBA(204, 0, 185, 180); + else + colour = CRGBA(178, 0, 162, 180); + CFont::SetColor(colour); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(113.0f), gUString); + + if (CStats::FindChaseString(fCurAttentionLevel) != prevChaseString) { + prevChaseString = CStats::FindChaseString(fCurAttentionLevel); + nMediaLevelCounter = 100; + } - CFont::SetColor(WANTED_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(60.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + if (nMediaLevelCounter != 0) { + nMediaLevelCounter--; + UnicodeMakeUpperCase(gUString, CStats::FindChaseString(fCurAttentionLevel)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(138.0f), gUString); + } } } @@ -448,7 +688,6 @@ void CHud::Draw() DrawZoneName */ if (m_pZoneName) { - float fZoneAlpha = 255.0f; if (m_pZoneName != m_pLastZoneName) { switch (m_ZoneState) { @@ -457,6 +696,8 @@ void CHud::Draw() m_ZoneToPrint = m_pZoneName; m_ZoneNameTimer = 0; m_ZoneFadeTimer = 0; + if (m_VehicleState == 1 || m_VehicleState == 2) + m_VehicleState = 3; break; case 1: case 2: @@ -471,19 +712,20 @@ void CHud::Draw() m_pLastZoneName = m_pZoneName; } + float fZoneAlpha = 255.0f; if (m_ZoneState) { switch (m_ZoneState) { case 1: + fZoneAlpha = 255.0f; m_ZoneFadeTimer = 1000; - if (m_ZoneNameTimer > 10000) { + if (m_ZoneNameTimer > 10000.0f) { m_ZoneFadeTimer = 1000; m_ZoneState = 3; } - fZoneAlpha = 255.0f; break; case 2: m_ZoneFadeTimer += CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer > 1000) { + if (m_ZoneFadeTimer > 1000.0f) { m_ZoneState = 1; m_ZoneFadeTimer = 1000; } @@ -491,7 +733,7 @@ void CHud::Draw() break; case 3: m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer < 0) { + if (m_ZoneFadeTimer < 0.0f) { m_ZoneState = 0; m_ZoneFadeTimer = 0; } @@ -499,7 +741,7 @@ void CHud::Draw() break; case 4: m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer < 0) { + if (m_ZoneFadeTimer < 0.0f) { m_ZoneFadeTimer = 0; m_ZoneToPrint = m_pLastZoneName; m_ZoneState = 2; @@ -511,30 +753,35 @@ void CHud::Draw() } -#ifndef HUD_ENHANCEMENTS - if (!m_Message[0]) { -#else - if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide zone name if wasted/busted text is displaying -#endif + if (!m_Message[0] && BigMessageInUse[1] == 0.0f && BigMessageInUse[2] == 0.0f) { + m_ZoneNameTimer += CTimer::GetTimeStepInMilliseconds(); CFont::SetJustifyOff(); CFont::SetPropOn(); CFont::SetBackgroundOff(); if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) - CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.8f), SCREEN_SCALE_Y(1.2f)); + CFont::SetScale(SCREEN_SCALE_X(1.7f * 0.8f), SCREEN_SCALE_Y(1.8f)); else - CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); + CFont::SetScale(SCREEN_SCALE_X(1.7f), SCREEN_SCALE_Y(1.8f)); + + CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f)); + CFont::SetSlant(0.15f); CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, fZoneAlpha)); CFont::SetFontStyle(FONT_BANK); - CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint); - CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint); + + if (!CTheScripts::bPlayerIsInTheStatium) + CFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint); + + CFont::SetSlant(0.f); + } else { + m_ZoneState = 3; } } } @@ -552,6 +799,8 @@ void CHud::Draw() m_pVehicleNameToPrint = m_VehicleName; m_VehicleNameTimer = 0; m_VehicleFadeTimer = 0; + if (m_ZoneState == 1 || m_ZoneState == 2) + m_ZoneState = 3; break; case 1: case 2: @@ -605,30 +854,31 @@ void CHud::Draw() break; } -#ifndef HUD_ENHANCEMENTS if (!m_Message[0]) { -#else - if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide vehicle name if wasted/busted text is displaying -#endif m_VehicleNameTimer += CTimer::GetTimeStepInMilliseconds(); CFont::SetJustifyOff(); CFont::SetPropOn(); CFont::SetBackgroundOff(); if (FrontEndMenuManager.m_PrefsLanguage != CMenuManager::LANGUAGE_ITALIAN && FrontEndMenuManager.m_PrefsLanguage != CMenuManager::LANGUAGE_SPANISH) - CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); + CFont::SetScale(SCREEN_SCALE_X(1.7f), SCREEN_SCALE_Y(1.8f)); else - CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f)); + CFont::SetScale(SCREEN_SCALE_X(1.7f * 0.85f), SCREEN_SCALE_Y(1.8f)); + + CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f)); + CFont::SetSlant(0.15f); CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); CFont::SetFontStyle(FONT_BANK); - CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint); - + CFont::SetDropShadowPosition(2); CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint); + CFont::SetDropColor(CRGBA(0, 0, 0, fVehicleAlpha)); + + CFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f), m_pVehicleNameToPrint); + + CFont::SetSlant(0.f); } } } @@ -642,25 +892,26 @@ void CHud::Draw() /* DrawClock */ - CFont::SetJustifyOff(); - CFont::SetCentreOff(); - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(0.0f); - - sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes()); - AsciiToUnicode(sTemp, sPrint); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); + if (m_ClockState) { + CFont::SetJustifyOff(); + CFont::SetCentreOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetPropOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), sPrint); + sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes()); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(CLOCK_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint); + CFont::SetColor(CLOCK_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint); + } /* DrawOnScreenTimer @@ -668,172 +919,137 @@ void CHud::Draw() wchar sTimer[16]; - if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) + if (!CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed) TimerOnLastFrame = false; - if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed) - CounterOnLastFrame = false; -#ifdef FIX_BUGS -#define TIMER_RIGHT_OFFSET 34.0f // Taken from VC frenzy timer -#else -#define TIMER_RIGHT_OFFSET 27.0f -#endif + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + if (!CUserDisplay::OnscnTimer.m_sCounters[0].m_bCounterProcessed) + CounterOnLastFrame[i] = false; + } + if (CUserDisplay::OnscnTimer.m_bProcessed) { - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) { + if (CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed) { if (!TimerOnLastFrame) TimerFlashTimer = 1; TimerOnLastFrame = true; - if (TimerFlashTimer) { + if (TimerFlashTimer != 0) { if (++TimerFlashTimer > 50) TimerFlashTimer = 0; } - if (CTimer::GetFrameCounter() & 4 || !TimerFlashTimer) { - AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer); + if (CTimer::GetFrameCounter() & 4 || TimerFlashTimer == 0) { + AsciiToUnicode(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockBuffer, sTimer); CFont::SetPropOn(); CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetPropOff(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetColor(TIMER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer); - - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) { - CFont::SetPropOn(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetScale(SCREEN_SCALE_X(0.64f), SCREEN_SCALE_Y(1.35f)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(110.0f), sTimer); + CFont::SetPropOn(); + if (CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText[0]) { + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(TIMER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText)); } } } - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed) { - if (!CounterOnLastFrame) - CounterFlashTimer = 1; - CounterOnLastFrame = true; + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + if (CUserDisplay::OnscnTimer.m_sCounters[i].m_bCounterProcessed) { + if (!CounterOnLastFrame[i]) + CounterFlashTimer[i] = 1; - if (CounterFlashTimer) { - if (++CounterFlashTimer > 50) - CounterFlashTimer = 0; - } + CounterOnLastFrame[i] = true; - if (CTimer::GetFrameCounter() & 4 || !CounterFlashTimer) { - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_nType == COUNTER_DISPLAY_NUMBER) { - AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer, sTimer); - CFont::SetPropOn(); - - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetColor(CRGBA(244, 20, 20, 255)); - CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); - CFont::SetPropOff(); - CFont::SetBackGroundOnlyTextOn(); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), sTimer); - - CFont::SetColor(COUNTER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(132.0f), sTimer); - } else { - int counter = atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer); -#ifdef FIX_BUGS - counter = Min(counter, 100); -#endif - CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 80)); - CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_X(counter) / 2.0f + SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET + 50.0f) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 255)); + if (CounterFlashTimer[i] != 0) { + if (++CounterFlashTimer[i] > 50) + CounterFlashTimer[i] = 0; } - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) { - CFont::SetPropOn(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); - - CFont::SetColor(COUNTER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); + if (CTimer::GetFrameCounter() & 4 || CounterFlashTimer[i] == 0) { + if (CUserDisplay::OnscnTimer.m_sCounters[i].m_nType == COUNTER_DISPLAY_NUMBER) { + AsciiToUnicode(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterBuffer, sTimer); + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetPropOn(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(COUNTER_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i) + SCREEN_SCALE_Y(132.0f), sTimer); + } else { + int counter = atoi(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterBuffer); + + const float barWidth = SCREEN_SCALE_X(100.f / 2.f); + const float right = SCREEN_SCALE_FROM_RIGHT(37.0f); + const float left = right - barWidth; + + const float barHeight = SCREEN_SCALE_Y(11.0f); + const float top = SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f) + SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i); + const float bottom = top + barHeight; + + // shadow + CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(6.0f), top + SCREEN_SCALE_Y(2.0f), right + SCREEN_SCALE_X(6.0f), bottom + SCREEN_SCALE_Y(2.0f)), CRGBA(0, 0, 0, 255)); + + CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, right + SCREEN_SCALE_X(4.0f), bottom), CRGBA(27, 89, 130, 255)); + CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, left + SCREEN_SCALE_X(counter) / 2.0f + SCREEN_SCALE_X(4.0f), bottom), CRGBA(97, 194, 247, 255)); + } + + if (CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText[0]) { + CFont::SetPropOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(COUNTER_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i) + SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText)); + } + // unused/leftover color. I wonder what was it for + CFont::SetColor(CRGBA(244, 225, 91, 255)); } } } } -#undef TIMER_RIGHT_OFFSET - - /* - DrawPager - */ - if (!m_PagerMessage[0] && PagerOn == 1) { - PagerSoundPlayed = false; - PagerOn = 2; - } - if (m_PagerMessage[0] || PagerOn == 2) { - if (!PagerOn) { - PagerOn = 1; - PagerXOffset = 150.0f; - } - if (PagerOn == 1) { - if (PagerXOffset > 0.0f) { - float fStep = PagerXOffset * 0.1f; - if (fStep > 10.0f) - fStep = 10.0f; - PagerXOffset -= fStep * CTimer::GetTimeStep(); - } - if (!PagerSoundPlayed) { - DMAudio.PlayFrontEndSound(SOUND_PAGER, 0); - PagerSoundPlayed = 1; - } - } - else if (PagerOn == 2) { - float fStep = PagerXOffset * 0.1f; - if (fStep < 2.0f) - fStep = 2.0f; - PagerXOffset += fStep; - if (PagerXOffset > 150.0f) { - PagerXOffset = 150.0f; - PagerOn = 0; - } - } - - Sprites[HUD_PAGER].Draw(CRect(SCREEN_SCALE_X(26.0f - PagerXOffset), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_X(160.0 + 26.0f - PagerXOffset), SCREEN_SCALE_Y(80.0f + 27.0f)), CRGBA(255, 255, 255, 255)); - - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.84f), SCREEN_SCALE_Y(1.0f)); - CFont::SetColor(PAGER_COLOR); - CFont::SetRightJustifyOff(); - CFont::SetBackgroundOff(); - CFont::SetCentreOff(); - CFont::SetJustifyOff(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_PAGER); - CFont::PrintString(SCREEN_SCALE_X(52.0f - PagerXOffset), SCREEN_SCALE_Y(54.0f), m_PagerMessage); - } /* DrawRadar */ - if (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR) { + if (FrontEndMenuManager.m_PrefsRadarMode != 2 && + !m_HideRadar && (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR)) { + + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); CRadar::DrawMap(); - CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT)); + if (FrontEndMenuManager.m_PrefsRadarMode != 1) { + CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT)); #ifdef FIX_BUGS - rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); + rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #else - rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); + rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #endif - rect.Grow(4.0f); - Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); + + rect.Grow(6.0f); + rect.Translate(0.0f, 2.0f); + Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); + rect.Translate(0.0f, -2.0f); + Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); + } CRadar::DrawBlips(); } } @@ -922,30 +1138,166 @@ void CHud::Draw() /* DrawSubtitles */ - if (m_Message[0] && !m_BigMessage[2][0] && (FrontEndMenuManager.m_PrefsShowSubtitles == 1 || !TheCamera.m_WideScreenOn)) { + if (m_Message[0] && !m_BigMessage[2][0]) { + if (m_VehicleState != 0) + m_VehicleState = 3; + if (m_ZoneState != 0) + m_ZoneState = 3; + CFont::SetJustifyOff(); CFont::SetBackgroundOff(); CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128)); - CFont::SetScale(SCREEN_SCALE_X(0.48f), SCREEN_SCALE_Y(1.120f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetDropShadowPosition(0); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetColor(CRGBA(225, 225, 225, 255)); + + static bool onceItWasWidescreen = false; + + if (TheCamera.m_WideScreenOn) { + onceItWasWidescreen = true; + + if (FrontEndMenuManager.m_PrefsShowSubtitles || !CCutsceneMgr::IsRunning()) { + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(60.0f)); + CFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.2f)); + CFont::PrintString(SCREEN_WIDTH / 2.f, SCREEN_SCALE_FROM_BOTTOM(80.0f), m_Message); + } + } else { + if (onceItWasWidescreen) + m_Message[0] = '\0'; - float offsetX = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f); - float center = SCREEN_SCALE_FROM_RIGHT(50.0f) - SCREEN_SCALE_X(8.0f) - offsetX; - CFont::SetCentreSize(center); + onceItWasWidescreen = false; + CFont::DrawFonts(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.22f)); - const int16 shadow = 1; - CFont::SetDropShadowPosition(shadow); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::SetColor(CRGBA(235, 235, 235, 255)); + float offsetX = SCREEN_SCALE_X(140.0f) + SCREEN_SCALE_X(8.0f); + float center = SCREEN_SCALE_FROM_RIGHT(20.0f) - SCREEN_SCALE_X(8.0f) - offsetX; + CFont::SetCentreSize(center); - // I'm not sure shadow substaction was intentional here, might be a leftover if CFont::PrintString was used for a shadow draw call - CFont::PrintString(center / 2.0f + offsetX - SCREEN_SCALE_X(shadow), SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(68.0f) - SCREEN_SCALE_Y(shadow), m_Message); + CFont::PrintString(center / 2.0f + offsetX, SCREEN_SCALE_FROM_BOTTOM(105.f + 2.0f), m_Message); + } CFont::SetDropShadowPosition(0); } /* + HelpMessage + */ + + if (m_HelpMessage[0]) { + if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, HELP_MSG_LENGTH)) { + switch (m_HelpMessageState) { + case 0: + m_HelpMessageFadeTimer = 0; + m_HelpMessageState = 2; + m_HelpMessageTimer = 0; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH); + m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; + + if (TheCamera.m_ScreenReductionPercentage == 0.0f) + DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); + break; + case 1: + case 2: + case 3: + case 4: + m_HelpMessageTimer = 5; + m_HelpMessageState = 4; + break; + default: + break; + } + CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH); + } + + float fAlpha = 225.0f; + + if (m_HelpMessageState != 0) { + switch (m_HelpMessageState) { + case 1: + fAlpha = 225.0f; + m_HelpMessageFadeTimer = 600; + if (!m_HelpMessageDisplayForever && m_HelpMessageTimer > m_HelpMessageDisplayTime * 1000.0f || + m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { + + m_HelpMessageFadeTimer = 600; + m_HelpMessageState = 3; + } + break; + case 2: + if (TheCamera.m_WideScreenOn) + break; + + m_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds(); + if (m_HelpMessageFadeTimer > 0) { + m_HelpMessageState = 1; + m_HelpMessageFadeTimer = 0; + } + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; + break; + case 3: + m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); + if (m_HelpMessageFadeTimer < 0 || TheCamera.m_WideScreenOn) { + m_HelpMessageState = 0; + m_HelpMessageFadeTimer = 0; + } + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; + break; + case 4: + m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); + if (m_HelpMessageFadeTimer < 0) { + m_HelpMessageState = 2; + m_HelpMessageFadeTimer = 0; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, HELP_MSG_LENGTH); + } + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; + break; + default: + break; + } + + if (!TheCamera.m_WideScreenOn) { + m_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds(); + + CFont::SetAlphaFade(fAlpha); + CFont::SetCentreOff(); + CFont::SetPropOn(); + + if (CGame::germanGame) + CFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f)); +#ifdef MORE_LANGUAGES + else if (CFont::IsJapanese()) + CFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f); +#endif + else + CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); + + CFont::DrawFonts(); + CFont::SetColor(CRGBA(175, 175, 175, 255)); + CFont::SetJustifyOff(); +#ifdef MORE_LANGUAGES + if (CFont::IsJapanese()) + CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 34.0f - 4.0f)); + else +#endif + CFont::SetWrapx(SCREEN_SCALE_X(200.0f + 34.0f - 4.0f)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetBackgroundOn(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetDropShadowPosition(0); + CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f)); + CFont::SetColor(CRGBA(175, 175, 175, 255)); + CFont::PrintString(SCREEN_SCALE_X(34.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), m_HelpMessageToPrint); + CFont::SetAlphaFade(255.0f); + CFont::SetWrapx(SCREEN_WIDTH); + } + } + } else + m_HelpMessageState = 0; + + /* DrawBigMessage */ // MissionCompleteFailedText @@ -954,10 +1306,15 @@ void CHud::Draw() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); CFont::SetBackGroundOnlyTextOff(); - CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); + if (CGame::frenchGame || CGame::germanGame) { + CFont::SetScale(SCREEN_SCALE_X(1.6f), SCREEN_SCALE_Y(1.8f)); + } else { + CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); + } CFont::SetPropOn(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(25.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f)); + CFont::SetColor(CRGBA(255, 255, 0, BigMessageAlpha[0])); // unused color CFont::SetFontStyle(FONT_HEADING); // Appearently sliding text in here was abandoned very early, since this text is centered now. @@ -982,18 +1339,11 @@ void CHud::Draw() if (BigMessageAlpha[0] > 255.0f) BigMessageAlpha[0] = 255.0f; } - - CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[0])); -#ifdef FIX_BUGS -#define Y_OFFSET 18.0f -#else -#define Y_OFFSET 20.0f -#endif - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(Y_OFFSET) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]); + CFont::DrawFonts(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[0])); CFont::SetColor(CRGBA(BIGMESSAGE_COLOR.r, BIGMESSAGE_COLOR.g, BIGMESSAGE_COLOR.b, BigMessageAlpha[0])); CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]); - -#undef Y_OFFSET } else { BigMessageAlpha[0] = 0.0f; @@ -1024,15 +1374,19 @@ void CHud::Draw() CFont::SetRightJustifyOn(); 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::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); CFont::SetColor(CRGBA(WASTEDBUSTED_COLOR.r, WASTEDBUSTED_COLOR.g, WASTEDBUSTED_COLOR.b, BigMessageAlpha[2])); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(90.0f), m_BigMessage[2]); } else { - BigMessageAlpha[2] = 0.0f; BigMessageInUse[2] = 1.0f; + BigMessageAlpha[2] = 0.0f; + if (m_VehicleState != 0) // Hide vehicle name if wasted/busted text is displaying + m_VehicleState = 0; + if (m_ZoneState != 0) + m_ZoneState = 0; } } else { @@ -1043,108 +1397,13 @@ void CHud::Draw() void CHud::DrawAfterFade() { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + if (CTimer::GetIsUserPaused() || CReplay::IsPlayingBack()) return; - if (m_HelpMessage[0]) { - if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) { - switch (m_HelpMessageState) { - case 0: - m_HelpMessageFadeTimer = 0; - m_HelpMessageState = 2; - m_HelpMessageTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256); - m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; - - if (TheCamera.m_ScreenReductionPercentage == 0.0f) - DMAudio.PlayFrontEndSound(SOUND_HUD, 0); - break; - case 1: - case 2: - case 3: - case 4: - m_HelpMessageTimer = 5; - m_HelpMessageState = 4; - break; - default: - break; - } - CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); - } - - float fAlpha = 225.0f; - - if (m_HelpMessageState != 0) { - switch (m_HelpMessageState) { - case 1: - fAlpha = 225.0f; - m_HelpMessageFadeTimer = 600; - if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { - m_HelpMessageFadeTimer = 600; - m_HelpMessageState = 3; - } - break; - case 2: - m_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer > 0) { - m_HelpMessageState = 1; - m_HelpMessageFadeTimer = 0; - } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; - break; - case 3: - m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer < 0) { - m_HelpMessageState = 0; - m_HelpMessageFadeTimer = 0; - } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; - break; - case 4: - m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer < 0) { - m_HelpMessageState = 2; - m_HelpMessageFadeTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256); - } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; - break; - default: - break; - } - - m_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds(); - - CFont::SetAlphaFade(fAlpha); - CFont::SetCentreOff(); - CFont::SetPropOn(); - - if (CGame::germanGame) - CFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f)); -#ifdef MORE_LANGUAGES - else if (CFont::IsJapanese()) - CFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f); -#endif - else - CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); - - CFont::SetColor(CRGBA(175, 175, 175, 255)); - CFont::SetJustifyOff(); -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese()) - CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 26.0f - 4.0f)); - else -#endif - CFont::SetWrapx(SCREEN_SCALE_X(200.0f + 26.0f - 4.0f)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetBackgroundOn(); - CFont::SetBackGroundOnlyTextOff(); - 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); - } - } - 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) { @@ -1214,13 +1473,11 @@ void CHud::DrawAfterFade() CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(40.0f)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[3]); - + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(ODDJOB_COLOR); - CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[3]); + CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f) - SCREEN_SCALE_Y(16.0f), m_BigMessage[3]); } if (!m_BigMessage[1][0] && m_BigMessage[4][0]) { @@ -1229,14 +1486,12 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - - CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[4]); - + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(60.0f)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(ODDJOB_COLOR); - CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[4]); + CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f), m_BigMessage[4]); } // Oddjob result @@ -1286,20 +1541,18 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.2f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(80.0f)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); #ifdef BETA_SLIDING_TEXT - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f) - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); CFont::SetColor(ODDJOB2_COLOR); - CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); + CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_SCALE_Y(217.0f), m_BigMessage[5]); #else - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); CFont::SetColor(ODDJOB2_COLOR); - CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); + CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_Y(217.0f), m_BigMessage[5]); #endif } } @@ -1312,66 +1565,66 @@ void CHud::DrawAfterFade() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); + // will be overwritten below if (CGame::frenchGame || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH) CFont::SetScale(SCREEN_SCALE_X(0.884f), SCREEN_SCALE_Y(1.36f)); else CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); CFont::SetPropOn(); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(-500.0f)); + CFont::SetRightJustifyWrap(0.0f); CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); + CFont::SetFontStyle(FONT_BANK); + CFont::SetScale(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_AMERICAN ? SCREEN_SCALE_X(1.7f) : SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.8f)); + if (BigMessageX[1] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { BigMessageInUse[1] += CTimer::GetTimeStep(); if (BigMessageInUse[1] >= 120.0f) { BigMessageInUse[1] = 120.0f; - BigMessageAlpha[1] -= (CTimer::GetTimeStepInMilliseconds() * 0.3f); + BigMessageAlpha[1] -= CTimer::GetTimeStepInMilliseconds(); } - if (BigMessageAlpha[1] <= 0) { + if (BigMessageAlpha[1] <= 0.0f) { m_BigMessage[1][0] = 0; + BigMessageInUse[1] = 0.0f; BigMessageAlpha[1] = 0.0f; } } else { BigMessageX[1] += SCREEN_SCALE_X((CTimer::GetTimeStepInMilliseconds() * 0.3f)); - BigMessageAlpha[1] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); + BigMessageAlpha[1] += CTimer::GetTimeStepInMilliseconds(); if (BigMessageAlpha[1] > 255.0f) BigMessageAlpha[1] = 255.0f; } - CFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1])); -#ifdef BETA_SLIDING_TEXT - CFont::PrintString(SCREEN_SCALE_X(2.0f) + BigMessageX[1], SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[1]); + CFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1])); // what was that for? + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[1])); CFont::SetColor(CRGBA(MISSIONTITLE_COLOR.r, MISSIONTITLE_COLOR.g, MISSIONTITLE_COLOR.b, BigMessageAlpha[1])); - CFont::PrintString(BigMessageX[1], SCREEN_SCALE_FROM_BOTTOM(120.0f), m_BigMessage[1]); +#ifdef BETA_SLIDING_TEXT + CFont::PrintString(BigMessageX[1], SCREEN_SCALE_FROM_BOTTOM(140.0f), m_BigMessage[1]); #else - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[1]); - - CFont::SetColor(CRGBA(MISSIONTITLE_COLOR.r, MISSIONTITLE_COLOR.g, MISSIONTITLE_COLOR.b, BigMessageAlpha[1])); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), m_BigMessage[1]); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(140.0f), m_BigMessage[1]); #endif - } - else { - BigMessageAlpha[1] = 0.0f; + } else { + m_ZoneFadeTimer = 0; BigMessageX[1] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); BigMessageInUse[1] = 1.0f; + m_ZoneState = 0; } - } - else { + } else { BigMessageInUse[1] = 0.0f; } } void CHud::GetRidOfAllHudMessages() { - m_ZoneState = 0; - m_pLastZoneName = nil; m_ZoneNameTimer = 0; m_pZoneName = nil; + m_ZoneState = 0; - for (int i = 0; i < 256; i++) { + for (int i = 0; i < HELP_MSG_LENGTH; i++) { m_HelpMessage[i] = 0; m_LastHelpMessage[i] = 0; m_HelpMessageToPrint[i] = 0; @@ -1381,15 +1634,15 @@ void CHud::GetRidOfAllHudMessages() m_HelpMessageFadeTimer = 0; m_HelpMessageState = 0; m_HelpMessageQuick = 0; - m_fHelpMessageTime = 1.0f; + m_HelpMessageDisplayForever = false; + m_HelpMessageDisplayTime = 1.0f; m_VehicleName = nil; - m_pLastVehicleName = nil; m_pVehicleNameToPrint = nil; m_VehicleNameTimer = 0; m_VehicleFadeTimer = 0; m_VehicleState = 0; - for (int i = 0; i < 256; i++) + for (int i = 0; i < ARRAY_SIZE(m_Message); i++) m_Message[i] = 0; for (int i = 0; i < 6; i++) { @@ -1400,6 +1653,30 @@ void CHud::GetRidOfAllHudMessages() } } +#ifdef RELOADABLES +void CHud::ReloadTXD() +{ + for (int i = 0; i < NUM_HUD_SPRITES; ++i) { + Sprites[i].Delete(); + } + + int HudTXD = CTxdStore::FindTxdSlot("hud"); + CTxdStore::RemoveTxdSlot(HudTXD); + + debug("Reloading HUD.TXD...\n"); + + HudTXD = CTxdStore::AddTxdSlot("hud"); + CTxdStore::LoadTxd(HudTXD, "MODELS/HUD.TXD"); + CTxdStore::AddRef(HudTXD); + CTxdStore::PopCurrentTxd(); + CTxdStore::SetCurrentTxd(HudTXD); + + for (int i = 0; i < NUM_HUD_SPRITES; i++) { + Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); + } +} +#endif + void CHud::Initialise() { m_Wants_To_Draw_Hud = true; @@ -1415,20 +1692,34 @@ void CHud::Initialise() Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); } + m_pLastZoneName = nil; GetRidOfAllHudMessages(); + m_pLastVehicleName = nil; if (gpSniperSightTex == nil) - gpSniperSightTex = RwTextureRead("sitesniper", nil); + gpSniperSightTex = RwTextureRead("sitesniper", nil); // unused if (gpRocketSightTex == nil) gpRocketSightTex = RwTextureRead("siterocket", nil); - - CounterOnLastFrame = false; + if (gpLaserSightTex == nil) + gpLaserSightTex = RwTextureRead("sitelaser", nil); // unused + if (gpLaserDotTex == nil) + gpLaserDotTex = RwTextureRead("laserdot", "laserdotm"); + if (gpViewFinderTex == nil) + gpViewFinderTex = RwTextureRead("viewfinder_128", "viewfinder_128m"); // unused + + m_ClockState = 1; + CounterOnLastFrame[0] = false; + CounterOnLastFrame[1] = false; + CounterOnLastFrame[2] = false; + m_ItemToFlash = ITEM_NONE; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; OddJob2XOffset = 0.0f; - CounterFlashTimer = 0; + CounterFlashTimer[0] = 0; + CounterFlashTimer[1] = 0; + CounterFlashTimer[2] = 0; TimerOnLastFrame = false; TimerFlashTimer = 0; SpriteBrightness = 0; @@ -1437,6 +1728,32 @@ void CHud::Initialise() PagerSoundPlayed = 0; PagerXOffset = 150.0f; +#ifdef HUD_AUTO_FADE + m_EnergyLostState = START_FADE_OUT; + m_WantedState = START_FADE_OUT; + m_DisplayScoreState = START_FADE_OUT; + m_WeaponState = START_FADE_OUT; +#else + m_EnergyLostState = FADE_DISABLED; + m_WantedState = FADE_DISABLED; + m_DisplayScoreState = FADE_DISABLED; + m_WeaponState = FADE_DISABLED; +#endif + m_WantedFadeTimer = 0; + m_WantedTimer = 0; + m_EnergyLostFadeTimer = 0; + m_EnergyLostTimer = 0; + m_DisplayScoreFadeTimer = 0; + m_DisplayScoreTimer = 0; + m_WeaponFadeTimer = 0; + m_WeaponTimer = 0; + + m_HideRadar = false; + m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss; + m_LastWanted = 0; + m_LastWeapon = 0; + CTxdStore::PopCurrentTxd(); } @@ -1444,15 +1761,22 @@ void CHud::ReInitialise() { m_Wants_To_Draw_Hud = true; m_Wants_To_Draw_3dMarkers = true; + m_pLastZoneName = nil; GetRidOfAllHudMessages(); + m_pLastVehicleName = nil; - CounterOnLastFrame = false; + CounterOnLastFrame[0] = false; + CounterOnLastFrame[1] = false; + CounterOnLastFrame[2] = false; m_ItemToFlash = ITEM_NONE; + m_ClockState = 1; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; OddJob2XOffset = 0.0f; - CounterFlashTimer = 0; + CounterFlashTimer[0] = 0; + CounterFlashTimer[1] = 0; + CounterFlashTimer[2] = 0; TimerOnLastFrame = false; TimerFlashTimer = 0; SpriteBrightness = 0; @@ -1460,14 +1784,43 @@ void CHud::ReInitialise() { PagerTimer = 0; PagerSoundPlayed = 0; PagerXOffset = 150.0f; + +#ifdef HUD_AUTO_FADE + m_EnergyLostState = START_FADE_OUT; + m_WantedState = START_FADE_OUT; + m_DisplayScoreState = START_FADE_OUT; + m_WeaponState = START_FADE_OUT; +#else + m_EnergyLostState = FADE_DISABLED; + m_WantedState = FADE_DISABLED; + m_DisplayScoreState = FADE_DISABLED; + m_WeaponState = FADE_DISABLED; +#endif + m_WantedFadeTimer = 0; + m_WantedTimer = 0; + m_EnergyLostFadeTimer = 0; + m_EnergyLostTimer = 0; + m_DisplayScoreFadeTimer = 0; + m_DisplayScoreTimer = 0; + m_WeaponFadeTimer = 0; + m_WeaponTimer = 0; + + m_HideRadar = false; + m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss; + m_LastWanted = 0; + m_LastWeapon = 0; } wchar LastBigMessage[6][128]; -void CHud::SetBigMessage(wchar *message, int16 style) +void CHud::SetBigMessage(wchar *message, uint16 style) { int i = 0; + if (BigMessageInUse[style] != 0.0f) + return; + if (style == 5) { for (i = 0; i < 128; i++) { if (message[i] == 0) @@ -1492,25 +1845,54 @@ void CHud::SetBigMessage(wchar *message, int16 style) m_BigMessage[style][i] = 0; } -void CHud::SetHelpMessage(wchar *message, bool quick) +void CHud::SetHelpMessage(wchar *message, bool quick, bool displayForever) { if (!CReplay::IsPlayingBack()) { - CMessages::WideStringCopy(m_HelpMessage, message, 256); + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_HelpMessage[i] = 0; + } + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_LastHelpMessage[i] = 0; + } + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_HelpMessageToPrint[i] = 0; + } + + CMessages::WideStringCopy(m_HelpMessage, message, HELP_MSG_LENGTH); CMessages::InsertPlayerControlKeysInString(m_HelpMessage); + if (m_HelpMessageState == 0 || !CMessages::WideStringCompare(m_HelpMessage, m_HelpMessageToPrint, HELP_MSG_LENGTH)) { + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_LastHelpMessage[i] = 0; + } - for (int i = 0; i < 256; i++) { - m_LastHelpMessage[i] = 0; + if (!message) { + m_HelpMessage[0] = 0; + m_HelpMessageToPrint[0] = 0; + } + if (!displayForever) { + m_HelpMessageState = displayForever; + } else { + m_HelpMessageState = 1; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH); + CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH); + } + + m_HelpMessageQuick = quick; + m_HelpMessageDisplayForever = displayForever; } - m_HelpMessageState = 0; - m_HelpMessageQuick = quick; } } +bool CHud::IsHelpMessageBeingDisplayed(void) +{ + return m_HelpMessageState != 0; +} + void CHud::SetMessage(wchar *message) { int i = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < ARRAY_SIZE(m_Message); i++) { if (message[i] == 0) break; @@ -1522,7 +1904,7 @@ void CHud::SetMessage(wchar *message) void CHud::SetPagerMessage(wchar *message) { int i = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < ARRAY_SIZE(m_PagerMessage); i++) { if (message[i] == 0) break; @@ -1553,6 +1935,127 @@ void CHud::Shutdown() RwTextureDestroy(gpRocketSightTex); gpRocketSightTex = nil; + RwTextureDestroy(gpLaserSightTex); + gpLaserSightTex = nil; + + RwTextureDestroy(gpLaserDotTex); + gpLaserDotTex = nil; + + RwTextureDestroy(gpViewFinderTex); + gpViewFinderTex = nil; + int HudTXD = CTxdStore::FindTxdSlot("hud"); CTxdStore::RemoveTxdSlot(HudTXD); } + +float CHud::DrawFadeState(DRAW_FADE_STATE fadingElement, int forceFadingIn) +{ + float alpha = 255.0f; + uint32 operation, timer; + int32 fadeTimer; + + switch (fadingElement) { + case HUD_WANTED_FADING: + fadeTimer = m_WantedFadeTimer; + operation = m_WantedState; + timer = m_WantedTimer; + break; + case HUD_ENERGY_FADING: + fadeTimer = m_EnergyLostFadeTimer; + operation = m_EnergyLostState; + timer = m_EnergyLostTimer; + break; + case HUD_SCORE_FADING: + fadeTimer = m_DisplayScoreFadeTimer; + operation = m_DisplayScoreState; + timer = m_DisplayScoreTimer; + break; + case HUD_WEAPON_FADING: + fadeTimer = m_WeaponFadeTimer; + operation = m_WeaponState; + timer = m_WeaponTimer; + break; + default: + break; + } + if (forceFadingIn) { + switch (operation) { + case FADED_OUT: + fadeTimer = 0; + case START_FADE_OUT: + case FADING_OUT: + timer = 5; + operation = FADING_IN; + break; + default: + break; + } + } + if (operation != FADED_OUT && operation != FADE_DISABLED) { + switch (operation) { + case START_FADE_OUT: + fadeTimer = 1000; + alpha = 255.0f; + if (timer > 10000) { + fadeTimer = 3000; + operation = FADING_OUT; + } + break; + case FADING_IN: + fadeTimer += CTimer::GetTimeStepInMilliseconds(); + if (fadeTimer > 1000.0f) { + operation = START_FADE_OUT; + fadeTimer = 1000; + } + alpha = fadeTimer / 1000.0f * 255.0f; + break; + case FADING_OUT: + fadeTimer -= CTimer::GetTimeStepInMilliseconds(); + if (fadeTimer < 0.0f) { + fadeTimer = 0; + operation = FADED_OUT; + } + alpha = fadeTimer / 1000.0f * 255.0f; + break; + default: + break; + } + timer += CTimer::GetTimeStepInMilliseconds(); + } + + switch (fadingElement) { + case HUD_WANTED_FADING: + m_WantedFadeTimer = fadeTimer; + m_WantedState = operation; + m_WantedTimer = timer; + break; + case HUD_ENERGY_FADING: + m_EnergyLostFadeTimer = fadeTimer; + m_EnergyLostState = operation; + m_EnergyLostTimer = timer; + break; + case HUD_SCORE_FADING: + m_DisplayScoreFadeTimer = fadeTimer; + m_DisplayScoreState = operation; + m_DisplayScoreTimer = timer; + break; + case HUD_WEAPON_FADING: + m_WeaponFadeTimer = fadeTimer; + m_WeaponState = operation; + m_WeaponTimer = timer; + break; + default: + break; + } + + return clamp(alpha, 0.0f, 255.0f); +} + +void +CHud::ResetWastedText(void) +{ + BigMessageInUse[2] = 0.0f; + BigMessageInUse[0] = 0.0f; + m_BigMessage[2][0] = 0; + m_BigMessage[0][0] = 0; +}
\ No newline at end of file diff --git a/src/render/Hud.h b/src/render/Hud.h index 701e47e2..a4b9609a 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -1,6 +1,11 @@ #pragma once #include "Sprite2d.h" +#define HELP_MSG_LENGTH 256 + +#define HUD_TEXT_SCALE_X 0.7f +#define HUD_TEXT_SCALE_Y 1.25f + enum eItems { ITEM_NONE = -1, @@ -9,41 +14,51 @@ enum eItems ITEM_RADAR = 8 }; +// Thanks for vague name, R* +enum DRAW_FADE_STATE +{ + HUD_WANTED_FADING = 0, + HUD_ENERGY_FADING, + HUD_SCORE_FADING, + HUD_WEAPON_FADING, +}; + +// My name +enum eFadeOperation +{ + FADED_OUT = 0, + START_FADE_OUT, + FADING_IN, + FADING_OUT, + FADE_DISABLED = 5, +}; + enum eSprites { HUD_FIST, - HUD_BAT, - HUD_PISTOL, - HUD_UZI, - HUD_SHOTGUN, - HUD_AK47, - HUD_M16, - HUD_SNIPER, - HUD_ROCKET, - HUD_FLAME, - HUD_MOLOTOV, - HUD_GRENADE, - HUD_DETONATOR, - HUD_RADARDISC = 15, - HUD_PAGER = 16, - HUD_SITESNIPER = 20, + HUD_SITEROCKET = 41, + HUD_RADARDISC = 50, + HUD_SITESNIPER = 63, HUD_SITEM16, - HUD_SITEROCKET, - NUM_HUD_SPRITES, + HUD_SITELASER, + HUD_LASERDOT, + HUD_VIEWFINDER, + HUD_BLEEDER, + NUM_HUD_SPRITES = 69, }; class CHud { public: static CSprite2d Sprites[NUM_HUD_SPRITES]; - static wchar m_HelpMessage[256]; - static wchar m_LastHelpMessage[256]; + static wchar m_HelpMessage[HELP_MSG_LENGTH]; + static wchar m_LastHelpMessage[HELP_MSG_LENGTH]; static uint32 m_HelpMessageState; static uint32 m_HelpMessageTimer; static int32 m_HelpMessageFadeTimer; - static wchar m_HelpMessageToPrint[256]; - static float &m_HelpMessageDisplayTime; - static float m_fHelpMessageTime; + static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH]; + static float m_HelpMessageDisplayTime; + static bool m_HelpMessageDisplayForever; static bool m_HelpMessageQuick; static uint32 m_ZoneState; static int32 m_ZoneFadeTimer; @@ -63,15 +78,17 @@ public: static bool m_Wants_To_Draw_3dMarkers; static wchar m_BigMessage[6][128]; static int16 m_ItemToFlash; + static bool m_HideRadar; + static int32 m_ClockState; // These aren't really in CHud static float BigMessageInUse[6]; static float BigMessageAlpha[6]; static float BigMessageX[6]; static float OddJob2OffTimer; - static bool CounterOnLastFrame; + static bool CounterOnLastFrame[NUMONSCREENCOUNTERS]; static float OddJob2XOffset; - static uint16 CounterFlashTimer; + static uint16 CounterFlashTimer[NUMONSCREENCOUNTERS]; static uint16 OddJob2Timer; static bool TimerOnLastFrame; static int16 OddJob2On; @@ -82,17 +99,41 @@ public: static int16 PagerTimer; static int16 PagerOn; + static uint32 m_WantedFadeTimer; + static uint32 m_WantedState; + static uint32 m_WantedTimer; + static uint32 m_EnergyLostFadeTimer; + static uint32 m_EnergyLostState; + static uint32 m_EnergyLostTimer; + static uint32 m_DisplayScoreFadeTimer; + static uint32 m_DisplayScoreState; + static uint32 m_DisplayScoreTimer; + static uint32 m_WeaponFadeTimer; + static uint32 m_WeaponState; + static uint32 m_WeaponTimer; + + static uint32 m_LastDisplayScore; + static uint32 m_LastWanted; + static uint32 m_LastWeapon; + static uint32 m_LastTimeEnergyLost; + public: static void Draw(); static void DrawAfterFade(); static void GetRidOfAllHudMessages(); +#ifdef RELOADABLES + static void ReloadTXD(); +#endif static void Initialise(); static void ReInitialise(); - static void SetBigMessage(wchar *message, int16 style); - static void SetHelpMessage(wchar *message, bool quick); + static void SetBigMessage(wchar *message, uint16 style); + static void SetHelpMessage(wchar *message, bool quick, bool displayForever = false); + static bool IsHelpMessageBeingDisplayed(void); static void SetMessage(wchar *message); static void SetPagerMessage(wchar *message); static void SetVehicleName(wchar *name); static void SetZoneName(wchar *name); static void Shutdown(); + static float DrawFadeState(DRAW_FADE_STATE, int); + static void ResetWastedText(void); }; diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index de15358e..08298a1f 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -10,6 +10,7 @@ #include "RwHelper.h" #include "Camera.h" #include "MBlur.h" +#include "Timer.h" #include "postfx.h" // Originally taken from RW example 'mblur' @@ -18,8 +19,10 @@ RwRaster *CMBlur::pFrontBuffer; bool CMBlur::ms_bJustInitialised; bool CMBlur::ms_bScaledBlur; bool CMBlur::BlurOn; +float CMBlur::Drunkness; static RwIm2DVertex Vertex[4]; +static RwIm2DVertex Vertex2[4]; static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 }; #ifndef LIBRW @@ -201,6 +204,43 @@ CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect) RwIm2DVertexSetU(&Vertex[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam)); RwIm2DVertexSetV(&Vertex[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam)); RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255); + + + RwIm2DVertexSetScreenX(&Vertex2[0], zero + 2.0f); + RwIm2DVertexSetScreenY(&Vertex2[0], zero + 2.0f); + RwIm2DVertexSetScreenZ(&Vertex2[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Vertex2[0], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&Vertex2[0], 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetU(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetV(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetIntRGBA(&Vertex2[0], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&Vertex2[1], 2.0f); + RwIm2DVertexSetScreenY(&Vertex2[1], ymax + 2.0f); + RwIm2DVertexSetScreenZ(&Vertex2[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Vertex2[1], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&Vertex2[1], 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetU(&Vertex2[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetV(&Vertex2[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetIntRGBA(&Vertex2[1], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&Vertex2[2], xmax + 2.0f); + RwIm2DVertexSetScreenY(&Vertex2[2], ymax + 2.0f); + RwIm2DVertexSetScreenZ(&Vertex2[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Vertex2[2], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&Vertex2[2], 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetU(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetV(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetIntRGBA(&Vertex2[2], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&Vertex2[3], xmax + 2.0f); + RwIm2DVertexSetScreenY(&Vertex2[3], zero + 2.0f); + RwIm2DVertexSetScreenZ(&Vertex2[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Vertex2[3], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&Vertex2[3], 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetU(&Vertex2[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetV(&Vertex2[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetIntRGBA(&Vertex2[3], 255, 255, 255, 255); } void @@ -214,23 +254,24 @@ CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, u if( pFrontBuffer ) OverlayRender(cam, pFrontBuffer, color, type, bluralpha); #else + if(ms_bJustInitialised) + ms_bJustInitialised = false; + else + OverlayRender(cam, pFrontBuffer, color, type, bluralpha); if(BlurOn){ - if(pFrontBuffer){ - if(ms_bJustInitialised) - ms_bJustInitialised = false; - else - OverlayRender(cam, pFrontBuffer, color, type, bluralpha); - } RwRasterPushContext(pFrontBuffer); RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0); RwRasterPopContext(); - }else{ - OverlayRender(cam, nil, color, type, bluralpha); } #endif #endif } +static uint8 DrunkBlurRed = 128; +static uint8 DrunkBlurGreen = 128; +static uint8 DrunkBlurBlue = 128; +static int32 DrunkBlurIncrement = 1; + void CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha) { @@ -278,41 +319,104 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, } if(!BlurOn){ - r = Min(r*0.6f, 255.0f); - g = Min(g*0.6f, 255.0f); - b = Min(b*0.6f, 255.0f); - if(type != MOTION_BLUR_SNIPER) - a = Min(a*0.6f, 255.0f); - // game clamps to 255 here, but why? + // gta clamps these to 255 (probably a macro or inlined function) + int ovR = r * 0.6f; + int ovG = g * 0.6f; + int ovB = b * 0.6f; + int ovA = type == MOTION_BLUR_SNIPER ? a : a*0.6f; + RwIm2DVertexSetIntRGBA(&Vertex[0], ovR, ovG, ovB, ovA); + RwIm2DVertexSetIntRGBA(&Vertex[1], ovR, ovG, ovB, ovA); + RwIm2DVertexSetIntRGBA(&Vertex[2], ovR, ovG, ovB, ovA); + RwIm2DVertexSetIntRGBA(&Vertex[3], ovR, ovG, ovB, ovA); + }else{ + RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a); } - RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a); - RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a); - RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a); - RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, BlurOn ? raster : nil); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + if(BlurOn){ + if(type == MOTION_BLUR_SNIPER){ + RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, 80); + RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, 80); + RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, 80); + RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, 80); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + // TODO(MIAMI): pBufVertCount = 0; + }else{ + RwIm2DVertexSetIntRGBA(&Vertex2[0], r*2, g*2, b*2, 30); + RwIm2DVertexSetIntRGBA(&Vertex2[1], r*2, g*2, b*2, 30); + RwIm2DVertexSetIntRGBA(&Vertex2[2], r*2, g*2, b*2, 30); + RwIm2DVertexSetIntRGBA(&Vertex2[3], r*2, g*2, b*2, 30); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6); - a = bluralpha/2; - if(a < 30) - a = 30; + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a); + RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6); + } + } - if(BlurOn && a != 0){ // the second condition should always be true - RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, a); - RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, a); - RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, a); - RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, a); + int DrunkBlurAlpha = 175.0f * Drunkness; + if(DrunkBlurAlpha != 0){ + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + if(BlurOn){ + RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, DrunkBlurAlpha); + RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, DrunkBlurAlpha); + RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, DrunkBlurAlpha); + RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, DrunkBlurAlpha); + }else{ + RwIm2DVertexSetIntRGBA(&Vertex[0], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha); + RwIm2DVertexSetIntRGBA(&Vertex[1], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha); + RwIm2DVertexSetIntRGBA(&Vertex[2], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha); + RwIm2DVertexSetIntRGBA(&Vertex[3], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha); + if(DrunkBlurIncrement){ + if(DrunkBlurRed < 255) DrunkBlurRed++; + if(DrunkBlurGreen < 255) DrunkBlurGreen++; + if(DrunkBlurBlue < 255) DrunkBlurBlue++; + if(DrunkBlurRed == 255) + DrunkBlurIncrement = 0; + }else{ + if(DrunkBlurRed > 128) DrunkBlurRed--; + if(DrunkBlurGreen > 128) DrunkBlurGreen--; + if(DrunkBlurBlue > 128) DrunkBlurBlue--; + if(DrunkBlurRed == 128) + DrunkBlurIncrement = 1; + } + } RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6); } + // TODO(MIAMI): OverlayRenderFx + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); @@ -321,3 +425,16 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); } + +void +CMBlur::SetDrunkBlur(float drunkness) +{ + Drunkness = clamp(drunkness, 0.0f, 1.0f); +} + +void +CMBlur::ClearDrunkBlur() +{ + Drunkness = 0.0f; + CTimer::SetTimeScale(1.0f); +}
\ No newline at end of file diff --git a/src/render/MBlur.h b/src/render/MBlur.h index e2e5d38c..c2572256 100644 --- a/src/render/MBlur.h +++ b/src/render/MBlur.h @@ -1,5 +1,15 @@ #pragma once +enum FxType +{ + FXTYPE_0 = 0, + FXTYPE_1, + FXTYPE_2, + FXTYPE_3, + FXTYPE_4, + FXTYPE_5, +}; + class CMBlur { public: @@ -7,6 +17,7 @@ public: static bool ms_bJustInitialised; static bool ms_bScaledBlur; static bool BlurOn; + static float Drunkness; public: static RwBool MotionBlurOpen(RwCamera *cam); @@ -14,4 +25,10 @@ public: static void CreateImmediateModeData(RwCamera *cam, RwRect *rect); static void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha); static void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha); + static void SetDrunkBlur(float drunkness); + static void ClearDrunkBlur(); + + //TODO + static void AddRenderFx(RwCamera *,RwRect *,float,FxType) + {} }; diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp new file mode 100644 index 00000000..79ce0461 --- /dev/null +++ b/src/render/Occlusion.cpp @@ -0,0 +1,490 @@ +#include "common.h" + +#include "main.h" +#include "Occlusion.h" +#include "Game.h" +#include "Camera.h" +#include "Vector.h" +#include "Draw.h" +#include "Timer.h" +#include "RwHelper.h" + +int32 COcclusion::NumOccludersOnMap; +int16 COcclusion::FarAwayList; +int16 COcclusion::NearbyList; +int16 COcclusion::ListWalkThroughFA; +int16 COcclusion::PreviousListWalkThroughFA; +int16 COcclusion::NumActiveOccluders; +COccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES]; +CActiveOccluder COcclusion::aActiveOccluders[NUMACTIVEOCCLUDERS]; + +CVector gCenterOnScreen; + +float gMinYInOccluder; +float gMinXInOccluder; +float gMaxYInOccluder; +float gMaxXInOccluder; + +bool gOccluderCoorsValid[8]; +CVector gOccluderCoorsOnScreen[8]; +CVector gOccluderCoors[8]; + +#ifndef MASTER +bool bDisplayOccDebugStuff; +#endif + +void +COcclusion::Init(void) +{ + NumOccludersOnMap = 0; + FarAwayList = -1; + NearbyList = -1; + ListWalkThroughFA = -1; + PreviousListWalkThroughFA = -1; +#ifndef MASTER + bDisplayOccDebugStuff = false; +#endif +} + +void +COcclusion::AddOne(float x, float y, float z, float width, float length, float height, float angle) +{ + if(NumOccludersOnMap >= NUMOCCLUSIONVOLUMES) + return; + + aOccluders[NumOccludersOnMap].x = x; + aOccluders[NumOccludersOnMap].y = y; + aOccluders[NumOccludersOnMap].z = z; + aOccluders[NumOccludersOnMap].width = width; + aOccluders[NumOccludersOnMap].length = length; + aOccluders[NumOccludersOnMap].height = height; + while(angle < 0.0f) angle += 360.0f; + while(angle > 360.0f) angle -= 360.0f; + aOccluders[NumOccludersOnMap].angle = angle/360.0f * UINT16_MAX; + aOccluders[NumOccludersOnMap].listIndex = FarAwayList; + FarAwayList = NumOccludersOnMap++; +} + +bool +COccluder::NearCamera() { + return (TheCamera.GetPosition() - CVector(x, y, z)).Magnitude() - (Max(width, length) / 2.0f) < 250.0f; +} + +bool +DoesInfiniteLineCrossFiniteLine(float p1X, float p1Y, float p2X, float p2Y, float lineX, float lineY, float lineDX, float lineDY) +{ + float side1 = (p1X - lineX) * lineDY - (p1Y - lineY) * lineDX; + float side2 = (p2X - lineX) * lineDY - (p2Y - lineY) * lineDX; + return side1 * side2 < 0.0f; // if points lie on opposite sides of the infinte line, the line between them crosses it +} + +bool DoesInfiniteLineTouchScreen(float lineX, float lineY, float lineDX, float lineDY) { + if (lineX > 0.0f && lineY > 0.0f && SCREEN_WIDTH > lineX && SCREEN_HEIGHT > lineY) + return true; + + return (DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, lineX, lineY, lineDX, lineDY) || + DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, 0.0f, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) || + DoesInfiniteLineCrossFiniteLine(SCREEN_WIDTH, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) || + DoesInfiniteLineCrossFiniteLine(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY)); +} + +bool IsPointInsideLine(float lineX, float lineY, float lineDX, float lineDY, float pX, float pY, float area = 0.0f) { + return (pX - lineX) * lineDY - (pY - lineY) * lineDX >= area; +} + +bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh) { + *out = TheCamera.m_viewMatrix * in; + + if (out->z <= 1.0f) return false; + + float recip = 1.0f / out->z; + out->x *= SCREEN_WIDTH * recip; + out->y *= SCREEN_HEIGHT * recip; + + float fovScale = DefaultFOV / CDraw::GetFOV(); + + *outw = fovScale * recip * SCREEN_WIDTH; + *outh = fovScale * recip * SCREEN_HEIGHT; + + return true; +} + +bool CalcScreenCoors(CVector const &in, CVector *out) { + *out = TheCamera.m_viewMatrix * in; + + if (out->z <= 1.0f) return false; + + float recip = 1.0f / out->z; + out->x *= SCREEN_WIDTH * recip; + out->y *= SCREEN_HEIGHT * recip; + + return true; +} + +bool +COccluder::ProcessLineSegment(int corner1, int corner2, CActiveOccluder *occl) { + if (!gOccluderCoorsValid[corner1] && !gOccluderCoorsValid[corner2]) + return false; + + float x1, y1, x2, y2; + + CVector p1, p2; + if (!gOccluderCoorsValid[corner1]) { + float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f); + float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f); + float ratio = clipDist2 / (clipDist1 + clipDist2); + CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1]; + + if (!CalcScreenCoors(clippedCoors, &p1, &x1, &y1)) + return true; + } + else { + p1 = gOccluderCoorsOnScreen[corner1]; + } + + if (!gOccluderCoorsValid[corner2]) { + float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f); + float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f); + float ratio = clipDist1 / (clipDist1 + clipDist2); + CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1]; + + if (!CalcScreenCoors(clippedCoors, &p2, &x2, &y2)) + return true; + } + else { + p2 = gOccluderCoorsOnScreen[corner2]; + } + + gMinXInOccluder = Min(Min(gMinXInOccluder, p1.x), p2.x); + gMaxXInOccluder = Max(Max(gMaxXInOccluder, p1.x), p2.x); + gMinYInOccluder = Min(Min(gMinYInOccluder, p1.y), p2.y); + gMaxYInOccluder = Max(Max(gMaxYInOccluder, p1.y), p2.y); + + CVector2D origin = p1; + CVector2D direction = p2 - p1; + + // Make sure lines are counter-clockwise around center + if (!IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, gCenterOnScreen.x, gCenterOnScreen.y, 0.0f)) { + origin += direction; + direction *= -1.0f; + } + + float magnitude = direction.Magnitude(); + + occl->lines[occl->linesCount].origin = origin; + occl->lines[occl->linesCount].direction = direction / magnitude; + occl->lines[occl->linesCount].length = magnitude; + + if (!DoesInfiniteLineTouchScreen(origin.x, origin.y, direction.x, direction.y)) + return !IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f, 0.0f); + + occl->linesCount++; + + return false; +} + +bool +COccluder::ProcessOneOccluder(CActiveOccluder *occl) { + float outX, outY; + + occl->linesCount = 0; + CVector pos(x, y, z); + + if (!CalcScreenCoors(pos, &gCenterOnScreen, &outX, &outY) || gCenterOnScreen.z < -150.0f || gCenterOnScreen.z > 300.0f) { + return false; + } + + occl->radius = Max(width, length) * 0.35f + gCenterOnScreen.z; + + CVector vec[3]; + + vec[0].x = length / 2.0f * Sin(GetAngle()); + vec[0].y = -length / 2.0f * Cos(GetAngle()); + vec[0].z = 0.0f; + + vec[1].x = width / 2.0f * Cos(GetAngle()); + vec[1].y = width / 2.0f * Sin(GetAngle()); + vec[1].z = 0.0f; + + vec[2].x = 0.0f; + vec[2].y = 0.0f; + vec[2].z = height / 2.0f; + + // Figure out if we see the front or back of a face + bool bFrontFace[6]; + for (int i = 0; i < 3; i++) { + bFrontFace[i*2+0] = DotProduct((pos + vec[i] - TheCamera.GetPosition()), vec[i]) < 0.0f; + bFrontFace[i*2+1] = DotProduct((pos - vec[i] - TheCamera.GetPosition()), -vec[i]) < 0.0f; + } + + //calculating vertices of a box + gOccluderCoors[0] = pos + vec[0] + vec[1] + vec[2]; + gOccluderCoors[1] = pos - vec[0] + vec[1] + vec[2]; + gOccluderCoors[2] = pos + vec[0] - vec[1] + vec[2]; + gOccluderCoors[3] = pos - vec[0] - vec[1] + vec[2]; + gOccluderCoors[4] = pos + vec[0] + vec[1] - vec[2]; + gOccluderCoors[5] = pos - vec[0] + vec[1] - vec[2]; + gOccluderCoors[6] = pos + vec[0] - vec[1] - vec[2]; + gOccluderCoors[7] = pos - vec[0] - vec[1] - vec[2]; + + for(int i = 0; i < 8; i++) + gOccluderCoorsValid[i] = CalcScreenCoors(gOccluderCoors[i], &gOccluderCoorsOnScreen[i], &outX, &outY); + + gMinYInOccluder = 999999.875f; + gMinXInOccluder = 999999.875f; + gMaxYInOccluder = -999999.875f; + gMaxXInOccluder = -999999.875f; + + // Between two differently facing sides we see an edge, so process those + if (bFrontFace[2] != bFrontFace[0] && ProcessLineSegment(0, 4, occl)) + return false; + if (bFrontFace[3] != bFrontFace[0] && ProcessLineSegment(2, 6, occl)) + return false; + if (bFrontFace[4] != bFrontFace[0] && ProcessLineSegment(0, 2, occl)) + return false; + if (bFrontFace[5] != bFrontFace[0] && ProcessLineSegment(4, 6, occl)) + return false; + if (bFrontFace[2] != bFrontFace[1] && ProcessLineSegment(1, 5, occl)) + return false; + if (bFrontFace[3] != bFrontFace[1] && ProcessLineSegment(3, 7, occl)) + return false; + if (bFrontFace[4] != bFrontFace[1] && ProcessLineSegment(1, 3, occl)) + return false; + if (bFrontFace[5] != bFrontFace[1] && ProcessLineSegment(5, 7, occl)) + return false; + if (bFrontFace[4] != bFrontFace[2] && ProcessLineSegment(0, 1, occl)) + return false; + if (bFrontFace[3] != bFrontFace[4] && ProcessLineSegment(2, 3, occl)) + return false; + if (bFrontFace[5] != bFrontFace[3] && ProcessLineSegment(6, 7, occl)) + return false; + if (bFrontFace[2] != bFrontFace[5] && ProcessLineSegment(4, 5, occl)) + return false; + + if (gMaxXInOccluder - gMinXInOccluder < SCREEN_WIDTH * 0.1f || + gMaxYInOccluder - gMinYInOccluder < SCREEN_HEIGHT * 0.07f) + return false; + + return true; +} + +bool +COcclusion::OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2) { + for (int i = 0; i < occl1->linesCount; i++) { + for (int j = 0; j < occl2->linesCount; j++) { + if (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x, + occl2->lines[j].direction.y, occl1->lines[i].origin.x, occl1->lines[i].origin.y, 0.0f)) + return false; + + + if (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x, + occl2->lines[j].direction.y, (occl1->lines[i].origin.x + occl1->lines[i].direction.x * occl1->lines[i].length), + (occl1->lines[i].origin.y + occl1->lines[i].direction.y * occl1->lines[i].length), 0.0f)) + return false; + } + } + + return true; +} + +void +COcclusion::ProcessBeforeRendering(void) +{ + NumActiveOccluders = 0; + + if (CGame::currArea != AREA_MAIN_MAP) + return; + + if (ListWalkThroughFA == -1) { + PreviousListWalkThroughFA = -1; + ListWalkThroughFA = FarAwayList; + } + + int i; + for (i = 0; i < 16 && ListWalkThroughFA != -1; i++) { + if (aOccluders[ListWalkThroughFA].NearCamera()) { + int prevListWalkThroughFA = ListWalkThroughFA; + + if (PreviousListWalkThroughFA == -1) { + FarAwayList = aOccluders[ListWalkThroughFA].listIndex; + } + else { + aOccluders[PreviousListWalkThroughFA].listIndex = aOccluders[ListWalkThroughFA].listIndex; + } + + int prevNearbyList = NearbyList; + ListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex; + NearbyList = prevListWalkThroughFA; + aOccluders[prevListWalkThroughFA].listIndex = prevNearbyList; + } + else { + PreviousListWalkThroughFA = ListWalkThroughFA; + ListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex; + } + } + + int prevNearbyList = -1; + int tmpNearbyList = NearbyList; + int indexTmpNearbyList, storeTmpNearbyList, prevFarAwayList; + while (tmpNearbyList != -1) + { + if (NumActiveOccluders < NUMACTIVEOCCLUDERS && aOccluders[tmpNearbyList].ProcessOneOccluder(&aActiveOccluders[NumActiveOccluders])) + ++NumActiveOccluders; + + indexTmpNearbyList = tmpNearbyList; + if (aOccluders[indexTmpNearbyList].NearCamera()) + { + prevNearbyList = tmpNearbyList; + tmpNearbyList = aOccluders[indexTmpNearbyList].listIndex; + + } + else + { + storeTmpNearbyList = tmpNearbyList; + if (prevNearbyList == -1) { + NearbyList = aOccluders[indexTmpNearbyList].listIndex; + } + else { + aOccluders[prevNearbyList].listIndex = aOccluders[indexTmpNearbyList].listIndex; + } + tmpNearbyList = aOccluders[indexTmpNearbyList].listIndex; + prevFarAwayList = FarAwayList; + FarAwayList = storeTmpNearbyList; + aOccluders[storeTmpNearbyList].listIndex = prevFarAwayList; + } + } + + for (i = 0; i < NumActiveOccluders; i++) { + for (int j = 0; j < NumActiveOccluders; j++) { + if (i != j && aActiveOccluders[j].radius < aActiveOccluders[i].radius) { + if (OccluderHidesBehind(&aActiveOccluders[i], &aActiveOccluders[j])) { + for (int k = i; k < NumActiveOccluders - 1; k++) { + for (int l = 0; l < aActiveOccluders[k + 1].linesCount; l++) + aActiveOccluders[k].lines[l] = aActiveOccluders[k + 1].lines[l]; + aActiveOccluders[k].linesCount = aActiveOccluders[k + 1].linesCount; + aActiveOccluders[k].radius = aActiveOccluders[k + 1].radius; + } + NumActiveOccluders--; + i--; + // Taken from Mobile! +#ifdef FIX_BUGS + if (i == -1) { + i = 0; + } +#endif + } + } + } + } +} + +bool CActiveOccluder::IsPointWithinOcclusionArea(float pX, float pY, float area) { + for (int i = 0; i < linesCount; i++) { + if (!IsPointInsideLine(lines[i].origin.x, lines[i].origin.y, lines[i].direction.x, lines[i].direction.y, pX, pY, area)) + return false; + } + + return true; +} + +bool COcclusion::IsAABoxOccluded(CVector pos, float width, float length, float height) { + + CVector coors; + float outW, outH; + + if (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &outW, &outH)) + return false; + + float side = CVector(width, length, height).Magnitude() / 4.0f; + float area = Max(outW, outH) * side; + + CVector minCorner, maxCorner; + + minCorner.x = pos.x - width / 2.0f; + minCorner.y = pos.y - length / 2.0f; + minCorner.z = pos.z - height / 2.0f; + + maxCorner.x = pos.x + width / 2.0f; + maxCorner.y = pos.y + length / 2.0f; + maxCorner.z = pos.z + height / 2.0f; + + for (int i = 0; i < NumActiveOccluders; i++) { + if (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) { + if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) + return true; + + if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) { + if (CalcScreenCoors(minCorner, &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(maxCorner.x, maxCorner.y, minCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(maxCorner.x, minCorner.y, maxCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(minCorner.x, maxCorner.y, maxCorner.z), &coors, &outW, &outH) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + + return true; + } + } + } + + return false; +} + +bool COcclusion::IsPositionOccluded(CVector pos, float side) { + + CVector coors; + float width, height; + + if (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &width, &height)) + return false; + + float area = Max(width, height) * side; + + for (int i = 0; i < NumActiveOccluders; i++) { + if (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) + if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) + return true; + } + + return false; +} + +#ifndef MASTER +#include "Lines.h" + +RwIm2DVertex vertexbufferT[2]; + +void COcclusion::Render() { + if (!bDisplayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200)) + return; + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, FALSE); + + float recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera); + for (int i = 0; i < NumActiveOccluders; i++) { + for (int j = 0; j < aActiveOccluders[i].linesCount; j++) { + RwIm2DVertexSetScreenX(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.x); + RwIm2DVertexSetScreenY(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.y); + RwIm2DVertexSetScreenZ(&vertexbufferT[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&vertexbufferT[0], RwCameraGetNearClipPlane(Scene.camera)); + RwIm2DVertexSetRecipCameraZ(&vertexbufferT[0], recipz); + + RwIm2DVertexSetScreenX(&vertexbufferT[1], + aActiveOccluders[i].lines[j].origin.x + aActiveOccluders[i].lines[j].direction.x * aActiveOccluders[i].lines[j].length); + RwIm2DVertexSetScreenY(&vertexbufferT[1], + aActiveOccluders[i].lines[j].origin.y + aActiveOccluders[i].lines[j].direction.y * aActiveOccluders[i].lines[j].length); + RwIm2DVertexSetScreenZ(&vertexbufferT[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&vertexbufferT[1], RwCameraGetNearClipPlane(Scene.camera)); + RwIm2DVertexSetRecipCameraZ(&vertexbufferT[1], recipz); + + RwIm2DVertexSetIntRGBA(&vertexbufferT[0], 255, 255, 0, 255); + RwIm2DVertexSetIntRGBA(&vertexbufferT[1], 255, 255, 0, 255); + RwIm2DRenderLine(vertexbufferT, 2, 0, 1); + } + } + + DefinedState(); +} +#endif diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h new file mode 100644 index 00000000..8a444525 --- /dev/null +++ b/src/render/Occlusion.h @@ -0,0 +1,62 @@ +#pragma once + +struct ActiveOccluderLine { + CVector2D origin; + CVector2D direction; + float length; +}; + +class CActiveOccluder { + +public: + ActiveOccluderLine lines[6]; + int32 linesCount; + float radius; + + bool IsPointWithinOcclusionArea(float x, float y, float area); +}; + +class COccluder +{ +public: + int16 length, width, height; + int16 x, y, z; + uint16 angle; + int16 listIndex; + + bool NearCamera(); + bool ProcessOneOccluder(CActiveOccluder *occl); + bool ProcessLineSegment(int corner1, int corner2, CActiveOccluder* occl); + float GetAngle(void) { return angle*TWOPI/UINT16_MAX; } +}; + +class COcclusion +{ +public: + static int32 NumOccludersOnMap; + static int16 FarAwayList; + static int16 NearbyList; + static int16 ListWalkThroughFA; + static int16 PreviousListWalkThroughFA; + static int16 NumActiveOccluders; + + static COccluder aOccluders[NUMOCCLUSIONVOLUMES]; + static CActiveOccluder aActiveOccluders[NUMACTIVEOCCLUDERS]; + + static void Init(void); + static void AddOne(float x, float y, float z, float width, float length, float height, float angle); + static void ProcessBeforeRendering(void); + static bool OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2); + static bool IsAABoxOccluded(CVector pos, float width, float length, float height); + static bool IsPositionOccluded(CVector pos, float side); +#ifndef MASTER + static void Render(); +#endif +}; + +bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh); +bool CalcScreenCoors(CVector const &in, CVector *out); + +#ifndef MASTER +extern bool bDisplayOccDebugStuff; +#endif
\ No newline at end of file diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index a867ae13..6a42bc4d 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -5,23 +5,27 @@ #include "TxdStore.h" #include "Sprite.h" #include "Camera.h" +#include "Clock.h" #include "Collision.h" #include "World.h" #include "Shadows.h" +#include "Replay.h" +#include "Stats.h" +#include "Weather.h" +#include "MBlur.h" +#include "main.h" #include "AudioScriptObject.h" #include "ParticleObject.h" #include "Particle.h" #include "soundlist.h" -#define MAX_PARTICLES_ON_SCREEN (1000) +#define MAX_PARTICLES_ON_SCREEN (750) //(5) #define MAX_SMOKE_FILES ARRAY_SIZE(SmokeFiles) -//(5) -#define MAX_SMOKE2_FILES ARRAY_SIZE(Smoke2Files) //(5) #define MAX_RUBBER_FILES ARRAY_SIZE(RubberFiles) //(5) @@ -36,16 +40,16 @@ #define MAX_RAINSPLASHUP_FILES ARRAY_SIZE(RainSplashupFiles) //(4) #define MAX_BIRDFRONT_FILES ARRAY_SIZE(BirdfrontFiles) +//(8) +#define MAX_BOAT_FILES ARRAY_SIZE(BoatFiles) //(4) #define MAX_CARDEBRIS_FILES ARRAY_SIZE(CardebrisFiles) //(4) #define MAX_CARSPLASH_FILES ARRAY_SIZE(CarsplashFiles) -//(4) -#define MAX_RAINDROP_FILES ARRAY_SIZE(RaindropFiles) - - +#define MAX_RAINDRIP_FILES (2) + const char SmokeFiles[][6+1] = { "smoke1", @@ -56,15 +60,6 @@ const char SmokeFiles[][6+1] = }; -const char Smoke2Files[][9+1] = -{ - "smokeII_1", - "smokeII_2", - "smokeII_3", - "smokeII_4", - "smokeII_5" -}; - const char RubberFiles[][7+1] = { "rubber1", @@ -108,14 +103,6 @@ const char GunFlashFiles[][9+1] = "gunflash4" }; -const char RaindropFiles[][9+1] = -{ - "raindrop1", - "raindrop2", - "raindrop3", - "raindrop4" -}; - const char RainSplashupFiles[][10+1] = { "splash_up1", @@ -130,6 +117,18 @@ const char BirdfrontFiles[][8+1] = "birdf_04" }; +const char BoatFiles[][8+1] = +{ + "boats_01", + "boats_02", + "boats_03", + "boats_04", + "boats_05", + "boats_06", + "boats_07", + "boats_08" +}; + const char CardebrisFiles[][12+1] = { "cardebris_01", @@ -149,7 +148,7 @@ const char CarsplashFiles[][12+1] = CParticle gParticleArray[MAX_PARTICLES_ON_SCREEN]; RwTexture *gpSmokeTex[MAX_SMOKE_FILES]; -RwTexture *gpSmoke2Tex[MAX_SMOKE2_FILES]; +RwTexture *gpSmoke2Tex; RwTexture *gpRubberTex[MAX_RUBBER_FILES]; RwTexture *gpRainSplashTex[MAX_RAINSPLASH_FILES]; RwTexture *gpWatersprayTex[MAX_WATERSPRAY_FILES]; @@ -157,26 +156,27 @@ RwTexture *gpExplosionMediumTex[MAX_EXPLOSIONMEDIUM_FILES]; RwTexture *gpGunFlashTex[MAX_GUNFLASH_FILES]; RwTexture *gpRainSplashupTex[MAX_RAINSPLASHUP_FILES]; RwTexture *gpBirdfrontTex[MAX_BIRDFRONT_FILES]; +RwTexture *gpBoatTex[MAX_BOAT_FILES]; RwTexture *gpCarDebrisTex[MAX_CARDEBRIS_FILES]; RwTexture *gpCarSplashTex[MAX_CARSPLASH_FILES]; +RwTexture *gpBoatWakeTex; RwTexture *gpFlame1Tex; RwTexture *gpFlame5Tex; RwTexture *gpRainDropSmallTex; RwTexture *gpBloodTex; RwTexture *gpLeafTex; -RwTexture *gpCloudTex1; // unused +RwTexture *gpCloudTex1; RwTexture *gpCloudTex4; RwTexture *gpBloodSmallTex; RwTexture *gpGungeTex; RwTexture *gpCollisionSmokeTex; RwTexture *gpBulletHitTex; RwTexture *gpGunShellTex; -RwTexture *gpWakeOldTex; RwTexture *gpPointlightTex; RwRaster *gpSmokeRaster[MAX_SMOKE_FILES]; -RwRaster *gpSmoke2Raster[MAX_SMOKE2_FILES]; +RwRaster *gpSmoke2Raster; RwRaster *gpRubberRaster[MAX_RUBBER_FILES]; RwRaster *gpRainSplashRaster[MAX_RAINSPLASH_FILES]; RwRaster *gpWatersprayRaster[MAX_WATERSPRAY_FILES]; @@ -184,45 +184,62 @@ RwRaster *gpExplosionMediumRaster[MAX_EXPLOSIONMEDIUM_FILES]; RwRaster *gpGunFlashRaster[MAX_GUNFLASH_FILES]; RwRaster *gpRainSplashupRaster[MAX_RAINSPLASHUP_FILES]; RwRaster *gpBirdfrontRaster[MAX_BIRDFRONT_FILES]; +RwRaster *gpBoatRaster[MAX_BOAT_FILES]; RwRaster *gpCarDebrisRaster[MAX_CARDEBRIS_FILES]; RwRaster *gpCarSplashRaster[MAX_CARSPLASH_FILES]; +RwRaster *gpBoatWakeRaster; RwRaster *gpFlame1Raster; RwRaster *gpFlame5Raster; RwRaster *gpRainDropSmallRaster; RwRaster *gpBloodRaster; RwRaster *gpLeafRaster; -RwRaster *gpCloudRaster1; // unused +RwRaster *gpCloudRaster1; RwRaster *gpCloudRaster4; RwRaster *gpBloodSmallRaster; RwRaster *gpGungeRaster; RwRaster *gpCollisionSmokeRaster; RwRaster *gpBulletHitRaster; RwRaster *gpGunShellRaster; -RwRaster *gpWakeOldRaster; - - -RwRaster *gpPointlightRaster; // CPointLights::RenderFogEffect - -RwTexture *gpRainDropTex[MAX_RAINDROP_FILES]; // CWeather::RenderRainStreaks - - -RwRaster *gpRainDropRaster[MAX_RAINDROP_FILES]; +RwRaster *gpPointlightRaster; + +RwTexture *gpRainDropTex; +RwRaster *gpRainDropRaster; + +RwTexture *gpLetterTex; +RwRaster *gpLetterRaster; + +RwTexture *gpSparkTex; +RwTexture *gpNewspaperTex; +RwTexture *gpGunSmokeTex; +RwTexture *gpDotTex; +RwTexture *gpHeathazeTex; +RwTexture *gpBeastieTex; +RwTexture *gpRaindripTex1[MAX_RAINDRIP_FILES]; +RwTexture *gpRaindripTex2[MAX_RAINDRIP_FILES]; + +RwRaster *gpSparkRaster; +RwRaster *gpNewspaperRaster; +RwRaster *gpGunSmokeRaster; +RwRaster *gpDotRaster; +RwRaster *gpHeathazeRaster; +RwRaster *gpBeastieRaster; +RwRaster *gpRaindripRaster1[MAX_RAINDRIP_FILES]; +RwRaster *gpRaindripRaster2[MAX_RAINDRIP_FILES]; float CParticle::ms_afRandTable[CParticle::RAND_TABLE_SIZE]; - - CParticle *CParticle::m_pUnusedListHead; - - float CParticle::m_SinTable[CParticle::SIN_COS_TABLE_SIZE]; float CParticle::m_CosTable[CParticle::SIN_COS_TABLE_SIZE]; int32 Randomizer; - int32 nParticleCreationInterval = 1; +float PARTICLE_WIND_TEST_SCALE = 0.002f; float fParticleScaleLimit = 0.5f; +bool clearWaterDrop; +int32 numWaterDropOnScreen; + #ifdef DEBUGMENU SETTWEAKPATH("Particle"); TWEAKINT32(nParticleCreationInterval, 0, 5, 1); @@ -230,6 +247,8 @@ TWEAKFLOAT(fParticleScaleLimit, 0.0f, 1.0f, 0.1f); TWEAKFUNC(CParticle::ReloadConfig); #endif + + void CParticle::ReloadConfig() { debug("Initialising CParticleMgr..."); @@ -302,8 +321,8 @@ void CParticle::Initialise() { float angle = DEGTORAD(float(i) * float(360.0f / SIN_COS_TABLE_SIZE)); - m_SinTable[i] = Sin(angle); - m_CosTable[i] = Cos(angle); + m_SinTable[i] = ::Sin(angle); + m_CosTable[i] = ::Cos(angle); } int32 slot = CTxdStore::FindTxdSlot("particle"); @@ -317,11 +336,8 @@ void CParticle::Initialise() gpSmokeRaster[i] = RwTextureGetRaster(gpSmokeTex[i]); } - for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ ) - { - gpSmoke2Tex[i] = RwTextureRead(Smoke2Files[i], nil); - gpSmoke2Raster[i] = RwTextureGetRaster(gpSmoke2Tex[i]); - } + gpSmoke2Tex = RwTextureRead("smokeII_3", nil); + gpSmoke2Raster = RwTextureGetRaster(gpSmoke2Tex); for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ ) { @@ -349,15 +365,13 @@ void CParticle::Initialise() for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ ) { - gpGunFlashTex[i] = RwTextureRead(GunFlashFiles[i], NULL); + gpGunFlashTex[i] = RwTextureRead(GunFlashFiles[i], nil); gpGunFlashRaster[i] = RwTextureGetRaster(gpGunFlashTex[i]); } - for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ ) - { - gpRainDropTex[i] = RwTextureRead(RaindropFiles[i], nil); - gpRainDropRaster[i] = RwTextureGetRaster(gpRainDropTex[i]); - } + gpRainDropTex = RwTextureRead("raindrop4", nil); + gpRainDropRaster = RwTextureGetRaster(gpRainDropTex); + for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ ) { @@ -367,10 +381,16 @@ void CParticle::Initialise() for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ ) { - gpBirdfrontTex[i] = RwTextureRead(BirdfrontFiles[i], NULL); + gpBirdfrontTex[i] = RwTextureRead(BirdfrontFiles[i], nil); gpBirdfrontRaster[i] = RwTextureGetRaster(gpBirdfrontTex[i]); } + for ( int32 i = 0; i < MAX_BOAT_FILES; i++ ) + { + gpBoatTex[i] = RwTextureRead(BoatFiles[i], nil); + gpBoatRaster[i] = RwTextureGetRaster(gpBoatTex[i]); + } + for ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ ) { gpCarDebrisTex[i] = RwTextureRead(CardebrisFiles[i], nil); @@ -383,7 +403,10 @@ void CParticle::Initialise() gpCarSplashRaster[i] = RwTextureGetRaster(gpCarSplashTex[i]); } - gpFlame1Tex = RwTextureRead("flame1", NULL); + gpBoatWakeTex = RwTextureRead("boatwake2", nil); + gpBoatWakeRaster = RwTextureGetRaster(gpBoatWakeTex); + + gpFlame1Tex = RwTextureRead("flame1", nil); gpFlame1Raster = RwTextureGetRaster(gpFlame1Tex); gpFlame5Tex = RwTextureRead("flame5", nil); @@ -402,6 +425,9 @@ void CParticle::Initialise() gpLeafTex = RwTextureRead("gameleaf01_64", nil); gpLeafRaster = RwTextureGetRaster(gpLeafTex); + + gpLetterTex = RwTextureRead("letter", nil); + gpLetterRaster = RwTextureGetRaster(gpLetterTex); gpCloudTex1 = RwTextureRead("cloud3", nil); gpCloudRaster1 = RwTextureGetRaster(gpCloudTex1); @@ -424,12 +450,39 @@ void CParticle::Initialise() gpGunShellTex = RwTextureRead("gunshell", nil); gpGunShellRaster = RwTextureGetRaster(gpGunShellTex); - gpWakeOldTex = RwTextureRead("wake_old", nil); - gpWakeOldRaster = RwTextureGetRaster(gpWakeOldTex); - gpPointlightTex = RwTextureRead("pointlight", nil); gpPointlightRaster = RwTextureGetRaster(gpPointlightTex); + gpSparkTex = RwTextureRead("spark", nil); + gpSparkRaster = RwTextureGetRaster(gpSparkTex); + + gpNewspaperTex = RwTextureRead("newspaper02_64", nil); + gpNewspaperRaster = RwTextureGetRaster(gpNewspaperTex); + + gpGunSmokeTex = RwTextureRead("gunsmoke3", nil); + gpGunSmokeRaster = RwTextureGetRaster(gpGunSmokeTex); + + gpDotTex = RwTextureRead("dot", nil); + gpDotRaster = RwTextureGetRaster(gpDotTex); + + gpHeathazeTex = RwTextureRead("heathaze", nil); + gpHeathazeRaster = RwTextureGetRaster(gpHeathazeTex); + + gpBeastieTex = RwTextureRead("beastie", nil); + gpBeastieRaster = RwTextureGetRaster(gpBeastieTex); + + gpRaindripTex1[0] = RwTextureRead("raindrip64", nil); + gpRaindripRaster1[0] = RwTextureGetRaster(gpRaindripTex1[0]); + + gpRaindripTex1[1] = RwTextureRead("raindripb64", nil); + gpRaindripRaster1[1] = RwTextureGetRaster(gpRaindripTex1[1]); + + gpRaindripTex2[0] = RwTextureRead("raindrip64_d", nil); + gpRaindripRaster2[0] = RwTextureGetRaster(gpRaindripTex2[0]); + + gpRaindripTex2[1] = RwTextureRead("raindripb64_d", nil); + gpRaindripRaster2[1] = RwTextureGetRaster(gpRaindripTex2[1]); + CTxdStore::PopCurrentTxd(); for ( int32 i = 0; i < MAX_PARTICLES; i++ ) @@ -438,145 +491,180 @@ void CParticle::Initialise() switch ( i ) { + case PARTICLE_SPARK: + case PARTICLE_SPARK_SMALL: + case PARTICLE_RAINDROP_SMALL: + case PARTICLE_HELI_ATTACK: + entry->m_ppRaster = &gpRainDropSmallRaster; + break; + + case PARTICLE_WATER_SPARK: + entry->m_ppRaster = &gpSparkRaster; + break; + + case PARTICLE_WHEEL_DIRT: + case PARTICLE_SAND: + case PARTICLE_STEAM2: + case PARTICLE_STEAM_NY: + case PARTICLE_STEAM_NY_SLOWMOTION: + case PARTICLE_GROUND_STEAM: + case PARTICLE_ENGINE_STEAM: + case PARTICLE_PEDFOOT_DUST: + case PARTICLE_CAR_DUST: + case PARTICLE_EXHAUST_FUMES: + entry->m_ppRaster = &gpSmoke2Raster; + break; + + case PARTICLE_WHEEL_WATER: + case PARTICLE_WATER: + case PARTICLE_SMOKE: + case PARTICLE_SMOKE_SLOWMOTION: + case PARTICLE_DRY_ICE: + case PARTICLE_GARAGEPAINT_SPRAY: + case PARTICLE_STEAM: + case PARTICLE_WATER_CANNON: + case PARTICLE_EXTINGUISH_STEAM: + case PARTICLE_HELI_DUST: + case PARTICLE_PAINT_SMOKE: + case PARTICLE_BULLETHIT_SMOKE: + entry->m_ppRaster = gpSmokeRaster; + break; + case PARTICLE_BLOOD: entry->m_ppRaster = &gpBloodRaster; break; - + case PARTICLE_BLOOD_SMALL: case PARTICLE_BLOOD_SPURT: entry->m_ppRaster = &gpBloodSmallRaster; break; - + + case PARTICLE_DEBRIS: + case PARTICLE_TREE_LEAVES: + entry->m_ppRaster = &gpLeafRaster; + break; + case PARTICLE_DEBRIS2: entry->m_ppRaster = &gpGungeRaster; break; - + + case PARTICLE_FLYERS: + entry->m_ppRaster = &gpNewspaperRaster; + break; + + case PARTICLE_FLAME: + case PARTICLE_CARFLAME: + entry->m_ppRaster = &gpFlame1Raster; + break; + + case PARTICLE_FIREBALL: + entry->m_ppRaster = &gpFlame5Raster; + break; + case PARTICLE_GUNFLASH: case PARTICLE_GUNFLASH_NOANIM: entry->m_ppRaster = gpGunFlashRaster; break; - + + case PARTICLE_GUNSMOKE: - case PARTICLE_SPLASH: + case PARTICLE_WATERDROP: + case PARTICLE_BLOODDROP: + case PARTICLE_HEATHAZE: + case PARTICLE_HEATHAZE_IN_DIST: entry->m_ppRaster = nil; break; - - case PARTICLE_FLAME: - case PARTICLE_CARFLAME: - entry->m_ppRaster = &gpFlame1Raster; + + case PARTICLE_GUNSMOKE2: + case PARTICLE_BOAT_THRUSTJET: + case PARTICLE_RUBBER_SMOKE: + entry->m_ppRaster = gpRubberRaster; break; - - case PARTICLE_FIREBALL: - entry->m_ppRaster = &gpFlame5Raster; + + case PARTICLE_CIGARETTE_SMOKE: + entry->m_ppRaster = &gpGunSmokeRaster; break; - + + case PARTICLE_TEARGAS: + entry->m_ppRaster = &gpHeathazeRaster; + break; + + case PARTICLE_SHARD: + case PARTICLE_RAINDROP: + case PARTICLE_RAINDROP_2D: + entry->m_ppRaster = &gpRainDropRaster; + break; + + case PARTICLE_SPLASH: + case PARTICLE_PED_SPLASH: + case PARTICLE_CAR_SPLASH: + case PARTICLE_WATER_HYDRANT: + entry->m_ppRaster = gpCarSplashRaster; + break; + case PARTICLE_RAIN_SPLASH: case PARTICLE_RAIN_SPLASH_BIGGROW: entry->m_ppRaster = gpRainSplashRaster; break; - + case PARTICLE_RAIN_SPLASHUP: entry->m_ppRaster = gpRainSplashupRaster; break; - + case PARTICLE_WATERSPRAY: entry->m_ppRaster = gpWatersprayRaster; break; - - case PARTICLE_SHARD: - case PARTICLE_RAINDROP: - case PARTICLE_RAINDROP_2D: - entry->m_ppRaster = gpRainDropRaster; - break; - + case PARTICLE_EXPLOSION_MEDIUM: case PARTICLE_EXPLOSION_LARGE: case PARTICLE_EXPLOSION_MFAST: case PARTICLE_EXPLOSION_LFAST: entry->m_ppRaster = gpExplosionMediumRaster; break; - - case PARTICLE_BOAT_WAKE: - entry->m_ppRaster = &gpWakeOldRaster; - break; - - case PARTICLE_CAR_SPLASH: - case PARTICLE_WATER_HYDRANT: - case PARTICLE_PED_SPLASH: - entry->m_ppRaster = gpCarSplashRaster; - break; - - case PARTICLE_SPARK: - case PARTICLE_SPARK_SMALL: - case PARTICLE_RAINDROP_SMALL: - case PARTICLE_HELI_ATTACK: - entry->m_ppRaster = &gpRainDropSmallRaster; - break; - - case PARTICLE_DEBRIS: - case PARTICLE_TREE_LEAVES: - entry->m_ppRaster = &gpLeafRaster; - break; - - case PARTICLE_CAR_DEBRIS: - case PARTICLE_HELI_DEBRIS: - entry->m_ppRaster = gpCarDebrisRaster; - break; - - case PARTICLE_WHEEL_DIRT: - case PARTICLE_STEAM2: - case PARTICLE_STEAM_NY: - case PARTICLE_STEAM_NY_SLOWMOTION: - case PARTICLE_ENGINE_STEAM: - case PARTICLE_BOAT_THRUSTJET: - case PARTICLE_PEDFOOT_DUST: - case PARTICLE_EXHAUST_FUMES: - entry->m_ppRaster = gpSmoke2Raster; + + case PARTICLE_BOAT_SPLASH: + entry->m_ppRaster = &gpBoatWakeRaster; break; - - case PARTICLE_GUNSMOKE2: - case PARTICLE_RUBBER_SMOKE: - entry->m_ppRaster = gpRubberRaster; + + case PARTICLE_ENGINE_SMOKE: + case PARTICLE_ENGINE_SMOKE2: + case PARTICLE_CARFLAME_SMOKE: + case PARTICLE_FIREBALL_SMOKE: + case PARTICLE_ROCKET_SMOKE: + case PARTICLE_TEST: + entry->m_ppRaster = &gpCloudRaster4; break; - + case PARTICLE_CARCOLLISION_DUST: case PARTICLE_BURNINGRUBBER_SMOKE: entry->m_ppRaster = &gpCollisionSmokeRaster; break; - - case PARTICLE_WHEEL_WATER: - case PARTICLE_WATER: - case PARTICLE_SMOKE: - case PARTICLE_SMOKE_SLOWMOTION: - case PARTICLE_GARAGEPAINT_SPRAY: - case PARTICLE_STEAM: - case PARTICLE_BOAT_SPLASH: - case PARTICLE_WATER_CANNON: - case PARTICLE_EXTINGUISH_STEAM: - case PARTICLE_HELI_DUST: - case PARTICLE_PAINT_SMOKE: - case PARTICLE_BULLETHIT_SMOKE: - entry->m_ppRaster = gpSmokeRaster; + + case PARTICLE_CAR_DEBRIS: + case PARTICLE_HELI_DEBRIS: + case PARTICLE_BIRD_DEBRIS: + entry->m_ppRaster = gpCarDebrisRaster; break; - + case PARTICLE_GUNSHELL_FIRST: case PARTICLE_GUNSHELL: case PARTICLE_GUNSHELL_BUMP1: case PARTICLE_GUNSHELL_BUMP2: entry->m_ppRaster = &gpGunShellRaster; break; - - case PARTICLE_ENGINE_SMOKE: - case PARTICLE_ENGINE_SMOKE2: - case PARTICLE_CARFLAME_SMOKE: - case PARTICLE_FIREBALL_SMOKE: - case PARTICLE_TEST: - entry->m_ppRaster = &gpCloudRaster4; - break; - + + case PARTICLE_BIRD_FRONT: entry->m_ppRaster = gpBirdfrontRaster; break; + + case PARTICLE_SHIP_SIDE: + entry->m_ppRaster = gpBoatRaster; + break; + + case PARTICLE_BEASTIE: + entry->m_ppRaster = &gpBeastieRaster; + break; } } @@ -590,168 +678,145 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_SMOKE_FILES; i++ ) { RwTextureDestroy(gpSmokeTex[i]); -#ifdef GTA3_1_1_PATCH gpSmokeTex[i] = nil; -#endif } - for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ ) - { - RwTextureDestroy(gpSmoke2Tex[i]); -#ifdef GTA3_1_1_PATCH - gpSmoke2Tex[i] = nil; -#endif - } + RwTextureDestroy(gpSmoke2Tex); + gpSmoke2Tex = nil; for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ ) { RwTextureDestroy(gpRubberTex[i]); -#ifdef GTA3_1_1_PATCH gpRubberTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ ) { RwTextureDestroy(gpRainSplashTex[i]); -#ifdef GTA3_1_1_PATCH gpRainSplashTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ ) { RwTextureDestroy(gpWatersprayTex[i]); -#ifdef GTA3_1_1_PATCH gpWatersprayTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ ) { RwTextureDestroy(gpExplosionMediumTex[i]); -#ifdef GTA3_1_1_PATCH gpExplosionMediumTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ ) { RwTextureDestroy(gpGunFlashTex[i]); -#ifdef GTA3_1_1_PATCH gpGunFlashTex[i] = nil; -#endif } - for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ ) - { - RwTextureDestroy(gpRainDropTex[i]); -#ifdef GTA3_1_1_PATCH - gpRainDropTex[i] = nil; -#endif - } + RwTextureDestroy(gpRainDropTex); + gpRainDropTex = nil; for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ ) { RwTextureDestroy(gpRainSplashupTex[i]); -#ifdef GTA3_1_1_PATCH gpRainSplashupTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ ) { RwTextureDestroy(gpBirdfrontTex[i]); -#ifdef GTA3_1_1_PATCH gpBirdfrontTex[i] = nil; -#endif + } + + for ( int32 i = 0; i < MAX_BOAT_FILES; i++ ) + { + RwTextureDestroy(gpBoatTex[i]); + gpBoatTex[i] = nil; } for ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ ) { RwTextureDestroy(gpCarDebrisTex[i]); -#ifdef GTA3_1_1_PATCH gpCarDebrisTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ ) { RwTextureDestroy(gpCarSplashTex[i]); -#ifdef GTA3_1_1_PATCH gpCarSplashTex[i] = nil; -#endif } + for ( int32 i = 0; i < MAX_RAINDRIP_FILES; i++ ) + { + RwTextureDestroy(gpRaindripTex1[i]); + gpRaindripTex1[i] = nil; + + RwTextureDestroy(gpRaindripTex2[i]); + gpRaindripTex2[i] = nil; + } + + RwTextureDestroy(gpBoatWakeTex); + gpBoatWakeTex = nil; + RwTextureDestroy(gpFlame1Tex); -#ifdef GTA3_1_1_PATCH gpFlame1Tex = nil; -#endif RwTextureDestroy(gpFlame5Tex); -#ifdef GTA3_1_1_PATCH gpFlame5Tex = nil; -#endif RwTextureDestroy(gpRainDropSmallTex); -#ifdef GTA3_1_1_PATCH gpRainDropSmallTex = nil; -#endif RwTextureDestroy(gpBloodTex); -#ifdef GTA3_1_1_PATCH gpBloodTex = nil; -#endif RwTextureDestroy(gpLeafTex); -#ifdef GTA3_1_1_PATCH gpLeafTex = nil; -#endif + + RwTextureDestroy(gpLetterTex); + gpLetterTex = nil; RwTextureDestroy(gpCloudTex1); -#ifdef GTA3_1_1_PATCH gpCloudTex1 = nil; -#endif RwTextureDestroy(gpCloudTex4); -#ifdef GTA3_1_1_PATCH gpCloudTex4 = nil; -#endif RwTextureDestroy(gpBloodSmallTex); -#ifdef GTA3_1_1_PATCH gpBloodSmallTex = nil; -#endif RwTextureDestroy(gpGungeTex); -#ifdef GTA3_1_1_PATCH gpGungeTex = nil; -#endif RwTextureDestroy(gpCollisionSmokeTex); -#ifdef GTA3_1_1_PATCH gpCollisionSmokeTex = nil; -#endif RwTextureDestroy(gpBulletHitTex); -#ifdef GTA3_1_1_PATCH gpBulletHitTex = nil; -#endif RwTextureDestroy(gpGunShellTex); -#ifdef GTA3_1_1_PATCH gpGunShellTex = nil; -#endif - - RwTextureDestroy(gpWakeOldTex); -#ifdef GTA3_1_1_PATCH - gpWakeOldTex = nil; -#endif RwTextureDestroy(gpPointlightTex); -#ifdef GTA3_1_1_PATCH gpPointlightTex = nil; -#endif + + RwTextureDestroy(gpSparkTex); + gpSparkTex = nil; + + RwTextureDestroy(gpNewspaperTex); + gpNewspaperTex = nil; + + RwTextureDestroy(gpGunSmokeTex); + gpGunSmokeTex = nil; + + RwTextureDestroy(gpDotTex); + gpDotTex = nil; + RwTextureDestroy(gpHeathazeTex); + gpHeathazeTex = nil; + + RwTextureDestroy(gpBeastieTex); + gpBeastieTex = nil; int32 slot; @@ -761,6 +826,40 @@ void CParticle::Shutdown() debug("CParticle shut down"); } + +void CParticle::AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan) +{ + CVector vecDist = vecEnd - vecStart; + float fDist = vecDist.Magnitude(); + float fSteps = Max(fDist / fPower, 1.0f); + int32 nSteps = (int32)fSteps; + + CVector vecStep = vecDist * (1.0f / (float)nSteps); + + for ( int32 i = 0; i < nSteps; i++ ) + { + CVector vecPos = float(i) * vecStep + vecStart; + AddParticle(type, vecPos, vecDir, pEntity, fSize, nRotationSpeed, nRotation, nCurFrame, nLifeSpan); + } +} + +void CParticle::AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan) +{ + CVector vecDist = vecEnd - vecStart; + float fDist = vecDist.Magnitude(); + float fSteps = Max(fDist / fPower, 1.0f); + int32 nSteps = (int32)fSteps; + + CVector vecStep = vecDist * (1.0f / (float)nSteps); + + for ( int32 i = 0; i < nSteps; i++ ) + { + CVector vecPos = float(i) * vecStep + vecStart; + + AddParticle(type, vecPos, vecDir, pEntity, fSize, color, nRotationSpeed, nRotation, nCurFrame, nLifeSpan); + } +} + CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan) { CRGBA color(0, 0, 0, 0); @@ -770,9 +869,8 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan) { if ( CTimer::GetIsPaused() ) - return NULL; + return nil; -#ifdef PC_PARTICLE if ( ( type == PARTICLE_ENGINE_SMOKE || type == PARTICLE_ENGINE_SMOKE2 || type == PARTICLE_ENGINE_STEAM @@ -785,8 +883,10 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe { return nil; } -#endif + if ( !CReplay::IsPlayingBack() ) + CReplay::RecordParticle(type, vecPos, vecDir, fSize, color); + CParticle *pParticle = m_pUnusedListHead; if ( pParticle == nil ) @@ -807,7 +907,19 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe pParticle->m_nTimeWhenWillBeDestroyed = CTimer::GetTimeInMilliseconds() + psystem->m_nLifeSpan; pParticle->m_nColorIntensity = psystem->m_nFadeToBlackInitialIntensity; + + pParticle->m_nFadeToBlackTimer = psystem->m_nFadeToBlackAmount; + + if ( psystem->m_nFadeToBlackTime ) + pParticle->m_nFadeToBlackTimer /= psystem->m_nFadeToBlackTime; + pParticle->m_nAlpha = psystem->m_nFadeAlphaInitialIntensity; + + pParticle->m_nFadeAlphaTimer = psystem->m_nFadeAlphaAmount; + + if ( psystem->m_nFadeAlphaTime ) + pParticle->m_nFadeAlphaTimer /= psystem->m_nFadeAlphaTime; + pParticle->m_nCurrentZRotation = psystem->m_nZRotationInitialAngle; pParticle->m_fCurrentZRadius = psystem->m_fInitialZRadius; @@ -816,14 +928,29 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe else pParticle->m_nCurrentFrame = psystem->m_nStartAnimationFrame; - pParticle->m_nFadeToBlackTimer = 0; - pParticle->m_nFadeAlphaTimer = 0; + pParticle->m_nZRotationTimer = 0; pParticle->m_nZRadiusTimer = 0; pParticle->m_nAnimationSpeedTimer = 0; pParticle->m_fZGround = 0.0f; - pParticle->m_vecPosition = vecPos; + + if ( type != PARTICLE_HEATHAZE ) + pParticle->m_vecPosition = vecPos; + else + { + CVector screen; + float w, h; + + if ( !CSprite::CalcScreenCoors(vecPos, screen, &w, &h, true) ) + return nil; + + pParticle->m_vecPosition = screen; + psystem->m_vecTextureStretch.x = w; + psystem->m_vecTextureStretch.y = h; + } + pParticle->m_vecVelocity = vecDir; + pParticle->m_vecParticleMovementOffset = CVector(0.0f, 0.0f, 0.0f); pParticle->m_nTimeWhenColorWillBeChanged = 0; @@ -831,7 +958,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe RwRGBAAssign(&pParticle->m_Color, &color); else { - RwRGBAAssign(&pParticle->m_Color, &psystem->m_RenderColouring); + RwRGBAAssign(&pParticle->m_Color, psystem->m_RenderColouring); if ( psystem->m_ColorFadeTime != 0 ) pParticle->m_nTimeWhenColorWillBeChanged = CTimer::GetTimeInMilliseconds() + psystem->m_ColorFadeTime; @@ -839,7 +966,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe if ( psystem->m_InitialColorVariation != 0 ) { int32 ColorVariation = CGeneral::GetRandomNumberInRange(-psystem->m_InitialColorVariation, psystem->m_InitialColorVariation); - //Float ColorVariation = CGeneral::GetRandomNumberInRange((float)-psystem->m_InitialColorVariation, (float)psystem->m_InitialColorVariation); + //float ColorVariation = CGeneral::GetRandomNumberInRange((float)-psystem->m_InitialColorVariation, (float)psystem->m_InitialColorVariation); pParticle->m_Color.red = clamp(pParticle->m_Color.red + PERCENT(pParticle->m_Color.red, ColorVariation), @@ -856,13 +983,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe } pParticle->m_nRotation = nRotation; - -// PC only - if ( pParticle->m_nRotation >= 360 ) - pParticle->m_nRotation -= 360; - else if ( pParticle->m_nRotation < 0 ) - pParticle->m_nRotation += 360; - + if ( nRotationSpeed != 0 ) pParticle->m_nRotationStep = nRotationSpeed; else @@ -871,8 +992,6 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe if ( CGeneral::GetRandomNumber() & 1 ) pParticle->m_nRotationStep = -pParticle->m_nRotationStep; - pParticle->m_vecScreenPosition.x = 0.0f; // bug ? - if ( psystem->m_fPositionRandomError != 0.0f ) { pParticle->m_vecPosition.x += psystem->m_fPositionRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE]; @@ -891,7 +1010,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe pParticle->m_vecVelocity.z += psystem->m_fVelocityRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE]; } - if ( psystem->m_fExpansionRateError != 0.0f ) + if ( psystem->m_fExpansionRateError != 0.0f && !(psystem->Flags & SCREEN_TRAIL) ) pParticle->m_fExpansionRate += psystem->m_fExpansionRateError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE] + psystem->m_fExpansionRateError; if ( psystem->m_nRotationRateError != 0 ) @@ -1015,6 +1134,25 @@ void CParticle::Update() float fFricDeccel99 = pow(0.99f, CTimer::GetTimeStep()); CParticleObject::UpdateAll(); + + // ejaculation at 23:00, 23:15, 23:30, 23:45 + if ( CClock::ms_nGameClockHours == 23 && + ( CClock::ms_nGameClockMinutes == 0 + || CClock::ms_nGameClockMinutes == 15 + || CClock::ms_nGameClockMinutes == 30 + || CClock::ms_nGameClockMinutes == 45 ) ) + { + AddParticle(PARTICLE_CAR_SPLASH, + CVector(557.03f, -4.0f, 151.46f), + CVector(0.0f, 0.0f, 2.5f), + NULL, + 2.0f, + CRGBA(255, 255, 255, 255), + 0, + 0, + 1, + 1000); + } for ( int32 i = 0; i < MAX_PARTICLES; i++ ) { @@ -1028,9 +1166,209 @@ void CParticle::Update() for ( ; particle != nil; _Next(particle, prevParticle, psystem, bRemoveParticle) ) { + CVector vecWind(0.0f, 0.0f, 0.0f); + bRemoveParticle = false; - CVector moveStep = particle->m_vecPosition + ( particle->m_vecVelocity * CTimer::GetTimeStep() ); + CVector vecMoveStep = particle->m_vecVelocity * CTimer::GetTimeStep(); + CVector vecPos = particle->m_vecPosition; + + if ( numWaterDropOnScreen == 0 ) + clearWaterDrop = false; + + if ( psystem->m_Type == PARTICLE_WATERDROP ) + { + if ( CGame::IsInInterior() || clearWaterDrop == true ) + { + bRemoveParticle = true; + continue; + } + + static uint8 nWaterDropCount; + + if ( nWaterDropCount == 5 ) + { + vecMoveStep = CVector(0.0f, 0.0f, 0.0f); + particle->m_nTimeWhenWillBeDestroyed += 1250; + nWaterDropCount = 0; + } + else + { + if ( TheCamera.m_CameraAverageSpeed > 0.35f ) + { + if ( vecMoveStep.Magnitude() > 0.5f ) + { + if ( vecMoveStep.Magnitude() > 0.4f && vecMoveStep.Magnitude() < 0.8f ) + { + vecMoveStep.x += TheCamera.m_CameraAverageSpeed * 1.5f; + vecMoveStep.y += TheCamera.m_CameraAverageSpeed * 1.5f; + } + else if ( vecMoveStep.Magnitude() != 0.0f ) + { + vecMoveStep.x += CGeneral::GetRandomNumberInRange(0.01f, 0.05f); + vecMoveStep.y += CGeneral::GetRandomNumberInRange(0.01f, 0.05f); + } + } + } + + nWaterDropCount++; + } + + if ( vecPos.z <= 1.5f ) + vecMoveStep.z = 0.0f; + } + + if ( psystem->m_Type == PARTICLE_HEATHAZE || psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST ) + { +#ifdef FIX_BUGS + int32 nSinCosIndex = (int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) + SIN_COS_TABLE_SIZE) % SIN_COS_TABLE_SIZE; +#else + int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE; +#endif + vecMoveStep.x = Sin(nSinCosIndex); + vecMoveStep.y = Sin(nSinCosIndex); + + if ( psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST ) + particle->m_nRotation = int16((float)particle->m_nRotation + 0.75f); + else + particle->m_nRotation = int16((float)particle->m_nRotation + 1.0f); + } + + if ( psystem->m_Type == PARTICLE_BEASTIE ) + { +#ifdef FIX_BUGS + int32 nSinCosIndex = (int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) + SIN_COS_TABLE_SIZE) % SIN_COS_TABLE_SIZE; +#else + int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE; +#endif + particle->m_vecVelocity.x = 0.50f * Cos(nSinCosIndex); + particle->m_vecVelocity.y = Cos(nSinCosIndex); + particle->m_vecVelocity.z = 0.25f * Sin(nSinCosIndex); + + if ( particle->m_vecVelocity.Magnitude() > 2.0f + || vecPos.z > 40.0f + || (TheCamera.GetPosition() - vecPos).Magnitude() < 60.0f + ) + { + bRemoveParticle = true; + continue; + } + } + + vecPos += vecMoveStep; + + if ( psystem->m_Type == PARTICLE_FIREBALL ) + { + AddParticle(PARTICLE_HEATHAZE, particle->m_vecPosition, CVector(0.0f, 0.0f, 0.0f), + nil, particle->m_fSize * 5.0f); + } + + if ( psystem->m_Type == PARTICLE_GUNSMOKE2 ) + { + if ( CTimer::GetFrameCounter() & 10 ) + { +#ifdef FIX_BUGS + if ( FindPlayerPed() && FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN ) +#else + if ( FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN ) +#endif + { + AddParticle(PARTICLE_HEATHAZE, particle->m_vecPosition, CVector(0.0f, 0.0f, 0.0f)); + } + } + } + + if ( CWeather::Wind > 0.0f ) + { + if ( vecMoveStep.Magnitude() != 0.0f ) + { + vecWind.x = CGeneral::GetRandomNumberInRange(0.75f, 1.25f) * -CWeather::Wind; + vecWind.y = CGeneral::GetRandomNumberInRange(0.75f, 1.25f) * -CWeather::Wind; + vecWind *= PARTICLE_WIND_TEST_SCALE * psystem->m_fWindFactor * CTimer::GetTimeStep(); + particle->m_vecVelocity += vecWind; + } + } + + if ( psystem->m_Type == PARTICLE_RAINDROP + || psystem->m_Type == PARTICLE_RAINDROP_SMALL + || psystem->m_Type == PARTICLE_RAIN_SPLASH + || psystem->m_Type == PARTICLE_RAIN_SPLASH_BIGGROW + || psystem->m_Type == PARTICLE_CAR_SPLASH + || psystem->m_Type == PARTICLE_BOAT_SPLASH + || psystem->m_Type == PARTICLE_RAINDROP_2D ) + { + int32 nMaxDrops = int32(6.0f * TheCamera.m_CameraAverageSpeed + 1.0f); + float fDistToCam = 0.0f; + + if ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH ) + { + if ( vecPos.z + particle->m_fSize < 5.0f ) + { + bRemoveParticle = true; + continue; + } + + switch ( TheCamera.GetLookDirection() ) + { + case LOOKING_LEFT: + case LOOKING_RIGHT: + case LOOKING_FORWARD: + nMaxDrops /= 2; + break; + + default: + nMaxDrops = 0; + break; + } + + fDistToCam = (TheCamera.GetPosition() - vecPos).Magnitude(); + } + + if ( numWaterDropOnScreen < nMaxDrops && numWaterDropOnScreen < 63 + && fDistToCam < 10.0f + && clearWaterDrop == false + && !CGame::IsInInterior() ) + { + CVector vecWaterdropTarget + ( + CGeneral::GetRandomNumberInRange(-0.25f, 0.25f), + CGeneral::GetRandomNumberInRange(0.1f, 0.75f), + -0.01f + ); + + CVector vecWaterdropPos; + + if ( TheCamera.m_CameraAverageSpeed < 0.35f ) + vecWaterdropPos.x = (float)CGeneral::GetRandomNumberInRange(50, int32(SCREEN_WIDTH) - 50); + else + vecWaterdropPos.x = (float)CGeneral::GetRandomNumberInRange(200, int32(SCREEN_WIDTH) - 200); + + if ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH ) + vecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT / 2, SCREEN_HEIGHT); + else + { + if ( TheCamera.m_CameraAverageSpeed < 0.35f ) + vecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(0, int32(SCREEN_HEIGHT)); + else + vecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(150, int32(SCREEN_HEIGHT) - 200); + } + + vecWaterdropPos.z = 2.0f; + + if ( AddParticle(PARTICLE_WATERDROP, + vecWaterdropPos, + vecWaterdropTarget, + nil, + CGeneral::GetRandomNumberInRange(0.1f, 0.15f), + 0, + 0, + CGeneral::GetRandomNumber() & 1, + 0) != nil ) + { + numWaterDropOnScreen++; + } + } + } if ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed || particle->m_nAlpha == 0 ) { @@ -1057,7 +1395,7 @@ void CParticle::Update() 0, 255); } else - RwRGBAAssign(&particle->m_Color, &psystem->m_FadeDestinationColor); + RwRGBAAssign(&particle->m_Color, psystem->m_FadeDestinationColor); } if ( psystem->Flags & CLIPOUT2D ) @@ -1070,16 +1408,41 @@ void CParticle::Update() } } - float size = particle->m_fSize + particle->m_fExpansionRate; - - if ( size < 0.0f ) + if ( !(psystem->Flags & SCREEN_TRAIL) ) { - bRemoveParticle = true; - continue; + float size; + + if ( particle->m_fExpansionRate > 0.0f ) + { + float speed = Max(vecWind.Magnitude(), vecMoveStep.Magnitude()); + + if ( psystem->m_Type == PARTICLE_EXHAUST_FUMES || psystem->m_Type == PARTICLE_ENGINE_STEAM ) + speed *= 2.0f; + + if ( ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH ) + && particle->m_fSize > 1.2f ) + { + size = particle->m_fSize - (1.0f + speed) * particle->m_fExpansionRate; + particle->m_vecVelocity.z -= 0.15f; + } + else + size = particle->m_fSize + (1.0f + speed) * particle->m_fExpansionRate; + } + else + size = particle->m_fSize + particle->m_fExpansionRate; + + if ( psystem->m_Type == PARTICLE_WATERDROP ) + size = (size - Abs(vecMoveStep.x) * 0.000150000007f) + (Abs(vecMoveStep.z) * 0.0500000007f); //TODO: + + if ( size < 0.0f ) + { + bRemoveParticle = true; + continue; + } + + particle->m_fSize = size; } - particle->m_fSize = size; - switch ( psystem->m_nFrictionDecceleration ) { case 50: @@ -1199,7 +1562,7 @@ void CParticle::Update() if ( randVal == 5 ) { - CShadows::AddPermanentShadow(1, gpBloodPoolTex, &vecPosn, + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &vecPosn, 0.1f, 0.0f, 0.0f, -0.1f, 255, 255, 0, 0, @@ -1207,7 +1570,7 @@ void CParticle::Update() } else if ( randVal == 2 ) { - CShadows::AddPermanentShadow(1, gpBloodPoolTex, &vecPosn, + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &vecPosn, 0.2f, 0.0f, 0.0f, -0.2f, 255, 255, 0, 0, @@ -1225,12 +1588,12 @@ void CParticle::Update() CColPoint point; CEntity *entity; - if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, moveStep.z, point, entity, + if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, vecPos.z, point, entity, true, true, false, false, true, false, nil) ) { - if ( moveStep.z <= point.point.z ) + if ( vecPos.z <= point.point.z ) { - moveStep.z = point.point.z; + vecPos.z = point.point.z; if ( psystem->m_Type == PARTICLE_DEBRIS2 ) { particle->m_vecVelocity.x *= 0.8f; @@ -1317,16 +1680,16 @@ void CParticle::Update() CColPoint point; CEntity *entity; - if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, moveStep.z, point, entity, + if ( CWorld::ProcessVerticalLine(particle->m_vecPosition, vecPos.z, point, entity, true, false, false, false, true, false, nil) ) { - if ( moveStep.z <= point.point.z ) + if ( vecPos.z <= point.point.z ) { - moveStep.z = point.point.z; + vecPos.z = point.point.z; if ( psystem->m_Type == PARTICLE_HELI_ATTACK ) { bRemoveParticle = true; - AddParticle(PARTICLE_STEAM, moveStep, CVector(0.0f, 0.0f, 0.05f), nil, 0.2f, 0, 0, 0, 0); + AddParticle(PARTICLE_STEAM, vecPos, CVector(0.0f, 0.0f, 0.05f), nil, 0.2f, 0, 0, 0, 0); continue; } } @@ -1335,37 +1698,21 @@ void CParticle::Update() } } - if ( psystem->m_nFadeToBlackAmount != 0 ) + if ( particle->m_nFadeToBlackTimer != 0 ) { - if ( particle->m_nFadeToBlackTimer >= psystem->m_nFadeToBlackTime ) - { - particle->m_nFadeToBlackTimer = 0; - - particle->m_nColorIntensity = clamp(particle->m_nColorIntensity - psystem->m_nFadeToBlackAmount, + particle->m_nColorIntensity = clamp(particle->m_nColorIntensity - particle->m_nFadeToBlackTimer, 0, 255); - } - else - ++particle->m_nFadeToBlackTimer; } - if ( psystem->m_nFadeAlphaAmount != 0 ) + if ( particle->m_nFadeAlphaTimer != 0 ) { - if ( particle->m_nFadeAlphaTimer >= psystem->m_nFadeAlphaTime ) - { - particle->m_nFadeAlphaTimer = 0; - - particle->m_nAlpha = clamp(particle->m_nAlpha - psystem->m_nFadeAlphaAmount, + particle->m_nAlpha = clamp(particle->m_nAlpha - particle->m_nFadeAlphaTimer, 0, 255); -#ifdef PC_PARTICLE - if ( particle->m_nAlpha == 0 ) - { - bRemoveParticle = true; - continue; - } -#endif + if ( particle->m_nAlpha == 0 ) + { + bRemoveParticle = true; + continue; } - else - ++particle->m_nFadeAlphaTimer; } if ( psystem->m_nZRotationAngleChangeAmount != 0 ) @@ -1409,31 +1756,28 @@ void CParticle::Update() } if ( particle->m_nRotationStep != 0 ) - { +#ifdef FIX_BUGS + particle->m_nRotation = CGeneral::LimitAngle(particle->m_nRotation + particle->m_nRotationStep); +#else particle->m_nRotation += particle->m_nRotationStep; - - if ( particle->m_nRotation >= 360 ) - particle->m_nRotation -= 360; - else if ( particle->m_nRotation < 0 ) - particle->m_nRotation += 360; - } +#endif if ( particle->m_fCurrentZRadius != 0.0f ) { - int32 nRot = particle->m_nCurrentZRotation % (SIN_COS_TABLE_SIZE - 1); + int32 nSinCosIndex = particle->m_nCurrentZRotation % SIN_COS_TABLE_SIZE; - float fX = (Cos(nRot) - Sin(nRot)) * particle->m_fCurrentZRadius; + float fX = (Cos(nSinCosIndex) - Sin(nSinCosIndex)) * particle->m_fCurrentZRadius; - float fY = (Sin(nRot) + Cos(nRot)) * particle->m_fCurrentZRadius; + float fY = (Sin(nSinCosIndex) + Cos(nSinCosIndex)) * particle->m_fCurrentZRadius; - moveStep -= particle->m_vecParticleMovementOffset; + vecPos -= particle->m_vecParticleMovementOffset; - moveStep += CVector(fX, fY, 0.0f); + vecPos += CVector(fX, fY, 0.0f); particle->m_vecParticleMovementOffset = CVector(fX, fY, 0.0f); } - particle->m_vecPosition = moveStep; + particle->m_vecPosition = vecPos; } } } @@ -1457,13 +1801,10 @@ void CParticle::Render() for ( int32 i = 0; i < MAX_PARTICLES; i++ ) { tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[i]; -#ifdef PC_PARTICLE bool particleBanned = false; -#endif CParticle *particle = psystem->m_pParticles; RwRaster **frames = psystem->m_ppRaster; -#ifdef PC_PARTICLE tParticleType type = psystem->m_Type; if ( type == PARTICLE_ENGINE_SMOKE @@ -1477,7 +1818,6 @@ void CParticle::Render() { particleBanned = true; } -#endif if ( particle ) { @@ -1519,11 +1859,10 @@ void CParticle::Render() while ( particle != nil ) { bool canDraw = true; -#ifdef PC_PARTICLE if ( particle->m_nAlpha == 0 ) canDraw = false; -#endif + if ( canDraw && psystem->m_nFinalAnimationFrame != 0 && frames != nil ) { RwRaster *curFrame = frames[particle->m_nCurrentFrame]; @@ -1537,28 +1876,153 @@ void CParticle::Render() if ( canDraw && psystem->Flags & DRAWTOP2D ) { - if ( particle->m_nRotation != 0 ) + float screenZ = (particle->m_vecPosition.z - CDraw::GetNearClipZ()) + * (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ()) + * CDraw::GetFarClipZ() + / ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * particle->m_vecPosition.z ) + + CSprite::GetNearScreenZ(); + + float stretchTexW; + float stretchTexH; + + if ( i == PARTICLE_RAINDROP || i == PARTICLE_RAINDROP_SMALL || i == PARTICLE_RAINDROP_2D ) { - CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension( - particle->m_vecPosition.x, - particle->m_vecPosition.y, - particle->m_fSize * 63.0f, - particle->m_fSize * 63.0f, - particle->m_Color, - particle->m_nColorIntensity, - (float)particle->m_nRotation, //DEGTORAD((float)particle->m_nRotation) ps2 - particle->m_nAlpha); + stretchTexW = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x * (float)particle->m_nCurrentFrame + 63.0f; + stretchTexH = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y * (float)particle->m_nCurrentFrame + 63.0f; } else { - CSprite::RenderBufferedOneXLUSprite2D( - particle->m_vecPosition.x, - particle->m_vecPosition.y, - particle->m_fSize * 63.0f, - particle->m_fSize * 63.0f, - particle->m_Color, - particle->m_nColorIntensity, - particle->m_nAlpha); + stretchTexW = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x + 63.0f; + stretchTexH = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y + 63.0f; + } + + + if ( i == PARTICLE_WATERDROP ) + { + int32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed; + + stretchTexH += (1.0f - (float)timeLeft ) * psystem->m_vecTextureStretch.y; + + RwRect rect; + + rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW)); + rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH)); + rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW)); + rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH)); + + FxType fxtype; + + if ( particle->m_nCurrentFrame != 0 ) + fxtype = FXTYPE_1; + else + fxtype = FXTYPE_0; + + CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, fxtype); + + canDraw = false; + } + + if ( i == PARTICLE_BLOODDROP ) + { + int32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed; + + stretchTexH += (1.0f + (float)timeLeft) * psystem->m_vecTextureStretch.y; + stretchTexW += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.x; + + RwRect rect; + + rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW)); + rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH)); + rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW)); + rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH)); + + FxType fxtype; + + if ( particle->m_nCurrentFrame ) + fxtype = FXTYPE_3; + else + fxtype = FXTYPE_2; + + CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, fxtype); + + canDraw = false; + } + + if ( i == PARTICLE_HEATHAZE_IN_DIST ) + { + RwRect rect; + + rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW)); + rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH * 0.15f)); + rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW)); + rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH * 0.15f)); + + CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_4); + + canDraw = false; + } + + if ( i == PARTICLE_HEATHAZE ) + { + RwRect rect; + + switch ( TheCamera.GetLookDirection() ) + { + case LOOKING_LEFT: + rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x * 2.0f)); + rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y)); + rect.w = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x)); + rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y)); + + break; + + case LOOKING_RIGHT: + rect.x = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x)); + rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y)); + rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x * 4.0f)); + rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y)); + + break; + + default: + rect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x)); + rect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y)); + rect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x)); + rect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y)); + + break; + } + + CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_4); + + canDraw = false; + } + + if ( canDraw ) + { + if ( particle->m_nRotation != 0 ) + { + CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension( + particle->m_vecPosition.x, + particle->m_vecPosition.y, + particle->m_fSize * stretchTexW, + particle->m_fSize * stretchTexH, + particle->m_Color, + particle->m_nColorIntensity, + DEGTORAD((float)particle->m_nRotation), + particle->m_nAlpha); + } + else + { + CSprite::RenderBufferedOneXLUSprite2D( + particle->m_vecPosition.x, + particle->m_vecPosition.y, + particle->m_fSize * stretchTexW, + particle->m_fSize * stretchTexH, + particle->m_Color, + particle->m_nColorIntensity, + particle->m_nAlpha); + } } canDraw = false; @@ -1572,174 +2036,234 @@ void CParticle::Render() if ( CSprite::CalcScreenCoors(particle->m_vecPosition, coors, &w, &h, true) ) { -#ifdef PC_PARTICLE - if ( (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w) - && SCREEN_HEIGHT * fParticleScaleLimit >= h ) -#endif + + if ( i == PARTICLE_ENGINE_STEAM + || i == PARTICLE_ENGINE_SMOKE + || i == PARTICLE_ENGINE_SMOKE2 + || i == PARTICLE_CARFLAME_SMOKE + || i == PARTICLE_CARCOLLISION_DUST + || i == PARTICLE_EXHAUST_FUMES + || i == PARTICLE_RUBBER_SMOKE + || i == PARTICLE_BURNINGRUBBER_SMOKE ) { - if ( particle->m_nRotation != 0 ) - { - CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z, - particle->m_fSize * w, particle->m_fSize * h, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - float(particle->m_nRotation), // DEGTORAD((float)particle->m_nRotation) ps2 - particle->m_nAlpha); + switch ( TheCamera.GetLookDirection() ) + { + case LOOKING_LEFT: + case LOOKING_RIGHT: + w += CGeneral::GetRandomNumberInRange(1.0f, 7.5f) * psystem->m_vecTextureStretch.x; + h += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y; + break; + + default: + w += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x; + h += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y; + break; } - else if ( psystem->Flags & SCREEN_TRAIL ) + } + else if ( i == PARTICLE_WATER_HYDRANT ) + { + int32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed; + + w += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.x; + h += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.y; + } + else if ( i == PARTICLE_FLYERS ) + { + w += psystem->m_vecTextureStretch.x; + h += psystem->m_vecTextureStretch.y; + + w = Max(w, 12.0f); + h = Max(h, 12.0f); + } + else + { + w += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x; + h += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y; + } + + if ( i == PARTICLE_WATER_HYDRANT + || (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w) + && SCREEN_HEIGHT * fParticleScaleLimit >= h ) + { + if ( i == PARTICLE_WATER_HYDRANT ) { - float fRotation; - float fTrailLength; + RwRect rect; - if ( particle->m_vecScreenPosition.x == 0.0f ) + if ( w > 0.0f ) { - fTrailLength = 0.0f; - fRotation = 0.0f; + rect.x = int32(coors.x - SCREEN_STRETCH_X(particle->m_fSize * w)); + rect.w = int32(coors.x + SCREEN_STRETCH_X(particle->m_fSize * w)); } else { - CVector2D vecDist - ( - coors.x - particle->m_vecScreenPosition.x, - coors.y - particle->m_vecScreenPosition.y - ); - - float fDist = vecDist.Magnitude(); - - fTrailLength = fDist; - - float fRot = Asin(vecDist.x / fDist); - - fRotation = fRot; - - if ( vecDist.y < 0.0f ) - fRotation = -1.0f * fRot + DEGTORAD(180.0f); - - fRotation = RADTODEG(fRotation); - - if ( fRotation < 0.0f ) - fRotation += 360.0f; - - float fSpeed = particle->m_vecVelocity.Magnitude(); - - float fNewTrailLength = fSpeed * CTimer::GetTimeStep() * w * 2.0f; - - if ( fDist > fNewTrailLength ) - fTrailLength = fNewTrailLength; + rect.w = int32(coors.x - SCREEN_STRETCH_X(particle->m_fSize * w)); + rect.x = int32(coors.x + SCREEN_STRETCH_X(particle->m_fSize * w)); } - CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z, - particle->m_fSize * w, - particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - fRotation, - particle->m_nAlpha); - - particle->m_vecScreenPosition = coors; + if ( h > 0.0f ) + { + rect.y = int32(coors.y - SCREEN_STRETCH_Y(particle->m_fSize * h)); + rect.h = int32(coors.y + SCREEN_STRETCH_Y(particle->m_fSize * h)); + } + else + { + rect.h = int32(coors.y - SCREEN_STRETCH_Y(particle->m_fSize * h)); + rect.y = int32(coors.y + SCREEN_STRETCH_Y(particle->m_fSize * h)); + } + + float screenZ = (coors.z - CDraw::GetNearClipZ()) + * (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ()) * CDraw::GetFarClipZ() + / ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * coors.z ) + CSprite::GetNearScreenZ(); + + CMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_5); } - else if ( psystem->Flags & SPEED_TRAIL ) + else { - CVector vecPrevPos = particle->m_vecPosition - particle->m_vecVelocity; - float fRotation; - float fTrailLength; - - if ( CSprite::CalcScreenCoors(vecPrevPos, particle->m_vecScreenPosition, &fTrailLength, &fRotation, true) ) + if ( particle->m_nRotation != 0 && i != PARTICLE_BEASTIE ) + { + CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z, + particle->m_fSize * w, particle->m_fSize * h, + particle->m_Color.red, + particle->m_Color.green, + particle->m_Color.blue, + particle->m_nColorIntensity, + 1.0f / coors.z, + DEGTORAD((float)particle->m_nRotation), + particle->m_nAlpha); + } + else if ( psystem->Flags & SCREEN_TRAIL ) { - CVector2D vecDist - ( - coors.x - particle->m_vecScreenPosition.x, - coors.y - particle->m_vecScreenPosition.y - ); - - float fDist = vecDist.Magnitude(); + float fRotation; + float fTrailLength; - fTrailLength = fDist; - - float fRot = Asin(vecDist.x / fDist); - - fRotation = fRot; + if ( particle->m_fZGround == 0.0f ) + { + fTrailLength = 0.0f; + fRotation = 0.0f; + } + else + { + CVector2D vecDist + ( + coors.x - particle->m_fZGround, + coors.y - particle->m_fExpansionRate + ); + + float fDist = vecDist.Magnitude(); + + fTrailLength = fDist; + + float fRot = Asin(vecDist.x / fDist); + + fRotation = fRot; + + if ( vecDist.y < 0.0f ) + fRotation = -1.0f * fRot + DEGTORAD(180.0f); + + float fSpeed = particle->m_vecVelocity.Magnitude(); + + float fNewTrailLength = fSpeed * CTimer::GetTimeStep() * w * 2.0f; + + if ( fDist > fNewTrailLength ) + fTrailLength = fNewTrailLength; + } - if ( vecDist.y < 0.0f ) - fRotation = -1.0f * fRot + DEGTORAD(180.0f); + CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z, + particle->m_fSize * w, + particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier, + particle->m_Color.red, + particle->m_Color.green, + particle->m_Color.blue, + particle->m_nColorIntensity, + 1.0f / coors.z, + fRotation, + particle->m_nAlpha); + + particle->m_fZGround = coors.x; // WTF ? + particle->m_fExpansionRate = coors.y; // WTF ? + } + else if ( psystem->Flags & SPEED_TRAIL ) + { + CVector vecPrevPos = particle->m_vecPosition - particle->m_vecVelocity; + float fRotation; + float fTrailLength; + CVector vecScreenPosition; - fRotation = RADTODEG(fRotation); + if ( CSprite::CalcScreenCoors(vecPrevPos, vecScreenPosition, &fTrailLength, &fRotation, true) ) + { + CVector2D vecDist + ( + coors.x - vecScreenPosition.x, + coors.y - vecScreenPosition.y + ); + + float fDist = vecDist.Magnitude(); + + fTrailLength = fDist; + + float fRot = Asin(vecDist.x / fDist); + + fRotation = fRot; + + if ( vecDist.y < 0.0f ) + fRotation = -1.0f * fRot + DEGTORAD(180.0f); + } + else + { + fRotation = 0.0f; + fTrailLength = 0.0f; + } - if ( fRotation < 0.0f ) - fRotation += 360.0f; + CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z, + particle->m_fSize * w, + particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier, + particle->m_Color.red, + particle->m_Color.green, + particle->m_Color.blue, + particle->m_nColorIntensity, + 1.0f / coors.z, + fRotation, + particle->m_nAlpha); } - else + else if ( psystem->Flags & VERT_TRAIL ) { - fRotation = 0.0f; - fTrailLength = 0.0f; + float fTrailLength = fabsf(particle->m_vecVelocity.z * 10.0f); + + CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, + particle->m_fSize * w, + (particle->m_fSize + fTrailLength * psystem->m_fTrailLengthMultiplier) * h, + particle->m_Color.red, + particle->m_Color.green, + particle->m_Color.blue, + particle->m_nColorIntensity, + 1.0f / coors.z, + particle->m_nAlpha); + } + else if ( i == PARTICLE_RAINDROP_SMALL ) + { + CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, + particle->m_fSize * w * 0.05f, + particle->m_fSize * h, + particle->m_Color.red, + particle->m_Color.green, + particle->m_Color.blue, + particle->m_nColorIntensity, + 1.0f / coors.z, + particle->m_nAlpha); + } + /*else if ( i == PARTICLE_BOAT_WAKE )*/ + else + { + CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, + particle->m_fSize * w, + particle->m_fSize * h, + particle->m_Color.red, + particle->m_Color.green, + particle->m_Color.blue, + particle->m_nColorIntensity, + 1.0f / coors.z, + particle->m_nAlpha); } - - CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z, - particle->m_fSize * w, - particle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - fRotation, - particle->m_nAlpha); - } - else if ( psystem->Flags & VERT_TRAIL ) - { - float fTrailLength = fabsf(particle->m_vecVelocity.z * 10.0f); - - CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, - particle->m_fSize * w, - (particle->m_fSize + fTrailLength * psystem->m_fTrailLengthMultiplier) * h, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - particle->m_nAlpha); - } - else if ( i == PARTICLE_RAINDROP_SMALL ) - { - CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, - particle->m_fSize * w * 0.05f, - particle->m_fSize * h, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - particle->m_nAlpha); - } - else if ( i == PARTICLE_BOAT_WAKE ) - { - CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, - particle->m_fSize * w, - psystem->m_fDefaultInitialRadius * h, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - particle->m_nAlpha); - } - else - { - CSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z, - particle->m_fSize * w, - particle->m_fSize * h, - particle->m_Color.red, - particle->m_Color.green, - particle->m_Color.blue, - particle->m_nColorIntensity, - 1.0f / coors.z, - particle->m_nAlpha); } } } @@ -1769,6 +2293,9 @@ void CParticle::RemovePSystem(tParticleType type) void CParticle::RemoveParticle(CParticle *pParticle, CParticle *pPrevParticle, tParticleSystemData *pPSystemData) { + if ( pPSystemData->m_Type == PARTICLE_WATERDROP ) + --numWaterDropOnScreen; + if ( pPrevParticle ) pPrevParticle->m_pNext = pParticle->m_pNext; else @@ -1857,3 +2384,89 @@ void CParticle::AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatr 0.3f, color, 0, 0, 0, 0); } } + +void CParticle::CalWindDir(CVector *vecDirIn, CVector *vecDirOut) +{ + vecDirOut->x = (Cos(128) * vecDirIn->x) + (Sin(128) * vecDirIn->y); + + vecDirOut->x = (Cos(128) * vecDirIn->x) + (Sin(128) * vecDirIn->y) * CWeather::Wind; + vecDirOut->y = (Sin(128) * vecDirIn->x) - (Cos(128) * vecDirIn->y) * CWeather::Wind; +} + +void CParticle::HandleShipsAtHorizonStuff() +{ + tParticleSystemData *psystemdata = &mod_ParticleSystemManager.m_aParticles[PARTICLE_SHIP_SIDE]; + + for ( CParticle *particle = psystemdata->m_pParticles; particle; particle = particle->m_pNext ) + { + if ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed - 32000 + && CTimer::GetTimeInMilliseconds() < particle->m_nTimeWhenWillBeDestroyed - 22000 ) + { + particle->m_nAlpha = Min(particle->m_nAlpha + 1, 96); + } + if ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed - 10000 ) + particle->m_nFadeAlphaTimer = 1; + } +} + +void CParticle::HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos) +{ + float fHeadingRad = entity->GetForward().Heading(); + float fHeading = RADTODEG(fHeadingRad); + float fBirdAngle = ::Cos(DEGTORAD(1.5f)); + + tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[PARTICLE_BIRD_FRONT]; + CParticle *particle = psystem->m_pParticles; + CParticle *prevParticle = nil; + bool bRemoveParticle; + + for ( ; particle != nil; _Next(particle, prevParticle, psystem, bRemoveParticle) ) + { + bRemoveParticle = false; + + CVector2D vecPos(particle->m_vecPosition.x, particle->m_vecPosition.y); + CVector2D vecCamPos(camPos.x, camPos.y); + + CVector2D vecDist = vecPos - vecCamPos; + vecDist.Normalise(); + + float fHead = DEGTORAD(fHeading); + + CVector2D vecDir(-::Sin(fHead), ::Cos(fHead)); + vecDir.Normalise(); + + float fDot = DotProduct2D(vecDir, vecDist); + + if ( fDot > 0.0f && fDot > fBirdAngle ) + { + if ( (camPos - particle->m_vecPosition).MagnitudeSqr() < 40000.0f ) + { + CStats::SeagullsKilled++; + + bRemoveParticle = true; + + for ( int32 i = 0; i < 8; i++ ) + { + CParticle *pBirdDerbis = AddParticle(PARTICLE_BIRD_DEBRIS, + particle->m_vecPosition, + CVector + ( + CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), + CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), + CGeneral::GetRandomNumberInRange(-3.0f, 3.0f) + ), + nil, + 0.3f, + particle->m_Color, + CGeneral::GetRandomNumberInRange(20, 40), + 0, + CGeneral::GetRandomNumber() & 3, + 200); + if ( pBirdDerbis ) + pBirdDerbis->m_nAlpha = particle->m_nAlpha; + } + } + } + } + +} diff --git a/src/render/Particle.h b/src/render/Particle.h index 7f02e318..9c496fe1 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -15,25 +15,24 @@ public: CVector m_vecPosition; CVector m_vecVelocity; - CVector m_vecScreenPosition; - uint32 m_nTimeWhenWillBeDestroyed; - uint32 m_nTimeWhenColorWillBeChanged; + uint32 m_nTimeWhenWillBeDestroyed; + uint32 m_nTimeWhenColorWillBeChanged; float m_fZGround; CVector m_vecParticleMovementOffset; int16 m_nCurrentZRotation; - uint16 m_nZRotationTimer; + uint16 m_nZRotationTimer; float m_fCurrentZRadius; - uint16 m_nZRadiusTimer; - float m_fSize; - float m_fExpansionRate; - uint16 m_nFadeToBlackTimer; - uint16 m_nFadeAlphaTimer; + uint16 m_nZRadiusTimer; uint8 m_nColorIntensity; uint8 m_nAlpha; - uint16 m_nCurrentFrame; + float m_fSize; + float m_fExpansionRate; + int16 m_nFadeToBlackTimer; + int16 m_nFadeAlphaTimer; int16 m_nAnimationSpeedTimer; int16 m_nRotationStep; int16 m_nRotation; + uint8 m_nCurrentFrame; RwRGBA m_Color; CParticle *m_pNext; @@ -60,8 +59,11 @@ public: static void Initialise(); static void Shutdown(); - static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity = nil, float fSize = 0.0f, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0); - static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0); + static void AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity = nil, float fSize = 0.0f, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0); + static void AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, RwRGBA const&color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0); + + static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity = nil, float fSize = 0.0f, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0); + static CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0); static void Update(); static void Render(); @@ -89,6 +91,13 @@ public: static void AddJetExplosion(CVector const &vecPos, float fPower, float fSize); static void AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatrix); + static void CalWindDir(CVector *vecDirIn, CVector *vecDirOut); + + static void HandleShipsAtHorizonStuff(); + static void HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos); }; -VALIDATE_SIZE(CParticle, 0x68); +extern bool clearWaterDrop; +extern int32 numWaterDropOnScreen; + +VALIDATE_SIZE(CParticle, 0x58); diff --git a/src/render/ParticleMgr.cpp b/src/render/ParticleMgr.cpp index 3387d471..f6919435 100644 --- a/src/render/ParticleMgr.cpp +++ b/src/render/ParticleMgr.cpp @@ -216,6 +216,18 @@ void cParticleSystemMgr::LoadParticleData() case CFG_PARAM_TRAIL_LENGTH_MULTIPLIER: entry->m_fTrailLengthMultiplier = atof(value); break; + + case CFG_PARAM_STRETCH_VALUE_X: + entry->m_vecTextureStretch.x = atof(value); + break; + + case CFG_PARAM_STRETCH_VALUE_Y: + entry->m_vecTextureStretch.y = atof(value); + break; + + case CFG_PARAM_WIND_FACTOR: + entry->m_fWindFactor = atof(value); + break; case CFG_PARAM_PARTICLE_CREATE_RANGE: entry->m_fCreateRange = SQR(atof(value)); diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h index 0100bb65..f4afc018 100644 --- a/src/render/ParticleMgr.h +++ b/src/render/ParticleMgr.h @@ -36,14 +36,14 @@ struct tParticleSystemData uint16 m_nZRadiusChangeTime; float m_fInitialZRadius; float m_fZRadiusChangeAmount; - uint16 m_nFadeToBlackTime; - int16 m_nFadeToBlackAmount; + int16 m_nFadeToBlackTime; uint8 m_nFadeToBlackInitialIntensity; + int16 m_nFadeToBlackAmount; uint8 m_nFadeAlphaInitialIntensity; - uint16 m_nFadeAlphaTime; + int16 m_nFadeAlphaTime; int16 m_nFadeAlphaAmount; - uint16 m_nStartAnimationFrame; - uint16 m_nFinalAnimationFrame; + uint8 m_nStartAnimationFrame; + uint8 m_nFinalAnimationFrame; uint16 m_nAnimationSpeed; uint16 m_nRotationSpeed; float m_fGravitationalAcceleration; @@ -56,16 +56,19 @@ struct tParticleSystemData uint32 m_nLifeSpanErrorShape; float m_fTrailLengthMultiplier; uint32 Flags; - RwRGBA m_RenderColouring; + CRGBA m_RenderColouring; uint8 m_InitialColorVariation; - RwRGBA m_FadeDestinationColor; + CRGBA m_FadeDestinationColor; uint32 m_ColorFadeTime; + + CVector2D m_vecTextureStretch; + float m_fWindFactor; RwRaster **m_ppRaster; CParticle *m_pParticles; }; -VALIDATE_SIZE(tParticleSystemData, 0x88); +VALIDATE_SIZE(tParticleSystemData, 0x94); class cParticleSystemMgr { @@ -107,6 +110,11 @@ class cParticleSystemMgr CFG_PARAM_ROTATION_RATE_ERROR, CFG_PARAM_LIFE_SPAN_ERROR_SHAPE, CFG_PARAM_TRAIL_LENGTH_MULTIPLIER, + + CFG_PARAM_STRETCH_VALUE_X, + CFG_PARAM_STRETCH_VALUE_Y, + CFG_PARAM_WIND_FACTOR, + CFG_PARAM_PARTICLE_CREATE_RANGE, CFG_PARAM_FLAGS, @@ -125,6 +133,6 @@ public: void RangeCheck(tParticleSystemData *pData) { } }; -VALIDATE_SIZE(cParticleSystemMgr, 0x2420); +VALIDATE_SIZE(cParticleSystemMgr, 0x2FFC); extern cParticleSystemMgr mod_ParticleSystemManager; diff --git a/src/render/ParticleType.h b/src/render/ParticleType.h index 8d352c44..0af9a1e1 100644 --- a/src/render/ParticleType.h +++ b/src/render/ParticleType.h @@ -4,13 +4,16 @@ enum tParticleType { PARTICLE_SPARK = 0, PARTICLE_SPARK_SMALL, + PARTICLE_WATER_SPARK, PARTICLE_WHEEL_DIRT, + PARTICLE_SAND, PARTICLE_WHEEL_WATER, PARTICLE_BLOOD, PARTICLE_BLOOD_SMALL, PARTICLE_BLOOD_SPURT, PARTICLE_DEBRIS, PARTICLE_DEBRIS2, + PARTICLE_FLYERS, PARTICLE_WATER, PARTICLE_FLAME, PARTICLE_FIREBALL, @@ -18,8 +21,11 @@ enum tParticleType PARTICLE_GUNFLASH_NOANIM, PARTICLE_GUNSMOKE, PARTICLE_GUNSMOKE2, + PARTICLE_CIGARETTE_SMOKE, PARTICLE_SMOKE, PARTICLE_SMOKE_SLOWMOTION, + PARTICLE_DRY_ICE, + PARTICLE_TEARGAS, PARTICLE_GARAGEPAINT_SPRAY, PARTICLE_SHARD, PARTICLE_SPLASH, @@ -28,6 +34,7 @@ enum tParticleType PARTICLE_STEAM2, PARTICLE_STEAM_NY, PARTICLE_STEAM_NY_SLOWMOTION, + PARTICLE_GROUND_STEAM, PARTICLE_ENGINE_STEAM, PARTICLE_RAINDROP, PARTICLE_RAINDROP_SMALL, @@ -35,6 +42,8 @@ enum tParticleType PARTICLE_RAIN_SPLASH_BIGGROW, PARTICLE_RAIN_SPLASHUP, PARTICLE_WATERSPRAY, + PARTICLE_WATERDROP, + PARTICLE_BLOODDROP, PARTICLE_EXPLOSION_MEDIUM, PARTICLE_EXPLOSION_LARGE, PARTICLE_EXPLOSION_MFAST, @@ -42,12 +51,12 @@ enum tParticleType PARTICLE_CAR_SPLASH, PARTICLE_BOAT_SPLASH, PARTICLE_BOAT_THRUSTJET, - PARTICLE_BOAT_WAKE, PARTICLE_WATER_HYDRANT, PARTICLE_WATER_CANNON, PARTICLE_EXTINGUISH_STEAM, PARTICLE_PED_SPLASH, PARTICLE_PEDFOOT_DUST, + PARTICLE_CAR_DUST, PARTICLE_HELI_DUST, PARTICLE_HELI_ATTACK, PARTICLE_ENGINE_SMOKE, @@ -58,6 +67,7 @@ enum tParticleType PARTICLE_TREE_LEAVES, PARTICLE_CARCOLLISION_DUST, PARTICLE_CAR_DEBRIS, + PARTICLE_BIRD_DEBRIS, PARTICLE_HELI_DEBRIS, PARTICLE_EXHAUST_FUMES, PARTICLE_RUBBER_SMOKE, @@ -67,9 +77,14 @@ enum tParticleType PARTICLE_GUNSHELL, PARTICLE_GUNSHELL_BUMP1, PARTICLE_GUNSHELL_BUMP2, + PARTICLE_ROCKET_SMOKE, PARTICLE_TEST, PARTICLE_BIRD_FRONT, + PARTICLE_SHIP_SIDE, + PARTICLE_BEASTIE, PARTICLE_RAINDROP_2D, + PARTICLE_HEATHAZE, + PARTICLE_HEATHAZE_IN_DIST, MAX_PARTICLES, PARTICLE_FIRST = PARTICLE_SPARK, diff --git a/src/render/PlayerSkin.cpp b/src/render/PlayerSkin.cpp index d66f7ce4..261bbec0 100644 --- a/src/render/PlayerSkin.cpp +++ b/src/render/PlayerSkin.cpp @@ -15,6 +15,8 @@ #include "Timer.h" #include "Lights.h" +//--MIAMI: file done + RpClump *gpPlayerClump; float gOldFov; @@ -97,7 +99,7 @@ CPlayerSkin::GetSkinTexture(const char *texName) CTxdStore::PopCurrentTxd(); if (tex != nil) return tex; - if (strcmp(DEFAULT_SKIN_NAME, texName) == 0) + if (strcmp(DEFAULT_SKIN_NAME, texName) == 0 || texName[0] == '\0') sprintf(gString, "models\\generic\\player.bmp"); else sprintf(gString, "skins\\%s.bmp", texName); @@ -109,9 +111,7 @@ CPlayerSkin::GetSkinTexture(const char *texName) tex = RwTextureCreate(raster); RwTextureSetName(tex, texName); -#ifdef FIX_BUGS - RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC -#endif + RwTextureSetFilterMode(tex, rwFILTERLINEAR); RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex); RwImageDestroy(image); @@ -143,8 +143,7 @@ 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 }; + const RwV3d axis = { 0.0f, 1.0f, 0.0f }; static uint32 LastFlash = 0; RwFrame *frame = RpClumpGetFrame(gpPlayerClump); @@ -157,8 +156,7 @@ CPlayerSkin::RenderFrontendSkinEdit(void) } RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE); RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT); - RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT); - RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT); + RwFrameRotate(frame, &axis, rotation, rwCOMBINEPRECONCAT); RwFrameUpdateObjects(frame); SetAmbientColours(&AmbientColor); RpClumpRender(gpPlayerClump); diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp index 0713dc6d..b09b07bd 100644 --- a/src/render/PointLights.cpp +++ b/src/render/PointLights.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "main.h" +#include "CutsceneMgr.h" #include "Lights.h" #include "Camera.h" #include "Weather.h" @@ -10,8 +11,23 @@ #include "Timer.h" #include "PointLights.h" +//--MIAMI: file done + int16 CPointLights::NumLights; CRegisteredPointLight CPointLights::aLights[NUMPOINTLIGHTS]; +CVector CPointLights::aCachedMapReads[32]; +float CPointLights::aCachedMapReadResults[32]; +int32 CPointLights::NextCachedValue; + +void +CPointLights::Init(void) +{ + for(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++){ + aCachedMapReads[i] = CVector(0.0f, 0.0f, 0.0f); + aCachedMapReadResults[i] = 0.0f; + } + NextCachedValue = 0; +} void CPointLights::InitPerFrame(void) @@ -142,12 +158,17 @@ CPointLights::RenderFogEffect(void) CVector spriteCoors; float spritew, spriteh; + if(CCutsceneMgr::IsRunning()) + return; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpPointlightRaster); + CSprite::InitSpriteBuffer(); + for(i = 0; i < NumLights; i++){ if(aLights[i].fogType != FOG_NORMAL && aLights[i].fogType != FOG_ALWAYS) continue; @@ -221,7 +242,7 @@ CPointLights::RenderFogEffect(void) if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){ float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x2000; float size = FogSizes[r>>1]; - CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z, + CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z, spritew * size, spriteh * size, aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity, intensity, 1/spriteCoors.z, rotation, 255); @@ -233,9 +254,8 @@ CPointLights::RenderFogEffect(void) } }else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS){ - if(CWorld::ProcessVerticalLine(aLights[i].coors, aLights[i].coors.z - 20.0f, - point, entity, true, false, false, false, true, false, nil)){ - + float groundZ; + if(ProcessVerticalLineUsingCache(aLights[i].coors, &groundZ)){ xmin = aLights[i].coors.x - FOG_AREA_RADIUS; ymin = aLights[i].coors.y - FOG_AREA_RADIUS; xmax = aLights[i].coors.x + FOG_AREA_RADIUS; @@ -266,11 +286,11 @@ CPointLights::RenderFogEffect(void) // more intensity the closer to light source intensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS); - CVector fogcoors(xi, yi, point.point.z + 1.6f); + CVector fogcoors(xi, yi, groundZ + 1.6f); if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){ float rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x4000; float size = FogSizes[r>>1]; - CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z, + CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z, spritew * size, spriteh * size, aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity, intensity, 1/spriteCoors.z, rotation, 255); @@ -282,4 +302,27 @@ CPointLights::RenderFogEffect(void) } } } + + CSprite::FlushSpriteBuffer(); +} + +bool +CPointLights::ProcessVerticalLineUsingCache(CVector coors, float *groundZ) +{ + for(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++) + if(aCachedMapReads[i] == coors){ + *groundZ = aCachedMapReadResults[i]; + return true; + } + + CColPoint point; + CEntity *entity; + if(CWorld::ProcessVerticalLine(coors, coors.z - 20.0f, point, entity, true, false, false, false, true, false, nil)){ + aCachedMapReads[NextCachedValue] = coors; + aCachedMapReadResults[NextCachedValue] = point.point.z; + NextCachedValue = (NextCachedValue+1) % ARRAY_SIZE(aCachedMapReads); + *groundZ = point.point.z; + return true; + } + return false; } diff --git a/src/render/PointLights.h b/src/render/PointLights.h index 9e94328f..827200b9 100644 --- a/src/render/PointLights.h +++ b/src/render/PointLights.h @@ -20,6 +20,9 @@ class CPointLights public: static int16 NumLights; static CRegisteredPointLight aLights[NUMPOINTLIGHTS]; + static CVector aCachedMapReads[32]; + static float aCachedMapReadResults[32]; + static int32 NextCachedValue; enum { LIGHT_POINT, @@ -37,9 +40,11 @@ public: FOG_ALWAYS }; + static void Init(void); static void InitPerFrame(void); static void AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows); static float GenerateLightsAffectingObject(Const CVector *objCoors); static void RemoveLightsAffectingObject(void); static void RenderFogEffect(void); + static bool ProcessVerticalLineUsingCache(CVector coors, float *groundZ); }; diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp index 6120dfe2..687cc76b 100644 --- a/src/render/RenderBuffer.cpp +++ b/src/render/RenderBuffer.cpp @@ -5,7 +5,7 @@ int32 TempBufferVerticesStored; int32 TempBufferIndicesStored; -RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; +VertexBufferUnion TempVertexBuffer; RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; int RenderBuffer::VerticesToBeStored; diff --git a/src/render/RenderBuffer.h b/src/render/RenderBuffer.h index 485d24e3..a0f3e7b9 100644 --- a/src/render/RenderBuffer.h +++ b/src/render/RenderBuffer.h @@ -9,10 +9,17 @@ public: static void RenderStuffInBuffer(void); }; -#define TEMPBUFFERVERTSIZE 256 +#define TEMPBUFFERVERTSIZE 512 #define TEMPBUFFERINDEXSIZE 1024 +struct VertexBufferUnion +{ + RwIm2DVertex im2d[TEMPBUFFERVERTSIZE]; + RwIm3DVertex im3d[TEMPBUFFERVERTSIZE]; +}; + extern int32 TempBufferVerticesStored; extern int32 TempBufferIndicesStored; -extern RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; +extern VertexBufferUnion TempVertexBuffer; +#define TempBufferRenderVertices (TempVertexBuffer.im3d) extern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE];
\ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 8c194067..3b996b55 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -7,6 +7,7 @@ #include "Ped.h" #include "Vehicle.h" #include "Heli.h" +#include "Bike.h" #include "Object.h" #include "PathFind.h" #include "Collision.h" @@ -18,15 +19,14 @@ #include "Streaming.h" #include "Shadows.h" #include "PointLights.h" +#include "Occlusion.h" #include "Renderer.h" -#include "Frontend.h" #include "custompipes.h" -bool gbShowPedRoadGroups; -bool gbShowCarRoadGroups; +//--MIAMI: file done + bool gbShowCollisionPolys; bool gbShowCollisionLines; -bool gbShowCullZoneDebugStuff; bool gbBigWhiteDebugLightSwitchedOn; bool gbDontRenderBuildings; @@ -98,12 +98,8 @@ CRenderer::RenderOneRoad(CEntity *e) return; if(gbShowCollisionPolys) CCollision::DrawColModel_Coloured(e->GetMatrix(), *CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(), e->GetModelIndex()); - else{ -#ifdef EXTENDED_PIPELINES - CustomPipes::AttachGlossPipe(e->GetAtomic()); -#endif + else e->Render(); - } } void @@ -152,8 +148,11 @@ CRenderer::RenderOneNonRoad(CEntity *e) resetLights = e->SetupLighting(); - if(e->IsVehicle()) + if(e->IsVehicle()){ + // unfortunately can't use GetClump here + CVisibilityPlugins::SetupVehicleVariables((RpClump*)e->m_rwObject); CVisibilityPlugins::InitAlphaAtomicList(); + } // Render Peds in vehicle before vehicle itself if(e->IsVehicle()){ @@ -163,6 +162,7 @@ CRenderer::RenderOneNonRoad(CEntity *e) for(i = 0; i < 8; i++) if(veh->pPassengers[i] && veh->pPassengers[i]->m_nPedState == PED_DRIVING) veh->pPassengers[i]->Render(); + SetCullMode(rwCULLMODECULLNONE); } e->Render(); @@ -170,6 +170,7 @@ CRenderer::RenderOneNonRoad(CEntity *e) e->bImBeingRendered = true; CVisibilityPlugins::RenderAlphaAtomics(); e->bImBeingRendered = false; + SetCullMode(rwCULLMODECULLBACK); } e->RemoveLighting(resetLights); @@ -190,38 +191,40 @@ CRenderer::RenderFirstPersonVehicle(void) RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); } +inline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CSimpleModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->m_wetRoadReflection; } + void CRenderer::RenderRoads(void) { int i; - CTreadable *t; + CEntity *e; RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); DeActivateDirectional(); SetAmbientColours(); for(i = 0; i < ms_nNoOfVisibleEntities; i++){ - t = (CTreadable*)ms_aVisibleEntityPtrs[i]; - if(t->IsBuilding() && t->GetIsATreadable()){ -#ifndef MASTER - if(gbShowCarRoadGroups || gbShowPedRoadGroups){ - int ind = 0; - if(gbShowCarRoadGroups) - ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_CAR][0]].group; - if(gbShowPedRoadGroups) - ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group; - SetAmbientColoursToIndicateRoadGroup(ind); - } -#endif - RenderOneRoad(t); -#ifndef MASTER - if(gbShowCarRoadGroups || gbShowPedRoadGroups) - ReSetAmbientAndDirectionalColours(); -#endif - } + e = ms_aVisibleEntityPtrs[i]; + if(IsRoad(e)) + RenderOneRoad(e); } } +inline bool PutIntoSortedVehicleList(CVehicle *veh) +{ + if(veh->IsBoat()){ + int mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if(mode == CCam::MODE_WHEELCAM || + mode == CCam::MODE_1STPERSON && TheCamera.GetLookDirection() != LOOKING_FORWARD && TheCamera.GetLookDirection() != LOOKING_BEHIND || + CVisibilityPlugins::GetClumpAlpha(veh->GetClump()) != 255) + return false; + return true; + }else + return veh->bTouchingWater; +} + void CRenderer::RenderEverythingBarRoads(void) { @@ -230,12 +233,15 @@ CRenderer::RenderEverythingBarRoads(void) CVector dist; EntityInfo ei; + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); gSortedVehiclesAndPeds.Clear(); for(i = 0; i < ms_nNoOfVisibleEntities; i++){ e = ms_aVisibleEntityPtrs[i]; - if(e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable()) + if(IsRoad(e)) continue; #ifdef EXTENDED_PIPELINES @@ -245,7 +251,7 @@ CRenderer::RenderEverythingBarRoads(void) if(e->IsVehicle() || e->IsPed() && CVisibilityPlugins::GetClumpAlpha((RpClump*)e->m_rwObject) != 255){ - if(e->IsVehicle() && ((CVehicle*)e)->IsBoat()){ + if(e->IsVehicle() && PutIntoSortedVehicleList((CVehicle*)e)){ ei.ent = e; dist = ms_vecCameraPosition - e->GetPosition(); ei.sort = dist.MagnitudeSqr(); @@ -263,34 +269,19 @@ CRenderer::RenderEverythingBarRoads(void) } void -CRenderer::RenderVehiclesButNotBoats(void) -{ - // This function doesn't do anything - // because only boats are inserted into the list - CLink<EntityInfo> *node; - - for(node = gSortedVehiclesAndPeds.tail.prev; - node != &gSortedVehiclesAndPeds.head; - node = node->prev){ - // only boats in this list - CVehicle *v = (CVehicle*)node->item.ent; - if(!v->IsBoat()) - RenderOneNonRoad(v); - } -} - -void CRenderer::RenderBoats(void) { CLink<EntityInfo> *node; + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); + for(node = gSortedVehiclesAndPeds.tail.prev; node != &gSortedVehiclesAndPeds.head; node = node->prev){ - // only boats in this list CVehicle *v = (CVehicle*)node->item.ent; - if(v->IsBoat()) - RenderOneNonRoad(v); + RenderOneNonRoad(v); } } @@ -298,12 +289,22 @@ void CRenderer::RenderFadingInEntities(void) { RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); DeActivateDirectional(); SetAmbientColours(); CVisibilityPlugins::RenderFadingEntities(); } void +CRenderer::RenderFadingInUnderwaterEntities(void) +{ + DeActivateDirectional(); + SetAmbientColours(); + CVisibilityPlugins::RenderFadingUnderwaterEntities(); +} + +void CRenderer::RenderCollisionLines(void) { int i; @@ -351,7 +352,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent) float dist; bool request = true; - if (mi->GetModelType() == MITYPE_TIME) { + if(mi->GetModelType() == MITYPE_TIME){ ti = (CTimeModelInfo*)mi; other = ti->GetOtherTimeModel(); if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){ @@ -367,25 +368,35 @@ CRenderer::SetupEntityVisibility(CEntity *ent) request = false; } }else{ - if (mi->GetModelType() != MITYPE_SIMPLE) { + if(mi->GetModelType() != MITYPE_SIMPLE && mi->GetModelType() != MITYPE_WEAPON){ if(FindPlayerVehicle() == ent && - TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){ + TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON && + !(FindPlayerVehicle()->IsBike() && ((CBike*)FindPlayerVehicle())->bWheelieCam)){ // Player's vehicle in first person mode - if(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD || + CVehicle *veh = (CVehicle*)ent; + int model = veh->GetModelIndex(); + int direction = TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking; + if(direction == LOOKING_FORWARD || ent->GetModelIndex() == MI_RHINO || ent->GetModelIndex() == MI_COACH || - TheCamera.m_bInATunnelAndABigVehicle){ + TheCamera.m_bInATunnelAndABigVehicle || + direction == LOOKING_BEHIND && veh->pHandling->Flags & HANDLING_UNKNOWN){ ent->bNoBrightHeadLights = true; - }else{ + return VIS_OFFSCREEN; + } + + if(direction != LOOKING_BEHIND || + !veh->IsBoat() || model == MI_REEFER || model == MI_TROPIC || model == MI_PREDATOR || model == MI_SKIMMER){ m_pFirstPersonVehicle = (CVehicle*)ent; ent->bNoBrightHeadLights = false; + return VIS_OFFSCREEN; } - return VIS_OFFSCREEN; } + // All sorts of Clumps if(ent->m_rwObject == nil || !ent->bIsVisible) return VIS_INVISIBLE; - if(!ent->GetIsOnScreen()) + if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()) return VIS_OFFSCREEN; if(ent->bDrawLast){ dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude(); @@ -395,22 +406,38 @@ CRenderer::SetupEntityVisibility(CEntity *ent) } return VIS_VISIBLE; } - if(ent->IsObject() && - ((CObject*)ent)->ObjectCreatedBy == TEMP_OBJECT){ + if(ent->bDontStream){ if(ent->m_rwObject == nil || !ent->bIsVisible) return VIS_INVISIBLE; - return ent->GetIsOnScreen() ? VIS_VISIBLE : VIS_OFFSCREEN; + if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()) + return VIS_OFFSCREEN; + if(ent->bDrawLast){ + dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude(); + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = false; + return VIS_INVISIBLE; + } + return VIS_VISIBLE; } } // Simple ModelInfo + if(!IsAreaVisible(ent->m_area)) + return VIS_INVISIBLE; + dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude(); - // This can only happen with multi-atomic models (e.g. railtracks) - // but why do we bump up the distance? can only be fading... - if(LOD_DISTANCE + STREAM_DISTANCE < dist && dist < mi->GetLargestLodDistance()) - dist = mi->GetLargestLodDistance(); +#ifndef FIX_BUGS + // Whatever this is supposed to do, it breaks fading for objects + // whose draw dist is > LOD_DISTANCE-FADE_DISTANCE, i.e. 280 + // because decreasing dist here makes the object visible above LOD_DISTANCE + // before fading normally once below LOD_DISTANCE. + // aha! this must be a workaround for the fact that we're not taking + // the LOD multiplier into account here anywhere + if(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE) + dist += mi->GetLargestLodDistance() - LOD_DISTANCE; +#endif if(ent->IsObject() && ent->bRenderDamaged) mi->m_isDamaged = true; @@ -430,7 +457,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent) if(ent->m_rwObject == nil || !ent->bIsVisible) return VIS_INVISIBLE; - if(!ent->GetIsOnScreen()){ + if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()){ mi->m_alpha = 255; return VIS_OFFSCREEN; } @@ -442,9 +469,10 @@ CRenderer::SetupEntityVisibility(CEntity *ent) } if(mi->m_drawLast || ent->bDrawLast){ - CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); - ent->bDistanceFade = false; - return VIS_INVISIBLE; + if(CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist)){ + ent->bDistanceFade = false; + return VIS_INVISIBLE; + } } return VIS_VISIBLE; } @@ -480,7 +508,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent) if(ent->m_rwObject == nil || !ent->bIsVisible) return VIS_INVISIBLE; - if(!ent->GetIsOnScreen()){ + if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()){ mi->m_alpha = 255; return VIS_OFFSCREEN; }else{ @@ -493,19 +521,32 @@ CRenderer::SetupEntityVisibility(CEntity *ent) int32 CRenderer::SetupBigBuildingVisibility(CEntity *ent) { - CSimpleModelInfo *mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex()); + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex); CTimeModelInfo *ti; int32 other; - if (mi->GetModelType() == MITYPE_TIME) { - ti = (CTimeModelInfo*)mi; + if(!IsAreaVisible(ent->m_area)) + return VIS_INVISIBLE; + + bool request = true; + if(mi->GetModelType() == MITYPE_TIME){ + ti = (CTimeModelInfo*)mi; other = ti->GetOtherTimeModel(); - // Hide objects not in time range if possible - if(CANTIMECULL) - if(!CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())) + if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){ + // don't fade in, or between time objects + if(CANTIMECULL) + ti->m_alpha = 255; + }else{ + // Hide if possible + if(CANTIMECULL){ + ent->DeleteRwObject(); return VIS_INVISIBLE; - // Draw like normal - } else if (mi->GetModelType() == MITYPE_VEHICLE) + } + // can't cull, so we'll try to draw this one, but don't request + // it since what we really want is the other one. + request = false; + } + }else if(mi->GetModelType() == MITYPE_VEHICLE) return ent->IsVisible() ? VIS_VISIBLE : VIS_INVISIBLE; float dist = (ms_vecCameraPosition-ent->GetPosition()).Magnitude(); @@ -514,7 +555,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // Find out whether to draw below near distance. // This is only the case if there is a non-LOD which is either not // loaded or not completely faded in yet. - if(dist < mi->GetNearDistance() && dist < LOD_DISTANCE + STREAM_DISTANCE){ + if(dist < mi->GetNearDistance() && dist < LOD_DISTANCE){ // No non-LOD or non-LOD is completely visible. if(nonLOD == nil || nonLOD->GetRwObject() && nonLOD->m_alpha == 255) @@ -522,7 +563,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // But if it is a time object, we'd rather draw the wrong // non-LOD than the right LOD. - if (nonLOD->GetModelType() == MITYPE_TIME) { + if(nonLOD->GetModelType() == MITYPE_TIME){ ti = (CTimeModelInfo*)nonLOD; other = ti->GetOtherTimeModel(); if(other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject()) @@ -530,7 +571,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) } } - RpAtomic *a = mi->GetAtomicFromDistance(dist); + RpAtomic *a = mi->GetFirstAtomicFromDistance(dist); if(a){ if(ent->m_rwObject == nil) ent->CreateRwObject(); @@ -541,8 +582,18 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // that of an atomic for another draw distance. if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) - if(!ent->IsVisibleComplex()) + mi->IncreaseAlpha(); + if(!ent->IsVisibleComplex() || ent->IsEntityOccluded()){ + mi->m_alpha = 255; return VIS_INVISIBLE; + } + + if(mi->m_alpha != 255){ + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = true; + return VIS_INVISIBLE; + } + if(mi->m_drawLast){ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); ent->bDistanceFade = false; @@ -558,10 +609,14 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // get faded atomic - a = mi->GetAtomicFromDistance(dist - FADE_DISTANCE); + a = mi->GetFirstAtomicFromDistance(dist - FADE_DISTANCE); if(a == nil){ - ent->DeleteRwObject(); - return VIS_INVISIBLE; + if(ent->bStreamBIGBuilding && dist-STREAM_DISTANCE < mi->GetLodDistance(0) && request){ + return ent->GetIsOnScreen() ? VIS_STREAMME : VIS_INVISIBLE; + }else{ + ent->DeleteRwObject(); + return VIS_INVISIBLE; + } } // Fade... @@ -571,14 +626,21 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject; if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) - if(ent->IsVisibleComplex()) - CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + mi->IncreaseAlpha(); + if(!ent->IsVisibleComplex() || ent->IsEntityOccluded()){ + mi->m_alpha = 255; + return VIS_INVISIBLE; + } + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = true; return VIS_INVISIBLE; } void CRenderer::ConstructRenderList(void) { + COcclusion::ProcessBeforeRendering(); + ms_nNoOfVisibleEntities = 0; ms_nNoOfInVisibleEntities = 0; ms_vecCameraPosition = TheCamera.GetPosition(); @@ -638,6 +700,15 @@ CRenderer::ScanWorld(void) CVisibilityPlugins::InitAlphaEntityList(); CWorld::AdvanceCurrentScanCode(); + // unused + static CVector prevPos; + static CVector prevFwd; + static bool smallMovement; + smallMovement = (TheCamera.GetPosition() - prevPos).MagnitudeSqr() < SQR(4.0f) && + DotProduct(TheCamera.GetForward(), prevFwd) > 0.98f; + prevPos = TheCamera.GetPosition(); + prevFwd = TheCamera.GetForward(); + if(cammatrix->at.z > 0.0f){ // looking up, bottom corners are further away vectors[CORNER_LOD_LEFT] = vectors[CORNER_FAR_BOTLEFT] * LOD_DISTANCE/f; @@ -683,6 +754,7 @@ CRenderer::ScanWorld(void) for(int y = y1; y <= y2; y++) ScanSectorList(CWorld::GetSector(x1, y)->m_lists); }else{ +#ifdef GTA_TRAIN CVehicle *train = FindPlayerTrain(); if(train && train->GetPosition().z < 0.0f){ poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); @@ -692,7 +764,9 @@ CRenderer::ScanWorld(void) poly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x); poly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y); ScanSectorPoly(poly, 3, ScanSectorList_Subway); - }else{ + }else +#endif + { if(f > LOD_DISTANCE){ // priority poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); @@ -720,19 +794,8 @@ CRenderer::ScanWorld(void) poly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y); ScanSectorPoly(poly, 3, ScanSectorList); } -#ifdef NO_ISLAND_LOADING - if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_HIGH) { - ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL)); - ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_COMMERCIAL)); - ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_SUBURBAN)); - } else -#endif - { - #ifdef FIX_BUGS - if (CCollision::ms_collisionInMemory != LEVEL_GENERIC) - #endif - ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory)); - } + + ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel)); ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC)); } } @@ -764,6 +827,7 @@ CRenderer::RequestObjectsInFrustum(void) cammatrix = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); CWorld::AdvanceCurrentScanCode(); + ms_vecCameraPosition = TheCamera.GetPosition(); if(cammatrix->at.z > 0.0f){ // looking up, bottom corners are further away @@ -982,11 +1046,26 @@ CRenderer::ScanBigBuildingList(CPtrList &list) { CPtrNode *node; CEntity *ent; + int vis; + int f = CTimer::GetFrameCounter() & 3; for(node = list.first; node; node = node->next){ ent = (CEntity*)node->item; - if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE) + if(ent->bOffscreen || (ent->m_randomSeed&3) != f){ + ent->bOffscreen = true; + vis = SetupBigBuildingVisibility(ent); + }else + vis = VIS_VISIBLE; + switch(vis){ + case VIS_VISIBLE: ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + ent->bOffscreen = false; + break; + case VIS_STREAMME: + if(!CStreaming::ms_disableStreaming) + CStreaming::RequestModel(ent->GetModelIndex(), 0); + break; + } } } @@ -1006,35 +1085,30 @@ CRenderer::ScanSectorList(CPtrList *lists) if(ent->m_scanCode == CWorld::GetCurrentScanCode()) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); + ent->bOffscreen = false; - if(IsEntityCullZoneVisible(ent)) - switch(SetupEntityVisibility(ent)){ - case VIS_VISIBLE: - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; - break; - case VIS_INVISIBLE: - if(!IsGlass(ent->GetModelIndex())) - break; - // fall through - case VIS_OFFSCREEN: - dx = ms_vecCameraPosition.x - ent->GetPosition().x; - dy = ms_vecCameraPosition.y - ent->GetPosition().y; - if(dx > -65.0f && dx < 65.0f && - dy > -65.0f && dy < 65.0f && - ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1) - ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent; - break; - case VIS_STREAMME: - if(!CStreaming::ms_disableStreaming) - if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) - CStreaming::RequestModel(ent->GetModelIndex(), 0); + switch(SetupEntityVisibility(ent)){ + case VIS_VISIBLE: + ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + break; + case VIS_INVISIBLE: + if(!IsGlass(ent->GetModelIndex())) break; - } - else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ + // fall through + case VIS_OFFSCREEN: + ent->bOffscreen = true; + dx = ms_vecCameraPosition.x - ent->GetPosition().x; + dy = ms_vecCameraPosition.y - ent->GetPosition().y; + if(dx > -30.0f && dx < 30.0f && + dy > -30.0f && dy < 30.0f && + ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1) + ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent; + break; + case VIS_STREAMME: if(!CStreaming::ms_disableStreaming) - if(SetupEntityVisibility(ent) == VIS_STREAMME) - if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) - CStreaming::RequestModel(ent->GetModelIndex(), 0); + if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) + CStreaming::RequestModel(ent->GetModelIndex(), 0); + break; } } } @@ -1056,41 +1130,38 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) if(ent->m_scanCode == CWorld::GetCurrentScanCode()) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); + ent->bOffscreen = false; - if(IsEntityCullZoneVisible(ent)) - switch(SetupEntityVisibility(ent)){ - case VIS_VISIBLE: - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; - break; - case VIS_INVISIBLE: - if(!IsGlass(ent->GetModelIndex())) - break; - // fall through - case VIS_OFFSCREEN: - dx = ms_vecCameraPosition.x - ent->GetPosition().x; - dy = ms_vecCameraPosition.y - ent->GetPosition().y; - if(dx > -65.0f && dx < 65.0f && - dy > -65.0f && dy < 65.0f && - ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1) - ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent; - break; - case VIS_STREAMME: - if(!CStreaming::ms_disableStreaming){ - CStreaming::RequestModel(ent->GetModelIndex(), 0); - if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED) - m_loadingPriority = true; - } + switch(SetupEntityVisibility(ent)){ + case VIS_VISIBLE: + ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + break; + case VIS_INVISIBLE: + if(!IsGlass(ent->GetModelIndex())) break; + // fall through + case VIS_OFFSCREEN: + ent->bOffscreen = true; + dx = ms_vecCameraPosition.x - ent->GetPosition().x; + dy = ms_vecCameraPosition.y - ent->GetPosition().y; + if(dx > -30.0f && dx < 30.0f && + dy > -30.0f && dy < 30.0f && + ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1) + ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent; + break; + case VIS_STREAMME: + if(!CStreaming::ms_disableStreaming){ + CStreaming::RequestModel(ent->GetModelIndex(), 0); + if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED) + m_loadingPriority = true; } - else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ - if(!CStreaming::ms_disableStreaming) - if(SetupEntityVisibility(ent) == VIS_STREAMME) - CStreaming::RequestModel(ent->GetModelIndex(), 0); + break; } } } } +#ifdef GTA_TRAIN void CRenderer::ScanSectorList_Subway(CPtrList *lists) { @@ -1107,15 +1178,17 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists) if(ent->m_scanCode == CWorld::GetCurrentScanCode()) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); + ent->bOffscreen = false; switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; break; case VIS_OFFSCREEN: + ent->bOffscreen = true; dx = ms_vecCameraPosition.x - ent->GetPosition().x; dy = ms_vecCameraPosition.y - ent->GetPosition().y; - if(dx > -65.0f && dx < 65.0f && - dy > -65.0f && dy < 65.0f && + if(dx > -30.0f && dx < 30.0f && + dy > -30.0f && dy < 30.0f && ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1) ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent; break; @@ -1123,6 +1196,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists) } } } +#endif void CRenderer::ScanSectorList_RequestModels(CPtrList *lists) @@ -1139,8 +1213,7 @@ CRenderer::ScanSectorList_RequestModels(CPtrList *lists) if(ent->m_scanCode == CWorld::GetCurrentScanCode()) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); - if(IsEntityCullZoneVisible(ent)) - if(ShouldModelBeStreamed(ent)) + if(ShouldModelBeStreamed(ent, ms_vecCameraPosition)) CStreaming::RequestModel(ent->GetModelIndex(), 0); } } @@ -1175,70 +1248,29 @@ CRenderer::SortBIGBuildingsForSectorList(CPtrList *list) } bool -CRenderer::ShouldModelBeStreamed(CEntity *ent) +CRenderer::ShouldModelBeStreamed(CEntity *ent, const CVector &campos) { - CSimpleModelInfo *mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex()); - float dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude(); + if(!IsAreaVisible(ent->m_area)) + return false; + CTimeModelInfo *mi = (CTimeModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex()); + if(mi->GetModelType() == MITYPE_TIME) + if(!CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())) + return false; + float dist = (ent->GetPosition() - campos).Magnitude(); if(mi->m_noFade) return dist - STREAM_DISTANCE < mi->GetLargestLodDistance(); else return dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance(); } -bool -CRenderer::IsEntityCullZoneVisible(CEntity *ent) -{ - CPed *ped; - CObject *obj; - - if(ent->bZoneCulled) - return false; - - switch(ent->GetType()){ - case ENTITY_TYPE_VEHICLE: - return IsVehicleCullZoneVisible(ent); - case ENTITY_TYPE_PED: - ped = (CPed*)ent; - if (ped->bInVehicle) { - if (ped->m_pMyVehicle) - return IsVehicleCullZoneVisible(ped->m_pMyVehicle); - else - return true; - } - return !(ped->m_pCurSurface && ped->m_pCurSurface->bZoneCulled2); - case ENTITY_TYPE_OBJECT: - obj = (CObject*)ent; - if(!obj->GetIsStatic()) - return true; - return !(obj->m_pCurSurface && obj->m_pCurSurface->bZoneCulled2); - default: break; - } - return true; -} - -bool -CRenderer::IsVehicleCullZoneVisible(CEntity *ent) -{ - CVehicle *v = (CVehicle*)ent; - switch(v->GetStatus()) { - case STATUS_SIMPLE: - case STATUS_PHYSICS: - case STATUS_ABANDONED: - case STATUS_WRECKED: - return !(v->m_pCurGroundEntity && v->m_pCurGroundEntity->bZoneCulled2); - default: break; - } - return true; -} - void CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset) { - if(ent->bRenderScorched){ - WorldReplaceScorchedLightsWithNormal(Scene.world); - return; + if(!ent->bRenderScorched){ + CPointLights::RemoveLightsAffectingObject(); + if(reset) + ReSetAmbientAndDirectionalColours(); } - CPointLights::RemoveLightsAffectingObject(); - if(reset) - ReSetAmbientAndDirectionalColours(); + SetAmbientColours(); + DeActivateDirectional(); } diff --git a/src/render/Renderer.h b/src/render/Renderer.h index 362741e3..e9f82078 100644 --- a/src/render/Renderer.h +++ b/src/render/Renderer.h @@ -2,11 +2,8 @@ class CEntity; -extern bool gbShowPedRoadGroups; -extern bool gbShowCarRoadGroups; extern bool gbShowCollisionPolys; extern bool gbShowCollisionLines; -extern bool gbShowCullZoneDebugStuff; extern bool gbBigWhiteDebugLightSwitchedOn; extern bool gbDontRenderBuildings; @@ -38,8 +35,8 @@ public: static void RenderRoads(void); static void RenderFadingInEntities(void); + static void RenderFadingInUnderwaterEntities(void); static void RenderEverythingBarRoads(void); - static void RenderVehiclesButNotBoats(void); static void RenderBoats(void); static void RenderOneRoad(CEntity *); static void RenderOneNonRoad(CEntity *); @@ -63,9 +60,7 @@ public: static void SortBIGBuildings(void); static void SortBIGBuildingsForSectorList(CPtrList *list); - static bool ShouldModelBeStreamed(CEntity *ent); - static bool IsEntityCullZoneVisible(CEntity *ent); - static bool IsVehicleCullZoneVisible(CEntity *ent); + static bool ShouldModelBeStreamed(CEntity *ent, const CVector &campos); static void RemoveVehiclePedLights(CEntity *ent, bool reset); }; diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp index bfd50c07..dada2439 100644 --- a/src/render/Rubbish.cpp +++ b/src/render/Rubbish.cpp @@ -8,17 +8,18 @@ #include "World.h" #include "Vehicle.h" #include "ZoneCull.h" +#include "Stats.h" #include "TxdStore.h" #include "RenderBuffer.h" #include "Rubbish.h" -#define RUBBISH_MAX_DIST (18.0f) -#define RUBBISH_FADE_DIST (16.5f) +//--MIAMI: file done + +#define RUBBISH_MAX_DIST (23.0f) +#define RUBBISH_FADE_DIST (20.0f) 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]; @@ -52,12 +53,16 @@ CRubbish::Render(void) { int type; + if(RubbishVisibility == 0) + return; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); for(type = 0; type < 4; type++){ - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type])); + if(type < 3 || CStats::PamphletMissionPassed) + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type])); TempBufferIndicesStored = 0; TempBufferVerticesStored = 0; @@ -69,7 +74,7 @@ CRubbish::Render(void) if(sheet->m_state == 0) continue; - uint32 alpha = 128; + uint32 alpha = 100; CVector pos; if(sheet->m_state == 1){ pos = sheet->m_basePos; @@ -82,7 +87,7 @@ CRubbish::Render(void) 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); + alpha = 100 * (f1+f2); } } @@ -92,17 +97,27 @@ CRubbish::Render(void) 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; + float vx1, vy1, vx2, vy2; + if(type == 0 || type == 1){ + vx1 = 0.9f*Sin(sheet->m_angle); + vy1 = 0.9f*Cos(sheet->m_angle); + vx2 = 0.3f*Cos(sheet->m_angle); + vy2 = -0.3f*Sin(sheet->m_angle); + }else{ + vx1 = 0.3f*Sin(sheet->m_angle); + vy1 = 0.3f*Cos(sheet->m_angle); + vx2 = 0.3f*Cos(sheet->m_angle); + vy2 = -0.3f*Sin(sheet->m_angle); + } int v = TempBufferVerticesStored; - RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx, pos.y + vy, pos.z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx1 + vx2, pos.y + vy1 + vy2, pos.z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x + vx1 - vx2, pos.y + vy1 - vy2, pos.z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x - vx1 + vx2, pos.y - vy1 + vy2, pos.z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx1 - vx2, pos.y - vy1 - vy2, 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); @@ -373,24 +388,6 @@ CRubbish::Init(void) 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; @@ -414,19 +411,11 @@ void CRubbish::Shutdown(void) { RwTextureDestroy(gpRubbishTexture[0]); -#ifdef GTA3_1_1_PATCH gpRubbishTexture[0] = nil; -#endif RwTextureDestroy(gpRubbishTexture[1]); -#ifdef GTA3_1_1_PATCH gpRubbishTexture[1] = nil; -#endif RwTextureDestroy(gpRubbishTexture[2]); -#ifdef GTA3_1_1_PATCH gpRubbishTexture[2] = nil; -#endif RwTextureDestroy(gpRubbishTexture[3]); -#ifdef GTA3_1_1_PATCH gpRubbishTexture[3] = nil; -#endif } diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h index 37f895f3..5a4e479b 100644 --- a/src/render/Rubbish.h +++ b/src/render/Rubbish.h @@ -53,3 +53,5 @@ public: static void Init(void); static void Shutdown(void); }; + +extern RwTexture *gpRubbishTexture[4]; diff --git a/src/render/ShadowCamera.cpp b/src/render/ShadowCamera.cpp new file mode 100644 index 00000000..f69c234f --- /dev/null +++ b/src/render/ShadowCamera.cpp @@ -0,0 +1,549 @@ +#include "common.h" +#include "rwcore.h" +#include "ShadowCamera.h" +#include "RwHelper.h" + +#define TEXELOFFSET 0.5f + +RpAtomic *ShadowRenderCallBack(RpAtomic *atomic, void *data) +{ + RpAtomicCallBackRender savedCB = RpAtomicGetRenderCallBack(atomic); + RpAtomicSetRenderCallBack(atomic, AtomicDefaultRenderCallBack); + RpAtomicRender(atomic); + RpAtomicSetRenderCallBack(atomic, savedCB); + return atomic; +} + +CShadowCamera::CShadowCamera() +{ + m_pCamera = nil; + m_pTexture = nil; +} + +CShadowCamera::~CShadowCamera() +{ + Destroy(); +} + +void +CShadowCamera::Destroy() +{ + if ( m_pCamera ) + { + RwRaster *raster; + RwFrame *frame; + + frame = RwCameraGetFrame(m_pCamera); + + if ( frame ) + { + RwCameraSetFrame(m_pCamera, nil); + RwFrameDestroy(frame); + } + + raster = RwCameraGetZRaster(m_pCamera); + if ( raster ) + { + RwCameraSetZRaster(m_pCamera, nil); + RwRasterDestroy(raster); + } + + raster = RwCameraGetRaster(m_pCamera); + if ( raster ) + { + RwCameraSetRaster(m_pCamera, nil); + RwRasterDestroy(raster); + } + + if ( m_pTexture ) + { + RwTextureSetRaster(m_pTexture, nil); + RwTextureDestroy(m_pTexture); + m_pTexture = nil; + } + + RwCameraDestroy(m_pCamera); + m_pCamera = nil; + } + return; +} + +RwCamera * +CShadowCamera::Create(int32 rasterSize) +{ + int32 size = 1 << rasterSize; + + m_pCamera = RwCameraCreate(); + ASSERT(m_pCamera != nil); + + if ( m_pCamera ) + { + RwCameraSetFrame(m_pCamera, RwFrameCreate()); + + if( RwCameraGetFrame(m_pCamera) ) + { + RwRaster *zRaster = RwRasterCreate(size, size, 0, rwRASTERTYPEZBUFFER); + ASSERT(zRaster != nil); + + if ( zRaster ) + { + RwCameraSetZRaster(m_pCamera, zRaster); + + RwRaster *raster = RwRasterCreate(size, size, 0, rwRASTERTYPECAMERATEXTURE); + ASSERT(raster != nil); + + if ( raster ) + { + RwCameraSetRaster(m_pCamera, raster); + m_pTexture = RwTextureCreate(raster); + ASSERT(m_pTexture != nil); + + if ( m_pTexture ) + { + RwTextureSetAddressing(m_pTexture, rwTEXTUREADDRESSCLAMP); + RwTextureSetFilterMode(m_pTexture, rwFILTERLINEAR); + RwCameraSetProjection(m_pCamera, rwPARALLEL); + return (m_pCamera); + } + } + } + } + } + + Destroy(); + + return (nil); +} + +RwCamera * +CShadowCamera::SetFrustum(float objectRadius) +{ + ASSERT(m_pCamera != nil); + + RwV2d vw; + + RwCameraSetFarClipPlane (m_pCamera, 2.0f * objectRadius); + RwCameraSetNearClipPlane(m_pCamera, 0.001f * objectRadius); + + vw.x = objectRadius; + vw.y = objectRadius; + RwCameraSetViewWindow(m_pCamera, &vw); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::SetLight(RpLight *light) +{ + ASSERT(light != nil); + ASSERT(m_pCamera != nil); + + RwFrame *camFrame = RwCameraGetFrame(m_pCamera); + RwMatrix *camMatrix = RwFrameGetMatrix(camFrame); + RwFrame *lightFrame = RpLightGetFrame(light); + RwMatrix *lightMatrix = RwFrameGetMatrix(lightFrame); + + *RwMatrixGetRight(camMatrix) = *RwMatrixGetRight(lightMatrix); + *RwMatrixGetUp(camMatrix) = *RwMatrixGetUp(lightMatrix); + *RwMatrixGetAt(camMatrix) = *RwMatrixGetAt(lightMatrix); + + RwMatrixUpdate(camMatrix); + RwFrameUpdateObjects(camFrame); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::SetCenter(RwV3d *center) +{ + ASSERT(center != nil); + ASSERT(m_pCamera != nil); + + RwFrame *camFrame = RwCameraGetFrame(m_pCamera); + RwMatrix *camMatrix = RwFrameGetMatrix(camFrame); + + *RwMatrixGetPos(camMatrix) = *center; + + RwV3dIncrementScaled(RwMatrixGetPos(camMatrix), RwMatrixGetAt(camMatrix), -0.5f * RwCameraGetFarClipPlane(m_pCamera)); + + RwMatrixUpdate(camMatrix); + RwFrameUpdateObjects(camFrame); + RwFrameOrthoNormalize(camFrame); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::Update(RpClump *clump) +{ + ASSERT(clump != nil); + ASSERT(m_pCamera != nil); + + RwUInt32 flags; + RpGeometry *geometry; + + RwRGBA bgColor = { 255, 255, 255, 0 }; + + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + geometry = RpAtomicGetGeometry(GetFirstAtomic(clump)); + ASSERT(geometry != nil); + + flags = RpGeometryGetFlags(geometry); + + RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT + |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR)); + + RpClumpForAllAtomics(clump, ShadowRenderCallBack, nil); + + RpGeometrySetFlags(geometry, flags); + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + + return m_pCamera; +} + +RwCamera * +CShadowCamera::Update(RpAtomic *atomic) +{ + ASSERT(atomic != nil); + ASSERT(m_pCamera != nil); + + RwUInt32 flags; + RpGeometry *geometry; + + RwRGBA bgColor = { 255, 255, 255, 0 }; + + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + geometry = RpAtomicGetGeometry(atomic); + ASSERT(geometry != nil); + flags = RpGeometryGetFlags(geometry); + + RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT + |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYNORMALS)); + + ShadowRenderCallBack(atomic, nil); + + RpGeometrySetFlags(geometry, flags); + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + + return m_pCamera; +} + +void +CShadowCamera::InvertRaster() +{ + ASSERT(m_pCamera != nil); + + RwIm2DVertex vx[4]; + float crw, crh; + RwRaster *raster; + float recipZ; + + raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + crw = (float)RwRasterGetWidth(raster); + crh = (float)RwRasterGetHeight(raster); + + recipZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], 0.0f); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipZ); + RwIm2DVertexSetIntRGBA (&vx[0], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[1], 0.0f); + RwIm2DVertexSetScreenY (&vx[1], crh); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipZ); + RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[2], crw); + RwIm2DVertexSetScreenY (&vx[2], 0.0f); + RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ); + RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[3], crw); + RwIm2DVertexSetScreenY (&vx[3], crh); + RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ); + RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255); + + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + + RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); +} + +RwRaster * +CShadowCamera::MakeGradientRaster() +{ + ASSERT(m_pCamera != nil); + + RwIm2DVertex vx[2]; + + if ( !m_pCamera ) + return nil; + + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float width = (float)RwRasterGetWidth(raster); + float height = (float)RwRasterGetHeight(raster); + + if ( height < 1 ) + return nil; + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)rwFILTERNAFILTERMODE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT); + + float color = 255.0f; + float step = (-191.0f / height); + + for ( int32 i = 0; i < height; i++ ) + { + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], i); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + RwIm2DVertexSetIntRGBA (&vx[0], (uint32)color, (uint32)color, (uint32)color, (uint32)color); + + RwIm2DVertexSetScreenX (&vx[1], width - 1); + RwIm2DVertexSetScreenY (&vx[1], i); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + RwIm2DVertexSetIntRGBA (&vx[1], (uint32)color, (uint32)color, (uint32)color, (uint32)color); + + RwIm2DRenderLine(vx, 2, 0, 1); + + color += step; + } + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEGOURAUD); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} + +RwRaster * +CShadowCamera::RasterResample(RwRaster *dstRaster) +{ + ASSERT(dstRaster != nil); + ASSERT(m_pCamera != nil); + + if ( !m_pCamera ) + return nil; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float) RwRasterGetWidth(raster); + float uvOffset = TEXELOFFSET / size; + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster); + + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, uvOffset); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} + +RwRaster * +CShadowCamera::RasterBlur(RwRaster *dstRaster, int32 numPasses) +{ + ASSERT(dstRaster != nil); + ASSERT(m_pCamera != nil); + + if ( !m_pCamera ) + return nil; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float) RwRasterGetWidth(dstRaster); + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + for (int i = 0; i < numPasses; i++ ) + { + RwCameraSetRaster(m_pCamera, raster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + if ( i == 0 ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + } + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster); + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 1.0f / size); + RwCameraEndUpdate(m_pCamera); + } + + RwCameraSetRaster(m_pCamera, dstRaster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster); + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0); + + if ( i == numPasses - 1 ) + { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + } + + RwCameraEndUpdate(m_pCamera); + } + } + + RwCameraSetRaster(m_pCamera, raster); + + return dstRaster; +} + +RwRaster * +CShadowCamera::RasterGradient(RwRaster *dstRaster) +{ + ASSERT(dstRaster != nil); + ASSERT(m_pCamera != nil); + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float)RwRasterGetWidth(dstRaster); + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwCameraSetRaster(m_pCamera, dstRaster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDSRCCOLOR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster); + + Im2DRenderQuad(0, 0, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + RwCameraEndUpdate(m_pCamera); + } + + RwCameraSetRaster(m_pCamera, raster); + + return dstRaster; +} + +RwRaster *CShadowCamera::DrawOutlineBorder(RwRGBA const& color) +{ + ASSERT(m_pCamera != nil); + + RwIm2DVertex vx[4]; + RwImVertexIndex ix[5]; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != nil); + + float size = (float)RwRasterGetWidth(raster) - 1.0f; + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], 0.0f); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[0], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[1], size); + RwIm2DVertexSetScreenY (&vx[1], 0.0f); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[1], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[2], size); + RwIm2DVertexSetScreenY (&vx[2], size); + RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[2], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[3], 0.0f); + RwIm2DVertexSetScreenY (&vx[3], size); + RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[3], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ); + + ix[0] = 0; + ix[4] = 0; + ix[1] = 1; + ix[2] = 2; + ix[3] = 3; + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)nil); + + RwIm2DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, vx, 4, ix, 5); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +}
\ No newline at end of file diff --git a/src/render/ShadowCamera.h b/src/render/ShadowCamera.h new file mode 100644 index 00000000..a2149db7 --- /dev/null +++ b/src/render/ShadowCamera.h @@ -0,0 +1,54 @@ +#pragma once + + +class CShadowCamera +{ +public: + RwCamera *m_pCamera; + RwTexture *m_pTexture; + + CShadowCamera(); + ~CShadowCamera(); + + RwCamera *Create(int32 rasterSize); + void Destroy(); + + RwCamera *SetFrustum(float objectRadius); + RwCamera *SetLight(RpLight *light); + RwCamera *SetCenter(RwV3d *center); + + RwCamera *Update(RpClump *clump); + RwCamera *Update(RpAtomic *atomic); + + void InvertRaster(); + + RwRaster* GetRwRenderRaster() + { + return RwCameraGetRaster(m_pCamera); + } + + // ShadowRasterRender(RwV2d *) + // ApplyAlphaMapToRaster(void) + + RwRaster *MakeGradientRaster(); + + RwTexture *GetRwRenderTexture() + { + return m_pTexture; + } + + RwRaster* GetRwZRaster() + { + return RwCameraGetZRaster(m_pCamera); + } + + RwRaster *RasterResample(RwRaster *dstRaster); + RwRaster *RasterBlur(RwRaster *dstRaster, int32 numPasses); + RwRaster *RasterGradient(RwRaster *dstRaster); + RwRaster *DrawOutlineBorder(RwRGBA const& color); + + RwCamera *GetRwCamera() + { + return m_pCamera; + } +};
\ No newline at end of file diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 8c892be3..a964ceb6 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -7,6 +7,7 @@ #include "Timecycle.h" #include "CutsceneMgr.h" #include "Automobile.h" +#include "Bike.h" #include "Ped.h" #include "PlayerPed.h" #include "World.h" @@ -18,7 +19,12 @@ #endif #include "PointLights.h" #include "SpecialFX.h" +#include "Script.h" +#include "TimeStep.h" #include "Shadows.h" +#include "CutsceneObject.h" +#include "CutsceneShadow.h" +#include "Clock.h" #ifdef DEBUGMENU SETTWEAKPATH("Shadows"); @@ -30,6 +36,8 @@ RwImVertexIndex ShadowIndexList[24]; RwTexture *gpShadowCarTex; RwTexture *gpShadowPedTex; RwTexture *gpShadowHeliTex; +RwTexture *gpShadowBikeTex; +RwTexture *gpShadowBaronTex; RwTexture *gpShadowExplosionTex; RwTexture *gpShadowHeadLightsTex; RwTexture *gpOutline1Tex; @@ -37,7 +45,6 @@ RwTexture *gpOutline2Tex; RwTexture *gpOutline3Tex; RwTexture *gpBloodPoolTex; RwTexture *gpReflectionTex; -RwTexture *gpGoalMarkerTex; RwTexture *gpWalkDontTex; RwTexture *gpCrackedGlassTex; RwTexture *gpPostShadowTex; @@ -59,37 +66,39 @@ CShadows::Init(void) int32 slut = CTxdStore::FindTxdSlot("particle"); CTxdStore::SetCurrentTxd(slut); - gpShadowCarTex = RwTextureRead("shad_car", NULL); - gpShadowPedTex = RwTextureRead("shad_ped", NULL); - gpShadowHeliTex = RwTextureRead("shad_heli", NULL); - gpShadowExplosionTex = RwTextureRead("shad_exp", NULL); - gpShadowHeadLightsTex = RwTextureRead("headlight", NULL); - gpOutline1Tex = RwTextureRead("outline_64", NULL); - gpOutline2Tex = RwTextureRead("outline2_64", NULL); - gpOutline3Tex = RwTextureRead("outline3_64", NULL); - gpBloodPoolTex = RwTextureRead("bloodpool_64", NULL); - gpReflectionTex = RwTextureRead("reflection01", NULL); - gpGoalMarkerTex = RwTextureRead("goal", NULL); - gpWalkDontTex = RwTextureRead("walk_dont", NULL); - gpCrackedGlassTex = RwTextureRead("wincrack_32", NULL); - gpPostShadowTex = RwTextureRead("lamp_shad_64", NULL); + gpShadowCarTex = RwTextureRead("shad_car", nil); + gpShadowPedTex = RwTextureRead("shad_ped", nil); + gpShadowHeliTex = RwTextureRead("shad_heli", nil); + gpShadowBikeTex = RwTextureRead("shad_bike", nil); + gpShadowBaronTex = RwTextureRead("shad_rcbaron", nil); + gpShadowExplosionTex = RwTextureRead("shad_exp", nil); + gpShadowHeadLightsTex = RwTextureRead("headlight", nil); + gpOutline1Tex = RwTextureRead("outline_64", nil); + gpOutline2Tex = RwTextureRead("outline2_64", nil); + gpOutline3Tex = RwTextureRead("outline3_64", nil); + gpBloodPoolTex = RwTextureRead("bloodpool_64", nil); + gpReflectionTex = RwTextureRead("reflection01", nil); + gpWalkDontTex = RwTextureRead("walk_dont", nil); + gpCrackedGlassTex = RwTextureRead("wincrack_32", nil); + gpPostShadowTex = RwTextureRead("lamp_shad_64", nil); CTxdStore::PopCurrentTxd(); - ASSERT(gpShadowCarTex != NULL); - ASSERT(gpShadowPedTex != NULL); - ASSERT(gpShadowHeliTex != NULL); - ASSERT(gpShadowExplosionTex != NULL); - ASSERT(gpShadowHeadLightsTex != NULL); - ASSERT(gpOutline1Tex != NULL); - ASSERT(gpOutline2Tex != NULL); - ASSERT(gpOutline3Tex != NULL); - ASSERT(gpBloodPoolTex != NULL); - ASSERT(gpReflectionTex != NULL); - ASSERT(gpGoalMarkerTex != NULL); - ASSERT(gpWalkDontTex != NULL); - ASSERT(gpCrackedGlassTex != NULL); - ASSERT(gpPostShadowTex != NULL); + ASSERT(gpShadowCarTex != nil); + ASSERT(gpShadowPedTex != nil); + ASSERT(gpShadowHeliTex != nil); + ASSERT(gpShadowBikeTex != nil); + ASSERT(gpShadowBaronTex != nil); + ASSERT(gpShadowExplosionTex != nil); + ASSERT(gpShadowHeadLightsTex != nil); + ASSERT(gpOutline1Tex != nil); + ASSERT(gpOutline2Tex != nil); + ASSERT(gpOutline3Tex != nil); + ASSERT(gpBloodPoolTex != nil); + ASSERT(gpReflectionTex != nil); + ASSERT(gpWalkDontTex != nil); + ASSERT(gpCrackedGlassTex != nil); + ASSERT(gpPostShadowTex != nil); ShadowIndexList[0] = 0; @@ -128,7 +137,7 @@ CShadows::Init(void) for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ ) { aStaticShadows[i].m_nId = 0; - aStaticShadows[i].m_pPolyBunch = NULL; + aStaticShadows[i].m_pPolyBunch = nil; } pEmptyBunchList = &aPolyBunches[0]; @@ -136,7 +145,7 @@ CShadows::Init(void) for ( int32 i = 0; i < MAX_POLYBUNCHES; i++ ) { if ( i == MAX_POLYBUNCHES - 1 ) - aPolyBunches[i].m_pNext = NULL; + aPolyBunches[i].m_pNext = nil; else aPolyBunches[i].m_pNext = &aPolyBunches[i + 1]; } @@ -150,24 +159,27 @@ CShadows::Init(void) void CShadows::Shutdown(void) { - ASSERT(gpShadowCarTex != NULL); - ASSERT(gpShadowPedTex != NULL); - ASSERT(gpShadowHeliTex != NULL); - ASSERT(gpShadowExplosionTex != NULL); - ASSERT(gpShadowHeadLightsTex != NULL); - ASSERT(gpOutline1Tex != NULL); - ASSERT(gpOutline2Tex != NULL); - ASSERT(gpOutline3Tex != NULL); - ASSERT(gpBloodPoolTex != NULL); - ASSERT(gpReflectionTex != NULL); - ASSERT(gpGoalMarkerTex != NULL); - ASSERT(gpWalkDontTex != NULL); - ASSERT(gpCrackedGlassTex != NULL); - ASSERT(gpPostShadowTex != NULL); + ASSERT(gpShadowCarTex != nil); + ASSERT(gpShadowPedTex != nil); + ASSERT(gpShadowHeliTex != nil); + ASSERT(gpShadowBikeTex != nil); + ASSERT(gpShadowBaronTex != nil); + ASSERT(gpShadowExplosionTex != nil); + ASSERT(gpShadowHeadLightsTex != nil); + ASSERT(gpOutline1Tex != nil); + ASSERT(gpOutline2Tex != nil); + ASSERT(gpOutline3Tex != nil); + ASSERT(gpBloodPoolTex != nil); + ASSERT(gpReflectionTex != nil); + ASSERT(gpWalkDontTex != nil); + ASSERT(gpCrackedGlassTex != nil); + ASSERT(gpPostShadowTex != nil); RwTextureDestroy(gpShadowCarTex); RwTextureDestroy(gpShadowPedTex); RwTextureDestroy(gpShadowHeliTex); + RwTextureDestroy(gpShadowBikeTex); + RwTextureDestroy(gpShadowBaronTex); RwTextureDestroy(gpShadowExplosionTex); RwTextureDestroy(gpShadowHeadLightsTex); RwTextureDestroy(gpOutline1Tex); @@ -175,7 +187,6 @@ CShadows::Shutdown(void) RwTextureDestroy(gpOutline3Tex); RwTextureDestroy(gpBloodPoolTex); RwTextureDestroy(gpReflectionTex); - RwTextureDestroy(gpGoalMarkerTex); RwTextureDestroy(gpWalkDontTex); RwTextureDestroy(gpCrackedGlassTex); RwTextureDestroy(gpPostShadowTex); @@ -187,8 +198,8 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale) { - ASSERT(pTexture != NULL); - ASSERT(pPosn != NULL); + ASSERT(pTexture != nil); + ASSERT(pPosn != nil); // find free slot @@ -215,36 +226,39 @@ CShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPo } } -void +bool CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D(); - if ( SQR(fDrawDistance) > fDistToCamSqr) + if ( SQR(fDrawDistance) > fDistToCamSqr || fDrawDistance == 0.0f ) { - float fDistToCam = Sqrt(fDistToCamSqr); - - if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) + if ( fDrawDistance != 0.0f ) { - //fDistToCam == 0 -> 4 - //fDistToCam == fDrawDistance -> 0 - float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))); + float fDistToCam = Sqrt(fDistToCamSqr); - nIntensity = (int32)(nIntensity * fMult); - nRed = (int32)(nRed * fMult); - nGreen = (int32)(nGreen * fMult); - nBlue = (int32)(nBlue * fMult); + if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) + { + //fDistToCam == 0 -> 4 + //fDistToCam == fDrawDistance -> 0 + float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))); + + nIntensity = (int32)(nIntensity * fMult); + nRed = (int32)(nRed * fMult); + nGreen = (int32)(nGreen * fMult); + nBlue = (int32)(nBlue * fMult); + } } int32 nSlot; nSlot = 0; - while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != NULL) ) + while ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != nil) ) nSlot++; if ( nSlot < MAX_STATICSHADOWS ) @@ -263,8 +277,10 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_fScale = fScale; aStaticShadows[nSlot].m_bTemp = bTempShadow; aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); + + return true; } - else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f + else if ( Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f && Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < 0.05f && Abs(pPosn->z - aStaticShadows[nSlot].m_vecPosn.z) < 2.0f @@ -284,6 +300,8 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_fScale = fScale; aStaticShadows[nSlot].m_bTemp = bTempShadow; aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); + + return true; } else { @@ -308,12 +326,14 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); GeneratePolysForStaticShadow(nSlot); + + return aStaticShadows[nSlot].m_pPolyBunch != nil; } } else { nSlot = 0; - while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != NULL ) + while ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != nil ) nSlot++; if ( nSlot != MAX_STATICSHADOWS ) @@ -337,9 +357,13 @@ CShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, C aStaticShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds(); GeneratePolysForStaticShadow(nSlot); + + return aStaticShadows[nSlot].m_pPolyBunch != nil; } } } + + return true; } void @@ -347,7 +371,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); switch ( ShadowTexture ) { @@ -361,7 +385,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -371,7 +395,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -381,7 +405,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -391,7 +415,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowHeliTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -401,7 +425,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowHeadLightsTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + 15.0f, false, 1.0f, nil, false); break; } @@ -410,8 +434,8 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, { StoreShadowToBeRendered(SHADOWTYPE_DARK, gpBloodPoolTex, pPosn, fFrontX, fFrontY, fSideX, fSideY, - nIntensity, nRed, nGreen, nBlue, - 15.0f, false, 1.0f); + nIntensity, nRed, 150, 0, + 15.0f, false, 1.0f, nil, false); break; } @@ -424,36 +448,39 @@ void CShadows::StoreShadowToBeRendered(uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, - float fZDistance, bool bDrawOnWater, float fScale) + float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings) { - ASSERT(pTexture != NULL); - ASSERT(pPosn != NULL); + ASSERT(pTexture != nil); + ASSERT(pPosn != nil); if ( ShadowsStoredToBeRendered < MAX_STOREDSHADOWS ) { - asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType; - asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture; - asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn; - asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX; - asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY; - asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX; - asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY; - asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity; - asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed; - asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen; - asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue; - asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance; - asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater; - asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale; + asShadowsStored[ShadowsStoredToBeRendered].m_ShadowType = ShadowType; + asShadowsStored[ShadowsStoredToBeRendered].m_pTexture = pTexture; + asShadowsStored[ShadowsStoredToBeRendered].m_vecPos = *pPosn; + asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x = fFrontX; + asShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y = fFrontY; + asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x = fSideX; + asShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y = fSideY; + asShadowsStored[ShadowsStoredToBeRendered].m_nIntensity = nIntensity; + asShadowsStored[ShadowsStoredToBeRendered].m_nRed = nRed; + asShadowsStored[ShadowsStoredToBeRendered].m_nGreen = nGreen; + asShadowsStored[ShadowsStoredToBeRendered].m_nBlue = nBlue; + asShadowsStored[ShadowsStoredToBeRendered].m_fZDistance = fZDistance; + asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater = bDrawOnWater; + asShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnBuildings = bDrawOnBuildings; + asShadowsStored[ShadowsStoredToBeRendered].m_fScale = fScale; + asShadowsStored[ShadowsStoredToBeRendered].m_pCutsceneShadow = pShadow; ShadowsStoredToBeRendered++; } } + void -CShadows::StoreShadowForCar(CAutomobile *pCar) +CShadows::StoreShadowForVehicle(CVehicle *pCar, VEH_SHD_TYPE type) { - ASSERT(pCar != NULL); + ASSERT(pCar != nil); if ( CTimeCycle::GetShadowStrength() != 0 ) { @@ -463,7 +490,22 @@ CShadows::StoreShadowForCar(CAutomobile *pCar) if ( CCutsceneMgr::IsRunning() ) fDistToCamSqr /= SQR(TheCamera.LODDistMultiplier) * 4.0f; - float fDrawDistance = 18.0f; + float fDrawDistance; + switch ( type ) + { + case VEH_SHD_TYPE_SEAPLANE: + case VEH_SHD_TYPE_RCPLANE: + fDrawDistance = 144.0f; + break; + + case VEH_SHD_TYPE_HELI: + fDrawDistance = 144.0f; + break; + + default: + fDrawDistance = 18.0f; + break; + } if ( fDistToCamSqr < SQR(fDrawDistance) ) { @@ -471,58 +513,214 @@ CShadows::StoreShadowForCar(CAutomobile *pCar) //fDistToCam == 0 -> 4 //fDistToCam == fDrawDistance -> 0 - float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))) ); + float fMult = 1.0f - (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))) / (fDrawDistance*(1.0f/4.0f)); int32 nColorStrength; if ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) ) - nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult); + nColorStrength = (int32)(fMult * CTimeCycle::GetShadowStrength()); else nColorStrength = CTimeCycle::GetShadowStrength(); - + + float fVehicleHeight = pCar->GetColModel()->boundingBox.GetSize().y; float fVehicleWidth = pCar->GetColModel()->boundingBox.GetSize().x; - - if ( pCar->GetModelIndex() == MI_DODO ) + + float size = 1.0f; + + if ( pCar->GetModelIndex() == MI_HUNTER ) + { + fVehicleWidth *= 3.0f; + fVehicleHeight *= 1.4f; + size *= 0.5f; + } + else if ( pCar->GetModelIndex() == MI_ANGEL ) + { + fVehicleHeight = fVehicleHeight * 1.5f; + size = 0.03f; + } + else if ( pCar->GetModelIndex() == MI_SEASPAR ) + { + fVehicleWidth *= 3.0f; + fVehicleHeight *= 1.4f; + size *= 0.5f; + } + else if ( pCar->GetModelIndex() == MI_PIZZABOY || pCar->GetModelIndex() == MI_PCJ600 || pCar->GetModelIndex() == MI_FAGGIO ) + { + fVehicleHeight *= 1.2f; + size = 0.05f; + } + else if ( pCar->GetModelIndex() == MI_FREEWAY ) + { + fVehicleHeight *= 1.5f; + size = 0.03f; + } + else if ( pCar->GetModelIndex() == MI_RCRAIDER ) + { + fVehicleHeight *= 1.5f; + fVehicleWidth *= 2.0f; + size = 0.2f; + } + else if ( pCar->GetModelIndex() == MI_SANCHEZ ) + { + fVehicleHeight *= 1.5f; + size = 0.03f; + } + else if ( pCar->GetModelIndex() == MI_SPARROW || pCar->GetModelIndex() == MI_MAVERICK || pCar->GetModelIndex() == MI_VCNMAV || pCar->GetModelIndex() == MI_POLMAV ) + { + fVehicleWidth *= 3.0f; + fVehicleHeight *= 1.4f; + size *= 0.5f; + } + else if ( pCar->GetModelIndex() == MI_RCGOBLIN ) + { + fVehicleHeight *= 1.5f; + fVehicleWidth *= 2.0f; + size = 0.2f; + } + else if ( pCar->GetModelIndex() == MI_DODO ) { fVehicleHeight *= 0.9f; fVehicleWidth *= 0.4f; } + + CarPos.x -= pCar->GetForward().x * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size); + CarPos.y -= pCar->GetForward().y * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size); + + RwTexture *tex = gpShadowCarTex; + switch ( type ) + { + case VEH_SHD_TYPE_BIKE: + { + float wheelZ = Abs(((CBike*)pCar)->m_fLeanLRAngle); + float mul = 5.092958f * wheelZ + 1.0f; + if (pCar->GetStatus() == STATUS_PHYSICS) + { + float z = pCar->GetRight().z; + if (z > 0.6f) + mul += 4.0f * z; + } + fVehicleWidth *= mul; + tex = gpShadowBikeTex; + break; + } + + case VEH_SHD_TYPE_HELI: + tex = gpShadowHeliTex; + break; + + case VEH_SHD_TYPE_SEAPLANE: + nColorStrength = CTimeCycle::GetShadowStrength(); + tex = gpShadowBaronTex; + break; + + case VEH_SHD_TYPE_RCPLANE: + tex = gpShadowBaronTex; + fVehicleHeight *= 1.5f; + fVehicleWidth *= 2.2f; + break; + + case VEH_SHD_TYPE_CAR: + tex = gpShadowCarTex; + break; + } + + float frontx = pCar->GetForward().x; + float fronty = pCar->GetForward().y; + float sidex = pCar->GetRight().x; + float sidey = pCar->GetRight().y; + + switch ( type ) + { + case VEH_SHD_TYPE_BIKE: + if ( Abs(pCar->GetRight().z) > 0.6f ) + { + sidex = pCar->GetUp().x; + sidey = pCar->GetUp().y; + } + break; + + case VEH_SHD_TYPE_HELI: + if ( Abs(pCar->GetRight().z) > 0.57f ) + { + sidex = pCar->GetUp().x; + sidey = pCar->GetUp().y; + } + if ( Abs(pCar->GetForward().z) > 0.57f ) + { + frontx = pCar->GetUp().x; + fronty = pCar->GetUp().y; + } + break; + } - CarPos.x -= pCar->GetForward().x * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y); - CarPos.y -= pCar->GetForward().y * ((fVehicleHeight / 2) - pCar->GetColModel()->boundingBox.max.y); - - if ( pCar->GetUp().z > 0.0f ) + bool bDrawOnBuildings = false; + if ( pCar->GetModelIndex() == MI_RCBANDIT + || pCar->GetModelIndex() == MI_RCBARON + || pCar->GetModelIndex() == MI_RCRAIDER + || pCar->GetModelIndex() == MI_RCGOBLIN + || pCar == FindPlayerVehicle() ) { - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos, - pCar->GetForward().x * (fVehicleHeight / 2), - pCar->GetForward().y * (fVehicleHeight / 2), - pCar->GetRight().x * (fVehicleWidth / 2), - pCar->GetRight().y * (fVehicleWidth / 2), - nColorStrength, nColorStrength, nColorStrength, nColorStrength, - 4.5f, false, 1.0f); + bDrawOnBuildings = true; + } + + if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.1f || bDrawOnBuildings ) + { + if ( pCar->GetUp().z > 0.0f ) + { + StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + sidex * (fVehicleWidth / 2), + sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, false, 1.0f, nil, bDrawOnBuildings); + } + else + { + StoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + -sidex * (fVehicleWidth / 2), + -sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, false, 1.0f, nil, bDrawOnBuildings); + } } else { - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &CarPos, - pCar->GetForward().x * (fVehicleHeight / 2), - pCar->GetForward().y * (fVehicleHeight / 2), - -pCar->GetRight().x * (fVehicleWidth / 2), - -pCar->GetRight().y * (fVehicleWidth / 2), - nColorStrength, nColorStrength, nColorStrength, nColorStrength, - 4.5f, false, 1.0f); + if ( pCar->GetUp().z > 0.0f ) + { + StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + sidex * (fVehicleWidth / 2), + sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, 1.0f, 0.0f, false, 0.1f); + } + else + { + StoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos, + frontx * (fVehicleHeight / 2), + fronty * (fVehicleHeight / 2), + -sidex * (fVehicleWidth / 2), + -sidey * (fVehicleWidth / 2), + nColorStrength, nColorStrength, nColorStrength, nColorStrength, + 4.5f, 1.0f, 0.0f, false, 0.1f); + } } } } } void -CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, +CShadows::StoreCarLightShadow(CVehicle *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle) { - ASSERT(pCar != NULL); - ASSERT(pPosn != NULL); + ASSERT(pCar != nil); + ASSERT(pPosn != nil); float fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D(); @@ -550,31 +748,131 @@ CShadows::StoreCarLightShadow(CAutomobile *pCar, int32 nID, RwTexture *pTexture, nBlue = (int32)(nBlue * fMult); } - StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn, - fFrontX, fFrontY, - fSideX, fSideY, - 128, nRed, nGreen, nBlue, - 6.0f, false, 1.0f); + if ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.4f || pCar == FindPlayerVehicle() ) + { + StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + 128, nRed, nGreen, nBlue, + 6.0f, false, 1.0f, + nil, pCar == FindPlayerVehicle()); + } + else + { + StoreStaticShadow((uintptr)pCar + nID, SHADOWTYPE_ADDITIVE, pTexture, pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + 128, nRed, nGreen, nBlue, + 6.0f, 1.0f, 27.0f, + false, 0.4f); + } + } + } +} + +#ifdef USE_CUTSCENE_SHADOW_FOR_PED +void +StoreShadowForCutscenePedObject(CPed *pObject, float fDisplacementX, float fDisplacementY, + float fFrontX, float fFrontY, float fSideX, float fSideY) +{ + ASSERT(pObject != nil); + + CCutsceneShadow *shadow = pObject->m_pRTShadow; + + if ( shadow == nil ) + return; + + if ( !shadow->IsInitialized() ) + return; + + CVector pos = pObject->GetPosition(); + + float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D(); + + float fDrawDistance = 100.0f; + + if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) ) + { + if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) ) + { + float fDistToCam = Sqrt(fDistToCamSqr); + + float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f))); + int32 nColorStrength; + + if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) ) + nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult); + else + nColorStrength = CTimeCycle::GetShadowStrength(); + + int32 color = int32(nColorStrength * 0.8f); + + pos.x += fDisplacementX; + pos.y += fDisplacementY; + + RwTexture *texture = shadow->GetShadowRwTexture(); + ASSERT(texture); + RwRGBA bordercolor = {0, 0, 0, 0}; + shadow->DrawBorderAroundTexture(bordercolor); + + pos.x -= fDisplacementX; + pos.y -= fDisplacementY; + + float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes + +60*CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f)); + + RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true); + ASSERT(frame); + CVector at(RwFrameGetMatrix(frame)->at); + at.Normalise(); + + CShadows::CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY); + + pos.x -= 2.5f * fDisplacementX; + pos.y -= 2.5f * fDisplacementY; + + CShadows::StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos, + fFrontX * 1.5f, fFrontY * 1.5f, + fSideX * 1.5f, fSideY * 1.5f, + color, color, color, color, + 4.0f, false, 1.0f, shadow, false); } } } +#endif + void CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY) { - ASSERT(pPed != NULL); + ASSERT(pPed != nil); if ( pPed->bIsVisible ) { if ( !(pPed->bInVehicle && pPed->m_nPedState != PED_DRAG_FROM_CAR && pPed->m_nPedState != PED_EXIT_CAR) ) { if ( CTimeCycle::GetShadowStrength() != 0 ) + { +#ifdef USE_CUTSCENE_SHADOW_FOR_PED + CCutsceneShadow *pShadow = pPed->m_pRTShadow; + + if (pShadow) + { + if (pShadow->IsInitialized()) + pShadow->UpdateForCutscene(); + ::StoreShadowForCutscenePedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY); + } + + return; +#endif + StoreShadowForPedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY); + } } } } @@ -582,8 +880,8 @@ CShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacemen void CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY) -{ - ASSERT(pPedObject != NULL); +{ + ASSERT(pPedObject != nil); CVector PedPos = pPedObject->GetPosition(); @@ -591,7 +889,7 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo float fDrawDistance = 26.0f; - if ( fDistToCamSqr < SQR(fDrawDistance*0.5f)/*?*/ ) + if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) ) { if ( pPedObject == FindPlayerPed() || TheCamera.IsSphereVisible(PedPos, 2.0f) != false ) { @@ -614,7 +912,80 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo fFrontX, fFrontY, fSideX, fSideY, nColorStrength, nColorStrength, nColorStrength, nColorStrength, - 4.0f, false, 1.0f); + 4.0f, false, 1.0f, nil, pPedObject == FindPlayerPed()); + } + } +} + + +void +CShadows::StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, + float fFrontX, float fFrontY, float fSideX, float fSideY) +{ +#ifdef DISABLE_CUTSCENE_SHADOWS + return; +#endif + ASSERT(pObject != nil); + + CCutsceneShadow *shadow = pObject->m_pShadow; + + if ( shadow == nil ) + return; + + if ( !shadow->IsInitialized() ) + return; + + CVector pos = pObject->GetPosition(); + + float fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D(); + + float fDrawDistance = 100.0f; + + if ( fDistToCamSqr < SQR(fDrawDistance*0.5f) ) + { + if ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) ) + { + float fDistToCam = Sqrt(fDistToCamSqr); + + float fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f))); + int32 nColorStrength; + + if ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) ) + nColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult); + else + nColorStrength = CTimeCycle::GetShadowStrength(); + + int32 color = int32(nColorStrength * 0.8f); + + pos.x += fDisplacementX; + pos.y += fDisplacementY; + + RwTexture *texture = shadow->GetShadowRwTexture(); + ASSERT(texture); + RwRGBA bordercolor = {0, 0, 0, 0}; + shadow->DrawBorderAroundTexture(bordercolor); + + pos.x -= fDisplacementX; + pos.y -= fDisplacementY; + + float angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes+60* + CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f)); + + RwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true); + ASSERT(frame); + CVector at(RwFrameGetMatrix(frame)->at); + at.Normalise(); + + CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY); + + pos.x -= 2.5f * fDisplacementX; + pos.y -= 2.5f * fDisplacementY; + + StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos, + fFrontX * 1.5f, fFrontY * 1.5f, + fSideX * 1.5f, fSideY * 1.5f, + color, color, color, color, + 4.0f, false, 1.0f, shadow, false); } } } @@ -622,14 +993,15 @@ CShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, flo void CShadows::StoreShadowForTree(CEntity *pTree) { - ASSERT(pTree != NULL); + ASSERT(pTree != nil); } + void CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID) { - ASSERT(pPole != NULL); + ASSERT(pPole != nil); if ( CTimeCycle::GetShadowStrength() != 0 ) { @@ -684,6 +1056,7 @@ CShadows::SetRenderModeForShadowType(uint8 ShadowType) } } + void CShadows::RenderStoredShadows(void) { @@ -692,17 +1065,20 @@ CShadows::RenderStoredShadows(void) RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSCLAMP); + for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ ) asShadowsStored[i].m_nFlags.bRendered = false; + for ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ ) { if ( !asShadowsStored[i].m_nFlags.bRendered ) { SetRenderModeForShadowType(asShadowsStored[i].m_ShadowType); - ASSERT(asShadowsStored[i].m_pTexture != NULL); + ASSERT(asShadowsStored[i].m_pTexture != nil); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(asShadowsStored[i].m_pTexture)); @@ -734,39 +1110,112 @@ CShadows::RenderStoredShadows(void) { CSector *pCurSector = CWorld::GetSector(x, y); - ASSERT(pCurSector != NULL); - - CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], - fStartX, fStartY, - fEndX, fEndY, - &shadowPos, - asShadowsStored[j].m_vecFront.x, - asShadowsStored[j].m_vecFront.y, - asShadowsStored[j].m_vecSide.x, - asShadowsStored[j].m_vecSide.y, - asShadowsStored[j].m_nIntensity, - asShadowsStored[j].m_nRed, - asShadowsStored[j].m_nGreen, - asShadowsStored[j].m_nBlue, - asShadowsStored[j].m_fZDistance, - asShadowsStored[j].m_fScale, - NULL); - - CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], - fStartX, fStartY, - fEndX, fEndY, - &shadowPos, - asShadowsStored[j].m_vecFront.x, - asShadowsStored[j].m_vecFront.y, - asShadowsStored[j].m_vecSide.x, - asShadowsStored[j].m_vecSide.y, - asShadowsStored[j].m_nIntensity, - asShadowsStored[j].m_nRed, - asShadowsStored[j].m_nGreen, - asShadowsStored[j].m_nBlue, - asShadowsStored[j].m_fZDistance, - asShadowsStored[j].m_fScale, - NULL); + ASSERT(pCurSector != nil); + + if ( asShadowsStored[j].m_pCutsceneShadow ) + { + CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil, + asShadowsStored[j].m_pCutsceneShadow); + + CastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil, + asShadowsStored[j].m_pCutsceneShadow); + } + else if ( asShadowsStored[j].m_nFlags.bDrawOnBuildings ) + { + CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + + CastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + } + else + { + CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + + CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], + fStartX, fStartY, + fEndX, fEndY, + &shadowPos, + asShadowsStored[j].m_vecFront.x, + asShadowsStored[j].m_vecFront.y, + asShadowsStored[j].m_vecSide.x, + asShadowsStored[j].m_vecSide.y, + asShadowsStored[j].m_nIntensity, + asShadowsStored[j].m_nRed, + asShadowsStored[j].m_nGreen, + asShadowsStored[j].m_nBlue, + asShadowsStored[j].m_fZDistance, + asShadowsStored[j].m_fScale, + nil); + } } } @@ -776,16 +1225,17 @@ CShadows::RenderStoredShadows(void) RenderBuffer::RenderStuffInBuffer(); } - } RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSWRAP); ShadowsStoredToBeRendered = 0; } + void CShadows::RenderStaticShadows(void) { @@ -811,19 +1261,19 @@ CShadows::RenderStaticShadows(void) // optimization trick, render all shadows with same renderstate and texture for ( int32 j = i; j < MAX_STATICSHADOWS; j++ ) { - if ( aStaticShadows[j].m_pPolyBunch != NULL + if ( aStaticShadows[j].m_pPolyBunch != nil && aStaticShadows[i].m_nType == aStaticShadows[j].m_nType && aStaticShadows[i].m_pTexture == aStaticShadows[j].m_pTexture ) { - for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != NULL; bunch = bunch->m_pNext ) + for ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != nil; bunch = bunch->m_pNext ) { RwImVertexIndex *pIndexes; RwIm3DVertex *pVerts; RenderBuffer::StartStoring(3 * (bunch->m_nNumVerts - 2), bunch->m_nNumVerts, &pIndexes, &pVerts); - ASSERT(pIndexes != NULL); - ASSERT(pVerts != NULL); + ASSERT(pIndexes != nil); + ASSERT(pVerts != nil); for ( int32 k = 0; k < bunch->m_nNumVerts; k++ ) { @@ -857,6 +1307,7 @@ CShadows::RenderStaticShadows(void) RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); } + void CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) { @@ -883,7 +1334,7 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) { CSector *pCurSector = CWorld::GetSector(x, y); - ASSERT(pCurSector != NULL); + ASSERT(pCurSector != nil); CastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS], fStartX, fStartY, @@ -914,50 +1365,109 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) } } + void CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); CPtrNode *pNode = PtrList.first; CRect Bound; - while ( pNode != NULL ) + while ( pNode != nil ) { CEntity *pEntity = (CEntity *)pNode->item; uint16 nScanCode = pEntity->m_scanCode; pNode = pNode->next; - ASSERT( pEntity != NULL ); + ASSERT( pEntity != nil ); if ( nScanCode != CWorld::GetCurrentScanCode() ) { - if ( pEntity->bUsesCollision && pEntity->IsBuilding() ) + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + + if ( pEntity->bUsesCollision && !pEntity->m_flagE2 ) { - pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + if ( IsAreaVisible(pEntity->m_area) ) + { + Bound = pEntity->GetBoundRect(); + + if ( fStartX < Bound.right + && fEndX > Bound.left + && fStartY < Bound.bottom + && fEndY > Bound.top ) + { + if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z + && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + { + CastShadowEntityXY(pEntity, + fStartX, fStartY, + fEndX, fEndY, + pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch); + } + } + } + } + } + } +} + + +void +CShadows::CastPlayerShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, + float fFrontX, float fFrontY, float fSideX, float fSideY, + int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, + float fZDistance, float fScale, CPolyBunch **ppPolyBunch) +{ + ASSERT(pPosn != nil); + + CPtrNode *pNode = PtrList.first; + + CRect Bound; + + while ( pNode != nil ) + { + CEntity *pEntity = (CEntity *)pNode->item; + uint16 nScanCode = pEntity->m_scanCode; + pNode = pNode->next; - Bound = pEntity->GetBoundRect(); + ASSERT( pEntity != nil ); - if ( fStartX < Bound.right - && fEndX > Bound.left - && fStartY < Bound.bottom - && fEndY > Bound.top ) + if ( nScanCode != CWorld::GetCurrentScanCode() ) + { + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + + if ( pEntity->bUsesCollision ) + { + if ( IsAreaVisible(pEntity->m_area) ) { - if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z - && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + Bound = pEntity->GetBoundRect(); + + if ( fStartX < Bound.right + && fEndX > Bound.left + && fStartY < Bound.bottom + && fEndY > Bound.top ) { - CastShadowEntity(pEntity, - fStartX, fStartY, - fEndX, fEndY, - pPosn, - fFrontX, fFrontY, - fSideX, fSideY, - nIntensity, nRed, nGreen, nBlue, - fZDistance, fScale, ppPolyBunch); + if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z + && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + { + CastShadowEntityXY(pEntity, + fStartX, fStartY, + fEndX, fEndY, + pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch); + } } } } @@ -965,21 +1475,74 @@ CShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, } } + void -CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, +CShadows::CastCutsceneShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, + float fFrontX, float fFrontY, float fSideX, float fSideY, + int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, + float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow) +{ + ASSERT(pPosn != nil); + ASSERT(pShadow != nil); + + CPtrNode *pNode = PtrList.first; + + CRect Bound; + + while ( pNode != nil ) + { + CEntity *pEntity = (CEntity *)pNode->item; + uint16 nScanCode = pEntity->m_scanCode; + pNode = pNode->next; + + ASSERT( pEntity != nil ); + + if ( nScanCode != CWorld::GetCurrentScanCode() ) + { + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + + if ( pEntity->bUsesCollision ) + { + if ( IsAreaVisible(pEntity->m_area) ) + { + Bound = pEntity->GetBoundRect(); + + if ( fStartX < Bound.right + && fEndX > Bound.left + && fStartY < Bound.bottom + && fEndY > Bound.top ) + { + if ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z + && pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z ) + { + CastShadowEntityXYZ(pEntity, pPosn, + fFrontX, fFrontY, + fSideX, fSideY, + nIntensity, nRed, nGreen, nBlue, + fZDistance, fScale, ppPolyBunch, pShadow); + } + } + } + } + } + } +} + +void +CShadows::CastShadowEntityXY(CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch) -{ - ASSERT(pEntity != NULL); - ASSERT(pPosn != NULL); +{ + ASSERT(pEntity != nil); + ASSERT(pPosn != nil); static CVector List [20]; static CVector Texture[20]; static CVector Points [4]; CColModel *pCol = pEntity->GetColModel(); - ASSERT(pCol != NULL); + ASSERT(pCol != nil); #ifndef MASTER if ( gbPrintShite ) @@ -1025,14 +1588,14 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa for ( int32 i = 0; i < pCol->numTriangles; i++ ) { CColTrianglePlane *pColTriPlanes = pCol->trianglePlanes; - ASSERT(pColTriPlanes != NULL); + ASSERT(pColTriPlanes != nil); CVector normal; pColTriPlanes[i].GetNormal(normal); if ( Abs(normal.z) > 0.1f ) { CColTriangle *pColTri = pCol->triangles; - ASSERT(pColTri != NULL); + ASSERT(pColTri != nil); CVector PointA, PointB, PointC; @@ -1432,12 +1995,12 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa } - if ( ppPolyBunch != NULL ) + if ( ppPolyBunch != nil ) { - if ( pEmptyBunchList != NULL ) + if ( pEmptyBunchList != nil ) { CPolyBunch *pBunch = pEmptyBunchList; - ASSERT(pBunch != NULL); + ASSERT(pBunch != nil); pEmptyBunchList = pEmptyBunchList->m_pNext; pBunch->m_pNext = *ppPolyBunch; *ppPolyBunch = pBunch; @@ -1462,8 +2025,8 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa RenderBuffer::StartStoring(3 * (numVerts3 - 2), numVerts3, &pIndexes, &pVerts); - ASSERT(pIndexes != NULL); - ASSERT(pVerts != NULL); + ASSERT(pIndexes != nil); + ASSERT(pVerts != nil); for ( int32 j = 0; j < numVerts3; j++ ) @@ -1487,12 +2050,222 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa } } + +typedef struct _ProjectionParam +{ + RwV3d at; /* Camera at vector */ + RwMatrix invMatrix; /* Transforms to shadow camera space */ + RwUInt8 shadowValue; /* Shadow opacity value */ + RwBool fade; /* Shadow fades with distance */ + RwUInt32 numIm3DBatch; /* Number of buffer flushes */ + RwMatrix entityMatrix; +} +ProjectionParam; + +RwV3d *ShadowRenderTriangleCB(RwV3d *points, RwV3d *normal, ProjectionParam *param) +{ + RwV3d vIn[3]; + RwV3d vShad[3]; + + RwV3dTransformPoints(&vIn[0], points, 3, ¶m->entityMatrix); + + /* + * Reject backfacing triangles + * This reject the triangles parallel to the light as well + */ + if (RwV3dDotProduct(normal, ¶m->at) > 0.0f) + { + return points; + } + + RwV3dTransformPoints(&vShad[0], &vIn[0], 3, ¶m->invMatrix); + + /* + * Reject triangles behind the camera (z test). Note that any world + * triangles lying in front of the camera but before the object may + * have a shadow applied. To minimize such artefacts, this test could + * be modified to use a specific value rather than 0.0f, perhaps + * to reject triangles behind the center plane of the object. + * + * Reject triangles that lie entirely outside the shadow texture range + * (x,y test). + */ + if (((vShad[0].z < 0.0f) && (vShad[1].z < 0.0f) + && (vShad[2].z < 0.0f)) || ((vShad[0].x < 0.0f) + && (vShad[1].x < 0.0f) + && (vShad[2].x < 0.0f)) + || ((vShad[0].x > 1.0f) && (vShad[1].x > 1.0f) + && (vShad[2].x > 1.0f)) || ((vShad[0].y < 0.0f) + && (vShad[1].y < 0.0f) + && (vShad[2].y < 0.0f)) + || ((vShad[0].y > 1.0f) && (vShad[1].y > 1.0f) + && (vShad[2].y > 1.0f))) + { + return points; + } + + RwIm3DVertex *imv = nil; + RwImVertexIndex *imi = nil; + + RenderBuffer::StartStoring(3, 3, &imi, &imv); + + /* + * Set the immediate mode vertices for this triangle + */ + + RwIm3DVertexSetPos(imv, vIn[0].x, vIn[0].y, vIn[0].z); + RwIm3DVertexSetPos(imv + 1, vIn[1].x, vIn[1].y, vIn[1].z); + RwIm3DVertexSetPos(imv + 2, vIn[2].x, vIn[2].y, vIn[2].z); + + RwIm3DVertexSetU(imv, vShad[0].x); + RwIm3DVertexSetU(imv + 1, vShad[1].x); + RwIm3DVertexSetU(imv + 2, vShad[2].x); + + RwIm3DVertexSetV(imv, vShad[0].y); + RwIm3DVertexSetV(imv + 1, vShad[1].y); + RwIm3DVertexSetV(imv + 2, vShad[2].y); + + /* + * Do we fade out the shadow with distance? + */ + if (param->fade) + { + RwReal fadeVal; + RwUInt8 val; + + fadeVal = 1.0f - vShad[0].z * vShad[0].z; + val = + (fadeVal < + 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue); + RwIm3DVertexSetRGBA(imv, val, val, val, val); + + fadeVal = 1.0f - vShad[1].z * vShad[1].z; + val = + (fadeVal < + 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue); + RwIm3DVertexSetRGBA(imv + 1, val, val, val, val); + + fadeVal = 1.0f - vShad[2].z * vShad[2].z; + val = + (fadeVal < + 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue); + RwIm3DVertexSetRGBA(imv + 2, val, val, val, val); + } + else + { + RwUInt8 val = param->shadowValue; + + RwIm3DVertexSetRGBA(imv, val, val, val, val); + RwIm3DVertexSetRGBA(imv + 1, val, val, val, val); + RwIm3DVertexSetRGBA(imv + 2, val, val, val, val); + } + + /* + * Update buffer position + */ + imi[0] = 0; + imi[1] = 1; + imi[2] = 2; + + RenderBuffer::StopStoring(); + + return points; +} + +void +CShadows::CastShadowEntityXYZ(CEntity *pEntity, CVector *pPosn, + float fFrontX, float fFrontY, float fSideX, float fSideY, + int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, + float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow) +{ + ASSERT(pEntity != nil); + ASSERT(pPosn != nil); + + if ( pShadow ) + { + ProjectionParam proj; + RwV3d scl; + RwV3d tr; + + CShadowCamera *shadow = pShadow->GetShadowCamera(); + CColModel *collision = pEntity->GetColModel(); + + CCollision::CalculateTrianglePlanes(collision); + + RwMatrix mat; + mat = *RwFrameGetMatrix(RwCameraGetFrame(shadow->GetRwCamera())); + + RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; + + RwMatrixRotate(&mat, &Xaxis, -45.0f, rwCOMBINEPRECONCAT); + + proj.at = mat.at; + pEntity->GetMatrix().CopyToRwMatrix(&proj.entityMatrix); + + RwMatrixInvert(&proj.invMatrix, &mat); + RwReal radius = RwCameraGetViewWindow(shadow->GetRwCamera())->x; + + scl.x = scl.y = -0.5f / (radius*0.9f); + scl.z = 1.0f / (radius*0.8f); + RwMatrixScale(&proj.invMatrix, &scl, rwCOMBINEPOSTCONCAT); + + tr.x = 0.5f; + tr.y = tr.z = 0.0f; + RwMatrixTranslate(&proj.invMatrix, &tr, rwCOMBINEPOSTCONCAT); + + proj.shadowValue = nIntensity; + proj.fade = 0; + + RwMatrix matrix; + pEntity->GetMatrix().CopyToRwMatrix(&matrix); + RwMatrix invMatrix; + RwMatrixInvert(&invMatrix, &matrix); + + + CVector center(pShadow->GetBaseSphere().center); + center += CVector(-fFrontX * 1.1f, -fFrontY * 1.1f, -0.5f); + + CSphere sphere; + sphere.Set(2.0f, center); + + RwV3d point; + RwV3dTransformPoints(&point, center, 1, &invMatrix); + + CColSphere colSphere; + colSphere.Set(2.0f, CVector(point), 0, 0); + + int i = 0; + while ( i < collision->numTriangles ) + { + CVector p[3]; + + collision->GetTrianglePoint(p[0], collision->triangles[i].a); + collision->GetTrianglePoint(p[1], collision->triangles[i].b); + collision->GetTrianglePoint(p[2], collision->triangles[i].c); + + if ( CCollision::TestSphereTriangle(colSphere, collision->vertices, collision->triangles[i], collision->trianglePlanes[i]) ) + { + CVector n(collision->trianglePlanes[i].GetNormalX(), collision->trianglePlanes[i].GetNormalY(), collision->trianglePlanes[i].GetNormalZ()); + CVector offset = n * 0.028f; + + p[0] += offset; + p[1] += offset; + p[2] += offset; + + if ( !ShadowRenderTriangleCB((RwV3d *)p, n, &proj) ) + break; + } + i++; + } + } +} + void CShadows::UpdateStaticShadows(void) { for ( int32 i = 0; i < MAX_STATICSHADOWS; i++ ) { - if ( aStaticShadows[i].m_pPolyBunch != NULL && !aStaticShadows[i].m_bJustCreated + if ( aStaticShadows[i].m_pPolyBunch != nil && !aStaticShadows[i].m_bJustCreated && (!aStaticShadows[i].m_bTemp || CTimer::GetTimeInMilliseconds() > aStaticShadows[i].m_nTimeCreated + 5000) ) { aStaticShadows[i].Free(); @@ -1515,13 +2288,14 @@ CShadows::UpdatePermanentShadows(void) aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; else { + bool bOk; if ( timePassed >= (aPermanentShadows[i].m_nLifeTime * 3 / 4) ) { // timePassed == 0 -> 4 // timePassed == aPermanentShadows[i].m_nLifeTime -> 0 float fMult = 1.0f - float(timePassed - (aPermanentShadows[i].m_nLifeTime * 3 / 4)) / (aPermanentShadows[i].m_nLifeTime / 4); - StoreStaticShadow((uintptr)&aPermanentShadows[i], + bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i], aPermanentShadows[i].m_nType, aPermanentShadows[i].m_pTexture, &aPermanentShadows[i].m_vecPos, @@ -1538,7 +2312,7 @@ CShadows::UpdatePermanentShadows(void) } else { - StoreStaticShadow((uintptr)&aPermanentShadows[i], + bOk = StoreStaticShadow((uintptr)&aPermanentShadows[i], aPermanentShadows[i].m_nType, aPermanentShadows[i].m_pTexture, &aPermanentShadows[i].m_vecPos, @@ -1553,6 +2327,9 @@ CShadows::UpdatePermanentShadows(void) aPermanentShadows[i].m_fZDistance, 1.0f, 40.0f, false, 0.0f); } + + if ( !bOk ) + aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; } } } @@ -1561,19 +2338,19 @@ CShadows::UpdatePermanentShadows(void) void CStaticShadow::Free(void) { - if ( m_pPolyBunch != NULL ) + if ( m_pPolyBunch != nil ) { CPolyBunch *pFree = CShadows::pEmptyBunchList; CShadows::pEmptyBunchList = m_pPolyBunch; CPolyBunch *pUsed = m_pPolyBunch; - while (pUsed->m_pNext != NULL) + while (pUsed->m_pNext != nil) pUsed = pUsed->m_pNext; pUsed->m_pNext = pFree; } - m_pPolyBunch = NULL; + m_pPolyBunch = nil; m_nId = 0; } @@ -1617,6 +2394,7 @@ CShadows::CalcPedShadowValues(CVector vecLightDir, } + void CShadows::RenderExtraPlayerShadows(void) { @@ -1627,64 +2405,13 @@ CShadows::RenderExtraPlayerShadows(void) if ( CTimeCycle::GetLightShadowStrength() != 0 ) { CVehicle *pCar = FindPlayerVehicle(); - - if ( pCar == NULL ) - { - for ( int32 i = 0; i < CPointLights::NumLights; i++ ) - { - if ( 0.0f != CPointLights::aLights[i].red - || 0.0f != CPointLights::aLights[i].green - || 0.0f != CPointLights::aLights[i].blue ) - { - if ( CPointLights::aLights[i].castExtraShadows ) - { - CVector vecLight = CPointLights::aLights[i].coors - FindPlayerCoors(); - float fLightDist = vecLight.Magnitude(); - float fRadius = CPointLights::aLights[i].radius; - - if ( fLightDist < fRadius ) - { - // fLightDist == fRadius -> 2.0f - // fLightDist == 0 -> 0.0f - float fMult = (1.0f - (2.0f * fLightDist - fRadius) / fRadius); - - int32 nColorStrength; - if ( fLightDist < fRadius*0.5f ) - nColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8); - else - nColorStrength = int32((5*CTimeCycle::GetLightShadowStrength()/8) * fMult); - - float fInv = 1.0f / fLightDist; - vecLight.x *= fInv; - vecLight.y *= fInv; - vecLight.z *= fInv; - - float fFrontX, fFrontY, fSideX, fSideY, fDisplacementX, fDisplacementY; - - CalcPedShadowValues(vecLight, - &fFrontX, &fFrontY, - &fSideX, &fSideY, - &fDisplacementX, &fDisplacementY); - - CVector shadowPos = FindPlayerCoors(); - - shadowPos.x += fDisplacementX; - shadowPos.y += fDisplacementY; - - - StoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &shadowPos, - fFrontX, fFrontY, - fSideX, fSideY, - nColorStrength, 0, 0, 0, - 4.0f, false, 1.0f); - } - } - } - } - } + if ( pCar == nil ) + ; // R* cut it out for playerped else { - if ( pCar->GetModelIndex() != MI_RCBANDIT ) + if ( pCar->GetModelIndex() != MI_RCBANDIT + && pCar->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE + && !pCar->IsBike() && !pCar->IsPlane() && !pCar->IsBoat() ) { for ( int32 i = 0; i < CPointLights::NumLights; i++ ) { @@ -1737,7 +2464,7 @@ CShadows::RenderExtraPlayerShadows(void) pCar->GetRight().x * (fVehicleWidth/3), pCar->GetRight().y * (fVehicleWidth/3), nColorStrength, 0, 0, 0, - 4.5f, false, 1.0f); + 4.5f, false, 1.0f, nil, false); } else { @@ -1747,7 +2474,7 @@ CShadows::RenderExtraPlayerShadows(void) -pCar->GetRight().x * (fVehicleWidth/2), -pCar->GetRight().y * (fVehicleWidth/2), nColorStrength, 0, 0, 0, - 4.5f, false, 1.0f); + 4.5f, false, 1.0f, nil, false); } } } @@ -1769,9 +2496,9 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity) { - ASSERT(pPosn != NULL); + ASSERT(pPosn != nil); C3dMarkers::PlaceMarkerSet(nID, MARKERTYPE_CYLINDER, *pPosn, Max(fFrontX, -fSideY), - 0, 128, 255, 128, - 2048, 0.2f, 0); + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, + SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0); } diff --git a/src/render/Shadows.h b/src/render/Shadows.h index 8c909df3..937ff4eb 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -1,12 +1,19 @@ #pragma once #define MAX_STOREDSHADOWS 48 -#define MAX_POLYBUNCHES 300 -#define MAX_STATICSHADOWS 64 +#define MAX_POLYBUNCHES 380 +#define MAX_STATICSHADOWS 48 #define MAX_PERMAMENTSHADOWS 48 + class CEntity; +class CPtrList; +class CAutomobile; +class CVehicle; +class CPed; +class CCutsceneShadow; +class CCutsceneObject; enum eShadowType { @@ -27,6 +34,16 @@ enum eShadowTextureType SHADOWTEX_BLOOD }; +enum VEH_SHD_TYPE +{ + VEH_SHD_TYPE_CAR = 0, + VEH_SHD_TYPE_BIKE, + VEH_SHD_TYPE_HELI, + VEH_SHD_TYPE_SEAPLANE, + VEH_SHD_TYPE_RCPLANE, +}; + + class CStoredShadow { public: @@ -35,6 +52,8 @@ public: CVector2D m_vecSide; float m_fZDistance; float m_fScale; + RwTexture *m_pTexture; + CCutsceneShadow *m_pCutsceneShadow; int16 m_nIntensity; uint8 m_ShadowType; uint8 m_nRed; @@ -44,9 +63,9 @@ public: { uint8 bDrawOnWater : 1; uint8 bRendered : 1; - //uint8 bDrawOnBuildings : 1; + uint8 bDrawOnBuildings : 1; } m_nFlags; - RwTexture *m_pTexture; + CStoredShadow() { } @@ -57,11 +76,11 @@ VALIDATE_SIZE(CStoredShadow, 0x30); class CPolyBunch { public: - int16 m_nNumVerts; CVector m_aVerts[7]; + CPolyBunch *m_pNext; + int16 m_nNumVerts; uint8 m_aU[7]; uint8 m_aV[7]; - CPolyBunch *m_pNext; CPolyBunch() { } @@ -80,15 +99,16 @@ public: CVector2D m_vecSide; float m_fZDistance; float m_fScale; - uint8 m_nType; + RwTexture *m_pTexture; int16 m_nIntensity; // unsigned ? + uint8 m_nType; uint8 m_nRed; uint8 m_nGreen; uint8 m_nBlue; bool m_bJustCreated; bool m_bRendered; bool m_bTemp; - RwTexture *m_pTexture; + CStaticShadow() { } @@ -106,14 +126,14 @@ public: CVector2D m_vecSide; float m_fZDistance; float m_fScale; + uint32 m_nTimeCreated; + uint32 m_nLifeTime; + RwTexture *m_pTexture; int16 m_nIntensity; uint8 m_nType; // eShadowType uint8 m_nRed; uint8 m_nGreen; uint8 m_nBlue; - uint32 m_nTimeCreated; - uint32 m_nLifeTime; - RwTexture *m_pTexture; CPermanentShadow() { } @@ -121,10 +141,6 @@ public: VALIDATE_SIZE(CPermanentShadow, 0x38); -class CPtrList; -class CAutomobile; -class CPed; - class CShadows { public: @@ -135,37 +151,52 @@ public: static CPolyBunch *pEmptyBunchList; static CPermanentShadow aPermanentShadows[MAX_PERMAMENTSHADOWS]; - static void Init (void); - static void Shutdown (void); - static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale); - static void StoreStaticShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance); - static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue); - static void StoreShadowToBeRendered ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale); - static void StoreShadowForCar (CAutomobile *pCar); - static void StoreCarLightShadow (CAutomobile *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle); - static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); - static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); - static void StoreShadowForTree (CEntity *pTree); - static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID); - static void SetRenderModeForShadowType (uint8 ShadowType); - static void RenderStoredShadows (void); - static void RenderStaticShadows (void); - static void GeneratePolysForStaticShadow (int16 nStaticShadowID); - static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, + static void Init (void); + static void Shutdown (void); + static void AddPermanentShadow ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale); + + static bool StoreStaticShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance); + static void StoreShadowToBeRendered ( uint8 ShadowType, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue); + static void StoreShadowToBeRendered ( uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings); + static void StoreShadowForVehicle (CVehicle *pCar, VEH_SHD_TYPE type); + static void StoreCarLightShadow (CVehicle *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle); + static void StoreShadowForPed (CPed *pPed, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); + static void StoreShadowForPedObject (CEntity *pPedObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); + static void StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY); + static void StoreShadowForTree (CEntity *pTree); + static void StoreShadowForPole (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID); + static void SetRenderModeForShadowType (uint8 ShadowType); + static void RenderStoredShadows (void); + static void RenderStaticShadows (void); + + static void GeneratePolysForStaticShadow (int16 nStaticShadowID); + static void CastShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch); - static void CastShadowEntity (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, + + static void CastPlayerShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, + CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch); + + static void CastCutsceneShadowSectorList (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, + CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow); + + static void CastShadowEntityXY (CEntity *pEntity, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch); - static void UpdateStaticShadows (void); - static void UpdatePermanentShadows (void); + + static void CastShadowEntityXYZ (CEntity *pEntity, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow); + + static void UpdateStaticShadows (void); + static void UpdatePermanentShadows (void); static void CalcPedShadowValues (CVector vecLightDir, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY, float *pfDisplacementX, float *pfDisplacementY); - static void RenderExtraPlayerShadows (void); - static void TidyUpShadows (void); - static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity); + static void RenderExtraPlayerShadows (void); + static void TidyUpShadows (void); + static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity); }; extern RwTexture *gpShadowCarTex; extern RwTexture *gpShadowPedTex; extern RwTexture *gpShadowHeliTex; +extern RwTexture *gpShadowBikeTex; +extern RwTexture *gpShadowBaronTex; extern RwTexture *gpShadowExplosionTex; extern RwTexture *gpShadowHeadLightsTex; extern RwTexture *gpOutline1Tex; @@ -173,7 +204,6 @@ extern RwTexture *gpOutline2Tex; extern RwTexture *gpOutline3Tex; extern RwTexture *gpBloodPoolTex; extern RwTexture *gpReflectionTex; -extern RwTexture *gpGoalMarkerTex; extern RwTexture *gpWalkDontTex; extern RwTexture *gpCrackedGlassTex; extern RwTexture *gpPostShadowTex; diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index ad036d58..0251878a 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -6,13 +6,13 @@ #include "Replay.h" #include "Skidmarks.h" +//--MIAMI: file done + CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS]; RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6]; RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2]; RwTexture *gpSkidTex; -RwTexture *gpSkidBloodTex; -RwTexture *gpSkidMudTex; void CSkidmarks::Init(void) @@ -22,8 +22,6 @@ CSkidmarks::Init(void) 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++){ @@ -41,30 +39,13 @@ CSkidmarks::Init(void) 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); -#ifdef GTA3_1_1_PATCH gpSkidTex = nil; -#endif - RwTextureDestroy(gpSkidBloodTex); -#ifdef GTA3_1_1_PATCH - gpSkidBloodTex = nil; -#endif - RwTextureDestroy(gpSkidMudTex); -#ifdef GTA3_1_1_PATCH - gpSkidMudTex = nil; -#endif } void @@ -116,32 +97,23 @@ 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); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex)); 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; - } + CRGBA color(0, 0, 0, 255); + switch(aSkidmarks[i].m_type){ + case SKIDMARK_NORMAL: color = CRGBA(0, 0, 0, 255); break; + case SKIDMARK_MUDDY: color = CRGBA(90, 62, 9, 255); break; + case SKIDMARK_SANDY: color = CRGBA(108, 108, 96, 255); break; + case SKIDMARK_BLOODY: color = CRGBA(132, 34, 11, 255); break; } uint32 fade, alpha; @@ -156,12 +128,20 @@ CSkidmarks::Render(void) 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); + CVector p1 = aSkidmarks[i].m_pos[j]; + p1.x += aSkidmarks[i].m_sideX[j]; + p1.y += aSkidmarks[i].m_sideY[j]; + CVector p2 = aSkidmarks[i].m_pos[j]; + p2.x -= aSkidmarks[i].m_sideX[j]; + p2.y -= aSkidmarks[i].m_sideY[j]; + RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], color.red, color.green, color.blue, alpha); RwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f); - RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], 255, 255, 255, alpha); + RwIm3DVertexSetU(&SkidmarkVertices[j*2+0], 0.0f); + RwIm3DVertexSetV(&SkidmarkVertices[j*2+0], j*5.01f); + RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], color.red, color.green, color.blue, alpha); RwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f); + RwIm3DVertexSetU(&SkidmarkVertices[j*2+1], 1.0f); + RwIm3DVertexSetV(&SkidmarkVertices[j*2+1], j*5.01f); } LittleTest(); @@ -177,7 +157,20 @@ CSkidmarks::Render(void) } void -CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody) +CSkidmarks::RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody) +{ + eSkidmarkType type; + if(*isBloody) + type = SKIDMARK_BLOODY; + else if(*isMuddy) + type = SKIDMARK_MUDDY; + else + type = SKIDMARK_NORMAL; + RegisterOne(id, pos, fwdX, fwdY, type, isBloody); +} + +void +CSkidmarks::RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, eSkidmarkType type, bool *isBloody) { int i; CVector2D fwd(fwdX, fwdY); @@ -193,7 +186,7 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i if(i < NUMSKIDMARKS){ // Continue this one - if(aSkidmarks[i].m_isBloody != *isBloody){ + if((aSkidmarks[i].m_type==SKIDMARK_BLOODY) != *isBloody){ // Blood-status changed, end this one aSkidmarks[i].m_state = 2; aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000; @@ -225,13 +218,16 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i CVector2D right(aSkidmarks[i].m_pos[aSkidmarks[i].m_last].y - aSkidmarks[i].m_pos[aSkidmarks[i].m_last - 1].y, aSkidmarks[i].m_pos[aSkidmarks[i].m_last - 1].x - aSkidmarks[i].m_pos[aSkidmarks[i].m_last].x); - right.NormaliseSafe(); - fwd.NormaliseSafe(); + right.Normalise(); + fwd.Normalise(); 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]; + aSkidmarks[i].m_sideX[aSkidmarks[i].m_last] = right.x * turn * 0.125f; + aSkidmarks[i].m_sideY[aSkidmarks[i].m_last] = right.y * turn * 0.125f; + if(aSkidmarks[i].m_last == 1){ + aSkidmarks[i].m_sideX[0] = aSkidmarks[i].m_sideX[1]; + aSkidmarks[i].m_sideY[0] = aSkidmarks[i].m_sideY[1]; + } if(aSkidmarks[i].m_last > 8) *isBloody = false; // stop blood marks after 8 @@ -247,12 +243,15 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i 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_sideX[0] = 0.0f; + aSkidmarks[i].m_sideY[0] = 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; + if(*isBloody) + aSkidmarks[i].m_type = SKIDMARK_BLOODY; + else + aSkidmarks[i].m_type = type; }else *isBloody = false; // stop blood marks if no space } diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h index c061782d..28082f08 100644 --- a/src/render/Skidmarks.h +++ b/src/render/Skidmarks.h @@ -2,20 +2,28 @@ enum { SKIDMARK_LENGTH = 16 }; +enum eSkidmarkType +{ + SKIDMARK_NORMAL, + SKIDMARK_MUDDY, + SKIDMARK_SANDY, + SKIDMARK_BLOODY +}; + class CSkidmark { public: - uint8 m_state; - bool m_wasUpdated; - bool m_isBloody; - bool m_isMuddy; + CVector m_pos[SKIDMARK_LENGTH]; + float m_sideX[SKIDMARK_LENGTH]; + float m_sideY[SKIDMARK_LENGTH]; 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]; + uint32 m_type; + int16 m_last; + uint8 m_state; + bool m_wasUpdated; }; class CSkidmarks @@ -28,5 +36,6 @@ public: static void Clear(void); static void Update(void); static void Render(void); - static void RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody); + static void RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, eSkidmarkType type, bool *isBloody); + static void RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody); }; diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 34423d83..08dfda35 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -21,6 +21,9 @@ #include "Camera.h" #include "Shadows.h" #include "main.h" +#include "ColStore.h" +#include "Coronas.h" +#include "Script.h" RwIm3DVertex StreakVertices[4]; RwImVertexIndex StreakIndexList[12]; @@ -28,6 +31,8 @@ RwImVertexIndex StreakIndexList[12]; RwIm3DVertex TraceVertices[6]; RwImVertexIndex TraceIndexList[12]; +bool CSpecialFX::bSnapShotActive; +int32 CSpecialFX::SnapShotFrames; void CSpecialFX::Init(void) @@ -369,6 +374,8 @@ MarkerAtomicCB(RpAtomic *atomic, void *data) return atomic; } +// --MIAMI: C3dMarker and C3dMarkers done + bool C3dMarker::AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { @@ -413,6 +420,7 @@ C3dMarker::DeleteMarkerObject() m_nIdentifier = 0; m_nStartTime = 0; m_bIsUsed = false; + m_bFindZOnNextPlacement = false; m_nType = MARKERTYPE_INVALID; frame = RpAtomicGetFrame(m_pAtomic); @@ -456,6 +464,7 @@ C3dMarkers::Init() m_aMarkerArray[i].m_pAtomic = nil; m_aMarkerArray[i].m_nType = MARKERTYPE_INVALID; m_aMarkerArray[i].m_bIsUsed = false; + m_aMarkerArray[i].m_bFindZOnNextPlacement = false; m_aMarkerArray[i].m_nIdentifier = 0; m_aMarkerArray[i].m_Color.red = 255; m_aMarkerArray[i].m_Color.green = 255; @@ -501,8 +510,15 @@ C3dMarkers::Render() ActivateDirectional(); for (int i = 0; i < NUM3DMARKERS; i++) { if (m_aMarkerArray[i].m_bIsUsed) { - if (m_aMarkerArray[i].m_fCameraRange < 120.0f) + if (m_aMarkerArray[i].m_fCameraRange < 150.0f) { m_aMarkerArray[i].Render(); + if (m_aMarkerArray[i].m_nType == MARKERTYPE_ARROW) { + CCoronas::RegisterCorona((uintptr)&m_aMarkerArray[i], + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, 192, + m_aMarkerArray[i].m_Matrix.GetPosition(), 1.2f * m_aMarkerArray[i].m_fSize, 50.0f * TheCamera.LODDistMultiplier, + CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f, false); + } + } NumActiveMarkers++; m_aMarkerArray[i].m_bIsUsed = false; } else if (m_aMarkerArray[i].m_pAtomic != nil) { @@ -515,9 +531,9 @@ C3dMarker * C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { C3dMarker *pMarker; - + CVector2D playerPos = FindPlayerCentreOfWorld(0); pMarker = nil; - float dist = Sqrt((pos.x - FindPlayerCentreOfWorld(0).x) * (pos.x - FindPlayerCentreOfWorld(0).x) + (pos.y - FindPlayerCentreOfWorld(0).y) * (pos.y - FindPlayerCentreOfWorld(0).y)); + float dist = ((CVector2D)pos - playerPos).Magnitude(); if (type != MARKERTYPE_ARROW && type != MARKERTYPE_CYLINDER) return nil; @@ -590,6 +606,15 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size } if (type == MARKERTYPE_ARROW) pMarker->m_Matrix.GetPosition() = pos; + + if (pMarker->m_bFindZOnNextPlacement) { + if ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) { + float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil); + if (z != 0.0f) + pMarker->m_Matrix.GetPosition().z = z - 0.05f * size; + pMarker->m_bFindZOnNextPlacement = false; + } + } pMarker->m_bIsUsed = true; return pMarker; } @@ -599,9 +624,14 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size pMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate); if (type == MARKERTYPE_CYLINDER || type == MARKERTYPE_0 || type == MARKERTYPE_2) { - float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil); - if (z != 0.0f) - pos.z = z - 0.05f * size; + if ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) { + float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil); + if (z != 0.0f) + pos.z = z - 0.05f * size; + pMarker->m_bFindZOnNextPlacement = false; + } else { + pMarker->m_bFindZOnNextPlacement = true; + } } pMarker->m_Matrix.SetTranslate(pos.x, pos.y, pos.z); if (type == MARKERTYPE_2) { @@ -1062,7 +1092,7 @@ CMoneyMessage::Render() CFont::SetJustifyOff(); CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity)); CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::PrintString(vecOut.x, vecOut.y, m_aText); } } diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h index 2d9f18b1..8bd0d5e1 100644 --- a/src/render/SpecialFX.h +++ b/src/render/SpecialFX.h @@ -3,6 +3,9 @@ class CSpecialFX { public: + static bool bSnapShotActive; + static int32 SnapShotFrames; + static void Render(void); static void Update(void); static void Init(void); @@ -54,6 +57,13 @@ public: static void AddTrace(CVector*, CVector*); static void Render(void); static void Update(void); + +//TODO(MIAMI) + static void AddTrace(CVector *, CVector *, float, unsigned int, unsigned char) {} + static void AddTrace(CVector *a, CVector *b, int32 weapontype, class CEntity *shooter) + { + AddTrace(a, b); //TODO: temp + } }; enum @@ -77,6 +87,7 @@ public: RpMaterial *m_pMaterial; uint16 m_nType; bool m_bIsUsed; + bool m_bFindZOnNextPlacement; uint32 m_nIdentifier; RwRGBA m_Color; uint16 m_nPulsePeriod; diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 9ec7b002..401eebd0 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -148,10 +148,10 @@ CSprite::RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, fl // Fade out when too near // why not in buffered version? - if(z < 3.0f){ - if(z < 1.5f) + if(z < 2.3f){ + if(z < 1.3f) return; - int f = (z - 1.5f)/1.5f * 255; + int f = (z - 1.3f)/(2.3f-1.3f) * 255; r = f*r >> 8; g = f*g >> 8; b = f*b >> 8; @@ -263,8 +263,8 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z, { m_bFlushSpriteBufferSwitchZTest = 0; // TODO: replace with lookup - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -576,8 +576,8 @@ CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w { m_bFlushSpriteBufferSwitchZTest = 1; CRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha); - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); Set6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex], x + c*w - s*h, diff --git a/src/render/Sprite.h b/src/render/Sprite.h index ec4c1d1b..fae6684e 100644 --- a/src/render/Sprite.h +++ b/src/render/Sprite.h @@ -7,6 +7,9 @@ class CSprite static float m_fRecipNearClipPlane; static int32 m_bFlushSpriteBufferSwitchZTest; public: + static float GetNearScreenZ(void) { return m_f2DNearScreenZ; } + static float GetFarScreenZ(void) { return m_f2DFarScreenZ; } + static float CalcHorizonCoors(void); static bool CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip); static void InitSpriteBuffer(void); diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 98bb6eb2..0cd0e8bb 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -5,79 +5,32 @@ #include "Camera.h" #include "Sprite2d.h" #include "Font.h" +#include "RenderBuffer.h" -RwIm2DVertex CSprite2d::maVertices[8]; float CSprite2d::RecipNearClip; -int32 CSprite2d::mCurrentBank; -RwTexture *CSprite2d::mpBankTextures[10]; -int32 CSprite2d::mCurrentSprite[10]; -int32 CSprite2d::mBankStart[10]; -RwIm2DVertex CSprite2d::maBankVertices[500]; +float CSprite2d::NearScreenZ; +float CSprite2d::NearCamZ; +int CSprite2d::nextBufferVertex; +int CSprite2d::nextBufferIndex; +RwIm2DVertex CSprite2d::maVertices[8]; void CSprite2d::SetRecipNearClip(void) { - RecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera); + // Used but empty in VC, instead they set in InitPerFrame. Isn't that great? } void CSprite2d::InitPerFrame(void) { - int i; - - mCurrentBank = 0; - for(i = 0; i < 10; i++) - mCurrentSprite[i] = 0; -#ifndef SQUEEZE_PERFORMANCE - for(i = 0; i < 10; i++) - mpBankTextures[i] = nil; -#endif -} - -int32 -CSprite2d::GetBank(int32 n, RwTexture *tex) -{ -#ifndef SQUEEZE_PERFORMANCE - mpBankTextures[mCurrentBank] = tex; -#endif - mCurrentSprite[mCurrentBank] = 0; - mBankStart[mCurrentBank+1] = mBankStart[mCurrentBank] + n; - return mCurrentBank++; -} - -void -CSprite2d::AddSpriteToBank(int32 bank, const CRect &rect, const CRGBA &col, - float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2) -{ - SetVertices(&maBankVertices[6 * (mCurrentSprite[bank] + mBankStart[bank])], - rect, col, col, col, col, - u0, v0, u1, v1, u2, v2, u3, v3); - mCurrentSprite[bank]++; - if(mCurrentSprite[bank] + mBankStart[bank] >= mBankStart[bank+1]){ - DrawBank(bank); - mCurrentSprite[bank] = 0; - } -} - -void -CSprite2d::DrawBank(int32 bank) -{ - if(mCurrentSprite[bank] == 0) - return; -#ifndef SQUEEZE_PERFORMANCE - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, - mpBankTextures[bank] ? RwTextureGetRaster(mpBankTextures[bank]) : nil); -#else - CFont::Sprite[bank].SetRenderState(); -#endif - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, &maBankVertices[6*mBankStart[bank]], 6*mCurrentSprite[bank]); - mCurrentSprite[bank] = 0; - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + nextBufferVertex = 0; + nextBufferIndex = 0; + RecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera); + NearScreenZ = RwIm2DGetNearScreenZ(); + // not original but you're supposed to set camera z too + // wrapping all this in FIX_BUGS is too ugly + NearCamZ = RwCameraGetNearClipPlane(Scene.camera); } - - void CSprite2d::Delete(void) { @@ -122,7 +75,7 @@ CSprite2d::SetRenderState(void) void CSprite2d::Draw(float x, float y, float w, float h, const CRGBA &col) { - SetVertices(CRect(x, y, x + w, y + h), col, col, col, col, 0); + SetVertices(CRect(x, y, x + w, y + h), col, col, col, col); SetRenderState(); RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); } @@ -130,7 +83,7 @@ CSprite2d::Draw(float x, float y, float w, float h, const CRGBA &col) void CSprite2d::Draw(const CRect &rect, const CRGBA &col) { - SetVertices(rect, col, col, col, col, 0); + SetVertices(rect, col, col, col, col); SetRenderState(); RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); } @@ -147,7 +100,7 @@ CSprite2d::Draw(const CRect &rect, const CRGBA &col, void CSprite2d::Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { - SetVertices(rect, c0, c1, c2, c3, 0); + SetVertices(rect, c0, c1, c2, c3); SetRenderState(); RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); } @@ -160,24 +113,13 @@ CSprite2d::Draw(float x1, float y1, float x2, float y2, float x3, float y3, floa RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); } - // Arguments: // 2---3 // | | // 0---1 void -CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far) +CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { - float screenz, z, recipz; - - if(far){ - screenz = RwIm2DGetFarScreenZ(); - z = RwCameraGetFarClipPlane(Scene.camera); - }else{ - screenz = RwIm2DGetNearScreenZ(); - z = 1.0f/RecipNearClip; - } - recipz = 1.0f/z; float offset = 1.0f/1024.0f; // This is what we draw: @@ -186,159 +128,141 @@ CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C // 3---2 RwIm2DVertexSetScreenX(&maVertices[0], r.left); RwIm2DVertexSetScreenY(&maVertices[0], r.top); - RwIm2DVertexSetScreenZ(&maVertices[0], screenz); - RwIm2DVertexSetCameraZ(&maVertices[0], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz); + RwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a); - RwIm2DVertexSetU(&maVertices[0], 0.0f+offset, recipz); - RwIm2DVertexSetV(&maVertices[0], 0.0f+offset, recipz); + RwIm2DVertexSetU(&maVertices[0], 0.0f+offset, RecipNearClip); + RwIm2DVertexSetV(&maVertices[0], 0.0f+offset, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[1], r.right); RwIm2DVertexSetScreenY(&maVertices[1], r.top); - RwIm2DVertexSetScreenZ(&maVertices[1], screenz); - RwIm2DVertexSetCameraZ(&maVertices[1], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz); + RwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a); - RwIm2DVertexSetU(&maVertices[1], 1.0f+offset, recipz); - RwIm2DVertexSetV(&maVertices[1], 0.0f+offset, recipz); + RwIm2DVertexSetU(&maVertices[1], 1.0f+offset, RecipNearClip); + RwIm2DVertexSetV(&maVertices[1], 0.0f+offset, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[2], r.right); RwIm2DVertexSetScreenY(&maVertices[2], r.bottom); - RwIm2DVertexSetScreenZ(&maVertices[2], screenz); - RwIm2DVertexSetCameraZ(&maVertices[2], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz); + RwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a); - RwIm2DVertexSetU(&maVertices[2], 1.0f+offset, recipz); - RwIm2DVertexSetV(&maVertices[2], 1.0f+offset, recipz); + RwIm2DVertexSetU(&maVertices[2], 1.0f+offset, RecipNearClip); + RwIm2DVertexSetV(&maVertices[2], 1.0f+offset, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[3], r.left); RwIm2DVertexSetScreenY(&maVertices[3], r.bottom); - RwIm2DVertexSetScreenZ(&maVertices[3], screenz); - RwIm2DVertexSetCameraZ(&maVertices[3], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz); + RwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a); - RwIm2DVertexSetU(&maVertices[3], 0.0f+offset, recipz); - RwIm2DVertexSetV(&maVertices[3], 1.0f+offset, recipz); + RwIm2DVertexSetU(&maVertices[3], 0.0f+offset, RecipNearClip); + RwIm2DVertexSetV(&maVertices[3], 1.0f+offset, RecipNearClip); } void CSprite2d::SetVertices(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, z, recipz; - - screenz = RwIm2DGetNearScreenZ(); - z = 1.0f/RecipNearClip; - recipz = 1.0f/z; - // This is what we draw: // 0---1 // | / | // 3---2 RwIm2DVertexSetScreenX(&maVertices[0], r.left); RwIm2DVertexSetScreenY(&maVertices[0], r.top); - RwIm2DVertexSetScreenZ(&maVertices[0], screenz); - RwIm2DVertexSetCameraZ(&maVertices[0], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz); + RwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a); - RwIm2DVertexSetU(&maVertices[0], u0, recipz); - RwIm2DVertexSetV(&maVertices[0], v0, recipz); + RwIm2DVertexSetU(&maVertices[0], u0, RecipNearClip); + RwIm2DVertexSetV(&maVertices[0], v0, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[1], r.right); RwIm2DVertexSetScreenY(&maVertices[1], r.top); - RwIm2DVertexSetScreenZ(&maVertices[1], screenz); - RwIm2DVertexSetCameraZ(&maVertices[1], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz); + RwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a); - RwIm2DVertexSetU(&maVertices[1], u1, recipz); - RwIm2DVertexSetV(&maVertices[1], v1, recipz); + RwIm2DVertexSetU(&maVertices[1], u1, RecipNearClip); + RwIm2DVertexSetV(&maVertices[1], v1, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[2], r.right); RwIm2DVertexSetScreenY(&maVertices[2], r.bottom); - RwIm2DVertexSetScreenZ(&maVertices[2], screenz); - RwIm2DVertexSetCameraZ(&maVertices[2], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz); + RwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a); - RwIm2DVertexSetU(&maVertices[2], u2, recipz); - RwIm2DVertexSetV(&maVertices[2], v2, recipz); + RwIm2DVertexSetU(&maVertices[2], u2, RecipNearClip); + RwIm2DVertexSetV(&maVertices[2], v2, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[3], r.left); RwIm2DVertexSetScreenY(&maVertices[3], r.bottom); - RwIm2DVertexSetScreenZ(&maVertices[3], screenz); - RwIm2DVertexSetCameraZ(&maVertices[3], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz); + RwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a); - RwIm2DVertexSetU(&maVertices[3], u3, recipz); - RwIm2DVertexSetV(&maVertices[3], v3, recipz); + RwIm2DVertexSetU(&maVertices[3], u3, RecipNearClip); + RwIm2DVertexSetV(&maVertices[3], v3, RecipNearClip); } void CSprite2d::SetVertices(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, 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; - RwIm2DVertexSetScreenX(&maVertices[0], x3); RwIm2DVertexSetScreenY(&maVertices[0], y3); - RwIm2DVertexSetScreenZ(&maVertices[0], screenz); - RwIm2DVertexSetCameraZ(&maVertices[0], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz); + RwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a); - RwIm2DVertexSetU(&maVertices[0], 0.0f, recipz); - RwIm2DVertexSetV(&maVertices[0], 0.0f, recipz); + RwIm2DVertexSetU(&maVertices[0], 0.0f, RecipNearClip); + RwIm2DVertexSetV(&maVertices[0], 0.0f, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[1], x4); RwIm2DVertexSetScreenY(&maVertices[1], y4); - RwIm2DVertexSetScreenZ(&maVertices[1], screenz); - RwIm2DVertexSetCameraZ(&maVertices[1], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz); + RwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a); - RwIm2DVertexSetU(&maVertices[1], 1.0f, recipz); - RwIm2DVertexSetV(&maVertices[1], 0.0f, recipz); + RwIm2DVertexSetU(&maVertices[1], 1.0f, RecipNearClip); + RwIm2DVertexSetV(&maVertices[1], 0.0f, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[2], x2); RwIm2DVertexSetScreenY(&maVertices[2], y2); - RwIm2DVertexSetScreenZ(&maVertices[2], screenz); - RwIm2DVertexSetCameraZ(&maVertices[2], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz); + RwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a); - RwIm2DVertexSetU(&maVertices[2], 1.0f, recipz); - RwIm2DVertexSetV(&maVertices[2], 1.0f, recipz); + RwIm2DVertexSetU(&maVertices[2], 1.0f, RecipNearClip); + RwIm2DVertexSetV(&maVertices[2], 1.0f, RecipNearClip); RwIm2DVertexSetScreenX(&maVertices[3], x1); RwIm2DVertexSetScreenY(&maVertices[3], y1); - RwIm2DVertexSetScreenZ(&maVertices[3], screenz); - RwIm2DVertexSetCameraZ(&maVertices[3], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz); + RwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a); - RwIm2DVertexSetU(&maVertices[3], 0.0f, recipz); - RwIm2DVertexSetV(&maVertices[3], 1.0f, recipz); + RwIm2DVertexSetU(&maVertices[3], 0.0f, RecipNearClip); + RwIm2DVertexSetV(&maVertices[3], 1.0f, RecipNearClip); } void CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col) { int i; - 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]); RwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]); - RwIm2DVertexSetScreenZ(&maVertices[i], screenz + 0.0001f); - RwIm2DVertexSetCameraZ(&maVertices[i], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz); + RwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ + 0.0001f); + RwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[i], col.r, col.g, col.b, col.a); - RwIm2DVertexSetU(&maVertices[i], uvs[i*2 + 0], recipz); - RwIm2DVertexSetV(&maVertices[i], uvs[i*2 + 1], recipz); + RwIm2DVertexSetU(&maVertices[i], uvs[i*2 + 0], RecipNearClip); + RwIm2DVertexSetV(&maVertices[i], uvs[i*2 + 1], RecipNearClip); } } @@ -346,18 +270,13 @@ void CSprite2d::SetMaskVertices(int n, float *positions) { int i; - 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]); RwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]); - RwIm2DVertexSetScreenZ(&maVertices[i], screenz); - RwIm2DVertexSetCameraZ(&maVertices[i], z); - RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz); + RwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ); + RwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip); RwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255); // 0, 0, 0, 0 on PC } } @@ -366,72 +285,47 @@ 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, z; - - screenz = RwIm2DGetNearScreenZ(); - recipz = RecipNearClip; - z = RwCameraGetNearClipPlane(Scene.camera); // not done by game - RwIm2DVertexSetScreenX(&verts[0], r.left); RwIm2DVertexSetScreenY(&verts[0], r.top); - RwIm2DVertexSetScreenZ(&verts[0], screenz); - RwIm2DVertexSetCameraZ(&verts[0], z); - RwIm2DVertexSetRecipCameraZ(&verts[0], recipz); + RwIm2DVertexSetScreenZ(&verts[0], NearScreenZ); + RwIm2DVertexSetCameraZ(&verts[0], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&verts[0], RecipNearClip); RwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a); - RwIm2DVertexSetU(&verts[0], u0, recipz); - RwIm2DVertexSetV(&verts[0], v0, recipz); - - RwIm2DVertexSetScreenX(&verts[1], r.left); - RwIm2DVertexSetScreenY(&verts[1], r.bottom); - RwIm2DVertexSetScreenZ(&verts[1], screenz); - RwIm2DVertexSetCameraZ(&verts[1], z); - RwIm2DVertexSetRecipCameraZ(&verts[1], recipz); - RwIm2DVertexSetIntRGBA(&verts[1], c0.r, c0.g, c0.b, c0.a); - RwIm2DVertexSetU(&verts[1], u2, recipz); - RwIm2DVertexSetV(&verts[1], v2, recipz); + RwIm2DVertexSetU(&verts[0], u0, RecipNearClip); + RwIm2DVertexSetV(&verts[0], v0, RecipNearClip); + + RwIm2DVertexSetScreenX(&verts[1], r.right); + RwIm2DVertexSetScreenY(&verts[1], r.top); + RwIm2DVertexSetScreenZ(&verts[1], NearScreenZ); + RwIm2DVertexSetCameraZ(&verts[1], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&verts[1], RecipNearClip); + RwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a); + RwIm2DVertexSetU(&verts[1], u1, RecipNearClip); + RwIm2DVertexSetV(&verts[1], v1, RecipNearClip); RwIm2DVertexSetScreenX(&verts[2], r.right); RwIm2DVertexSetScreenY(&verts[2], r.bottom); - RwIm2DVertexSetScreenZ(&verts[2], screenz); - RwIm2DVertexSetCameraZ(&verts[2], z); - RwIm2DVertexSetRecipCameraZ(&verts[2], recipz); + RwIm2DVertexSetScreenZ(&verts[2], NearScreenZ); + RwIm2DVertexSetCameraZ(&verts[2], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&verts[2], RecipNearClip); RwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a); - RwIm2DVertexSetU(&verts[2], u3, recipz); - RwIm2DVertexSetV(&verts[2], v3, recipz); + RwIm2DVertexSetU(&verts[2], u2, RecipNearClip); + RwIm2DVertexSetV(&verts[2], v2, RecipNearClip); RwIm2DVertexSetScreenX(&verts[3], r.left); - RwIm2DVertexSetScreenY(&verts[3], r.top); - RwIm2DVertexSetScreenZ(&verts[3], screenz); - RwIm2DVertexSetCameraZ(&verts[3], z); - RwIm2DVertexSetRecipCameraZ(&verts[3], recipz); - RwIm2DVertexSetIntRGBA(&verts[3], c2.r, c2.g, c2.b, c2.a); - RwIm2DVertexSetU(&verts[3], u0, recipz); - RwIm2DVertexSetV(&verts[3], v0, recipz); - - RwIm2DVertexSetScreenX(&verts[4], r.right); - RwIm2DVertexSetScreenY(&verts[4], r.bottom); - RwIm2DVertexSetScreenZ(&verts[4], screenz); - RwIm2DVertexSetCameraZ(&verts[4], z); - RwIm2DVertexSetRecipCameraZ(&verts[4], recipz); - RwIm2DVertexSetIntRGBA(&verts[4], c1.r, c1.g, c1.b, c1.a); - RwIm2DVertexSetU(&verts[4], u3, recipz); - RwIm2DVertexSetV(&verts[4], v3, recipz); - - RwIm2DVertexSetScreenX(&verts[5], r.right); - RwIm2DVertexSetScreenY(&verts[5], r.top); - RwIm2DVertexSetScreenZ(&verts[5], screenz); - RwIm2DVertexSetCameraZ(&verts[5], z); - RwIm2DVertexSetRecipCameraZ(&verts[5], recipz); - RwIm2DVertexSetIntRGBA(&verts[5], c3.r, c3.g, c3.b, c3.a); - RwIm2DVertexSetU(&verts[5], u1, recipz); - RwIm2DVertexSetV(&verts[5], v1, recipz); - + RwIm2DVertexSetScreenY(&verts[3], r.bottom); + RwIm2DVertexSetScreenZ(&verts[3], NearScreenZ); + RwIm2DVertexSetCameraZ(&verts[3], NearCamZ); + RwIm2DVertexSetRecipCameraZ(&verts[3], RecipNearClip); + RwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a); + RwIm2DVertexSetU(&verts[3], u3, RecipNearClip); + RwIm2DVertexSetV(&verts[3], v3, RecipNearClip); } void CSprite2d::DrawRect(const CRect &r, const CRGBA &col) { - SetVertices(r, col, col, col, col, false); + SetVertices(r, col, col, col, col); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); @@ -446,7 +340,7 @@ CSprite2d::DrawRect(const CRect &r, const CRGBA &col) void CSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { - SetVertices(r, c0, c1, c2, c3, false); + SetVertices(r, c0, c1, c2, c3); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -459,7 +353,7 @@ CSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGB void CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) { - SetVertices(r, c0, c1, c2, c3, false); + SetVertices(r, c0, c1, c2, c3); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -471,6 +365,22 @@ CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); } +void +CSprite2d::DrawAnyRect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, + const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) +{ + SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, c0, c1, c2, c3); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(c0.alpha != 255 || c1.alpha != 255 || c2.alpha != 255 || c3.alpha != 255)); + RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); +} + 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); @@ -484,3 +394,37 @@ void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); } + +void +CSprite2d::AddToBuffer(const CRect &r, const CRGBA &c, float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2) +{ + SetVertices(&TempVertexBuffer.im2d[nextBufferVertex], r, c, c, c, c, u0, v0, u1, v1, u3, v3, u2, v2); + RwImVertexIndex *pIndexList = &TempBufferRenderIndexList[nextBufferIndex]; + pIndexList[0] = nextBufferVertex; + pIndexList[1] = nextBufferVertex + 1; + pIndexList[2] = nextBufferVertex + 2; + pIndexList[3] = nextBufferVertex + 3; + pIndexList[4] = nextBufferVertex; + pIndexList[5] = nextBufferVertex + 2; + nextBufferIndex += 6; + nextBufferVertex += 4; + if (IsVertexBufferFull()) + RenderVertexBuffer(); +} + +bool +CSprite2d::IsVertexBufferFull() +{ + return (nextBufferVertex > TEMPBUFFERVERTSIZE-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6); +} + +void +CSprite2d::RenderVertexBuffer() +{ + if (nextBufferVertex > 0) { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempVertexBuffer.im2d, nextBufferVertex, TempBufferRenderIndexList, nextBufferIndex); + nextBufferVertex = 0; + nextBufferIndex = 0; + } +}
\ No newline at end of file diff --git a/src/render/Sprite2d.h b/src/render/Sprite2d.h index 0e12d441..5abd8d71 100644 --- a/src/render/Sprite2d.h +++ b/src/render/Sprite2d.h @@ -3,21 +3,16 @@ class CSprite2d { static float RecipNearClip; - static int32 mCurrentBank; - static RwTexture *mpBankTextures[10]; - static int32 mCurrentSprite[10]; - static int32 mBankStart[10]; - static RwIm2DVertex maBankVertices[500]; + static float NearScreenZ; + static float NearCamZ; // not original + static int nextBufferVertex; + static int nextBufferIndex; static RwIm2DVertex maVertices[8]; public: RwTexture *m_pTexture; static void SetRecipNearClip(void); static void InitPerFrame(void); - static int32 GetBank(int32 n, RwTexture *tex); - static void AddSpriteToBank(int32 bank, const CRect &rect, const CRGBA &col, - float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2); - static void DrawBank(int32 bank); CSprite2d(void) : m_pTexture(nil) {}; ~CSprite2d(void) { Delete(); }; @@ -33,7 +28,7 @@ public: void Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3); void Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &col); - static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far); + static void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3); static void SetVertices(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); static void SetVertices(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, @@ -46,8 +41,14 @@ public: static void DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3); static void DrawRect(const CRect &r, const CRGBA &col); static void DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3); + static void DrawAnyRect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, + const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3); static void Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color); static RwIm2DVertex* GetVertices() { return maVertices; }; + + static bool IsVertexBufferFull(); + static void AddToBuffer(const CRect &a1, const CRGBA &a2, float a3, float a4, float a5, float a6, float a7, float a8, float a9, float a10); + static void RenderVertexBuffer(); }; diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index 0d94dbd6..b20a2443 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -10,50 +10,74 @@ #include "FileMgr.h" #include "Timecycle.h" -int32 CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS]; -int16 CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS]; -int16 CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS]; -int16 CTimeCycle::m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS]; -int32 CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS]; -float CTimeCycle::m_fBlurAlpha[NUMHOURS][NUMWEATHERS]; +//--MIAMI: done + +uint8 CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS]; +int8 CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS]; +int8 CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS]; +int8 CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS]; +int16 CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS]; +int16 CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fWaterRed[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fWaterGreen[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fWaterBlue[NUMHOURS][NUMWEATHERS]; +uint8 CTimeCycle::m_fWaterAlpha[NUMHOURS][NUMWEATHERS]; + float CTimeCycle::m_fCurrentAmbientRed; float CTimeCycle::m_fCurrentAmbientGreen; float CTimeCycle::m_fCurrentAmbientBlue; +float CTimeCycle::m_fCurrentAmbientRed_Obj; +float CTimeCycle::m_fCurrentAmbientGreen_Obj; +float CTimeCycle::m_fCurrentAmbientBlue_Obj; +float CTimeCycle::m_fCurrentAmbientRed_Bl; +float CTimeCycle::m_fCurrentAmbientGreen_Bl; +float CTimeCycle::m_fCurrentAmbientBlue_Bl; +float CTimeCycle::m_fCurrentAmbientRed_Obj_Bl; +float CTimeCycle::m_fCurrentAmbientGreen_Obj_Bl; +float CTimeCycle::m_fCurrentAmbientBlue_Obj_Bl; float CTimeCycle::m_fCurrentDirectionalRed; float CTimeCycle::m_fCurrentDirectionalGreen; float CTimeCycle::m_fCurrentDirectionalBlue; @@ -74,7 +98,7 @@ float CTimeCycle::m_fCurrentSpriteSize; float CTimeCycle::m_fCurrentSpriteBrightness; int32 CTimeCycle::m_nCurrentShadowStrength; int32 CTimeCycle::m_nCurrentLightShadowStrength; -int32 CTimeCycle::m_nCurrentTreeShadowStrength; +int32 CTimeCycle::m_nCurrentPoleShadowStrength; float CTimeCycle::m_fCurrentFogStart; float CTimeCycle::m_fCurrentFarClip; float CTimeCycle::m_fCurrentLightsOnGroundBrightness; @@ -90,12 +114,18 @@ int32 CTimeCycle::m_nCurrentFluffyCloudsBottomBlue; float CTimeCycle::m_fCurrentBlurRed; float CTimeCycle::m_fCurrentBlurGreen; float CTimeCycle::m_fCurrentBlurBlue; -float CTimeCycle::m_fCurrentBlurAlpha; +float CTimeCycle::m_fCurrentWaterRed; +float CTimeCycle::m_fCurrentWaterGreen; +float CTimeCycle::m_fCurrentWaterBlue; +float CTimeCycle::m_fCurrentWaterAlpha; int32 CTimeCycle::m_nCurrentFogColourRed; int32 CTimeCycle::m_nCurrentFogColourGreen; int32 CTimeCycle::m_nCurrentFogColourBlue; int32 CTimeCycle::m_FogReduction; +int32 CTimeCycle::m_bExtraColourOn; +int32 CTimeCycle::m_ExtraColour; +float CTimeCycle::m_ExtraColourInter; int32 CTimeCycle::m_CurrentStoredValue; CVector CTimeCycle::m_VectorToSun[16]; @@ -106,7 +136,6 @@ float CTimeCycle::m_fShadowSideY[16]; float CTimeCycle::m_fShadowDisplacementX[16]; float CTimeCycle::m_fShadowDisplacementY[16]; - void CTimeCycle::Initialise(void) { @@ -115,18 +144,22 @@ CTimeCycle::Initialise(void) char line[1040]; int ambR, ambG, ambB; + int ambobjR, ambobjG, ambobjB; + int ambblR, ambblG, ambblB; + int ambobjblR, ambobjblG, ambobjblB; int dirR, dirG, dirB; int skyTopR, skyTopG, skyTopB; int skyBotR, skyBotG, skyBotB; int sunCoreR, sunCoreG, sunCoreB; int sunCoronaR, sunCoronaG, sunCoronaB; float sunSz, sprSz, sprBght; - int shad, lightShad, treeShad; + int shad, lightShad, poleShad; float farClp, fogSt, lightGnd; int cloudR, cloudG, cloudB; int fluffyTopR, fluffyTopG, fluffyTopB; int fluffyBotR, fluffyBotG, fluffyBotB; - float blurR, blurG, blurB, blurA; + float blurR, blurG, blurB; + float waterR, waterG, waterB, waterA; debug("Intialising CTimeCycle...\n"); @@ -144,31 +177,49 @@ CTimeCycle::Initialise(void) bi++; bi++; } - while(work_buff[bi] != '\n') + while(work_buff[bi] != '\n' +#ifdef FIX_BUGS + && work_buff[bi] != '\0' +#endif + ) line[li++] = work_buff[bi++]; line[li] = '\0'; bi++; sscanf(line, "%d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d " "%d %d %d %d %d %d %f %f %f %d %d %d %f %f %f " - "%d %d %d %d %d %d %d %d %d %f %f %f %f", + "%d %d %d %d %d %d %d %d %d %f %f %f %f %f %f %f", &ambR, &ambG, &ambB, - &dirR, &dirG, &dirB, + &ambobjR, &ambobjG, &ambobjB, + &ambblR, &ambblG, &ambblB, + &ambobjblR, &ambobjblG, &ambobjblB, + &dirR, &dirG, &dirB, &skyTopR, &skyTopG, &skyTopB, &skyBotR, &skyBotG, &skyBotB, &sunCoreR, &sunCoreG, &sunCoreB, &sunCoronaR, &sunCoronaG, &sunCoronaB, &sunSz, &sprSz, &sprBght, - &shad, &lightShad, &treeShad, + &shad, &lightShad, &poleShad, &farClp, &fogSt, &lightGnd, &cloudR, &cloudG, &cloudB, &fluffyTopR, &fluffyTopG, &fluffyTopB, &fluffyBotR, &fluffyBotG, &fluffyBotB, - &blurR, &blurG, &blurB, &blurA); + &blurR, &blurG, &blurB, + &waterR, &waterG, &waterB, &waterA); m_nAmbientRed[h][w] = ambR; m_nAmbientGreen[h][w] = ambG; m_nAmbientBlue[h][w] = ambB; + m_nAmbientRed_Obj[h][w] = ambobjR; + m_nAmbientGreen_Obj[h][w] = ambobjG; + m_nAmbientBlue_Obj[h][w] = ambobjB; + m_nAmbientRed_Bl[h][w] = ambblR; + m_nAmbientGreen_Bl[h][w] = ambblG; + m_nAmbientBlue_Bl[h][w] = ambblB; + m_nAmbientRed_Obj_Bl[h][w] = ambobjblR; + m_nAmbientGreen_Obj_Bl[h][w] = ambobjblG; + m_nAmbientBlue_Obj_Bl[h][w] = ambobjblB; m_nDirectionalRed[h][w] = dirR; m_nDirectionalGreen[h][w] = dirG; m_nDirectionalBlue[h][w] = dirB; @@ -184,15 +235,15 @@ CTimeCycle::Initialise(void) m_nSunCoronaRed[h][w] = sunCoronaR; m_nSunCoronaGreen[h][w] = sunCoronaG; m_nSunCoronaBlue[h][w] = sunCoronaB; - m_fSunSize[h][w] = sunSz; - m_fSpriteSize[h][w] = sprSz; - m_fSpriteBrightness[h][w] = sprBght; + m_fSunSize[h][w] = sunSz * 10.0f; + m_fSpriteSize[h][w] = sprSz * 10.0f; + m_fSpriteBrightness[h][w] = sprBght * 10.0f; m_nShadowStrength[h][w] = shad; m_nLightShadowStrength[h][w] = lightShad; - m_nTreeShadowStrength[h][w] = treeShad; + m_nPoleShadowStrength[h][w] = poleShad; m_fFarClip[h][w] = farClp; m_fFogStart[h][w] = fogSt; - m_fLightsOnGroundBrightness[h][w] = lightGnd; + m_fLightsOnGroundBrightness[h][w] = lightGnd * 10.0f; m_nLowCloudsRed[h][w] = cloudR; m_nLowCloudsGreen[h][w] = cloudG; m_nLowCloudsBlue[h][w] = cloudB; @@ -205,7 +256,10 @@ CTimeCycle::Initialise(void) m_fBlurRed[h][w] = blurR; m_fBlurGreen[h][w] = blurG; m_fBlurBlue[h][w] = blurB; - m_fBlurAlpha[h][w] = blurA; + m_fWaterRed[h][w] = waterR; + m_fWaterGreen[h][w] = waterG; + m_fWaterBlue[h][w] = waterB; + m_fWaterAlpha[h][w] = waterA; } m_FogReduction = 0; @@ -213,6 +267,51 @@ CTimeCycle::Initialise(void) debug("CTimeCycle ready\n"); } +static float interp_c0, interp_c1, interp_c2, interp_c3; + +float CTimeCycle::Interpolate(int8 *a, int8 *b) +{ + return a[CWeather::OldWeatherType] * interp_c0 + + b[CWeather::OldWeatherType] * interp_c1 + + a[CWeather::NewWeatherType] * interp_c2 + + b[CWeather::NewWeatherType] * interp_c3; +} + +float CTimeCycle::Interpolate(uint8 *a, uint8 *b) +{ + return a[CWeather::OldWeatherType] * interp_c0 + + b[CWeather::OldWeatherType] * interp_c1 + + a[CWeather::NewWeatherType] * interp_c2 + + b[CWeather::NewWeatherType] * interp_c3; +} + +float CTimeCycle::Interpolate(int16 *a, int16 *b) +{ + return a[CWeather::OldWeatherType] * interp_c0 + + b[CWeather::OldWeatherType] * interp_c1 + + a[CWeather::NewWeatherType] * interp_c2 + + b[CWeather::NewWeatherType] * interp_c3; +} + +void +CTimeCycle::StartExtraColour(int32 c, bool fade) +{ + m_bExtraColourOn = true; + m_ExtraColour = c; + if(fade) + m_ExtraColourInter = 0.0f; + else + m_ExtraColourInter = 1.0f; +} + +void +CTimeCycle::StopExtraColour(bool fade) +{ + m_bExtraColourOn = false; + if(!fade) + m_ExtraColourInter = 0.0f; +} + void CTimeCycle::Update(void) { @@ -220,14 +319,14 @@ CTimeCycle::Update(void) int h2 = (h1+1)%24; int w1 = CWeather::OldWeatherType; int w2 = CWeather::NewWeatherType; - float timeInterp = CClock::GetMinutes()/60.0f; + float timeInterp = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f; // coefficients for a bilinear interpolation - float c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue); - float c1 = timeInterp * (1.0f-CWeather::InterpolationValue); - float c2 = (1.0f-timeInterp) * CWeather::InterpolationValue; - float c3 = timeInterp * CWeather::InterpolationValue; + interp_c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue); + interp_c1 = timeInterp * (1.0f-CWeather::InterpolationValue); + interp_c2 = (1.0f-timeInterp) * CWeather::InterpolationValue; + interp_c3 = timeInterp * CWeather::InterpolationValue; -#define INTERP(v) v[h1][w1]*c0 + v[h2][w1]*c1 + v[h1][w2]*c2 + v[h2][w2]*c3 +#define INTERP(v) Interpolate(v[h1], v[h2]) m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed); m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen); @@ -240,16 +339,22 @@ CTimeCycle::Update(void) m_fCurrentAmbientRed = INTERP(m_nAmbientRed); m_fCurrentAmbientGreen = INTERP(m_nAmbientGreen); m_fCurrentAmbientBlue = INTERP(m_nAmbientBlue); - m_fCurrentAmbientRed /= 255.0f; - m_fCurrentAmbientGreen /= 255.0f; - m_fCurrentAmbientBlue /= 255.0f; + + m_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj); + m_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj); + m_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj); + + m_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl); + m_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl); + m_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl); + + m_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl); + m_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl); + m_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl); m_fCurrentDirectionalRed = INTERP(m_nDirectionalRed); m_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen); m_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue); - m_fCurrentDirectionalRed /= 255.0f; - m_fCurrentDirectionalGreen /= 255.0f; - m_fCurrentDirectionalBlue /= 255.0f; m_nCurrentSunCoreRed = INTERP(m_nSunCoreRed); m_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen); @@ -259,15 +364,15 @@ CTimeCycle::Update(void) m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen); m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue); - m_fCurrentSunSize = INTERP(m_fSunSize); - m_fCurrentSpriteSize = INTERP(m_fSpriteSize); - m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness); + m_fCurrentSunSize = INTERP(m_fSunSize)/10.0f; + m_fCurrentSpriteSize = INTERP(m_fSpriteSize)/10.0f; + m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness)/10.0f; m_nCurrentShadowStrength = INTERP(m_nShadowStrength); m_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength); - m_nCurrentTreeShadowStrength = INTERP(m_nTreeShadowStrength); + m_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength); m_fCurrentFarClip = INTERP(m_fFarClip); m_fCurrentFogStart = INTERP(m_fFogStart); - m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness); + m_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness)/10.0f; m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed); m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen); @@ -284,26 +389,131 @@ CTimeCycle::Update(void) m_fCurrentBlurRed = INTERP(m_fBlurRed); m_fCurrentBlurGreen = INTERP(m_fBlurGreen); m_fCurrentBlurBlue = INTERP(m_fBlurBlue); - m_fCurrentBlurAlpha = INTERP(m_fBlurAlpha); - if(TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) - TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, m_fCurrentBlurAlpha, MOTION_BLUR_LIGHT_SCENE); + m_fCurrentWaterRed = INTERP(m_fWaterRed); + m_fCurrentWaterGreen = INTERP(m_fWaterGreen); + m_fCurrentWaterBlue = INTERP(m_fWaterBlue); + m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha); +#undef INTERP if(m_FogReduction != 0) m_fCurrentFarClip = Max(m_fCurrentFarClip, m_FogReduction/64.0f * 650.0f); - m_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3; - m_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3; - m_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3; m_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF; - float sunAngle = 2*PI*(CClock::GetMinutes() + CClock::GetHours()*60)/(24*60); + float sunAngle = 2*PI*(CClock::GetSeconds()/60.0f + CClock::GetMinutes() + CClock::GetHours()*60)/(24*60); CVector &sunPos = GetSunDirection(); sunPos.x = Sin(sunAngle); sunPos.y = 1.0f; sunPos.z = 0.2f - Cos(sunAngle); sunPos.Normalise(); + if(m_bExtraColourOn) + m_ExtraColourInter = Min(1.0f, m_ExtraColourInter + CTimer::GetTimeStep()/120.0f); + else + m_ExtraColourInter = Max(-.0f, m_ExtraColourInter - CTimer::GetTimeStep()/120.0f); + if(m_ExtraColourInter > 0.0f){ +#define INTERP(extra,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS] + (1.0f-m_ExtraColourInter)*cur) +#define INTERPscl(extra,scl,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS]/scl + (1.0f-m_ExtraColourInter)*cur) + if(m_nSkyTopRed[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 || + m_nSkyTopGreen[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 || + m_nSkyTopBlue[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0){ + m_nCurrentSkyTopRed = INTERP(m_nSkyTopRed,m_nCurrentSkyTopRed); + m_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen,m_nCurrentSkyTopGreen); + m_nCurrentSkyTopBlue = INTERP(m_nSkyTopBlue,m_nCurrentSkyTopBlue); + + m_nCurrentSkyBottomRed = INTERP(m_nSkyBottomRed,m_nCurrentSkyBottomRed); + m_nCurrentSkyBottomGreen = INTERP(m_nSkyBottomGreen,m_nCurrentSkyBottomGreen); + m_nCurrentSkyBottomBlue = INTERP(m_nSkyBottomBlue,m_nCurrentSkyBottomBlue); + + m_nCurrentSunCoreRed = INTERP(m_nSunCoreRed,m_nCurrentSunCoreRed); + m_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen,m_nCurrentSunCoreGreen); + m_nCurrentSunCoreBlue = INTERP(m_nSunCoreBlue,m_nCurrentSunCoreBlue); + + m_nCurrentSunCoronaRed = INTERP(m_nSunCoronaRed,m_nCurrentSunCoronaRed); + m_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen,m_nCurrentSunCoronaGreen); + m_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue,m_nCurrentSunCoronaBlue); + + m_fCurrentSunSize = INTERPscl(m_fSunSize,10.0f,m_fCurrentSunSize); + + m_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed,m_nCurrentLowCloudsRed); + m_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen,m_nCurrentLowCloudsGreen); + m_nCurrentLowCloudsBlue = INTERP(m_nLowCloudsBlue,m_nCurrentLowCloudsBlue); + + m_nCurrentFluffyCloudsTopRed = INTERP(m_nFluffyCloudsTopRed,m_nCurrentFluffyCloudsTopRed); + m_nCurrentFluffyCloudsTopGreen = INTERP(m_nFluffyCloudsTopGreen,m_nCurrentFluffyCloudsTopGreen); + m_nCurrentFluffyCloudsTopBlue = INTERP(m_nFluffyCloudsTopBlue,m_nCurrentFluffyCloudsTopBlue); + + m_nCurrentFluffyCloudsBottomRed = INTERP(m_nFluffyCloudsBottomRed,m_nCurrentFluffyCloudsBottomRed); + m_nCurrentFluffyCloudsBottomGreen = INTERP(m_nFluffyCloudsBottomGreen,m_nCurrentFluffyCloudsBottomGreen); + m_nCurrentFluffyCloudsBottomBlue = INTERP(m_nFluffyCloudsBottomBlue,m_nCurrentFluffyCloudsBottomBlue); + + m_fCurrentWaterRed = INTERP(m_fWaterRed,m_fCurrentWaterRed); + m_fCurrentWaterGreen = INTERP(m_fWaterGreen,m_fCurrentWaterGreen); + m_fCurrentWaterBlue = INTERP(m_fWaterBlue,m_fCurrentWaterBlue); + m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha,m_fCurrentWaterAlpha); + } + + m_fCurrentAmbientRed = INTERP(m_nAmbientRed,m_fCurrentAmbientRed); + m_fCurrentAmbientGreen = INTERP(m_nAmbientGreen,m_fCurrentAmbientGreen); + m_fCurrentAmbientBlue = INTERP(m_nAmbientBlue,m_fCurrentAmbientBlue); + + m_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj,m_fCurrentAmbientRed_Obj); + m_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj,m_fCurrentAmbientGreen_Obj); + m_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj,m_fCurrentAmbientBlue_Obj); + + m_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl,m_fCurrentAmbientRed_Bl); + m_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl,m_fCurrentAmbientGreen_Bl); + m_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl,m_fCurrentAmbientBlue_Bl); + + m_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl,m_fCurrentAmbientRed_Obj_Bl); + m_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl,m_fCurrentAmbientGreen_Obj_Bl); + m_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl,m_fCurrentAmbientBlue_Obj_Bl); + + m_fCurrentDirectionalRed = INTERP(m_nDirectionalRed,m_fCurrentDirectionalRed); + m_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen,m_fCurrentDirectionalGreen); + m_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue,m_fCurrentDirectionalBlue); + + m_fCurrentSpriteSize = INTERPscl(m_fSpriteSize,10.0f,m_fCurrentSpriteSize); + m_fCurrentSpriteBrightness = INTERPscl(m_fSpriteBrightness,10.0f,m_fCurrentSpriteBrightness); + m_nCurrentShadowStrength = INTERP(m_nShadowStrength,m_nCurrentShadowStrength); + m_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength,m_nCurrentLightShadowStrength); + m_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength,m_nCurrentPoleShadowStrength); + m_fCurrentFarClip = INTERP(m_fFarClip,m_fCurrentFarClip); + m_fCurrentFogStart = INTERP(m_fFogStart,m_fCurrentFogStart); + m_fCurrentLightsOnGroundBrightness = INTERPscl(m_fLightsOnGroundBrightness,10.0f,m_fCurrentLightsOnGroundBrightness); + + m_fCurrentBlurRed = INTERP(m_fBlurRed,m_fCurrentBlurRed); + m_fCurrentBlurGreen = INTERP(m_fBlurGreen,m_fCurrentBlurGreen); + m_fCurrentBlurBlue = INTERP(m_fBlurBlue,m_fCurrentBlurBlue); + +#undef INTERP +#undef INTERPscl + } + + if(TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) + TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, 5, MOTION_BLUR_LIGHT_SCENE); + + m_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3; + m_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3; + m_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3; + + m_fCurrentAmbientRed /= 255.0f; + m_fCurrentAmbientGreen /= 255.0f; + m_fCurrentAmbientBlue /= 255.0f; + m_fCurrentAmbientRed_Obj /= 255.0f; + m_fCurrentAmbientGreen_Obj /= 255.0f; + m_fCurrentAmbientBlue_Obj /= 255.0f; + m_fCurrentAmbientRed_Bl /= 255.0f; + m_fCurrentAmbientGreen_Bl /= 255.0f; + m_fCurrentAmbientBlue_Bl /= 255.0f; + m_fCurrentAmbientRed_Obj_Bl /= 255.0f; + m_fCurrentAmbientGreen_Obj_Bl /= 255.0f; + m_fCurrentAmbientBlue_Obj_Bl /= 255.0f; + m_fCurrentDirectionalRed /= 255.0f; + m_fCurrentDirectionalGreen /= 255.0f; + m_fCurrentDirectionalBlue /= 255.0f; + CShadows::CalcPedShadowValues(sunPos, &m_fShadowFrontX[m_CurrentStoredValue], &m_fShadowFrontY[m_CurrentStoredValue], &m_fShadowSideX[m_CurrentStoredValue], &m_fShadowSideY[m_CurrentStoredValue], diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index d5d7b67a..da911b75 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -2,50 +2,71 @@ class CTimeCycle { - static int32 m_nAmbientRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nAmbientGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nAmbientBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nDirectionalRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nDirectionalGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nDirectionalBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nSkyTopRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nSkyTopGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nSkyTopBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nSkyBottomRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nSunCoreRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nSunCoreGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nSunCoreBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nSunCoronaRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS]; - static float m_fSunSize[NUMHOURS][NUMWEATHERS]; - static float m_fSpriteSize[NUMHOURS][NUMWEATHERS]; - static float m_fSpriteBrightness[NUMHOURS][NUMWEATHERS]; - static int16 m_nShadowStrength[NUMHOURS][NUMWEATHERS]; - static int16 m_nLightShadowStrength[NUMHOURS][NUMWEATHERS]; - static int16 m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS]; - static float m_fFogStart[NUMHOURS][NUMWEATHERS]; - static float m_fFarClip[NUMHOURS][NUMWEATHERS]; - static float m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS]; - static int32 m_nLowCloudsRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS]; - static int32 m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS]; - static int32 m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS]; - static int32 m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS]; - static float m_fBlurRed[NUMHOURS][NUMWEATHERS]; - static float m_fBlurGreen[NUMHOURS][NUMWEATHERS]; - static float m_fBlurBlue[NUMHOURS][NUMWEATHERS]; - static float m_fBlurAlpha[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS]; + static uint8 m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS]; + static uint8 m_nDirectionalRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nDirectionalGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nDirectionalBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSkyTopRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSkyTopGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSkyTopBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSkyBottomRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSunCoreRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSunCoreGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSunCoreBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSunCoronaRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS]; + static int8 m_fSunSize[NUMHOURS][NUMWEATHERS]; + static int8 m_fSpriteSize[NUMHOURS][NUMWEATHERS]; + static int8 m_fSpriteBrightness[NUMHOURS][NUMWEATHERS]; + static uint8 m_nShadowStrength[NUMHOURS][NUMWEATHERS]; + static uint8 m_nLightShadowStrength[NUMHOURS][NUMWEATHERS]; + static uint8 m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS]; + static int16 m_fFogStart[NUMHOURS][NUMWEATHERS]; + static int16 m_fFarClip[NUMHOURS][NUMWEATHERS]; + static uint8 m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS]; + static uint8 m_nLowCloudsRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_fBlurRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_fBlurGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_fBlurBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_fWaterRed[NUMHOURS][NUMWEATHERS]; + static uint8 m_fWaterGreen[NUMHOURS][NUMWEATHERS]; + static uint8 m_fWaterBlue[NUMHOURS][NUMWEATHERS]; + static uint8 m_fWaterAlpha[NUMHOURS][NUMWEATHERS]; static float m_fCurrentAmbientRed; static float m_fCurrentAmbientGreen; static float m_fCurrentAmbientBlue; + static float m_fCurrentAmbientRed_Obj; + static float m_fCurrentAmbientGreen_Obj; + static float m_fCurrentAmbientBlue_Obj; + static float m_fCurrentAmbientRed_Bl; + static float m_fCurrentAmbientGreen_Bl; + static float m_fCurrentAmbientBlue_Bl; + static float m_fCurrentAmbientRed_Obj_Bl; + static float m_fCurrentAmbientGreen_Obj_Bl; + static float m_fCurrentAmbientBlue_Obj_Bl; static float m_fCurrentDirectionalRed; static float m_fCurrentDirectionalGreen; static float m_fCurrentDirectionalBlue; @@ -66,7 +87,7 @@ class CTimeCycle static float m_fCurrentSpriteBrightness; static int32 m_nCurrentShadowStrength; static int32 m_nCurrentLightShadowStrength; - static int32 m_nCurrentTreeShadowStrength; + static int32 m_nCurrentPoleShadowStrength; static float m_fCurrentFogStart; static float m_fCurrentFarClip; static float m_fCurrentLightsOnGroundBrightness; @@ -82,7 +103,10 @@ class CTimeCycle static float m_fCurrentBlurRed; static float m_fCurrentBlurGreen; static float m_fCurrentBlurBlue; - static float m_fCurrentBlurAlpha; + static float m_fCurrentWaterRed; + static float m_fCurrentWaterGreen; + static float m_fCurrentWaterBlue; + static float m_fCurrentWaterAlpha; static int32 m_nCurrentFogColourRed; static int32 m_nCurrentFogColourGreen; static int32 m_nCurrentFogColourBlue; @@ -90,6 +114,9 @@ class CTimeCycle static int32 m_FogReduction; public: + static int32 m_bExtraColourOn; + static int32 m_ExtraColour; + static float m_ExtraColourInter; static int32 m_CurrentStoredValue; static CVector m_VectorToSun[16]; static float m_fShadowFrontX[16]; @@ -102,6 +129,15 @@ public: static float GetAmbientRed(void) { return m_fCurrentAmbientRed; } static float GetAmbientGreen(void) { return m_fCurrentAmbientGreen; } static float GetAmbientBlue(void) { return m_fCurrentAmbientBlue; } + static float GetAmbientRed_Obj(void) { return m_fCurrentAmbientRed_Obj; } + static float GetAmbientGreen_Obj(void) { return m_fCurrentAmbientGreen_Obj; } + static float GetAmbientBlue_Obj(void) { return m_fCurrentAmbientBlue_Obj; } + static float GetAmbientRed_Bl(void) { return m_fCurrentAmbientRed_Bl; } + static float GetAmbientGreen_Bl(void) { return m_fCurrentAmbientGreen_Bl; } + static float GetAmbientBlue_Bl(void) { return m_fCurrentAmbientBlue_Bl; } + static float GetAmbientRed_Obj_Bl(void) { return m_fCurrentAmbientRed_Obj_Bl; } + static float GetAmbientGreen_Obj_Bl(void) { return m_fCurrentAmbientGreen_Obj_Bl; } + static float GetAmbientBlue_Obj_Bl(void) { return m_fCurrentAmbientBlue_Obj_Bl; } static float GetDirectionalRed(void) { return m_fCurrentDirectionalRed; } static float GetDirectionalGreen(void) { return m_fCurrentDirectionalGreen; } static float GetDirectionalBlue(void) { return m_fCurrentDirectionalBlue; } @@ -140,8 +176,21 @@ public: static int32 GetFogBlue(void) { return m_nCurrentFogColourBlue; } static int32 GetFogReduction(void) { return m_FogReduction; } + static int32 GetBlurRed(void) { return m_fCurrentBlurRed; } + static int32 GetBlurGreen(void) { return m_fCurrentBlurGreen; } + static int32 GetBlurBlue(void) { return m_fCurrentBlurBlue; } + static int32 GetWaterRed(void) { return m_fCurrentWaterRed; } + static int32 GetWaterGreen(void) { return m_fCurrentWaterGreen; } + static int32 GetWaterBlue(void) { return m_fCurrentWaterBlue; } + static int32 GetWaterAlpha(void) { return m_fCurrentWaterAlpha; } + static void Initialise(void); static void Update(void); + static float Interpolate(int8 *a, int8 *b); + static float Interpolate(uint8 *a, uint8 *b); + static float Interpolate(int16 *a, int16 *b); + static void StartExtraColour(int32 c, bool fade); + static void StopExtraColour(bool fade); static CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; } static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; } static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; } diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp index 2b34db37..91304be3 100644 --- a/src/render/WaterCannon.cpp +++ b/src/render/WaterCannon.cpp @@ -11,6 +11,9 @@ #include "Fire.h" #include "WaterLevel.h" #include "Camera.h" +#include "Particle.h" + +// --MIAMI: file done #define WATERCANNONVERTS 4 #define WATERCANNONINDEXES 12 @@ -64,7 +67,7 @@ void CWaterCannon::Update_OncePerFrame(int16 index) if (CTimer::GetTimeInMilliseconds() > m_nTimeCreated + WATERCANNON_LIFETIME ) { - m_nCur = (m_nCur + 1) % -NUM_SEGMENTPOINTS; + m_nCur = (m_nCur + 1) % NUM_SEGMENTPOINTS; m_abUsed[m_nCur] = false; } @@ -77,9 +80,13 @@ void CWaterCannon::Update_OncePerFrame(int16 index) } } - int32 extinguishingPoint = CGeneral::GetRandomNumber() & (NUM_SEGMENTPOINTS - 1); - if ( m_abUsed[extinguishingPoint] ) - gFireManager.ExtinguishPoint(m_avecPos[extinguishingPoint], 3.0f); + for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ ) + { + if ( m_abUsed[i] && gFireManager.ExtinguishPointWithWater(m_avecPos[i], 4.0f) ) + { + break; + } + } if ( ((index + CTimer::GetFrameCounter()) & 3) == 0 ) PushPeds(); @@ -124,7 +131,7 @@ void CWaterCannon::Render(void) RwIm3DVertexSetV(&WaterCannonVertices[2], v); RwIm3DVertexSetV(&WaterCannonVertices[3], v); - int16 pointA = m_nCur % -NUM_SEGMENTPOINTS; + int16 pointA = m_nCur % NUM_SEGMENTPOINTS; int16 pointB = pointA - 1; if ( (pointA - 1) < 0 ) @@ -231,11 +238,16 @@ void CWaterCannon::PushPeds(void) ped->m_vecMoveSpeed.x = (0.6f * m_avecVelocity[j].x + ped->m_vecMoveSpeed.x) * 0.5f; ped->m_vecMoveSpeed.y = (0.6f * m_avecVelocity[j].y + ped->m_vecMoveSpeed.y) * 0.5f; - ped->SetFall(2000, AnimationId(ANIM_KO_SKID_FRONT + localDir), 0); - - CFire *fire = ped->m_pFire; - if ( fire ) - fire->Extinguish(); + float pedSpeed2D = ped->m_vecMoveSpeed.Magnitude2D(); + + if ( pedSpeed2D > 0.2f ) { + ped->m_vecMoveSpeed.x *= (0.2f / pedSpeed2D); + ped->m_vecMoveSpeed.y *= (0.2f / pedSpeed2D); + } + ped->SetFall(2000, (AnimationId)(localDir + ANIM_KO_SKID_FRONT), 0); + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, ped->GetPosition(), ped->m_vecMoveSpeed * 0.3f, 0, 0.5f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, ped->GetPosition(), ped->m_vecMoveSpeed * -0.3f + CVector(0.f, 0.f, 0.5f), 0, 0.5f, + CGeneral::GetRandomNumberInRange(0.f, 10.f), CGeneral::GetRandomNumberInRange(0.f, 90.f), 1); j = NUM_SEGMENTPOINTS; } diff --git a/src/render/WaterCreatures.cpp b/src/render/WaterCreatures.cpp new file mode 100644 index 00000000..90f24183 --- /dev/null +++ b/src/render/WaterCreatures.cpp @@ -0,0 +1,267 @@ +#include "WaterCreatures.h" +#include "ModelIndices.h" +#include "World.h" +#include "WaterLevel.h" +#include "Camera.h" +#include "PlayerPed.h" +#include "config.h" +#include "General.h" + +int CWaterCreatures::nNumActiveSeaLifeForms; +CWaterCreature CWaterCreatures::aWaterCreatures[NUM_WATER_CREATURES]; + +struct WaterCreatureProperties aProperties[65] = { + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_JELLYFISH, 0.01f, 2.2f, 0.0005f, 3.5f }, + { &MI_JELLYFISH01, 0.01f, 2.2f, 0.0005f, 3.5f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_TURTLE, 0.01f, 2.0f, 0.0005f, 4.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_DOLPHIN, 0.03f, 1.5f, 0.0005f, 4.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_SHARK, 0.03f, 0.4f, 0.0005f, 4.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, +}; + +CWaterCreature::CWaterCreature() { + Free(); +} + +CWaterCreature::~CWaterCreature() { + //looks like unused +} + +void CWaterCreature::Initialise(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) { + this->m_pObj = pObj; + this->m_fRightMult = fRightMult; + this->m_fZTurnSpeed = fZTurnSpeed; + this->m_fWaterDepth = fWaterDepth; + this->m_alpha = alpha; + this->m_state = state; +} + +void CWaterCreature::Allocate(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) { + CWaterCreature::Initialise(pObj, fRightMult, fZTurnSpeed, fWaterDepth, alpha, state); +} + +void CWaterCreature::Free() { + CWaterCreature::Initialise(nil, 0.0f, 0.0f, 0.0f, 0, WATER_CREATURE_DISABLED); +} + +CWaterCreature *CWaterCreatures::GetFishStructSlot() { + for (int i = 0; i < NUM_WATER_CREATURES; i++) + if (aWaterCreatures[i].m_state == WATER_CREATURE_DISABLED) + return &aWaterCreatures[i]; + + return nil; +} + +CObject *CWaterCreatures::CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle) { + if (CObject::nNoTempObjects >= 40) + return nil; + + CObject *pObj = new CObject(modelID, true); + + if (!pObj) return nil; + + pObj->GetMatrix().GetPosition() = pos; + pObj->GetMatrix().UpdateRW(); + pObj->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + pObj->GetMatrix().SetRotateZOnly(DEGTORAD(zRotAngle)); + pObj->GetMatrix().UpdateRW(); + pObj->ObjectCreatedBy = CONTROLLED_SUB_OBJECT; + pObj->bIsStatic = false; + + if (pObj->ObjectCreatedBy == TEMP_OBJECT) { + CObject::nNoTempObjects++; + pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000; + } + + pObj->bTouchingWater = true; + pObj->bUnderwater = true; + CWorld::Add(pObj); + + return pObj; +} + +bool CWaterCreatures::IsSpaceForMoreWaterCreatures() { + return nNumActiveSeaLifeForms < NUM_WATER_CREATURES; +} + +float CWaterCreatures::CalculateFishHeading(CVector const& pos1, CVector const& pos2) { + CVector delta = pos1 - pos2; + delta.Normalise(); + + return Atan2(-delta.x, delta.y); +} + +void CWaterCreatures::CreateOne(CVector const& pos, int32 modelID) { + if (!IsSpaceForMoreWaterCreatures()) + return; + + CVector storedPos = pos; + float fDepth, fLevelNoWaves; + if (!TheCamera.IsSphereVisible(storedPos, 3.0f) + && CWaterLevel::GetWaterDepth(storedPos, &fDepth, &fLevelNoWaves, nil) && fDepth > 4.5f) { + + if (modelID == -1 || modelID < 0 || modelID > 64) + modelID = CGeneral::GetRandomNumberInRange(0, 64); + + WaterCreatureProperties *creature = &aProperties[modelID]; + storedPos.z = fLevelNoWaves - creature->fLevel; + float fRightMult = CGeneral::GetRandomNumberInRange(0.0f, creature->fRightMult) + 0.01f; + float angle = CWaterCreatures::CalculateFishHeading(FindPlayerPed()->GetPosition(), storedPos); + + CObject *fish = CreateSeaLifeForm(storedPos, *(int16*)creature->modelID, angle); + if (!fish) return; + + fish->SetRwObjectAlpha(255); + CWaterCreature *wc = GetFishStructSlot(); + wc->Allocate(fish, fRightMult, 0.0f, creature->fWaterDepth, 255, WATER_CREATURE_ALLOCATED); + nNumActiveSeaLifeForms++; + } +} + +void CWaterCreatures::FreeFishStructSlot(CWaterCreature *wc) { + wc->Free(); +} + +void CWaterCreatures::UpdateAll() { + if (nNumActiveSeaLifeForms == 0) + return; + + CVector playerPos = FindPlayerPed()->GetPosition(); + for (int i = 0; i < NUM_WATER_CREATURES; i++) { + switch (aWaterCreatures[i].m_state) { + case WATER_CREATURE_ACTIVE: + aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000; + if (!aWaterCreatures[i].m_pObj->GetIsOnScreen()) { + aWaterCreatures[i].m_pObj->SetRwObjectAlpha(0); + aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE; + break; + } + case WATER_CREATURE_ALLOCATED: { + if ((playerPos - aWaterCreatures[i].m_pObj->GetPosition()).Magnitude() < SQR(75.0f)) { + if (aWaterCreatures[i].m_alpha < 255) + aWaterCreatures[i].m_alpha = Min(aWaterCreatures[i].m_alpha + 4, 255); + aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha); + CVector newRight = aWaterCreatures[i].m_pObj->GetRight(); + newRight.Normalise(); + aWaterCreatures[i].m_pObj->m_vecMoveSpeed = newRight * aWaterCreatures[i].m_fRightMult; + aWaterCreatures[i].m_pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, aWaterCreatures[i].m_fZTurnSpeed); + aWaterCreatures[i].m_pObj->bIsStatic = false; + float fDepth = 0.0; + CWaterLevel::GetWaterDepth(aWaterCreatures[i].m_pObj->GetPosition(), &fDepth, nil, nil); + if (aWaterCreatures[i].m_fWaterDepth < fDepth) { + if (aWaterCreatures[i].m_pObj->m_nEndOfLifeTime - 40000 <= CTimer::GetTimeInMilliseconds()) + aWaterCreatures[i].m_state = WATER_CREATURE_ACTIVE; + } + else { + aWaterCreatures[i].m_state = WATER_CREATURE_UPDATE; + } + + } + else { + aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE; + } + break; + } + case WATER_CREATURE_UPDATE: { + aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000; + if (aWaterCreatures[i].m_alpha <= 0) { + aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE; + } + else { + aWaterCreatures[i].m_alpha = Max(aWaterCreatures[i].m_alpha - 6, 0); + aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha); + CVector newRight = aWaterCreatures[i].m_pObj->GetRight(); + newRight.Normalise(); + newRight.x *= aWaterCreatures[i].m_fRightMult; + newRight.y *= aWaterCreatures[i].m_fRightMult; + newRight.z -= 0.015f; + aWaterCreatures[i].m_pObj->m_vecMoveSpeed = newRight; + + if (!aWaterCreatures[i].m_pObj->GetIsOnScreen()) + aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE; + } + break; + } + case WATER_CREATURE_TO_REMOVE: + if (aWaterCreatures[i].m_pObj) + CWorld::Remove(aWaterCreatures[i].m_pObj); + FreeFishStructSlot(&aWaterCreatures[i]); + nNumActiveSeaLifeForms--; + aWaterCreatures[i].m_state = WATER_CREATURE_DISABLED; + break; + default: + break; + } + } +} + +void CWaterCreatures::RemoveAll() { + for (int i = 0; i < NUM_WATER_CREATURES; i++) { + if (aWaterCreatures[i].m_state != WATER_CREATURE_DISABLED) { + CWorld::Remove(aWaterCreatures[i].m_pObj); + FreeFishStructSlot(&aWaterCreatures[i]); + aWaterCreatures[i].m_state = WATER_CREATURE_DISABLED; + nNumActiveSeaLifeForms--; + } + } +}
\ No newline at end of file diff --git a/src/render/WaterCreatures.h b/src/render/WaterCreatures.h new file mode 100644 index 00000000..7dcaa288 --- /dev/null +++ b/src/render/WaterCreatures.h @@ -0,0 +1,49 @@ +#pragma once +#include "Object.h" + +enum eFishSlotState { + WATER_CREATURE_ALLOCATED = 0, + WATER_CREATURE_ACTIVE, + WATER_CREATURE_UPDATE, + WATER_CREATURE_TO_REMOVE, + WATER_CREATURE_DISABLED +}; + +class CWaterCreature { +public: + CObject *m_pObj; + float m_fRightMult; + float m_fZTurnSpeed; + int32 m_alpha; + float m_fWaterDepth; + int32 m_state; + + CWaterCreature(); + ~CWaterCreature(); + void Allocate(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state); + void Free(); + void Initialise(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state); +}; + +class CWaterCreatures { + +public: + static CWaterCreature aWaterCreatures[NUM_WATER_CREATURES]; + static int32 nNumActiveSeaLifeForms; + static CObject *CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle); + static void CreateOne(CVector const& pos, int32 modelID); + static void UpdateAll(); + static void FreeFishStructSlot(CWaterCreature *wc); + static bool IsSpaceForMoreWaterCreatures(); + static float CalculateFishHeading(CVector const& pos1, CVector const& pos2); + static void RemoveAll(); + static CWaterCreature* GetFishStructSlot(); +}; + +struct WaterCreatureProperties { + int16 *modelID; + float fRightMult; + float fLevel; + float fUnknown; //unused + float fWaterDepth; +};
\ No newline at end of file diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 6133b1d7..ec9485d2 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -6,6 +6,7 @@ #include "Weather.h" #include "Camera.h" #include "Vehicle.h" +#include "PlayerPed.h" #include "Boat.h" #include "World.h" #include "General.h" @@ -19,46 +20,102 @@ #include "CdStream.h" #include "Pad.h" #include "RenderBuffer.h" +#include <rwcore.h> #include <rpworld.h> +#include <rpmatfx.h> +#include "Occlusion.h" +#include "Replay.h" #include "WaterLevel.h" +#include "SurfaceTable.h" +#include "WaterCreatures.h" +#define RwIm3DVertexSet_RGBA(vert, rgba) RwIm3DVertexSetRGBA(vert, rgba.red, rgba.green, rgba.blue, rgba.alpha) // (RwRGBAAssign(&(_dst)->color, &_src)) float TEXTURE_ADDU; float TEXTURE_ADDV; +float _TEXTURE_MASK_ADDU; +float _TEXTURE_MASK_ADDV; + +float _TEXTURE_WAKE_ADDU; +float _TEXTURE_WAKE_ADDV; + int32 CWaterLevel::ms_nNoOfWaterLevels; float CWaterLevel::ms_aWaterZs[48]; CRect CWaterLevel::ms_aWaterRects[48]; -uint8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; -uint8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; +uint8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SECTORS][WATER_BLOCK_SECTORS]; +uint8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SECTORS][WATER_FINEBLOCK_SECTORS]; bool CWaterLevel::WavesCalculatedThisFrame; + + +bool CWaterLevel::RequireWavySector; +bool CWaterLevel::MaskCalculatedThisFrame; +CVector CWaterLevel::PreCalculatedMaskPosn; +bool CWaterLevel::m_bRenderSeaBed; +int32 CWaterLevel::m_nRenderWaterLayers; + RpAtomic *CWaterLevel::ms_pWavyAtomic; -RpGeometry *CWaterLevel::apGeomArray[8]; -int16 CWaterLevel::nGeomUsed; +RpAtomic *CWaterLevel::ms_pMaskAtomic; //"Custom" Don´t Render Water Toggle bool gbDontRenderWater; -//RwTexture *gpWaterTex; -//RwRaster *gpWaterRaster; RwTexture *gpWaterTex; -RwRaster *gpWaterRaster; +RwTexture *gpWaterEnvTex; +RwTexture *gpWaterEnvBaseTex; +RwTexture *gpWaterWakeTex; +RwRaster *gpWaterRaster; +RwRaster *gpWaterEnvRaster; +RwRaster *gpWaterEnvBaseRaster; +RwRaster *gpWaterWakeRaster; -const float fAdd1 = 180.0f; -const float fAdd2 = 80.0f; -const float fRedMult = 0.6f; -const float fGreenMult = 1.0f; -const float fBlueMult = 1.4f; +bool _bSeaLife; +float _fWaterZOffset = 0.5f; +#ifdef PC_WATER +float fEnvScale = 0.25f; +#else +float fEnvScale = 0.5f; +#endif +float fWave2InvLength = 0.03f; +float fWave2NormScale = 0.5f; +float fWave2Ampl = 0.1f; +uint8 nWaterAlpha = 192; +uint8 nWakeAlpha = 192; +float fUnder1 = 4.0; +float fUnder2 = 2.5; +float fUnder3 = 1.5; +int nMaskAlpha = 230; +float fAdd1 = 180.0f; +float fAdd2 = 80.0; +float fRedMult = 0.6f; +float fGreenMult = 1.0f; +float fBlueMult = 1.4f; +float fAlphaMult = 500.0f; +float fAlphaBase = 30.0f; +float fRandomMoveDiv = 8.0f; +float fRandomDamp = 0.99f; +float fNormMult = 2.0f; +float fNormMultB = 1.0f; +float fBumpScale = 1.5; +float fBumpTexRepeat = 2.0; +float fNormalDirectionScalar1 = 2.0f; +float fNormalDirectionScalar2 = 1.0f; +bool bTestDoNormals = true; +float fSeaBedZ = 25.0f; +float aAlphaFade[5] = { 0.4f, 1.0f, 0.2f, 1.0f, 0.4f}; //CWaterLevel::RenderWakeSegment +float fFlatWaterBlendRange = 0.05f; +float fStartBlendDistanceAdd = 64.0f; +float fMinWaterAlphaMult = -30.0f; void -CWaterLevel::Initialise(Const char *pWaterDat) +WaterLevelInitialise(Const char *pWaterDat) { - ms_nNoOfWaterLevels = 0; + CWaterLevel::ms_nNoOfWaterLevels = 0; - int32 hFile = -1; + int32 hFile; do { @@ -70,11 +127,11 @@ CWaterLevel::Initialise(Const char *pWaterDat) { if ( hFile >= 0 ) { - CFileMgr::Read(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels)); - CFileMgr::Read(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs)); - CFileMgr::Read(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects)); - CFileMgr::Read(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList)); - CFileMgr::Read(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList)); + CFileMgr::Read(hFile, (char *)&CWaterLevel::ms_nNoOfWaterLevels, sizeof(CWaterLevel::ms_nNoOfWaterLevels)); + CFileMgr::Read(hFile, (char *)CWaterLevel::ms_aWaterZs, sizeof(CWaterLevel::ms_aWaterZs)); + CFileMgr::Read(hFile, (char *)CWaterLevel::ms_aWaterRects, sizeof(CWaterLevel::ms_aWaterRects)); + CFileMgr::Read(hFile, (char *)CWaterLevel::aWaterBlockList, sizeof(CWaterLevel::aWaterBlockList)); + CFileMgr::Read(hFile, (char *)CWaterLevel::aWaterFineBlockList, sizeof(CWaterLevel::aWaterFineBlockList)); } CFileMgr::CloseFile(hFile); @@ -85,14 +142,27 @@ CWaterLevel::Initialise(Const char *pWaterDat) int32 slot = CTxdStore::FindTxdSlot("particle"); CTxdStore::SetCurrentTxd(slot); - if ( gpWaterTex == NULL ) - gpWaterTex = RwTextureRead("water_old", NULL); + if ( gpWaterTex == nil ) + gpWaterTex = RwTextureRead("waterclear256", nil); gpWaterRaster = RwTextureGetRaster(gpWaterTex); + if ( gpWaterEnvTex == nil ) + gpWaterEnvTex = RwTextureRead("waterreflection2", nil); + gpWaterEnvRaster = RwTextureGetRaster(gpWaterEnvTex); + +#ifdef PC_WATER + if ( gpWaterEnvBaseTex == nil ) + gpWaterEnvBaseTex = RwTextureRead("sandywater", nil); + gpWaterEnvBaseRaster = RwTextureGetRaster(gpWaterEnvBaseTex); +#endif + + if ( gpWaterWakeTex == nil ) + gpWaterWakeTex = RwTextureRead("waterwake", nil); + gpWaterWakeRaster = RwTextureGetRaster(gpWaterWakeTex); + CTxdStore::PopCurrentTxd(); - CreateWavyAtomic(); - FreeBoatWakeArray(); + CWaterLevel::CreateWavyAtomic(); printf("Done Initing waterlevels\n"); } @@ -100,92 +170,153 @@ CWaterLevel::Initialise(Const char *pWaterDat) void CWaterLevel::Shutdown() { - FreeBoatWakeArray(); DestroyWavyAtomic(); - if ( gpWaterTex != NULL ) - { - RwTextureDestroy(gpWaterTex); - gpWaterTex = NULL; - } +#define _DELETE_TEXTURE(t) if ( t ) \ + { \ + RwTextureDestroy(t); \ + t = nil; \ + } + + _DELETE_TEXTURE(gpWaterTex); + _DELETE_TEXTURE(gpWaterEnvTex); + _DELETE_TEXTURE(gpWaterEnvBaseTex); + +#undef _DELETE_TEXTURE } void CWaterLevel::CreateWavyAtomic() { RpGeometry *wavyGeometry; + RpGeometry *maskGeometry; RpMaterial *wavyMaterial; - RpTriangle *wavyTriangles; + RpMaterial *maskMaterial; + + RpTriangle *wavytlist; + RpTriangle *masktlist; + RpMorphTarget *wavyMorphTarget; - RwSphere boundingSphere; + RpMorphTarget *maskMorphTarget; + + RwSphere boundingSphere; + RwV3d *wavyVert; - + RwV3d *wavyNormal; + + RwV3d *maskVert; + RwV3d *maskNormal; + RwFrame *wavyFrame; + RwFrame *maskFrame; { - wavyGeometry = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP + wavyGeometry = RpGeometryCreate(17*17, 512, rpGEOMETRYTRISTRIP |rpGEOMETRYTEXTURED |rpGEOMETRYPRELIT + |rpGEOMETRYNORMALS |rpGEOMETRYMODULATEMATERIALCOLOR); - - ASSERT(wavyGeometry != NULL); - +#ifdef PC_WATER + RpGeometryAddMorphTarget(wavyGeometry); +#endif + } + + { + maskGeometry = RpGeometryCreate(33*33, 2048, rpGEOMETRYTRISTRIP + |rpGEOMETRYTEXTURED + |rpGEOMETRYPRELIT + |rpGEOMETRYNORMALS + |rpGEOMETRYMODULATEMATERIALCOLOR); +#ifdef PC_WATER + RpGeometryAddMorphTarget(maskGeometry); +#endif } { wavyMaterial = RpMaterialCreate(); - - ASSERT(wavyMaterial != NULL); - ASSERT(gpWaterTex != NULL); - RpMaterialSetTexture(wavyMaterial, gpWaterTex); + RwRGBA watercolor = { 255, 255, 255, 192 }; + RpMaterialSetColor(wavyMaterial, &watercolor); } { - wavyTriangles = RpGeometryGetTriangles(wavyGeometry); - - ASSERT(wavyTriangles != NULL); - /* - [B] [C] - *********** - * * * - * * * - * * * - * * * - *********** - [A] [D] - */ + maskMaterial = RpMaterialCreate(); +#ifdef PC_WATER + RpMaterialSetTexture(maskMaterial, gpWaterEnvBaseTex); +#else + RpMaterialSetTexture(maskMaterial, gpWaterTex); +#endif + RwRGBA watercolor = { 255, 255, 255, 192 }; + RpMaterialSetColor(maskMaterial, &watercolor); + } + + { + wavytlist = RpGeometryGetTriangles(wavyGeometry); - for ( int32 i = 0; i < 8; i++ ) + for ( int32 i = 0; i < 16; i++ ) { - for ( int32 j = 0; j < 8; j++ ) - { + for ( int32 j = 0; j < 16; j++ ) + { + const RwUInt16 base = (RwUInt16)((16 + 1)*i+j); + + RpGeometryTriangleSetVertexIndices(wavyGeometry, + wavytlist, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+16+2)); + RpGeometryTriangleSetVertexIndices(wavyGeometry, - &wavyTriangles[2 * 8*i + 2*j + 0], /*A*/9*i+j+0, /*B*/9*i+j+1, /*C*/9*i+j+9+1); - - RpGeometryTriangleSetVertexIndices(wavyGeometry, - &wavyTriangles[2 * 8*i + 2*j + 1], /*A*/9*i+j+0, /*C*/9*i+j+9+1, /*D*/9*i+j+9 ); + (wavytlist+1), (RwInt16)base, (RwInt16)(base+16+2), (RwInt16)(base+16+1)); - RpGeometryTriangleSetMaterial(wavyGeometry, &wavyTriangles[2 * 8*i + 2*j + 0], wavyMaterial); - RpGeometryTriangleSetMaterial(wavyGeometry, &wavyTriangles[2 * 8*i + 2*j + 1], wavyMaterial); + RpGeometryTriangleSetMaterial(wavyGeometry, wavytlist, wavyMaterial); + + RpGeometryTriangleSetMaterial(wavyGeometry, (wavytlist+1), wavyMaterial); + + wavytlist+=2; } } } + { + masktlist = RpGeometryGetTriangles(maskGeometry); + + for ( int32 i = 0; i < 32; i++ ) + { + for ( int32 j = 0; j < 32; j++ ) + { + const RwUInt16 base = (RwUInt16)((32 + 1)*i+j); + + RpGeometryTriangleSetVertexIndices(maskGeometry, + masktlist, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+32+2)); + + RpGeometryTriangleSetVertexIndices(maskGeometry, + (masktlist+1), (RwInt16)base, (RwInt16)(base+32+2), (RwInt16)(base+32+1)); + + RpGeometryTriangleSetMaterial(maskGeometry, masktlist, maskMaterial); + + RpGeometryTriangleSetMaterial(maskGeometry, (masktlist+1), maskMaterial); + + masktlist+=2; + } + } + } { wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0); - ASSERT(wavyMorphTarget != NULL); - wavyVert = RpMorphTargetGetVertices(wavyMorphTarget); - ASSERT(wavyVert != NULL); + wavyVert = RpMorphTargetGetVertices(wavyMorphTarget); + wavyNormal = RpMorphTargetGetVertexNormals(wavyMorphTarget); - for ( int32 i = 0; i < 9; i++ ) + for ( int32 i = 0; i < 17; i++ ) { - for ( int32 j = 0; j < 9; j++ ) + for ( int32 j = 0; j < 17; j++ ) { - wavyVert[9*i+j].x = (float)i * 4.0f; - wavyVert[9*i+j].y = (float)j * 4.0f; - wavyVert[9*i+j].z = 0.0f; + (*wavyVert).x = (float)i * 2.0f; + (*wavyVert).y = (float)j * 2.0f; + (*wavyVert).z = 0.0f; + + (*wavyNormal).x = 0.0f; + (*wavyNormal).y = 0.0f; + (*wavyNormal).z = 1.0f; + + wavyVert++; + wavyNormal++; } } @@ -194,60 +325,112 @@ CWaterLevel::CreateWavyAtomic() RpGeometryUnlock(wavyGeometry); } - { - wavyFrame = RwFrameCreate(); - ASSERT( wavyFrame != NULL ); + maskMorphTarget = RpGeometryGetMorphTarget(maskGeometry, 0); + maskVert = RpMorphTargetGetVertices(maskMorphTarget); + maskNormal = RpMorphTargetGetVertexNormals(maskMorphTarget); - ms_pWavyAtomic = RpAtomicCreate(); - ASSERT( ms_pWavyAtomic != NULL ); + for ( int32 i = 0; i < 33; i++ ) + { + for ( int32 j = 0; j < 33; j++ ) + { + (*maskVert).x = (float)i * 2.0f; + (*maskVert).y = (float)j * 2.0f; + (*maskVert).z = 0.0f; + + (*maskNormal).x = 0.0f; + (*maskNormal).y = 0.0f; + (*maskNormal).z = 1.0f; + + maskVert++; + maskNormal++; + } + } + RpMorphTargetCalcBoundingSphere(maskMorphTarget, &boundingSphere); + RpMorphTargetSetBoundingSphere(maskMorphTarget, &boundingSphere); + RpGeometryUnlock(maskGeometry); + } + + { + wavyFrame = RwFrameCreate(); + ms_pWavyAtomic = RpAtomicCreate(); RpAtomicSetGeometry(ms_pWavyAtomic, wavyGeometry, 0); RpAtomicSetFrame(ms_pWavyAtomic, wavyFrame); RpMaterialDestroy(wavyMaterial); RpGeometryDestroy(wavyGeometry); } + + { + maskFrame = RwFrameCreate(); + ms_pMaskAtomic = RpAtomicCreate(); + RpAtomicSetGeometry(ms_pMaskAtomic, maskGeometry, 0); + RpAtomicSetFrame(ms_pMaskAtomic, maskFrame); + RpMaterialDestroy(maskMaterial); + RpGeometryDestroy(maskGeometry); + } + + static RwFrame *wakeEnvFrame; + + if ( wakeEnvFrame == nil ) + { + wakeEnvFrame = RwFrameCreate(); + RwMatrixSetIdentity(RwFrameGetMatrix(wakeEnvFrame)); + RwFrameUpdateObjects(wakeEnvFrame); + } + + RpMatFXMaterialSetEffects(maskMaterial, rpMATFXEFFECTENVMAP); + RpMatFXMaterialSetupEnvMap(maskMaterial, gpWaterEnvTex, wakeEnvFrame, TRUE, fEnvScale); + RpMatFXAtomicEnableEffects(ms_pMaskAtomic); } void CWaterLevel::DestroyWavyAtomic() { - RwFrame *frame; - - frame = RpAtomicGetFrame(ms_pWavyAtomic); - - RpAtomicDestroy(ms_pWavyAtomic); +#define _DELETE_ATOMIC(a) \ + { \ + RwFrame *frame; \ + frame = RpAtomicGetFrame(a); \ + RpAtomicDestroy(a); \ + RwFrameDestroy(frame); \ + } + + _DELETE_ATOMIC(ms_pWavyAtomic); + _DELETE_ATOMIC(ms_pMaskAtomic); - RwFrameDestroy(frame); +#undef _DELETE_ATOMIC } bool CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ) { - int32 x = WATER_HUGE_X(fX); - int32 y = WATER_HUGE_Y(fY); - - ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE ); - ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE ); + int32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET); + int32 y = WATER_TO_SMALL_SECTOR_Y(fY); + +#ifdef FIX_BUGS + if ( x < 0 || x >= MAX_SMALL_SECTORS ) return false; + if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false; +#endif uint8 nBlock = aWaterFineBlockList[x][y]; - if ( nBlock == 128 ) + if ( nBlock == 0x80 ) return false; - ASSERT( pfOutLevel != NULL ); + ASSERT( pfOutLevel != nil ); *pfOutLevel = ms_aWaterZs[nBlock]; float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); float fWave = Sin ( - /*( WATER_UNSIGN_Y(fY) - float(y) * MAX_HUGE_SECTORS + WATER_UNSIGN_X(fX) - float(x) * MAX_HUGE_SECTORS )*/ // VC - (float)( ((int32)fX & (MAX_HUGE_SECTORS-1)) + ((int32)fY & (MAX_HUGE_SECTORS-1)) ) - * (TWOPI / MAX_HUGE_SECTORS ) + fAngle + ( WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE + + WATER_UNSIGN_X(fX + WATER_X_OFFSET) - x*SMALL_SECTOR_SIZE ) + + * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle ); - float fWindFactor = CWeather::Wind * 0.7f + 0.3f; + float fWindFactor = CWeather::WindClipped * 0.4f + 0.2f; *pfOutLevel += fWave * fWindFactor; @@ -263,35 +446,69 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bool CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel) { - int32 x = WATER_HUGE_X(fX); - int32 y = WATER_HUGE_Y(fY); - - ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE ); - ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE ); + int32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET); + int32 y = WATER_TO_SMALL_SECTOR_Y(fY); + +#ifdef FIX_BUGS + if ( x < 0 || x >= MAX_SMALL_SECTORS ) return false; + if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false; +#endif uint8 nBlock = aWaterFineBlockList[x][y]; - if ( nBlock == 128 ) + if ( nBlock == 0x80 ) return false; - ASSERT( pfOutLevel != NULL ); + ASSERT( pfOutLevel != nil ); *pfOutLevel = ms_aWaterZs[nBlock]; return true; } -inline float -_GetWaterDrawDist() +float +CWaterLevel::GetWaterWavesOnly(short x, short y) { - // if z less then 15.0f return 1200.0f - if ( TheCamera.GetPosition().z < 15.0f ) - return 1200.0f; + float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); + + float fWindFactor = CWeather::WindClipped * 0.7f + 0.3f; + + float fWave = Sin( float(float(4 * y + 4 * x) * (TWOPI / SMALL_SECTOR_SIZE )) + fAngle ); + + return fWave * fWindFactor; +} + +CVector +CWaterLevel::GetWaterNormal(float fX, float fY) +{ + //TODO: BUG ? no x offset + + int32 x = WATER_TO_SMALL_SECTOR_X(fX); + int32 y = WATER_TO_SMALL_SECTOR_Y(fY); + + float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); + float fWindFactor = CWeather::WindClipped * 0.4f + 0.2f; + + //TODO: + float _fWave = (WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE + WATER_UNSIGN_X(fX) - x*SMALL_SECTOR_SIZE) + * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle; + + CVector vA(1.0f, 0.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave)); + CVector vB(0.0f, 1.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave)); + + CVector norm = CrossProduct(vA, vB); + + norm.Normalise(); + + return norm; +} - // if z greater then 60.0f return 2000.0f; - if ( TheCamera.GetPosition().z > 60.0f ) - return 2000.0f; - return (TheCamera.GetPosition().z + -15.0f) * 800.0f / 45.0f + 1200.0f; +inline float +_GetWaterDrawDist() +{ + if ( TheCamera.GetPosition().z < 15.0f ) return 1200.0f; + if ( TheCamera.GetPosition().z > 60.0f ) return 2000.0f; + return ( TheCamera.GetPosition().z + -15.0f ) * 800.0f / 45.0f + 1200.0f; } inline float @@ -325,6 +542,49 @@ _GetCamBounds(bool *bUseCamStartY, bool *bUseCamEndY, bool *bUseCamStartX, bool } } + +inline bool +_IsColideWithBlock(int32 x, int32 y, int32 &block) +{ + block = CWaterLevel::aWaterFineBlockList[x + 0][y + 0]; + if (!(block & 0x80)) + return true; + + block = CWaterLevel::aWaterFineBlockList[x + 0][y + 1]; + if (!(block & 0x80)) + { + block = CWaterLevel::aWaterFineBlockList[x + 0][y + 2]; + if (!(block & 0x80)) + return true; + } + + block = CWaterLevel::aWaterFineBlockList[x + 1][y + 0]; + if (!(block & 0x80)) + return true; + + block = CWaterLevel::aWaterFineBlockList[x + 1][y + 1]; + if (!(block & 0x80)) + { + block = CWaterLevel::aWaterFineBlockList[x + 1][y + 2]; + if (!(block & 0x80)) + return true; + } + + block = CWaterLevel::aWaterFineBlockList[x + 2][y + 0]; + if (!(block & 0x80)) + return true; + + block = CWaterLevel::aWaterFineBlockList[x + 2][y + 1]; + if (!(block & 0x80)) + { + block = CWaterLevel::aWaterFineBlockList[x + 2][y + 2]; + if (!(block & 0x80)) + return true; + } + + return false; +} + inline float SectorRadius(float fSize) { @@ -345,64 +605,85 @@ CWaterLevel::RenderWater() bool bUseCamStartX = false; bool bUseCamEndY = false; - float fWavySectorMaxRenderDist = _GetWavyDrawDist(); - float fWavySectorMaxRenderDistSqr = SQR(fWavySectorMaxRenderDist); + if ( !CGame::CanSeeWaterFromCurrArea() ) + return; _GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX); float fHugeSectorMaxRenderDist = _GetWaterDrawDist(); float fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist); - float windAddUV = CWeather::Wind * 0.0015f + 0.0005f; + float windAddUV = CWeather::WindClipped * 0.0005f + 0.0006f; + float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); if ( !CTimer::GetIsPaused() ) { -#ifdef FIX_BUGS - TEXTURE_ADDU += (CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV) * CTimer::GetTimeStepFix(); - TEXTURE_ADDV += (CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV) * CTimer::GetTimeStepFix(); -#else - TEXTURE_ADDU += CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV; - TEXTURE_ADDV += CGeneral::GetRandomNumberInRange(-0.0005f, 0.0005f) + windAddUV; -#endif + TEXTURE_ADDU += windAddUV; + TEXTURE_ADDV += windAddUV; + + _TEXTURE_MASK_ADDU += Sin(fAngle) * 0.0005f + 1.1f * windAddUV; + _TEXTURE_MASK_ADDV -= Cos(fAngle * 1.3f) * 0.0005f + 1.2f * windAddUV; + + _TEXTURE_WAKE_ADDU -= Sin(fAngle) * 0.0003f + windAddUV; + _TEXTURE_WAKE_ADDV += Cos(fAngle * 0.7f) * 0.0003f + windAddUV; } + if ( _TEXTURE_MASK_ADDU >= 1.0f ) + _TEXTURE_MASK_ADDU = 0.0f; + if ( _TEXTURE_MASK_ADDV >= 1.0f ) + _TEXTURE_MASK_ADDV = 0.0f; + + if ( _TEXTURE_WAKE_ADDU >= 1.0f ) + _TEXTURE_WAKE_ADDU = 0.0f; + if ( _TEXTURE_WAKE_ADDV >= 1.0f ) + _TEXTURE_WAKE_ADDV = 0.0f; + if ( TEXTURE_ADDU >= 1.0f ) TEXTURE_ADDU = 0.0f; if ( TEXTURE_ADDV >= 1.0f ) TEXTURE_ADDV = 0.0f; - WavesCalculatedThisFrame = false; +#ifdef PC_WATER + _fWaterZOffset = CWeather::WindClipped * 0.5f + 0.25f; +#endif RwRGBA color = { 0, 0, 0, 255 }; - - color.red = uint32((CTimeCycle::GetDirectionalRed() * 0.5f + CTimeCycle::GetAmbientRed() ) * 255.0f); - color.green = uint32((CTimeCycle::GetDirectionalGreen() * 0.5f + CTimeCycle::GetAmbientGreen()) * 255.0f); - color.blue = uint32((CTimeCycle::GetDirectionalBlue() * 0.5f + CTimeCycle::GetAmbientBlue() ) * 255.0f); + + color.red = CTimeCycle::GetWaterRed(); + color.green = CTimeCycle::GetWaterGreen(); + color.blue = CTimeCycle::GetWaterBlue(); + +#ifndef PC_WATER + RwRGBA colorUnderwater = { 0, 0, 0, 255 }; + colorUnderwater.red = (uint32)(0.8f * (float)colorUnderwater.red); + colorUnderwater.green = (uint32)(0.8f * (float)colorUnderwater.green); + colorUnderwater.blue = (uint32)(0.8f * (float)colorUnderwater.blue); +#endif TempBufferVerticesStored = 0; TempBufferIndicesStored = 0; + +#ifndef PC_WATER + WavesCalculatedThisFrame = false; +#endif RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); - CVector2D camPos - ( - TheCamera.GetPosition().x, - TheCamera.GetPosition().y - ); + CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y); - int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist); - int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist) + 1; + int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET); + int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1; int32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist); int32 nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist) + 1; - + if ( bUseCamStartX ) - nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x); + nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET); if ( bUseCamEndX ) - nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x); + nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET); if ( bUseCamStartY ) nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y); if ( bUseCamEndY ) @@ -417,12 +698,279 @@ CWaterLevel::RenderWater() { for ( int32 y = nStartY; y <= nEndY; y++ ) { - if ( !(aWaterBlockList[2*x+0][2*y+0] & 128) - || !(aWaterBlockList[2*x+1][2*y+0] & 128) - || !(aWaterBlockList[2*x+0][2*y+1] & 128) - || !(aWaterBlockList[2*x+1][2*y+1] & 128) ) + if ( !(aWaterBlockList[2*x+0][2*y+0] & 0x80) + || !(aWaterBlockList[2*x+1][2*y+0] & 0x80) + || !(aWaterBlockList[2*x+0][2*y+1] & 0x80) + || !(aWaterBlockList[2*x+1][2*y+1] & 0x80) ) { - float fX = WATER_FROM_HUGE_SECTOR_X(x); + float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET; + float fY = WATER_FROM_HUGE_SECTOR_Y(y); + + CVector2D vecHugeSectorCentre(fX + HUGE_SECTOR_SIZE/2,fY + HUGE_SECTOR_SIZE/2); + + float fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr(); + + if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr ) + { + if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) + { +#ifndef PC_WATER + WavesCalculatedThisFrame = true; +#endif + + + float fZ; + + if ( !(aWaterBlockList[2*x+0][2*y+0] & 0x80) ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ]; + + if ( !(aWaterBlockList[2*x+1][2*y+0] & 0x80) ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ]; + + if ( !(aWaterBlockList[2*x+0][2*y+1] & 0x80) ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ]; + + if ( !(aWaterBlockList[2*x+1][2*y+1] & 0x80) ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ]; + + if ( fHugeSectorDistToCamSqr >= SQR(500.0f) ) + { + RenderOneFlatHugeWaterPoly(fX, fY, fZ, color); + } + else + { +#ifndef PC_WATER + if (m_bRenderSeaBed) + RenderOneSlopedUnderWaterPoly(fX, fY, fZ, colorUnderwater); +#endif + // see RenderTransparentWater() + ; + } + } + } + } + } + } + + /* + ----------- ---------------------- ---------------------- + | [N] | | [ EndY ] | | [ top ] | + | | | | | | + |[W] [0] [E]| |[StartX] [] [ EndX ]| |[ left ] [] [ right]| + | | | | | | + | [S] | | [StartY] | | [bottom] | + ----------- ---------------------- ---------------------- + + + [S] [StartY] [bottom] + [N] [EndY] [top] + [W] [StartX] [left] + [E] [EndX] [right] + + [S] -> [N] && [W] -> [E] + bottom -> top && left -> right + */ + + for ( int32 x = 0; x < 26; x++ ) + { + for ( int32 y = 0; y < 5; y++ ) + { + float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - 400.0f; + float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; + + if ( !bUseCamStartY ) + { + CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2); + + float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); + + if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) + { + if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) + { + RenderOneFlatExtraHugeWaterPoly( + vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, + vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, + 0.0f, + color); + } + } + } + + if ( !bUseCamEndY ) + { + CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, -(fY + EXTRAHUGE_SECTOR_SIZE/2)); + + float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); + + if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) + { + if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) + { + RenderOneFlatExtraHugeWaterPoly( + vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, + vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, + 0.0f, + color); + } + } + } + } + } + + for ( int32 y = 5; y < 21; y++ ) + { + for ( int32 x = 0; x < 5; x++ ) + { + float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - WATER_X_OFFSET; + float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f + WATER_X_OFFSET; + float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; + + if ( !bUseCamStartX ) + { + CVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2); + + float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); + + if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) + { + if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) + { + RenderOneFlatExtraHugeWaterPoly( + vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, + vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, + 0.0f, + color); + } + } + } + + if ( !bUseCamEndX ) + { + CVector2D vecExtraHugeSectorCentre(-(fX2 + EXTRAHUGE_SECTOR_SIZE/2), fY + EXTRAHUGE_SECTOR_SIZE/2); + + float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); + + if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) + { + if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.x, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) + { + RenderOneFlatExtraHugeWaterPoly( + vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, + vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, + 0.0f, + color); + } + } + } + } + } + + RenderAndEmptyRenderBuffer(); + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + if ( WavesCalculatedThisFrame ) + { + RenderSeaBirds(); + RenderShipsOnHorizon(); + CParticle::HandleShipsAtHorizonStuff(); + HandleBeachToysStuff(); + } + + if ( _bSeaLife ) + HandleSeaLifeForms(); + + DefinedState(); +} + + +void +CWaterLevel::RenderTransparentWater(void) +{ + bool bUseCamEndX = false; + bool bUseCamStartY = false; + + bool bUseCamStartX = false; + bool bUseCamEndY = false; + + _bSeaLife = false; + + if ( !CGame::CanSeeWaterFromCurrArea() ) + return; + + float fWaterDrawDist = _GetWavyDrawDist(); + float fWaterDrawDistLarge = fWaterDrawDist + 90.0f; + float fWavySectorMaxRenderDistSqr = SQR(fWaterDrawDist); + + _GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX); + + float fHugeSectorMaxRenderDist = _GetWaterDrawDist(); + float fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist); + + RenderBoatWakes(); + + RwRGBA color; + + color.red = CTimeCycle::GetWaterRed(); + color.green = CTimeCycle::GetWaterGreen(); + color.blue = CTimeCycle::GetWaterBlue(); + color.alpha = 255; + + RwRGBA colorTrans; + + colorTrans.red = CTimeCycle::GetWaterRed(); + colorTrans.green = CTimeCycle::GetWaterGreen(); + colorTrans.blue = CTimeCycle::GetWaterBlue(); + colorTrans.alpha = CTimeCycle::GetWaterAlpha(); + + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + +#ifndef PC_WATER + WavesCalculatedThisFrame = false; +#endif + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster); +#ifndef PC_WATER + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); +#endif + + CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y); + + int32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET); + int32 nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1; + int32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist ); + int32 nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist ) + 1; + + if ( bUseCamStartX ) + nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET); + if ( bUseCamEndX ) + nEndX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET); + if ( bUseCamStartY ) + nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y ); + if ( bUseCamEndY ) + nEndY = WATER_TO_HUGE_SECTOR_Y(camPos.y ); + + nStartX = clamp(nStartX, 0, MAX_HUGE_SECTORS - 1); + nEndX = clamp(nEndX, 0, MAX_HUGE_SECTORS - 1); + nStartY = clamp(nStartY, 0, MAX_HUGE_SECTORS - 1); + nEndY = clamp(nEndY, 0, MAX_HUGE_SECTORS - 1); + + + for ( int32 x = nStartX; x <= nEndX; x++ ) + { + for ( int32 y = nStartY; y <= nEndY; y++ ) + { + if ( !(aWaterBlockList[2*x+0][2*y+0] & 0x80) + || !(aWaterBlockList[2*x+1][2*y+0] & 0x80) + || !(aWaterBlockList[2*x+0][2*y+1] & 0x80) + || !(aWaterBlockList[2*x+1][2*y+1] & 0x80) ) + { + float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET; float fY = WATER_FROM_HUGE_SECTOR_Y(y); CVector2D vecHugeSectorCentre @@ -432,29 +980,15 @@ CWaterLevel::RenderWater() ); float fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr(); - + if ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr ) { - if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), - &TheCamera.GetCameraMatrix()) ) + if ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) { - if ( fHugeSectorDistToCamSqr >= SQR(500.0f) /*fHugeSectorNearDist*/ ) + if ( fHugeSectorDistToCamSqr >= SQR(500.0f) ) { - float fZ; - - if ( !(aWaterBlockList[2*x+0][2*y+0] & 128) ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ]; - - if ( !(aWaterBlockList[2*x+1][2*y+0] & 128) ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ]; - - if ( !(aWaterBlockList[2*x+0][2*y+1] & 128) ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ]; - - if ( !(aWaterBlockList[2*x+1][2*y+1] & 128) ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ]; - - RenderOneFlatHugeWaterPoly(fX, fY, fZ, color); + // see RenderWater() + ; } else { @@ -462,23 +996,18 @@ CWaterLevel::RenderWater() { for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ ) { - if ( !(aWaterBlockList[x2][y2] & 128) ) + if ( !(aWaterBlockList[x2][y2] & 0x80) ) { - float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2); + float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2) - WATER_X_OFFSET; float fLargeY = WATER_FROM_LARGE_SECTOR_Y(y2); - CVector2D vecLargeSectorCentre - ( - fLargeX + LARGE_SECTOR_SIZE/2, - fLargeY + LARGE_SECTOR_SIZE/2 - ); + CVector2D vecLargeSectorCentre(fLargeX + LARGE_SECTOR_SIZE/2, fLargeY + LARGE_SECTOR_SIZE/2); float fLargeSectorDistToCamSqr = (camPos - vecLargeSectorCentre).MagnitudeSqr(); if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr ) { - if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE), //90.879997f, - &TheCamera.GetCameraMatrix()) ) + if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) ) { // Render four small(32x32) sectors, or one large(64x64). @@ -491,93 +1020,81 @@ CWaterLevel::RenderWater() // --------- // [S] // - - if ( fLargeSectorDistToCamSqr < SQR(176.0f) ) - { + + float fLargeSectorDrawDistSqr = SQR((fWaterDrawDistLarge + 16.0f)); + + if ( fLargeSectorDistToCamSqr < fLargeSectorDrawDistSqr ) + { + _bSeaLife = true; + float fZ; // WS - if ( !(aWaterFineBlockList[2*x2+0][2*y2+0] & 128) ) + if ( !(aWaterFineBlockList[2*x2+0][2*y2+0] & 0x80) ) { float fSmallX = fLargeX; float fSmallY = fLargeY; - CVector2D vecSmallSectorCentre - ( - fSmallX + SMALL_SECTOR_SIZE/2, - fSmallY + SMALL_SECTOR_SIZE/2 - ); + CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2); float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr(); fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+0] ]; if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr ) - RenderOneWavySector(fSmallX, fSmallY, fZ, color); + RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans); else - RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color); + RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist); } // SE - if ( !(aWaterFineBlockList[2*x2+1][2*y2+0] & 128) ) + if ( !(aWaterFineBlockList[2*x2+1][2*y2+0] & 0x80) ) { float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2); float fSmallY = fLargeY; - CVector2D vecSmallSectorCentre - ( - fSmallX + SMALL_SECTOR_SIZE/2, - fSmallY + SMALL_SECTOR_SIZE/2 - ); + CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2); float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr(); fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+0] ]; if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr ) - RenderOneWavySector(fSmallX, fSmallY, fZ, color); + RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans); else - RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color); + RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist); } // WN - if ( !(aWaterFineBlockList[2*x2+0][2*y2+1] & 128) ) + if ( !(aWaterFineBlockList[2*x2+0][2*y2+1] & 0x80) ) { float fSmallX = fLargeX; float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2); - CVector2D vecSmallSectorCentre - ( - fSmallX + SMALL_SECTOR_SIZE/2, - fSmallY + SMALL_SECTOR_SIZE/2 - ); + CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2,fSmallY + SMALL_SECTOR_SIZE/2); float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr(); fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+1] ]; if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr ) - RenderOneWavySector(fSmallX, fSmallY, fZ, color); + RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans); else - RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color); + RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist); } //NE - if ( !(aWaterFineBlockList[2*x2+1][2*y2+1] & 128) ) + if ( !(aWaterFineBlockList[2*x2+1][2*y2+1] & 0x80) ) { float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2); float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2); - CVector2D vecSmallSectorCentre - ( - fSmallX + SMALL_SECTOR_SIZE/2, - fSmallY + SMALL_SECTOR_SIZE/2 - ); + CVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2); float fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr(); fZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+1] ]; if ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr ) - RenderOneWavySector(fSmallX, fSmallY, fZ, color); + RenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans); else - RenderOneFlatSmallWaterPoly(fSmallX, fSmallY, fZ, color); + RenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist); } } else @@ -588,13 +1105,11 @@ CWaterLevel::RenderWater() RenderOneFlatLargeWaterPoly(fLargeX, fLargeY, fZ, color); } - } // if ( TheCamera.IsSphereVisible - } // if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr ) - } // if ( !(aWaterBlockList[x2][y2] & 128) ) - } // for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ ) - } // for ( int32 x2 = 2*x; x2 <= 2*x+1; x2++ ) - // - + } + } + } + } + } } } } @@ -602,195 +1117,100 @@ CWaterLevel::RenderWater() } } - /* - ----------- ---------------------- ---------------------- - | [N] | | [ EndY ] | | [ top ] | - | | | | | | - |[W] [0] [E]| |[StartX] [] [ EndX ]| |[ left ] [] [ right]| - | | | | | | - | [S] | | [StartY] | | [bottom] | - ----------- ---------------------- ---------------------- - - - [S] [StartY] [bottom] - [N] [EndY] [top] - [W] [StartX] [left] - [E] [EndX] [right] + RenderAndEmptyRenderBuffer(); - [S] -> [N] && [W] -> [E] - bottom -> top && left -> right - */ - - if ( !bUseCamStartY ) +#ifdef PC_WATER + if ( MaskCalculatedThisFrame + && (m_nRenderWaterLayers == 0 || m_nRenderWaterLayers == 2 || m_nRenderWaterLayers == 3) ) { - for ( int32 x = 0; x < 26; x++ ) - { - for ( int32 y = 0; y < 5; y++ ) - { - float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; - float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; - - CVector2D vecExtraHugeSectorCentre - ( - fX + EXTRAHUGE_SECTOR_SIZE/2, - fY + EXTRAHUGE_SECTOR_SIZE/2 - ); - - float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + + pos.x = PreCalculatedMaskPosn.x; + pos.y = PreCalculatedMaskPosn.y; + pos.z = PreCalculatedMaskPosn.z; + + RpMatFXMaterialSetEnvMapFrame(RpGeometryGetMaterial(RpAtomicGetGeometry(ms_pMaskAtomic), 0), + RwCameraGetFrame(RwCameraGetCurrentCamera())); + + RwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE); - if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) - { - if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), - &TheCamera.GetCameraMatrix()) ) - { - RenderOneFlatExtraHugeWaterPoly( - vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, - vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, - 0.0f, - color); - } - } - } - } + RpAtomicRender(ms_pMaskAtomic); } - - for ( int32 y = 5; y < 21; y++ ) +#else + if (!CCullZones::WaterFudge()) { - for ( int32 x = 0; x < 5; x++ ) - { - float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; - float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; - float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; - - if ( !bUseCamStartX ) - { - CVector2D vecExtraHugeSectorCentre - ( - fX + EXTRAHUGE_SECTOR_SIZE/2, - fY + EXTRAHUGE_SECTOR_SIZE/2 - ); - - float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); - - if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) - { - if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), - &TheCamera.GetCameraMatrix()) ) - { - RenderOneFlatExtraHugeWaterPoly( - vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, - vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, - 0.0f, - color); - } - } - } - - if ( !bUseCamEndX ) - { - CVector2D vecExtraHugeSectorCentre - ( - -(fX2 + EXTRAHUGE_SECTOR_SIZE/2), - fY + EXTRAHUGE_SECTOR_SIZE/2 - ); - - float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude(); - - if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr ) - { - if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), - &TheCamera.GetCameraMatrix()) ) - { - RenderOneFlatExtraHugeWaterPoly( - vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2, - vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2, - 0.0f, - color); - } - } - } - } - } + int32 signX = 0; + int32 signY = 0; - RenderAndEmptyRenderBuffer(); - - CVector cur_pos = TheCamera.GetPosition(); - - if ( !CCullZones::CamNoRain() - && !CCullZones::PlayerNoRain() - && CWeather::NewWeatherType == WEATHER_SUNNY - && CClock::GetHours() > 6 && CClock::GetHours() < 20 - && WavesCalculatedThisFrame) - { - static CVector prev_pos(0.0f, 0.0f, 0.0f); - static CVector prev_front(0.0f, 0.0f, 0.0f); - static int32 timecounter; + float fCamX = camPos.x - SMALL_SECTOR_SIZE; + float fCamY = camPos.y - SMALL_SECTOR_SIZE; - if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f ) - { - prev_pos = cur_pos; - timecounter = CTimer::GetTimeInMilliseconds(); - } - else if ( CTimer::GetTimeInMilliseconds() - timecounter > 5000 ) + if (TheCamera.GetForward().x > 0.3f) + signX = 1; + else if (TheCamera.GetForward().x < -0.3f) + signX = -1; + + fCamX += 0.3f * (float)signX * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f + + if (TheCamera.GetForward().y > 0.3f) + signY = 1; + else if (TheCamera.GetForward().y < -0.3f) + signY = -1; + + fCamY += 0.3f * (float)signY * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f + + int32 nBlock; + + int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + 400.0f) + 1; + int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY) + 1; + + if (_IsColideWithBlock(BlockX, BlockY, nBlock)) { - static int32 birdgenTime = 0; - - if ( CTimer::GetTimeInMilliseconds() - birdgenTime > 1000 ) + if (m_nRenderWaterLayers != 1 && m_nRenderWaterLayers != 6) { - birdgenTime = CTimer::GetTimeInMilliseconds(); - - CVector vecPos = cur_pos; - - float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f); - - int32 nRot = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE-1; - - float fCos = CParticle::Cos(nRot); - float fSin = CParticle::Sin(nRot); - - vecPos.x += (fCos - fSin) * fAngle; - vecPos.y += (fSin + fCos) * fAngle; - vecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f); - - CVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f), - CGeneral::GetRandomNumberInRange(-1.0f, 1.0f), - 0.0f); - - CParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir); + float fMaskX = Floor(fCamX / 2.0f) * 2.0f; + float fMaskY = Floor(fCamY / 2.0f) * 2.0f; + float fWaterZ = CWaterLevel::ms_aWaterZs[nBlock]; + float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - 400.0f; + float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY); + + RenderWavyMask(fMaskX, fMaskY, fWaterZ, + fSectorX, fSectorY, + signX, signY, colorTrans); } } } - + DefinedState(); +#endif } -void -CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color) +void CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color) { if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 ) RenderAndEmptyRenderBuffer(); int32 vidx = TempBufferVerticesStored; - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color); int32 iidx = TempBufferIndicesStored; @@ -814,25 +1234,25 @@ CWaterLevel::RenderOneFlatLargeWaterPoly(float fX, float fY, float fZ, RwRGBA co int32 vidx = TempBufferVerticesStored; - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 2.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 2.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 2.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 2.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, color.alpha); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color); int32 iidx = TempBufferIndicesStored; @@ -855,27 +1275,33 @@ CWaterLevel::RenderOneFlatHugeWaterPoly(float fX, float fY, float fZ, RwRGBA con RenderAndEmptyRenderBuffer(); int32 vidx = TempBufferVerticesStored; - - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET); + RwRGBA c; + + c.red = color.red; + c.green = color.green; + c.blue = color.blue; + c.alpha = 255; + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 4.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 4.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 4.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 4.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c); int32 iidx = TempBufferIndicesStored; @@ -898,27 +1324,33 @@ CWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGB RenderAndEmptyRenderBuffer(); int32 vidx = TempBufferVerticesStored; - - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - WATER_Z_OFFSET); + RwRGBA c; + + c.red = color.red; + c.green = color.green; + c.blue = color.blue; + c.alpha = 255; + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 8.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 8.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 8.0f); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c); - RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - WATER_Z_OFFSET); + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset); RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 8.0f); RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV); - RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255); + RwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c); int32 iidx = TempBufferIndicesStored; @@ -935,172 +1367,1218 @@ CWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGB } void -CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bUnk) +CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender) { - float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); - - if ( !WavesCalculatedThisFrame ) + CVector vecSectorPos(fX + (SMALL_SECTOR_SIZE/2), fY + (SMALL_SECTOR_SIZE/2), fZ + 2.0f); + + if ( COcclusion::IsAABoxOccluded(vecSectorPos, SMALL_SECTOR_SIZE, SMALL_SECTOR_SIZE, 4.0f) ) + return; + +#ifdef PC_WATER + RequireWavySector = true; +#else + if (!WavesCalculatedThisFrame) { - nGeomUsed = 0; - WavesCalculatedThisFrame = true; + + float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); + + RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); + RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0); + RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0); + RwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry); + RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph); + RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph); + + RpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS); + + RwMatrix *camMat = RwFrameGetLTM(RwCameraGetFrame(RwCameraGetCurrentCamera())); //or curWorld + + float randomDampInv2 = (1.0f - fRandomDamp) * 2.0f; + + float move = 1.0f / 16.0f; + float randomMove = 1.0f / (16.0f * fRandomMoveDiv); + + float vertMul = 0.5f; + + float wind = CWeather::WindClipped * 0.4f + 0.2f; + float waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f; + + float waveA = (TWOPI / 16.0f) + * ((fNormalDirectionScalar1 * Abs(camMat->at.x + camMat->at.y) + fNormMult) * (CWeather::WindClipped * 0.4f + 0.2f)); + + float waveB = TWOPI / (16.0f * fWave2NormScale) + * ((fNormalDirectionScalar2 * Abs(camMat->at.y - camMat->at.x) + fNormMultB) * (CWeather::WindClipped * 0.2f + 0.1f)); + + CVector vA(1.0f, 0.0f, 0.0f); + CVector vB(0.0f, 1.0f, 0.0f); + + for ( int32 i = 0; i < 17; i++ ) + { + for ( int32 j = 0; j < 17; j++ ) + { + wavyTexCoords->u = float(i) * move + TEXTURE_ADDV; + wavyTexCoords->v = float(j) * move + TEXTURE_ADDU; + + RwRGBAAssign(wavyPreLight, &color); + + if (i > 0 && i < 16 && j > 0 && j < 16) + { + wavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove; + wavyMorphVerts->x *= fRandomDamp; + wavyMorphVerts->x += float(i) * randomDampInv2; + + wavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove; + wavyMorphVerts->y *= fRandomDamp; + wavyMorphVerts->y += float(j) * randomDampInv2; + } + + float morphVertXHalf = (i == 16) ? 0.0f : vertMul * wavyMorphVerts->x; + float morphVertYHalf = (j == 16) ? 0.0f : vertMul * wavyMorphVerts->y; + + float waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle; + float waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle; + + wavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB); + + vA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB)); + vB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB)); + + CVector norm = CrossProduct(vA, vB); + norm.Normalise(); + + wavyMorphNormals->x = norm.x; + wavyMorphNormals->y = norm.y; + wavyMorphNormals->z = norm.z; + + ++wavyPreLight; + ++wavyTexCoords; + + ++wavyMorphVerts; + ++wavyMorphNormals; + } + } + + RpGeometryUnlock(wavyGeometry); + } + + float fCentreX = fX + (SMALL_SECTOR_SIZE / 2); + float fCentreY = fY + (SMALL_SECTOR_SIZE / 2); +#endif + +#ifdef PC_WATER + if ( WavesCalculatedThisFrame ) +#endif + { + if (bDontRender == false + && m_nRenderWaterLayers != 2 + && m_nRenderWaterLayers != 4 + && m_nRenderWaterLayers != 6 ) + { + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + + pos.x = fX; + pos.y = fY; + pos.z = fZ; + + RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE); - CBoat::FillBoatList(); + RpAtomicRender(ms_pWavyAtomic); + } + } +} - ASSERT( ms_pWavyAtomic != NULL ); +int16 +_RoundValue(int32 v) +{ + int16 result = v; + + while ( result < 0 ) result += 16; + while ( result > 16 ) result -= 16; + + return result; +} - RpGeometry *geometry = RpAtomicGetGeometry(ms_pWavyAtomic); - - ASSERT( geometry != NULL ); +void +CWaterLevel::RenderWavyMask(float fX, float fY, float fZ, + float fSectorX, float fSectorY, +#ifdef PC_WATER + float fCamPosX, float fCamPosY, + float fCamDirX, float fCamDirY, RwRGBA const&color) +#else + int32 nCamDirX, int32 nCamDirY, RwRGBA const&color) +#endif +{ +#ifndef PC_WATER + bool bRender = true; + if (m_nRenderWaterLayers != 0 && m_nRenderWaterLayers != 2 && m_nRenderWaterLayers != 3) + bRender = false; +#endif + CVector vecSectorPos(fX + (LARGE_SECTOR_SIZE/2), fY + (LARGE_SECTOR_SIZE/2), fZ + 2.0f); - RwRGBA *wavyPreLights = RpGeometryGetPreLightColors(geometry); - RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(geometry, rwTEXTURECOORDINATEINDEX0); - RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geometry, 0)); - - ASSERT( wavyPreLights != NULL ); - ASSERT( wavyTexCoords != NULL ); - ASSERT( wavyVertices != NULL ); + if ( COcclusion::IsAABoxOccluded(vecSectorPos, LARGE_SECTOR_SIZE, LARGE_SECTOR_SIZE, 4.0f) ) + return; - RpGeometryLock(geometry, rpGEOMETRYLOCKVERTICES - | rpGEOMETRYLOCKPRELIGHT - | rpGEOMETRYLOCKTEXCOORDS); - - for ( int32 i = 0; i < 9; i++ ) +#ifndef PC_WATER + float fUOffset = fX - (MAX_LARGE_SECTORS * (int32)Floor(fX / MAX_LARGE_SECTORS)); + float fVOffset = fY - (MAX_LARGE_SECTORS * (int32)Floor(fY / MAX_LARGE_SECTORS)); + + int32 nSecsX = (int32)((fX - fSectorX) / 2.0f); + int32 nSecsY = (int32)((fY - fSectorY) / 2.0f); +#endif + + RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); + RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0); + RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph); + RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph); + + RpGeometry *maskGeometry = RpAtomicGetGeometry(ms_pMaskAtomic); + RwTexCoords *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0); + RwRGBA *maskPreLight = RpGeometryGetPreLightColors(maskGeometry); + RpMorphTarget *maskMorph = RpGeometryGetMorphTarget(maskGeometry, 0); + RwV3d *maskMorphVerts = RpMorphTargetGetVertices(maskMorph); + RwV3d *maskMorphNormals = RpMorphTargetGetVertexNormals(maskMorph); + + RpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES|rpGEOMETRYLOCKNORMALS|rpGEOMETRYLOCKPRELIGHT|rpGEOMETRYLOCKTEXCOORDS); + +#ifndef PC_WATER + RpMaterial *maskMat = RpGeometryGetMaterial(maskGeometry, 0); + RpMatFXMaterialSetEnvMapFrame(maskMat, RwCameraGetFrame(RwCameraGetCurrentCamera())); + RpMatFXMaterialSetEnvMapCoefficient(maskMat, fEnvScale); + RpMatFXMaterialSetEnvMapFrameBufferAlpha(maskMat, TRUE); +#endif + +#ifndef PC_WATER + float fMinSparkZ = (CWeather::WindClipped * fWave2Ampl + 0.05f + + CWeather::WindClipped * 0.4f + 0.2) * (1.0f - 0.04f * CWeather::SunGlare); + + int32 randval = CGeneral::GetRandomNumber(); + + float fUVStep = 0.125f; + float f27 = 2.0f; + + float fMinU = (fUOffset / 16.0f) + _TEXTURE_MASK_ADDU; + float fMinV = (fVOffset / 16.0f) + _TEXTURE_MASK_ADDV; + + float fAlphaMul = ((float)color.alpha * 0.4f) / 16.0f; + + float fXOffset = 16.0f; + if (nCamDirX > 0) + fXOffset = 6.4f; + else if (nCamDirX < 0) + fXOffset = 25.6f; + + float fYOffset = 16.0f; + if (nCamDirY > 0) + fYOffset = 6.4f; + else if (nCamDirY < 0) + fYOffset = 25.6f; + + int16 nX = _RoundValue(nSecsX - 1); + int16 nY = _RoundValue(nSecsY - 1); +#else + float fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f + + 0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare); + + int32 randval = CGeneral::GetRandomNumber() & 255; + + int16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1); + int16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1); +#endif + int16 idxX = nX; + + for ( int32 i = 0; i < 17; i++ ) + { + int16 idxY = nY; + + if ( ++idxX > 16 ) + idxX -= 16; + + for ( int32 j = 0; j < 17; j++ ) { - for ( int32 j = 0; j < 9; j++ ) + if ( ++idxY > 16 ) + idxY -= 16; + + const int32 a = (0*16); + const int32 b = (1*16); + const int32 c = (33*16); + const int32 d = (34*16); + + int32 base = (i*33+j); + +#ifndef PC_WATER + maskTexCoords[base + a].u = fMinU + ((float)i * fUVStep); + maskTexCoords[base + a].v = fMinV + ((float)j * fUVStep); + + maskTexCoords[base + b].u = maskTexCoords[base + a].u; + maskTexCoords[base + b].v = maskTexCoords[base + a].v + (16.0f * fUVStep); + + maskTexCoords[base + c].u = maskTexCoords[base + a].u + (16.0f * fUVStep); + maskTexCoords[base + c].v = maskTexCoords[base + a].v; + + maskTexCoords[base + d].u = maskTexCoords[base + a].u + (16.0f * fUVStep); + maskTexCoords[base + d].v = maskTexCoords[base + a].v + (16.0f * fUVStep); +#else + maskTexCoords[base+a].v = float(j) / SMALL_SECTOR_SIZE + ((fCamPosY - fY) / 64); + maskTexCoords[base+c].v = maskTexCoords[base+a].v; + maskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f; + maskTexCoords[base+b].v = maskTexCoords[base+d].v; + + maskTexCoords[base+a].u = float(i) / SMALL_SECTOR_SIZE + ((fCamPosX - fX) / 64); + maskTexCoords[base+b].u = maskTexCoords[base+a].u; + maskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f; + maskTexCoords[base+c].u = maskTexCoords[base+d].u; +#endif + + maskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f); + maskMorphVerts[base+b].x = maskMorphVerts[base+a].x; + maskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE; + maskMorphVerts[base+d].x = maskMorphVerts[base+c].x; + + maskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f); + maskMorphVerts[base+c].y = maskMorphVerts[base+a].y; + maskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE; + maskMorphVerts[base+d].y = maskMorphVerts[base+b].y; + + maskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z; + maskMorphVerts[base+d].z = maskMorphVerts[base+a].z; + maskMorphVerts[base+c].z = maskMorphVerts[base+d].z; + maskMorphVerts[base+b].z = maskMorphVerts[base+c].z; + +#ifndef PC_WATER + if (maskMorphVerts[base].z >= fMinSparkZ) +#else + if ( maskMorphVerts[base].z > fMinSparkZ ) +#endif { - wavyTexCoords[9*i+j].u = float(i) / 8 + TEXTURE_ADDV; - wavyTexCoords[9*i+j].v = float(j) / 8 + TEXTURE_ADDU; - RwRGBAAssign(&wavyPreLights[9*i+j], &color); + switch ( (i + j + randval) & 3 ) + { + case 0: + { + CVector vecPos + ( + fX + maskMorphVerts[base+a].x, + fY + maskMorphVerts[base+a].y, + fZ + maskMorphVerts[base+a].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; - wavyVertices[9*i+j].z = ( CWeather::Wind * 0.7f + 0.3f ) - * ( Sin(float(i + j) * DEGTORAD(45.0f) + fAngle) ) - + ( CWeather::Wind * 0.2f * Sin(float(j - i) * PI + (2.0f * fAngle)) ); + case 1: + { + CVector vecPos + ( + fX + maskMorphVerts[base+c].x, + fY + maskMorphVerts[base+c].y, + fZ + maskMorphVerts[base+c].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; + + case 2: + { + CVector vecPos + ( + fX + maskMorphVerts[base+b].x, + fY + maskMorphVerts[base+b].y, + fZ + maskMorphVerts[base+b].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; + + case 3: + { + CVector vecPos + ( + fX + maskMorphVerts[base+d].x, + fY + maskMorphVerts[base+d].y, + fZ + maskMorphVerts[base+d].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; + } } + + maskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x; + maskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y; + maskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z; + + maskMorphNormals[base+d].x = maskMorphNormals[base+a].x; + maskMorphNormals[base+d].y = maskMorphNormals[base+a].y; + maskMorphNormals[base+d].z = maskMorphNormals[base+a].z; + + maskMorphNormals[base+c].x = maskMorphNormals[base+d].x; + maskMorphNormals[base+c].y = maskMorphNormals[base+d].y; + maskMorphNormals[base+c].z = maskMorphNormals[base+d].z; + + maskMorphNormals[base+b].x = maskMorphNormals[base+c].x; + maskMorphNormals[base+b].y = maskMorphNormals[base+c].y; + maskMorphNormals[base+b].z = maskMorphNormals[base+c].z; + + maskPreLight[base+a].red = color.red; + maskPreLight[base+a].green = color.green; + maskPreLight[base+a].blue = color.blue; + maskPreLight[base+a].alpha = color.alpha; + + maskPreLight[base+d].red = maskPreLight[base+a].red; + maskPreLight[base+d].green = maskPreLight[base+a].green; + maskPreLight[base+d].blue = maskPreLight[base+a].blue; + maskPreLight[base+d].alpha = maskPreLight[base+a].alpha; + + maskPreLight[base+c].red = maskPreLight[base+d].red; + maskPreLight[base+c].green = maskPreLight[base+d].green; + maskPreLight[base+c].blue = maskPreLight[base+d].blue; + maskPreLight[base+c].alpha = maskPreLight[base+d].alpha; + + maskPreLight[base+b].red = maskPreLight[base+c].red; + maskPreLight[base+b].green = maskPreLight[base+c].green; + maskPreLight[base+b].blue = maskPreLight[base+c].blue; + maskPreLight[base+b].alpha = maskPreLight[base+c].alpha; + +#ifndef PC_WATER + maskPreLight[base + a].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs((float)j - fYOffset))))); + maskPreLight[base + b].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset))))); + maskPreLight[base + c].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs((float)j - fYOffset))))); + maskPreLight[base + d].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset))))); +#endif } - - RpGeometryUnlock(geometry); } - static CBoat *apBoatList[4] = { NULL }; + RpGeometryUnlock(maskGeometry); + +#ifndef PC_WATER + { + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + + pos.x = fX; + pos.y = fY; + pos.z = fZ + 0.05f; + + RwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE); + + if (bRender) + { +#ifdef PS2 + RpSkyTexCacheFlush(); +#endif + RpAtomicRender(ms_pMaskAtomic); + } + } +#endif +} + +#ifdef PC_WATER +void +CWaterLevel::PreCalcWaterGeometry(void) +{ + if ( !RequireWavySector ) + { + WavesCalculatedThisFrame = false; + MaskCalculatedThisFrame = false; + return; + } + + RequireWavySector = false; + WavesCalculatedThisFrame = true; - if ( apGeomArray[0] - && nGeomUsed < MAX_BOAT_WAKES - && CBoat::IsSectorAffectedByWake( - CVector2D(fX + (SMALL_SECTOR_SIZE / 2), fY + (SMALL_SECTOR_SIZE / 2)), - SMALL_SECTOR_SIZE / 2, - apBoatList) ) + RwRGBA color; + + color.red = CTimeCycle::GetWaterRed(); + color.green = CTimeCycle::GetWaterGreen(); + color.blue = CTimeCycle::GetWaterBlue(); + color.alpha = CTimeCycle::GetWaterAlpha(); + + PreCalcWavySector(color); + + if ( CCullZones::WaterFudge() ) { - float fWakeColor = fAdd1 - Max(255.0f - float(color.blue + color.red + color.green) / 3, fAdd2); - - RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); - RpGeometry *geom = apGeomArray[nGeomUsed++]; - - ASSERT( wavyGeometry != NULL ); - ASSERT( geom != NULL ); - - RpAtomic *atomic = RpAtomicCreate(); - ASSERT( atomic != NULL ); - - RpAtomicSetGeometry(atomic, geom, 0); - - RwFrame *frame = RwFrameCreate(); - ASSERT( frame != NULL ); - - RwMatrixCopy(RwFrameGetMatrix(frame), RwFrameGetMatrix(RpAtomicGetFrame(ms_pWavyAtomic))); - RpAtomicSetFrame(atomic, frame); + MaskCalculatedThisFrame = false; + return; + } + + CVector CamFwdDir = TheCamera.GetForward(); + CamFwdDir.z = 0.0f; + CamFwdDir.Normalise(); + + float fCamX = TheCamera.GetPosition().x - SMALL_SECTOR_SIZE; + float fCamY = TheCamera.GetPosition().y - SMALL_SECTOR_SIZE; + + //1.4144272f; 1.4144f; + float signX = CamFwdDir.x * 1.4144272f; + float signY = CamFwdDir.y * 1.4144272f; + + signX = clamp(signX, -1.0f, 1.0f); + fCamX += 0.4f * signX * float(SMALL_SECTOR_SIZE * 2.0f); + + signY = clamp(signY, -1.0f, 1.0f); + fCamY += 0.4f * signY * float(SMALL_SECTOR_SIZE * 2.0f); + + int32 nBlock; + + int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1; + int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY ) + 1; + + ASSERT( BlockX >= 0 && BlockX < MAX_SMALL_SECTORS ); + ASSERT( BlockY >= 0 && BlockY < MAX_SMALL_SECTORS ); + + if ( _IsColideWithBlock(BlockX, BlockY, nBlock) ) + { + float fMaskX = Floor(fCamX / 2.0f) * 2.0f; + float fMaskY = Floor(fCamY / 2.0f) * 2.0f; + + float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET; + float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY); - RwTexCoords *geomTexCoords = RpGeometryGetVertexTexCoords(geom, rwTEXTURECOORDINATEINDEX0); - RwTexCoords *wavyTexCoord = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0); - RwRGBA *geomPreLights = RpGeometryGetPreLightColors(geom); - RwV3d *geomVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geom, 0)); - RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(wavyGeometry, 0)); + if ( PreCalcWavyMask( fMaskX, fMaskY, ms_aWaterZs[nBlock], + fSectorX, fSectorY, fCamX, fCamY, CamFwdDir.x, CamFwdDir.y, color ) ) + { + PreCalculatedMaskPosn.x = fMaskX; + PreCalculatedMaskPosn.y = fMaskY; + PreCalculatedMaskPosn.z = ms_aWaterZs[nBlock] + 0.05f; + + MaskCalculatedThisFrame = true; + } + else + MaskCalculatedThisFrame = false; + } + else + MaskCalculatedThisFrame = false; +} + +bool +CWaterLevel::PreCalcWavySector(RwRGBA const &color) +{ + float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); + + RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); + + RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0); + RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0); + + RwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry); + RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph); + RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph); + + if ( !m_bRenderSeaBed ) + RpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES + |rpGEOMETRYLOCKNORMALS + |rpGEOMETRYLOCKPRELIGHT + |rpGEOMETRYLOCKTEXCOORDS); + + CVector camPosUp = TheCamera.GetForward(); - ASSERT( geomTexCoords != NULL ); - ASSERT( wavyTexCoord != NULL ); - ASSERT( geomPreLights != NULL ); - ASSERT( geomVertices != NULL ); - ASSERT( wavyVertices != NULL ); + float randomDampInv2 = (1.0f - fRandomDamp) * 2.0f; + + float randomMove = 1.0f / (16.0f * fRandomMoveDiv); + + float wind = CWeather::WindClipped * 0.4f + 0.2f; + float waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f; - RpGeometryLock(geom, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS); + float waveA = (TWOPI / 16.0f) + * ((CWeather::WindClipped * 0.4f + 0.2f) * (fNormalDirectionScalar1 * Abs(camPosUp.x + camPosUp.y) + fNormMult)); - for ( int32 i = 0; i < 9; i++ ) + float waveB = TWOPI / (16.0f * fWave2NormScale) + * ((CWeather::WindClipped * 0.2f + 0.1f) * (fNormalDirectionScalar2 * Abs(camPosUp.y - camPosUp.x) + fNormMultB)); + + + CVector vA(1.0f, 0.0f, 0.0f); + CVector vB(0.0f, 1.0f, 0.0f); + + for ( int32 i = 0; i < 17; i++ ) + { + for ( int32 j = 0; j < 17; j++ ) { - for ( int32 j = 0; j < 9; j++ ) + wavyTexCoords->u = (float(i) / 16.0f) + TEXTURE_ADDV; + wavyTexCoords->v = (float(j) / 16.0f) + TEXTURE_ADDU; + + RwRGBAAssign(wavyPreLight, &color); + + if ( i > 0 && i < 16 && j > 0 && j < 16 ) { - geomTexCoords[9*i+j] = wavyTexCoord[9*i+j]; + wavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove; + wavyMorphVerts->x *= fRandomDamp; + wavyMorphVerts->x += float(i) * randomDampInv2; + + wavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove; + wavyMorphVerts->y *= fRandomDamp; + wavyMorphVerts->y += float(j) * randomDampInv2; + } + + float morphVertXHalf = ( i == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->x; + float morphVertYHalf = ( j == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->y; + + float waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle; + float waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle; + + wavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB); + + vA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB)); + vB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB)); - float fVertexX = (float)i * 4.0f + fX; - float fVertexY = (float)j * 4.0f + fY; + CVector norm = CrossProduct(vA, vB); + norm.Normalise(); - float fDistMult = 0.0f; - - for ( int32 k = 0; k < 4; k++ ) - { - if ( apBoatList[k] != NULL ) - fDistMult += CBoat::IsVertexAffectedByWake(CVector(fVertexX, fVertexY, 0.0f), apBoatList[k]); - } - - if ( fDistMult > 0.0f ) + wavyMorphNormals->x = norm.x; + wavyMorphNormals->y = norm.y; + wavyMorphNormals->z = norm.z; + + ++wavyPreLight; + ++wavyTexCoords; + + ++wavyMorphVerts; + ++wavyMorphNormals; + } + } + + RpGeometryUnlock(wavyGeometry); + + return true; +} + +bool +CWaterLevel::PreCalcWavyMask(float fX, float fY, float fZ, + float fSectorX, float fSectorY, + float fCamPosX, float fCamPosY, + float fCamDirX, float fCamDirY, + RwRGBA const&color) +{ + CVector vecSectorPos(fX + (MAX_LARGE_SECTORS/2), fY + (MAX_LARGE_SECTORS/2), fZ + 2.0f); + + if ( COcclusion::IsAABoxOccluded(vecSectorPos, MAX_LARGE_SECTORS, MAX_LARGE_SECTORS, 4.0f) ) + return false; + + Floor(fX / MAX_LARGE_SECTORS); + Floor(fY / MAX_LARGE_SECTORS); + + RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); + RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0); + RwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph); + RwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph); + + RpGeometry *maskGeometry = RpAtomicGetGeometry(ms_pMaskAtomic); + RwTexCoords *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0); + RwRGBA *maskPreLight = RpGeometryGetPreLightColors(maskGeometry); + RpMorphTarget *maskMorph = RpGeometryGetMorphTarget(maskGeometry, 0); + RwV3d *maskMorphVerts = RpMorphTargetGetVertices(maskMorph); + RwV3d *maskMorphNormals = RpMorphTargetGetVertexNormals(maskMorph); + + if ( !m_bRenderSeaBed ) + RpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS); + + + float fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f + + 0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare); + + int32 randval = CGeneral::GetRandomNumber() & 255; + + int16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1); + int16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1); + + int16 idxX = nX; + + for ( int32 i = 0; i < 17; i++ ) + { + int16 idxY = nY; + + if ( ++idxX > 16 ) + idxX -= 16; + + for ( int32 j = 0; j < 17; j++ ) + { + if ( ++idxY > 16 ) + idxY -= 16; + + const int32 a = (0*16); + const int32 b = (1*16); + const int32 c = (33*16); + const int32 d = (34*16); + + int32 base = (i*33+j); + + maskTexCoords[base+a].v = float(j) / 32 + ((fCamPosY - fY) / 64); + maskTexCoords[base+c].v = maskTexCoords[base+a].v; + maskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f; + maskTexCoords[base+b].v = maskTexCoords[base+d].v; + + maskTexCoords[base+a].u = float(i) / 32 + ((fCamPosX - fX) / 64); + maskTexCoords[base+b].u = maskTexCoords[base+a].u; + maskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f; + maskTexCoords[base+c].u = maskTexCoords[base+d].u; + + maskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f); + maskMorphVerts[base+b].x = maskMorphVerts[base+a].x; + maskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE; + maskMorphVerts[base+d].x = maskMorphVerts[base+c].x; + + maskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f); + maskMorphVerts[base+c].y = maskMorphVerts[base+a].y; + maskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE; + maskMorphVerts[base+d].y = maskMorphVerts[base+b].y; + + maskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z; + maskMorphVerts[base+d].z = maskMorphVerts[base+a].z; + maskMorphVerts[base+c].z = maskMorphVerts[base+d].z; + maskMorphVerts[base+b].z = maskMorphVerts[base+c].z; + + if ( maskMorphVerts[base].z > fMinSparkZ ) + { + switch ( (i + j + randval) & 3 ) { - RwRGBA wakeColor; - - RwRGBAAssign(&wakeColor, &color); + case 0: + { + CVector vecPos + ( + fX + maskMorphVerts[base+a].x, + fY + maskMorphVerts[base+a].y, + fZ + maskMorphVerts[base+a].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; - wakeColor.red = Min(color.red + int32(fWakeColor * fRedMult * fDistMult), 255); - wakeColor.green = Min(color.green + int32(fWakeColor * fGreenMult * fDistMult), 255); - wakeColor.blue = Min(color.blue + int32(fWakeColor * fBlueMult * fDistMult), 255); - - RwRGBAAssign(&geomPreLights[9*i+j], &wakeColor); + case 1: + { + CVector vecPos + ( + fX + maskMorphVerts[base+c].x, + fY + maskMorphVerts[base+c].y, + fZ + maskMorphVerts[base+c].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; + case 2: + { + CVector vecPos + ( + fX + maskMorphVerts[base+b].x, + fY + maskMorphVerts[base+b].y, + fZ + maskMorphVerts[base+b].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; + + case 3: + { + CVector vecPos + ( + fX + maskMorphVerts[base+d].x, + fY + maskMorphVerts[base+d].y, + fZ + maskMorphVerts[base+d].z + 0.12f + ); + + vecPos -= 0.05f * TheCamera.GetForward(); + + CParticle::AddParticle(PARTICLE_WATER_SPARK, + vecPos, + CVector(0.0f, 0.0f, 0.0f), + nil, + 0.0f, + 15, + CGeneral::GetRandomNumberInRange(-90, 90), + 0, + 0); + } + break; } - else - RwRGBAAssign(&geomPreLights[9*i+j], &color); - - - geomVertices[9*i+j].z = wavyVertices[9*i+j].z; } + + maskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x; + maskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y; + maskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z; + + maskMorphNormals[base+d].x = maskMorphNormals[base+a].x; + maskMorphNormals[base+d].y = maskMorphNormals[base+a].y; + maskMorphNormals[base+d].z = maskMorphNormals[base+a].z; + + maskMorphNormals[base+c].x = maskMorphNormals[base+d].x; + maskMorphNormals[base+c].y = maskMorphNormals[base+d].y; + maskMorphNormals[base+c].z = maskMorphNormals[base+d].z; + + maskMorphNormals[base+b].x = maskMorphNormals[base+c].x; + maskMorphNormals[base+b].y = maskMorphNormals[base+c].y; + maskMorphNormals[base+b].z = maskMorphNormals[base+c].z; + + maskPreLight[base+a].red = color.red; + maskPreLight[base+a].green = color.green; + maskPreLight[base+a].blue = color.blue; + maskPreLight[base+a].alpha = color.alpha; + + maskPreLight[base+d].red = maskPreLight[base+a].red; + maskPreLight[base+d].green = maskPreLight[base+a].green; + maskPreLight[base+d].blue = maskPreLight[base+a].blue; + maskPreLight[base+d].alpha = maskPreLight[base+a].alpha; + + maskPreLight[base+c].red = maskPreLight[base+d].red; + maskPreLight[base+c].green = maskPreLight[base+d].green; + maskPreLight[base+c].blue = maskPreLight[base+d].blue; + maskPreLight[base+c].alpha = maskPreLight[base+d].alpha; + + maskPreLight[base+b].red = maskPreLight[base+c].red; + maskPreLight[base+b].green = maskPreLight[base+c].green; + maskPreLight[base+b].blue = maskPreLight[base+c].blue; + maskPreLight[base+b].alpha = maskPreLight[base+c].alpha; } + } + + RpGeometryUnlock(maskGeometry); + return true; +} +#endif + +void +CWaterLevel::RenderBoatWakes(void) +{ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterWakeRaster); +#ifndef PC_WATER + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); +#endif + +#ifdef _XBOX + // TODO save and restore rwRENDERSTATESRCBLEND rwRENDERSTATEDESTBLEND +#endif + + CBoat::FillBoatList(); + + float fWakeZ = 5.97f; + float fWakeLifeTimeMult = 0.01f / CBoat::WAKE_LIFETIME; + + for ( int32 idx = 0; idx < ARRAY_SIZE(CBoat::apFrameWakeGeneratingBoats); idx++ ) + { + CBoat *pBoat = CBoat::apFrameWakeGeneratingBoats[idx]; + + if ( pBoat == nil ) + break; + + CVector2D vecDistA(pBoat->GetForward().x, pBoat->GetForward().y); + + + float fSize = pBoat->GetColModel()->boundingBox.max.z + * 0.65f; - RpGeometryUnlock(geom); + if ( pBoat->GetModelIndex() == MI_SKIMMER) + fSize *= 0.4f; + float fAplhaA = 255.0f; + float fSizeA = fSize; + float fAplhaB; + float fSizeB; - RwV3d pos = {0.0f, 0.0f, 0.0f}; + for ( int32 wake = 1; wake < pBoat->m_nNumWakePoints; wake++ ) + { + bool bRender = true; + + float fTimeleft = CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake]; - pos.x = fX; - pos.z = fZ; - pos.y = fY; + float fWakeSizeB = ((float)wake * 0.19f) + fSize - fWakeLifeTimeMult * Max(fTimeleft, 0.0f); + + fSizeB = fWakeSizeB / CBoat::MIN_WAKE_INTERVAL; + if ( fSizeB < 0.0f ) + fSizeB = 1.0f; + + if ( wake == pBoat->m_nNumWakePoints - 1 ) + { + // set alpha to 0 if it's last point + fAplhaB = 0.0f; + } + else + { + // clip (-100, 500), less lifetime - less val + float val = 500.0f - (CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake]) + * 600.0f / CBoat::WAKE_LIFETIME; + + fAplhaB = clamp(val, 0.0f, 255.0f); + } - RwFrameTranslate(RpAtomicGetFrame(atomic), &pos, rwCOMBINEREPLACE); + CVector2D vecDistB = pBoat->m_avec2dWakePoints[wake - 1] - pBoat->m_avec2dWakePoints[wake]; - RpAtomicRender(atomic); - - RpAtomicDestroy(atomic); - RwFrameDestroy(frame); + float fScal = vecDistB.MagnitudeSqr(); + + // normalize if distance between points is greater than 3 + + if ( fScal > SQR(3.0f) ) + { + float fNorm = 1.0f / sqrt(fScal); + + vecDistB.x *= fNorm; + vecDistB.y *= fNorm; + + // disable render if distance between points too big + + if ( sqrt(fScal) > 13.0f ) + bRender = false; + } + + CVector2D vecAA + ( + pBoat->m_avec2dWakePoints[wake - 1].x - (fSizeA * vecDistA.y), + pBoat->m_avec2dWakePoints[wake - 1].y + (fSizeA * vecDistA.x) + ); + CVector2D vecAB + ( + pBoat->m_avec2dWakePoints[wake - 1].x + (fSizeA * vecDistA.y), + pBoat->m_avec2dWakePoints[wake - 1].y - (fSizeA * vecDistA.x) + ); + CVector2D vecBA + ( + pBoat->m_avec2dWakePoints[wake].x + (fSizeB * vecDistB.y), + pBoat->m_avec2dWakePoints[wake].y - (fSizeB * vecDistB.x) + ); + CVector2D vecBB + ( + pBoat->m_avec2dWakePoints[wake].x - (fSizeB * vecDistB.y), + pBoat->m_avec2dWakePoints[wake].y + (fSizeB * vecDistB.x) + ); + + if ( bRender ) + RenderWakeSegment(vecAA, vecAB, vecBA, vecBB, fSizeA, fSizeB, fAplhaA, fAplhaB, fWakeZ); + + vecDistA = vecDistB; + fSizeA = fSizeB; + + fAplhaB = fAplhaA; + } } - else + + RenderAndEmptyRenderBuffer(); +} + +inline float +_GetWindedWave(float fX, float fY) +{ + float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); + float x = WATER_HUGE_X(fX + WATER_X_OFFSET); + float y = WATER_HUGE_Y(fY); + + float fWindFactor (CWeather::WindClipped * 0.4f + 0.2f); + float fWave = Sin(( (x - Floor(x)) + (y - Floor(y)) ) * TWOPI + fAngle); + + return fWindFactor * fWave; +} + +void +CWaterLevel::RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD, + float &fSizeA, float &fSizeB, + float &fAlphaA, float &fAlphaB, + float &fWakeZ) +{ + for ( int32 i = 0; i < 4; i++ ) { - RwV3d pos = { 0.0f, 0.0f, 0.0f }; + if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 ) + RenderAndEmptyRenderBuffer(); + + float fCurStep = (float)i / 4; + float fNxtStep = (float)(i + 1) / 4; + + float fLeftCurStep = 1.0f - fCurStep; + float fLeftNxtStep = 1.0f - fNxtStep; - pos.x = fX; - pos.y = fY; - pos.z = fZ; + uint8 AlphaA = (uint32)(fAlphaA * aAlphaFade[i] ); + uint8 AlphaB = (uint32)(fAlphaA * aAlphaFade[i + 1]); + uint8 AlphaC = (uint32)(fAlphaB * aAlphaFade[i + 1]); + uint8 AlphaD = (uint32)(fAlphaB * aAlphaFade[i] ); + + CVector2D PosA = vecB*fCurStep + vecA*fLeftCurStep; + CVector2D PosB = vecB*fNxtStep + vecA*fLeftNxtStep; + CVector2D PosC = vecC*fNxtStep + vecD*fLeftNxtStep; + CVector2D PosD = vecC*fCurStep + vecD*fLeftCurStep; + + float fUA = (PosA.x / 4) + _TEXTURE_WAKE_ADDU; + float fVA = (PosA.y / 4) + _TEXTURE_WAKE_ADDV; + + float fUB = (PosB.x / 4) + _TEXTURE_WAKE_ADDU; + float fVB = (PosB.y / 4) + _TEXTURE_WAKE_ADDV; + + float fUC = (PosC.x / 4) + _TEXTURE_WAKE_ADDU; + float fVC = (PosC.y / 4) + _TEXTURE_WAKE_ADDV; + + float fUD = (PosD.x / 4) + _TEXTURE_WAKE_ADDU; + float fVD = (PosD.y / 4) + _TEXTURE_WAKE_ADDV; - ASSERT( ms_pWavyAtomic != NULL ); +#define MIN4(a, b, c, d) (Min((a), Min((b), Min((c), (d))))) + float fMinU = Floor(MIN4(fUA, fUB, fUC, fUD)); + float fMinV = Floor(MIN4(fVA, fVB, fVC, fVD)); +#undef MIN4 + + float fZA = _GetWindedWave(PosA.x, PosA.y) + fWakeZ; + float fZB = _GetWindedWave(PosB.x, PosB.y) + fWakeZ; + float fZC = _GetWindedWave(PosC.x, PosC.y) + fWakeZ; + float fZD = _GetWindedWave(PosD.x, PosD.y) + fWakeZ; + + int32 vidx = TempBufferVerticesStored; + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], PosA.x, PosA.y, fZA); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], fUA - fMinU); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], fVA - fMinV); + RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], 255, 255, 255, AlphaA); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], PosB.x, PosB.y, fZB); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], fUB - fMinU); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], fVB - fMinV); + RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], 255, 255, 255, AlphaB); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], PosC.x, PosC.y, fZC); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], fUC - fMinU); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], fVC - fMinV); + RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], 255, 255, 255, AlphaC); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], PosD.x, PosD.y, fZD); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], fUD - fMinU); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], fVD - fMinV); + RwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], 255, 255, 255, AlphaD); - RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE); + int32 iidx = TempBufferIndicesStored; + + TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1; + TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3; + TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2; - RpAtomicRender(ms_pWavyAtomic); + TempBufferVerticesStored += 4; + + TempBufferIndicesStored += 6; } } +void +CWaterLevel::RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color) +{ + CVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y); + + float fDistA = (CVector2D(fX, fY) - camPos).Magnitude() + -140.0f; + float fDistB = (CVector2D(fX, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f; + float fDistC = (CVector2D(fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f; + float fDistD = (CVector2D(fX + HUGE_SECTOR_SIZE, fY) - camPos).Magnitude() + -140.0f; + +#ifndef PC_WATER +#define CALCSEABED(v, d) \ + { \ + if ( d < 0.0f ) \ + v = 0.1f + fSeaBedZ; \ + else if ( d > 240.0f ) \ + v = 0.1f; \ + else \ + v = 0.1f + ((fSeaBedZ * (240.0f - d)) / 240.0f); \ + } +#else + #define CALCSEABED(v, d) \ + { \ + v = 0.1f; \ + if ( d < 0.0f ) \ + v += fSeaBedZ; \ + else if ( d <= 240.0f ) \ + v += (fSeaBedZ / 240.0f) * (240.0f - d); \ + } +#endif + float fSeaBedA, fSeaBedB, fSeaBedC, fSeaBedD; + + CALCSEABED(fSeaBedA, fDistA); + CALCSEABED(fSeaBedB, fDistB); + CALCSEABED(fSeaBedC, fDistC); + CALCSEABED(fSeaBedD, fDistD); + + #undef CALCSEABED + + if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 ) + RenderAndEmptyRenderBuffer(); + + int32 vidx = TempBufferVerticesStored; + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset - fSeaBedA); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], 0.0f); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], 0.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedB); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], 0.0f); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], 4.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedC); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], 4.0f); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], 4.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset - fSeaBedD); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], 4.0f); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], 0.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255); + + int32 iidx = TempBufferIndicesStored; + + TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1; + TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3; + TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2; + + TempBufferVerticesStored += 4; + + TempBufferIndicesStored += 6; +} + +void +CWaterLevel::RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY, + RwRGBA const &color, RwRGBA const &colorTrans, + float fDrawDist) +{ + if ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 ) + RenderAndEmptyRenderBuffer(); + + int32 vidx = TempBufferVerticesStored; + + float fBlendDrawDist = fDrawDist + fStartBlendDistanceAdd; + + float fDistStartX = SQR(fX - fCamX); + float fDistStartY = SQR(fY - fCamY); + float fDistEndX = SQR((fX + SMALL_SECTOR_SIZE) - fCamX); + float fDistEndY = SQR((fY + SMALL_SECTOR_SIZE) - fCamY); + + + float fAlphaBlendMulA + = Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f); + float fAlphaBlendMulB + = Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistEndY ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f); + float fAlphaBlendMulC + = Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX + fDistEndY ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f); + float fAlphaBlendMulD + = Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f); + + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, + (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulA)); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, + (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulB)); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, + (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulC)); + + RwIm3DVertexSetPos (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset); + RwIm3DVertexSetU (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f); + RwIm3DVertexSetV (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, + (colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulD)); + + + int32 iidx = TempBufferIndicesStored; + + TempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2; + TempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1; + TempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0; + TempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3; + TempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2; + + TempBufferVerticesStored += 4; + + TempBufferIndicesStored += 6; +} + float CWaterLevel::CalcDistanceToWater(float fX, float fY) { - const float fSectorMaxRenderDist = 75.0f; + const float fSectorMaxRenderDist = 250.0f; - int32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist) - 1; - int32 nEndX = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist) + 1; + int32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist + WATER_X_OFFSET) - 1; + int32 nEndX = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist + WATER_X_OFFSET) + 1; int32 nStartY = WATER_TO_SMALL_SECTOR_Y(fY - fSectorMaxRenderDist) - 1; int32 nEndY = WATER_TO_SMALL_SECTOR_Y(fY + fSectorMaxRenderDist) + 1; @@ -1115,9 +2593,9 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY) { for ( int32 y = nStartY; y <= nEndY; y++ ) { - if ( !(aWaterFineBlockList[x][y] & 128) ) + if ( !(aWaterFineBlockList[x][y] & 0x80) ) { - float fSectorX = WATER_FROM_SMALL_SECTOR_X(x); + float fSectorX = WATER_FROM_SMALL_SECTOR_X(x) - WATER_X_OFFSET; float fSectorY = WATER_FROM_SMALL_SECTOR_Y(y); CVector2D vecDist @@ -1141,7 +2619,7 @@ CWaterLevel::RenderAndEmptyRenderBuffer() { LittleTest(); - if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, NULL, rwIM3D_VERTEXUV) ) + if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV) ) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); RwIm3DEnd(); @@ -1152,97 +2630,344 @@ CWaterLevel::RenderAndEmptyRenderBuffer() TempBufferVerticesStored = 0; } -void -CWaterLevel::AllocateBoatWakeArray() +bool +CWaterLevel::GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance) +{ + CColPoint point; + CEntity *entity; + + if ( !CWorld::ProcessVerticalLine(vecPosn + CVector(0.0f, 0.0f, fDistance), + -fDistance, point, entity, true, false, false, false, true, false, nil) ) + return false; + + *pfOutLevel = point.point.z; + + if ( pData != nil ) + { + pData->SurfaceType = point.surfaceB; + pData->PieceType = point.pieceB; + } + + return true; +} + +bool +CWaterLevel::IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset) +{ + int32 x = int32((vecPosn.x / 50.0f) + 48.0f); + int32 y = int32((vecPosn.y / 50.0f) + 40.0f); + + return x < nOffset || x >= 80 - nOffset || y < nOffset || y >= 80 - nOffset; +} + +bool +CWaterLevel::GetGroundLevel_WS(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance) { - CStreaming::MakeSpaceFor(14 * CDSTREAM_SECTOR_SIZE); + if ( IsLocationOutOfWorldBounds_WS(vecPosn, 0) ) + return false; + else + return GetGroundLevel(vecPosn, pfOutLevel, pData, fDistance); +} - ASSERT(ms_pWavyAtomic != NULL ); +bool +CWaterLevel::GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel) +{ + float fLevelNoWaves; + float fGroundLevel; + + if ( !GetWaterLevelNoWaves(vecPosn.x, vecPosn.y, vecPosn.z, &fLevelNoWaves) ) + return false; + + if ( !GetGroundLevel(vecPosn, &fGroundLevel, nil, 30.0f) ) + fGroundLevel = -100.0; - RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); - ASSERT(wavyGeometry != NULL ); - RpMorphTarget *wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0); - RpMaterial *wavyMaterial = RpGeometryGetMaterial(wavyGeometry, 0); + if ( pfDepth != nil ) + *pfDepth = fLevelNoWaves - fGroundLevel; - ASSERT(wavyMorphTarget != NULL ); - ASSERT(wavyMaterial != NULL ); + if ( pfLevelNoWaves != nil ) + *pfLevelNoWaves = fLevelNoWaves; + + if ( pfGroundLevel != nil ) + *pfGroundLevel = fGroundLevel; + + return true; +} - for ( int32 geom = 0; geom < MAX_BOAT_WAKES; geom++ ) +void +CWaterLevel::RenderSeaBirds() +{ + CVector cur_pos = TheCamera.GetPosition(); + + if ( !CCullZones::CamNoRain() + && !CCullZones::PlayerNoRain() + && (CWeather::NewWeatherType == WEATHER_SUNNY || CWeather::NewWeatherType == WEATHER_EXTRA_SUNNY) + && CClock::ms_nGameClockHours > 6 && CClock::ms_nGameClockHours < 20 ) { - if ( apGeomArray[geom] == NULL ) + static CVector prev_pos(0.0f, 0.0f, 0.0f); + static CVector prev_front(0.0f, 0.0f, 0.0f); + static int32 timecounter; + + if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f ) { - apGeomArray[geom] = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP - | rpGEOMETRYPRELIT - | rpGEOMETRYMODULATEMATERIALCOLOR - | rpGEOMETRYTEXTURED); - ASSERT(apGeomArray[geom] != NULL); + prev_pos = cur_pos; + timecounter = CTimer::GetTimeInMilliseconds(); + } + else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 ) + { + static int32 birdgenTime = 0; + + if ( (CTimer::GetTimeInMilliseconds() - birdgenTime) > 1000 ) + { + birdgenTime = CTimer::GetTimeInMilliseconds(); + + CVector vecPos = cur_pos; + + float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f); + + uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1); + + float fCos = CParticle::Cos(nSinCosIdx); + float fSin = CParticle::Sin(nSinCosIdx); + + vecPos.x += (fCos - fSin) * fAngle; + vecPos.y += (fSin + fCos) * fAngle; + vecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f); + + CVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f), + CGeneral::GetRandomNumberInRange(-1.0f, 1.0f), + 0.0f); + + CParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir, nil, 0.0f, 0, 0, 0, 0); + } + } + } +} + +void +CWaterLevel::RenderShipsOnHorizon() +{ +#ifdef FIX_BUGS + CVector cur_pos = FindPlayerCoors(); +#else + CVector cur_pos = FindPlayerPed()->GetPosition(); +#endif - RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]); + static CVector prev_pos(0.0f, 0.0f, 0.0f); + static CVector prev_front(0.0f, 0.0f, 0.0f); + static int32 timecounter; + + if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f ) + { + prev_pos = cur_pos; + timecounter = CTimer::GetTimeInMilliseconds(); + } + else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 ) + { + static int32 shipgenTime = 0; + + if ( (CTimer::GetTimeInMilliseconds() - shipgenTime) > 4000 ) + { + shipgenTime = CTimer::GetTimeInMilliseconds(); + + CVector vecPos = cur_pos; + + float fAngle = CGeneral::GetRandomNumberInRange(450.0f, 750.0f); - ASSERT( geomTriangles != NULL ); + uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1); + + float fCos = CParticle::Cos(nSinCosIdx); + float fSin = CParticle::Sin(nSinCosIdx); - for ( int32 i = 0; i < 8; i++ ) + vecPos.x += (fCos - fSin) * fAngle; + vecPos.y += (fSin + fCos) * fAngle; + + float fLevelNoWaves; + + if ( GetWaterLevelNoWaves(vecPos.x, vecPos.y, vecPos.z, &fLevelNoWaves) ) { - for ( int32 j = 0; j < 8; j++ ) + if ( IsLocationOutOfWorldBounds_WS(vecPos, 1) ) { + vecPos.z = fLevelNoWaves + 9.5f; - /* - [B] [C] - *********** - * * * - * * * - * * * - * * * - *********** - [A] [D] - */ - + CVector vecDir + ( + CGeneral::GetRandomNumberInRange(-0.1f, 0.1f), + 0.0f, + 0.0f + ); - RpGeometryTriangleSetVertexIndices(apGeomArray[geom], - &geomTriangles[2 * 8*i + 2*j + 0], /*A*/i*9+j+0, /*B*/i*9+j+1, /*C*/i*9+j+9+1); - - RpGeometryTriangleSetVertexIndices(apGeomArray[geom], - &geomTriangles[2 * 8*i + 2*j + 1], /*A*/i*9+j+0, /*C*/i*9+j+9+1, /*D*/i*9+j+9 ); - - RpGeometryTriangleSetMaterial(apGeomArray[geom], &geomTriangles[2 * 8*i + 2*j + 0], wavyMaterial); - - RpGeometryTriangleSetMaterial(apGeomArray[geom], &geomTriangles[2 * 8*i + 2*j + 1], wavyMaterial); + CParticle::AddParticle(PARTICLE_SHIP_SIDE, vecPos, vecDir, + nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 7, 0); } } + } + } +} - RpMorphTarget *geomMorphTarget = RpGeometryGetMorphTarget(apGeomArray[geom], 0); - RwV3d *geomVertices = RpMorphTargetGetVertices(geomMorphTarget); - - ASSERT( geomMorphTarget != NULL ); - ASSERT( geomVertices != NULL ); +void +CWaterLevel::HandleSeaLifeForms() +{ + if ( CReplay::IsPlayingBack() ) + return; + + CVector cur_pos = FindPlayerPed()->GetPosition(); - for ( int32 i = 0; i < 9; i++ ) + static CVector prev_pos(0.0f, 0.0f, 0.0f); + static int32 timecounter; + + if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f ) + { + prev_pos = cur_pos; + timecounter = CTimer::GetTimeInMilliseconds(); + } + else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 ) + { + if ( CWaterCreatures::IsSpaceForMoreWaterCreatures() ) + { + for ( int32 i = 0; i < 3; i++ ) { - for ( int32 j = 0; j < 9; j++ ) - { - geomVertices[9*i+j].x = (float)i * 4.0f; - geomVertices[9*i+j].y = (float)j * 4.0f; - geomVertices[9*i+j].z = 0.0f; - } + CVector vecPos = cur_pos; + + float fAngle = CGeneral::GetRandomNumberInRange(15.0f, 30.0f); + + uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1); + + float fCos = CParticle::Cos(nSinCosIdx); + float fSin = CParticle::Sin(nSinCosIdx); + + vecPos.x += (fCos - fSin) * fAngle; + vecPos.y += (fSin + fCos) * fAngle; + + CWaterCreatures::CreateOne(vecPos, -1); } - - RpMorphTargetSetBoundingSphere(geomMorphTarget, RpMorphTargetGetBoundingSphere(wavyMorphTarget)); - RpGeometryUnlock(apGeomArray[geom]); } } + + CWaterCreatures::UpdateAll(); } void -CWaterLevel::FreeBoatWakeArray() +CWaterLevel::HandleBeachToysStuff(void) { - for ( int32 i = 0; i < MAX_BOAT_WAKES; i++ ) +#ifdef FIX_BUGS + CVector cur_pos = FindPlayerCoors(); +#else + CVector cur_pos = FindPlayerPed()->GetPosition(); +#endif + + static bool bBeachBallInit = true; + static CVector FirstBeachBallPos = cur_pos; + static bool bLoungeInit = true; + static CVector FirstLoungePos = cur_pos; + static CVector prev_pos(0.0f, 0.0f, 0.0f); + static int32 timecounter; + + if ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f ) { - if ( apGeomArray[i] != NULL ) + prev_pos = cur_pos; + timecounter = CTimer::GetTimeInMilliseconds(); + } + else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 ) + { + static int32 toygenTime = CTimer::GetTimeInMilliseconds(); + + if ( (CTimer::GetTimeInMilliseconds() - toygenTime) > 20000 ) { - RpGeometryDestroy(apGeomArray[i]); - apGeomArray[i] = NULL; + toygenTime = CTimer::GetTimeInMilliseconds(); + + if ( bBeachBallInit || (cur_pos - FirstBeachBallPos).MagnitudeSqr() > 6400.0f ) + { + for ( int32 i = 0; i < 3; i++ ) + { + CVector vecPos = cur_pos; + + float fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f); + + uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1); + + float fCos = CParticle::Cos(nSinCosIdx); + float fSin = CParticle::Sin(nSinCosIdx); + + vecPos.x += (fCos - fSin) * fAngle; + vecPos.y += (fSin + fCos) * fAngle; + + if ( TheCamera.IsSphereVisible(vecPos, 1.0f, &TheCamera.GetCameraMatrix()) ) + { + float fWaterLevel; + + if ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) ) + { + float fGroundLevel; + ColData coldata; + + if ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) ) + { + if ( coldata.SurfaceType == SURFACE_SAND ) + { + CEntity *toy = CreateBeachToy(vecPos, BEACHTOY_BALL); + + if ( toy ) + { + FirstBeachBallPos = cur_pos; + bBeachBallInit = false; + i = 10; + } + } + } + } + } + } + } + + if ( bLoungeInit || (cur_pos - FirstLoungePos).MagnitudeSqr() > 6400.0f ) + { + for ( int32 i = 0; i < 5; i++ ) + { + CVector vecPos = cur_pos; + + float fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f); + + uint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1); + + float fCos = CParticle::Cos(nSinCosIdx); + float fSin = CParticle::Sin(nSinCosIdx); + + vecPos.x += (fCos - fSin) * fAngle; + vecPos.y += (fSin + fCos) * fAngle; + + if ( TheCamera.IsSphereVisible(vecPos, 2.0f, &TheCamera.GetCameraMatrix()) ) + { + float fWaterLevel; + + if ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) ) + { + float fGroundLevel; + ColData coldata; + + if ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) ) + { + if ( coldata.SurfaceType == SURFACE_SAND ) + { + CEntity *toy = CreateBeachToy(vecPos, BEACHTOY_LOUNGE); + if ( toy ) + { + toy->SetHeading(DEGTORAD(CGeneral::GetRandomNumberInRange(0.0f, 359.0f))); + FirstLoungePos = cur_pos; + bLoungeInit = false; + } + } + } + } + } + } + } } } - - nGeomUsed = 0; } + +CEntity * +CWaterLevel::CreateBeachToy(CVector const &vec, eBeachToy beachtoy) +{ + //TODO(MIAMI) + return nil; +}
\ No newline at end of file diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h index 269d6091..58940c63 100644 --- a/src/render/WaterLevel.h +++ b/src/render/WaterLevel.h @@ -1,8 +1,10 @@ #pragma once -#define WATER_BLOCK_SIZE LARGE_SECTOR_SIZE -#define WATER_FINEBLOCK_SIZE HUGE_SECTOR_SIZE -#define WATER_Z_OFFSET (1.5f) +#define WATER_X_OFFSET (400.0f) + +#define WATER_BLOCK_SECTORS MAX_LARGE_SECTORS +#define WATER_FINEBLOCK_SECTORS MAX_SMALL_SECTORS +#define WATER_Z_OFFSET (0.5f) #define MAX_SMALL_SECTORS 128 #define MAX_LARGE_SECTORS 64 @@ -29,6 +31,14 @@ #define WATER_SIGN_X(x) ( (x) - (WATER_WIDTH /2) ) #define WATER_SIGN_Y(y) ( (y) - (WATER_HEIGHT/2) ) +// 64x64 Large blocks 64x64 each +#define WATER_TO_BLOCK_X(x) ( WATER_UNSIGN_X(x) / WATER_BLOCK_SECTORS ) +#define WATER_TO_BLOCK_Y(x) ( WATER_UNSIGN_Y(x) / WATER_BLOCK_SECTORS ) + +// 128x128 Small blocks 32x32 each +#define WATER_TO_FINEBLOCK_X(x) ( WATER_UNSIGN_X(x) / WATER_FINEBLOCK_SECTORS ) +#define WATER_TO_FINEBLOCK_Y(x) ( WATER_UNSIGN_Y(x) / WATER_FINEBLOCK_SECTORS ) + // 32 #define WATER_SMALL_X(x) ( WATER_UNSIGN_X(x) / MAX_SMALL_SECTORS ) #define WATER_SMALL_Y(y) ( WATER_UNSIGN_Y(y) / MAX_SMALL_SECTORS ) @@ -61,40 +71,108 @@ #define WATER_TO_EXTRAHUGE_SECTOR_X(x) ( WATER_UNSIGN_X(x) / EXTRAHUGE_SECTOR_SIZE ) #define WATER_TO_EXTRAHUGE_SECTOR_Y(y) ( WATER_UNSIGN_Y(y) / EXTRAHUGE_SECTOR_SIZE ) +struct ColData +{ + uint8 SurfaceType; + uint8 PieceType; +}; -#define MAX_BOAT_WAKES 8 +enum eBeachToy +{ + BEACHTOY_0 = 0, + BEACHTOY_BALL, + BEACHTOY_2, + BEACHTOY_3, + BEACHTOY_4, + BEACHTOY_LOUNGE = 5, + BEACHTOY_6, + BEACHTOY_11 = 11 +}; extern RwRaster* gpWaterRaster; extern bool gbDontRenderWater; +class CEntity; + class CWaterLevel { +public: static int32 ms_nNoOfWaterLevels; static float ms_aWaterZs[48]; static CRect ms_aWaterRects[48]; - static uint8 aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; - static uint8 aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; + static uint8 aWaterBlockList[WATER_BLOCK_SECTORS][WATER_BLOCK_SECTORS]; // 64x64 Large blocks 64x64 each + static uint8 aWaterFineBlockList[WATER_FINEBLOCK_SECTORS][WATER_FINEBLOCK_SECTORS]; // 128x128 Small blocks 32x32 each static bool WavesCalculatedThisFrame; - static RpAtomic *ms_pWavyAtomic; - static RpGeometry *apGeomArray[MAX_BOAT_WAKES]; - static int16 nGeomUsed; + + static bool RequireWavySector; + static bool MaskCalculatedThisFrame; + static CVector PreCalculatedMaskPosn; + static bool m_bRenderSeaBed; + static int32 m_nRenderWaterLayers; + + static RpAtomic *ms_pWavyAtomic; + static RpAtomic *ms_pMaskAtomic; -public: - static void Initialise(Const char *pWaterDat); static void Shutdown(); + static void CreateWavyAtomic(); static void DestroyWavyAtomic(); + + static bool GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ); static bool GetWaterLevel(CVector coors, float *pfOutLevel, bool bDontCheckZ) { return GetWaterLevel(coors.x, coors.y, coors.z, pfOutLevel, bDontCheckZ); } static bool GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel); + static float GetWaterWavesOnly(short x, short y); // unused + static CVector GetWaterNormal(float fX, float fY); + static void RenderWater(); - static void RenderOneFlatSmallWaterPoly (float fX, float fY, float fZ, RwRGBA const &color); - static void RenderOneFlatLargeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color); - static void RenderOneFlatHugeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color); - static void RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color); - static void RenderOneWavySector (float fX, float fY, float fZ, RwRGBA const &color, bool bUnk = false); - static float CalcDistanceToWater(float fX, float fY); - static void RenderAndEmptyRenderBuffer(); - static void AllocateBoatWakeArray(); - static void FreeBoatWakeArray(); + static void RenderTransparentWater(void); + // unused + static void RenderOneFlatSmallWaterPoly (float fX, float fY, float fZ, RwRGBA const &color); + // inlined + static void RenderOneFlatLargeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color); + static void RenderOneFlatHugeWaterPoly (float fX, float fY, float fZ, RwRGBA const &color); + static void RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color); + // inlined + static void RenderOneWavySector (float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender = false); + // unused +#ifdef PC_WATER + static void RenderWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, float fCamPosX, float fCamPosY, float fCamDirX, float fCamDirY, RwRGBA const&color); +#else + static void RenderWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, int32 nCamDirX, int32 nCamDirY, RwRGBA const&color); +#endif + +#ifdef PC_WATER + static void PreCalcWaterGeometry(void); + static bool PreCalcWavySector(RwRGBA const &color); //fucked up + static bool PreCalcWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, float fCamPosX, float fCamPosY, float fCamDirX, float fCamDirY, RwRGBA const&color); +#endif + + + static void RenderBoatWakes(void); + static void RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD, float &fSizeA, float &fSizeB, float &fAlphaA, float &fAlphaB, float &fWakeZ); + + // unused + static void RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color); // UNUSED + static void RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY, RwRGBA const &color, RwRGBA const &colorTrans, float fDrawDist); + static float CalcDistanceToWater(float fX, float fY); + static void RenderAndEmptyRenderBuffer(); + + static bool GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance); + + // unused + static bool IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset); + // unused + static bool GetGroundLevel_WS(CVector const & vecPosn, float *pfOutLevel, ColData *pData, float fDistance); + static bool GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel); + + static void RenderSeaBirds(); + static void RenderShipsOnHorizon(); + + static void HandleSeaLifeForms(); + + static void HandleBeachToysStuff(void); + static CEntity *CreateBeachToy(CVector const &vec, eBeachToy beachtoy); }; + +extern void WaterLevelInitialise(Const char *datFile);
\ No newline at end of file diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 2c0b27d2..3f242362 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -8,6 +8,7 @@ #include "DMAudio.h" #include "General.h" #include "Pad.h" +#include "PlayerPed.h" #include "Particle.h" #include "RenderBuffer.h" #include "Stats.h" @@ -17,6 +18,10 @@ #include "Vehicle.h" #include "World.h" #include "ZoneCull.h" +#include "SpecialFX.h" +#include "Replay.h" + +//--MIAMI: file done int32 CWeather::SoundHandle = -1; @@ -31,7 +36,9 @@ uint32 CWeather::LightningStart; uint32 CWeather::LightningFlashLastChange; uint32 CWeather::WhenToPlayLightningSound; uint32 CWeather::LightningDuration; +int32 CWeather::StreamAfterRainTimer; +float CWeather::ExtraSunnyness; float CWeather::Foggyness; float CWeather::CloudCoverage; float CWeather::Wind; @@ -39,41 +46,60 @@ float CWeather::Rain; float CWeather::InterpolationValue; float CWeather::WetRoads; float CWeather::Rainbow; +float CWeather::SunGlare; +float CWeather::WindClipped; +float CWeather::TrafficLightBrightness; bool CWeather::bScriptsForceRain; -bool CWeather::Stored_StateStored; - -float CWeather::Stored_InterpolationValue; -int16 CWeather::Stored_OldWeatherType; -int16 CWeather::Stored_NewWeatherType; -float CWeather::Stored_Rain; tRainStreak Streaks[NUM_RAIN_STREAKS]; const int16 WeatherTypesList[] = { + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_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_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, + WEATHER_RAINY, WEATHER_RAINY, 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_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY +}; + +const int16 WeatherTypesList_WithHurricanes[] = { + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_CLOUDY, + WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_CLOUDY, WEATHER_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, 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, + WEATHER_CLOUDY, WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_HURRICANE, + WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY }; const float Windyness[] = { - 0.0f, // WEATHER_SUNNY + 0.25f,// WEATHER_SUNNY 0.7f, // WEATHER_CLOUDY 1.0f, // WEATHER_RAINY - 0.5f // WEATHER_FOGGY + 0.0f, // WEATHER_FOGGY + 0.0f, // WEATHER_EXTRA_SUNNY + 2.0f, // WEATHER_HURRICANE + 0.0f }; #define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50) @@ -104,10 +130,9 @@ const float Windyness[] = { void CWeather::Init(void) { - NewWeatherType = WEATHER_SUNNY; + NewWeatherType = WEATHER_EXTRA_SUNNY; bScriptsForceRain = false; - OldWeatherType = WEATHER_CLOUDY; - Stored_StateStored = false; + OldWeatherType = WEATHER_EXTRA_SUNNY; InterpolationValue = 0.0f; WhenToPlayLightningSound = 0; WeatherTypeInList = 0; @@ -119,30 +144,27 @@ void CWeather::Init(void) 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) % ARRAY_SIZE(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; + if(!CReplay::IsPlayingBack()){ + float fNewInterpolation = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f; + if (fNewInterpolation < InterpolationValue) { + // new hour + OldWeatherType = NewWeatherType; + if (ForcedWeatherType >= 0) + NewWeatherType = ForcedWeatherType; + else { + WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList); + NewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList]; + } } -#endif + InterpolationValue = fNewInterpolation; } - InterpolationValue = fNewInterpolation; + +#ifndef FINAL if (CPad::GetPad(1)->GetRightShockJustDown()) { NewWeatherType = (NewWeatherType + 1) % WEATHER_TOTAL; OldWeatherType = NewWeatherType; } +#endif // Lightning if (NewWeatherType != WEATHER_RAINY || OldWeatherType != WEATHER_RAINY) { @@ -188,14 +210,14 @@ void CWeather::Update(void) } // Wet roads - if (OldWeatherType == WEATHER_RAINY) { - if (NewWeatherType == WEATHER_RAINY) + if (OldWeatherType == WEATHER_RAINY || OldWeatherType == WEATHER_HURRICANE) { + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) WetRoads = 1.0f; else WetRoads = 1.0f - InterpolationValue; } else { - if (NewWeatherType == WEATHER_RAINY) + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) WetRoads = InterpolationValue; else WetRoads = 0.0f; @@ -203,10 +225,10 @@ void CWeather::Update(void) // Rain float fNewRain; - if (NewWeatherType == WEATHER_RAINY) { + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) { // 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 (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) { if (InterpolationValue < 0.4f) // if rain has just started (<24 minutes), always 0.5 fNewRain = 0.5f; @@ -214,22 +236,18 @@ void CWeather::Update(void) // 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; } + fNewRain = Max(fNewRain, 0.5f); } 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()); - } + Rain = fNewRain; // Clouds - if (OldWeatherType != WEATHER_SUNNY) + if (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY) CloudCoverage = 1.0f - InterpolationValue; else CloudCoverage = 0.0f; - if (NewWeatherType != WEATHER_SUNNY) + if (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY) CloudCoverage += InterpolationValue; // Fog @@ -239,12 +257,100 @@ void CWeather::Update(void) 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) + + // Extra Sunnyness + if (OldWeatherType == WEATHER_EXTRA_SUNNY) + ExtraSunnyness = 1.0f - InterpolationValue; + else + ExtraSunnyness = 0.0f; + if (NewWeatherType == WEATHER_EXTRA_SUNNY) + ExtraSunnyness += InterpolationValue; + + // Rainbow + if (OldWeatherType == WEATHER_CLOUDY && (NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_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; + + // Sun Glare + if (OldWeatherType == WEATHER_EXTRA_SUNNY) + SunGlare = 1.0f - InterpolationValue; + else + SunGlare = 0.0f; + if (NewWeatherType == WEATHER_EXTRA_SUNNY) + SunGlare += InterpolationValue; + + if (SunGlare > 0.0f) { + SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunDirection().z); + SunGlare = clamp(SunGlare, 0.0f, 1.0f); + if (!CSpecialFX::bSnapShotActive) + SunGlare *= (1.0f - (CGeneral::GetRandomNumber()&0x1F)*0.007f); + } + Wind = InterpolationValue * Windyness[NewWeatherType] + (1.0f - InterpolationValue) * Windyness[OldWeatherType]; + WindClipped = Min(1.0f, Wind); + + if (CClock::GetHours() > 20) + TrafficLightBrightness = 1.0f; + else if (CClock::GetHours() > 19) + TrafficLightBrightness = CClock::GetMinutes() / 60.0f; + else if (CClock::GetHours() > 6) + TrafficLightBrightness = 0.0f; + else if (CClock::GetHours() > 5) + TrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f; + else + TrafficLightBrightness = 1.0f; + TrafficLightBrightness = Max(WetRoads, TrafficLightBrightness); + TrafficLightBrightness = Max(Foggyness, TrafficLightBrightness); + TrafficLightBrightness = Max(Rain, TrafficLightBrightness); + AddRain(); + + if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && + !CGame::IsInInterior() && !CCutsceneMgr::IsRunning() && (CTimer::GetFrameCounter() & 7) == 0) { +#ifdef FIX_BUGS + if (FindPlayerPed() && (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f && + CClock::GetHours() > 6 && CClock::GetHours() < 18)) +#else + if (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f && + CClock::GetHours() > 6 && CClock::GetHours() < 18) +#endif + AddHeatHaze(); + } + + if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && !CGame::IsInInterior() && !CCutsceneMgr::IsRunning()) + AddBeastie(); +} + +void CWeather::AddHeatHaze() +{ + if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || + TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) + return; + CVector pos; + pos.x = SCREEN_WIDTH*0.5f; + if(TheCamera.GetLookingForwardFirstPerson()) + pos.y = CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT*0.25f, SCREEN_HEIGHT*0.9f); + else + pos.y = CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT*0.4f, SCREEN_HEIGHT*0.9f); + pos.z = 100.0f; + CParticle::AddParticle(PARTICLE_HEATHAZE_IN_DIST, pos, CVector(0.0f, 0.0f, 0.0f)); +} + +void CWeather::AddBeastie() +{ + if(FindPlayerVehicle() || CTimer::GetFrameCounter()%10 || (CGeneral::GetRandomNumber()&5) == 0) + return; + CVector pos = TheCamera.GetPosition(); + float dist = CGeneral::GetRandomNumberInRange(90.0f, 60.0f); + int angle = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE; + float c = CParticle::m_CosTable[angle]; + float s = CParticle::m_SinTable[angle]; + pos.x += dist*(c - s); + pos.y += dist*(c + s); + pos.z += CGeneral::GetRandomNumberInRange(7.5f, 30.0f); + CParticle::AddParticle(PARTICLE_BEASTIE, pos, CVector(0.0f, 0.0f, 0.0f)); } void CWeather::ForceWeather(int16 weather) @@ -264,6 +370,62 @@ void CWeather::ReleaseWeather() ForcedWeatherType = -1; } +void CWeather::AddSplashesDuringHurricane() +{ + RwRGBA colour = { 255, 255, 255, 32 }; + CVector pos = TheCamera.pTargetEntity ? TheCamera.pTargetEntity->GetPosition() : TheCamera.GetPosition(); + bool foundGround; + float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &foundGround) + 0.1f; + if(!foundGround) + groundZ = pos.z + 0.5f; + for(int i = 0; i < 20; i++){ + float dist = (CGeneral::GetRandomNumber()&0xFF)/255.0f + + CGeneral::GetRandomNumberInRange(-10.0f, 30.0f); + float angle; + uint8 rnd = CGeneral::GetRandomNumber(); + if(rnd&1) + angle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI; + else + angle = TheCamera.Orientation + (rnd-128)/160.0f; + pos.x = TheCamera.GetPosition().x + dist*Sin(angle); + pos.y = TheCamera.GetPosition().y + dist*Cos(angle); + pos.z = groundZ; + if(foundGround) + CParticle::AddParticle(PARTICLE_GROUND_STEAM, pos, CVector(-0.002f, -0.002f, 0.015f), nil, 0.0f, colour); + } +} + +static int startStreamAfterRain; + +void CWeather::AddStreamAfterRain() +{ + if(CClock::GetHours() > 6 && CClock::GetHours() < 18){ + RwRGBA colour = { 255, 255, 255, 24 }; + CVector pos = TheCamera.pTargetEntity ? TheCamera.pTargetEntity->GetPosition() : TheCamera.GetPosition(); + bool foundGround; + float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &foundGround) + 0.2f; + if(!foundGround) + groundZ = pos.z + 0.75f; + for(int i = 0; i < 20; i++){ + float dist = (CGeneral::GetRandomNumber()&0xFF)/255.0f + + CGeneral::GetRandomNumberInRange(-10.0f, 30.0f); + float angle; + uint8 rnd = CGeneral::GetRandomNumber(); + if(rnd&1) + angle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI; + else + angle = TheCamera.Orientation + (rnd-128)/160.0f; + pos.x = TheCamera.GetPosition().x + dist*Sin(angle); + pos.y = TheCamera.GetPosition().y + dist*Cos(angle); + pos.z = groundZ; + CParticle::AddParticle(PARTICLE_GROUND_STEAM, pos, CVector(0.0f, 0.0f, 0.015f), nil, 0.0f, colour); + } + }else{ + startStreamAfterRain = 0; + StreamAfterRainTimer = 800; + } +} + void CWeather::AddRain() { if (CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) @@ -275,104 +437,77 @@ void CWeather::AddRain() return; } } + + if(Rain > 0.0){ + startStreamAfterRain = 1; + StreamAfterRainTimer = 800; + }else if(startStreamAfterRain){ + if(StreamAfterRainTimer > 0){ + AddStreamAfterRain(); + StreamAfterRainTimer--; + }else{ + startStreamAfterRain = 0; + StreamAfterRainTimer = 800; + } + } + + if (Wind > 1.1f) + AddSplashesDuringHurricane(); + if (Rain <= 0.1f) return; static RwRGBA colour; - float screen_width = SCREEN_WIDTH; - float screen_height = SCREEN_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); + int numDrops = 5.0f * Rain; + int numSplashes = 2.0f * Rain; + CVector pos, dir; + for(int i = 0; i < numDrops; i++){ + pos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH); + pos.y = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_HEIGHT/5); + pos.z = 0.0f; + dir.x = 0.0f; + dir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f); + dir.z = 0.0f; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0); + + pos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH); + pos.y = CGeneral::GetRandomNumberInRange((int)SCREEN_HEIGHT/5, (int)SCREEN_HEIGHT/2); + pos.z = 0.0f; + dir.x = 0.0f; + dir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f); + dir.z = 0.0f; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0); + + pos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH); + pos.y = 0.0f; + pos.z = 0.0f; + dir.x = 0.0f; + dir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f); + dir.z = 0.0f; + CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0); + + float dist = CGeneral::GetRandomNumberInRange(0.0f, Max(10.0f*Rain, 40.0f)/2.0f); + float angle; + uint8 rnd = CGeneral::GetRandomNumber(); + if(rnd&1) + angle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI; + else + angle = TheCamera.Orientation + (rnd-128)/160.0f; + pos.x = TheCamera.GetPosition().x + dist*Sin(angle); + pos.y = TheCamera.GetPosition().y + dist*Cos(angle); 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); + CEntity *ent; + if(CWorld::ProcessVerticalLine(pos+CVector(0.0f, 0.0f, 40.0f), -40.0f, point, ent, true, false, false, false, true, false, nil)){ + pos.z = point.point.z; + for(int j = 0; j < numSplashes+15; j++){ + CVector pos2 = pos; + pos2.x += CGeneral::GetRandomNumberInRange(-15.0f, 15.0f); + pos2.y += CGeneral::GetRandomNumberInRange(-15.0f, 15.0f); + if(CGeneral::GetRandomNumber() & 1) + CParticle::AddParticle(PARTICLE_RAIN_SPLASH, pos2, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour); + else + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, pos2, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour); + } } } } @@ -420,9 +555,9 @@ void RenderOneRainStreak(CVector pos, CVector unused, int intensity, bool scale, 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; + RandomTex = 0.0f; + RandomTexX = 0.0f; + RandomTexY = 0.0f; } RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0.5f * u - RandomTex + RandomTexX); RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 0], -v * 0.5f + RandomTexY); @@ -445,6 +580,8 @@ void CWeather::RenderRainStreaks(void) int base_intensity = (64.0f - CTimeCycle::GetFogReduction()) / 64.0f * int(255 * Rain); if (base_intensity == 0) return; + if (TheCamera.m_CameraAverageSpeed > 1.75f) + return; TempBufferIndicesStored = 0; TempBufferVerticesStored = 0; for (int i = 0; i < NUM_RAIN_STREAKS; i++) { @@ -455,11 +592,11 @@ void CWeather::RenderRainStreaks(void) else{ int intensity; if (secondsElapsed < STREAK_INTEROLATION_TIME) - intensity = base_intensity * 0.5f * secondsElapsed / STREAK_INTEROLATION_TIME; + intensity = base_intensity * 0.25f * secondsElapsed / STREAK_INTEROLATION_TIME; else if (secondsElapsed > (STREAK_LIFETIME - STREAK_INTEROLATION_TIME)) - intensity = (STREAK_LIFETIME - secondsElapsed) * 0.5f * base_intensity / STREAK_INTEROLATION_TIME; + intensity = (STREAK_LIFETIME - secondsElapsed) * 0.25f * base_intensity / STREAK_INTEROLATION_TIME; else - intensity = base_intensity * 0.5f; + intensity = base_intensity * 0.25f; CVector dir = Streaks[i].direction; dir.Normalise(); CVector pos = Streaks[i].position + secondsElapsed * Streaks[i].direction; @@ -473,7 +610,7 @@ void CWeather::RenderRainStreaks(void) } else if ((CGeneral::GetRandomNumber() & 0xF00) == 0){ // 1/16 probability - Streaks[i].direction = CVector(4.0f, 4.0f, -4.0f); + Streaks[i].direction = CVector(0.0f, 0.0f, -12.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; @@ -481,8 +618,8 @@ void CWeather::RenderRainStreaks(void) } 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].position.x += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.04f; + Streaks[i].position.y += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.04f; Streaks[i].timer = CTimer::GetTimeInMilliseconds(); } } @@ -494,7 +631,7 @@ void CWeather::RenderRainStreaks(void) RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex[3])); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex)); if (RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 1)) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); @@ -510,23 +647,3 @@ void CWeather::RenderRainStreaks(void) TempBufferVerticesStored = 0; TempBufferIndicesStored = 0; } - -void CWeather::StoreWeatherState() -{ - Stored_StateStored = true; - Stored_InterpolationValue = InterpolationValue; - Stored_Rain = Rain; - Stored_NewWeatherType = NewWeatherType; - Stored_OldWeatherType = OldWeatherType; -} - -void CWeather::RestoreWeatherState() -{ -#ifdef FIX_BUGS // it's not used anyway though - Stored_StateStored = false; -#endif - InterpolationValue = Stored_InterpolationValue; - Rain = Stored_Rain; - NewWeatherType = Stored_NewWeatherType; - OldWeatherType = Stored_OldWeatherType; -} diff --git a/src/render/Weather.h b/src/render/Weather.h index 9c670317..ef62ebb6 100644 --- a/src/render/Weather.h +++ b/src/render/Weather.h @@ -1,21 +1,19 @@ enum { - WEATHER_SUNNY, + WEATHER_RANDOM = -1, + WEATHER_SUNNY = 0, WEATHER_CLOUDY, WEATHER_RAINY, - WEATHER_FOGGY + WEATHER_FOGGY, + WEATHER_EXTRA_SUNNY, + WEATHER_HURRICANE, + WEATHER_TOTAL, + + WEATHER_EXTRACOLOURS = 6 }; 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; @@ -29,7 +27,9 @@ public: static uint32 LightningFlashLastChange; static uint32 WhenToPlayLightningSound; static uint32 LightningDuration; + static int32 StreamAfterRainTimer; + static float ExtraSunnyness; static float Foggyness; static float CloudCoverage; static float Wind; @@ -37,13 +37,11 @@ public: static float InterpolationValue; static float WetRoads; static float Rainbow; + static float SunGlare; + static float WindClipped; + static float TrafficLightBrightness; static bool bScriptsForceRain; - static bool Stored_StateStored; - static float Stored_InterpolationValue; - static int16 Stored_OldWeatherType; - static int16 Stored_NewWeatherType; - static float Stored_Rain; static void RenderRainStreaks(void); static void Update(void); @@ -52,9 +50,11 @@ public: static void ReleaseWeather(); static void ForceWeather(int16); static void ForceWeatherNow(int16); - static void StoreWeatherState(); - static void RestoreWeatherState(); + static void AddSplashesDuringHurricane(); + static void AddStreamAfterRain(); static void AddRain(); + static void AddHeatHaze(); + static void AddBeastie(); }; enum { @@ -68,4 +68,4 @@ struct tRainStreak uint32 timer; }; -extern RwTexture* gpRainDropTex[4];
\ No newline at end of file +extern RwTexture* gpRainDropTex;
\ No newline at end of file diff --git a/src/render/WindModifiers.cpp b/src/render/WindModifiers.cpp new file mode 100644 index 00000000..2061df6a --- /dev/null +++ b/src/render/WindModifiers.cpp @@ -0,0 +1,51 @@ +#include "common.h" +#include "WindModifiers.h" +#include "Camera.h" +#include "General.h" + +#define MAX_HEIGHT_DIST 40.0f +#define MIN_FADE_DIST 20.0f +#define MAX_FADE_DIST 50.0f + +CWindModifiers Array[16]; +int32 CWindModifiers::Number; + +void +CWindModifiers::RegisterOne(CVector pos, int32 type = 1) +{ + if (CWindModifiers::Number < 16 && (pos - TheCamera.GetPosition()).Magnitude() < 100.0f) { + Array[Number].m_pos = pos; + Array[Number].m_type = type; + Number++; + } +} + +bool +CWindModifiers::FindWindModifier(CVector pos, float *x, float *y) +{ + bool bWasWindModifierFound = false; + CVector2D dir; + for (int i = 0; i < Number; i++) { + if (Array[i].m_type == 1) { + float zDist = Abs(15.0f + pos.z - Array[i].m_pos.z); + + if (zDist < MAX_HEIGHT_DIST) { + float dist = (pos - Array[i].m_pos).Magnitude(); + if (dist < MAX_FADE_DIST) { + float distFade = dist < MIN_FADE_DIST ? 1.0f : 1.0f - (dist - MIN_FADE_DIST) / (MAX_FADE_DIST - MIN_FADE_DIST); + float heightFade = 1.0f - zDist / MAX_HEIGHT_DIST; + dir = (pos - Array[i].m_pos) * heightFade / dist; + bWasWindModifierFound = true; + } + } + } + } + + if (bWasWindModifierFound) { + float directionMult = ((CGeneral::GetRandomNumber() & 0x1F) - 16) * 0.0035f + 1.0f; + *x += dir.x * directionMult; + *y += dir.y * directionMult; + } + + return bWasWindModifierFound; +} diff --git a/src/render/WindModifiers.h b/src/render/WindModifiers.h new file mode 100644 index 00000000..7c2e57bd --- /dev/null +++ b/src/render/WindModifiers.h @@ -0,0 +1,11 @@ +#pragma once + +class CWindModifiers +{ + CVector m_pos; + int32 m_type; +public: + static int32 Number; + static void RegisterOne(CVector pos, int32 windSourceType); + static bool FindWindModifier(CVector pos, float *x, float *y); +}; |