diff options
Diffstat (limited to 'src/renderer')
62 files changed, 14977 insertions, 5615 deletions
diff --git a/src/renderer/2dEffect.h b/src/renderer/2dEffect.h index a8013b34..8ad2b946 100644 --- a/src/renderer/2dEffect.h +++ b/src/renderer/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); -#if GTA_VERSION >= GTA3_PC_11 light.corona = nil; -#endif if(light.shadow) RwTextureDestroy(light.shadow); -#if GTA_VERSION >= GTA3_PC_11 light.shadow = nil; -#endif } } }; diff --git a/src/renderer/Clouds.cpp b/src/renderer/Clouds.cpp index 957844a5..9cd32c5f 100644 --- a/src/renderer/Clouds.cpp +++ b/src/renderer/Clouds.cpp @@ -4,6 +4,7 @@ #include "Sprite.h" #include "Sprite2d.h" #include "General.h" +#include "Game.h" #include "Coronas.h" #include "Camera.h" #include "TxdStore.h" @@ -24,8 +25,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) @@ -45,25 +48,15 @@ void CClouds::Shutdown(void) { RwTextureDestroy(gpCloudTex[0]); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[0] = nil; -#endif RwTextureDestroy(gpCloudTex[1]); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[1] = nil; -#endif RwTextureDestroy(gpCloudTex[2]); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[2] = nil; -#endif RwTextureDestroy(gpCloudTex[3]); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[3] = nil; -#endif RwTextureDestroy(gpCloudTex[4]); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[4] = nil; -#endif } void @@ -71,15 +64,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 }; @@ -124,6 +117,9 @@ CClouds::Render(void) RwV3d screenpos; RwV3d worldpos; + if(!CGame::CanSeeOutSideFromCurrArea()) + return; + PUSH_RENDERGROUP("CClouds::Render"); CCoronas::SunBlockedByClouds = false; @@ -135,25 +131,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 = 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); } @@ -202,7 +193,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; @@ -223,10 +214,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); @@ -238,15 +229,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,11 +269,10 @@ CClouds::Render(void) for(i = 0; i < 37; i++){ RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f }; worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x; - worldpos.y = pos.x*rot_sin - pos.y*rot_cos + campos.y; + worldpos.y = pos.x*rot_sin + pos.y*rot_cos + campos.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, @@ -329,14 +320,17 @@ CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue, { PUSH_RENDERGROUP("CClouds::RenderBackground"); - 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; @@ -359,75 +353,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; } POP_RENDERGROUP(); @@ -439,28 +432,42 @@ CClouds::RenderHorizon(void) if(UseDarkBackground()) return; + PUSH_RENDERGROUP("CClouds::RenderHorizon"); + 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; - PUSH_RENDERGROUP("CClouds::RenderHorizon"); + 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); POP_RENDERGROUP(); } diff --git a/src/renderer/Clouds.h b/src/renderer/Clouds.h index 4d8cd2c8..ef33030b 100644 --- a/src/renderer/Clouds.h +++ b/src/renderer/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/renderer/Console.cpp b/src/renderer/Console.cpp index 8ea5b7a3..244bfb17 100644 --- a/src/renderer/Console.cpp +++ b/src/renderer/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/renderer/Coronas.cpp b/src/renderer/Coronas.cpp index e9f9e662..d9bf88d1 100644 --- a/src/renderer/Coronas.cpp +++ b/src/renderer/Coronas.cpp @@ -3,6 +3,7 @@ #include "main.h" #include "General.h" #include "Entity.h" +#include "RenderBuffer.h" #include "TxdStore.h" #include "Camera.h" #include "Sprite.h" @@ -58,7 +59,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; @@ -134,13 +135,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; @@ -193,15 +203,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 @@ -316,7 +330,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? @@ -378,7 +392,7 @@ CCoronas::Render(void) } } - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); @@ -434,9 +448,7 @@ CCoronas::RenderReflections(void) if(CWeather::WetRoads > 0.0f){ PUSH_RENDERGROUP("CCoronas::RenderReflections"); -#ifdef FIX_BUGS CSprite::InitSpriteBuffer(); -#endif RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -475,7 +487,7 @@ CCoronas::RenderReflections(void) CVector spriteCoors; float spritew, spriteh; - if(CSprite::CalcScreenCoors(coors, &spriteCoors, &spritew, &spriteh, true)){ + if(CSprite::CalcScreenCoors(coors, &spriteCoors, &spritew, &spriteh, true)) { float drawDist = 0.75f * aCoronas[i].drawDist; drawDist = Min(drawDist, 55.0f); if(spriteCoors.z < drawDist){ @@ -519,6 +531,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) { @@ -535,7 +671,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(), @@ -544,7 +680,7 @@ CCoronas::DoSunAndMoon(void) CVector spriteCoors; float spritew, spriteh; - if(CSprite::CalcScreenCoors(sunCoors, &spriteCoors, &spritew, &spriteh, true)){ + if(CSprite::CalcScreenCoors(sunCoors, &spriteCoors, &spritew, &spriteh, true)) { SunScreenX = spriteCoors.x; SunScreenY = spriteCoors.y; }else{ @@ -611,80 +747,66 @@ CEntity::ProcessLightsForEntity(void) for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){ effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i); - if(effect->type != EFFECT_LIGHT) - continue; + switch(effect->type){ + case EFFECT_LIGHT: + pos = GetMatrix() * effect->pos; - pos = GetMatrix() * effect->pos; - - lightOn = false; - lightFlickering = false; - switch(effect->light.lightType){ - case LIGHT_ON: - lightOn = true; - break; - case LIGHT_ON_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) - lightOn = true; - break; - case LIGHT_FLICKER: - if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) - lightOn = true; - else - lightFlickering = true; - if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3) + lightOn = false; + lightFlickering = false; + switch(effect->light.lightType){ + case LIGHT_ON: lightOn = true; - break; - case LIGHT_FLICKER_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){ + break; + case LIGHT_ON_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + lightOn = true; + break; + case LIGHT_FLICKER: if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) lightOn = true; else lightFlickering = true; if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3) lightOn = true; - } - break; - case LIGHT_FLASH1: - if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200) - lightOn = true; - break; - case LIGHT_FLASH1_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + break; + case LIGHT_FLICKER_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){ + if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) + lightOn = true; + else + lightFlickering = true; + if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3) + lightOn = true; + } + break; + case LIGHT_FLASH1: if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200) lightOn = true; - break; - case LIGHT_FLASH2: - if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400) - lightOn = true; - break; - case LIGHT_FLASH2_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + break; + case LIGHT_FLASH1_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200) + lightOn = true; + break; + case LIGHT_FLASH2: if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400) lightOn = true; - break; - case LIGHT_FLASH3: - if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800) - lightOn = true; - break; - case LIGHT_FLASH3_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + break; + case LIGHT_FLASH2_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400) + lightOn = true; + break; + case LIGHT_FLASH3: if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800) lightOn = true; - break; - case LIGHT_RANDOM_FLICKER: - if(m_randomSeed > 16) - lightOn = true; - else{ - if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60) - lightOn = true; - else - lightFlickering = true; - if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3) - lightOn = true; - } - break; - case LIGHT_RANDOM_FLICKER_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7){ + break; + case LIGHT_FLASH3_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800) + lightOn = true; + break; + case LIGHT_RANDOM_FLICKER: if(m_randomSeed > 16) lightOn = true; else{ @@ -695,85 +817,143 @@ CEntity::ProcessLightsForEntity(void) if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3) lightOn = true; } + break; + case LIGHT_RANDOM_FLICKER_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7){ + if(m_randomSeed > 16) + lightOn = true; + else{ + if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60) + lightOn = true; + else + lightFlickering = true; + if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3) + lightOn = true; + } + } + break; + case LIGHT_BRIDGE_FLASH1: + if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200) + lightOn = true; + break; + case LIGHT_BRIDGE_FLASH2: + if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60) + lightOn = true; + break; + } + + if(effect->light.flags & LIGHTFLAG_HIDE_OBJECT){ + if(lightOn) + bDoNotRender = false; + else + bDoNotRender = true; + return; + } + + // Corona + if(lightOn) + CCoronas::RegisterCorona((uintptr)this + i, + effect->col.r, effect->col.g, effect->col.b, 255, + pos, effect->light.size, effect->light.dist, + effect->light.corona, effect->light.flareType, effect->light.roadReflection, + effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f, + !!(effect->light.flags&LIGHTFLAG_LONG_DIST)); + else if(lightFlickering) + CCoronas::RegisterCorona((uintptr)this + i, + 0, 0, 0, 255, + pos, effect->light.size, effect->light.dist, + effect->light.corona, effect->light.flareType, effect->light.roadReflection, + effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f, + !!(effect->light.flags&LIGHTFLAG_LONG_DIST)); + + // Pointlight + bool alreadyProcessedFog; + alreadyProcessedFog = false; + if(effect->light.range != 0.0f && lightOn){ + if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){ + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos, CVector(0.0f, 0.0f, 0.0f), + effect->light.range, + 0.0f, 0.0f, 0.0f, + CPointLights::FOG_NONE, true); + }else{ + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos, CVector(0.0f, 0.0f, 0.0f), + effect->light.range, + effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f, + effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f, + effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f, + (effect->light.flags & LIGHTFLAG_FOG) >> 1, + true); + alreadyProcessedFog = true; + } } - break; - case LIGHT_BRIDGE_FLASH1: - if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200) - lightOn = true; - break; - case LIGHT_BRIDGE_FLASH2: - if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60) - lightOn = true; - break; - } - // Corona - if(lightOn) - CCoronas::RegisterCorona((uintptr)this + i, - effect->col.r, effect->col.g, effect->col.b, 255, - pos, effect->light.size, effect->light.dist, - effect->light.corona, effect->light.flareType, effect->light.roadReflection, - effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f); - else if(lightFlickering) - CCoronas::RegisterCorona((uintptr)this + i, - 0, 0, 0, 255, - pos, effect->light.size, effect->light.dist, - effect->light.corona, effect->light.flareType, effect->light.roadReflection, - effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f); - - // Pointlight - if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){ - CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, - CPointLights::FOG_ALWAYS, true); - }else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){ - CPointLights::AddLight(CPointLights::LIGHT_FOGONLY, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, - CPointLights::FOG_NORMAL, true); - }else if(lightOn && effect->light.range != 0.0f){ - if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){ - CPointLights::AddLight(CPointLights::LIGHT_POINT, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - 0.0f, 0.0f, 0.0f, - CPointLights::FOG_NONE, true); - }else{ - CPointLights::AddLight(CPointLights::LIGHT_POINT, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f, - effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f, - effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f, - // half-useless because LIGHTFLAG_FOG_ALWAYS can't be on - (effect->light.flags & LIGHTFLAG_FOG) >> 1, - true); + if(!alreadyProcessedFog){ + if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){ + CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS, + pos, CVector(0.0f, 0.0f, 0.0f), + 0.0f, + effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, + CPointLights::FOG_ALWAYS, true); + }else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){ + CPointLights::AddLight(CPointLights::LIGHT_FOGONLY, + pos, CVector(0.0f, 0.0f, 0.0f), + 0.0f, + effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, + CPointLights::FOG_NORMAL, true); + } } - } - // Light shadow - if(effect->light.shadowSize != 0.0f){ - if(lightOn){ - CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, - effect->light.shadow, &pos, - effect->light.shadowSize, 0.0f, - 0.0f, -effect->light.shadowSize, - 128, - effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, - effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, - effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, - 15.0f, 1.0f, 40.0f, false, 0.0f); - }else if(lightFlickering){ - CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, - effect->light.shadow, &pos, - effect->light.shadowSize, 0.0f, - 0.0f, -effect->light.shadowSize, - 0, 0.0f, 0.0f, 0.0f, - 15.0f, 1.0f, 40.0f, false, 0.0f); + // Light shadow + if(effect->light.shadowSize != 0.0f){ + if(lightOn){ + CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, + effect->light.shadow, &pos, + effect->light.shadowSize, 0.0f, + 0.0f, -effect->light.shadowSize, + 128, + effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, + effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, + effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, + 15.0f, 1.0f, 40.0f, false, 0.0f); + }else if(lightFlickering){ + CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, + effect->light.shadow, &pos, + effect->light.shadowSize, 0.0f, + 0.0f, -effect->light.shadowSize, + 0, 0.0f, 0.0f, 0.0f, + 15.0f, 1.0f, 40.0f, false, 0.0f); + } } + break; + + case EFFECT_SUNGLARE: + if(CWeather::SunGlare >= 0.0f){ + CVector pos = GetMatrix() * effect->pos; + CVector glareDir = pos - GetPosition(); + glareDir.Normalise(); + CVector camDir = TheCamera.GetPosition() - pos; + float dist = camDir.Magnitude(); + camDir *= 2.0f/dist; + glareDir += camDir; + glareDir.Normalise(); + float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection()); + if(camAngle > 0.0f){ + float intens = Sqrt(camAngle) * CWeather::SunGlare; + pos += camDir; + CCoronas::RegisterCorona((uintptr)this + 33 + i, + intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f, + intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f, + intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f, + 255, + pos, 0.5f*CWeather::SunGlare*Sqrt(dist), 120.0f, + CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, + CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, + CCoronas::STREAK_OFF, 0.0f); + } + } + break; } } -} +}
\ No newline at end of file diff --git a/src/renderer/Coronas.h b/src/renderer/Coronas.h index 46eb4315..45f027d8 100644 --- a/src/renderer/Coronas.h +++ b/src/renderer/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/renderer/Credits.cpp b/src/renderer/Credits.cpp index 60581793..81e76625 100644 --- a/src/renderer/Credits.cpp +++ b/src/renderer/Credits.cpp @@ -7,6 +7,7 @@ #include "Camera.h" #include "Text.h" #include "Credits.h" +#include "Pad.h" bool CCredits::bCreditsGoing; uint32 CCredits::CreditsStartTime; @@ -39,22 +40,21 @@ CCredits::PrintCreditSpace(float space, uint32 &line) void CCredits::PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset) { -#ifdef FIX_BUGS - float start = DEFAULT_SCREEN_HEIGHT + 50.0f; -#else - float start = SCREEN_HEIGHT + 50.0f; -#endif - float y = lineoffset + start - scrolloffset; - if(y > -50.0f && y < start){ -#ifdef FIX_BUGS - CFont::SetScale(SCREEN_SCALE_X(scaleX), SCREEN_SCALE_Y(scaleY)); - CFont::PrintString(SCREEN_WIDTH/2.0f, SCREEN_SCALE_Y(y), (uint16*)text); -#else - CFont::SetScale(scaleX, scaleY); - CFont::PrintString(SCREEN_WIDTH/2.0f, y, (uint16*)text); -#endif + 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 @@ -71,434 +71,736 @@ CCredits::Render(void) scrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f; CFont::SetJustifyOff(); CFont::SetBackgroundOff(); -#ifdef FIX_BUGS - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); -#else - CFont::SetCentreSize(SCREEN_WIDTH - 20); -#endif + CFont::SetCentreSize(SCREEN_SCALE_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(SCREEN_SCALE_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(SCREEN_SCALE_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(SCREEN_SCALE_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(SCREEN_SCALE_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(SCREEN_SCALE_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(SCREEN_SCALE_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(); +#ifdef CUTSCENE_BORDERS_SWITCH + if (CMenuManager::m_PrefsCutsceneBorders) +#endif if(TheCamera.m_WideScreenOn) TheCamera.DrawBordersForWideScreen(); diff --git a/src/renderer/CutsceneShadow.cpp b/src/renderer/CutsceneShadow.cpp new file mode 100644 index 00000000..8cb33896 --- /dev/null +++ b/src/renderer/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/renderer/CutsceneShadow.h b/src/renderer/CutsceneShadow.h new file mode 100644 index 00000000..a59fe78f --- /dev/null +++ b/src/renderer/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/renderer/Draw.cpp b/src/renderer/Draw.cpp index f702f188..a5e7504b 100644 --- a/src/renderer/Draw.cpp +++ b/src/renderer/Draw.cpp @@ -5,8 +5,8 @@ #include "Camera.h" #include "CutsceneMgr.h" -#ifdef ASPECT_RATIO_SCALE float CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO; +#ifdef ASPECT_RATIO_SCALE float CDraw::ms_fScaledFOV = 45.0f; #endif @@ -30,15 +30,10 @@ bool CDraw::ms_bFixRadar = true; bool CDraw::ms_bFixSprites = true; #endif +#ifdef ASPECT_RATIO_SCALE float -CDraw::FindAspectRatio(void) +FindAspectRatio(void) { -#ifndef ASPECT_RATIO_SCALE - if(FrontEndMenuManager.m_PrefsUseWideScreen) - return 16.0f/9.0f; - else - return 4.0f/3.0f; -#else switch (FrontEndMenuManager.m_PrefsUseWideScreen) { case AR_AUTO: return SCREEN_WIDTH / SCREEN_HEIGHT; @@ -54,7 +49,30 @@ CDraw::FindAspectRatio(void) case AR_21_9: return 21.0f / 9.0f; }; +} +#endif + +float +CDraw::CalculateAspectRatio(void) +{ +#ifdef ASPECT_RATIO_SCALE + if (TheCamera.m_WideScreenOn) + CDraw::ms_fAspectRatio = (5.f / 3.f) * FindAspectRatio() / (16.f / 9.f); // It's used on theatrical showings according to Wiki + else + CDraw::ms_fAspectRatio = FindAspectRatio(); +#else + if(FrontEndMenuManager.m_PrefsUseWideScreen) { + 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; + } else if (TheCamera.m_WideScreenOn) { + CDraw::ms_fAspectRatio = 5.f/4.f; + } else { + CDraw::ms_fAspectRatio = 4.f/3.f; + } #endif + return CDraw::ms_fAspectRatio; } #ifdef ASPECT_RATIO_SCALE diff --git a/src/renderer/Draw.h b/src/renderer/Draw.h index 8727e0e0..b96fa813 100644 --- a/src/renderer/Draw.h +++ b/src/renderer/Draw.h @@ -10,7 +10,7 @@ enum eAspectRatio AR_16_10, AR_16_9, AR_21_9, - + AR_MAX, }; @@ -20,10 +20,10 @@ private: static float ms_fNearClipZ; static float ms_fFarClipZ; static float ms_fFOV; -#ifdef ASPECT_RATIO_SCALE // we use this variable to scale a lot of 2D elements // so better cache it static float ms_fAspectRatio; +#ifdef ASPECT_RATIO_SCALE // similar thing for 3D rendering static float ms_fScaledFOV; #endif @@ -58,15 +58,12 @@ 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 - #ifdef PROPER_SCALING static float ScaleY(float y); #endif diff --git a/src/renderer/Fluff.cpp b/src/renderer/Fluff.cpp index c4cfe7f7..1e4d289b 100644 --- a/src/renderer/Fluff.cpp +++ b/src/renderer/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,300 @@ #include "Stats.h" #include "maths.h" #include "Frontend.h" +#include "CutsceneMgr.h" +#include "PlayerPed.h" +#include "Bones.h" +#include "World.h" +#include "Replay.h" +#include "Coronas.h" +#include "SaveBuf.h" + +#ifdef COMPATIBLE_SAVES +#define SCRIPTPATHS_SAVE_SIZE 0x9C +#else +#define SCRIPTPATHS_SAVE_SIZE sizeof(aArray) +#endif + +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 }, // ' ' @@ -79,23 +377,17 @@ uint8 ScrollCharSet[59][5] = { // ---------- CMovingThings ---------- enum eScrollBarTypes { - SCROLL_BUSINESS, - SCROLL_TRAFFIC, - SCROLL_ENTERTAINMENT, - SCROLL_AIRPORT_DOORS, - SCROLL_AIRPORT_FRONT, - SCROLL_STORE, - SCROLL_USED_CARS + SCROLL_ARENA_STRING }; -CScrollBar aScrollBars[11]; -CTowerClock aTowerClocks[2]; -CDigitalClock aDigitalClocks[3]; +CScrollBar aScrollBars[1]; CMovingThing CMovingThings::StartCloseList; CMovingThing CMovingThings::EndCloseList; int16 CMovingThings::Num; CMovingThing CMovingThings::aMovingThings[NUMMOVINGTHINGS]; + +int32 CScrollBar::TonightsEvent; void CMovingThings::Init() { @@ -103,126 +395,194 @@ void CMovingThings::Init() StartCloseList.m_pPrev = nil; EndCloseList.m_pNext = nil; EndCloseList.m_pPrev = &CMovingThings::StartCloseList; + + CPlaneTrails::Init(); + CSmokeTrails::Init(); + CPlaneBanners::Init(); + CPointLights::Init(); + Num = 0; - - // 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); - aScrollBars[2].Init(CVector(-1089.61f, -584.224f, 13.246f), SCROLL_AIRPORT_DOORS, 0.0f, -0.1706f, 0.107f, 255, 0, 0, 0.11f); - aScrollBars[3].Init(CVector(-1089.61f, -602.04602f, 13.246f), SCROLL_AIRPORT_DOORS, 0.0f, -0.1706f, 0.107f, 0, 255, 0, 0.11f); - aScrollBars[4].Init(CVector(-1089.61f, -619.81702f, 13.246f), SCROLL_AIRPORT_DOORS, 0.0f, -0.1706f, 0.107f, 255, 128, 0, 0.11f); - aScrollBars[5].Init(CVector(-754.578f, -633.50897f, 18.411f), SCROLL_AIRPORT_FRONT, 0.0f, 0.591f, 0.52f, 100, 100, 255, 0.3f); - aScrollBars[6].Init(CVector( -754.578f, -586.672f, 18.411f), SCROLL_AIRPORT_FRONT, 0.0f, 0.591f, 0.52f, 100, 100, 255, 0.3f); - aScrollBars[7].Init(CVector( 85.473f, -1069.512f, 30.5f ), SCROLL_STORE, 0.625f, -0.3125f, 0.727f, 100, 100, 255, 0.5f); - aScrollBars[8].Init(CVector( 74.823f, -1086.879f, 31.495f), SCROLL_ENTERTAINMENT, -0.2083f, 0.1041f, 0.5f, 255, 255, 128, 0.3f); - aScrollBars[9].Init(CVector( -36.459f, -1031.2371f, 32.534f), SCROLL_ENTERTAINMENT, -0.1442f, 0.0721f, 0.229f, 150, 255, 50, 0.3f); - aScrollBars[10].Init(CVector( 1208.0f, -62.208f, 19.157f), SCROLL_USED_CARS, 0.0642f, -0.20365f, 0.229f, 255, 128, 0, 0.3f); - - // Initialize tower clocks - aTowerClocks[0].Init(CVector(59.4f, -1081.3f, 54.15f), -1.0f, 0.0f, 0, 0, 0, 80.0f, 2.0f); - aTowerClocks[1].Init(CVector(55.4f, -1083.6f, 54.15f), 0.0f, -1.0f, 0, 0, 0, 80.0f, 2.0f); - - // Initialize digital clocks - CVector2D sz(3.7f, 2.144f); - sz.Normalise(); - aDigitalClocks[0].Init( - CVector(54.485f - sz.x * 0.05f + sz.y * 0.3f, -1081.679f - sz.y * 0.05f - sz.x * 0.3f, 32.803f), - sz.y, -sz.x, 255, 0, 0, 100.0f, 0.8f - ); - aDigitalClocks[1].Init( - CVector(60.564f + sz.x * 0.05f - sz.y * 0.3f, -1083.089f + sz.y * 0.05f + sz.x * 0.3f, 32.803f), - -sz.y, sz.x, 0, 0, 255, 100.0f, 0.8f - ); - aDigitalClocks[2].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 - ); + + for (int32 i = 0; i < NUMMOVINGTHINGS; i++) { + aMovingThings[i].m_nType = 0; + aMovingThings[i].m_farAway = 0; + } + + for (int i = 0; i < NUMSECTORS_X; i++) { + for (int j = 0; j < NUMSECTORS_Y; j++) { + for (CPtrNode *pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + PossiblyAddThisEntity(pEntity); + } + } + } + + for (int32 i = 0; i < NUM_LEVELS; i++) { + for (CPtrNode *pNode = CWorld::GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + PossiblyAddThisEntity(pEntity); + } + } + + CEscalators::Init(); + aScrollBars[0].Init(CVector(-1069.209f, 1320.126f, 18.848f), CVector(-1069.209f, 1342.299f, 22.612f), SCROLL_ARENA_STRING, 128, 255, 0, 0.3f); } 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); + + aScrollBars[0].SetVisibility(false); + CEscalators::Shutdown(); } void CMovingThings::Update() { + CPlaneBanners::Update(); + CPlaneTrails::Update(); + CEscalators::Update(); + + const int TIME_SPAN = 8; // frames to process all aMovingThings + int16 i; -#ifndef SQUEEZE_PERFORMANCE - const int TIME_SPAN = 64; // frames to process all aMovingThings int block = CTimer::GetFrameCounter() % TIME_SPAN; for (i = (block * NUMMOVINGTHINGS) / TIME_SPAN; i < ((block + 1) * NUMMOVINGTHINGS) / TIME_SPAN; i++) { - if (aMovingThings[i].m_nHidden == 1) + if (aMovingThings[i].m_farAway == 1) aMovingThings[i].Update(); } for (i = 0; i < CMovingThings::Num; i++) { - if (aMovingThings[i].m_nHidden == 0) + if (aMovingThings[i].m_farAway == 0) aMovingThings[i].Update(); } -#endif for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i) { if (aScrollBars[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0) aScrollBars[i].Update(); } - for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i) - { - if (aTowerClocks[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0) - aTowerClocks[i].Update(); - } - for (i = 0; i < ARRAY_SIZE(aDigitalClocks); ++i) - { - if (aDigitalClocks[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0) - aDigitalClocks[i].Update(); - } } void CMovingThings::Render() { - int i; PUSH_RENDERGROUP("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()) - aTowerClocks[i].Render(); + + CPlaneTrails::Render(); + CSmokeTrails::Render(); + CPlaneBanners::Render(); + POP_RENDERGROUP(); +} + +void CMovingThings::RegisterOne(CEntity *pEnt, uint16 nType) { + if (Num >= NUMMOVINGTHINGS) + return; + + aMovingThings[Num].m_pEntity = pEnt; + aMovingThings[Num].m_nType = nType; + aMovingThings[Num].m_farAway = 0; + aMovingThings[Num].m_vecPosn = pEnt->GetPosition(); + aMovingThings[Num].AddToList(&CMovingThings::StartCloseList); + Num++; +} + +void CMovingThings::PossiblyAddThisEntity(CEntity *pEnt) { + if (pEnt->GetModelIndex() == MI_LIGHTBEAM) { + RegisterOne(pEnt, 1); } - for (i = 0; i < ARRAY_SIZE(aDigitalClocks); ++i) - { - if (aDigitalClocks[i].IsVisible()) - aDigitalClocks[i].Render(); + else if (pEnt->GetModelIndex() == MI_AIRPORTRADAR) { + RegisterOne(pEnt, 2); + } + else if (pEnt->GetModelIndex() == MI_MALLFAN || pEnt->GetModelIndex() == MI_HOTELFAN_NIGHT + || pEnt->GetModelIndex() == MI_HOTELFAN_DAY || pEnt->GetModelIndex() == MI_HOTROOMFAN) { + RegisterOne(pEnt, 3); + } + else if (pEnt->GetModelIndex() == MI_BLIMP_NIGHT || pEnt->GetModelIndex() == MI_BLIMP_DAY) { + RegisterOne(pEnt, 4); } - POP_RENDERGROUP(); } // ---------- CMovingThing ---------- +static float maxUpdateDists[5] = { 100.0f, 1500.0f, 400.0f, 100.0f, 2000.0f }; + void CMovingThing::Update() { + switch (m_nType) { + case 1: { + float angle = (CTimer::GetTimeInMilliseconds() % 0x3FFF) * TWOPI / 0x3FFF; + float s = Sin(angle); + float c = Cos(angle); + m_pEntity->GetRight() = CVector(-s, c, 0.0f); + m_pEntity->GetForward() = CVector(0.0f, 0.0f, 1.0f); + m_pEntity->GetUp() = CVector(c, s, 0.0f); + + if (CClock::GetHours() >= 20 || CClock::GetHours() < 5) { + if (Abs(TheCamera.GetPosition().x - m_pEntity->GetPosition().x) < 600.0f && + Abs(TheCamera.GetPosition().y - m_pEntity->GetPosition().y) < 600.0f) { + CVector delta = m_pEntity->GetPosition() - TheCamera.GetPosition(); + delta /= delta.Magnitude(); + + if (DotProduct(delta, CVector(c, s, 0.0f)) < -0.92f) { + CVector coors = m_pEntity->GetPosition() - 10.0f * delta; + CCoronas::RegisterCorona(43, 128, 128, 100, 255, coors, 70.0f, 600.0f, 0.0f, CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + } + } + } + } + break; + case 2: { + float angle = (CTimer::GetTimeInMilliseconds() % 0x7FF) * TWOPI / 0x7FF; + float s = Sin(angle); + float c = Cos(angle); + m_pEntity->GetRight() = CVector(c, s, 0.0f); + m_pEntity->GetForward() = CVector(-s, c, 0.0f); + m_pEntity->GetUp() = CVector(0.0f, 0.0f, 1.0f); + } + break; + case 3: { + float angle = (CTimer::GetTimeInMilliseconds() % 0x3FF) * TWOPI / 0x3FF; + float s = Sin(angle); + float c = Cos(angle); + m_pEntity->GetRight() = CVector(c, s, 0.0f); + m_pEntity->GetForward() = CVector(-s, c, 0.0f); + m_pEntity->GetUp() = CVector(0.0f, 0.0f, 1.0f); + } + break; + case 4: { + float angle = (CTimer::GetTimeInMilliseconds() % 0x3FFFF) * TWOPI / 0x3FFFF; + float s = Sin(angle); + float c = Cos(angle); + m_pEntity->GetRight() = CVector(-c, -s, 0.0f); + m_pEntity->GetForward() = CVector(s, -c, 0.0f); + m_pEntity->GetUp() = CVector(0.0f, 0.0f, 1.0f); + m_pEntity->SetPosition(CVector(350.0f * c - 465.0f, 350.0f * s + 1163.0f, 260.0f)); + } + break; + default: + break; + } + m_pEntity->GetMatrix().UpdateRW(); m_pEntity->UpdateRwFrame(); - if (SQR(m_pEntity->GetPosition().x - TheCamera.GetPosition().x) + SQR(m_pEntity->GetPosition().y - TheCamera.GetPosition().y) < 40000.0f) { - if (m_nHidden == 1) { + if (SQR(m_pEntity->GetPosition().x - TheCamera.GetPosition().x) + SQR(m_pEntity->GetPosition().y - TheCamera.GetPosition().y) < SQR(maxUpdateDists[m_nType])) { + if (m_farAway == 1) { AddToList(&CMovingThings::StartCloseList); - m_nHidden = 0; + m_farAway = 0; } - } else { - if (m_nHidden == 0) { + } + else { + if (m_farAway == 0) { RemoveFromList(); - m_nHidden = 1; + m_farAway = 1; } } } @@ -254,29 +614,6 @@ int16 CMovingThing::SizeList() return count; } -// ---------- Find message functions ---------- -const char* FindTunnelMessage() -{ - if (CStats::CommercialPassed) - return "LIBERTY TUNNEL HAS BEEN OPENED TO ALL TRAFFIC . . . "; - - if (CStats::IndustrialPassed) - return "FIRST PHASE LIBERTY TUNNEL HAS BEEN COMPLETED . . . "; - - return "FIRST PHASE LIBERTY TUNNEL ABOUT TO BE COMPLETED . . . "; -} - -const char* FindBridgeMessage() -{ - if (CStats::CommercialPassed) - return "STAUNTON LIFT BRIDGE IS OPERATIONAL AGAIN "; - - if (CStats::IndustrialPassed) - return "LONG DELAYS BEHIND US AS CALLAHAN BRIDGE IS FIXED . . . STAUNTON LIFT BRIDGE STUCK OPEN "; - - return "CHAOS AS CALLAHAN BRIDGE IS UNDER REPAIR. . . "; -} - char String_Time[] = "THE TIME IS 12:34 "; const char* FindTimeMessage() { @@ -287,49 +624,23 @@ const char* FindTimeMessage() return String_Time; } -char String_DigitalClock[] = "12:34"; -const char* FindDigitalClockMessage() -{ - if (((CTimer::GetTimeInMilliseconds() >> 10) & 7) < 6) - { - String_DigitalClock[0] = '0' + CClock::GetHours() / 10; - String_DigitalClock[1] = '0' + CClock::GetHours() % 10; - String_DigitalClock[2] = CTimer::GetTimeInMilliseconds() & 0x200 ? ':' : ' '; - String_DigitalClock[3] = '0' + CClock::GetMinutes() / 10; - String_DigitalClock[4] = '0' + CClock::GetMinutes() % 10; - } - else - { - // they didn't use rad2deg here because of 3.14 - int temperature = 13.0f - 6.0f * Cos((CClock::GetMinutes() + 60.0f * CClock::GetHours()) / (4.0f * 180.0f / 3.14f) - 1.0f); - String_DigitalClock[0] = '0' + temperature / 10; - if (String_DigitalClock[0] == '0') - String_DigitalClock[0] = ' '; - String_DigitalClock[1] = '0' + temperature % 10; - String_DigitalClock[2] = ' '; - String_DigitalClock[3] = '@'; - String_DigitalClock[4] = 'C'; - } - return String_DigitalClock; -} - // ---------- CScrollBar ---------- -void CScrollBar::Init(CVector position, uint8 type, float sizeX, float sizeY, float sizeZ, uint8 red, uint8 green, uint8 blue, float scale) +void CScrollBar::Init(CVector pos1, CVector pos2, uint8 type, uint8 red, uint8 green, uint8 blue, float scale) { for (int i = 0; i < ARRAY_SIZE(m_MessageBar); ++i) m_MessageBar[i] = 0; m_pMessage = ". "; m_MessageCurrentChar = 0; - m_MessageLength = 2; + m_MessageLength = strlen(m_pMessage); m_Counter = 0; m_bVisible = false; - m_Position = position; + m_Position = pos1; m_Type = type; - m_Size.x = sizeX; - m_Size.y = sizeY; - m_Size.z = sizeZ; + m_Size.x = (pos2.x - pos1.x) * 0.025f; + m_Size.y = (pos2.y - pos1.y) * 0.025f; + m_Size.z = (pos2.z - pos1.z) * 0.2f; m_uRed = red; m_uGreen = green; m_uBlue = blue; @@ -358,263 +669,48 @@ void CScrollBar::Update() if (m_Counter == 0 && ++m_MessageCurrentChar >= m_MessageLength) { const char* previousMessage = m_pMessage; - switch (m_Type) - { - case SCROLL_BUSINESS: - while (previousMessage == m_pMessage) - { - switch (CGeneral::GetRandomNumber() % 7) - { - case 0: - m_pMessage = "SHARES UYE<10% DWD<20% NDWE>22% . . . "; - break; - case 1: - m_pMessage = "CRIME WAVE HITS LIBERTY CITY . . . "; - break; - case 2: - m_pMessage = "SHARES OBR>29% MADD<76% LEZ<11% ADAMSKI>53% AAG>110%. . . "; - break; - case 3: - m_pMessage = FindTunnelMessage(); - break; - case 4: - m_pMessage = FindBridgeMessage(); - break; - case 5: - m_pMessage = FindTimeMessage(); - break; - case 6: - if (CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_GERMAN) - m_pMessage = FindTimeMessage(); - else - m_pMessage = "WWW.GRANDTHEFTAUTO3.COM "; - break; - } - } - break; - case SCROLL_TRAFFIC: - while (previousMessage == m_pMessage) - { - switch (CGeneral::GetRandomNumber() % 8) - { - case 0: - m_pMessage = "DRIVE CAREFULLY . . . "; - break; - case 1: - m_pMessage = "RECENT WAVE OF CARJACKINGS. KEEP YOUR DOORS LOCKED !!! "; - break; - case 2: - m_pMessage = "CHECK YOUR SPEED . . . "; - break; - case 3: - m_pMessage = "KEEP YOUR EYES ON THE ROAD AND NOT ON THIS SIGN "; - break; - case 4: - if (CWeather::Foggyness > 0.5f) - m_pMessage = "POOR VISIBILITY ! "; - else if (CWeather::WetRoads > 0.5f) - m_pMessage = "ROADS ARE SLIPPERY ! "; - else - m_pMessage = "ENJOY YOUR TRIP "; - break; - case 5: - m_pMessage = FindTunnelMessage(); - break; - case 6: - m_pMessage = FindBridgeMessage(); - break; - case 7: - m_pMessage = FindTimeMessage(); - break; - } - } - break; - case SCROLL_ENTERTAINMENT: - while (previousMessage == m_pMessage) - { - switch (CGeneral::GetRandomNumber() % 12) - { - case 0: - m_pMessage = " )69TH STREET) STILL HOLDS TOP POSITION THIS MONTH AT THE BOX-OFFICE WITH )MY FAIR LADYBOY) JUST CREEPING UP BEHIND. "; - break; - case 1: - m_pMessage = " TALKING OF )FANNIE). THERE IS STILL TIME TO CATCH THIS LOVELY FAMILY MUSICAL, ABOUT THE ORPHAN WHO IS SO EASILY TAKEN IN BY ANY MAN WITH LOADS OF MONEY. "; - break; - case 2: - m_pMessage = " DO NOT MISS )GTA3, THE MUSICAL) . . . "; - break; - case 3: - m_pMessage = - " STILL RUNNING ARE )RATS) AND )GUYS AND DOGS), BETWEEN THEN THEY SHOULD HAVE THE LEGS TO LAST TILL THE AND OF THE YEAR. . . " - " ALSO FOR FOUR LEGGED FANS, THE STAGE VERSION OF THE GRITTY REALISTIC )SATERDAY NIGHT BEAVER) OPENED LAST WEEKEND," - " AND I FOR ONE CERTAINLY ENJOYED THAT. "; - break; - case 4: - m_pMessage = - " NOW SHOWING STATE-WIDE, ARNOLD STEELONE, HOLLYWOODS BEST LIVING SPECIAL EFFECT, APPEARS AGAIN AS A HALF_MAN," - " HALF ANDROID IN THE HALF-BAKED ROMP, )TOP DOWN CITY). AN HOMAGE TO HIS EARLIER TWO MULTI_MILLION MAKING MOVIES," - " IN WHICH HE PLAYED TWO-DEE, AN OUT OF CONTROL MONSTER, INTENT ON CORRUPTING CIVILISATION! "; - break; - case 5: - m_pMessage = - " ALSO APPEARING THIS WEEK )HALF-COCKED) SEES CHUCK SCHWARTZ UP TO HIS USUAL NONSENSE AS HE TAKES ON HALF OF LIBERTY CITY" - " IN AN ATTEMPT TO SAVE HIS CROSS-DRESSING LADY-BOY SIDEKICK, )MISS PING-PONG), FROM A GANG OF RUTHLESS COSMETIC SURGEONS. "; - break; - case 6: - m_pMessage = - " STILL SHOWING: )SOLDIERS OF MISFORTUNE), ATTROCIOUS ACTING WHICH SEES BOYZ 2 GIRLZ) TRANSITION FROM THE CHARTS TO THE BIG SCREEN," - " AT LEAST THEY ALL DIE AT THE END. . . "; - break; - case 7: - m_pMessage = - " )BADFELLAS) IS STILL GOING STRONG WITH CROWDS ALMOST BEING PUSHED INTO CINEMAS TO SEE THIS ONE." - " ANOTHER ONE WORTH LOOKING INTO IS )THE TUNNEL). "; - break; - case 8: - m_pMessage = FindTunnelMessage(); - break; - case 9: - m_pMessage = FindBridgeMessage(); - break; - case 10: - m_pMessage = FindTimeMessage(); - break; - case 11: - m_pMessage = "WWW.ROCKSTARGAMES.COM "; - break; - } - } - break; - case SCROLL_AIRPORT_DOORS: - while (previousMessage == m_pMessage) - { - switch (CGeneral::GetRandomNumber() % 4) - { - case 0: - m_pMessage = "WELCOME TO LIBERTY CITY . . . "; - break; - case 1: - m_pMessage = "PLEASE HAVE YOUR PASSPORT READY . . . "; - break; - case 2: - m_pMessage = "PLACE KEYS, FIREARMS, CHANGE AND OTHER METAL OBJECTS ON THE TRAY PLEASE . . . "; - break; - case 3: - m_pMessage = FindTimeMessage(); - break; - } - } - break; - case SCROLL_AIRPORT_FRONT: + if (m_Type == SCROLL_ARENA_STRING) { while (previousMessage == m_pMessage) { switch (CGeneral::GetRandomNumber() % 4) { case 0: - m_pMessage = "WELCOME TO FRANCIS INTERNATIONAL AIRPORT . . . "; + switch (TonightsEvent) { + case 0: + m_pMessage = "MAIN EVENT TONIGHT: CAR RACING . . . "; + break; + case 1: + m_pMessage = "MAIN EVENT TONIGHT: DESTRUCTION DERBY . . . "; + break; + case 2: + m_pMessage = "MAIN EVENT TONIGHT: BIKE RACING . . . "; + break; + } break; case 1: - m_pMessage = "PLEASE DO NOT LEAVE LUGGAGE UNATTENDED . . . "; + switch (TonightsEvent) { + case 0: + m_pMessage = "FOR TICKETS TO THE HOT RING EVENT CALL 555-3764 . . . "; + break; + case 1: + m_pMessage = "FOR TICKETS TO THE BLOOD RING EVENT CALL 555-3765 . . . "; + break; + case 2: + m_pMessage = "FOR TICKETS TO THE DIRT RING EVENT CALL 555-3766 . . . "; + break; + } break; case 2: - m_pMessage = "FOLLOW 1 FOR LONG AND SHORT TERM PARKING "; + m_pMessage = "HYMAN MEMORIAL STADIUM. HOME TO SOME OF THE BIGGEST EVENTS OF" + " THE WESTERN HEMISPHERE. ALSO AVAILABLE FOR CHILDREN PARTIES. . . "; break; case 3: m_pMessage = FindTimeMessage(); break; - } - } - break; - case SCROLL_STORE: - while (previousMessage == m_pMessage) - { - switch (CGeneral::GetRandomNumber() % 10) - { - case 0: - m_pMessage = "WWW.ROCKSTARGAMES.COM "; - break; - case 1: - m_pMessage = "GTA3 OUT NOW . . . "; - break; - case 2: - m_pMessage = "OUR STUFF IS CHEAP CHEAP CHEAP "; - break; - case 3: - m_pMessage = "BUY 12 CDS GET ONE FREE . . . "; - break; - case 4: - m_pMessage = "APPEARING IN SHOP SOON, )THE BLOODY CHOPPERS), WITH THEIR NEW ALBUM, )IS THAT MY DAUGHTER?) "; - break; - case 5: - m_pMessage = "THIS MONTH IS OUR CRAZY CLEAROUT MONTH, EVERYTHING MUST GO, CDS, DVDS, STAFF, EVEN OUR CARPETS! "; - break; - case 6: - m_pMessage = - "OUT THIS WEEK: THE THEME TUNE TO )BOYS TO GIRLS) FIRST MOVIE )SOLDIERS OF MISFORTUNE), " - "THE SINGLE )LET ME IN YOU)RE BODY-BAG) IS TAKEN FROM THE SOUNDTRACK ALBUM, )BOOT CAMP BOYS). " - "ALSO INCLUDES THE SMASH SINGLE, )PRAY IT GOES OK). "; - break; - case 7: - m_pMessage = - "ALBUMS OUT THIS WEEK: MARYDANCING, )MUTHA O) CHRIST), FEATURING THE SINGLE )WASH HIM OFF), " - "ALSO CRAIG GRAYS) DEBUT, )FADE AWAY), INCLUDES THE SINGLE OF THE SAME NAME. . . "; - break; - case 8: - m_pMessage = - "ON THE FILM FRONT, A NELY COMPILED COMPILATION OF ARNOLD STEELONES GREATEST MOVIES ON DVD. " - "THE PACK INCLUDES THE EARLY )BY-CEP), THE CULT CLASSIC )FUTURE ANNHILATOR), AND THE HILARIOUS CROSS-DRESSING COMEDY )SISTERS). " - "ONE FOR ALL THE FAMILY. . . "; - break; - case 9: - m_pMessage = FindTimeMessage(); + default: break; } } - break; - case SCROLL_USED_CARS: - while (previousMessage == m_pMessage) - { - switch (CGeneral::GetRandomNumber() % 11) - { - case 0: - m_pMessage = "QUICK, TAKE A LOOK AT OUR CURRENT STOCK )CAUSE THESE AUTOS ARE MOVIN) FAST . . . "; - break; - case 1: - m_pMessage = "THAT)S RIGHT, HERE AT )CAPITAL AUTO SALES) OUR VEHICLES ARE SO GOOD THAT THEY PRACTICALLY DRIVE THEMSELVES OFF OUR LOT . . . "; - break; - case 2: - m_pMessage = "EASY CREDIT ON ALL CARS . . . "; - break; - case 3: - m_pMessage = "FEEL LIKE A STUD IN ONE OF OUR STALLIONS OR TEST-DRIVE OUR BANSHEE, IT)S A REAL STEAL!!! "; - break; - case 4: - m_pMessage = "TRY OUR HARDY PERENNIAL, IT)LL LAST YOU THE WHOLE YEAR. OUR BOBCATS AIN)T NO PUSSIES EITHER!!! "; - break; - case 5: - m_pMessage = "IF IT)S A GUARANTEE YOU'RE AFTER, GO SOMEWHERE ELSE, )CAPITAL) CARS ARE THAT GOOD THEY DON)T NEED GUARANTEES!!! "; - break; - case 6: - m_pMessage = "TOP DOLLAR OFFERED FOR YOUR OLD WHEELS, NOT YOUR CAR, JUST IT)S WHEELS. . . "; - break; - case 7: - m_pMessage = "THAT)S RIGHT WE)RE CAR SILLY. TEST DRIVE ANY CAR, YOU WON)T WANT TO BRING IT BACK!!! "; - break; - case 8: - m_pMessage = "FREE FLUFFY DICE WITH ALL PURCHASES. . ."; - break; - case 9: - if (CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || CMenuManager::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 "; - break; - case 10: - m_pMessage = FindTimeMessage(); - break; - } - } - break; } m_MessageLength = (uint32)strlen(m_pMessage); @@ -699,172 +795,570 @@ void CScrollBar::Render() CSprite::FlushSpriteBuffer(); } -// ---------- CTowerClock ---------- -void CTowerClock::Init(CVector position, float sizeX, float sizeY, uint8 red, uint8 green, uint8 blue, float drawDistance, float scale) -{ - m_bVisible = false; - m_Position = position; - m_Size.x = sizeX; - m_Size.y = sizeY; - m_Size.z = 0.0f; - m_uRed = red; - m_uGreen = green; - m_uBlue = blue; - m_fDrawDistance = drawDistance; - m_fScale = scale; -} - -void CTowerClock::Update() -{ - float distanceFromCamera = (TheCamera.GetPosition() - m_Position).Magnitude(); - if (distanceFromCamera < m_fDrawDistance) - { - m_bVisible = true; - if (distanceFromCamera < 0.75f * m_fDrawDistance) - m_fIntensity = 1.0f; - else - m_fIntensity = 1.0f - (distanceFromCamera - 0.75f * m_fDrawDistance) * 4.0f / m_fDrawDistance; +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; } - else - m_bVisible = false; + 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; } -RwIm3DVertex TempV[4]; -void CTowerClock::Render() -{ - if (TheCamera.IsSphereVisible(m_Position, m_fScale)) - { - // Calculate angle for each clock index - float angleHour = 2.0f * (float)PI * (CClock::GetMinutes() + 60.0f * CClock::GetHours()) / 720.0f; - float angleMinute = 2.0f * (float)PI * (CClock::GetSeconds() + 60.0f * CClock::GetMinutes()) / 3600.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++; + } + } + } - // Prepare render states - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + if (numVerts > 1) { RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); - - // Set vertices colors - RwIm3DVertexSetRGBA(&TempV[0], m_uRed, m_uGreen, m_uBlue, (uint8)(m_fIntensity * 255.0f)); - RwIm3DVertexSetRGBA(&TempV[1], m_uRed, m_uGreen, m_uBlue, (uint8)(m_fIntensity * 255.0f)); - RwIm3DVertexSetRGBA(&TempV[2], m_uRed, m_uGreen, m_uBlue, (uint8)(m_fIntensity * 255.0f)); - RwIm3DVertexSetRGBA(&TempV[3], m_uRed, m_uGreen, m_uBlue, (uint8)(m_fIntensity * 255.0f)); - - // Set vertices position - RwIm3DVertexSetPos(&TempV[0], m_Position.x, m_Position.y, m_Position.z); - RwIm3DVertexSetPos( - &TempV[1], - m_Position.x + Sin(angleMinute) * m_fScale * m_Size.x, - m_Position.y + Sin(angleMinute) * m_fScale * m_Size.y, - m_Position.z + Cos(angleMinute) * m_fScale - ); - RwIm3DVertexSetPos(&TempV[2], m_Position.x, m_Position.y, m_Position.z); - RwIm3DVertexSetPos( - &TempV[3], - m_Position.x + Sin(angleHour) * 0.75f * m_fScale * m_Size.x, - m_Position.y + Sin(angleHour) * 0.75f * m_fScale * m_Size.y, - m_Position.z + Cos(angleHour) * 0.75f * m_fScale - ); - - LittleTest(); - - // Draw lines - if (RwIm3DTransform(TempV, 4, nil, 0)) - { - RwIm3DRenderLine(0, 1); - RwIm3DRenderLine(2, 3); + 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(); } } } -// ---------- CDigitalClock ---------- -void CDigitalClock::Init(CVector position, float sizeX, float sizeY, uint8 red, uint8 green, uint8 blue, float drawDistance, float scale) -{ - m_bVisible = false; - m_Position = position; - m_Size.x = sizeX; - m_Size.y = sizeY; - m_Size.z = 0.0f; - m_uRed = red; - m_uGreen = green; - m_uBlue = blue; - m_fDrawDistance = drawDistance; - m_fScale = scale; -} - -void CDigitalClock::Update() -{ - float distanceFromCamera = (TheCamera.GetPosition() - m_Position).Magnitude(); - if (distanceFromCamera < m_fDrawDistance) - { - m_bVisible = true; - if (distanceFromCamera < 0.75f * m_fDrawDistance) - m_fIntensity = 1.0f; - else - m_fIntensity = 1.0f - (distanceFromCamera - 0.75f * m_fDrawDistance) * 4.0f / m_fDrawDistance; +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(); } - else - m_bVisible = false; } -void CDigitalClock::Render() -{ - if (TheCamera.IsSphereVisible(m_Position, 5.0f * m_fScale)) - { - CSprite::InitSpriteBuffer(); +CEscalator CEscalators::aEscalators[NUM_ESCALATORS]; +int32 CEscalators::NumEscalators; - // Simulate flicker - float currentIntensity = m_fIntensity * CGeneral::GetRandomNumberInRange(0x300, 0x400) / 1024.0f; +CEscalator::CEscalator() { + m_bIsActive = false; - uint8 r = currentIntensity * m_uRed; - uint8 g = currentIntensity * m_uGreen; - uint8 b = currentIntensity * m_uBlue; + for (int i = 0; i < 24; i++) { + m_pSteps[i] = nil; + } +} - // Set render states - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0])); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); +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; - const char* clockMessage = FindDigitalClockMessage(); + 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; - CVector coronaCoord, screenCoord; - float screenW, screenH; - for (int c = 0; c < 5; ++c) // for each char to be displayed - { - for (int i = 0; i < 5; ++i) // for each column of coronas - { - for (int j = 0; j < 5; ++j) // for each row of coronas - { - if (ScrollCharSet[clockMessage[c] - ' '][i] & (1 << j)) - { - coronaCoord.x = m_Position.x + (8 * c + i) * m_Size.x * m_fScale / 8.0f; - coronaCoord.y = m_Position.y + (8 * c + i) * m_Size.y * m_fScale / 8.0f; - coronaCoord.z = m_Position.z + j * m_fScale / 8.0f; - - if (CSprite::CalcScreenCoors(coronaCoord, &screenCoord, &screenW, &screenH, true)) - { - CSprite::RenderBufferedOneXLUSprite( - screenCoord.x, screenCoord.y, screenCoord.z, - screenW * m_fScale * 0.12f, - screenW * m_fScale * 0.12f, - r, g, b, - 255, - 1.0f / screenCoord.z, - 255); - } + 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 = Min(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; - CSprite::FlushSpriteBuffer(); + 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++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&aArray[i].m_numNodes, buf); + SkipSaveBuf(buf, 4); + ReadSaveBuf(&aArray[i].m_fTotalLength, buf); + ReadSaveBuf(&aArray[i].m_fSpeed, buf); + ReadSaveBuf(&aArray[i].m_fPosition, buf); + ReadSaveBuf(&aArray[i].m_fObjectLength, buf); + ReadSaveBuf(&aArray[i].m_state, buf); +#else + ReadSaveBuf(&aArray[i], buf); +#endif + + for (int32 j = 0; j < 6; j++) { +#ifdef COMPATIBLE_SAVES + aArray[i].m_pObjects[j] = nil; + int32 tmp; + ReadSaveBuf(&tmp, buf); + if (tmp != 0) { + aArray[i].m_pObjects[j] = CPools::GetObjectPool()->GetSlot(tmp - 1); + aArray[i].m_pObjects[j]->m_phy_flagA08 = false; + } +#else + 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; + } +#endif + } + + aArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes]; + for (int32 j = 0; j < aArray[i].m_numNodes; j++) { + ReadSaveBuf(&aArray[i].m_pNode[j], buf); + } + } +VALIDATESAVEBUF(size) +} + +void CScriptPaths::Save(uint8 *buf, uint32 *size) { + *size = SCRIPTPATHS_SAVE_SIZE; +INITSAVEBUF + for (int32 i = 0; i < 3; i++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aArray[i].m_numNodes); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, aArray[i].m_fTotalLength); + WriteSaveBuf(buf, aArray[i].m_fSpeed); + WriteSaveBuf(buf, aArray[i].m_fPosition); + WriteSaveBuf(buf, aArray[i].m_fObjectLength); + WriteSaveBuf(buf, aArray[i].m_state); +#else + CScriptPath *pPath = WriteSaveBuf(buf, aArray[i]); +#endif + + for (int32 j = 0; j < 6; j++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aArray[i].m_pObjects[j] != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aArray[i].m_pObjects[j]) + 1 : 0); +#else + if (pPath->m_pObjects[j] != nil) + pPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pPath->m_pObjects[j]) + 1); +#endif + } + + 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/renderer/Fluff.h b/src/renderer/Fluff.h index fe3ab256..58c8410c 100644 --- a/src/renderer/Fluff.h +++ b/src/renderer/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 { @@ -8,7 +125,7 @@ public: CMovingThing *m_pNext; CMovingThing *m_pPrev; int16 m_nType; - int16 m_nHidden; + int16 m_farAway; CVector m_vecPosn; CEntity* m_pEntity; @@ -18,7 +135,7 @@ public: int16 SizeList(); }; -#define NUMMOVINGTHINGS 128 +#define NUMMOVINGTHINGS 48 class CMovingThings { @@ -32,6 +149,8 @@ public: static void Shutdown(); static void Update(); static void Render(); + static void PossiblyAddThisEntity(CEntity *pEnt); + static void RegisterOne(CEntity *pEnt, uint16 nType); }; class CScrollBar @@ -53,54 +172,34 @@ private: float m_fScale; public: - void SetVisibility(bool visible) { m_bVisible = visible; } - bool IsVisible() { return m_bVisible; } - - void Init(CVector, uint8, float, float, float, uint8, uint8, uint8, float); - void Update(); - void Render(); -}; - -class CTowerClock -{ -private: - CVector m_Position; - CVector m_Size; - float m_fDrawDistance; - float m_fScale; - uint8 m_uRed; - uint8 m_uGreen; - uint8 m_uBlue; - bool m_bVisible; - float m_fIntensity; + static int TonightsEvent; public: void SetVisibility(bool visible) { m_bVisible = visible; } bool IsVisible() { return m_bVisible; } - void Init(CVector, float, float, uint8, uint8, uint8, float, float); + void Init(CVector pos1, CVector pos2, uint8 type, uint8 red, uint8 green, uint8 blue, float scale); void Update(); void Render(); }; -class CDigitalClock -{ -private: - CVector m_Position; - CVector m_Size; - float m_fDrawDistance; - float m_fScale; - uint8 m_uRed; - uint8 m_uGreen; - uint8 m_uBlue; - bool m_bVisible; - float m_fIntensity; - +class CSmokeTrail { + CVector m_pos[16]; + float m_opacity[16]; + int m_time[16]; + char m_unused[536]; + int m_seed; public: - void SetVisibility(bool visible) { m_bVisible = visible; } - bool IsVisible() { return m_bVisible; } + void Render(void); + void RegisterPoint(CVector position, float a); + void Init(int num); +}; - void Init(CVector, float, float, uint8, uint8, uint8, float, float); - void Update(); - void Render(); +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/renderer/Font.cpp b/src/renderer/Font.cpp index 6a9944e1..6ae10011 100644 --- a/src/renderer/Font.cpp +++ b/src/renderer/Font.cpp @@ -6,6 +6,7 @@ #ifdef BUTTON_ICONS #include "FileMgr.h" #endif +#include "Timer.h" void AsciiToUnicode(const char *src, wchar *dst) @@ -33,216 +34,216 @@ 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; bool16 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 - -#if !defined(GTA_PS2) || defined(FIX_BUGS) - { - 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 - } -#else // #if defined(GTA_PS2) && !defined(FIX_BUGS) - { - 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, - 24, 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, + { + //FONT2 EFIGS + //SPC,!, $, %, &, ', [, ], +, , -, ., + 12, 9, 22, 17, 19, 19, 25, 4, 33, 33, 25, 35, 11, 10, 6, 33, + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ??, + 18, 10, 17, 17, 17, 17, 17, 15, 12, 16, 5, 30, 30, 30, 30, 30, + // A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, + 12, 16, 19, 16, 19, 18, 18, 17, 22, 11, 17, 18, 18, 30, 22, 19, + //P, Q, R, S, T, U, V, W, X, Y, Z, ??, ??, ??, ¡, \, + #ifdef FIX_BUGS + 22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 10, 19, + #else + 22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 19, 19, + #endif + //??,a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + 12, 14, 11, 11, 16, 11, 12, 14, 14, 10, 13, 12, 10, 19, 18, 12, + //p, q, r, s, t, u, v, w, x, y, z, ??, ??, ??, ??, ??, + 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, + //ë, ì, í, î, ï, ò, ó, ô, ö, ù, ú, û, ü, Ñ, ñ, ¿, + #ifdef FIX_BUGS + 11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15, 15, 22, 18, 21, + #else + 11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15, 15, 24, 18, 21, + #endif + //i,BLANKS + 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, - 16 - }, - - { - 15, 14, 16, 25, 19, 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27, - 19, 18, 19, 19, 21, 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, 19, - 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, 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, - 19 - } -#endif - -#ifdef MORE_LANGUAGES + //space, unprop + 19, 16 }, { - { 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, 13, - 33, 13, 13, 13, 24, 22, 22, 19, 26, 21, 30, 20, 23, - 23, 21, 24, 26, 23, 22, 23, 21, 22, 20, 20, 26, 25, - 24, 22, 31, 32, 23, 30, 22, 22, 32, 23, 19, 18, 18, - 15, 22, 19, 27, 19, 20, 20, 18, 22, 24, 20, 19, 19, - 20, 19, 16, 19, 28, 20, 20, 18, 26, 27, 19, 26, 18, - 19, 27, 19, 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, - 21, 21, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35, - 35, 35, 35, 37, 19, 19, 19, 19, 19, 19, 29, 19, 19, - 19, 20, 22, 31, 19, 19, 19, 19, 19, 29, 19, 29, 19, - 21, 19, 30, 31, 21, 29, 19, 19, 29, 19, 21, 23, 32, - 21, 21, 30, 31, 22, 21, 32, 33, 23, 32, 21, 21, 32, - 21, 19, 19, 30, 31, 22, 22, 21, 32, 33, 23, 32, 21, - 21, 32, 21, 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 }, - }, + //FONT1 EFIGS + //Characters with a '2' refer to the Pricedown font. + //Characters that are referred as '*I' are characters that contain icons for PS2/XBOX, but contain regular characters on PC + //in order to display them properly in the Keyboard controls menu. + //!2,!, *I,(R), $, %, &, ', [, ], *I, +, , -, ., *I, + 15, 7, 31, 25, 20, 23, 21, 7, 11, 10, 26, 14, 6, 12, 6, 26, + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, *I, *I, *I, *I, ?, + 20, 7, 20, 20, 21, 20, 20, 19, 21, 20, 8, 30, 24, 30, 24, 19, + //TM,A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, + 20, 22, 22, 21, 22, 18, 18, 22, 22, 9, 14, 21, 18, 27, 21, 24, + //P, Q, R, S, T, U, V, W, X, Y, Z, *I, \, *I, ¡, °, + #ifdef FIX_BUGS + 22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30, 7, 19, + #else + 22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30, 10, 19, + #endif + //(C),a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + 10, 17, 17, 16, 17, 17, 11, 17, 17, 7, 7, 18, 7, 25, 17, 17, + //p, q, r, s, t, u, v, w, x, y, z, *I, *I, $2, (2, )2, + 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, + //ë, ì, í, î, ï, ò, ó, ô, ö, ù, ú, û, ü, Ñ, ñ, ¿, + #ifdef FIX_BUGS + 17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 21, 17, 19, + #else + 17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 19, 20, 20, + #endif + //02,12,22, 32, 42, 52, 62, 72, 82, 92, :2, A2, B2, C2, D2, E2, + 20, 18, 19, 19, 21, 19, 19, 19, 19, 19, 16, 19, 19, 19, 20, 19, + //F2,G2,H2, I2, J2, K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, + 16, 19, 19, 9, 19, 20, 14, 29, 19, 19, 19, 19, 19, 19, 21, 19, + //V2,W2,X2, Y2, Z2, À2, Á2, Â2, Ä2, Æ2, Ç2, È2, É2, Ê2, Ë2, Ì2, + 20, 32, 20, 19, 19, 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, + //Í2,Î2,Ï2, Ò2, Ó2, Ô2, Ö2, Ù2, Ú2, Û2, Ü2, ß2, Ñ2, ¿2, '2, .2, + #ifdef FIX_BUGS + 9, 9, 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 10, 9, + #else + 9, 9, 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, 10, 9, + #endif + //space, unprop + 10, 20 + } +#ifdef MORE_LANGUAGES + }, { - { - 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 + { + 5, 9, 9, 0, 17, 17, 23, 3, 21, 18, 0, 8, 3, 8, 3, 0, + 16, 9, 16, 16, 15, 19, 15, 14, 17, 17, 4, 4, 0, 0, 0, 17, + 19, 17, 19, 15, 21, 18, 19, 16, 21, 13, 15, 21, 20, 28, 21, 18, + 22, 17, 21, 20, 18, 18, 20, 26, 22, 18, 18, 0, 8, 0, 9, 8, + 0, 14, 11, 12, 16, 11, 13, 13, 15, 10, 14, 15, 11, 21, 17, 10, + 20, 15, 12, 12, 16, 17, 13, 16, 13, 21, 11, 0, 0, 0, 0, 0, + 20, 19, 19, 22, 27, 15, 18, 18, 20, 26, 21, 23, 17, 22, 21, 17, + 26, 25, 26, 17, 20, 26, 17, 16, 11, 12, 13, 21, 11, 17, 17, 12, + 21, 17, 17, 15, 24, 16, 10, 20, 23, 16, 7, 9, 16, 23, 12, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 19, 16 }, - + { + 11, 5, 10, 15, 19, 22, 20, 5, 9, 8, 11, 12, 5, 12, 6, 12, + 19, 5, 18, 19, 20, 18, 19, 18, 20, 19, 5, 6, 26, 12, 30, 19, + 23, 21, 20, 20, 20, 16, 16, 21, 19, 5, 13, 19, 16, 24, 20, 21, + 20, 21, 20, 19, 17, 20, 21, 30, 22, 21, 20, 25, 13, 30, 5, 9, + 10, 15, 15, 14, 15, 16, 10, 15, 15, 5, 5, 15, 5, 23, 15, 16, + 15, 15, 9, 16, 10, 15, 17, 24, 18, 15, 15, 27, 5, 19, 2, 2, + 20, 20, 16, 23, 30, 19, 20, 20, 21, 24, 19, 19, 20, 23, 22, 19, + 27, 29, 25, 20, 20, 28, 24, 16, 16, 14, 19, 25, 16, 16, 16, 17, + 19, 16, 16, 17, 25, 19, 15, 23, 26, 21, 16, 14, 22, 20, 16, 19, + 15, 14, 15, 16, 17, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15, + 13, 15, 15, 7, 15, 16, 13, 23, 15, 15, 15, 15, 15, 15, 17, 15, + 16, 24, 17, 17, 17, 15, 15, 13, 20, 23, 15, 17, 17, 16, 24, 15, + 15, 15, 23, 18, 15, 23, 26, 23, 16, 15, 23, 15, 15, 19, 2, 2, + 10, 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, + //FONT2 EFIGS + //SPC,!, $, %, &, ', [, ], +, , -, ., + 12, 9, 22, 17, 19, 19, 25, 4, 33, 33, 25, 35, 11, 10, 6, 33, + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ??, + 18, 10, 17, 17, 17, 17, 17, 15, 12, 16, 5, 30, 30, 30, 30, 30, + // A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, + 12, 16, 19, 16, 19, 18, 18, 17, 22, 11, 17, 18, 18, 30, 22, 19, + //P, Q, R, S, T, U, V, W, X, Y, Z, ??, ??, ??, ¡, \, + 22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 10, 19, + //??,a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + 12, 14, 11, 11, 16, 11, 12, 14, 14, 10, 13, 12, 10, 19, 18, 12, + //p, q, r, s, t, u, v, w, x, y, z, ??, ??, ??, ??, ??, + 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, 22, 18, 21, + //i,BLANKS + 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, 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 + //space, unprop + 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 + //FONT1 EFIGS + //Characters with a '2' refer to the Pricedown font. + //Characters that are referred as '*I' are characters that contain icons for PS2/XBOX, but contain regular characters on PC + //in order to display them properly in the Keyboard controls menu. + //!2,!, *I,(R), $, %, &, ', [, ], *I, +, , -, ., *I, + 15, 7, 31, 25, 20, 23, 21, 7, 11, 10, 26, 14, 6, 12, 6, 26, + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, *I, *I, *I, *I, ?, + 20, 7, 20, 20, 21, 20, 20, 19, 21, 20, 8, 30, 24, 30, 24, 19, + //TM,A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, + 20, 22, 22, 21, 22, 18, 18, 22, 22, 9, 14, 21, 18, 27, 21, 24, + //P, Q, R, S, T, U, V, W, X, Y, Z, *I, \, *I, ¡, °, + 22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30, 7, 19, + //(C),a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + 10, 17, 17, 16, 17, 17, 11, 17, 17, 7, 7, 18, 7, 25, 17, 17, + //p, q, r, s, t, u, v, w, x, y, z, *I, *I, $2, (2, )2, + 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, 21, 17, 19, + //02,12,22, 32, 42, 52, 62, 72, 82, 92, :2, A2, B2, C2, D2, E2, + 20, 18, 19, 19, 21, 19, 19, 19, 19, 19, 16, 19, 19, 19, 20, 19, + //F2,G2,H2, I2, J2, K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2, + 16, 19, 19, 9, 19, 20, 14, 29, 19, 19, 19, 19, 19, 19, 21, 19, + //V2,W2,X2, Y2, Z2, À2, Á2, Â2, Ä2, Æ2, Ç2, È2, É2, Ê2, Ë2, Ì2, + 20, 32, 20, 19, 19, 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, + //Í2,Î2,Ï2, Ò2, Ó2, Ô2, Ö2, Ù2, Ú2, Û2, Ü2, ß2, Ñ2, ¿2, '2, .2, + 9, 9, 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 10, 9, + //space, unprop + 10, 20 } } #endif @@ -279,6 +280,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]; + #ifdef BUTTON_ICONS CSprite2d CFont::ButtonSprite[MAX_BUTTON_ICONS]; int CFont::PS2Symbol = BUTTON_NONE; @@ -315,29 +331,22 @@ 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); SetColor(CRGBA(255, 255, 255, 0)); SetJustifyOff(); SetCentreOff(); -#ifdef FIX_BUGS - SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); - SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); -#else - SetWrapx(DEFAULT_SCREEN_WIDTH); - SetCentreSize(DEFAULT_SCREEN_WIDTH); -#endif + SetWrapx(SCREEN_WIDTH); + SetCentreSize(SCREEN_WIDTH); SetBackgroundOff(); SetBackgroundColor(CRGBA(128, 128, 128, 128)); SetBackGroundOnlyTextOff(); @@ -356,7 +365,7 @@ CFont::Initialise(void) #ifdef BUTTON_ICONS void -CFont::LoadButtons(const char* txdPath) +CFont::LoadButtons(const char *txdPath) { if (int file = CFileMgr::OpenFile(txdPath)) { CFileMgr::CloseFile(file); @@ -371,12 +380,10 @@ CFont::LoadButtons(const char* txdPath) CTxdStore::AddRef(ButtonsSlot); CTxdStore::PushCurrentTxd(); CTxdStore::SetCurrentTxd(ButtonsSlot); -#if 0 // unused - ButtonSprite[BUTTON_UP].SetTexture("up"); - ButtonSprite[BUTTON_DOWN].SetTexture("down"); - ButtonSprite[BUTTON_LEFT].SetTexture("left"); - ButtonSprite[BUTTON_RIGHT].SetTexture("right"); -#endif + ButtonSprite[BUTTON_UP].SetTexture("thumblyu"); + ButtonSprite[BUTTON_DOWN].SetTexture("thumblyd"); + ButtonSprite[BUTTON_LEFT].SetTexture("thumblxl"); + ButtonSprite[BUTTON_RIGHT].SetTexture("thumblxr"); ButtonSprite[BUTTON_CROSS].SetTexture("cross"); ButtonSprite[BUTTON_CIRCLE].SetTexture("circle"); ButtonSprite[BUTTON_SQUARE].SetTexture("square"); @@ -387,6 +394,10 @@ CFont::LoadButtons(const char* txdPath) ButtonSprite[BUTTON_R1].SetTexture("r1"); ButtonSprite[BUTTON_R2].SetTexture("r2"); ButtonSprite[BUTTON_R3].SetTexture("r3"); + ButtonSprite[BUTTON_RSTICK_UP].SetTexture("thumbryu"); + ButtonSprite[BUTTON_RSTICK_DOWN].SetTexture("thumbryd"); + ButtonSprite[BUTTON_RSTICK_LEFT].SetTexture("thumbrxl"); + ButtonSprite[BUTTON_RSTICK_RIGHT].SetTexture("thumbrxr"); CTxdStore::PopCurrentTxd(); } else { @@ -407,9 +418,8 @@ CFont::ReloadFonts(uint8 set) if (Slot != -1 && LanguageSet != set) { Sprite[0].Delete(); Sprite[1].Delete(); - Sprite[2].Delete(); if (IsJapanese()) - Sprite[3].Delete(); + Sprite[2].Delete(); CTxdStore::PushCurrentTxd(); CTxdStore::RemoveTxd(Slot); switch (set) @@ -431,12 +441,9 @@ CFont::ReloadFonts(uint8 set) CTxdStore::SetCurrentTxd(Slot); Sprite[0].SetTexture("font2", "font2_mask"); if (set == FONT_LANGSET_JAPANESE) { - Sprite[1].SetTexture("FONTJAP", "FONTJAP_mask"); - Sprite[3].SetTexture("FONTJAP", "FONTJAP_mask"); + Sprite[2].SetTexture("FONTJAP", "FONTJAP_mask"); } - else - Sprite[1].SetTexture("pager", "pager_mask"); - Sprite[2].SetTexture("font1", "font1_mask"); + Sprite[1].SetTexture("font1", "font1_mask"); CTxdStore::PopCurrentTxd(); } LanguageSet = set; @@ -456,7 +463,6 @@ CFont::Shutdown(void) #endif Sprite[0].Delete(); Sprite[1].Delete(); - Sprite[2].Delete(); #ifdef MORE_LANGUAGES if (IsJapanese()) Sprite[3].Delete(); @@ -470,13 +476,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 = false; #ifdef BUTTON_ICONS @@ -494,14 +496,20 @@ CFont::DrawButton(float x, float y) if (PS2Symbol != BUTTON_NONE) { CRect rect; rect.left = x; - rect.top = Details.scaleY + Details.scaleY + y; - rect.right = Details.scaleY * 17.0f + x; - rect.bottom = Details.scaleY * 19.0f + y; + rect.top = RenderState.scaleY + RenderState.scaleY + y; + rect.right = RenderState.scaleY * 17.0f + x; + rect.bottom = RenderState.scaleY * 19.0f + y; int vertexAlphaState; + void *raster; RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState); + RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &raster); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); - ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, Details.color.a)); + if (RenderState.bIsShadow) + ButtonSprite[PS2Symbol].Draw(rect, RenderState.color); + else + ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, RenderState.color.a)); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState); } } @@ -510,15 +518,15 @@ CFont::DrawButton(float x, float y) void CFont::PrintChar(float x, float y, wchar c) { + bool bDontPrint = false; if(x <= 0.0f || x > SCREEN_WIDTH || -#ifdef FIX_BUGS - y <= 0.0f || y > SCREEN_HEIGHT) -#else - y <= 0.0f || y > SCREEN_WIDTH) -#endif + 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 @@ -529,65 +537,52 @@ CFont::PrintChar(float x, float y, wchar c) } #endif - if(Details.style == FONT_BANK || Details.style == FONT_HEADING){ - if(Details.dropShadowPosition != 0){ - CSprite2d::AddSpriteToBank( -#ifdef FIX_BUGS - Details.bank + Details.style, -#else - Details.style, // BUG: game doesn't add bank -#endif -#ifdef FIX_BUGS - 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), -#else - CRect(x + Details.dropShadowPosition, - y + Details.dropShadowPosition, - x + Details.dropShadowPosition + 32.0f * Details.scaleX * 1.0f, - y + Details.dropShadowPosition + 40.0f * Details.scaleY * 0.5f), -#endif - 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( + if(RenderState.style == FONT_BANK || RenderState.style == FONT_STANDARD){ + if (bDontPrint) return; + if (RenderState.slant == 0.0f) { #ifdef FIX_BUGS - Details.bank + Details.style, + if (c < 192) { #else - Details.style, // BUG: game doesn't add bank -#endif - 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 (c < 193) { +#endif + 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 + 0.0021f, + (xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f, + xoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.017f, + (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()) { + /*}else if (IsJapaneseFont()) { if (Details.dropShadowPosition != 0) { - CSprite2d::AddSpriteToBank( -#ifdef FIX_BUGS - Details.bank + Details.style, -#else - Details.style, // BUG: game doesn't add bank -#endif -#ifdef FIX_BUGS + 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 / 2.75f), -#else - CRect(x + Details.dropShadowPosition, - y + Details.dropShadowPosition, - x + Details.dropShadowPosition + 32.0f * Details.scaleX * 1.0f, - y + Details.dropShadowPosition + 40.0f * Details.scaleY / 2.75f), -#endif Details.dropColor, xoff * w / 1024.0f, yoff / 25.6f, xoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, yoff / 25.6f, @@ -602,24 +597,19 @@ CFont::PrintChar(float x, float y, wchar c) xoff * w / 1024.0f, yoff / 25.6f, xoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, yoff / 25.6f, 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( -#ifdef FIX_BUGS - Details.bank + Details.style, -#else - Details.style, // BUG: game doesn't add bank + xoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, (yoff + 1.0f) / 25.6f - 0.0001f);*/ #endif + } 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); } } @@ -646,6 +636,210 @@ bool CFont::IsAnsiCharacter(wchar *s) #endif 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; + color = RenderState.color; + 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 == '~') { +#ifdef BUTTON_ICONS + PS2Symbol = BUTTON_NONE; +#endif + pRenderStateBufPointer.pStr = ParseToken(pRenderStateBufPointer.pStr, color, bFlash, bBold); +#ifdef BUTTON_ICONS + if(PS2Symbol != BUTTON_NONE) { + DrawButton(textPosX, textPosY); + textPosX += RenderState.scaleY * 17.0f; + PS2Symbol = BUTTON_NONE; + } +#endif + 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; + } +#ifdef FIX_BUGS + // PS2 uses different chars for some symbols + if (!RenderState.bFontHalfTexture && c == 30) c = 61; // wanted star +#endif + textPosX += RenderState.scaleX * GetCharacterWidth(c); + if (c == '\0') + textPosX += RenderState.fExtraSpace; + } + CSprite2d::RenderVertexBuffer(); + FontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf; +} + +#if 0 //def MORE_LANGUAGES +bool +CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, float japX) +{ + wchar *s, c, unused; + + if (IsJapanese()) { + float jx = 0.0f; + for (s = start; s < end; s++) { + if (*s == JAP_TERMINATION || *s == '~') + s = ParseToken(s, &unused, true); + if (NewLine) { + NewLine = false; + break; + } + jx += GetCharacterSize(*s - ' '); + } + s = start; + if (Details.centre) + x = japX - jx / 2.0f; + else if (Details.rightJustify) + x = japX - jx; + } + + for (s = start; s < end; s++) { + if (*s == '~' || (IsJapanese() && *s == JAP_TERMINATION)) + s = ParseToken(s, &unused); + if (NewLine && IsJapanese()) { + NewLine = false; + end = s; + return true; + } + c = *s - ' '; + if (Details.slant != 0.0f && !IsJapanese()) + y = (Details.slantRefX - x) * Details.slant + Details.slantRefY; + + PrintChar(x, y, c); + x += GetCharacterSize(c); + if (c == 0 && (!NewLine || !IsJapanese())) // space + x += spwidth; + } + return false; +} +#else +void +CFont::PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth) +{ + wchar *s; + + 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); +} + +void CFont::PrintString(float xstart, float ystart, wchar *s) { CRect rect; @@ -655,10 +849,14 @@ CFont::PrintString(float xstart, float ystart, wchar *s) bool first; wchar *start, *t; + Details.bFlash = false; + if(*s == '*') return; + Details.anonymous_25++; if(Details.background){ + RenderState.color = Details.color; GetNumberLines(xstart, ystart, s); // BUG: result not used GetTextRect(&rect, xstart, ystart, s); CSprite2d::DrawRect(rect, Details.backgroundColor); @@ -698,10 +896,10 @@ CFont::PrintString(float xstart, float ystart, wchar *s) float xleft = Details.centre ? xstart - x/2 : Details.rightJustify ? xstart - x : xstart; -#ifdef MORE_LANGUAGES +#if 0//def 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; @@ -713,10 +911,10 @@ CFont::PrintString(float xstart, float ystart, wchar *s) x = xstart; #ifdef MORE_LANGUAGES if (IsJapaneseFont()) - y += 32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY; else #endif - y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY; start = s; }else break; @@ -736,7 +934,7 @@ CFont::PrintString(float xstart, float ystart, wchar *s) #endif lineLength = x; s = t+1; -#ifdef MORE_LANGUAGES +#if 0 //def MORE_LANGUAGES if (IsJapaneseFont() && !*s) { x += GetStringWidth(s); if (IsAnsiCharacter(s)) @@ -752,7 +950,7 @@ CFont::PrintString(float xstart, float ystart, wchar *s) else x = 0.0f; - y += 32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY; numSpaces = 0; first = true; lineLength = 0.0f; @@ -768,20 +966,20 @@ CFont::PrintString(float xstart, float ystart, wchar *s) float xleft = Details.centre ? xstart - x/2 : Details.rightJustify ? xstart - x : xstart; -#ifdef MORE_LANGUAGES +#if 0 //def MORE_LANGUAGES if (PrintString(xleft, y, start, s, 0.0f, xstart) && IsJapaneseFont()) { start = s; if (!Details.centre && !Details.rightJustify) x = xstart; else x = 0.0f; - y += 32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY; numSpaces = 0; first = true; lineLength = 0.0f; } #else - PrintString(xleft, y, start, s, 0.0f); + PrintString(xleft, y, Details.anonymous_25, start, s, 0.0f); #endif } } @@ -794,7 +992,7 @@ CFont::GetNumberLines(float xstart, float ystart, wchar *s) wchar *t; n = 0; -#ifdef MORE_LANGUAGES +#if 0//def MORE_LANGUAGES bool bSomeJapBool = false; if (IsJapanese()) { @@ -852,10 +1050,10 @@ CFont::GetNumberLines(float xstart, float ystart, wchar *s) // Why even? #ifdef MORE_LANGUAGES if (IsJapanese()) - y += 32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY; else #endif - y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY; }else{ // still space in current line t = GetNextSpace(s); @@ -903,12 +1101,7 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s) numLines = GetNumberLines(xstart, ystart, s); }else{ #endif - -#ifdef FIX_BUGS if(Details.centre || Details.rightJustify) -#else - if(Details.centre) -#endif x = 0.0f; else x = xstart; @@ -926,16 +1119,12 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s) // reached end of line if(x > maxlength) maxlength = x; -#ifdef FIX_BUGS if(Details.centre || Details.rightJustify) -#else - if(Details.centre) -#endif x = 0.0f; else x = xstart; numLines++; - y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY; + y += 32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY; }else{ // still space in current line t = GetNextSpace(s); @@ -963,11 +1152,11 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s) rect->right = xstart + maxlength/2 + 4.0f; #ifdef MORE_LANGUAGES if (IsJapaneseFont()) { - rect->bottom = (32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY) * numLines + ystart + (4.0f / 2.75f); + rect->bottom = (32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY) * numLines + ystart + (4.0f / 2.75f); rect->top = ystart - (4.0f / 2.75f); } else { #endif - rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f; + rect->bottom = (32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f; rect->top = ystart - 2.0f; #ifdef MORE_LANGUAGES } @@ -977,11 +1166,11 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s) rect->right = xstart + Details.centreSize*0.5f + 4.0f; #ifdef MORE_LANGUAGES if (IsJapaneseFont()) { - rect->bottom = (32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY) * numLines + ystart + (4.0f / 2.75f); + rect->bottom = (32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY) * numLines + ystart + (4.0f / 2.75f); rect->top = ystart - (4.0f / 2.75f); } else { #endif - rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f; + rect->bottom = (32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f; rect->top = ystart - 2.0f; #ifdef MORE_LANGUAGES } @@ -994,159 +1183,51 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s) rect->bottom = ystart - 4.0f + 4.0f; #ifdef MORE_LANGUAGES if (IsJapaneseFont()) - rect->top = (32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f + (4.0f / 2.75f); + rect->top = (32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f + (4.0f / 2.75f); else #endif - rect->top = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines + ystart + 2.0f + 2.0f; + rect->top = (32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f + 2.0f; } } -#ifdef MORE_LANGUAGES -bool -CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, float japX) -{ - wchar *s, c, unused; - - if (IsJapanese()) { - float jx = 0.0f; - for (s = start; s < end; s++) { - if (*s == JAP_TERMINATION || *s == '~') - s = ParseToken(s, &unused, true); - if (NewLine) { - NewLine = false; - break; - } - jx += GetCharacterSize(*s - ' '); - } - s = start; - if (Details.centre) - x = japX - jx / 2.0f; - else if (Details.rightJustify) - x = japX - jx; - } - - for (s = start; s < end; s++) { - if (*s == '~' || (IsJapanese() && *s == JAP_TERMINATION)) - s = ParseToken(s, &unused); - if (NewLine && IsJapanese()) { - NewLine = false; - end = s; - return true; - } - c = *s - ' '; - if (Details.slant != 0.0f && !IsJapanese()) - y = (Details.slantRefX - x) * Details.slant + Details.slantRefY; - -#ifdef BUTTON_ICONS - if (PS2Symbol != BUTTON_NONE) { - DrawButton(x, y); - x += Details.scaleY * 17.0f; - PS2Symbol = BUTTON_NONE; - } -#endif - - PrintChar(x, y, c); - x += GetCharacterSize(c); - if (c == 0 && (!NewLine || !IsJapanese())) // space - x += spwidth; - } - return false; -} -#else -void -CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth) -{ - wchar *s, c, unused; - - 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; - } -} -#endif - -void -CFont::PrintStringFromBottom(float x, float y, wchar *str) -{ -#ifdef MORE_LANGUAGES - if (IsJapaneseFont()) - y -= (32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY) * GetNumberLines(x, y, str); - else -#endif - y -= (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * GetNumberLines(x, y, str); - PrintString(x, y, str); -} - -#ifdef XBOX_SUBTITLES -void -CFont::PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor) -{ - CRGBA textColor = Details.color; - SetColor(outlineColor); - CVector2D offsets[] = { {1.f, 1.f}, {1.f, -1.f}, {-1.f, 1.f}, {-1.f, -1.f} }; - for(int i = 0; i < ARRAY_SIZE(offsets); i++){ - if (fromBottom) - PrintStringFromBottom(x + SCREEN_SCALE_X(offsets[i].x * outlineStrength), y + SCREEN_SCALE_Y(offsets[i].y * outlineStrength), str); - else - PrintString(x + SCREEN_SCALE_X(offsets[i].x * outlineStrength), y + SCREEN_SCALE_Y(offsets[i].y * outlineStrength), str); - } - SetColor(textColor); - - if (fromBottom) - PrintStringFromBottom(x, y, str); - else - PrintString(x, y, str); -} -#endif - float CFont::GetCharacterWidth(wchar c) { #ifdef MORE_LANGUAGES if (IsJapanese()) { - if (!Details.proportional) + if (!RenderState.proportional) return Size[0][Details.style][192]; - if (c <= 94 || Details.style == FONT_HEADING || Details.style == FONT_BANK) { - switch (Details.style) + if (c <= 94 || Details.style == FONT_HEADING || RenderState.style == FONT_BANK) { + switch (RenderState.style) { case FONT_JAPANESE: return Size_jp[c]; default: - return Size[0][Details.style][c]; + return Size[0][RenderState.style][c]; } } - if (c < 254 && Details.style == FONT_PAGER) - return 29.4f; - switch (Details.style) + switch (RenderState.style) { case FONT_JAPANESE: return 29.4f; case FONT_BANK: return 10.0f; - case FONT_PAGER: - return 31.5f; default: - return Size[0][Details.style][c]; + return Size[0][RenderState.style][c]; } } - else if (Details.proportional) - return Size[LanguageSet][Details.style][c]; + else if (RenderState.proportional) + return Size[LanguageSet][RenderState.style][c]; else - return Size[LanguageSet][Details.style][192]; + return Size[LanguageSet][RenderState.style][209]; #else - if (Details.proportional) - return Size[Details.style][c]; + + if (RenderState.proportional) + return Size[RenderState.style][c]; else - return Size[Details.style][192]; + return Size[RenderState.style][209]; #endif // MORE_LANGUAGES } @@ -1158,7 +1239,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) { @@ -1168,8 +1249,6 @@ CFont::GetCharacterSize(wchar c) return Size[0][Details.style][c] * Details.scaleX; } } - if (c < 254 && (Details.style == FONT_PAGER)) - return 29.4f * Details.scaleX; switch (Details.style) { @@ -1177,21 +1256,32 @@ CFont::GetCharacterSize(wchar c) return 29.4f * Details.scaleX; case FONT_BANK: return 10.0f * Details.scaleX; - case FONT_PAGER: - return 31.5f * Details.scaleX; default: return Size[0][Details.style][c] * Details.scaleX; } } - else if(Details.proportional) - return Size[LanguageSet][Details.style][c] * Details.scaleX; else - return Size[LanguageSet][Details.style][192] * Details.scaleX; + { + if (!Details.bFontHalfTexture && c == 30) c = 61; // wanted star + if (Details.bFontHalfTexture) + c = FindNewCharacter(c); + if (Details.proportional) + return Size[LanguageSet][Details.style][c] * Details.scaleX; + else + return Size[LanguageSet][Details.style][209] * Details.scaleX; + } #else + +#ifdef FIX_BUGS + // PS2 don't call FindNewCharacter in here at all, and also uses different chars for some symbols + if (!Details.bFontHalfTexture && c == 30) c = 61; // wanted star +#endif + 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 } @@ -1212,12 +1302,10 @@ CFont::GetStringWidth(wchar *s, bool spaces) s++; #ifdef BUTTON_ICONS switch (*s) { -#if 0 // unused case 'U': case 'D': case '<': case '>': -#endif case 'X': case 'O': case 'Q': @@ -1228,6 +1316,8 @@ CFont::GetStringWidth(wchar *s, bool spaces) case 'J': case 'V': case 'C': + case '(': + case ')': w += 17.0f * Details.scaleY; break; default: @@ -1245,17 +1335,15 @@ CFont::GetStringWidth(wchar *s, bool spaces) } else #endif { - for (; (*s != ' ' || spaces) && *s != '\0'; s++) { - if (*s == '~') { + for (wchar c = *s; (c != ' ' || spaces) && c != '\0'; c = *(++s)) { + if (c == '~') { s++; #ifdef BUTTON_ICONS switch (*s) { -#if 0 // unused case 'U': case 'D': case '<': case '>': -#endif case 'X': case 'O': case 'Q': @@ -1266,27 +1354,27 @@ CFont::GetStringWidth(wchar *s, bool spaces) case 'J': case 'V': case 'C': + case '(': + case ')': w += 17.0f * Details.scaleY; break; default: break; } #endif - while (*s != '~') s++; -#ifndef FIX_BUGS - s++; - if (*s == ' ' && !spaces) - break; - } -#else - } else -#endif - w += GetCharacterSize(*s - ' '); + while (*s != '~') { + s++; + } + } + else { + w += GetCharacterSize(c - ' '); + } } } return w; } + #ifdef MORE_LANGUAGES float CFont::GetStringWidth_Jap(wchar* s) @@ -1334,19 +1422,128 @@ CFont::GetNextSpace(wchar *s) if(*s == '~'){ s++; while(*s != '~') s++; -#ifndef FIX_BUGS - s++; - if(*s == ' ') - break; -#endif } } return s; } -#ifdef MORE_LANGUAGES wchar* -CFont::ParseToken(wchar *s, wchar* ss, bool japShit) +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; +#ifdef BUTTON_ICONS + case 'U': PS2Symbol = BUTTON_UP; break; + case 'D': PS2Symbol = BUTTON_DOWN; break; + case '<': PS2Symbol = BUTTON_LEFT; break; + case '>': PS2Symbol = BUTTON_RIGHT; break; + case 'X': PS2Symbol = BUTTON_CROSS; break; + case 'O': PS2Symbol = BUTTON_CIRCLE; break; + case 'Q': PS2Symbol = BUTTON_SQUARE; break; + case 'T': PS2Symbol = BUTTON_TRIANGLE; break; + case 'K': PS2Symbol = BUTTON_L1; break; + case 'M': PS2Symbol = BUTTON_L2; break; + case 'A': PS2Symbol = BUTTON_L3; break; + case 'J': PS2Symbol = BUTTON_R1; break; + case 'V': PS2Symbol = BUTTON_R2; break; + case 'C': PS2Symbol = BUTTON_R3; break; + case 'H': PS2Symbol = BUTTON_RSTICK_UP; break; + case 'L': PS2Symbol = BUTTON_RSTICK_DOWN; break; + case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break; + case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break; +#endif + default: + break; + } + } + while (*s != '~') + ++s; + if (*(++s) == '~') + s = ParseToken(s, color, flash, bold); + return s; +} + +#if 0//def MORE_LANGUAGES +wchar* +CFont::ParseToken(wchar *s, bool japShit) { s++; if ((Details.color.r || Details.color.g || Details.color.b) && !japShit) { @@ -1367,12 +1564,10 @@ CFont::ParseToken(wchar *s, wchar* ss, bool japShit) case 'w': SetColor(CRGBA(175, 175, 175, 255)); break; case 'y': SetColor(CRGBA(210, 196, 106, 255)); break; #ifdef BUTTON_ICONS -#if 0 // unused case 'U': PS2Symbol = BUTTON_UP; break; case 'D': PS2Symbol = BUTTON_DOWN; break; case '<': PS2Symbol = BUTTON_LEFT; break; case '>': PS2Symbol = BUTTON_RIGHT; break; -#endif case 'X': PS2Symbol = BUTTON_CROSS; break; case 'O': PS2Symbol = BUTTON_CIRCLE; break; case 'Q': PS2Symbol = BUTTON_SQUARE; break; @@ -1383,6 +1578,10 @@ CFont::ParseToken(wchar *s, wchar* ss, bool japShit) case 'J': PS2Symbol = BUTTON_R1; break; case 'V': PS2Symbol = BUTTON_R2; break; case 'C': PS2Symbol = BUTTON_R3; break; + case 'H': PS2Symbol = BUTTON_RSTICK_UP; break; + case 'L': PS2Symbol = BUTTON_RSTICK_DOWN; break; + case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break; + case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break; #endif } } else if (IsJapanese()) { @@ -1390,40 +1589,111 @@ CFont::ParseToken(wchar *s, wchar* ss, bool japShit) NewLine = true; } while ((!IsJapanese() || (*s != JAP_TERMINATION)) && *s != '~') s++; -#ifdef FIX_BUGS - if (*(++s) == '~') - s = ParseToken(s, ss, japShit); - return s; -#else return s + 1; -#endif } #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 = true; break; - case 'b': SetColor(CRGBA(128, 167, 243, 255)); break; - case 'g': SetColor(CRGBA(95, 160, 106, 255)); break; - case 'h': SetColor(CRGBA(225, 225, 225, 255)); break; - case 'l': SetColor(CRGBA(0, 0, 0, 255)); break; - case 'p': SetColor(CRGBA(168, 110, 252, 255)); break; - case 'r': SetColor(CRGBA(113, 43, 73, 255)); break; - case 'w': SetColor(CRGBA(175, 175, 175, 255)); break; - case 'y': SetColor(CRGBA(210, 196, 106, 255)); break; + case 'b': + Details.color.r = 27; + Details.color.g = 89; + Details.color.b = 130; + Details.anonymous_23 = true; + break; + case 'f': + Details.bFlash = !Details.bFlash; + if (!Details.bFlash) + Details.color.a = 255; + break; + case 'g': + Details.color.r = 255; + Details.color.g = 150; + Details.color.b = 225; + Details.anonymous_23 = true; + break; + case 'h': + Details.color.r = 225; + Details.color.g = 225; + Details.color.b = 225; + Details.anonymous_23 = true; + break; + case 'l': + Details.color.r = 0; + Details.color.g = 0; + Details.color.b = 0; + Details.anonymous_23 = true; + break; + case 'o': + Details.color.r = 229; + Details.color.g = 125; + Details.color.b = 126; + Details.anonymous_23 = true; + break; + case 'p': + Details.color.r = 168; + Details.color.g = 110; + Details.color.b = 252; + Details.anonymous_23 = true; + break; + case 'q': + Details.color.r = 199; + Details.color.g = 144; + Details.color.b = 203; + Details.anonymous_23 = true; + break; + case 'r': + Details.color.r = 255; + Details.color.g = 150; + Details.color.b = 225; + Details.anonymous_23 = true; + break; + case 't': + Details.color.r = 86; + Details.color.g = 212; + Details.color.b = 146; + Details.anonymous_23 = true; + break; + case 'w': + Details.color.r = 175; + Details.color.g = 175; + Details.color.b = 175; + Details.anonymous_23 = true; + break; + case 'x': +#ifdef FIX_BUGS + Details.color.r = 0; + Details.color.g = 255; + Details.color.b = 255; +#else + Details.color.r = 132; + Details.color.g = 146; + Details.color.b = 197; +#endif + Details.anonymous_23 = true; + break; + case 'y': + Details.color.r = 255; + Details.color.g = 227; + Details.color.b = 79; + Details.anonymous_23 = true; + break; #ifdef BUTTON_ICONS -#if 0 // unused case 'U': PS2Symbol = BUTTON_UP; break; case 'D': PS2Symbol = BUTTON_DOWN; break; case '<': PS2Symbol = BUTTON_LEFT; break; case '>': PS2Symbol = BUTTON_RIGHT; break; -#endif case 'X': PS2Symbol = BUTTON_CROSS; break; case 'O': PS2Symbol = BUTTON_CIRCLE; break; case 'Q': PS2Symbol = BUTTON_SQUARE; break; @@ -1434,25 +1704,42 @@ CFont::ParseToken(wchar *s, wchar*) case 'J': PS2Symbol = BUTTON_R1; break; case 'V': PS2Symbol = BUTTON_R2; break; case 'C': PS2Symbol = BUTTON_R3; break; + case 'H': PS2Symbol = BUTTON_RSTICK_UP; break; + case 'L': PS2Symbol = BUTTON_RSTICK_DOWN; break; + case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break; + case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break; #endif } while(*s != '~') s++; - return s+1; + if (*(++s) == '~') + s = ParseToken(s); + return s; } #endif void -CFont::DrawFonts(void) +CFont::FilterOutTokensFromString(wchar *str) { - 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 + int newIdx = 0; + wchar copy[256], *c; + UnicodeStrcpy(copy, str); + + for (c = copy; *c != '\0'; c++) { + if (*c == '~') { + c++; + while (*c != '~') c++; + } else { + str[newIdx++] = *c; + } + } + str[newIdx] = '\0'; } +void +CFont::DrawFonts(void) +{ + RenderFontBuffer(); +} void CFont::SetScale(float x, float y) @@ -1576,21 +1863,27 @@ CFont::SetRightJustifyOff(void) } void -CFont::SetPropOn(void) +CFont::SetPropOff(void) { - Details.proportional = true; + Details.proportional = false; } void -CFont::SetPropOff(void) +CFont::SetPropOn(void) { - Details.proportional = false; + Details.proportional = true; } void CFont::SetFontStyle(int16 style) { - Details.style = style; + if (style == FONT_HEADING) { + Details.style = FONT_STANDARD; + Details.bFontHalfTexture = true; + } else { + Details.style = style; + Details.bFontHalfTexture = false; + } } void @@ -1619,6 +1912,23 @@ CFont::SetDropShadowPosition(int16 pos) Details.dropShadowPosition = pos; } +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 CFont::character_code(uint8 c) { diff --git a/src/renderer/Font.h b/src/renderer/Font.h index 9316ed34..02e7df3b 100644 --- a/src/renderer/Font.h +++ b/src/renderer/Font.h @@ -6,6 +6,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 { @@ -21,27 +22,54 @@ struct CFontDetails bool8 background; bool8 backgroundOnlyText; bool8 proportional; + bool8 bIsShadow; + bool8 bFlash; + bool8 bBold; float alphaFade; CRGBA backgroundColor; float wrapX; float centreSize; float rightJustifyWrap; int16 style; - int32 bank; + bool8 bFontHalfTexture; + uint32 bank; int16 dropShadowPosition; CRGBA dropColor; + bool8 bFlashState; + int nFlashTimer; + bool8 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; + bool8 bIsShadow; + bool8 bFontHalfTexture; + bool8 proportional; + bool8 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 { @@ -69,12 +97,10 @@ enum enum { BUTTON_NONE = -1, -#if 0 // unused BUTTON_UP, BUTTON_DOWN, BUTTON_LEFT, BUTTON_RIGHT, -#endif BUTTON_CROSS, BUTTON_CIRCLE, BUTTON_SQUARE, @@ -85,6 +111,10 @@ enum BUTTON_R1, BUTTON_R2, BUTTON_R3, + BUTTON_RSTICK_UP, + BUTTON_RSTICK_DOWN, + BUTTON_RSTICK_LEFT, + BUTTON_RSTICK_RIGHT, MAX_BUTTON_ICONS }; #endif // BUTTON_ICONS @@ -93,22 +123,23 @@ enum class CFont { #ifdef MORE_LANGUAGES - static int16 Size[LANGSET_MAX][MAX_FONTS][193]; + static int16 Size[LANGSET_MAX][MAX_FONTS][210]; static uint8 LanguageSet; static int32 Slot; #else - static int16 Size[MAX_FONTS][193]; + static int16 Size[MAX_FONTS][210]; #endif static bool16 NewLine; public: static CSprite2d Sprite[MAX_FONTS]; static CFontDetails Details; + static CFontRenderState RenderState; #ifdef BUTTON_ICONS static int32 ButtonsSlot; static CSprite2d ButtonSprite[MAX_BUTTON_ICONS]; static int PS2Symbol; - + static void LoadButtons(const char *txdPath); static void DrawButton(float x, float y); #endif // BUTTON_ICONS @@ -119,17 +150,18 @@ public: static void InitPerFrame(void); static void PrintChar(float x, float y, wchar c); static void PrintString(float x, float y, wchar *s); - static void PrintStringFromBottom(float x, float y, wchar *str); #ifdef XBOX_SUBTITLES + static void PrintStringFromBottom(float x, float y, wchar *str); static void PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor); #endif static int GetNumberLines(float xstart, float ystart, wchar *s); static void GetTextRect(CRect *rect, float xstart, float ystart, wchar *s); -#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); -#endif +//#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, 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); @@ -137,12 +169,14 @@ public: static float GetStringWidth_Jap(wchar* s); #endif static uint16 *GetNextSpace(wchar *s); -#ifdef MORE_LANGUAGES - static uint16 *ParseToken(wchar *s, wchar*, bool japShit = false); -#else - static uint16 *ParseToken(wchar *s, wchar*); -#endif +//#ifdef MORE_LANGUAGES +// static uint16 *ParseToken(wchar *s, bool japShit = false); +//#else + 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 void SetScale(float x, float y); @@ -169,7 +203,8 @@ public: static void SetBackgroundColor(CRGBA col); static void SetColor(CRGBA col); static void SetDropColor(CRGBA col); - + static wchar FindNewCharacter(wchar c); + static void FilterOutTokensFromString(wchar*); #ifdef MORE_LANGUAGES static void ReloadFonts(uint8 set); @@ -177,6 +212,6 @@ public: static bool IsAnsiCharacter(wchar* s); static bool IsJapanesePunctuation(wchar* str); static bool IsJapanese() { return LanguageSet == FONT_LANGSET_JAPANESE; } - static bool IsJapaneseFont() { return IsJapanese() && (Details.style == FONT_JAPANESE || Details.style == FONT_PAGER); } + static bool IsJapaneseFont() { return IsJapanese() && (Details.style == FONT_JAPANESE); } #endif }; diff --git a/src/renderer/Glass.cpp b/src/renderer/Glass.cpp index cc45648c..b4ec8c7e 100644 --- a/src/renderer/Glass.cpp +++ b/src/renderer/Glass.cpp @@ -3,6 +3,8 @@ #include "Glass.h" #include "Timer.h" #include "Object.h" +#include "Vehicle.h" +#include "Pools.h" #include "General.h" #include "AudioScriptObject.h" #include "World.h" @@ -14,6 +16,7 @@ #include "ModelIndices.h" #include "main.h" #include "soundlist.h" +#include "SurfaceTable.h" uint32 CGlass::NumGlassEntities; @@ -57,17 +60,17 @@ const CVector2D CoorsWithTriangle[NUM_GLASSTRIANGLES][3] = #define TEMPBUFFERVERTHILIGHTOFFSET 0 #define TEMPBUFFERINDEXHILIGHTOFFSET 0 -#define TEMPBUFFERVERTHILIGHTSIZE 128 +#define TEMPBUFFERVERTHILIGHTSIZE 256 #define TEMPBUFFERINDEXHILIGHTSIZE 512 #define TEMPBUFFERVERTSHATTEREDOFFSET TEMPBUFFERVERTHILIGHTSIZE #define TEMPBUFFERINDEXSHATTEREDOFFSET TEMPBUFFERINDEXHILIGHTSIZE -#define TEMPBUFFERVERTSHATTEREDSIZE 192 +#define TEMPBUFFERVERTSHATTEREDSIZE 384 #define TEMPBUFFERINDEXSHATTEREDSIZE 768 #define TEMPBUFFERVERTREFLECTIONOFFSET TEMPBUFFERVERTSHATTEREDSIZE #define TEMPBUFFERINDEXREFLECTIONOFFSET TEMPBUFFERINDEXSHATTEREDSIZE -#define TEMPBUFFERVERTREFLECTIONSIZE 256 +#define TEMPBUFFERVERTREFLECTIONSIZE 512 #define TEMPBUFFERINDEXREFLECTIONSIZE 1024 int32 TempBufferIndicesStoredHiLight = 0; @@ -83,10 +86,16 @@ CFallingGlassPane::Update(void) if ( CTimer::GetTimeInMilliseconds() >= m_nTimer ) { // Apply MoveSpeed - GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep(); + if ( m_bCarGlass ) + GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep() * 0.35f; + else + GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep(); // Apply Gravity - m_vecMoveSpeed.z -= 0.02f * CTimer::GetTimeStep(); + if ( m_bCarGlass ) + m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep(); + else + m_vecMoveSpeed.z -= 0.02f * CTimer::GetTimeStep(); // Apply TurnSpeed GetRight() += CrossProduct(m_vecTurn, GetRight()); @@ -106,24 +115,27 @@ CFallingGlassPane::Update(void) RwRGBA color = { 255, 255, 255, 255 }; - static int32 nFrameGen = 0; - - for ( int32 i = 0; i < 4; i++ ) + if ( !m_bCarGlass ) { - dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); - dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); - dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f); - - CParticle::AddParticle(PARTICLE_CAR_DEBRIS, - pos, - dir, - nil, - CGeneral::GetRandomNumberInRange(0.02f, 0.2f), - color, - CGeneral::GetRandomNumberInRange(-40, 40), - 0, - ++nFrameGen & 3, - 500); + static int32 nFrameGen = 0; + + for ( int32 i = 0; i < 4; i++ ) + { + dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); + dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); + dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f); + + CParticle::AddParticle(PARTICLE_CAR_DEBRIS, + pos, + dir, + nil, + CGeneral::GetRandomNumberInRange(0.02f, 0.2f), + color, + CGeneral::GetRandomNumberInRange(-40, 40), + 0, + ++nFrameGen & 3, + 500); + } } } } @@ -150,7 +162,10 @@ CFallingGlassPane::Render(void) CGlass::RenderHiLightPolys(); // HiLight Polys - + + if ( m_bCarGlass && color < 64 ) + color = 64; + RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], color, color, color, color); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], color, color, color, color); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], color, color, color, color); @@ -190,9 +205,9 @@ CFallingGlassPane::Render(void) if ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-7 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-4 ) CGlass::RenderShatteredPolys(); - uint8 shatteredColor = 255; + uint8 shatteredColor = 140; if ( distToCamera > 30.0f ) - shatteredColor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 255); + shatteredColor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 140); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], shatteredColor, shatteredColor, shatteredColor, shatteredColor); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], shatteredColor, shatteredColor, shatteredColor, shatteredColor); @@ -300,8 +315,8 @@ CGlass::FindFreePane(void) } void -CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector point, - float moveSpeed, bool cracked, bool explosion) +CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center, + float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass) { float upLen = up.Magnitude(); float rightLen = right.Magnitude(); @@ -312,10 +327,10 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig float rightSteps = rightLen + 0.75f; if ( rightSteps < 1.0f ) rightSteps = 1.0f; - uint32 ysteps = (uint32)upSteps; + uint32 ysteps = stepmul * (uint32)upSteps; if ( ysteps > 3 ) ysteps = 3; - uint32 xsteps = (uint32)rightSteps; + uint32 xsteps = stepmul * (uint32)rightSteps; if ( xsteps > 3 ) xsteps = 3; if ( explosion ) @@ -346,11 +361,8 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig pane->m_nTriIndex = i; pane->GetRight() = (right * rightScl) / rightLen; -#ifdef FIX_BUGS pane->GetUp() = (up * upScl) / upLen; -#else - pane->GetUp() = (up * upScl) / rightLen; // copypaste bug -#endif + CVector fwd = CrossProduct(pane->GetRight(), pane->GetUp()); fwd.Normalise(); @@ -366,7 +378,7 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig if ( moveSpeed != 0.0f ) { - CVector dist = pane->GetPosition() - point; + CVector dist = pane->GetPosition() - center; dist.Normalise(); pane->m_vecMoveSpeed += moveSpeed * dist; @@ -379,10 +391,11 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig switch ( type ) { case 0: + case 2: pane->m_nTimer = CTimer::GetTimeInMilliseconds(); break; case 1: - float dist = (pane->GetPosition() - point).Magnitude(); + float dist = (pane->GetPosition() - center).Magnitude(); pane->m_nTimer = uint32(dist*100 + CTimer::GetTimeInMilliseconds()); break; } @@ -390,6 +403,7 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig pane->m_fGroundZ = groundZ; pane->m_bShattered = cracked; pane->m_fStep = upLen / float(ysteps); + pane->m_bCarGlass = carGlass; pane->m_bActive = true; } } @@ -621,42 +635,48 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CColModel *col = object->GetColModel(); ASSERT(col!=nil); - CVector a = object->GetMatrix() * col->vertices[0].Get(); - CVector b = object->GetMatrix() * col->vertices[1].Get(); - CVector c = object->GetMatrix() * col->vertices[2].Get(); - CVector d = object->GetMatrix() * col->vertices[3].Get(); - - float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); - float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); - float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); - float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); - float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); - float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); - - - if ( amount > 300.0f ) - { - PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition()); - - GeneratePanesForWindow(0, - CVector(minx, miny, minz), - CVector(0.0f, 0.0f, maxz-minz), - CVector(maxx-minx, maxy-miny, 0.0f), - speed, point, 0.1f, !!object->bGlassCracked, explosion); - } - else + if ( col->numTriangles == 2 ) { - PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); - - GeneratePanesForWindow(1, - CVector(minx, miny, minz), - CVector(0.0f, 0.0f, maxz-minz), - CVector(maxx-minx, maxy-miny, 0.0f), - speed, point, 0.1f, !!object->bGlassCracked, explosion); + CVector a = col->vertices[0].Get(); + CVector b = col->vertices[1].Get(); + CVector c = col->vertices[2].Get(); + CVector d = col->vertices[3].Get(); + + float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); + float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); + float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); + float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); + float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); + float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); + + CVector pa = object->GetMatrix() * CVector(minx, miny, minz); + CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz); + + if ( amount > 300.0f ) + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition()); + + GeneratePanesForWindow(0, + pa, + CVector(0.0f, 0.0f, maxz-minz), + pb - pa, + speed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false); + } + else + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); + + GeneratePanesForWindow(1, + pa, + CVector(0.0f, 0.0f, maxz-minz), + pb - pa, + speed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false); + } } - + object->bGlassBroken = true; - object->GetMatrix().GetPosition().z = -100.0f; + object->bIsVisible = false; + object->bUsesCollision = false; } void @@ -666,7 +686,7 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) CObject *object = (CObject *)entity; - if ( amount > 50.0f && !object->bGlassCracked ) + if ( entity->bUsesCollision && amount > 50.0f && !object->bGlassCracked ) { PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); object->bGlassCracked = true; @@ -682,15 +702,18 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) if ( IsGlass(object->GetModelIndex()) ) { - if ( !object->bGlassCracked ) - { - PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); - object->bGlassCracked = true; - } - else + if ( object->bUsesCollision ) { - if ( (CGeneral::GetRandomNumber() & 3) == 2 ) - WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false); + if ( !object->bGlassCracked ) + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); + object->bGlassCracked = true; + } + else + { + if ( (CGeneral::GetRandomNumber() & 3) == 2 ) + WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false); + } } } } @@ -701,19 +724,304 @@ CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) ASSERT(entity!=nil); CObject *object = (CObject *)entity; + + if ( object->bUsesCollision ) + { + CVector distToGlass = object->GetPosition() - point; + + float fDistToGlass = distToGlass.Magnitude(); + + if ( fDistToGlass < 10.0f ) + { + distToGlass *= (0.3f / fDistToGlass); // normalise + WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true); + } + else + { + if ( fDistToGlass < 30.0f ) + object->bGlassCracked = true; + } + } +} - CVector distToGlass = object->GetPosition() - point; - float fDistToGlass = distToGlass.Magnitude(); +void +CGlass::CarWindscreenShatters(CVehicle *vehicle, bool unk) +{ + ASSERT(vehicle!=nil); + + CColModel *col = vehicle->GetColModel(); + ASSERT(col!=nil); + + if ( col->numTriangles < 2 ) + return; + + CColTriangle *tria = nil; + int32 triIndex = -1; + CColTriangle *trib = nil; + + for ( int32 i = 0; i < col->numTriangles; i++ ) + { + CColTriangle *tri = &col->triangles[i]; + if ( tri->surface == SURFACE_GLASS ) + { + if ( tria ) + { + trib = tri; + break; + } + + triIndex = i; + tria = tri; + } + } + + if ( trib == nil ) + return; + + CCollision::CalculateTrianglePlanes(col); + + CColTrianglePlane *triPlanes = col->trianglePlanes; + + if ( triPlanes == nil ) + return; + + CVector planeNormal; + triPlanes[triIndex].GetNormal(planeNormal); + planeNormal = Multiply3x3(vehicle->GetMatrix(), planeNormal); + + CVector vec1 = CrossProduct(vehicle->GetRight(), planeNormal); + vec1.Normalise(); + + CVector vec2 = CrossProduct(planeNormal, vehicle->GetUp()); + vec2.Normalise(); + + CVector v[6]; + float proj1[6]; + float proj2[6]; + + v[0] = col->vertices[tria->a].Get(); + v[1] = col->vertices[tria->b].Get(); + v[2] = col->vertices[tria->c].Get(); + + v[3] = col->vertices[trib->a].Get(); + v[4] = col->vertices[trib->b].Get(); + v[5] = col->vertices[trib->c].Get(); + + v[0] = vehicle->GetMatrix() * v[0]; + v[1] = vehicle->GetMatrix() * v[1]; + v[2] = vehicle->GetMatrix() * v[2]; + v[3] = vehicle->GetMatrix() * v[3]; + v[4] = vehicle->GetMatrix() * v[4]; + v[5] = vehicle->GetMatrix() * v[5]; + + proj1[0] = DotProduct(v[0], vec1); + proj2[0] = DotProduct(v[0], vec2); + proj1[1] = DotProduct(v[1], vec1); + proj2[1] = DotProduct(v[1], vec2); + proj1[2] = DotProduct(v[2], vec1); + proj2[2] = DotProduct(v[2], vec2); + + proj1[3] = DotProduct(v[3], vec1); + proj2[3] = DotProduct(v[3], vec2); + proj1[4] = DotProduct(v[4], vec1); + proj2[4] = DotProduct(v[4], vec2); + proj1[5] = DotProduct(v[5], vec1); + proj2[5] = DotProduct(v[5], vec2); + + int32 originIndex = 0; + float max1 = proj1[0]; + float max2 = proj2[0]; + float origin = proj1[0] + proj2[0]; + + for ( int32 i = 1; i < 6; i++ ) + { + float o = proj1[i] + proj2[i]; + if ( o < origin ) + { + origin = o; + originIndex = i; + } + + if ( proj1[i] > max1 ) + max1 = proj1[i]; + if ( proj2[i] > max2 ) + max2 = proj2[i]; + } + + float bound1 = max1 - proj1[originIndex]; + float bound2 = max2 - proj2[originIndex]; + + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, vehicle->GetPosition()); + + CVector center = v[originIndex] + ((0.5f*bound1) * vec1) + ((0.5f*bound2) * vec2); + CVector speed = vehicle->m_vecMoveSpeed; + CVector right = bound2 * vec2; + CVector up = bound1 * vec1; + CVector pos = v[originIndex]; + + GeneratePanesForWindow(2, pos, up, right, speed, center, 0.1f, false, false, 2, true); +} - if ( fDistToGlass < 10.0f ) +bool +CGlass::HasGlassBeenShatteredAtCoors(float x, float y, float z) +{ + CEntity *entity = nil; + float dist = 20.0f; + + int32 nStartX = Max(CWorld::GetSectorIndexX(x - 30.0f), 0); + int32 nStartY = Max(CWorld::GetSectorIndexY(y - 30.0f), 0); + int32 nEndX = Min(CWorld::GetSectorIndexX(x + 30.0f), NUMSECTORS_X-1); + int32 nEndY = Min(CWorld::GetSectorIndexY(y + 30.0f), NUMSECTORS_Y-1); + + CWorld::AdvanceCurrentScanCode(); + + for ( int32 ys = nStartY; ys <= nEndY; ys++ ) { - distToGlass *= (0.3f / fDistToGlass); // normalise - WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true); + for ( int32 xs = nStartX; xs <= nEndX; xs++ ) + { + CSector *sector = CWorld::GetSector(xs, ys); + + ASSERT(sector != nil); + + FindWindowSectorList(sector->m_lists[ENTITYLIST_OBJECTS], &dist, &entity, x, y, z); + FindWindowSectorList(sector->m_lists[ENTITYLIST_DUMMIES], &dist, &entity, x, y, z); + } } - else + + if ( entity ) { - if ( fDistToGlass < 30.0f ) - object->bGlassCracked = true; + if ( entity->GetType() == ENTITY_TYPE_DUMMY ) + return false; + + return !!((CObject*)entity)->bGlassBroken; } + + return false; } + +void +CGlass::FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z) +{ + ASSERT(dist!=nil); + ASSERT(entity!=nil); + + CPtrNode *node = list.first; + + while ( node != nil ) + { + CEntity *ent = (CEntity *)node->item; + uint16 scanCode = ent->m_scanCode; + node = node->next; + + ASSERT(ent!=nil); + + if ( IsGlass(ent->GetModelIndex()) ) + { + if ( scanCode != CWorld::GetCurrentScanCode() ) + { + ent->m_scanCode = CWorld::GetCurrentScanCode(); + + float dst = (CVector(x,y,z) - ent->GetPosition()).Magnitude(); + + if ( dst < *dist ) + { + *dist = dst; + *entity = ent; + } + } + } + } +} + +void +CGlass::BreakGlassPhysically(CVector pos, float radius) +{ + static uint32 breakTime = 0; + + if ( CTimer::GetTimeInMilliseconds() < breakTime + 1000 && CTimer::GetTimeInMilliseconds() >= breakTime ) + return; + + CColSphere sphere; + sphere.piece = 0; + sphere.radius = radius; + sphere.surface = 0; + + for ( int32 i = CPools::GetObjectPool()->GetSize() - 1; i >= 0; i-- ) + { + CObject *object = CPools::GetObjectPool()->GetSlot(i); + if (object) + { + if ( IsGlass(object->GetModelIndex()) ) + { + if ( object->bUsesCollision ) + { + CColModel *col = object->GetColModel(); + ASSERT(col!=nil); + + if ( col->numTriangles < 2 ) + continue; + + bool hit = false; + + CVector dist = pos - object->GetPosition(); + + sphere.center.x = DotProduct(dist, object->GetRight()); + sphere.center.y = DotProduct(dist, object->GetForward()); + sphere.center.z = DotProduct(dist, object->GetUp()); + + CCollision::CalculateTrianglePlanes(col); + + for ( int32 j = 0; j < col->numTriangles; j++ ) + { + if ( CCollision::TestSphereTriangle(sphere, + col->vertices, col->triangles[j], col->trianglePlanes[j]) ) + { + hit = true; + } + } + + if ( hit ) + { + breakTime = CTimer::GetTimeInMilliseconds(); + + if ( object->bGlassCracked ) + { + CVector a = col->vertices[0].Get(); + CVector b = col->vertices[1].Get(); + CVector c = col->vertices[2].Get(); + CVector d = col->vertices[3].Get(); + + float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); + float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); + float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); + float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); + float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); + float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); + + CVector pa = object->GetMatrix() * CVector(minx, miny, minz); + CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz); + + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); + + GeneratePanesForWindow(1, + pa, + CVector(0.0f, 0.0f, maxz-minz), + pb - pa, + CVector(0.0f, 0.0f, 0.0f), pos, 0.1f, !!object->bGlassCracked, false, 1, false); + + object->bGlassBroken = true; + object->bIsVisible = false; + object->bUsesCollision = false; + } + else + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); + object->bGlassCracked = true; + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/renderer/Glass.h b/src/renderer/Glass.h index 51c5aae9..f1c85779 100644 --- a/src/renderer/Glass.h +++ b/src/renderer/Glass.h @@ -1,6 +1,8 @@ #pragma once class CEntity; +class CVehicle; +class CPtrList; class CFallingGlassPane : public CMatrix { @@ -13,6 +15,7 @@ public: uint8 m_nTriIndex; bool m_bActive; bool m_bShattered; + bool m_bCarGlass; CFallingGlassPane() { } ~CFallingGlassPane() { } @@ -38,7 +41,7 @@ public: static void Update(void); static void Render(void); static CFallingGlassPane *FindFreePane(void); - static void GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector point, float moveSpeed, bool cracked, bool explosion); + static void GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center, float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass); static void AskForObjectToBeRenderedInGlass(CEntity *entity); static void RenderEntityInGlass(CEntity *entity); static int32 CalcAlphaWithNormal(CVector *normal); @@ -49,4 +52,8 @@ public: static void WindowRespondsToSoftCollision(CEntity *entity, float amount); static void WasGlassHitByBullet(CEntity *entity, CVector point); static void WindowRespondsToExplosion(CEntity *entity, CVector point); + static void CarWindscreenShatters(CVehicle *vehicle, bool unk); + static bool HasGlassBeenShatteredAtCoors(float x, float y, float z); + static void FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z); + static void BreakGlassPhysically(CVector pos, float radius); };
\ No newline at end of file diff --git a/src/renderer/Hud.cpp b/src/renderer/Hud.cpp index bba8c525..d7d8050f 100644 --- a/src/renderer/Hud.cpp +++ b/src/renderer/Hud.cpp @@ -20,50 +20,11 @@ #include "TxdStore.h" #include "User.h" #include "World.h" - -#ifdef PS2_HUD -#define MONEY_X 100.0f -#define WEAPON_X 91.0f -#define AMMO_X 59.0f -#define HEALTH_X 100.0f -#define STARS_X 49.0f -#define ZONE_Y 61.0f -#define VEHICLE_Y 81.0f -#define CLOCK_X 101.0f -#define SUBS_Y 83.0f -#define WASTEDBUSTED_Y 122.0f -#define BIGMESSAGE_Y 80.0f -#else -#define MONEY_X 110.0f -#define WEAPON_X 99.0f -#define AMMO_X 66.0f -#define HEALTH_X 110.0f -#define STARS_X 60.0f -#define ZONE_Y 30.0f -#define VEHICLE_Y 55.0f -#define CLOCK_X 111.0f -#define SUBS_Y 68.0f -#define WASTEDBUSTED_Y 82.0f -#define BIGMESSAGE_Y 84.0f -#endif - -#ifdef FIX_BUGS -#define TIMER_RIGHT_OFFSET 34.0f // Taken from VC frenzy timer -#define BIGMESSAGE_Y_OFFSET 18.0f -#else -#define TIMER_RIGHT_OFFSET 27.0f -#define BIGMESSAGE_Y_OFFSET 20.0f -#endif - -#if defined(PS2_HUD) && !defined(FIX_BUGS) - #define SCREEN_SCALE_X_PC(a) (a) - #define SCREEN_SCALE_Y_PC(a) (a) - #define SCALE_AND_CENTER_X_PC(a) (a) -#else - #define SCREEN_SCALE_X_PC(a) SCREEN_SCALE_X(a) - #define SCREEN_SCALE_Y_PC(a) SCREEN_SCALE_Y(a) - #define SCALE_AND_CENTER_X_PC(a) SCALE_AND_CENTER_X(a) -#endif +#include "CutsceneMgr.h" +#include "Stats.h" +#include "main.h" +#include "General.h" +#include "VarConsole.h" #if defined(FIX_BUGS) #define SCREEN_SCALE_X_FIX(a) SCREEN_SCALE_X(a) @@ -83,295 +44,222 @@ // 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); - -int16 CHud::m_ItemToFlash; -CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; -wchar *CHud::m_pZoneName; -wchar *CHud::m_pLastZoneName; -wchar *CHud::m_ZoneToPrint; -wchar CHud::m_Message[256]; -wchar CHud::m_BigMessage[6][128]; -wchar LastBigMessage[6][128]; -wchar CHud::m_PagerMessage[256]; -uint32 CHud::m_ZoneNameTimer; -int32 CHud::m_ZoneFadeTimer; -uint32 CHud::m_ZoneState; wchar CHud::m_HelpMessage[HELP_MSG_LENGTH]; wchar CHud::m_LastHelpMessage[HELP_MSG_LENGTH]; -wchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH]; +uint32 CHud::m_HelpMessageState; uint32 CHud::m_HelpMessageTimer; int32 CHud::m_HelpMessageFadeTimer; -uint32 CHud::m_HelpMessageState; -bool CHud::m_HelpMessageQuick; +wchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH]; float CHud::m_HelpMessageDisplayTime; -int32 CHud::SpriteBrightness; -bool CHud::m_Wants_To_Draw_Hud; -bool CHud::m_Wants_To_Draw_3dMarkers; -wchar *CHud::m_pVehicleName; -wchar *CHud::m_pLastVehicleName; -uint32 CHud::m_VehicleNameTimer; -int32 CHud::m_VehicleFadeTimer; +bool CHud::m_HelpMessageDisplayForever; +bool CHud::m_HelpMessageQuick; +uint32 CHud::m_ZoneState; +int32 CHud::m_ZoneFadeTimer; +uint32 CHud::m_ZoneNameTimer; +wchar *CHud::m_pZoneName; +wchar *CHud::m_pLastZoneName; +wchar *CHud::m_ZoneToPrint; uint32 CHud::m_VehicleState; +int32 CHud::m_VehicleFadeTimer; +uint32 CHud::m_VehicleNameTimer; +wchar *CHud::m_VehicleName; +wchar *CHud::m_pLastVehicleName; wchar *CHud::m_pVehicleNameToPrint; +wchar CHud::m_Message[256]; +wchar CHud::m_PagerMessage[256]; +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 BigMessageInUse[6]; -float BigMessageX[6]; -float BigMessageAlpha[6]; -int16 PagerOn; -int16 PagerTimer; -float PagerXOffset; -int16 PagerSoundPlayed; -int16 OddJob2On; -uint16 OddJob2Timer; -float OddJob2XOffset; -float OddJob2OffTimer; -bool CounterOnLastFrame; -uint16 CounterFlashTimer; -bool TimerOnLastFrame; -uint16 TimerFlashTimer; +float CHud::BigMessageInUse[6]; +float CHud::BigMessageAlpha[6]; +float CHud::BigMessageX[6]; +float CHud::OddJob2OffTimer; +bool CHud::CounterOnLastFrame[NUMONSCREENCOUNTERS]; +float CHud::OddJob2XOffset; +uint16 CHud::CounterFlashTimer[NUMONSCREENCOUNTERS]; +uint16 CHud::OddJob2Timer; +bool CHud::TimerOnLastFrame; +int16 CHud::OddJob2On; +uint16 CHud::TimerFlashTimer; +int16 CHud::PagerSoundPlayed; +int32 CHud::SpriteBrightness; +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; -RwTexture *gpSniperSightTex; -RwTexture *gpRocketSightTex; +CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; 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", "" } }; -void CHud::Initialise() -{ - m_Wants_To_Draw_Hud = true; - m_Wants_To_Draw_3dMarkers = true; - - int 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); - } - - GetRidOfAllHudMessages(); - - if (gpSniperSightTex == nil) - gpSniperSightTex = RwTextureRead("sitesniper", nil); - if (gpRocketSightTex == nil) - gpRocketSightTex = RwTextureRead("siterocket", nil); - - CounterOnLastFrame = false; - m_ItemToFlash = ITEM_NONE; - OddJob2Timer = 0; - OddJob2OffTimer = 0.0f; - OddJob2On = 0; - OddJob2XOffset = 0.0f; - CounterFlashTimer = 0; - TimerOnLastFrame = false; - TimerFlashTimer = 0; - SpriteBrightness = 0; - PagerOn = 0; - PagerTimer = 0; - PagerSoundPlayed = 0; - PagerXOffset = 150.0f; - - CTxdStore::PopCurrentTxd(); -} - -void CHud::Shutdown() -{ - for (int i = 0; i < NUM_HUD_SPRITES; ++i) { - Sprites[i].Delete(); - } - - RwTextureDestroy(gpSniperSightTex); - gpSniperSightTex = nil; - - RwTextureDestroy(gpRocketSightTex); - gpRocketSightTex = nil; - - int HudTXD = CTxdStore::FindTxdSlot("hud"); - CTxdStore::RemoveTxdSlot(HudTXD); -} - -void CHud::ReInitialise() { - m_Wants_To_Draw_Hud = true; - m_Wants_To_Draw_3dMarkers = true; - - GetRidOfAllHudMessages(); - - CounterOnLastFrame = false; - m_ItemToFlash = ITEM_NONE; - OddJob2Timer = 0; - OddJob2OffTimer = 0.0f; - OddJob2On = 0; - OddJob2XOffset = 0.0f; - CounterFlashTimer = 0; - TimerOnLastFrame = false; - TimerFlashTimer = 0; - SpriteBrightness = 0; - PagerOn = 0; - PagerTimer = 0; - PagerSoundPlayed = 0; - PagerXOffset = 150.0f; -} - -void CHud::GetRidOfAllHudMessages() -{ - m_ZoneState = 0; - m_pLastZoneName = nil; - m_ZoneNameTimer = 0; - m_pZoneName = nil; - - for (int i = 0; i < HELP_MSG_LENGTH; i++) { - m_HelpMessage[i] = 0; - m_LastHelpMessage[i] = 0; - m_HelpMessageToPrint[i] = 0; - } - - m_HelpMessageTimer = 0; - m_HelpMessageFadeTimer = 0; - m_HelpMessageState = 0; - m_HelpMessageQuick = 0; - m_HelpMessageDisplayTime = 1.0f; - m_pVehicleName = nil; - m_pLastVehicleName = nil; - m_pVehicleNameToPrint = nil; - m_VehicleNameTimer = 0; - m_VehicleFadeTimer = 0; - m_VehicleState = 0; - - for (int i = 0; i < ARRAY_SIZE(m_Message); i++) - m_Message[i] = 0; - - for (int i = 0; i < 6; i++) { - BigMessageInUse[i] = 0.0f; - - for (int j = 0; j < 128; j++) - m_BigMessage[i][j] = 0; - } -} - -void CHud::SetZoneName(wchar *name) -{ - m_pZoneName = name; -} - -void CHud::SetHelpMessage(wchar *message, bool quick) -{ - if (!CReplay::IsPlayingBack()) { - CMessages::WideStringCopy(m_HelpMessage, message, HELP_MSG_LENGTH); - CMessages::InsertPlayerControlKeysInString(m_HelpMessage); - - for (int i = 0; i < HELP_MSG_LENGTH; i++) { - m_LastHelpMessage[i] = 0; - } - - m_HelpMessageState = 0; - m_HelpMessageQuick = quick; - } -} - -void CHud::SetVehicleName(wchar *name) -{ - m_pVehicleName = name; -} +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; -#ifdef GTA_PC if (CReplay::IsPlayingBack()) return; -#endif if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) { + // unused statics in here bool DrawCrossHair = false; -#ifdef GTA_PC + bool CrossHairHidesHud = false; bool DrawCrossHairPC = false; -#endif - 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 -#ifdef GTA_PC - || Mode == CCam::MODE_HELICANNON_1STPERSON -#endif - ) - { + 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; - } - -#ifdef GTA_PC + 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; + } + } } } -#endif - if ( DrawCrossHair -#ifdef GTA_PC - || DrawCrossHairPC -#endif - ) - { + if (DrawCrossHair || DrawCrossHairPC) { RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); SpriteBrightness = Min(SpriteBrightness+1, 30); @@ -379,16 +267,15 @@ void CHud::Draw() RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); float fStep = Sin((CTimer::GetTimeInMilliseconds() & 1023)/1024.0f * 6.28f); - float fMultBright = SpriteBrightness / 30.0f * (0.25f * fStep + 0.75f); + float fMultBright = SpriteBrightness * 0.03f * (0.25f * fStep + 0.75f); CRect rect; -#ifdef GTA_PC if (DrawCrossHairPC && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()) { float f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX; float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY; #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); @@ -406,17 +293,10 @@ 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 -#endif - { - if (Mode == CCam::MODE_M16_1STPERSON -#ifdef GTA_PC - || Mode == CCam::MODE_M16_1STPERSON_RUNABOUT - || Mode == CCam::MODE_HELICANNON_1STPERSON -#endif - ) - { + } else { + if (Mode == CCam::MODE_M16_1STPERSON || + Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || + Mode == CCam::MODE_HELICANNON_1STPERSON) { rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f); rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f); rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f); @@ -424,7 +304,6 @@ 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); } -#ifdef GTA_PC else if (Mode == CCam::MODE_1STPERSON_RUNABOUT) { rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f); rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f * 0.7f); @@ -434,210 +313,309 @@ 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); } -#endif - else if (Mode == CCam::MODE_ROCKETLAUNCHER -#ifdef GTA_PC - || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT -#endif - ) - { + else if (Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) { RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex)); - CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X_PC(40.0f), SCREEN_SCALE_Y_PC(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255); + + 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.01f, 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); +#ifdef FIX_BUGS + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); +#else + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA); +#endif + 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); + 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::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)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MONEY_X) + SCREEN_SCALE_X_FIX(2.0f), SCREEN_SCALE_Y(43.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrint); - CFont::SetColor(MONEY_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MONEY_X), SCREEN_SCALE_Y(43.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); + + if (FrontEndMenuManager.m_PrefsShowHud) { + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); + } + } /* DrawAmmo */ - int32 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition; - int32 AmmoInClip = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoInClip; - int32 TotalAmmo = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoTotal; - int32 Ammo, Clip; - - if (AmmoAmount <= 1 || AmmoAmount >= 1000) - sprintf(sTemp, "%d", TotalAmmo); - else { - if (WeaponType == WEAPONTYPE_FLAMETHROWER) { - Clip = AmmoInClip / 10; - - Ammo = Min((TotalAmmo - AmmoInClip) / 10, 9999); - } + 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(); + int32 AmmoAmount = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType)->m_nAmountofAmmunition; + int32 AmmoInClip = weapon->m_nAmmoInClip; + int32 TotalAmmo = weapon->m_nAmmoTotal; + int32 Ammo, Clip; + + if (AmmoAmount <= 1 || AmmoAmount >= 1000) + sprintf(sTemp, "%d", TotalAmmo); else { - Clip = AmmoInClip; + if (WeaponType == WEAPONTYPE_FLAMETHROWER) { + Clip = AmmoInClip / 10; - Ammo = Min(TotalAmmo - AmmoInClip, 9999); - } + Ammo = Min((TotalAmmo - AmmoInClip) / 10, 9999); + } else { + Clip = AmmoInClip; - sprintf(sTemp, "%d-%d", Ammo, Clip); - } + Ammo = Min(TotalAmmo - AmmoInClip, 9999); + } - AsciiToUnicode(sTemp, sPrint); + sprintf(sTemp, "%d-%d", Ammo, Clip); + } - /* - DrawWeaponIcon - */ - Sprites[WeaponType].Draw( - CRect( - SCREEN_SCALE_FROM_RIGHT(WEAPON_X), - SCREEN_SCALE_Y(27.0f), - SCREEN_SCALE_FROM_RIGHT(WEAPON_X)+SCREEN_SCALE_X(64.0f), - SCREEN_SCALE_Y(27.0f)+SCREEN_SCALE_Y(64.0f)), - CRGBA(255, 255, 255, 255), - 0.015f, - 0.015f, - 1.0f, - 0.0f, - 0.015f, - 1.0f, - 1.0f, - 1.0f); - - 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); + 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->GetModelName()); + if (weaponIcon) { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); +#ifndef FIX_BUGS + const float xSize = SCREEN_SCALE_X(64.0f / 2.0f); + const float ySize = SCREEN_SCALE_Y(64.0f / 2.0f); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon)); + 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); +#else + static CSprite2d sprite; + sprite.m_pTexture = weaponIcon; + sprite.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); + sprite.m_pTexture = nil; +#endif + } + } + } - if (!CDarkel::FrenzyOnGoing() && WeaponType != WEAPONTYPE_UNARMED && WeaponType != WEAPONTYPE_BASEBALLBAT) { - CFont::SetColor(AMMO_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(AMMO_X), SCREEN_SCALE_Y(73.0f), 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); + } + } } /* 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 && FRAMECOUNTER & 8 - || m_ItemToFlash != ITEM_HEALTH - || FindPlayerPed()->m_fHealth < 10 - && FRAMECOUNTER & 8) { - if (FindPlayerPed()->m_fHealth >= 10 - || FindPlayerPed()->m_fHealth < 10 && FRAMECOUNTER & 8) { - - AsciiToUnicode("{", sPrintIcon); + 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; + } + + 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 (m_ItemToFlash == ITEM_HEALTH && FRAMECOUNTER & 8 + || m_ItemToFlash != ITEM_HEALTH + || playerPed->m_fHealth < 10 + && FRAMECOUNTER & 8) { + if (playerPed->m_fHealth >= 10 + || playerPed->m_fHealth < 10 && FRAMECOUNTER & 8) { + + 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); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEALTH_X) + SCREEN_SCALE_X_FIX(2.0f), SCREEN_SCALE_Y(65.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrint); + AsciiToUnicode(sTemp, sPrint); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || FRAMECOUNTER & 4) - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEALTH_X) + SCREEN_SCALE_X_FIX(2.0f) - SCREEN_SCALE_X(56.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(65.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrintIcon); - - CFont::SetColor(HEALTH_COLOR); - - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEALTH_X), SCREEN_SCALE_Y(65.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 || FRAMECOUNTER & 4) - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(HEALTH_X) + SCREEN_SCALE_X_FIX(2.0f) - SCREEN_SCALE_X(56.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || FRAMECOUNTER & 4) { + // CFont::SetColor(HEALTH_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 54.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } + } + } } - } - /* - DrawArmour - */ - if (m_ItemToFlash == ITEM_ARMOUR && FRAMECOUNTER & 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); + /* + DrawArmour + */ + if (m_ItemToFlash == ITEM_ARMOUR && FRAMECOUNTER & 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(FindPlayerPed()->m_fArmour + 0.5f)); + sprintf(sTemp, "%03d", int32(playerPed->m_fArmour + 0.5f)); #else - sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fArmour); + sprintf(sTemp, "%03d", (int32)playerPed->m_fArmour); #endif - AsciiToUnicode(sTemp, sPrint); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f) + SCREEN_SCALE_X_FIX(2.0f), SCREEN_SCALE_Y(65.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrint); - - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || FRAMECOUNTER & 4) - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f) + SCREEN_SCALE_X_FIX(2.0f) - SCREEN_SCALE_X(54.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(65.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrintIcon); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(ARMOUR_COLOR); + CFont::SetColor(ARMOUR_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.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_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || FRAMECOUNTER & 1) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f) - SCREEN_SCALE_X(54.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || FRAMECOUNTER & 4) { + // CFont::SetColor(ARMOUR_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } + } } } } @@ -645,38 +623,99 @@ void CHud::Draw() /* 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); + if (m_LastWanted == playerPed->m_pWanted->GetWantedLevel()) { + alpha = DrawFadeState(HUD_WANTED_FADING, 0); + } else { + alpha = DrawFadeState(HUD_WANTED_FADING, 1); + m_LastWanted = playerPed->m_pWanted->GetWantedLevel(); + } - AsciiToUnicode("]", sPrintIcon); - - float fStarsX = SCREEN_SCALE_FROM_RIGHT(STARS_X); + 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); + + AsciiToUnicode(">", sPrintIcon); + + for (int i = 0; i < 6; i++) { + if (FrontEndMenuManager.m_PrefsShowHud) { + if (playerPed->m_pWanted->GetWantedLevel() > i + && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange + + 2000 || FRAMECOUNTER & 4)) { + + 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); + + } else if (playerPed->m_pWanted->m_nMinWantedLevel > i && FRAMECOUNTER & 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); - for (int i = 0; i < 6; i++) { - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(fStarsX + SCREEN_SCALE_X_FIX(2.0f), SCREEN_SCALE_Y(87.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrintIcon); + } else if (playerPed->m_pWanted->GetWantedLevel() <= 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); + } + } + } + } + + 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)); - if (FindPlayerPed()->m_pWanted->GetWantedLevel() > i - && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange - + 2000 || FRAMECOUNTER & 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(fStarsX, 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); + } } - - fStarsX -= SCREEN_SCALE_X(23.0f); } /* DrawZoneName */ if (m_pZoneName) { - float fZoneAlpha = 255.0f; if (m_pZoneName != m_pLastZoneName) { switch (m_ZoneState) { @@ -685,6 +724,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: @@ -699,70 +740,76 @@ 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; } - fZoneAlpha = m_ZoneFadeTimer / 1000.0f * 255.0f; + fZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f; break; case 3: m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer < 0) { + if (m_ZoneFadeTimer < 0.0f) { m_ZoneState = 0; m_ZoneFadeTimer = 0; } - fZoneAlpha = m_ZoneFadeTimer / 1000.0f * 255.0f; + fZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f; 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; } - fZoneAlpha = m_ZoneFadeTimer / 1000.0f * 255.0f; + fZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f; break; default: break; } -#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_FIX(1.0f), SCREEN_SCALE_FROM_BOTTOM(ZONE_Y) + SCREEN_SCALE_Y_FIX(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(ZONE_Y), 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; } } } @@ -770,16 +817,18 @@ void CHud::Draw() /* DrawVehicleName */ - if (m_pVehicleName) { + if (m_VehicleName) { float fVehicleAlpha = 0.0f; - if (m_pVehicleName != m_pLastVehicleName) { + if (m_VehicleName != m_pLastVehicleName) { switch (m_VehicleState) { case 0: m_VehicleState = 2; - m_pVehicleNameToPrint = m_pVehicleName; + 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: @@ -791,7 +840,7 @@ void CHud::Draw() default: break; } - m_pLastVehicleName = m_pVehicleName; + m_pLastVehicleName = m_VehicleName; } if (m_VehicleState) { @@ -809,7 +858,7 @@ void CHud::Draw() m_VehicleState = 1; m_VehicleFadeTimer = 1000; } - fVehicleAlpha = m_VehicleFadeTimer / 1000.0f * 255.0f; + fVehicleAlpha = m_VehicleFadeTimer * 0.001f * 255.0f; break; case 3: m_VehicleFadeTimer -= CTimer::GetTimeStepInMilliseconds(); @@ -817,7 +866,7 @@ void CHud::Draw() m_VehicleState = 0; m_VehicleFadeTimer = 0; } - fVehicleAlpha = m_VehicleFadeTimer / 1000.0f * 255.0f; + fVehicleAlpha = m_VehicleFadeTimer * 0.001f * 255.0f; break; case 4: m_VehicleFadeTimer -= CTimer::GetTimeStepInMilliseconds(); @@ -827,36 +876,37 @@ void CHud::Draw() m_VehicleNameTimer = 0; m_VehicleState = 2; } - fVehicleAlpha = m_VehicleFadeTimer / 1000.0f * 255.0f; + fVehicleAlpha = m_VehicleFadeTimer * 0.001f * 255.0f; break; default: 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 - { + if (!m_Message[0]) { 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_FIX(1.0f), SCREEN_SCALE_FROM_BOTTOM(VEHICLE_Y) + SCREEN_SCALE_Y_FIX(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(VEHICLE_Y), 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); } } } @@ -870,214 +920,165 @@ 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); + 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)); - sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes()); - AsciiToUnicode(sTemp, sPrint); + sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes()); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(CLOCK_X) + SCREEN_SCALE_X_FIX(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y_FIX(2.0f), sPrint); - CFont::SetColor(CLOCK_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(CLOCK_X), 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 */ + 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; + + 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 (FRAMECOUNTER & 4 || !TimerFlashTimer) { - AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer); + if (FRAMECOUNTER & 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_FIX(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y_FIX(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); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(110.0f), sTimer); + CFont::SetPropOn(); - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) { - CFont::SetPropOn(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetScale(SCREEN_SCALE_X(0.8f * 0.8f), 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_FIX(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); + 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 (FRAMECOUNTER & 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_FIX(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y_FIX(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_FIX(4.0f), - SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), - SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X_FIX(4.0f), - SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y_PC(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_FIX(4.0f), - SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), - SCREEN_SCALE_X_PC((float)counter) / 2.0f + SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2.0f + SCREEN_SCALE_X_FIX(4.0f), - SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y_PC(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_X(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y_FIX(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 (FRAMECOUNTER & 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)); } } } } - ///////////////////////////////// - /* - 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) - SCREEN_SCALE_X_FIX(PagerXOffset), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_X(160.0f) + SCREEN_SCALE_X(26.0f) - SCREEN_SCALE_X_FIX(PagerXOffset), SCREEN_SCALE_Y(80.0f) + SCREEN_SCALE_Y(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::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); - CFont::SetJustifyOff(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_PAGER); - CFont::PrintString(SCREEN_SCALE_X(52.0f) - SCREEN_SCALE_X_FIX(PagerXOffset), SCREEN_SCALE_Y(54.0f), m_PagerMessage); - } - /* DrawRadar */ - if (m_ItemToFlash == ITEM_RADAR && FRAMECOUNTER & 8 || m_ItemToFlash != ITEM_RADAR) { + if (FrontEndMenuManager.m_PrefsRadarMode != 2 && + !m_HideRadar && (m_ItemToFlash == ITEM_RADAR && FRAMECOUNTER & 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)); - rect.Translate(SCREEN_SCALE_X_FIX(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); - -#ifdef PS2_HUD - #ifdef FIX_BUGS - rect.Grow(SCREEN_SCALE_X(2.0f), SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(4.0f)); - #else - rect.Grow(2.0f, 4.0f); - #endif + if (FrontEndMenuManager.m_PrefsRadarMode != 1) { + CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT)); + + rect.Translate(SCREEN_SCALE_X_FIX(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); + +#ifdef FIX_BUGS + rect.Grow(SCREEN_SCALE_X(6.0f), SCREEN_SCALE_X(6.0f), SCREEN_SCALE_Y(6.0f), SCREEN_SCALE_Y(6.0f)); #else - #ifdef FIX_BUGS - rect.Grow(SCREEN_SCALE_X(4.0f), SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(4.0f), SCREEN_SCALE_Y(4.0f)); - #else - rect.Grow(4.0f); - #endif + rect.Grow(6.0f); #endif - Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); + rect.Translate(SCREEN_SCALE_X_FIX(0.0f), SCREEN_SCALE_Y_FIX(2.0f)); + Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); + rect.Translate(SCREEN_SCALE_X_FIX(0.0f), SCREEN_SCALE_Y_FIX(-2.0f)); + Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); + } CRadar::DrawBlips(); } } @@ -1095,12 +1096,7 @@ void CHud::Draw() if (!CTimer::GetIsUserPaused()) { for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) { if (CTheScripts::IntroTextLines[i].m_Text[0] && CTheScripts::IntroTextLines[i].m_bTextBeforeFade) { - CFont::SetScale(SCREEN_SCALE_X_PC(CTheScripts::IntroTextLines[i].m_fScaleX), SCREEN_SCALE_Y_PC(CTheScripts::IntroTextLines[i].m_fScaleY) -#if !defined(PS2_HUD) || defined(FIX_BUGS) - * 0.5f -#endif - ); - + CFont::SetScale(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fScaleX), SCREEN_SCALE_Y(CTheScripts::IntroTextLines[i].m_fScaleY * 0.5f)); CFont::SetColor(CTheScripts::IntroTextLines[i].m_sColor); if (CTheScripts::IntroTextLines[i].m_bJustify) @@ -1118,10 +1114,9 @@ void CHud::Draw() else CFont::SetCentreOff(); - CFont::SetWrapx(SCALE_AND_CENTER_X_PC(CTheScripts::IntroTextLines[i].m_fWrapX)); - - CFont::SetCentreSize(SCREEN_SCALE_X_PC(CTheScripts::IntroTextLines[i].m_fCenterSize)); - + CFont::SetWrapx(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fWrapX)); + CFont::SetCentreSize(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); + if (CTheScripts::IntroTextLines[i].m_bBackground) CFont::SetBackgroundOn(); else @@ -1140,12 +1135,7 @@ void CHud::Draw() CFont::SetPropOff(); CFont::SetFontStyle(FONT_LOCALE(CTheScripts::IntroTextLines[i].m_nFont)); - -#if defined(PS2_HUD) && !defined(FIX_BUGS) - CFont::PrintString(CTheScripts::IntroTextLines[i].m_fAtX, CTheScripts::IntroTextLines[i].m_fAtY, CTheScripts::IntroTextLines[i].m_Text); -#else - CFont::PrintString(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text); -#endif + CFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text); } } for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) { @@ -1177,41 +1167,173 @@ 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_PC(0.48f), SCREEN_SCALE_Y_PC(1.12f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); +#ifdef CUTSCENE_BORDERS_SWITCH + if (!FrontEndMenuManager.m_PrefsCutsceneBorders) { + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetDropShadowPosition(2); + } + else +#endif + CFont::SetDropShadowPosition(0); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetColor(CRGBA(225, 225, 225, 255)); -#ifdef XBOX_SUBTITLES - float radarBulge = SCREEN_SCALE_X(45.0f) + SCREEN_SCALE_X(16.0f); - float rectWidth = SCREEN_WIDTH - SCREEN_SCALE_X(45.0f) - SCREEN_SCALE_X(16.0f) - radarBulge; - CFont::SetCentreSize(rectWidth); - CFont::SetColor(CRGBA(180, 180, 180, 255)); + static bool onceItWasWidescreen = false; - CFont::PrintOutlinedString(rectWidth / 2.0f + radarBulge, SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(48.0f) - SCREEN_SCALE_Y(1), m_Message, - 2.0f, true, CRGBA(0, 0, 0, 255)); -#else - float radarBulge = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f); - float rectWidth = SCREEN_SCALE_FROM_RIGHT(50.0f) - SCREEN_SCALE_X(8.0f) - radarBulge; - - CFont::SetCentreSize(rectWidth); + if (TheCamera.m_WideScreenOn) { + onceItWasWidescreen = true; + + if (FrontEndMenuManager.m_PrefsShowSubtitles || !CCutsceneMgr::IsRunning()) { + CFont::SetCentreSize(SCREEN_WIDTH - SCREEN_SCALE_X(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'; - const int16 shadow = 1; - CFont::SetDropShadowPosition(shadow); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::SetColor(CRGBA(235, 235, 235, 255)); + 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)); + + float radarBulge = SCREEN_SCALE_X(140.0f) + SCREEN_SCALE_X(8.0f); + float rectWidth = SCREEN_WIDTH - SCREEN_SCALE_X(20.0f) - SCREEN_SCALE_X(8.0f) - radarBulge; + CFont::SetCentreSize(rectWidth); - // 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(rectWidth / 2.0f + radarBulge - SCREEN_SCALE_X_FIX(shadow), SCREEN_SCALE_Y_PC(4.0f) + SCREEN_SCALE_FROM_BOTTOM(SUBS_Y) - SCREEN_SCALE_Y_FIX(shadow), m_Message); + CFont::PrintString(rectWidth / 2.0f + radarBulge, SCREEN_SCALE_FROM_BOTTOM(105.f + 2.0f), m_Message); + } CFont::SetDropShadowPosition(0); -#endif // #ifdef XBOX_SUBTITLES } /* + 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, 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 @@ -1220,25 +1342,20 @@ void CHud::Draw() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); CFont::SetBackGroundOnlyTextOff(); - - if (CGame::frenchGame || CGame::germanGame) - CFont::SetScale(SCREEN_SCALE_X_PC(1.8f), SCREEN_SCALE_Y_PC(1.8f)); - else - CFont::SetScale(SCREEN_SCALE_X_PC(1.8f), SCREEN_SCALE_Y_PC(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_X(DEFAULT_SCREEN_WIDTH - 25)); - CFont::SetColor(CRGBA(255, 255, 0, 255)); + CFont::SetCentreSize(SCREEN_SCALE_X(590.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. -#ifdef FIX_BUGS - if (BigMessageX[0] >= SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH-20)) -#else - if (BigMessageX[0] >= SCREEN_WIDTH-20) -#endif - { + + if (BigMessageX[0] >= SCALE_AND_CENTER_X(620.0f)) { BigMessageInUse[0] += CTimer::GetTimeStep(); if (BigMessageInUse[0] >= 120.0f) { @@ -1252,29 +1369,21 @@ void CHud::Draw() } } else { - BigMessageX[0] += SCREEN_SCALE_X_FIX(CTimer::GetTimeStepInMilliseconds() * 0.3f); + BigMessageX[0] += SCREEN_SCALE_X((CTimer::GetTimeStepInMilliseconds() * 0.3f)); BigMessageAlpha[0] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); if (BigMessageAlpha[0] > 255.0f) BigMessageAlpha[0] = 255.0f; } - CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[0])); - -#if defined(PS2_HUD) && !defined(FIX_BUGS) // yeah, that's right. ps2 uses y=ScaleX(a) - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X_FIX(2.0f), (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(120.0f) + SCREEN_SCALE_Y_FIX(2.0f), m_BigMessage[0]); -#else - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X_FIX(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(BIGMESSAGE_Y_OFFSET) + SCREEN_SCALE_Y_FIX(2.0f), m_BigMessage[0]); -#endif + 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])); -#if defined(PS2_HUD) && !defined(FIX_BUGS) // same - CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(120.0f), m_BigMessage[0]); -#else CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]); -#endif } else { BigMessageAlpha[0] = 0.0f; - BigMessageX[0] = SCALE_AND_CENTER_X_FIX(-60.0f); + BigMessageX[0] = SCALE_AND_CENTER_X(-60.0f); BigMessageInUse[0] = 1.0f; } } @@ -1293,22 +1402,27 @@ void CHud::Draw() CFont::SetBackgroundOff(); if (CGame::frenchGame || CGame::germanGame) - CFont::SetScale(SCREEN_SCALE_X_PC(1.4f), SCREEN_SCALE_Y_PC(1.4f)); + CFont::SetScale(SCREEN_SCALE_X(1.4f), SCREEN_SCALE_Y(1.4f)); else - CFont::SetScale(SCREEN_SCALE_X_PC(2.0f), SCREEN_SCALE_Y_PC(2.0f)); + CFont::SetScale(SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(2.0f)); CFont::SetPropOn(); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); - CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[2]*0.75f)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X_FIX(4.0f), SCREEN_SCALE_FROM_BOTTOM(WASTEDBUSTED_Y) + SCREEN_SCALE_Y(4.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(WASTEDBUSTED_Y), 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 { @@ -1319,118 +1433,18 @@ 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, 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) / 20.0f + 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, HELP_MSG_LENGTH); - } - - float fAlpha = 225.0f; - - if (m_HelpMessageState != 0) { - switch (m_HelpMessageState) { - case 1: - fAlpha = 225.0f; - m_HelpMessageFadeTimer = 600; - if (m_HelpMessageTimer > m_HelpMessageDisplayTime * 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 / 1000.0f * 225.0f; - break; - case 3: - m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer < 0) { - m_HelpMessageState = 0; - m_HelpMessageFadeTimer = 0; - } - fAlpha = m_HelpMessageFadeTimer / 1000.0f * 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 / 1000.0f * 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) + SCREEN_SCALE_X(26.0f) - SCREEN_SCALE_X_FIX(4.0f)); - else -#endif - CFont::SetWrapx(SCREEN_SCALE_X(200.0f) + SCREEN_SCALE_X(26.0f) - SCREEN_SCALE_X_FIX(4.0f)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetBackgroundOn(); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f)); - CFont::SetColor(CRGBA(175, 175, 175, 255)); - CFont::PrintString(SCREEN_SCALE_X(26.0f), SCREEN_SCALE_Y(28.0f) + SCREEN_SCALE_Y_FIX((150.0f - PagerXOffset) * 0.6f), 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) { + CFont::SetScale(SCREEN_SCALE_X(line.m_fScaleX), SCREEN_SCALE_Y(line.m_fScaleY) / 2); - CFont::SetScale(SCREEN_SCALE_X_PC(line.m_fScaleX), SCREEN_SCALE_Y_PC(line.m_fScaleY) -#if !defined(PS2_HUD) || defined(FIX_BUGS) - / 2 -#endif - ); CFont::SetColor(line.m_sColor); if (line.m_bJustify) CFont::SetJustifyOn(); @@ -1447,9 +1461,8 @@ void CHud::DrawAfterFade() else CFont::SetCentreOff(); - CFont::SetWrapx(SCALE_AND_CENTER_X_PC(line.m_fWrapX)); - CFont::SetCentreSize(SCREEN_SCALE_X_PC(line.m_fCenterSize)); - + CFont::SetWrapx(SCALE_AND_CENTER_X(line.m_fWrapX)); + CFont::SetCentreSize(SCREEN_SCALE_X(line.m_fCenterSize)); if (line.m_bBackground) CFont::SetBackgroundOn(); else @@ -1467,11 +1480,7 @@ void CHud::DrawAfterFade() CFont::SetPropOff(); CFont::SetFontStyle(line.m_nFont); -#if defined(PS2_HUD) && !defined(FIX_BUGS) - CFont::PrintString(line.m_fAtX, line.m_fAtY, line.m_Text); -#else - CFont::PrintString(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text); -#endif + CFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text); } } for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) { @@ -1496,29 +1505,29 @@ void CHud::DrawAfterFade() if (m_BigMessage[3][0]) { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X_PC(1.2f), SCREEN_SCALE_Y_PC(1.5f)); + CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 40)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X_FIX(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(BIGMESSAGE_Y) + SCREEN_SCALE_Y_FIX(2.0f), m_BigMessage[3]); + CFont::SetCentreSize(SCREEN_SCALE_X(600.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(BIGMESSAGE_Y), 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]) { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X_PC(1.2f), SCREEN_SCALE_Y_PC(1.5f)); + CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X_FIX(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(BIGMESSAGE_Y) - SCREEN_SCALE_Y_FIX(2.0f), m_BigMessage[4]); + CFont::SetCentreSize(SCREEN_SCALE_X(580.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(BIGMESSAGE_Y), m_BigMessage[4]); + CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f), m_BigMessage[4]); } // Oddjob result @@ -1568,24 +1577,12 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.2f)); CFont::SetCentreOn(); CFont::SetPropOn(); - // Not bug, we just want these kind of texts to be wrapped at the center. -#ifdef ASPECT_RATIO_SCALE - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20.0f)); -#else - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); -#endif - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - -#ifdef BETA_SLIDING_TEXT - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X_PC(2.0f) - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y_PC(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]); -#else - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X_PC(2.0f), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y_PC(2.0f), m_BigMessage[5]); + CFont::SetCentreSize(SCREEN_SCALE_X(560.0f)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(ODDJOB2_COLOR); - CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); -#endif + CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_Y(217.0f), m_BigMessage[5]); } } @@ -1597,82 +1594,261 @@ 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_PC(0.884f), SCREEN_SCALE_Y_PC(1.36f)); + CFont::SetScale(SCREEN_SCALE_X(0.884f), SCREEN_SCALE_Y(1.36f)); else - CFont::SetScale(SCREEN_SCALE_X_PC(1.04f), SCREEN_SCALE_Y_PC(1.6f)); + CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); CFont::SetPropOn(); -#ifdef FIX_BUGS - CFont::SetRightJustifyWrap(SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 500.0f)); -#else - CFont::SetRightJustifyWrap(-500.0f); -#endif + CFont::SetRightJustifyWrap(SCALE_AND_CENTER_X(0.0f)); CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); - - if (BigMessageX[1] >= SCREEN_WIDTH - SCREEN_SCALE_X_FIX(20.0f)) - { + 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_FIX(CTimer::GetTimeStepInMilliseconds() * 0.3f); - BigMessageAlpha[1] += (CTimer::GetTimeStepInMilliseconds() * 0.3f); + BigMessageX[1] += SCREEN_SCALE_X((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_PC(2.0f), m_BigMessage[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]); -#else - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X_FIX(2.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y_PC(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(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), m_BigMessage[1]); -#endif - } - else { - BigMessageAlpha[1] = 0.0f; -#ifdef FIX_BUGS + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(140.0f), m_BigMessage[1]); + } else { + m_ZoneFadeTimer = 0; BigMessageX[1] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); -#else - BigMessageX[1] = -60.0f; -#endif BigMessageInUse[1] = 1.0f; + m_ZoneState = 0; } - } - else { + } else { BigMessageInUse[1] = 0.0f; } } -void CHud::SetMessage(wchar *message) +void CHud::GetRidOfAllHudMessages() { - int i = 0; - for (i = 0; i < ARRAY_SIZE(m_Message); i++) { - if (message[i] == 0) - break; + m_ZoneNameTimer = 0; + m_pZoneName = nil; + m_ZoneState = 0; - m_Message[i] = message[i]; + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_HelpMessage[i] = 0; + m_LastHelpMessage[i] = 0; + m_HelpMessageToPrint[i] = 0; + } + + m_HelpMessageTimer = 0; + m_HelpMessageFadeTimer = 0; + m_HelpMessageState = 0; + m_HelpMessageQuick = 0; + m_HelpMessageDisplayForever = false; + m_HelpMessageDisplayTime = 1.0f; + m_VehicleName = nil; + m_pVehicleNameToPrint = nil; + m_VehicleNameTimer = 0; + m_VehicleFadeTimer = 0; + m_VehicleState = 0; + + for (int i = 0; i < ARRAY_SIZE(m_Message); i++) + m_Message[i] = 0; + + for (int i = 0; i < 6; i++) { + BigMessageInUse[i] = 0.0f; + + for (int j = 0; j < 128; j++) + m_BigMessage[i][j] = 0; } - m_Message[i] = 0; } +#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; + m_Wants_To_Draw_3dMarkers = true; + + int 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); + } + + m_pLastZoneName = nil; + GetRidOfAllHudMessages(); + m_pLastVehicleName = nil; + + if (gpSniperSightTex == nil) + gpSniperSightTex = RwTextureRead("sitesniper", nil); // unused + if (gpRocketSightTex == nil) + gpRocketSightTex = RwTextureRead("siterocket", nil); + 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] = 0; + CounterFlashTimer[1] = 0; + CounterFlashTimer[2] = 0; + TimerOnLastFrame = false; + TimerFlashTimer = 0; + SpriteBrightness = 0; + PagerOn = 0; + 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; + +#ifndef MASTER + VarConsole.Add("Draw HUD", &m_Wants_To_Draw_Hud, false); +#endif + CTxdStore::PopCurrentTxd(); +} + +void CHud::ReInitialise() { + m_Wants_To_Draw_Hud = true; + m_Wants_To_Draw_3dMarkers = true; + + m_pLastZoneName = nil; + GetRidOfAllHudMessages(); + m_pLastVehicleName = nil; + + 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] = 0; + CounterFlashTimer[1] = 0; + CounterFlashTimer[2] = 0; + TimerOnLastFrame = false; + TimerFlashTimer = 0; + SpriteBrightness = 0; + PagerOn = 0; + 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, uint16 style) { int i = 0; + if (BigMessageInUse[style] != 0.0f) + return; + if (style == 5) { for (i = 0; i < 128; i++) { if (message[i] == 0) @@ -1695,9 +1871,62 @@ void CHud::SetBigMessage(wchar *message, uint16 style) } LastBigMessage[style][i] = 0; m_BigMessage[style][i] = 0; -#ifndef FIX_BUGS - m_BigMessage[style][i] = 0; -#endif +} + +void CHud::SetHelpMessage(wchar *message, bool quick, bool displayForever) +{ + if (!CReplay::IsPlayingBack()) { + 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; + } + + 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; + } + + } +} + +bool CHud::IsHelpMessageBeingDisplayed(void) +{ + return m_HelpMessageState != 0; +} + +void CHud::SetMessage(wchar *message) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(m_Message); i++) { + if (message[i] == 0) + break; + + m_Message[i] = message[i]; + } + m_Message[i] = 0; } void CHud::SetPagerMessage(wchar *message) @@ -1710,4 +1939,151 @@ void CHud::SetPagerMessage(wchar *message) m_PagerMessage[i] = message[i]; } m_PagerMessage[i] = 0; -}
\ No newline at end of file +} + +void CHud::SetVehicleName(wchar *name) +{ + m_VehicleName = name; +} + +void CHud::SetZoneName(wchar *name) +{ + m_pZoneName = name; +} + +void CHud::Shutdown() +{ + for (int i = 0; i < NUM_HUD_SPRITES; ++i) { + Sprites[i].Delete(); + } + + RwTextureDestroy(gpSniperSightTex); + gpSniperSightTex = nil; + + 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; +} diff --git a/src/renderer/Hud.h b/src/renderer/Hud.h index adfdf1fc..a4b9609a 100644 --- a/src/renderer/Hud.h +++ b/src/renderer/Hud.h @@ -3,6 +3,9 @@ #define HELP_MSG_LENGTH 256 +#define HUD_TEXT_SCALE_X 0.7f +#define HUD_TEXT_SCALE_Y 1.25f + enum eItems { ITEM_NONE = -1, @@ -11,71 +14,126 @@ 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 int16 m_ItemToFlash; static CSprite2d Sprites[NUM_HUD_SPRITES]; - static wchar *m_pZoneName; - static wchar *m_pLastZoneName; - static wchar *m_ZoneToPrint; - static wchar m_Message[256]; - static wchar m_BigMessage[6][128]; - static wchar m_PagerMessage[256]; - static uint32 m_ZoneNameTimer; - static int32 m_ZoneFadeTimer; - static uint32 m_ZoneState; static wchar m_HelpMessage[HELP_MSG_LENGTH]; static wchar m_LastHelpMessage[HELP_MSG_LENGTH]; - static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH]; + static uint32 m_HelpMessageState; static uint32 m_HelpMessageTimer; static int32 m_HelpMessageFadeTimer; - static uint32 m_HelpMessageState; - static bool m_HelpMessageQuick; + static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH]; static float m_HelpMessageDisplayTime; - static int32 SpriteBrightness; - static bool m_Wants_To_Draw_Hud; - static bool m_Wants_To_Draw_3dMarkers; - static wchar *m_pVehicleName; + static bool m_HelpMessageDisplayForever; + static bool m_HelpMessageQuick; + static uint32 m_ZoneState; + static int32 m_ZoneFadeTimer; + static uint32 m_ZoneNameTimer; + static wchar *m_pZoneName; + static wchar *m_pLastZoneName; + static wchar *m_ZoneToPrint; + static wchar *m_VehicleName; static wchar *m_pLastVehicleName; - static uint32 m_VehicleNameTimer; - static int32 m_VehicleFadeTimer; - static uint32 m_VehicleState; static wchar *m_pVehicleNameToPrint; + static uint32 m_VehicleState; + static int32 m_VehicleFadeTimer; + static uint32 m_VehicleNameTimer; + static wchar m_Message[256]; + static wchar m_PagerMessage[256]; + static bool m_Wants_To_Draw_Hud; + static bool m_Wants_To_Draw_3dMarkers; + static wchar m_BigMessage[6][128]; + static int16 m_ItemToFlash; + 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[NUMONSCREENCOUNTERS]; + static float OddJob2XOffset; + static uint16 CounterFlashTimer[NUMONSCREENCOUNTERS]; + static uint16 OddJob2Timer; + static bool TimerOnLastFrame; + static int16 OddJob2On; + static uint16 TimerFlashTimer; + static int16 PagerSoundPlayed; + static int32 SpriteBrightness; + static float PagerXOffset; + static int16 PagerTimer; + static int16 PagerOn; + + 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 Initialise(); - static void Shutdown(); - static void ReInitialise(); - static void GetRidOfAllHudMessages(); - static void SetZoneName(wchar *name); - static void SetHelpMessage(wchar *message, bool quick); - static void SetVehicleName(wchar *name); static void Draw(); static void DrawAfterFade(); - static void SetMessage(wchar *message); + static void GetRidOfAllHudMessages(); +#ifdef RELOADABLES + static void ReloadTXD(); +#endif + static void Initialise(); + static void ReInitialise(); 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/renderer/MBlur.cpp b/src/renderer/MBlur.cpp index 8e5fba2a..cc8270ce 100644 --- a/src/renderer/MBlur.cpp +++ b/src/renderer/MBlur.cpp @@ -7,8 +7,14 @@ #endif #include "main.h" +#include "General.h" #include "RwHelper.h" #include "Camera.h" +#include "Timecycle.h" +#include "Particle.h" +#include "Timer.h" +#include "Hud.h" +#include "Frontend.h" #include "MBlur.h" #include "postfx.h" @@ -18,8 +24,12 @@ RwRaster *CMBlur::pFrontBuffer; bool CMBlur::ms_bJustInitialised; bool CMBlur::ms_bScaledBlur; bool CMBlur::BlurOn; +float CMBlur::Drunkness; + +int32 CMBlur::pBufVertCount; static RwIm2DVertex Vertex[4]; +static RwIm2DVertex Vertex2[4]; static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 }; #ifndef LIBRW @@ -201,6 +211,121 @@ 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 +CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect, RwIm2DVertex *verts, RwRGBA color, float u1Off, float v1Off, float u2Off, float v2Off, float z, int fullTexture) +{ + float x1 = rect->x; + float y1 = rect->y; + float x2 = rect->w; + float y2 = rect->h; + + float u1, v1, u2, v2; + if(fullTexture){ + u1 = 0.0f; + v1 = 0.0f; + u2 = 1.0f; + v2 = 1.0f; + }else{ + if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){ + x1 += HALFPX; + y1 += HALFPX; + x2 += HALFPX; + y2 += HALFPX; + }else{ + x1 -= HALFPX; + y1 -= HALFPX; + x2 -= HALFPX; + y2 -= HALFPX; + } + + int32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1); + int32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1); + u1 = x1/width + u1Off; + v1 = y1/height + v1Off; + u2 = x2/width + u2Off; + v2 = y2/height + v2Off; + u1 = Clamp(u1, 0.0f, 1.0f); + v1 = Clamp(v1, 0.0f, 1.0f); + u2 = Clamp(u2, 0.0f, 1.0f); + v2 = Clamp(v2, 0.0f, 1.0f); + } + + float recipz = 1.0f/z; + // TODO: CameraZ is wrong, what should we do? + RwIm2DVertexSetScreenX(&verts[0], x1); + RwIm2DVertexSetScreenY(&verts[0], y1); + RwIm2DVertexSetScreenZ(&verts[0], z); + RwIm2DVertexSetCameraZ(&verts[0], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&verts[0], recipz); + RwIm2DVertexSetU(&verts[0], u1, recipz); + RwIm2DVertexSetV(&verts[0], v1, recipz); + RwIm2DVertexSetIntRGBA(&verts[0], color.red, color.green, color.blue, color.alpha); + + RwIm2DVertexSetScreenX(&verts[1], x1); + RwIm2DVertexSetScreenY(&verts[1], y2); + RwIm2DVertexSetScreenZ(&verts[1], z); + RwIm2DVertexSetCameraZ(&verts[1], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&verts[1], recipz); + RwIm2DVertexSetU(&verts[1], u1, recipz); + RwIm2DVertexSetV(&verts[1], v2, recipz); + RwIm2DVertexSetIntRGBA(&verts[1], color.red, color.green, color.blue, color.alpha); + + RwIm2DVertexSetScreenX(&verts[2], x2); + RwIm2DVertexSetScreenY(&verts[2], y2); + RwIm2DVertexSetScreenZ(&verts[2], z); + RwIm2DVertexSetCameraZ(&verts[2], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&verts[2], recipz); + RwIm2DVertexSetU(&verts[2], u2, recipz); + RwIm2DVertexSetV(&verts[2], v2, recipz); + RwIm2DVertexSetIntRGBA(&verts[2], color.red, color.green, color.blue, color.alpha); + + RwIm2DVertexSetScreenX(&verts[3], x2); + RwIm2DVertexSetScreenY(&verts[3], y1); + RwIm2DVertexSetScreenZ(&verts[3], z); + RwIm2DVertexSetCameraZ(&verts[3], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&verts[3], recipz); + RwIm2DVertexSetU(&verts[3], u2, recipz); + RwIm2DVertexSetV(&verts[3], v1, recipz); + RwIm2DVertexSetIntRGBA(&verts[3], color.red, color.green, color.blue, color.alpha); } void @@ -215,24 +340,25 @@ 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 POP_RENDERGROUP(); #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) { @@ -280,41 +406,105 @@ 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); + 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); } + if(type != MOTION_BLUR_SNIPER) + OverlayRenderFx(cam, pFrontBuffer); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); @@ -323,3 +513,289 @@ 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); +} + +#define NUM_RENDER_FX 64 + +static RwRect fxRect[NUM_RENDER_FX]; +static FxType fxType[NUM_RENDER_FX]; +static float fxZ[NUM_RENDER_FX]; + +bool +CMBlur::PosInside(RwRect *rect, float x1, float y1, float x2, float y2) +{ + if((rect->x < x1 - 10.0f || rect->x > x2 + 10.0f || rect->y < y1 - 10.0f || rect->y > y2 + 10.0f) && + (rect->w < x1 - 10.0f || rect->w > x2 + 10.0f || rect->h < y1 - 10.0f || rect->h > y2 + 10.0f) && + (rect->x < x1 - 10.0f || rect->x > x2 + 10.0f || rect->h < y1 - 10.0f || rect->h > y2 + 10.0f) && + (rect->w < x1 - 10.0f || rect->w > x2 + 10.0f || rect->y < y1 - 10.0f || rect->y > y2 + 10.0f)) + return false; + return true; +} + +bool +CMBlur::AddRenderFx(RwCamera *cam, RwRect *rect, float z, FxType type) +{ + if(pBufVertCount >= NUM_RENDER_FX) + return false; + + rect->x = Max(rect->x, 0); + rect->y = Max(rect->y, 0); + rect->w = Min(rect->w, SCREEN_WIDTH); + rect->h = Min(rect->h, SCREEN_HEIGHT); + if(rect->x >= rect->w || rect->y >= rect->h) + return false; + + switch(type){ + case FXTYPE_WATER1: + case FXTYPE_WATER2: + case FXTYPE_BLOOD1: + case FXTYPE_BLOOD2: + case FXTYPE_HEATHAZE: // code seems to be duplicated for this case + for(int i = 0; i < pBufVertCount; i++) + if(fxType[i] == type && PosInside(rect, fxRect[i].x-10.0f, fxRect[i].y-10.0f, fxRect[i].w+10.0f, fxRect[i].h+10.0f)) + return false; + // TODO: fix aspect ratio scaling + // radar + if(PosInside(rect, 40.0f, SCREEN_SCALE_FROM_BOTTOM(116.0f), 40.0f + SCREEN_SCALE_X(94.0f), SCREEN_SCALE_FROM_BOTTOM(116.0f - 76.0f))) + return false; + // HUD + if(PosInside(rect, 400.0f, 0.0f, SCREEN_WIDTH, 90.0f)) + return false; + // vehicle name + if(CHud::m_VehicleState != 0 && PosInside(rect, SCREEN_WIDTH/2, 350.0f, SCREEN_WIDTH, SCREEN_HEIGHT)) + return false; + // zone name + if(CHud::m_ZoneState != 0 && PosInside(rect, SCREEN_WIDTH/2, 350.0f, SCREEN_WIDTH, SCREEN_HEIGHT)) + return false; + break; + } + + fxRect[pBufVertCount] = *rect; + fxZ[pBufVertCount] = z; + fxType[pBufVertCount] = type; + pBufVertCount++; + + return true; +} + +void +CMBlur::OverlayRenderFx(RwCamera *cam, RwRaster *frontBuf) +{ + bool drawWaterDrops = false; + RwIm2DVertex verts[4]; + int red = (0.75f*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed())*0.55f * 255; + int green = (0.75f*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen())*0.55f * 255; + int blue = (0.75f*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue())*0.55f * 255; + red = Clamp(red, 0, 255); + green = Clamp(green, 0, 255); + blue = Clamp(blue, 0, 255); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + +#ifdef LIBRW + rw::SetRenderState(rw::STENCILENABLE, TRUE); +#else + RwD3D8SetRenderState(D3DRS_STENCILENABLE, TRUE); +#endif + + for(int i = 0; i < pBufVertCount; i++) + switch(fxType[i]){ + case FXTYPE_WATER1: + case FXTYPE_WATER2: + case FXTYPE_BLOOD1: + case FXTYPE_BLOOD2: { + drawWaterDrops = true; + int32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1); + int32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1); + + float u1Off = (fxRect[i].w - fxRect[i].x)/width; + float u2Off = u1Off - (fxRect[i].w - fxRect[i].x + 0.5f)*0.66f/width; + float halfHeight = (fxRect[i].h - fxRect[i].y + 0.5f)*0.25f/height; + + if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){ + if(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2) + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 128), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + else + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(32, 32, 32, 225), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + }else{ + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(32, 32, 32, 225), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + } + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpDotRaster); +#ifdef LIBRW + rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS); + rw::SetRenderState(rw::STENCILFUNCTIONREF, 1); + rw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFFFFFFFF); + rw::SetRenderState(rw::STENCILFUNCTIONWRITEMASK, 0xFFFFFFFF); + rw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE); +#else + RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); + RwD3D8SetRenderState(D3DRS_STENCILREF, 1); + RwD3D8SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF); + RwD3D8SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF); + RwD3D8SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); + RwD3D8SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); + RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); +#endif + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + + if(RwRasterGetDepth(RwCameraGetRaster(cam)) != 16){ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, frontBuf); +#ifdef LIBRW + rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILEQUAL); + rw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP); +#else + RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); + RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); +#endif + if(BlurOn){ + if(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2) + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 255), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false); + else + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(225, 225, 225, 160), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDDESTALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA); + }else{ + if(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2) + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 128), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false); + else + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(128, 128, 128, 32), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + } + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + break; + } + case FXTYPE_SPLASH1: + case FXTYPE_SPLASH2: + case FXTYPE_SPLASH3: + drawWaterDrops = true; + break; + + case FXTYPE_HEATHAZE: + if(TheCamera.GetScreenFadeStatus() == FADE_0 && frontBuf){ + int alpha = FrontEndMenuManager.m_PrefsBrightness > 255 ? + FrontEndMenuManager.m_PrefsBrightness - 90 : + FrontEndMenuManager.m_PrefsBrightness - 130; + alpha = Clamp(alpha, 16, 200)/2; + + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(0, 0, 0, alpha), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpHeatHazeRaster); +#ifdef LIBRW + rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS); + rw::SetRenderState(rw::STENCILFUNCTIONREF, 1); + rw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFFFFFFFF); + rw::SetRenderState(rw::STENCILFUNCTIONWRITEMASK, 0xFFFFFFFF); + rw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP); + rw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE); +#else + RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); + RwD3D8SetRenderState(D3DRS_STENCILREF, 1); + RwD3D8SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF); + RwD3D8SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF); + RwD3D8SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); + RwD3D8SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); + RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); +#endif + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 255, 255, alpha), + CGeneral::GetRandomNumberInRange(-0.002f, 0.002f), + CGeneral::GetRandomNumberInRange(-0.002f, 0.002f), + CGeneral::GetRandomNumberInRange(-0.002f, 0.002f), + CGeneral::GetRandomNumberInRange(-0.002f, 0.002f), + fxZ[i], false); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, frontBuf); +#ifdef LIBRW + rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILEQUAL); + rw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP); +#else + RwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); + RwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); +#endif + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + break; + } +#ifdef LIBRW + rw::SetRenderState(rw::STENCILENABLE, FALSE); +#else + RwD3D8SetRenderState(D3DRS_STENCILENABLE, FALSE); +#endif + + if(drawWaterDrops){ + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + // Draw drops + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripRaster[0]); + for(int i = 0; i < pBufVertCount; i++) + if(fxType[i] == FXTYPE_WATER1 || fxType[i] == FXTYPE_BLOOD1){ + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, fxType[i] == FXTYPE_BLOOD1 ? 255 : 192), + 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripRaster[1]); + for(int i = 0; i < pBufVertCount; i++) + if(fxType[i] == FXTYPE_WATER2 || fxType[i] == FXTYPE_BLOOD2){ + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, fxType[i] == FXTYPE_BLOOD2 ? 255 : 192), + 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCarSplashRaster[0]); + for(int i = 0; i < pBufVertCount; i++) + if(fxType[i] == FXTYPE_SPLASH1 || fxType[i] == FXTYPE_SPLASH2 || fxType[i] == FXTYPE_SPLASH3){ + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(200, 200, 200, 255), + 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + + // Darken the water drops + int alpha = 192*0.5f; + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripDarkRaster[0]); + for(int i = 0; i < pBufVertCount; i++) + if(fxType[i] == FXTYPE_WATER1){ + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, alpha), + 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripDarkRaster[1]); + for(int i = 0; i < pBufVertCount; i++) + if(fxType[i] == FXTYPE_WATER2){ + CreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, alpha), + 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6); + } + } + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + pBufVertCount = 0; +} diff --git a/src/renderer/MBlur.h b/src/renderer/MBlur.h index e2e5d38c..3dc53082 100644 --- a/src/renderer/MBlur.h +++ b/src/renderer/MBlur.h @@ -1,5 +1,17 @@ #pragma once +enum FxType +{ + FXTYPE_WATER1, + FXTYPE_WATER2, + FXTYPE_BLOOD1, + FXTYPE_BLOOD2, + FXTYPE_HEATHAZE, + FXTYPE_SPLASH1, + FXTYPE_SPLASH2, + FXTYPE_SPLASH3 +}; + class CMBlur { public: @@ -7,11 +19,21 @@ public: static bool ms_bJustInitialised; static bool ms_bScaledBlur; static bool BlurOn; + static float Drunkness; + + static int32 pBufVertCount; public: static RwBool MotionBlurOpen(RwCamera *cam); static RwBool MotionBlurClose(void); static void CreateImmediateModeData(RwCamera *cam, RwRect *rect); + static void CreateImmediateModeData(RwCamera *cam, RwRect *rect, RwIm2DVertex *verts, RwRGBA color, float u1Off, float v1Off, float u2Off, float v2Off, float z, int fullTexture); 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(); + + static bool PosInside(RwRect *rect, float x1, float y1, float x2, float y2); + static bool AddRenderFx(RwCamera *cam, RwRect *rect, float z, FxType type); + static void OverlayRenderFx(RwCamera *cam, RwRaster *frontBuf); }; diff --git a/src/renderer/Occlusion.cpp b/src/renderer/Occlusion.cpp new file mode 100644 index 00000000..ec7101a6 --- /dev/null +++ b/src/renderer/Occlusion.cpp @@ -0,0 +1,530 @@ +#include "common.h" + +#include "main.h" +#include "Entity.h" +#include "Occlusion.h" +#include "Game.h" +#include "Camera.h" +#include "Vector.h" +#include "Draw.h" +#include "Timer.h" +#include "RwHelper.h" +#include "VarConsole.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 bDispayOccDebugStuff; // disPAY, yeah +#endif + +void +COcclusion::Init(void) +{ + NumOccludersOnMap = 0; +#ifndef MASTER + VarConsole.Add("Occlusion debug", &bDispayOccDebugStuff, true); +#endif + FarAwayList = -1; + NearbyList = -1; + ListWalkThroughFA = -1; + PreviousListWalkThroughFA = -1; +} + +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; + +#ifndef MASTER + if (gbModelViewer) + return; +#endif + + 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 (!bDispayOccDebugStuff || !(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 + +bool CEntity::IsEntityOccluded(void) { + + CVector coors; + float width, height; + + if (COcclusion::NumActiveOccluders == 0 || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height)) + return false; + + float area = Max(width, height) * GetBoundRadius() * 0.9f; + + for (int i = 0; i < COcclusion::NumActiveOccluders; i++) { + if (coors.z - (GetBoundRadius() * 0.85f) > COcclusion::aActiveOccluders[i].radius) { + if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) { + return true; + } + + if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) { + CVector min = m_matrix * CModelInfo::GetColModel(m_modelIndex)->boundingBox.min; + CVector max = m_matrix * CModelInfo::GetColModel(m_modelIndex)->boundingBox.max; + + if (CalcScreenCoors(min, &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(max.x, max.y, min.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(max.x, min.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(min.x, max.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + + return true; + } + } + } + + return false; +}
\ No newline at end of file diff --git a/src/renderer/Occlusion.h b/src/renderer/Occlusion.h new file mode 100644 index 00000000..e0edef53 --- /dev/null +++ b/src/renderer/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 bDispayOccDebugStuff; +#endif
\ No newline at end of file diff --git a/src/renderer/Particle.cpp b/src/renderer/Particle.cpp index 76ddde50..461a10a6 100644 --- a/src/renderer/Particle.cpp +++ b/src/renderer/Particle.cpp @@ -4,27 +4,30 @@ #include "General.h" #include "Timer.h" #include "TxdStore.h" -#include "Entity.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" +#include "SaveBuf.h" #include "debugmenu.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) @@ -39,16 +42,18 @@ #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) +#define MAX_LEAF_FILES (2) + const char SmokeFiles[][6+1] = { "smoke1", @@ -59,15 +64,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", @@ -111,14 +107,6 @@ const char GunFlashFiles[][9+1] = "gunflash4" }; -const char RaindropFiles[][9+1] = -{ - "raindrop1", - "raindrop2", - "raindrop3", - "raindrop4" -}; - const char RainSplashupFiles[][10+1] = { "splash_up1", @@ -133,6 +121,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", @@ -152,7 +152,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]; @@ -160,26 +160,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 *gpLeafTex[MAX_LEAF_FILES]; +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]; @@ -187,45 +188,59 @@ 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 *gpLeafRaster[MAX_LEAF_FILES]; +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 *gpSparkTex; +RwTexture *gpNewspaperTex; +RwTexture *gpGunSmokeTex; +RwTexture *gpDotTex; +RwTexture *gpHeatHazeTex; +RwTexture *gpBeastieTex; +RwTexture *gpRainDripTex[MAX_RAINDRIP_FILES]; +RwTexture *gpRainDripDarkTex[MAX_RAINDRIP_FILES]; + +RwRaster *gpSparkRaster; +RwRaster *gpNewspaperRaster; +RwRaster *gpGunSmokeRaster; +RwRaster *gpDotRaster; +RwRaster *gpHeatHazeRaster; +RwRaster *gpBeastieRaster; +RwRaster *gpRainDripRaster[MAX_RAINDRIP_FILES]; +RwRaster *gpRainDripDarkRaster[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); @@ -233,6 +248,8 @@ TWEAKFLOAT(fParticleScaleLimit, 0.0f, 1.0f, 0.1f); TWEAKFUNC(CParticle::ReloadConfig); #endif + + void CParticle::ReloadConfig() { debug("Initialising CParticleMgr..."); @@ -320,11 +337,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++ ) { @@ -352,15 +366,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++ ) { @@ -370,10 +382,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); @@ -386,7 +404,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); @@ -405,8 +426,11 @@ void CParticle::Initialise() gpBloodTex = RwTextureRead("blood", nil); gpBloodRaster = RwTextureGetRaster(gpBloodTex); - gpLeafTex = RwTextureRead("gameleaf01_64", nil); - gpLeafRaster = RwTextureGetRaster(gpLeafTex); + gpLeafTex[0] = RwTextureRead("gameleaf01_64", nil); + gpLeafRaster[0] = RwTextureGetRaster(gpLeafTex[0]); + + gpLeafTex[1] = RwTextureRead("letter", nil); + gpLeafRaster[1] = RwTextureGetRaster(gpLeafTex[1]); gpCloudTex1 = RwTextureRead("cloud3", nil); gpCloudRaster1 = RwTextureGetRaster(gpCloudTex1); @@ -429,12 +453,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); + + gpRainDripTex[0] = RwTextureRead("raindrip64", nil); + gpRainDripRaster[0] = RwTextureGetRaster(gpRainDripTex[0]); + + gpRainDripTex[1] = RwTextureRead("raindripb64", nil); + gpRainDripRaster[1] = RwTextureGetRaster(gpRainDripTex[1]); + + gpRainDripDarkTex[0] = RwTextureRead("raindrip64_d", nil); + gpRainDripDarkRaster[0] = RwTextureGetRaster(gpRainDripDarkTex[0]); + + gpRainDripDarkTex[1] = RwTextureRead("raindripb64_d", nil); + gpRainDripDarkRaster[1] = RwTextureGetRaster(gpRainDripDarkTex[1]); + CTxdStore::PopCurrentTxd(); for ( int32 i = 0; i < MAX_PARTICLES; i++ ) @@ -443,185 +494,186 @@ 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; } } debug("CParticle ready"); } -void -CEntity::AddSteamsFromGround(CVector *unused) -{ - int i, n; - C2dEffect *effect; - CVector pos; - - n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects(); - for(i = 0; i < n; i++){ - effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i); - if(effect->type != EFFECT_PARTICLE) - continue; - - pos = GetMatrix() * effect->pos; - switch(effect->particle.particleType){ - case 0: - CParticleObject::AddObject(POBJECT_PAVEMENT_STEAM, pos, effect->particle.dir, effect->particle.scale, false); - break; - case 1: - CParticleObject::AddObject(POBJECT_WALL_STEAM, pos, effect->particle.dir, effect->particle.scale, false); - break; - case 2: - CParticleObject::AddObject(POBJECT_DRY_ICE, pos, effect->particle.scale, false); - break; - case 3: - CParticleObject::AddObject(POBJECT_SMALL_FIRE, pos, effect->particle.dir, effect->particle.scale, false); - break; - case 4: - CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false); - break; - } - } -} - void CParticle::Shutdown() { debug("Shutting down CParticle..."); @@ -629,168 +681,145 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_SMOKE_FILES; i++ ) { RwTextureDestroy(gpSmokeTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpSmokeTex[i] = nil; -#endif } - for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ ) - { - RwTextureDestroy(gpSmoke2Tex[i]); -#if GTA_VERSION >= GTA3_PC_11 - gpSmoke2Tex[i] = nil; -#endif - } + RwTextureDestroy(gpSmoke2Tex); + gpSmoke2Tex = nil; for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ ) { RwTextureDestroy(gpRubberTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpRubberTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ ) { RwTextureDestroy(gpRainSplashTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpRainSplashTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ ) { RwTextureDestroy(gpWatersprayTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpWatersprayTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ ) { RwTextureDestroy(gpExplosionMediumTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpExplosionMediumTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ ) { RwTextureDestroy(gpGunFlashTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpGunFlashTex[i] = nil; -#endif } - for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ ) - { - RwTextureDestroy(gpRainDropTex[i]); -#if GTA_VERSION >= GTA3_PC_11 - gpRainDropTex[i] = nil; -#endif - } + RwTextureDestroy(gpRainDropTex); + gpRainDropTex = nil; for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ ) { RwTextureDestroy(gpRainSplashupTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpRainSplashupTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ ) { RwTextureDestroy(gpBirdfrontTex[i]); -#if GTA_VERSION >= GTA3_PC_11 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]); -#if GTA_VERSION >= GTA3_PC_11 gpCarDebrisTex[i] = nil; -#endif } for ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ ) { RwTextureDestroy(gpCarSplashTex[i]); -#if GTA_VERSION >= GTA3_PC_11 gpCarSplashTex[i] = nil; -#endif } + for ( int32 i = 0; i < MAX_RAINDRIP_FILES; i++ ) + { + RwTextureDestroy(gpRainDripTex[i]); + gpRainDripTex[i] = nil; + + RwTextureDestroy(gpRainDripDarkTex[i]); + gpRainDripDarkTex[i] = nil; + } + + RwTextureDestroy(gpBoatWakeTex); + gpBoatWakeTex = nil; + RwTextureDestroy(gpFlame1Tex); -#if GTA_VERSION >= GTA3_PC_11 gpFlame1Tex = nil; -#endif RwTextureDestroy(gpFlame5Tex); -#if GTA_VERSION >= GTA3_PC_11 gpFlame5Tex = nil; -#endif RwTextureDestroy(gpRainDropSmallTex); -#if GTA_VERSION >= GTA3_PC_11 gpRainDropSmallTex = nil; -#endif RwTextureDestroy(gpBloodTex); -#if GTA_VERSION >= GTA3_PC_11 gpBloodTex = nil; -#endif - RwTextureDestroy(gpLeafTex); -#if GTA_VERSION >= GTA3_PC_11 - gpLeafTex = nil; -#endif + RwTextureDestroy(gpLeafTex[0]); + gpLeafTex[0] = nil; + + RwTextureDestroy(gpLeafTex[1]); + gpLeafTex[1] = nil; RwTextureDestroy(gpCloudTex1); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex1 = nil; -#endif RwTextureDestroy(gpCloudTex4); -#if GTA_VERSION >= GTA3_PC_11 gpCloudTex4 = nil; -#endif RwTextureDestroy(gpBloodSmallTex); -#if GTA_VERSION >= GTA3_PC_11 gpBloodSmallTex = nil; -#endif RwTextureDestroy(gpGungeTex); -#if GTA_VERSION >= GTA3_PC_11 gpGungeTex = nil; -#endif RwTextureDestroy(gpCollisionSmokeTex); -#if GTA_VERSION >= GTA3_PC_11 gpCollisionSmokeTex = nil; -#endif RwTextureDestroy(gpBulletHitTex); -#if GTA_VERSION >= GTA3_PC_11 gpBulletHitTex = nil; -#endif RwTextureDestroy(gpGunShellTex); -#if GTA_VERSION >= GTA3_PC_11 gpGunShellTex = nil; -#endif - - RwTextureDestroy(gpWakeOldTex); -#if GTA_VERSION >= GTA3_PC_11 - gpWakeOldTex = nil; -#endif RwTextureDestroy(gpPointlightTex); -#if GTA_VERSION >= GTA3_PC_11 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; @@ -800,6 +829,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); @@ -809,9 +872,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 @@ -824,8 +886,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 ) @@ -846,7 +910,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; @@ -855,14 +931,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; @@ -870,7 +961,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; @@ -878,7 +969,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), @@ -895,13 +986,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 @@ -910,8 +995,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]; @@ -930,7 +1013,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 ) @@ -1054,6 +1137,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++ ) { @@ -1067,9 +1169,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 ) { @@ -1096,7 +1398,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 ) @@ -1109,16 +1411,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: @@ -1238,7 +1565,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, @@ -1246,7 +1573,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, @@ -1264,12 +1591,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; @@ -1356,16 +1683,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; } } @@ -1374,37 +1701,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 ) @@ -1448,31 +1759,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; } } } @@ -1498,13 +1806,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 @@ -1518,7 +1823,6 @@ void CParticle::Render() { particleBanned = true; } -#endif if ( particle ) { @@ -1560,11 +1864,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]; @@ -1578,28 +1881,168 @@ void CParticle::Render() if ( canDraw && psystem->Flags & DRAWTOP2D ) { - if ( particle->m_nRotation != 0 ) + float screenZ; +#ifdef FIX_BUGS + bool zIsZero = true; + if ( particle->m_vecPosition.z != 0.0f ) { +#endif + screenZ = (particle->m_vecPosition.z - CDraw::GetNearClipZ()) + * (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ()) + * CDraw::GetFarClipZ() + / ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * particle->m_vecPosition.z ) + + CSprite::GetNearScreenZ(); +#ifdef FIX_BUGS + zIsZero = false; + } +#endif + + 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; + } + +#ifdef FIX_BUGS + if (!zIsZero) { +#endif + + 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_WATER2; + else + fxtype = FXTYPE_WATER1; + + 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_BLOOD2; + else + fxtype = FXTYPE_BLOOD1; + + 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_HEATHAZE); + + 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_HEATHAZE); + + canDraw = false; + } +#ifdef FIX_BUGS + } + if ( !(zIsZero && (i == PARTICLE_WATERDROP || i == PARTICLE_BLOODDROP || i == PARTICLE_HEATHAZE_IN_DIST || i == PARTICLE_HEATHAZE) ) ) +#endif + 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; @@ -1613,174 +2056,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)); + } + + 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)); } - 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; + 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_SPLASH1); } - 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(); - - fTrailLength = fDist; + float fRotation; + float fTrailLength; - 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); } } } @@ -1812,6 +2315,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 @@ -1900,3 +2406,129 @@ 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; + } + } + } + } + +} + +void +CEntity::AddSteamsFromGround(CVector *unused) +{ + int i, n; + C2dEffect *effect; + CVector pos; + + n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects(); + for(i = 0; i < n; i++){ + effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i); + if(effect->type != EFFECT_PARTICLE) + continue; + + pos = GetMatrix() * effect->pos; + switch(effect->particle.particleType){ + case 0: + CParticleObject::AddObject(POBJECT_PAVEMENT_STEAM, pos, effect->particle.dir, effect->particle.scale, false); + break; + case 1: + CParticleObject::AddObject(POBJECT_WALL_STEAM, pos, effect->particle.dir, effect->particle.scale, false); + break; + case 2: + CParticleObject::AddObject(POBJECT_DRY_ICE, pos, effect->particle.scale, false); + break; + case 3: + CParticleObject::AddObject(POBJECT_SMALL_FIRE, pos, effect->particle.dir, effect->particle.scale, false); + break; + case 4: + CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false); + break; + case 5: + CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_VERT, pos, effect->particle.dir, effect->particle.scale, false); + break; + case 6: + CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_HORIZ, pos, effect->particle.dir, effect->particle.scale, false); + break; + } + } +} diff --git a/src/renderer/Particle.h b/src/renderer/Particle.h index 7f02e318..5542dc02 100644 --- a/src/renderer/Particle.h +++ b/src/renderer/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,18 @@ 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; +extern RwRaster *gpCarSplashRaster[]; +extern RwRaster *gpHeatHazeRaster; +extern RwRaster *gpDotRaster; +extern RwRaster *gpRainDripRaster[]; +extern RwRaster *gpRainDripDarkRaster[]; + +VALIDATE_SIZE(CParticle, 0x58); diff --git a/src/renderer/ParticleMgr.cpp b/src/renderer/ParticleMgr.cpp index 3387d471..f6919435 100644 --- a/src/renderer/ParticleMgr.cpp +++ b/src/renderer/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/renderer/ParticleMgr.h b/src/renderer/ParticleMgr.h index 0100bb65..f4afc018 100644 --- a/src/renderer/ParticleMgr.h +++ b/src/renderer/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/renderer/ParticleType.h b/src/renderer/ParticleType.h index 8d352c44..9578083d 100644 --- a/src/renderer/ParticleType.h +++ b/src/renderer/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,11 +77,16 @@ 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, - PARTICLE_LAST = PARTICLE_RAINDROP_2D + PARTICLE_LAST = PARTICLE_HEATHAZE_IN_DIST };
\ No newline at end of file diff --git a/src/renderer/PlayerSkin.cpp b/src/renderer/PlayerSkin.cpp index f0fae45a..ee944ca7 100644 --- a/src/renderer/PlayerSkin.cpp +++ b/src/renderer/PlayerSkin.cpp @@ -74,6 +74,7 @@ LoadPlayerDff(void) void CPlayerSkin::Initialise(void) { + // empty on PS2 m_txdSlot = CTxdStore::AddTxdSlot("skin"); CTxdStore::Create(m_txdSlot); CTxdStore::AddRef(m_txdSlot); @@ -82,6 +83,7 @@ CPlayerSkin::Initialise(void) void CPlayerSkin::Shutdown(void) { + // empty on PS2 CTxdStore::RemoveTxdSlot(m_txdSlot); } @@ -98,7 +100,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); @@ -110,9 +112,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); @@ -144,8 +144,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); @@ -158,8 +157,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/renderer/PointLights.cpp b/src/renderer/PointLights.cpp index 84ac4ab2..13872401 100644 --- a/src/renderer/PointLights.cpp +++ b/src/renderer/PointLights.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "main.h" +#include "CutsceneMgr.h" #include "Lights.h" #include "Camera.h" #include "Weather.h" @@ -12,6 +13,19 @@ 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,6 +156,9 @@ CPointLights::RenderFogEffect(void) CVector spriteCoors; float spritew, spriteh; + if(CCutsceneMgr::IsRunning()) + return; + PUSH_RENDERGROUP("CPointLights::RenderFogEffect"); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -150,6 +167,8 @@ CPointLights::RenderFogEffect(void) 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; @@ -220,10 +239,10 @@ CPointLights::RenderFogEffect(void) // more intensity the closer to line intensity *= 1.0f - sq(Sqrt(linedistsq) / FOG_AREA_WIDTH); - if(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)){ + 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); @@ -235,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; @@ -268,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); - if(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)){ + 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); @@ -285,5 +303,28 @@ CPointLights::RenderFogEffect(void) } } + CSprite::FlushSpriteBuffer(); + POP_RENDERGROUP(); } + +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/renderer/PointLights.h b/src/renderer/PointLights.h index 9e94328f..827200b9 100644 --- a/src/renderer/PointLights.h +++ b/src/renderer/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/renderer/RenderBuffer.cpp b/src/renderer/RenderBuffer.cpp index 6120dfe2..687cc76b 100644 --- a/src/renderer/RenderBuffer.cpp +++ b/src/renderer/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/renderer/RenderBuffer.h b/src/renderer/RenderBuffer.h index 485d24e3..a0f3e7b9 100644 --- a/src/renderer/RenderBuffer.h +++ b/src/renderer/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/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index 25effc81..49e8e611 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -9,6 +9,7 @@ #include "Vehicle.h" #include "Boat.h" #include "Heli.h" +#include "Bike.h" #include "Object.h" #include "PathFind.h" #include "Collision.h" @@ -20,17 +21,17 @@ #include "Streaming.h" #include "Shadows.h" #include "PointLights.h" +#include "Occlusion.h" #include "Renderer.h" -#include "Frontend.h" #include "custompipes.h" -#include "Debug.h" +#include "Frontend.h" bool gbShowPedRoadGroups; bool gbShowCarRoadGroups; bool gbShowCollisionPolys; +bool gbShowCollisionPolysReflections; +bool gbShowCollisionPolysNoShadows; bool gbShowCollisionLines; -bool gbShowCullZoneDebugStuff; -bool gbDisableZoneCull; // not original bool gbBigWhiteDebugLightSwitchedOn; bool gbDontRenderBuildings; @@ -39,21 +40,6 @@ bool gbDontRenderPeds; bool gbDontRenderObjects; bool gbDontRenderVehicles; -int32 EntitiesRendered; -int32 EntitiesNotRendered; -int32 RenderedBigBuildings; -int32 RenderedBuildings; -int32 RenderedCars; -int32 RenderedPeds; -int32 RenderedObjects; -int32 RenderedDummies; -int32 TestedBigBuildings; -int32 TestedBuildings; -int32 TestedCars; -int32 TestedPeds; -int32 TestedObjects; -int32 TestedDummies; - // unused int16 TestCloseThings; int16 TestBigThings; @@ -75,8 +61,6 @@ int32 CRenderer::ms_nNoOfVisibleVehicles; CEntity *CRenderer::ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES]; int32 CRenderer::ms_nNoOfVisibleBuildings; CEntity *CRenderer::ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES]; - -CLinkList<EntityInfo> gSortedBuildings; #endif CVector CRenderer::ms_vecCameraPosition; @@ -86,26 +70,20 @@ float CRenderer::ms_lodDistScale = 1.2f; // unused BlockedRange CRenderer::aBlockedRanges[16]; -BlockedRange *CRenderer::pFullBlockedRanges; -BlockedRange *CRenderer::pEmptyBlockedRanges; +BlockedRange* CRenderer::pFullBlockedRanges; +BlockedRange* CRenderer::pEmptyBlockedRanges; void CRenderer::Init(void) { gSortedVehiclesAndPeds.Init(40); SortBIGBuildings(); -#ifdef NEW_RENDERER - gSortedBuildings.Init(NUMVISIBLEENTITIES); -#endif } void CRenderer::Shutdown(void) { gSortedVehiclesAndPeds.Shutdown(); -#ifdef NEW_RENDERER - gSortedBuildings.Shutdown(); -#endif } void @@ -122,12 +100,8 @@ CRenderer::PreRender(void) for(i = 0; i < ms_nNoOfVisibleVehicles; i++) ms_aVisibleVehiclePtrs[i]->PreRender(); // How is this done with cWorldStream? - //for(i = 0; i < ms_nNoOfVisibleBuildings; i++) - // ms_aVisibleBuildingPtrs[i]->PreRender(); - for(CLink<EntityInfo> *node = gSortedBuildings.head.next; - node != &gSortedBuildings.tail; - node = node->next) - ((CEntity*)node->item.ent)->PreRender(); + for(i = 0; i < ms_nNoOfVisibleBuildings; i++) + ms_aVisibleBuildingPtrs[i]->PreRender(); for(node = CVisibilityPlugins::m_alphaBuildingList.head.next; node != &CVisibilityPlugins::m_alphaBuildingList.tail; node = node->next) @@ -154,26 +128,18 @@ CRenderer::PreRender(void) void CRenderer::RenderOneRoad(CEntity *e) { -#ifndef MASTER +#ifndef FINAL if(gbDontRenderBuildings) return; - if(gbShowCollisionPolys) +#endif +#ifndef MASTER + if(gbShowCollisionPolys || gbShowCollisionPolysReflections || gbShowCollisionPolysNoShadows) CCollision::DrawColModel_Coloured(e->GetMatrix(), *CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(), e->GetModelIndex()); else #endif { -#ifdef EXTENDED_PIPELINES - CustomPipes::AttachGlossPipe(e->GetAtomic()); -#endif PUSH_RENDERGROUP(CModelInfo::GetModelInfo(e->GetModelIndex())->GetModelName()); -#ifdef EXTRA_MODEL_FLAGS - if(!e->IsBuilding() || CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ - BACKFACE_CULLING_OFF; - e->Render(); - BACKFACE_CULLING_ON; - }else -#endif e->Render(); POP_RENDERGROUP(); @@ -189,12 +155,15 @@ CRenderer::RenderOneNonRoad(CEntity *e) bool resetLights; #ifndef MASTER - if(gbShowCollisionPolys){ + if(gbShowCollisionPolys || gbShowCollisionPolysReflections || gbShowCollisionPolysNoShadows){ if(!e->IsVehicle()){ CCollision::DrawColModel_Coloured(e->GetMatrix(), *CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(), e->GetModelIndex()); return; } - }else if(e->IsBuilding()){ + }else +#endif +#ifndef FINAL + if(e->IsBuilding()){ if(e->bIsBIGBuilding){ if(gbDontRenderBigBuildings) return; @@ -205,7 +174,7 @@ CRenderer::RenderOneNonRoad(CEntity *e) }else #endif if(e->IsPed()){ -#ifndef MASTER +#ifndef FINAL if(gbDontRenderPeds) return; #endif @@ -213,7 +182,7 @@ CRenderer::RenderOneNonRoad(CEntity *e) if(ped->m_nPedState == PED_DRIVING) return; } -#ifndef MASTER +#ifndef FINAL else if(e->IsObject() || e->IsDummy()){ if(gbDontRenderObjects) return; @@ -228,8 +197,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()){ @@ -239,23 +211,15 @@ 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(); - BACKFACE_CULLING_OFF; + SetCullMode(rwCULLMODECULLNONE); } -#ifdef EXTRA_MODEL_FLAGS - if(!e->IsBuilding() || CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ - BACKFACE_CULLING_OFF; - e->Render(); - BACKFACE_CULLING_ON; - }else -#endif e->Render(); if(e->IsVehicle()){ - BACKFACE_CULLING_OFF; e->bImBeingRendered = true; CVisibilityPlugins::RenderAlphaAtomics(); e->bImBeingRendered = false; - BACKFACE_CULLING_ON; + SetCullMode(rwCULLMODECULLBACK); } e->RemoveLighting(resetLights); @@ -278,53 +242,53 @@ CRenderer::RenderFirstPersonVehicle(void) RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); } -inline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable(); } +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; PUSH_RENDERGROUP("CRenderer::RenderRoads"); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); - BACKFACE_CULLING_ON; + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); DeActivateDirectional(); SetAmbientColours(); for(i = 0; i < ms_nNoOfVisibleEntities; i++){ - t = (CTreadable*)ms_aVisibleEntityPtrs[i]; - if(IsRoad(t)){ -#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); } POP_RENDERGROUP(); } +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) { int i; CEntity *e; - CVector dist; EntityInfo ei; PUSH_RENDERGROUP("CRenderer::RenderEverythingBarRoads"); - BACKFACE_CULLING_ON; + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); gSortedVehiclesAndPeds.Clear(); for(i = 0; i < ms_nNoOfVisibleEntities; i++){ @@ -340,14 +304,12 @@ 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(); + ei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr(); gSortedVehiclesAndPeds.InsertSorted(ei); }else{ - dist = ms_vecCameraPosition - e->GetPosition(); - if(!CVisibilityPlugins::InsertEntityIntoSortedList(e, dist.Magnitude())){ + if(!CVisibilityPlugins::InsertEntityIntoSortedList(e, (ms_vecCameraPosition - e->GetPosition()).Magnitude())){ printf("Ran out of space in alpha entity list"); RenderOneNonRoad(e); } @@ -359,37 +321,38 @@ 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; PUSH_RENDERGROUP("CRenderer::RenderBoats"); - BACKFACE_CULLING_ON; + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); + +#ifdef NEW_RENDERER + int i; + CEntity *e; + EntityInfo ei; + if(gbNewRenderer){ + gSortedVehiclesAndPeds.Clear(); + // not the real thing + for(i = 0; i < ms_nNoOfVisibleVehicles; i++){ + e = ms_aVisibleVehiclePtrs[i]; + if(e->IsVehicle() && PutIntoSortedVehicleList((CVehicle*)e)){ + ei.ent = e; + ei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr(); + gSortedVehiclesAndPeds.InsertSorted(ei); + } + } + } +#endif 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); } POP_RENDERGROUP(); } @@ -407,8 +370,6 @@ enum { PASS_BLEND // normal blend }; -static RwRGBAReal black; - static void SetStencilState(int state) { @@ -449,14 +410,6 @@ CRenderer::RenderOneBuilding(CEntity *ent, float camdist) RpAtomic *atomic = (RpAtomic*)ent->m_rwObject; CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->GetModelIndex()); -#ifdef EXTRA_MODEL_FLAGS - bool resetCull = false; - if(!ent->IsBuilding() || mi->RenderDoubleSided()){ - resetCull = true; - BACKFACE_CULLING_OFF; - } -#endif - int pass = PASS_BLEND; if(mi->m_additive) // very questionable pass = PASS_ADD; @@ -486,11 +439,6 @@ CRenderer::RenderOneBuilding(CEntity *ent, float camdist) }else WorldRender::AtomicFirstPass(atomic, pass); -#ifdef EXTRA_MODEL_FLAGS - if(resetCull) - BACKFACE_CULLING_ON; -#endif - ent->bImBeingRendered = false; // TODO: this seems wrong, but do we even need it? } @@ -502,7 +450,7 @@ CRenderer::RenderWorld(int pass) CLink<CVisibilityPlugins::AlphaObjectInfo> *node; RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); - BACKFACE_CULLING_ON; + SetCullMode(rwCULLMODECULLBACK); DeActivateDirectional(); SetAmbientColours(); @@ -512,20 +460,11 @@ CRenderer::RenderWorld(int pass) // Roads PUSH_RENDERGROUP("CRenderer::RenderWorld - Roads"); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); -/* for(i = 0; i < ms_nNoOfVisibleBuildings; i++){ e = ms_aVisibleBuildingPtrs[i]; if(e->bIsBIGBuilding || IsRoad(e)) RenderOneBuilding(e); } -*/ - for(CLink<EntityInfo> *node = gSortedBuildings.tail.prev; - node != &gSortedBuildings.head; - node = node->prev){ - e = node->item.ent; - if(e->bIsBIGBuilding || IsRoad(e)) - RenderOneBuilding(e); - } for(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev; node != &CVisibilityPlugins::m_alphaBuildingList.head; node = node->prev){ @@ -533,33 +472,17 @@ CRenderer::RenderWorld(int pass) if(e->bIsBIGBuilding || IsRoad(e)) RenderOneBuilding(e, node->item.sort); } - - // KLUDGE for road puddles which have to be rendered at road-time - // only very temporary, there are more rendering issues - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - WorldRender::RenderBlendPass(PASS_BLEND); - WorldRender::numBlendInsts[PASS_BLEND] = 0; POP_RENDERGROUP(); break; case 1: // Opaque PUSH_RENDERGROUP("CRenderer::RenderWorld - Opaque"); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); -/* for(i = 0; i < ms_nNoOfVisibleBuildings; i++){ e = ms_aVisibleBuildingPtrs[i]; if(!(e->bIsBIGBuilding || IsRoad(e))) RenderOneBuilding(e); } -*/ - for(CLink<EntityInfo> *node = gSortedBuildings.tail.prev; - node != &gSortedBuildings.head; - node = node->prev){ - e = node->item.ent; - if(!(e->bIsBIGBuilding || IsRoad(e))) - RenderOneBuilding(e); - } for(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev; node != &CVisibilityPlugins::m_alphaBuildingList.head; node = node->prev){ @@ -618,8 +541,8 @@ CRenderer::RenderVehicles(void) e = ms_aVisibleVehiclePtrs[i]; if(!e->IsVehicle()) continue; -// if(PutIntoSortedVehicleList((CVehicle*)e)) -// continue; // boats handled elsewhere + if(PutIntoSortedVehicleList((CVehicle*)e)) + continue; // boats handled elsewhere ei.ent = e; ei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr(); gSortedVehiclesAndPeds.InsertSorted(ei); @@ -633,12 +556,12 @@ CRenderer::RenderVehicles(void) } void -CRenderer::RenderWater(void) +CRenderer::RenderTransparentWater(void) { int i; CEntity *e; - PUSH_RENDERGROUP("CRenderer::RenderWater"); + PUSH_RENDERGROUP("CRenderer::RenderTransparentWater"); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); @@ -659,7 +582,7 @@ CRenderer::RenderWater(void) RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); SetStencilState(1); - CWaterLevel::RenderWater(); + CWaterLevel::RenderTransparentWater(); SetStencilState(0); POP_RENDERGROUP(); @@ -673,7 +596,6 @@ CRenderer::ClearForFrame(void) ms_nNoOfVisibleBuildings = 0; ms_nNoOfInVisibleEntities = 0; gSortedVehiclesAndPeds.Clear(); - gSortedBuildings.Clear(); WorldRender::numBlendInsts[PASS_NOZ] = 0; WorldRender::numBlendInsts[PASS_ADD] = 0; @@ -686,7 +608,8 @@ CRenderer::RenderFadingInEntities(void) { PUSH_RENDERGROUP("CRenderer::RenderFadingInEntities"); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); - BACKFACE_CULLING_ON; + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetCullMode(rwCULLMODECULLBACK); DeActivateDirectional(); SetAmbientColours(); CVisibilityPlugins::RenderFadingEntities(); @@ -694,6 +617,16 @@ CRenderer::RenderFadingInEntities(void) } void +CRenderer::RenderFadingInUnderwaterEntities(void) +{ + PUSH_RENDERGROUP("CRenderer::RenderFadingInUnderwaterEntities"); + DeActivateDirectional(); + SetAmbientColours(); + CVisibilityPlugins::RenderFadingUnderwaterEntities(); + POP_RENDERGROUP(); +} + +void CRenderer::RenderCollisionLines(void) { int i; @@ -708,14 +641,6 @@ CRenderer::RenderCollisionLines(void) } } -// unused -void -CRenderer::RenderBlockBuildingLines(void) -{ - for(BlockedRange *br = pFullBlockedRanges; br; br = br->next) - printf("Blocked: %f %f\n", br->a, br->b); -} - enum Visbility { VIS_INVISIBLE, @@ -741,7 +666,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())){ @@ -750,32 +675,44 @@ CRenderer::SetupEntityVisibility(CEntity *ent) ti->m_alpha = 255; }else{ // Hide if possible - if(CANTIMECULL) + if(CANTIMECULL){ + ent->DeleteRwObject(); return VIS_INVISIBLE; + } // 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_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(); @@ -785,22 +722,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; @@ -820,7 +773,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; } @@ -832,9 +785,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; } @@ -870,7 +824,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{ @@ -883,19 +837,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(); @@ -904,7 +871,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) @@ -912,7 +879,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()) @@ -920,7 +887,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) } } - RpAtomic *a = mi->GetAtomicFromDistance(dist); + RpAtomic *a = mi->GetFirstAtomicFromDistance(dist); if(a){ if(ent->m_rwObject == nil) ent->CreateRwObject(); @@ -931,8 +898,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->IsVisible() || !ent->GetIsOnScreenComplex()) + mi->IncreaseAlpha(); + if(!ent->IsVisible() || !ent->GetIsOnScreenComplex() || 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; @@ -948,10 +925,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... @@ -961,14 +942,20 @@ 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->IsVisible() && ent->GetIsOnScreenComplex()) - CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + mi->IncreaseAlpha(); + if(!ent->IsVisible() || !ent->GetIsOnScreenComplex() || 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(); #ifdef NEW_RENDERER if(!gbNewRenderer) #endif @@ -1027,24 +1014,6 @@ CRenderer::ScanWorld(void) RwMatrix *cammatrix; RwV2d poly[3]; -#ifndef MASTER - // missing in game but has to be done somewhere - EntitiesRendered = 0; - EntitiesNotRendered = 0; - RenderedBigBuildings = 0; - RenderedBuildings = 0; - RenderedCars = 0; - RenderedPeds = 0; - RenderedObjects = 0; - RenderedDummies = 0; - TestedBigBuildings = 0; - TestedBuildings = 0; - TestedCars = 0; - TestedPeds = 0; - TestedObjects = 0; - TestedDummies = 0; -#endif - memset(vectors, 0, sizeof(vectors)); vectors[CORNER_FAR_TOPLEFT].x = -vw.x * f; vectors[CORNER_FAR_TOPLEFT].y = vw.y * f; @@ -1065,6 +1034,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; @@ -1110,6 +1088,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); @@ -1119,7 +1098,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); @@ -1147,35 +1128,22 @@ 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)); + if (FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_HIGH) { + ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_BEACH)); + ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_MAINLAND)); } else #endif { - #ifdef FIX_BUGS - if (CCollision::ms_collisionInMemory != LEVEL_GENERIC) - #endif - ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory)); +#ifdef FIX_BUGS + if(CCollision::ms_collisionInMemory != LEVEL_GENERIC) +#endif + ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel)); } ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC)); } } - -#ifndef MASTER - if(gbShowCullZoneDebugStuff){ - sprintf(gString, "Rejected: %d/%d.", EntitiesNotRendered, EntitiesNotRendered + EntitiesRendered); - CDebug::PrintAt(gString, 10, 10); - sprintf(gString, "Tested:BBuild:%d Build:%d Peds:%d Cars:%d Obj:%d Dummies:%d", - TestedBigBuildings, TestedBuildings, TestedPeds, TestedCars, TestedObjects, TestedDummies); - CDebug::PrintAt(gString, 10, 11); - sprintf(gString, "Rendered:BBuild:%d Build:%d Peds:%d Cars:%d Obj:%d Dummies:%d", - RenderedBigBuildings, RenderedBuildings, RenderedPeds, RenderedCars, RenderedObjects, RenderedDummies); - CDebug::PrintAt(gString, 10, 12); - } -#endif } void @@ -1204,6 +1172,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 @@ -1262,8 +1231,6 @@ CRenderer::RequestObjectsInFrustum(void) bool CEntity::SetupLighting(void) { - DeActivateDirectional(); - SetAmbientColours(); return false; } @@ -1289,7 +1256,7 @@ CPed::SetupLighting(void) } else { // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0. float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition()); - if (!bHasBlip && lightMult != 1.0f) { + if (lightMult != 1.0f) { SetAmbientAndDirectionalColours(lightMult); return true; } @@ -1300,7 +1267,13 @@ CPed::SetupLighting(void) void CPed::RemoveLighting(bool reset) { - CRenderer::RemoveVehiclePedLights(this, reset); + if (!bRenderScorched) { + CRenderer::RemoveVehiclePedLights(this, reset); + if (reset) + ReSetAmbientAndDirectionalColours(); + } + SetAmbientColours(); + DeActivateDirectional(); } float @@ -1472,13 +1445,9 @@ CRenderer::InsertEntityIntoList(CEntity *ent) // TODO: there are more flags being checked here if(gbNewRenderer && (ent->IsVehicle() || ent->IsPed())) ms_aVisibleVehiclePtrs[ms_nNoOfVisibleVehicles++] = ent; - else if(gbNewRenderer && ent->IsBuilding()){ - EntityInfo info; - info.ent = ent; - info.sort = -(ent->GetPosition() - ms_vecCameraPosition).MagnitudeSqr(); - gSortedBuildings.InsertSorted(info); -// ms_aVisibleBuildingPtrs[ms_nNoOfVisibleBuildings++] = ent; - }else + else if(gbNewRenderer && ent->IsBuilding()) + ms_aVisibleBuildingPtrs[ms_nNoOfVisibleBuildings++] = ent; + else #endif ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; } @@ -1488,22 +1457,25 @@ 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; -#ifndef MASTER - // all missing from game actually - TestedBigBuildings++; -#endif - if(!ent->bZoneCulled || gbDisableZoneCull){ - if(SetupBigBuildingVisibility(ent) == VIS_VISIBLE) - InsertEntityIntoList(ent); -#ifndef MASTER - EntitiesRendered++; - RenderedBigBuildings++; - }else{ - EntitiesNotRendered++; -#endif + if(ent->bOffscreen || (ent->m_randomSeed&3) != f){ + ent->bOffscreen = true; + vis = SetupBigBuildingVisibility(ent); + }else + vis = VIS_VISIBLE; + switch(vis){ + case VIS_VISIBLE: + InsertEntityIntoList(ent); + ent->bOffscreen = false; + break; + case VIS_STREAMME: + if(!CStreaming::ms_disableStreaming) + CStreaming::RequestModel(ent->GetModelIndex(), 0); + break; } } } @@ -1524,61 +1496,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: - InsertEntityIntoList(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); - break; - } -#ifndef MASTER - EntitiesRendered++; - switch(ent->GetType()){ - case ENTITY_TYPE_BUILDING: - if(ent->bIsBIGBuilding) - RenderedBigBuildings++; - else - RenderedBuildings++; - break; - case ENTITY_TYPE_VEHICLE: - RenderedCars++; - break; - case ENTITY_TYPE_PED: - RenderedPeds++; - break; - case ENTITY_TYPE_OBJECT: - RenderedObjects++; - break; - case ENTITY_TYPE_DUMMY: - RenderedDummies++; + switch(SetupEntityVisibility(ent)){ + case VIS_VISIBLE: + InsertEntityIntoList(ent); + break; + case VIS_INVISIBLE: + if(!IsGlass(ent->GetModelIndex())) break; - } -#endif - }else if(IsRoad(ent) && !CStreaming::ms_disableStreaming){ - if(SetupEntityVisibility(ent) == VIS_STREAMME) + // 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(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) CStreaming::RequestModel(ent->GetModelIndex(), 0); - }else{ -#ifndef MASTER - EntitiesNotRendered++; -#endif + break; } } } @@ -1600,69 +1541,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: - InsertEntityIntoList(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; - } - break; - } -#ifndef MASTER - // actually missing in game - EntitiesRendered++; - switch(ent->GetType()){ - case ENTITY_TYPE_BUILDING: - if(ent->bIsBIGBuilding) - RenderedBigBuildings++; - else - RenderedBuildings++; - break; - case ENTITY_TYPE_VEHICLE: - RenderedCars++; - break; - case ENTITY_TYPE_PED: - RenderedPeds++; - break; - case ENTITY_TYPE_OBJECT: - RenderedObjects++; - break; - case ENTITY_TYPE_DUMMY: - RenderedDummies++; + switch(SetupEntityVisibility(ent)){ + case VIS_VISIBLE: + InsertEntityIntoList(ent); + break; + case VIS_INVISIBLE: + if(!IsGlass(ent->GetModelIndex())) break; - } -#endif - }else if(IsRoad(ent) && !CStreaming::ms_disableStreaming){ - if(SetupEntityVisibility(ent) == VIS_STREAMME) + // 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); - }else{ -#ifndef MASTER - // actually missing in game - EntitiesNotRendered++; -#endif + if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED) + m_loadingPriority = true; + } + break; } } } } +#ifdef GTA_TRAIN void CRenderer::ScanSectorList_Subway(CPtrList *lists) { @@ -1679,15 +1589,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: InsertEntityIntoList(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; @@ -1695,6 +1607,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists) } } } +#endif void CRenderer::ScanSectorList_RequestModels(CPtrList *lists) @@ -1711,8 +1624,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); } } @@ -1747,95 +1659,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(gbDisableZoneCull) return true; - -#ifndef MASTER - switch(ent->GetType()){ - case ENTITY_TYPE_BUILDING: - if(ent->bIsBIGBuilding) - TestedBigBuildings++; - else - TestedBuildings++; - break; - case ENTITY_TYPE_VEHICLE: - TestedCars++; - break; - case ENTITY_TYPE_PED: - TestedPeds++; - break; - case ENTITY_TYPE_OBJECT: - TestedObjects++; - break; - case ENTITY_TYPE_DUMMY: - TestedDummies++; - break; - } -#endif - 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/renderer/Renderer.h b/src/renderer/Renderer.h index 0322939c..9b202098 100644 --- a/src/renderer/Renderer.h +++ b/src/renderer/Renderer.h @@ -10,20 +10,10 @@ class CEntity; #define FADE_DISTANCE 20.0f #define STREAM_DISTANCE 30.0f -#ifdef EXTRA_MODEL_FLAGS -#define BACKFACE_CULLING_ON SetCullMode(rwCULLMODECULLBACK) -#define BACKFACE_CULLING_OFF SetCullMode(rwCULLMODECULLNONE) -#else -#define BACKFACE_CULLING_ON -#define BACKFACE_CULLING_OFF -#endif - extern bool gbShowPedRoadGroups; extern bool gbShowCarRoadGroups; extern bool gbShowCollisionPolys; extern bool gbShowCollisionLines; -extern bool gbShowCullZoneDebugStuff; -extern bool gbDisableZoneCull; // not original extern bool gbBigWhiteDebugLightSwitchedOn; extern bool gbDontRenderBuildings; @@ -73,16 +63,14 @@ 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 *); static void RenderFirstPersonVehicle(void); static void RenderCollisionLines(void); - // unused - static void RenderBlockBuildingLines(void); static int32 SetupEntityVisibility(CEntity *ent); static int32 SetupBigBuildingVisibility(CEntity *ent); @@ -100,9 +88,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); @@ -113,7 +99,7 @@ public: static void RenderVehicles(void); // also renders peds in LCS static void RenderOneBuilding(CEntity *ent, float camdist = 0.0f); static void RenderWorld(int pass); // like cWorldStream::Render(int) - static void RenderWater(void); // keep-out polys and water + static void RenderTransparentWater(void); // keep-out polys and transparent water #endif static void InsertEntityIntoList(CEntity *ent); }; diff --git a/src/renderer/Rubbish.cpp b/src/renderer/Rubbish.cpp index 8da6b025..147c97b1 100644 --- a/src/renderer/Rubbish.cpp +++ b/src/renderer/Rubbish.cpp @@ -8,17 +8,16 @@ #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) +#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,6 +51,9 @@ CRubbish::Render(void) { int type; + if(RubbishVisibility == 0) + return; + PUSH_RENDERGROUP("CRubbish::Render"); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -59,7 +61,8 @@ CRubbish::Render(void) 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; @@ -71,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; @@ -84,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); } } @@ -94,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); @@ -377,24 +390,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; @@ -418,19 +413,11 @@ void CRubbish::Shutdown(void) { RwTextureDestroy(gpRubbishTexture[0]); -#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[0] = nil; -#endif RwTextureDestroy(gpRubbishTexture[1]); -#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[1] = nil; -#endif RwTextureDestroy(gpRubbishTexture[2]); -#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[2] = nil; -#endif RwTextureDestroy(gpRubbishTexture[3]); -#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[3] = nil; -#endif } diff --git a/src/renderer/Rubbish.h b/src/renderer/Rubbish.h index 37f895f3..5a4e479b 100644 --- a/src/renderer/Rubbish.h +++ b/src/renderer/Rubbish.h @@ -53,3 +53,5 @@ public: static void Init(void); static void Shutdown(void); }; + +extern RwTexture *gpRubbishTexture[4]; diff --git a/src/renderer/ShadowCamera.cpp b/src/renderer/ShadowCamera.cpp new file mode 100644 index 00000000..f69c234f --- /dev/null +++ b/src/renderer/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/renderer/ShadowCamera.h b/src/renderer/ShadowCamera.h new file mode 100644 index 00000000..a2149db7 --- /dev/null +++ b/src/renderer/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/renderer/Shadows.cpp b/src/renderer/Shadows.cpp index 3884d3bb..dd87bff6 100644 --- a/src/renderer/Shadows.cpp +++ b/src/renderer/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,13 @@ #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" +#include "VarConsole.h" #ifdef DEBUGMENU //SETTWEAKPATH("Shadows"); @@ -30,6 +37,8 @@ RwImVertexIndex ShadowIndexList[24]; RwTexture *gpShadowCarTex; RwTexture *gpShadowPedTex; RwTexture *gpShadowHeliTex; +RwTexture *gpShadowBikeTex; +RwTexture *gpShadowBaronTex; RwTexture *gpShadowExplosionTex; RwTexture *gpShadowHeadLightsTex; RwTexture *gpOutline1Tex; @@ -37,7 +46,6 @@ RwTexture *gpOutline2Tex; RwTexture *gpOutline3Tex; RwTexture *gpBloodPoolTex; RwTexture *gpReflectionTex; -RwTexture *gpGoalMarkerTex; RwTexture *gpWalkDontTex; RwTexture *gpCrackedGlassTex; RwTexture *gpPostShadowTex; @@ -50,6 +58,9 @@ CStaticShadow CShadows::aStaticShadows [MAX_STATICSHADOWS]; CPolyBunch *CShadows::pEmptyBunchList; CPermanentShadow CShadows::aPermanentShadows[MAX_PERMAMENTSHADOWS]; +#ifndef MASTER +bool gbCountPolysInShadow; +#endif void CShadows::Init(void) @@ -59,37 +70,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 +141,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 +149,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]; } @@ -145,29 +158,36 @@ CShadows::Init(void) { aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; } + +#ifndef MASTER + VarConsole.Add("Count polys in shadow", &gbCountPolysInShadow, true); +#endif } 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 +195,6 @@ CShadows::Shutdown(void) RwTextureDestroy(gpOutline3Tex); RwTextureDestroy(gpBloodPoolTex); RwTextureDestroy(gpReflectionTex); - RwTextureDestroy(gpGoalMarkerTex); RwTextureDestroy(gpWalkDontTex); RwTextureDestroy(gpCrackedGlassTex); RwTextureDestroy(gpPostShadowTex); @@ -187,8 +206,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 +234,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 +285,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 +308,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 +334,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 +365,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 +379,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 +393,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 +403,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 +413,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 +423,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 +433,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 +442,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 +456,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 +498,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 +521,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 +756,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 +888,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 +897,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 +920,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 +1001,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 +1064,7 @@ CShadows::SetRenderModeForShadowType(uint8 ShadowType) } } + void CShadows::RenderStoredShadows(void) { @@ -694,17 +1075,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)); @@ -736,39 +1120,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); + } } } @@ -778,18 +1235,19 @@ CShadows::RenderStoredShadows(void) RenderBuffer::RenderStuffInBuffer(); } - } RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSWRAP); ShadowsStoredToBeRendered = 0; POP_RENDERGROUP(); } + void CShadows::RenderStaticShadows(void) { @@ -817,19 +1275,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++ ) { @@ -865,6 +1323,7 @@ CShadows::RenderStaticShadows(void) POP_RENDERGROUP(); } + void CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) { @@ -891,7 +1350,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, @@ -922,50 +1381,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->bDontCastShadowsOn) { - 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); + } + } + } + } + } + } +} - Bound = pEntity->GetBoundRect(); - if ( fStartX < Bound.right - && fEndX > Bound.left - && fStartY < Bound.bottom - && fEndY > Bound.top ) +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; + + ASSERT( pEntity != nil ); + + 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); + } } } } @@ -973,21 +1491,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 ) @@ -1033,14 +1604,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; @@ -1440,12 +2011,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; @@ -1470,8 +2041,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++ ) @@ -1495,12 +2066,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, ¢er, 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(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(); @@ -1523,13 +2304,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, @@ -1546,7 +2328,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, @@ -1561,6 +2343,9 @@ CShadows::UpdatePermanentShadows(void) aPermanentShadows[i].m_fZDistance, 1.0f, 40.0f, false, 0.0f); } + + if ( !bOk ) + aPermanentShadows[i].m_nType = SHADOWTYPE_NONE; } } } @@ -1569,19 +2354,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; } @@ -1625,6 +2410,7 @@ CShadows::CalcPedShadowValues(CVector vecLightDir, } + void CShadows::RenderExtraPlayerShadows(void) { @@ -1635,64 +2421,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++ ) { @@ -1745,7 +2480,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 { @@ -1755,7 +2490,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); } } } @@ -1777,9 +2512,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/renderer/Shadows.h b/src/renderer/Shadows.h index 8c909df3..937ff4eb 100644 --- a/src/renderer/Shadows.h +++ b/src/renderer/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/renderer/Skidmarks.cpp b/src/renderer/Skidmarks.cpp index 4c662a79..08df330d 100644 --- a/src/renderer/Skidmarks.cpp +++ b/src/renderer/Skidmarks.cpp @@ -11,8 +11,6 @@ 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 +20,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 +37,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); -#if GTA_VERSION >= GTA3_PC_11 gpSkidTex = nil; -#endif - RwTextureDestroy(gpSkidBloodTex); -#if GTA_VERSION >= GTA3_PC_11 - gpSkidBloodTex = nil; -#endif - RwTextureDestroy(gpSkidMudTex); -#if GTA_VERSION >= GTA3_PC_11 - gpSkidMudTex = nil; -#endif } void @@ -116,7 +95,6 @@ void CSkidmarks::Render(void) { int i, j; - RwTexture *lastTex = nil; PUSH_RENDERGROUP("CSkidmarks::Render"); @@ -124,26 +102,18 @@ CSkidmarks::Render(void) 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; @@ -158,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(); @@ -181,7 +159,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); @@ -197,7 +188,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; @@ -229,13 +220,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 @@ -251,12 +245,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/renderer/Skidmarks.h b/src/renderer/Skidmarks.h index c061782d..28082f08 100644 --- a/src/renderer/Skidmarks.h +++ b/src/renderer/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/renderer/SpecialFX.cpp b/src/renderer/SpecialFX.cpp index 6d96d21a..61750f85 100644 --- a/src/renderer/SpecialFX.cpp +++ b/src/renderer/SpecialFX.cpp @@ -21,12 +21,24 @@ #include "Camera.h" #include "Shadows.h" #include "main.h" +#include "ColStore.h" +#include "Coronas.h" +#include "Script.h" +#include "DMAudio.h" RwIm3DVertex StreakVertices[4]; RwImVertexIndex StreakIndexList[12]; -RwIm3DVertex TraceVertices[6]; -RwImVertexIndex TraceIndexList[12]; +RwIm3DVertex TraceVertices[10]; +static RwImVertexIndex TraceIndexList[48] = {0, 5, 7, 0, 7, 2, 0, 7, 5, 0, 2, 7, 0, 4, 9, 0, + 9, 5, 0, 9, 4, 0, 5, 9, 0, 1, 6, 0, 6, 5, 0, 6, + 1, 0, 5, 6, 0, 3, 8, 0, 8, 5, 0, 8, 3, 0, 5, 8 }; + +bool CSpecialFX::bVideoCam; +bool CSpecialFX::bLiftCam; +bool CSpecialFX::bSnapShotActive; +int32 CSpecialFX::SnapShotFrames; +static RwTexture* gpSmokeTrailTexture; void @@ -34,6 +46,22 @@ CSpecialFX::Init(void) { CBulletTraces::Init(); + RwIm3DVertexSetU(&TraceVertices[0], 0.0); + RwIm3DVertexSetV(&TraceVertices[0], 0.0); + RwIm3DVertexSetU(&TraceVertices[1], 1.0); + RwIm3DVertexSetV(&TraceVertices[1], 0.0); + RwIm3DVertexSetU(&TraceVertices[2], 1.0); + RwIm3DVertexSetV(&TraceVertices[2], 0.0); + RwIm3DVertexSetU(&TraceVertices[3], 1.0); + RwIm3DVertexSetV(&TraceVertices[3], 0.0); + RwIm3DVertexSetU(&TraceVertices[4], 1.0); + RwIm3DVertexSetV(&TraceVertices[4], 0.0); + RwIm3DVertexSetU(&TraceVertices[5], 0.0); + RwIm3DVertexSetU(&TraceVertices[6], 1.0); + RwIm3DVertexSetU(&TraceVertices[7], 1.0); + RwIm3DVertexSetU(&TraceVertices[8], 1.0); + RwIm3DVertexSetU(&TraceVertices[9], 1.0); + RwIm3DVertexSetU(&StreakVertices[0], 0.0f); RwIm3DVertexSetV(&StreakVertices[0], 0.0f); RwIm3DVertexSetU(&StreakVertices[1], 1.0f); @@ -42,7 +70,6 @@ CSpecialFX::Init(void) RwIm3DVertexSetV(&StreakVertices[2], 0.0f); RwIm3DVertexSetU(&StreakVertices[3], 1.0f); RwIm3DVertexSetV(&StreakVertices[3], 0.0f); - StreakIndexList[0] = 0; StreakIndexList[1] = 1; StreakIndexList[2] = 2; @@ -56,43 +83,51 @@ CSpecialFX::Init(void) StreakIndexList[10] = 2; StreakIndexList[11] = 3; - RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255); - RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255); - RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255); - RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255); - RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255); - RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255); - RwIm3DVertexSetU(&TraceVertices[0], 0.0); - RwIm3DVertexSetV(&TraceVertices[0], 0.0); - RwIm3DVertexSetU(&TraceVertices[1], 1.0); - RwIm3DVertexSetV(&TraceVertices[1], 0.0); - RwIm3DVertexSetU(&TraceVertices[2], 0.0); - RwIm3DVertexSetV(&TraceVertices[2], 0.5); - RwIm3DVertexSetU(&TraceVertices[3], 1.0); - RwIm3DVertexSetV(&TraceVertices[3], 0.5); - RwIm3DVertexSetU(&TraceVertices[4], 0.0); - RwIm3DVertexSetV(&TraceVertices[4], 1.0); - RwIm3DVertexSetU(&TraceVertices[5], 1.0); - RwIm3DVertexSetV(&TraceVertices[5], 1.0); - - TraceIndexList[0] = 0; - TraceIndexList[1] = 2; - TraceIndexList[2] = 1; - TraceIndexList[3] = 1; - TraceIndexList[4] = 2; - TraceIndexList[5] = 3; - TraceIndexList[6] = 2; - TraceIndexList[7] = 4; - TraceIndexList[8] = 3; - TraceIndexList[9] = 3; - TraceIndexList[10] = 4; - TraceIndexList[11] = 5; - CMotionBlurStreaks::Init(); CBrightLights::Init(); CShinyTexts::Init(); CMoneyMessages::Init(); C3dMarkers::Init(); + CSpecialFX::bSnapShotActive = false; + CSpecialFX::bVideoCam = false; + CSpecialFX::SnapShotFrames = 0; + CSpecialFX::bLiftCam = false; + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("particle")); + if(gpSmokeTrailTexture == nil) + gpSmokeTrailTexture = RwTextureRead("smoketrail", 0); + CTxdStore::PopCurrentTxd(); +} + +void +CSpecialFX::AddWeaponStreak(int type) +{ + static CMatrix matrix; + CVector start; + CVector end; + + if (FindPlayerPed() != nil && FindPlayerPed()->m_pWeaponModel != nil) { + switch (type) { + case WEAPONTYPE_BASEBALLBAT: + matrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel)); + start = matrix * CVector(0.02f, 0.05f, 0.07f); + end = matrix * CVector(0.246f, 0.0325f, 0.796f); + break; + case WEAPONTYPE_GOLFCLUB: + matrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel)); + start = matrix * CVector(0.02f, 0.05f, 0.07f); + end = matrix * CVector(-0.054f, 0.0325f, 0.796f); + break; + case WEAPONTYPE_KATANA: + matrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel)); + start = matrix * CVector(0.02f, 0.05f, 0.07f); + end = matrix * CVector(0.096f, -0.0175f, 1.096f); + break; + default: + return; + } + CMotionBlurStreaks::RegisterStreak((uintptr)FindPlayerPed()->m_pWeaponModel, 100, 100, 100, start, end); + } } RwObject* @@ -114,23 +149,16 @@ CSpecialFX::Update(void) { CMotionBlurStreaks::Update(); CBulletTraces::Update(); - - if(FindPlayerPed() && - FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && - FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING){ -#ifdef PED_SKIN - if(IsClumpSkinned(FindPlayerPed()->GetClump())){ - LookForBatCB((RwObject*)FindPlayerPed()->m_pWeaponModel, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); - }else -#endif - RwFrameForAllObjects(FindPlayerPed()->m_pFrames[PED_HANDR]->frame, LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); - } } void CSpecialFX::Shutdown(void) { C3dMarkers::Shutdown(); + if (gpSmokeTrailTexture) { + RwTextureDestroy(gpSmokeTrailTexture); + gpSmokeTrailTexture = nil; + } } void @@ -149,6 +177,79 @@ CSpecialFX::Render(void) POP_RENDERGROUP(); } +void +CSpecialFX::Render2DFXs(void) +{ + if (CSpecialFX::bVideoCam) { + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetJustifyOff(); + CFont::SetBackgroundOff(); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); // unused + CFont::SetCentreOff(); + CFont::SetPropOn(); + CFont::SetColor(CRGBA(0, 255, 0, 200)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + sprintf(gString, "%d", CTimer::GetFrameCounter() & 0x3F); // mb % 63 + AsciiToUnicode(gString, gUString); + CFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString); + for (int32 i = 0; i < SCREEN_HEIGHT; i += 4) { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE); + CSprite2d::Draw2DPolygon(0.0f, i, SCREEN_WIDTH, i, 0.0f, i+1, SCREEN_WIDTH, i+1, CRGBA(0, 100, 0, 100)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0f, i+2, SCREEN_WIDTH, i+2, 0.0f, i+3, SCREEN_WIDTH, i+3, CRGBA(0, 0, 0, 150)); + } + int32 tmp = (CTimer::GetTimeInMilliseconds() & 0x7ff) * (SCREEN_HEIGHT + 70.0f) / 2048 - 70.0f; //mb % 2048 + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0, tmp, SCREEN_WIDTH, tmp, 0.0, tmp + 70.0f, SCREEN_WIDTH, tmp + 70.0f , CRGBA(0, 100, 0, 60)); + } + if (CSpecialFX::bLiftCam) { + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetJustifyOff(); + CFont::SetBackgroundOff(); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); // unused + CFont::SetCentreOff(); + CFont::SetPropOn(); + CFont::SetColor(CRGBA(100, 100, 100, 200)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + for (int32 i = 0; i < SCREEN_HEIGHT; i += 4) { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + CSprite2d::Draw2DPolygon(0.0f, i, SCREEN_WIDTH, i, 0.0f, i + 1, SCREEN_WIDTH, i + 1, CRGBA(100, 100, 100, 100)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0f, i + 2, SCREEN_WIDTH, i + 2, 0.0f, i + 3, SCREEN_WIDTH, i + 3, CRGBA(0, 0, 0, 150)); + } + int32 tmp = (CTimer::GetTimeInMilliseconds() & 0x7ff) * (SCREEN_HEIGHT + 70.0f) / 2048 - 70.0f; //mb % 2048 + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0, tmp, SCREEN_WIDTH, tmp, 0.0, tmp + 70.0f, SCREEN_WIDTH, tmp + 70.0f, CRGBA(100, 100, 100, 60)); + for (int32 i = 0; i < 200; i++) { + int32 posX = CGeneral::GetRandomNumber() % (int32)SCREEN_WIDTH; + int32 posY = CGeneral::GetRandomNumber() % (int32)SCREEN_HEIGHT; + CSprite2d::DrawRect(CRect(posX, posY + 2, posX+20, posY), CRGBA(255, 255, 255, 64)); + } + } + if (CSpecialFX::bSnapShotActive) { + if (++CSpecialFX::SnapShotFrames > 20) { + CSpecialFX::bSnapShotActive = false; + CTimer::SetTimeScale(1.0f); + } else { + CTimer::SetTimeScale(0.0f); //in andro it's 0.00001 + if (CSpecialFX::SnapShotFrames < 10) { + int32 tmp = (255 - 255 * CSpecialFX::SnapShotFrames / 10) * 0.65f; + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + CSprite2d::Draw2DPolygon(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, 0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, CRGBA(tmp, tmp, tmp, tmp)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + } + } + } +} + CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS]; void @@ -217,6 +318,7 @@ void CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { int i; + for(i = 0; i < NUMMBLURSTREAKS; i++){ if(aStreaks[i].m_id == id){ // Found a streak from last frame, update @@ -229,10 +331,12 @@ CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVecto return; } } + // Find free slot - for(i = 0; aStreaks[i].m_id != 0; i++) + for(i = 0; aStreaks[i].m_id != 0 ; i++) if(i == NUMMBLURSTREAKS-1) return; + // Create a new streak aStreaks[i].m_id = id; aStreaks[i].m_red = r; @@ -281,20 +385,103 @@ void CBulletTraces::Init(void) aTraces[i].m_bInUse = false; } -void CBulletTraces::AddTrace(CVector* vecStart, CVector* vecTarget) +void CBulletTraces::AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility) { - int index; - for (index = 0; index < NUMBULLETTRACES; index++) { - if (!aTraces[index].m_bInUse) - break; + int32 enabledCount; + uint32 modifiedLifeTime; + int32 nextSlot; + + enabledCount = 0; + for (int i = 0; i < NUMBULLETTRACES; i++) + if (aTraces[i].m_bInUse) + enabledCount++; + if (enabledCount >= 10) + modifiedLifeTime = lifeTime / 4; + else if (enabledCount >= 5) + modifiedLifeTime = lifeTime / 2; + else + modifiedLifeTime = lifeTime; + + nextSlot = 0; + for (int i = 0; nextSlot < NUMBULLETTRACES && aTraces[i].m_bInUse; i++) + nextSlot++; + if (nextSlot < 16) { + aTraces[nextSlot].m_vecStartPos = *start; + aTraces[nextSlot].m_vecEndPos = *end; + aTraces[nextSlot].m_bInUse = true; + aTraces[nextSlot].m_nCreationTime = CTimer::GetTimeInMilliseconds(); + aTraces[nextSlot].m_fVisibility = visibility; + aTraces[nextSlot].m_fThickness = thickness; + aTraces[nextSlot].m_nLifeTime = modifiedLifeTime; + } + + float startProjFwd = DotProduct(TheCamera.GetForward(), *start - TheCamera.GetPosition()); + float endProjFwd = DotProduct(TheCamera.GetForward(), *end - TheCamera.GetPosition()); + if (startProjFwd * endProjFwd < 0.0f) { //if one of point behind us and second before us + float fStartDistFwd = Abs(startProjFwd) / (Abs(startProjFwd) + Abs(endProjFwd)); + + float startProjUp = DotProduct(TheCamera.GetUp(), *start - TheCamera.GetPosition()); + float endProjUp = DotProduct(TheCamera.GetUp(), *end - TheCamera.GetPosition()); + float distUp = (endProjUp - startProjUp) * fStartDistFwd + startProjUp; + + float startProjRight = DotProduct(TheCamera.GetRight(), *start - TheCamera.GetPosition()); + float endProjRight = DotProduct(TheCamera.GetRight(), *end - TheCamera.GetPosition()); + float distRight = (endProjRight - startProjRight) * fStartDistFwd + startProjRight; + + float dist = Sqrt(SQR(distUp) + SQR(distRight)); + if (dist < 2.0f) { + if(distRight < 0.0f) + DMAudio.PlayFrontEndSound(SOUND_BULLETTRACE_2, 127 * (1.0f - dist * 0.5f)); + else + DMAudio.PlayFrontEndSound(SOUND_BULLETTRACE_1, 127 * (1.0f - dist * 0.5f)); + } + } +} + +void CBulletTraces::AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter) +{ + CPhysical* player; + float speed; + int16 camMode; + + if (shooter == (CEntity*)FindPlayerPed() || (FindPlayerVehicle() != nil && FindPlayerVehicle() == (CVehicle*)shooter)) { + camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (camMode == CCam::MODE_M16_1STPERSON + || camMode == CCam::MODE_CAMERA + || camMode == CCam::MODE_SNIPER + || camMode == CCam::MODE_M16_1STPERSON_RUNABOUT + || camMode == CCam::MODE_ROCKETLAUNCHER + || camMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT + || camMode == CCam::MODE_SNIPER_RUNABOUT + || camMode == CCam::MODE_HELICANNON_1STPERSON) { + + player = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed(); + speed = player->m_vecMoveSpeed.Magnitude(); + if (speed < 0.05f) + return; + } + } + + switch (weaponType) { + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + CBulletTraces::AddTrace(start, end, 0.7f, 1000, 200); + break; + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_HELICANNON: + CBulletTraces::AddTrace(start, end, 1.0f, 2000, 220); + break; + default: + CBulletTraces::AddTrace(start, end, 0.4f, 750, 150); + break; } - if (index == NUMBULLETTRACES) - return; - aTraces[index].m_vecCurrentPos = *vecStart; - aTraces[index].m_vecTargetPos = *vecTarget; - aTraces[index].m_bInUse = true; - aTraces[index].m_framesInUse = 0; - aTraces[index].m_lifeTime = 25 + CGeneral::GetRandomNumber() % 32; } void CBulletTraces::Render(void) @@ -303,31 +490,131 @@ void CBulletTraces::Render(void) if (!aTraces[i].m_bInUse) continue; RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSmokeTrailTexture)); + + float timeAlive = CTimer::GetTimeInMilliseconds() - aTraces[i].m_nCreationTime; + + float traceThickness = aTraces[i].m_fThickness * timeAlive / aTraces[i].m_nLifeTime; + CVector horizontalOffset = aTraces[i].m_vecEndPos - aTraces[i].m_vecStartPos; + horizontalOffset.Normalise(); + horizontalOffset *= traceThickness; + + //then closer trace to die then it more transparent + uint8 nAlphaValue = aTraces[i].m_fVisibility * (aTraces[i].m_nLifeTime - timeAlive) / aTraces[i].m_nLifeTime; + + CVector start = aTraces[i].m_vecStartPos; + CVector end = aTraces[i].m_vecEndPos; + float startProj = DotProduct(start - TheCamera.GetPosition(), TheCamera.GetForward()) - 0.7f; + float endProj = DotProduct(end - TheCamera.GetPosition(), TheCamera.GetForward()) - 0.7f; + if (startProj < 0.0f && endProj < 0.0f) //we dont need render trace behind us + continue; + + if (startProj < 0.0f) { //if strat behind us move it closer + float absStartProj = Abs(startProj); + float absEndProj = Abs(endProj); + start = (absEndProj * start + absStartProj * end) / (absStartProj + absEndProj); + } else if (endProj < 0.0f) { + float absStartProj = Abs(startProj); + float absEndProj = Abs(endProj); + end = (absEndProj * start + absStartProj * end) / (absStartProj + absEndProj); + } + + //we divide trace at three parts + CVector start2 = (7.0f * start + end) / 8; + CVector end2 = (7.0f * end + start) / 8; + + RwIm3DVertexSetV(&TraceVertices[5], 10.0f); + RwIm3DVertexSetV(&TraceVertices[6], 10.0f); + RwIm3DVertexSetV(&TraceVertices[7], 10.0f); + RwIm3DVertexSetV(&TraceVertices[8], 10.0f); + RwIm3DVertexSetV(&TraceVertices[9], 10.0f); + + RwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[5], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[6], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[7], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[8], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[9], 255, 255, 255, nAlphaValue); + //two points in center + RwIm3DVertexSetPos(&TraceVertices[0], start2.x, start2.y, start2.z); + RwIm3DVertexSetPos(&TraceVertices[5], end2.x, end2.y, end2.z); + //vertical planes + RwIm3DVertexSetPos(&TraceVertices[1], start2.x, start2.y, start2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[3], start2.x, start2.y, start2.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[6], end2.x, end2.y, end2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[8], end2.x, end2.y, end2.z - traceThickness); + //horizontal planes + RwIm3DVertexSetPos(&TraceVertices[2], start2.x + horizontalOffset.y, start2.y - horizontalOffset.x, start2.z); + RwIm3DVertexSetPos(&TraceVertices[7], end2.x + horizontalOffset.y, end2.y - horizontalOffset.x, end2.z); +#ifdef FIX_BUGS //this point calculated wrong for some reason + RwIm3DVertexSetPos(&TraceVertices[4], start2.x - horizontalOffset.y, start2.y + horizontalOffset.x, start2.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y + horizontalOffset.x, end2.z); +#else + RwIm3DVertexSetPos(&TraceVertices[4], start2.x - horizontalOffset.y, start2.y - horizontalOffset.y, start2.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y - horizontalOffset.y, end2.z); +#endif + + if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, 1)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); + RwIm3DEnd(); + } + + RwIm3DVertexSetV(&TraceVertices[5], 2.0f); + RwIm3DVertexSetV(&TraceVertices[6], 2.0f); + RwIm3DVertexSetV(&TraceVertices[7], 2.0f); + RwIm3DVertexSetV(&TraceVertices[8], 2.0f); + RwIm3DVertexSetV(&TraceVertices[9], 2.0f); + RwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, 0); + + RwIm3DVertexSetPos(&TraceVertices[0], start.x, start.y, start.z); + RwIm3DVertexSetPos(&TraceVertices[1], start.x, start.y, start.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[3], start.x, start.y, start.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[2], start.x + horizontalOffset.y, start.y - horizontalOffset.x, start.z); + + RwIm3DVertexSetPos(&TraceVertices[5], start2.x, start2.y, start2.z); + RwIm3DVertexSetPos(&TraceVertices[6], start2.x, start2.y, start2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[8], start2.x, start2.y, start2.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[7], start2.x + horizontalOffset.y, start2.y - horizontalOffset.x, start2.z); #ifdef FIX_BUGS - // Raster has no transparent pixels so it relies on the raster format having alpha - // to turn on blending. librw image conversion might get rid of it right now so let's - // just force it on. - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwIm3DVertexSetPos(&TraceVertices[4], start.x - horizontalOffset.y, start.y + horizontalOffset.x, start.z); + RwIm3DVertexSetPos(&TraceVertices[9], start2.x - horizontalOffset.y, start2.y + horizontalOffset.x, start2.z); +#else + RwIm3DVertexSetPos(&TraceVertices[4], start.x - horizontalOffset.y, start.y - horizontalOffset.y, start.z); + RwIm3DVertexSetPos(&TraceVertices[9], start2.x - horizontalOffset.y, start2.y - horizontalOffset.y, start2.z); #endif - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex)); - CVector inf = aTraces[i].m_vecCurrentPos; - CVector sup = aTraces[i].m_vecTargetPos; - CVector center = (inf + sup) / 2; - CVector width = CrossProduct(TheCamera.GetForward(), (sup - inf)); - width.Normalise(); - width /= 20; - uint8 intensity = aTraces[i].m_lifeTime; - for (int i = 0; i < ARRAY_SIZE(TraceVertices); i++) - RwIm3DVertexSetRGBA(&TraceVertices[i], intensity, intensity, intensity, 0xFF); - RwIm3DVertexSetPos(&TraceVertices[0], inf.x + width.x, inf.y + width.y, inf.z + width.z); - RwIm3DVertexSetPos(&TraceVertices[1], inf.x - width.x, inf.y - width.y, inf.z - width.z); - RwIm3DVertexSetPos(&TraceVertices[2], center.x + width.x, center.y + width.y, center.z + width.z); - RwIm3DVertexSetPos(&TraceVertices[3], center.x - width.x, center.y - width.y, center.z - width.z); - RwIm3DVertexSetPos(&TraceVertices[4], sup.x + width.x, sup.y + width.y, sup.z + width.z); - RwIm3DVertexSetPos(&TraceVertices[5], sup.x - width.x, sup.y - width.y, sup.z - width.z); - LittleTest(); + + if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); + RwIm3DEnd(); + } + + RwIm3DVertexSetPos(&TraceVertices[1], end.x, end.y, end.z); + RwIm3DVertexSetPos(&TraceVertices[2], end.x, end.y, end.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[4], end.x, end.y, end.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[3], end.x + horizontalOffset.y, end.y - horizontalOffset.x, end.z); + + RwIm3DVertexSetPos(&TraceVertices[5], end2.x, end2.y, end2.z); + RwIm3DVertexSetPos(&TraceVertices[6], end2.x, end2.y, end2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[8], end2.x, end2.y, end2.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[7], end2.x + horizontalOffset.y, end2.y - horizontalOffset.x, end2.z); +#ifdef FIX_BUGS + RwIm3DVertexSetPos(&TraceVertices[5], end.x - horizontalOffset.y, end.y + horizontalOffset.x, end.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y + horizontalOffset.x, end2.z); +#else + RwIm3DVertexSetPos(&TraceVertices[5], end.x - horizontalOffset.y, end.y - horizontalOffset.y, end.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y - horizontalOffset.y, end2.z); +#endif + if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); RwIm3DEnd(); @@ -348,23 +635,8 @@ void CBulletTraces::Update(void) void CBulletTrace::Update(void) { - if (m_framesInUse == 0) { - m_framesInUse++; - return; - } - if (m_framesInUse > 60) { + if (CTimer::GetTimeInMilliseconds() - m_nCreationTime >= m_nLifeTime) m_bInUse = false; - return; - } - CVector diff = m_vecCurrentPos - m_vecTargetPos; - float remaining = diff.Magnitude(); - if (remaining > 0.8f) - m_vecCurrentPos = m_vecTargetPos + (remaining - 0.8f) / remaining * diff; - else - m_bInUse = false; - if (--m_lifeTime == 0) - m_bInUse = false; - m_framesInUse++; } RpAtomic * @@ -418,6 +690,7 @@ C3dMarker::DeleteMarkerObject() m_nIdentifier = 0; m_nStartTime = 0; m_bIsUsed = false; + m_bFindZOnNextPlacement = false; m_nType = MARKERTYPE_INVALID; frame = RpAtomicGetFrame(m_pAtomic); @@ -461,6 +734,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; @@ -506,8 +780,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) { @@ -520,9 +801,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; @@ -588,13 +869,22 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size else pMarker->m_Color.alpha = (float)a * 0.4f * someSin + a; } - if (pMarker->m_nRotateRate) { + if (pMarker->m_nRotateRate != 0) { CVector pos = pMarker->m_Matrix.GetPosition(); pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep())); pMarker->m_Matrix.GetPosition() = pos; } 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; } @@ -604,9 +894,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) { @@ -766,6 +1061,10 @@ CBrightLights::Render(void) g = aBrightLights[i].m_green; b = aBrightLights[i].m_blue; break; +#ifdef FIX_BUGS //just to make sure that color never will be undefined + default: + return; +#endif } if(aBrightLights[i].m_camDist < BRIGHTLIGHTS_FADE_DIST) @@ -832,18 +1131,18 @@ CBrightLights::Render(void) case BRIGHTLIGHT_FRONT_BIG: case BRIGHTLIGHT_REAR_BIG: for (j = 0; j < 8; j++) { - pos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side + - BigCarHeadLightsUp[j] * aBrightLights[i].m_up + - BigCarHeadLightsFront[j] * aBrightLights[i].m_front + - aBrightLights[i].m_pos; - RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a); - RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z); - } - for (j = 0; j < 12 * 3; j++) - TempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored; - TempBufferVerticesStored += 8; - TempBufferIndicesStored += 12 * 3; - break; + pos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side + + BigCarHeadLightsUp[j] * aBrightLights[i].m_up + + BigCarHeadLightsFront[j] * aBrightLights[i].m_front + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z); + } + for (j = 0; j < 12 * 3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 8; + TempBufferIndicesStored += 12 * 3; + break; case BRIGHTLIGHT_FRONT_TALL: case BRIGHTLIGHT_REAR_TALL: @@ -1050,8 +1349,9 @@ CMoneyMessage::Render() { const float MAX_SCALE = 4.0f; uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered; - if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) m_nTimeRegistered = 0; - else { + if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) { + m_nTimeRegistered = 0; + } else { float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS; RwV3d vecOut; float fDistX, fDistY; @@ -1060,7 +1360,6 @@ CMoneyMessage::Render() fDistY *= (0.7f * fLifeTime + 2.0f) * m_fSize; CFont::SetPropOn(); CFont::SetBackgroundOff(); - float fScaleY = Min(fDistY / 100.0f, MAX_SCALE); float fScaleX = Min(fDistX / 100.0f, MAX_SCALE); @@ -1074,7 +1373,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); + FONT_LOCALE(FONT_STANDARD); CFont::PrintString(vecOut.x, vecOut.y, m_aText); } } diff --git a/src/renderer/SpecialFX.h b/src/renderer/SpecialFX.h index 2d9f18b1..f163d8ca 100644 --- a/src/renderer/SpecialFX.h +++ b/src/renderer/SpecialFX.h @@ -1,14 +1,24 @@ #pragma once +//file done + class CSpecialFX { public: + static bool bVideoCam; + static bool bLiftCam; + static bool bSnapShotActive; + static int32 SnapShotFrames; + static void Render(void); static void Update(void); static void Init(void); static void Shutdown(void); + static void AddWeaponStreak(int type); + static void Render2DFXs(); }; + class CRegisteredMotionBlurStreak { public: @@ -24,6 +34,7 @@ public: void Render(void); }; + class CMotionBlurStreaks { static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS]; @@ -34,26 +45,31 @@ public: static void Render(void); }; + struct CBulletTrace { - CVector m_vecCurrentPos; - CVector m_vecTargetPos; + CVector m_vecStartPos; + CVector m_vecEndPos; bool m_bInUse; - uint8 m_framesInUse; - uint8 m_lifeTime; + uint32 m_nCreationTime; + uint32 m_nLifeTime; + float m_fThickness; + uint8 m_fVisibility; void Update(void); }; + class CBulletTraces { public: static CBulletTrace aTraces[NUMBULLETTRACES]; static void Init(void); - static void AddTrace(CVector*, CVector*); static void Render(void); static void Update(void); + static void AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility); + static void AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter); }; enum @@ -77,6 +93,7 @@ public: RpMaterial *m_pMaterial; uint16 m_nType; bool m_bIsUsed; + bool m_bFindZOnNextPlacement; uint32 m_nIdentifier; RwRGBA m_Color; uint16 m_nPulsePeriod; @@ -93,6 +110,7 @@ public: void Render(); }; + class C3dMarkers { public: @@ -133,6 +151,7 @@ enum BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG, }; + class CBrightLight { public: @@ -147,6 +166,7 @@ public: uint8 m_blue; }; + class CBrightLights { static int NumBrightLights; @@ -166,6 +186,7 @@ enum SHINYTEXT_FLAT }; + class CShinyText { public: @@ -178,7 +199,8 @@ public: uint8 m_blue; }; -class CShinyTexts + +class CShinyTexts { static int NumShinyTexts; static CShinyText aShinyTexts[NUMSHINYTEXTS]; @@ -186,11 +208,12 @@ public: static void Init(void); static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, - uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); + uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); //not used static void Render(void); static void RenderOutGeometryBuffer(void); }; + class CMoneyMessage { friend class CMoneyMessages; @@ -205,6 +228,7 @@ public: void Render(); }; + class CMoneyMessages { static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES]; @@ -214,11 +238,12 @@ public: static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity); }; + class CSpecialParticleStuff { static uint32 BoatFromStart; public: - static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); - static void StartBoatFoamAnimation(); - static void UpdateBoatFoamAnimation(CMatrix*); + static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); //not used + static void StartBoatFoamAnimation(); //not used + static void UpdateBoatFoamAnimation(CMatrix*); //not used }; diff --git a/src/renderer/Sprite.cpp b/src/renderer/Sprite.cpp index 3fef0733..ecfd3fdc 100644 --- a/src/renderer/Sprite.cpp +++ b/src/renderer/Sprite.cpp @@ -156,10 +156,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; @@ -271,8 +271,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]; @@ -584,8 +584,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/renderer/Sprite.h b/src/renderer/Sprite.h index ec4c1d1b..fae6684e 100644 --- a/src/renderer/Sprite.h +++ b/src/renderer/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/renderer/Sprite2d.cpp b/src/renderer/Sprite2d.cpp index 59622516..92f326f8 100644 --- a/src/renderer/Sprite2d.cpp +++ b/src/renderer/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); #if !defined(GTA_PS2_STUFF) && defined(RWLIBS) RwIm2DVertexSetIntRGBA(&maVertices[i], 0, 0, 0, 0); #else @@ -370,72 +289,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); @@ -450,7 +344,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); @@ -463,7 +357,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); @@ -475,6 +369,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); @@ -488,3 +398,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/renderer/Sprite2d.h b/src/renderer/Sprite2d.h index 0e12d441..5abd8d71 100644 --- a/src/renderer/Sprite2d.h +++ b/src/renderer/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/renderer/Timecycle.cpp b/src/renderer/Timecycle.cpp index 0d94dbd6..95d9fe3c 100644 --- a/src/renderer/Timecycle.cpp +++ b/src/renderer/Timecycle.cpp @@ -10,50 +10,72 @@ #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]; +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 +96,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 +112,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 +134,6 @@ float CTimeCycle::m_fShadowSideY[16]; float CTimeCycle::m_fShadowDisplacementX[16]; float CTimeCycle::m_fShadowDisplacementY[16]; - void CTimeCycle::Initialise(void) { @@ -115,18 +142,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"); @@ -139,36 +170,55 @@ CTimeCycle::Initialise(void) for(w = 0; w < NUMWEATHERS; w++) for(h = 0; h < NUMHOURS; h++){ li = 0; - while(work_buff[bi] == '/'){ - while(work_buff[bi] != '\n') + while(work_buff[bi] == '/' || work_buff[bi] == '\n' || + work_buff[bi] == '\0' || work_buff[bi] == ' ' || work_buff[bi] == '\r'){ + while(work_buff[bi] != '\n' && work_buff[bi] != '\0' && work_buff[bi] != '\r') 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 +234,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 +255,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 +266,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 +318,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 +338,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 +363,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 +388,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/renderer/Timecycle.h b/src/renderer/Timecycle.h index d5d7b67a..da911b75 100644 --- a/src/renderer/Timecycle.h +++ b/src/renderer/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/renderer/VarConsole.cpp b/src/renderer/VarConsole.cpp new file mode 100644 index 00000000..372a091a --- /dev/null +++ b/src/renderer/VarConsole.cpp @@ -0,0 +1,786 @@ +#include "common.h" +#include "VarConsole.h" +#include "Font.h" +#include "Pad.h" + +#define VAR_CONSOLE_PAD 1 + +CVarConsole VarConsole; + +void +CVarConsole::Initialise() +{ + m_nCountEntries = 0; + m_nCurPage = 1; + m_bIsOpen = false; + m_nCurEntry = 0; + m_nFirstEntryOnPage = 0; +} + +void +CVarConsole::Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pInt8Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_INT8; + m_aEntries[i].I8_step = step; + m_aEntries[i].I8_min = min; + m_aEntries[i].I8_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pInt16Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_INT16; + m_aEntries[i].I16_step = step; + m_aEntries[i].I16_min = min; + m_aEntries[i].I16_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pInt32Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_INT32; + m_aEntries[i].I32_step = step; + m_aEntries[i].I32_min = min; + m_aEntries[i].I32_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pInt64Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_INT64; + m_aEntries[i].I64_step = step; + m_aEntries[i].I64_min = min; + m_aEntries[i].I64_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint8Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_UINT8; + m_aEntries[i].I8_step = step; + m_aEntries[i].I8_min = min; + m_aEntries[i].I8_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint16Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_UINT16; + m_aEntries[i].I16_step = step; + m_aEntries[i].I16_min = min; + m_aEntries[i].I16_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint32Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_UINT32; + m_aEntries[i].I32_step = step; + m_aEntries[i].I32_min = min; + m_aEntries[i].I32_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint64Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_UINT64; + m_aEntries[i].I64_step = step; + m_aEntries[i].I64_min = min; + m_aEntries[i].I64_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, float *pVal, float step, float min, float max, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pFloatValue = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_FLOAT; + m_aEntries[i].F_step = step; + m_aEntries[i].F_min = min; + m_aEntries[i].F_max = max; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, bool *pVal, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pBoolValue = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_BOOL; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, bool8 *pVal, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint8Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_BOOL8; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, bool16 *pVal, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint16Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_BOOL16; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, bool32 *pVal, bool8 isVar) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pUint32Value = pVal; + m_aEntries[i].bAllowExceedBounds = isVar; + m_aEntries[i].VarType = VCE_TYPE_BOOL32; + m_nCountEntries++; +} + +void +CVarConsole::Add(char *text, void (*pCallback)(void)) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + return; + } + + m_aEntries[i].text = text; + m_aEntries[i].pCallback = pCallback; + m_aEntries[i].VarType = VCE_TYPE_FUNCTION; + m_nCountEntries++; +} + +void +CVarConsole::Remove(char *text) +{ + int i; + for (i = 0; i < m_nCountEntries; i++) { + if (m_aEntries[i].text == text) + { + for (int j = i; j < m_nCountEntries-1; j++) + m_aEntries[j] = m_aEntries[j+1]; + m_nCountEntries--; + return; + } + } +} + +void +CVarConsole::SortPages() +{ + m_nNumPages = m_nCountEntries / 30 + 1; +} + +void +CVarConsole::Display() +{ + char s[256]; + wchar ws[256]; + + CFont::SetColor(CRGBA(200, 200, 200, 255)); + CFont::SetFontStyle(FONT_STANDARD); + CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.6f)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetPropOn(); + CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetRightJustifyWrap(0.0f); + sprintf(s, "PAGE %d", m_nCurPage); + AsciiToUnicode(s, ws); + CFont::SetRightJustifyOn(); + CFont::PrintString(SCREEN_SCALE_X(310.0f), SCREEN_SCALE_Y(30.0f), ws); + CFont::SetRightJustifyOff(); + int y = 45; + for (int i = m_nFirstEntryOnPage; i < m_nCountEntries && i < m_nFirstEntryOnPage + 30; i++) + { + switch (m_aEntries[i].VarType) + { + case VCE_TYPE_INT8: + sprintf(s, "(%d) %s:I8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt8Value); + break; + case VCE_TYPE_INT16: + sprintf(s, "(%d) %s:I16:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt16Value); + break; + case VCE_TYPE_INT32: + sprintf(s, "(%d) %s:I32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt32Value); + break; + case VCE_TYPE_INT64: +#ifdef FIX_BUGS + sprintf(s, "(%d) %s:I64:%lld", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt64Value); +#else + sprintf(s, "(%d) %s:I64:%d", i + 1, m_aEntries[i].text, (int32)*m_aEntries[i].pInt64Value); +#endif + break; + case VCE_TYPE_UINT8: + sprintf(s, "(%d) %s:U8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint8Value); + break; + case VCE_TYPE_UINT16: + sprintf(s, "(%d) %s:U6:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint16Value); + break; + case VCE_TYPE_UINT32: + sprintf(s, "(%d) %s:U32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint32Value); + break; + case VCE_TYPE_UINT64: +#ifdef FIX_BUGS + sprintf(s, "(%d) %s:U64:%llu", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint64Value); +#else + sprintf(s, "(%d) %s:U64:%d", i + 1, m_aEntries[i].text, (uint32)*m_aEntries[i].pUint64Value); +#endif + break; + case VCE_TYPE_FLOAT: + sprintf(s, "(%d) %s:F:%f", i + 1, m_aEntries[i].text, *m_aEntries[i].pFloatValue); + break; + case VCE_TYPE_BOOL: + if (*m_aEntries[i].pBoolValue) + sprintf(s, "(%d) %s:B:TRUE", i + 1, m_aEntries[i].text); + else + sprintf(s, "(%d) %s:B : FALSE", i + 1, m_aEntries[i].text); + break; + case VCE_TYPE_BOOL8: + if (*m_aEntries[i].pUint8Value == FALSE) + sprintf(s, "(%d) %s:B8:FALSE", i + 1, m_aEntries[i].text); + else + sprintf(s, "(%d) %s:B8:TRUE", i + 1, m_aEntries[i].text); + break; + case VCE_TYPE_BOOL16: + if (*m_aEntries[i].pUint16Value == FALSE) + sprintf(s, "(%d) %s:B16:FALSE", i + 1, m_aEntries[i].text); + else + sprintf(s, "(%d) %s:B16:TRUE", i + 1, m_aEntries[i].text); + break; + case VCE_TYPE_BOOL32: + if (*m_aEntries[i].pUint32Value == FALSE) + sprintf(s, "(%d) %s:B32:FALSE", i + 1, m_aEntries[i].text); + else + sprintf(s, "(%d) %s:B32:TRUE", i + 1, m_aEntries[i].text); + break; + case VCE_TYPE_FUNCTION: + sprintf(s, "(%d) %s:FUNCTION:call this function?", i + 1, m_aEntries[i].text); + break; + } + AsciiToUnicode(s, ws); + if (m_nCurEntry == i) { + CFont::SetBackgroundOn(); +#ifdef FIX_BUGS + CFont::SetBackgroundColor(CRGBA(128, 128, 128, 128)); +#endif + } +#ifdef FIX_BUGS + else + CFont::SetBackgroundColor(CRGBA(128, 128, 128, 0)); +#endif + + CFont::SetColor(CRGBA(200, 200, 200, 255)); + CFont::PrintString(SCREEN_SCALE_X(30.0f), SCREEN_SCALE_Y(y), ws); + if (m_nCurEntry == i) + CFont::SetBackgroundOff(); + y += 12; + } +} + +void +CVarConsole::ModifyLeft() +{ + CVarConsoleEntry &entry = m_aEntries[m_nCurEntry]; + switch (entry.VarType) + { + case VCE_TYPE_INT8: + *entry.pInt8Value -= entry.I8_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt8Value < entry.I8_min) + *entry.pInt8Value = entry.I8_max; + } else { + if (*entry.pInt8Value < entry.I8_min) + *entry.pInt8Value = entry.I8_min; + } + break; + case VCE_TYPE_INT16: + *entry.pInt16Value -= entry.I16_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt16Value < entry.I16_min) + *entry.pInt16Value = entry.I16_max; + } + else { + if (*entry.pInt16Value < entry.I16_min) + *entry.pInt16Value = entry.I16_min; + } + break; + case VCE_TYPE_INT32: + *entry.pInt32Value -= entry.I32_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt32Value < entry.I32_min) + *entry.pInt32Value = entry.I32_max; + } + else { + if (*entry.pInt32Value < entry.I32_min) + *entry.pInt32Value = entry.I32_min; + } + break; + case VCE_TYPE_INT64: + *entry.pInt64Value -= entry.I64_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt64Value < entry.I64_min) + *entry.pInt64Value = entry.I64_max; + } + else { + if (*entry.pInt64Value < entry.I64_min) + *entry.pInt64Value = entry.I64_min; + } + break; + case VCE_TYPE_UINT8: + *entry.pUint8Value -= entry.I8_step; + if (entry.bAllowExceedBounds) { + if (*(int8*)entry.pUint8Value < entry.I8_min) + *entry.pUint8Value = entry.I8_max; + } + else { + if (*(int8*)entry.pUint8Value < entry.I8_min) + *entry.pUint8Value = entry.I8_min; + } + break; + case VCE_TYPE_UINT16: + *entry.pUint16Value -= entry.I16_step; + if (entry.bAllowExceedBounds) { + if (*(int16*)entry.pUint16Value < entry.I16_min) + *entry.pUint16Value = entry.I16_max; + } + else { + if (*(int16*)entry.pUint16Value < entry.I16_min) + *entry.pUint16Value = entry.I16_min; + } + break; + case VCE_TYPE_UINT32: + *entry.pUint32Value -= entry.I32_step; + if (entry.bAllowExceedBounds) { + if (*(int32*)entry.pUint32Value < entry.I32_min) + *entry.pUint32Value = entry.I32_max; + } + else { + if (*(int32*)entry.pUint32Value < entry.I32_min) + *entry.pUint32Value = entry.I32_min; + } + break; + case VCE_TYPE_UINT64: + *entry.pUint64Value -= entry.I64_step; + if (entry.bAllowExceedBounds) { + if (*(int64*)entry.pUint64Value < entry.I64_min) + *entry.pUint64Value = entry.I64_max; + } + else { + if (*(int64*)entry.pUint64Value < entry.I64_min) + *entry.pUint64Value = entry.I64_min; + } + break; + case VCE_TYPE_FLOAT: + *entry.pFloatValue -= entry.F_step; + if (entry.bAllowExceedBounds) { + if (*entry.pFloatValue < entry.F_min) + *entry.pFloatValue = entry.F_max; + } + else { + if (*entry.pFloatValue < entry.F_min) + *entry.pFloatValue = entry.F_min; + } + break; + case VCE_TYPE_BOOL: + if (entry.bAllowExceedBounds) + *entry.pBoolValue ^= true; + else + *entry.pBoolValue = false; + break; + case VCE_TYPE_BOOL8: + if (entry.bAllowExceedBounds) + *entry.pUint8Value = *entry.pUint8Value == false; + else + *entry.pUint8Value = false; + break; + case VCE_TYPE_BOOL16: + if (entry.bAllowExceedBounds) + *entry.pUint16Value = *entry.pUint16Value == false; + else + *entry.pUint16Value = false; + break; + case VCE_TYPE_BOOL32: + if (entry.bAllowExceedBounds) + *entry.pUint32Value = *entry.pUint32Value == false; + else + *entry.pUint32Value = false; + break; + case VCE_TYPE_FUNCTION: + entry.pCallback(); + break; + default: + return; + } +} + +void +CVarConsole::ModifyRight() +{ + CVarConsoleEntry &entry = m_aEntries[m_nCurEntry]; + switch (entry.VarType) + { + case VCE_TYPE_INT8: + *entry.pInt8Value += entry.I8_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt8Value > entry.I8_max) + *entry.pInt8Value = entry.I8_min; + } + else { + if (*entry.pInt8Value > entry.I8_max) + *entry.pInt8Value = entry.I8_max; + } + break; + case VCE_TYPE_INT16: + *entry.pInt16Value += entry.I16_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt16Value > entry.I16_max) + *entry.pInt16Value = entry.I16_min; + } + else { + if (*entry.pInt16Value > entry.I16_max) + *entry.pInt16Value = entry.I16_max; + } + break; + case VCE_TYPE_INT32: + *entry.pInt32Value += entry.I32_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt32Value > entry.I32_max) + *entry.pInt32Value = entry.I32_min; + } + else { + if (*entry.pInt32Value > entry.I32_max) + *entry.pInt32Value = entry.I32_max; + } + break; + case VCE_TYPE_INT64: + *entry.pInt64Value += entry.I64_step; + if (entry.bAllowExceedBounds) { + if (*entry.pInt64Value > entry.I64_max) + *entry.pInt64Value = entry.I64_min; + } + else { + if (*entry.pInt64Value > entry.I64_max) + *entry.pInt64Value = entry.I64_max; + } + break; + case VCE_TYPE_UINT8: + *entry.pUint8Value += entry.I8_step; + if (entry.bAllowExceedBounds) { + if (*entry.pUint8Value > (uint8)entry.I8_max) + *entry.pUint8Value = entry.I8_min; + } + else { + if (*entry.pUint8Value > (uint8)entry.I8_max) + *entry.pUint8Value = entry.I8_max; + } + break; + case VCE_TYPE_UINT16: + *entry.pUint16Value += entry.I16_step; + if (entry.bAllowExceedBounds) { + if (*entry.pUint16Value > (uint16)entry.I16_max) + *entry.pUint16Value = entry.I16_min; + } + else { + if (*entry.pUint16Value > (uint16)entry.I16_max) + *entry.pUint16Value = entry.I16_max; + } + break; + case VCE_TYPE_UINT32: + *entry.pUint32Value += entry.I32_step; + if (entry.bAllowExceedBounds) { + if (*entry.pUint32Value > (uint32)entry.I32_max) + *entry.pUint32Value = entry.I32_min; + } + else { + if (*entry.pUint32Value > (uint32)entry.I32_max) + *entry.pUint32Value = entry.I32_max; + } + break; + case VCE_TYPE_UINT64: + *entry.pUint64Value += entry.I64_step; + if (entry.bAllowExceedBounds) { + if (*entry.pUint64Value > (uint64)entry.I64_max) + *entry.pUint64Value = entry.I64_min; + } + else { + if (*entry.pUint64Value > (uint64)entry.I64_max) + *entry.pUint64Value = entry.I64_max; + } + break; + case VCE_TYPE_FLOAT: + *entry.pFloatValue += entry.F_step; + if (entry.bAllowExceedBounds) { + if (*entry.pFloatValue > entry.F_max) + *entry.pFloatValue = entry.F_min; + } + else { + if (*entry.pFloatValue > entry.F_max) + *entry.pFloatValue = entry.F_max; + } + break; + case VCE_TYPE_BOOL: + if (entry.bAllowExceedBounds) + *entry.pBoolValue ^= true; + else + *entry.pBoolValue = true; + break; + case VCE_TYPE_BOOL8: + if (entry.bAllowExceedBounds) + *entry.pUint8Value = *entry.pUint8Value == false; + else + *entry.pUint8Value = true; + break; + case VCE_TYPE_BOOL16: + if (entry.bAllowExceedBounds) + *entry.pUint16Value = *entry.pUint16Value == false; + else + *entry.pUint16Value = true; + break; + case VCE_TYPE_BOOL32: + if (entry.bAllowExceedBounds) + *entry.pUint32Value = *entry.pUint32Value == false; + else + *entry.pUint32Value = true; + break; + case VCE_TYPE_FUNCTION: + entry.pCallback(); + break; + default: + return; + } +} + +void +CVarConsole::Enter() +{ + m_bIsOpen = true; +} + +void +CVarConsole::Exit() +{ + m_bIsOpen = false; +} + +void +CVarConsole::Input() +{ + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadDownJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadDown()) + { + m_nCurEntry++; + if (m_nCurEntry < m_nCountEntries) + { + if (m_nCurEntry > m_nFirstEntryOnPage + 29) + { + m_nFirstEntryOnPage = m_nCurEntry; + ++m_nCurPage; + } + } + else + { + m_nCurEntry = m_nCountEntries - 1; + } + } + + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadUpJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadUp()) + { + m_nCurEntry--; + if (m_nCurEntry < m_nFirstEntryOnPage) + { + m_nFirstEntryOnPage = m_nCurEntry - 29; + --m_nCurPage; + } + if (m_nFirstEntryOnPage < 0) + { + m_nCurEntry = 0; + m_nFirstEntryOnPage = 0; + m_nCurPage = 1; + } + } + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetSquare()) + ModifyLeft(); + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetTriangle()) + ModifyRight(); + + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadLeftJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadLeft()) + ModifyLeft(); + + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadRightJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadRight()) + ModifyRight(); + + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder2JustDown()) + { + if (m_nCurPage > 1) + { + m_nCurPage--; + m_nFirstEntryOnPage -= 30; + m_nCurEntry = m_nFirstEntryOnPage; + if (m_nFirstEntryOnPage < 0) + { + m_nFirstEntryOnPage = 0; + m_nCurEntry = m_nFirstEntryOnPage; + m_nCurPage = 1; + } + } + } + + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder2JustDown()) + { + if (m_nCurPage < m_nNumPages) + { + m_nCurPage++; + m_nFirstEntryOnPage += 30; + m_nCurEntry = m_nFirstEntryOnPage; + if (m_nFirstEntryOnPage >= m_nCountEntries) + { + m_nFirstEntryOnPage -= 30; + m_nCurEntry = m_nFirstEntryOnPage; + m_nCurPage--; + } + } + } + + if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown()) + Exit(); +} + +void +CVarConsole::Process() +{ + Input(); + SortPages(); + Display(); +} + +bool8 +CVarConsole::Open() +{ + return m_bIsOpen; +} + +void +CVarConsole::Check() +{ + if (Open()) + Process(); + else if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown()) + Enter(); +}
\ No newline at end of file diff --git a/src/renderer/VarConsole.h b/src/renderer/VarConsole.h new file mode 100644 index 00000000..5179a10d --- /dev/null +++ b/src/renderer/VarConsole.h @@ -0,0 +1,92 @@ +#pragma once + +enum eVarConsoleEntryType +{ + VCE_TYPE_INT8, + VCE_TYPE_INT16, + VCE_TYPE_INT32, + VCE_TYPE_INT64, + VCE_TYPE_UINT8, + VCE_TYPE_UINT16, + VCE_TYPE_UINT32, + VCE_TYPE_UINT64, + VCE_TYPE_FLOAT, + VCE_TYPE_BOOL, + VCE_TYPE_BOOL8, + VCE_TYPE_BOOL16, + VCE_TYPE_BOOL32, + VCE_TYPE_FUNCTION, +}; + +struct CVarConsoleEntry +{ + char *text; + int8 *pInt8Value; + int16 *pInt16Value; + int32 *pInt32Value; + int64 *pInt64Value; + uint8 *pUint8Value; + uint16 *pUint16Value; + uint32 *pUint32Value; + uint64 *pUint64Value; + float *pFloatValue; + bool *pBoolValue; + void (*pCallback)(void); + int8 I8_step, I8_max, I8_min; + int16 I16_step, I16_max, I16_min; + int32 I32_step, I32_max, I32_min; + int64 I64_step, I64_max, I64_min; + float F_step, F_max, F_min; + bool8 bAllowExceedBounds; + uint8 VarType; +}; + + +class CVarConsole +{ + int32 m_nCountEntries; + bool8 m_bIsOpen; + int32 m_nCurEntry; + int32 m_nFirstEntryOnPage; + int32 m_nCurPage; + int32 m_nNumPages; + CVarConsoleEntry m_aEntries[91]; +public: +#ifdef FIX_BUGS + CVarConsole() { Initialise(); } +#endif + void Initialise(); + void Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar); + void Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar); + void Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar); + void Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar); + void Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar); + void Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar); + void Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar); + void Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar); + void Add(char *text, float *pVal, float step, float min, float max, bool8 isVar); + void Add(char *text, bool *pVal, bool8 isVar); + void Add(char *text, bool8 *pVal, bool8 isVar); + void Add(char *text, bool16 *pVal, bool8 isVar); + void Add(char *text, bool32 *pVal, bool8 isVar); + void Add(char *text, void (*pVar)(void)); + + void Remove(char *text); + + void SortPages(); + void Display(); + + void ModifyLeft(); + void ModifyRight(); + + void Enter(); + void Exit(); + + void Input(); + void Process(); + + bool8 Open(); + void Check(); +}; + +extern CVarConsole VarConsole;
\ No newline at end of file diff --git a/src/renderer/WaterCannon.cpp b/src/renderer/WaterCannon.cpp index 08898be8..4976f8a3 100644 --- a/src/renderer/WaterCannon.cpp +++ b/src/renderer/WaterCannon.cpp @@ -11,6 +11,7 @@ #include "Fire.h" #include "WaterLevel.h" #include "Camera.h" +#include "Particle.h" #define WATERCANNONVERTS 4 #define WATERCANNONINDEXES 12 @@ -77,9 +78,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(); @@ -231,11 +236,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_STD_HIGHIMPACT_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_STD_HIGHIMPACT_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/renderer/WaterCreatures.cpp b/src/renderer/WaterCreatures.cpp new file mode 100644 index 00000000..92fb74ee --- /dev/null +++ b/src/renderer/WaterCreatures.cpp @@ -0,0 +1,275 @@ +#include "common.h" +#include "WaterCreatures.h" +#include "ModelIndices.h" +#include "World.h" +#include "WaterLevel.h" +#include "Camera.h" +#include "PlayerPed.h" +#include "General.h" +#include "Object.h" + +int CWaterCreatures::nNumActiveSeaLifeForms; +CWaterCreature CWaterCreatures::aWaterCreatures[NUM_WATER_CREATURES]; + +struct WaterCreatureProperties aProperties[65] = { + { &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.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, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.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, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.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, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.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, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH1SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH2SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f }, + { &MI_FISH3SINGLE, 0.04f, 1.0f, 0.0008f, 3.0f }, + { &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f }, +}; + +CWaterCreature::CWaterCreature() { + Free(); +} + +void CWaterCreature::Initialise(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) { + this->m_pObj = pObj; + this->m_fFwdSpeed = fFwdSpeed; + this->m_fZTurnSpeed = fZTurnSpeed; + this->m_fWaterDepth = fWaterDepth; + this->m_alpha = alpha; + this->m_state = state; +} + +void CWaterCreature::Allocate(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) { + CWaterCreature::Initialise(pObj, fFwdSpeed, 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 >= NUMTEMPOBJECTS) + return nil; + + CObject *pObj = new CObject(modelID, true); + + if (!pObj) return nil; + + pObj->SetPosition(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 CGeneral::GetRandomNumberInRange(-90, 90) + + RADTODEG(delta.Heading() + HALFPI + PI); +} + +void CWaterCreatures::CreateOne(CVector const& pos, int32 modelID) { + if (!IsSpaceForMoreWaterCreatures()) + return; + + CVector playerPos = FindPlayerPed()->GetPosition(); + CVector fishPos = pos; + float fDepth, fLevelNoWaves; + if (!TheCamera.IsSphereVisible(fishPos, 3.0f) + && CWaterLevel::GetWaterDepth(fishPos, &fDepth, &fLevelNoWaves, nil) && fDepth > 4.5f) { + + if (modelID == -1 || modelID < 0 || modelID > 64) + modelID = CGeneral::GetRandomNumberInRange(0, 64); + + WaterCreatureProperties *creature = &aProperties[modelID]; + fishPos.z = fLevelNoWaves - creature->fLevel; + float fFwdSpeed = CGeneral::GetRandomNumberInRange(0.0f, creature->fFwdSpeed) + 0.01f; + float angle = CWaterCreatures::CalculateFishHeading(playerPos, fishPos); + + CObject *fish = CreateSeaLifeForm(fishPos, *creature->modelID, angle); + if (!fish) return; + + fish->SetRwObjectAlpha(255); + CWaterCreature *wc = GetFishStructSlot(); + wc->Allocate(fish, fFwdSpeed, 0.0f, creature->fWaterDepth, 255, WATER_CREATURE_INIT); + 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: + // is this even reachable? + 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_REMOVE; + break; + } + // fall through + case WATER_CREATURE_INIT: { + if ((playerPos - aWaterCreatures[i].m_pObj->GetPosition()).MagnitudeSqr() < 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 fwd = aWaterCreatures[i].m_pObj->GetRight(); // for some reason they used x for forward + fwd.Normalise(); + aWaterCreatures[i].m_pObj->m_vecMoveSpeed = fwd * aWaterCreatures[i].m_fFwdSpeed; + 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) { + // it looks like this can never be true initially, looks like a BUG + if (aWaterCreatures[i].m_pObj->m_nEndOfLifeTime - 40000 <= CTimer::GetTimeInMilliseconds()) + aWaterCreatures[i].m_state = WATER_CREATURE_ACTIVE; + } + else { + // creature is deeper than water + aWaterCreatures[i].m_state = WATER_CREATURE_FADE_OUT; + } + + } + else { + aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE; + } + break; + } + case WATER_CREATURE_FADE_OUT: { + aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000; + if (aWaterCreatures[i].m_alpha <= 0) { + aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE; + } + else { + aWaterCreatures[i].m_alpha = Max(aWaterCreatures[i].m_alpha - 6, 0); + aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha); + CVector speed = aWaterCreatures[i].m_pObj->GetRight(); + speed.Normalise(); + speed.x *= aWaterCreatures[i].m_fFwdSpeed; + speed.y *= aWaterCreatures[i].m_fFwdSpeed; + speed.z = -0.015f; + aWaterCreatures[i].m_pObj->m_vecMoveSpeed = speed; + + if (!aWaterCreatures[i].m_pObj->GetIsOnScreen()) + aWaterCreatures[i].m_state = WATER_CREATURE_REMOVE; + } + break; + } + case WATER_CREATURE_REMOVE: + if (aWaterCreatures[i].m_pObj){ + CWorld::Remove(aWaterCreatures[i].m_pObj); + delete 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) { + if (aWaterCreatures[i].m_pObj){ + CWorld::Remove(aWaterCreatures[i].m_pObj); + delete 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/renderer/WaterCreatures.h b/src/renderer/WaterCreatures.h new file mode 100644 index 00000000..32754a10 --- /dev/null +++ b/src/renderer/WaterCreatures.h @@ -0,0 +1,49 @@ +#pragma once + +class CObject; + +enum eFishSlotState { + WATER_CREATURE_INIT = 0, + WATER_CREATURE_ACTIVE, + WATER_CREATURE_FADE_OUT, + WATER_CREATURE_REMOVE, + WATER_CREATURE_DISABLED +}; + +class CWaterCreature { +public: + CObject *m_pObj; + float m_fFwdSpeed; + float m_fZTurnSpeed; + int32 m_alpha; + float m_fWaterDepth; + int32 m_state; + + CWaterCreature(); + void Allocate(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state); + void Free(); + void Initialise(CObject *pObj, float fFwdSpeed, 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 fFwdSpeed; + float fLevel; + float fUnknown; //unused + float fWaterDepth; +};
\ No newline at end of file diff --git a/src/renderer/WaterLevel.cpp b/src/renderer/WaterLevel.cpp index 7001c0cf..dee60d66 100644 --- a/src/renderer/WaterLevel.cpp +++ b/src/renderer/WaterLevel.cpp @@ -7,6 +7,7 @@ #include "Weather.h" #include "Camera.h" #include "Vehicle.h" +#include "PlayerPed.h" #include "Boat.h" #include "World.h" #include "General.h" @@ -17,48 +18,105 @@ #include "ParticleMgr.h" #include "RwHelper.h" #include "Streaming.h" +#include "ColStore.h" #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 "MemoryHeap.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]; int8 CWaterLevel::aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS]; int8 CWaterLevel::aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_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; +RwTexture *gpWaterEnvTex; +RwTexture *gpWaterEnvBaseTex; +RwTexture *gpWaterWakeTex; + RwRaster *gpWaterRaster; +RwRaster *gpWaterEnvRaster; +RwRaster *gpWaterEnvBaseRaster; +RwRaster *gpWaterWakeRaster; +bool _bSeaLife; +float _fWaterZOffset = WATER_Z_OFFSET; -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; +#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) { ms_nNoOfWaterLevels = 0; - + #ifdef MASTER int32 hFile = -1; @@ -70,15 +128,14 @@ CWaterLevel::Initialise(Const char *pWaterDat) #else int32 hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb"); #endif - + 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_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::CloseFile(hFile); } #ifndef MASTER @@ -86,6 +143,9 @@ CWaterLevel::Initialise(Const char *pWaterDat) { printf("Init waterlevels\n"); + // collision is streamed in VC + CColStore::LoadAllCollision(); + CFileMgr::SetDir(""); hFile = CFileMgr::OpenFile(pWaterDat, "r"); @@ -93,11 +153,7 @@ CWaterLevel::Initialise(Const char *pWaterDat) while ((line = CFileLoader::LoadLine(hFile))) { -#ifdef FIX_BUGS if (*line && *line != ';' && !strstr(line, "* ;end of file")) -#else - if (*line && *line != ';') -#endif { float z, l, b, r, t; sscanf(line, "%f %f %f %f %f", &z, &l, &b, &r, &t); @@ -118,19 +174,15 @@ CWaterLevel::Initialise(Const char *pWaterDat) // rasterize water rects read from file for (int32 i = 0; i < ms_nNoOfWaterLevels; i++) { - int32 l = WATER_HUGE_X(ms_aWaterRects[i].left); - int32 r = WATER_HUGE_X(ms_aWaterRects[i].right) + 1.0f; + int32 l = WATER_HUGE_X(ms_aWaterRects[i].left + WATER_X_OFFSET); + int32 r = WATER_HUGE_X(ms_aWaterRects[i].right + WATER_X_OFFSET) + 1.0f; int32 t = WATER_HUGE_Y(ms_aWaterRects[i].top); int32 b = WATER_HUGE_Y(ms_aWaterRects[i].bottom) + 1.0f; -#ifdef FIX_BUGS - // water.dat has rects that go out of bounds - // which causes memory corruption l = Clamp(l, 0, MAX_SMALL_SECTORS - 1); r = Clamp(r, 0, MAX_SMALL_SECTORS - 1); t = Clamp(t, 0, MAX_SMALL_SECTORS - 1); b = Clamp(b, 0, MAX_SMALL_SECTORS - 1); -#endif for (int32 x = l; x <= r; x++) { @@ -144,11 +196,11 @@ CWaterLevel::Initialise(Const char *pWaterDat) // remove tiles that are obscured by land for (int32 x = 0; x < MAX_SMALL_SECTORS; x++) { - float worldX = WATER_START_X + x * SMALL_SECTOR_SIZE; + float worldX = WATER_START_X + x * SMALL_SECTOR_SIZE - WATER_X_OFFSET; for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { - if (aWaterFineBlockList[x][y] >= 0) + if (CWaterLevel::aWaterFineBlockList[x][y] >= 0) { float worldY = WATER_START_Y + y * SMALL_SECTOR_SIZE; @@ -160,7 +212,7 @@ CWaterLevel::Initialise(Const char *pWaterDat) CVector worldPos = CVector(worldX + i * (SMALL_SECTOR_SIZE / 8), worldY + j * (SMALL_SECTOR_SIZE / 8), ms_aWaterZs[aWaterFineBlockList[x][y]]); if ((worldPos.x > WORLD_MIN_X && worldPos.x < WORLD_MAX_X) && (worldPos.y > WORLD_MIN_Y && worldPos.y < WORLD_MAX_Y) && - (!WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) || TestVisibilityForFineWaterBlocks(worldPos))) + (!WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) || TestVisibilityForFineWaterBlocks(worldPos))) continue; // at least one point in the tile wasn't blocked, so don't remove water @@ -210,13 +262,16 @@ CWaterLevel::Initialise(Const char *pWaterDat) if (hFile > 0) { CFileMgr::Write(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels)); - CFileMgr::Write(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs)); + CFileMgr::Write(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs)); CFileMgr::Write(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects)); CFileMgr::Write(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList)); CFileMgr::Write(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList)); CFileMgr::CloseFile(hFile); } + + // collision is streamed in VC + CColStore::RemoveAllCollision(); } #endif @@ -226,13 +281,26 @@ CWaterLevel::Initialise(Const char *pWaterDat) CTxdStore::SetCurrentTxd(slot); if ( gpWaterTex == nil ) - gpWaterTex = RwTextureRead("water_old", 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(); printf("Done Initing waterlevels\n"); } @@ -240,92 +308,154 @@ CWaterLevel::Initialise(Const char *pWaterDat) void CWaterLevel::Shutdown() { - FreeBoatWakeArray(); DestroyWavyAtomic(); - if ( gpWaterTex != nil ) - { - RwTextureDestroy(gpWaterTex); - gpWaterTex = nil; - } +#define _DELETE_TEXTURE(t) if ( t ) \ + { \ + RwTextureDestroy(t); \ + t = nil; \ + } + + _DELETE_TEXTURE(gpWaterTex); + _DELETE_TEXTURE(gpWaterEnvTex); + _DELETE_TEXTURE(gpWaterWakeTex); + _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 != nil); - +#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 != nil); - ASSERT(gpWaterTex != nil); - RpMaterialSetTexture(wavyMaterial, gpWaterTex); + RwRGBA watercolor = { 255, 255, 255, 192 }; + RpMaterialSetColor(wavyMaterial, &watercolor); } { - wavyTriangles = RpGeometryGetTriangles(wavyGeometry); - - ASSERT(wavyTriangles != nil); - /* - [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, - &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, (RwInt16)base, (RwInt16)(base+1), (RwInt16)(base+16+2)); + + RpGeometryTriangleSetVertexIndices(wavyGeometry, + (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 != nil); - wavyVert = RpMorphTargetGetVertices(wavyMorphTarget); - ASSERT(wavyVert != nil); + 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++; } } @@ -334,31 +464,80 @@ CWaterLevel::CreateWavyAtomic() RpGeometryUnlock(wavyGeometry); } - { - wavyFrame = RwFrameCreate(); - ASSERT( wavyFrame != nil ); + maskMorphTarget = RpGeometryGetMorphTarget(maskGeometry, 0); + maskVert = RpMorphTargetGetVertices(maskMorphTarget); + maskNormal = RpMorphTargetGetVertexNormals(maskMorphTarget); - ms_pWavyAtomic = RpAtomicCreate(); - ASSERT( ms_pWavyAtomic != nil ); + 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 } #ifndef MASTER @@ -511,7 +690,7 @@ CWaterLevel::RemoveIsolatedWater() { for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { - if (aWaterFineBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] == 0.0f) + if (aWaterFineBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] == 6.0f) { numRemoved++; aWaterFineBlockList[x][y] = NO_WATER; @@ -528,11 +707,13 @@ CWaterLevel::RemoveIsolatedWater() 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 int8 nBlock = aWaterFineBlockList[x][y]; @@ -546,12 +727,13 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool 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; @@ -567,11 +749,13 @@ 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 int8 nBlock = aWaterFineBlockList[x][y]; @@ -584,18 +768,49 @@ CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLeve 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; + + float _fWave = (WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE + WATER_UNSIGN_X(fX) - x*SMALL_SECTOR_SIZE) + * (TWOPI / SMALL_SECTOR_SIZE ) + fAngle; - // if z greater then 60.0f return 2000.0f; - if ( TheCamera.GetPosition().z > 60.0f ) - return 2000.0f; + 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; +} - 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 @@ -629,6 +844,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 >= 0) + return true; + + block = CWaterLevel::aWaterFineBlockList[x + 0][y + 1]; + if (block >= 0) + { + block = CWaterLevel::aWaterFineBlockList[x + 0][y + 2]; + if (block >= 0) + return true; + } + + block = CWaterLevel::aWaterFineBlockList[x + 1][y + 0]; + if (block >= 0) + return true; + + block = CWaterLevel::aWaterFineBlockList[x + 1][y + 1]; + if (block >= 0) + { + block = CWaterLevel::aWaterFineBlockList[x + 1][y + 2]; + if (block >= 0) + return true; + } + + block = CWaterLevel::aWaterFineBlockList[x + 2][y + 0]; + if (block >= 0) + return true; + + block = CWaterLevel::aWaterFineBlockList[x + 2][y + 1]; + if (block >= 0) + { + block = CWaterLevel::aWaterFineBlockList[x + 2][y + 2]; + if (block >= 0) + return true; + } + + return false; +} + inline float SectorRadius(float fSize) { @@ -643,71 +901,91 @@ CWaterLevel::RenderWater() if (gbDontRenderWater) return; #endif - PUSH_RENDERGROUP("CWaterLevel::RenderWater"); bool bUseCamEndX = false; bool bUseCamStartY = false; 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 ) @@ -727,7 +1005,276 @@ CWaterLevel::RenderWater() || aWaterBlockList[2*x+0][2*y+1] >= 0 || aWaterBlockList[2*x+1][2*y+1] >= 0 ) { - 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)) ) + { +#ifndef PC_WATER + WavesCalculatedThisFrame = true; +#endif + + + float fZ; + + if ( aWaterBlockList[2*x+0][2*y+0] >= 0 ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ]; + + if ( aWaterBlockList[2*x+1][2*y+0] >= 0 ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ]; + + if ( aWaterBlockList[2*x+0][2*y+1] >= 0 ) + fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ]; + + if ( aWaterBlockList[2*x+1][2*y+1] >= 0 ) + 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 - WATER_X_OFFSET; + 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)) ) + { + 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)) ) + { + 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)) ) + { + 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)) ) + { + 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; + + PUSH_RENDERGROUP("CWaterLevel::RenderTransparentWater"); + + 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] >= 0 + || aWaterBlockList[2*x+1][2*y+0] >= 0 + || aWaterBlockList[2*x+0][2*y+1] >= 0 + || aWaterBlockList[2*x+1][2*y+1] >= 0 ) + { + float fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET; float fY = WATER_FROM_HUGE_SECTOR_Y(y); CVector2D vecHugeSectorCentre @@ -737,28 +1284,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)) ) { - if ( fHugeSectorDistToCamSqr >= SQR(500.0f) /*fHugeSectorNearDist*/ ) + if ( fHugeSectorDistToCamSqr >= SQR(500.0f) ) { - float fZ; - - if ( aWaterBlockList[2*x+0][2*y+0] >= 0 ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ]; - - if ( aWaterBlockList[2*x+1][2*y+0] >= 0 ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ]; - - if ( aWaterBlockList[2*x+0][2*y+1] >= 0 ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ]; - - if ( aWaterBlockList[2*x+1][2*y+1] >= 0 ) - fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ]; - - RenderOneFlatHugeWaterPoly(fX, fY, fZ, color); + // see RenderWater() + ; } else { @@ -768,20 +1302,16 @@ CWaterLevel::RenderWater() { if ( aWaterBlockList[x2][y2] >= 0 ) { - 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, + if ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE)) ) { // Render four small(32x32) sectors, or one large(64x64). @@ -794,9 +1324,13 @@ CWaterLevel::RenderWater() // --------- // [S] // - - if ( fLargeSectorDistToCamSqr < SQR(176.0f) ) - { + + float fLargeSectorDrawDistSqr = SQR((fWaterDrawDistLarge + 16.0f)); + + if ( fLargeSectorDistToCamSqr < fLargeSectorDrawDistSqr ) + { + _bSeaLife = true; + float fZ; // WS @@ -805,19 +1339,15 @@ CWaterLevel::RenderWater() 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 @@ -826,19 +1356,15 @@ CWaterLevel::RenderWater() 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 @@ -847,19 +1373,15 @@ CWaterLevel::RenderWater() 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 @@ -868,19 +1390,15 @@ CWaterLevel::RenderWater() 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 @@ -891,13 +1409,11 @@ CWaterLevel::RenderWater() RenderOneFlatLargeWaterPoly(fLargeX, fLargeY, fZ, color); } - } // if ( TheCamera.IsSphereVisible - } // if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr ) - } // if ( aWaterBlockList[x2][y2] >= 0 ) - } // for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ ) - } // for ( int32 x2 = 2*x; x2 <= 2*x+1; x2++ ) - // - + } + } + } + } + } } } } @@ -905,194 +1421,102 @@ 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)) ) - { - 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)) ) - { - 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)) ) - { - 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 + WATER_X_OFFSET) + 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) - WATER_X_OFFSET; + float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY); + + RenderWavyMask(fMaskX, fMaskY, fWaterZ, + fSectorX, fSectorY, + signX, signY, colorTrans); } } } - + DefinedState(); +#endif POP_RENDERGROUP(); } -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; @@ -1116,25 +1540,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; @@ -1157,27 +1581,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; @@ -1200,27 +1630,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; @@ -1237,172 +1673,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 != nil ); +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 != nil ); +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 != nil ); - ASSERT( wavyTexCoords != nil ); - ASSERT( wavyVertices != nil ); + 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(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); } - - RpGeometryUnlock(geometry); } +#endif +} + +#ifdef PC_WATER +void +CWaterLevel::PreCalcWaterGeometry(void) +{ + if ( !RequireWavySector ) + { + WavesCalculatedThisFrame = false; + MaskCalculatedThisFrame = false; + return; + } + + RequireWavySector = false; + WavesCalculatedThisFrame = true; - static CBoat *apBoatList[4] = { nil }; + RwRGBA color; - 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) ) + 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 != nil ); - ASSERT( geom != nil ); - - RpAtomic *atomic = RpAtomicCreate(); - ASSERT( atomic != nil ); - - RpAtomicSetGeometry(atomic, geom, 0); - - RwFrame *frame = RwFrameCreate(); - ASSERT( frame != nil ); - - 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 != nil ); - ASSERT( wavyTexCoord != nil ); - ASSERT( geomPreLights != nil ); - ASSERT( geomVertices != nil ); - ASSERT( wavyVertices != nil ); + 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] != nil ) - 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 != nil ); +#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; @@ -1419,7 +2901,7 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY) { if ( aWaterFineBlockList[x][y] >= 0 ) { - 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 @@ -1454,101 +2936,442 @@ CWaterLevel::RenderAndEmptyRenderBuffer() TempBufferVerticesStored = 0; } -void -CWaterLevel::AllocateBoatWakeArray() +bool +CWaterLevel::GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance) { - CStreaming::MakeSpaceFor(14 * CDSTREAM_SECTOR_SIZE); + 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; +} - PUSH_MEMID(MEMID_STREAM); +bool +CWaterLevel::GetGroundLevel_WS(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance) +{ + if ( IsLocationOutOfWorldBounds_WS(vecPosn, 0) ) + return false; + else + return GetGroundLevel(vecPosn, pfOutLevel, pData, fDistance); +} - ASSERT(ms_pWavyAtomic != nil ); +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 != nil ); - RpMorphTarget *wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0); - RpMaterial *wavyMaterial = RpGeometryGetMaterial(wavyGeometry, 0); + if ( pfDepth != nil ) + *pfDepth = fLevelNoWaves - fGroundLevel; - ASSERT(wavyMorphTarget != nil ); - ASSERT(wavyMaterial != nil ); + if ( pfLevelNoWaves != nil ) + *pfLevelNoWaves = fLevelNoWaves; - for ( int32 geom = 0; geom < MAX_BOAT_WAKES; geom++ ) + if ( pfGroundLevel != nil ) + *pfGroundLevel = fGroundLevel; + + return true; +} + +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] == nil ) + 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] != nil); + 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); + } + } + } +} - RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]); +void +CWaterLevel::RenderShipsOnHorizon() +{ +#ifdef FIX_BUGS + CVector cur_pos = FindPlayerCoors(); +#else + CVector cur_pos = FindPlayerPed()->GetPosition(); +#endif + + 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; - ASSERT( geomTriangles != nil ); + float fAngle = CGeneral::GetRandomNumberInRange(450.0f, 750.0f); + + 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 != nil ); - ASSERT( geomVertices != nil ); +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]); } } - - POP_MEMID(); + + 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 ) + { + prev_pos = cur_pos; + timecounter = CTimer::GetTimeInMilliseconds(); + } + else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 ) { - if ( apGeomArray[i] != nil ) + static int32 toygenTime = CTimer::GetTimeInMilliseconds(); + + if ( (CTimer::GetTimeInMilliseconds() - toygenTime) > 20000 ) { - RpGeometryDestroy(apGeomArray[i]); - apGeomArray[i] = nil; + 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) ) + { + 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) ) + { + 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_ANY_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) +{ + if (CObject::nNoTempObjects >= NUMTEMPOBJECTS) + return nil; + + int finalToy = beachtoy; + bool isStatic = false; + int model = MI_BEACHBALL; + switch (beachtoy) { + case BEACHTOY_ANY_LOUNGE: + switch ( CGeneral::GetRandomNumber() & 7 ) { + case 1: + case 7: + finalToy = BEACHTOY_LOUNGE_WOOD_UP; + break; + case 3: + case 5: + finalToy = BEACHTOY_LOUNGE_TOWEL_UP; + break; + default: + finalToy = BEACHTOY_LOUNGE_WOOD_ON; + break; + } + break; + case BEACHTOY_ANY_TOWEL: + switch ( CGeneral::GetRandomNumber() & 7 ) { + case 1: + case 7: + finalToy = BEACHTOY_TOWEL2; + break; + case 2: + case 6: + finalToy = BEACHTOY_TOWEL3; + break; + case 3: + case 5: + finalToy = BEACHTOY_TOWEL4; + break; + default: + finalToy = BEACHTOY_TOWEL1; + break; + } + if (CObject::nNoTempObjects >= 35) { + return nil; + } + default: + break; + } + switch (finalToy) { + case BEACHTOY_BALL: + isStatic = false; + model = MI_BEACHBALL; + break; + case BEACHTOY_LOUNGE_WOOD_UP: + isStatic = false; + model = MI_LOUNGE_WOOD_UP; + break; + case BEACHTOY_LOUNGE_TOWEL_UP: + isStatic = false; + model = MI_LOUNGE_TOWEL_UP; + break; + case BEACHTOY_LOUNGE_WOOD_ON: + isStatic = false; + model = MI_LOUNGE_WOOD_DN; + break; + case BEACHTOY_LOTION: + model = MI_LOTION; + isStatic = true; + break; + case BEACHTOY_TOWEL1: + model = MI_BEACHTOWEL01; + isStatic = true; + break; + case BEACHTOY_TOWEL2: + model = MI_BEACHTOWEL02; + isStatic = true; + break; + case BEACHTOY_TOWEL3: + model = MI_BEACHTOWEL03; + isStatic = true; + break; + case BEACHTOY_TOWEL4: + model = MI_BEACHTOWEL04; + isStatic = true; + break; + default: + break; + } + CObject *toy = new CObject(model, true); + if (toy) { + toy->SetPosition(vec); + toy->GetMatrix().UpdateRW(); + toy->m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + toy->m_vecTurnSpeed = CVector(0.f, 0.f, 0.f); + toy->ObjectCreatedBy = TEMP_OBJECT; + toy->bIsStatic = isStatic; + CObject::nNoTempObjects++; + toy->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 43200000; + CWorld::Add(toy); + return toy; + } else + return nil; +}
\ No newline at end of file diff --git a/src/renderer/WaterLevel.h b/src/renderer/WaterLevel.h index b797f251..6d6614d8 100644 --- a/src/renderer/WaterLevel.h +++ b/src/renderer/WaterLevel.h @@ -1,6 +1,8 @@ #pragma once -#define WATER_Z_OFFSET (1.5f) +#define WATER_X_OFFSET (400.0f) + +#define WATER_Z_OFFSET (0.5f) #define NO_WATER -128 @@ -28,6 +30,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 ) @@ -60,44 +70,115 @@ #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_LOUNGE_WOOD_UP, + BEACHTOY_LOUNGE_TOWEL_UP, + BEACHTOY_LOUNGE_WOOD_ON, + BEACHTOY_ANY_LOUNGE, + BEACHTOY_LOTION, + BEACHTOY_TOWEL1, + BEACHTOY_TOWEL2, + BEACHTOY_TOWEL3, + BEACHTOY_TOWEL4, + BEACHTOY_ANY_TOWEL, +}; 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 int8 aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS]; - static int8 aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS]; + static int8 aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS]; // 64x64 Large blocks 64x64 each + static int8 aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS]; // 128x128 Small blocks 32x32 each static bool WavesCalculatedThisFrame; - static RpAtomic *ms_pWavyAtomic; - static RpGeometry *apGeomArray[MAX_BOAT_WAKES]; - static int16 nGeomUsed; -public: + 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; + static void Initialise(Const char *pWaterDat); // out of class in III PC and later because of SecuROM static void Shutdown(); + static void CreateWavyAtomic(); static void DestroyWavyAtomic(); + static void AddWaterLevel(float fXLeft, float fYBottom, float fXRight, float fYTop, float fLevel); static bool WaterLevelAccordingToRectangles(float fX, float fY, float *pfOutLevel = nil); static bool TestVisibilityForFineWaterBlocks(const CVector &worldPos); static void RemoveIsolatedWater(); + 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); }; diff --git a/src/renderer/Weather.cpp b/src/renderer/Weather.cpp index e57d57d6..9f925a8c 100644 --- a/src/renderer/Weather.cpp +++ b/src/renderer/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,8 @@ #include "Vehicle.h" #include "World.h" #include "ZoneCull.h" +#include "SpecialFX.h" +#include "Replay.h" int32 CWeather::SoundHandle = -1; @@ -31,7 +34,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 +44,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_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, +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_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 +}; + +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 +128,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 +142,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,48 +208,25 @@ 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; } // Rain -#ifndef VC_RAIN_NERF float fNewRain; - if (NewWeatherType == WEATHER_RAINY) { - // if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s - fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f; - if (OldWeatherType != WEATHER_RAINY) { - if (InterpolationValue < 0.4f) - // if rain has just started (<24 minutes), always 0.5 - fNewRain = 0.5f; - else - // if rain is ongoing for >24 minutes, values: 0.25, 0.5, 0.75, 1.0, switching every ~16.5s - fNewRain = 0.25f + ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.25f; - } - } - else - fNewRain = 0.0f; - if (Rain != fNewRain) { // ok to use comparasion - if (Rain < fNewRain) - Rain = Min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); - else - Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); - } -#else - float fNewRain; - if (NewWeatherType == WEATHER_RAINY) { + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) { // if raining for >1 hour, values: 0, 0.33, switching every ~16.5s fNewRain = (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 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; @@ -242,14 +239,13 @@ void CWeather::Update(void) else fNewRain = 0.0f; Rain = fNewRain; -#endif // 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 @@ -259,12 +255,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) @@ -284,6 +368,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()) @@ -295,104 +435,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, 50); - } - 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(splash_points, 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); + } } } } @@ -440,9 +553,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); @@ -465,6 +578,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++) { @@ -475,11 +590,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; @@ -493,7 +608,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; @@ -501,8 +616,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(); } } @@ -514,7 +629,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); @@ -531,22 +646,17 @@ void CWeather::RenderRainStreaks(void) TempBufferIndicesStored = 0; } -void CWeather::StoreWeatherState() +#ifdef SECUROM +void CWeather::ForceHurricaneWeather() { - Stored_StateStored = true; - Stored_InterpolationValue = InterpolationValue; - Stored_Rain = Rain; - Stored_NewWeatherType = NewWeatherType; - Stored_OldWeatherType = OldWeatherType; -} + for (int i = 0; i < ARRAY_SIZE(WeatherTypesList_WithHurricanes); i++) + { + WeatherTypesList[i] = WEATHER_HURRICANE; + WeatherTypesList_WithHurricanes[i] = WEATHER_HURRICANE; + } -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; + CWeather::OldWeatherType = WEATHER_HURRICANE; + CWeather::NewWeatherType = WEATHER_HURRICANE; + CWeather::ForcedWeatherType = WEATHER_HURRICANE; } +#endif diff --git a/src/renderer/Weather.h b/src/renderer/Weather.h index 9c670317..bda57d55 100644 --- a/src/renderer/Weather.h +++ b/src/renderer/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,13 @@ 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(); + + static void ForceHurricaneWeather(); }; enum { @@ -68,4 +70,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/renderer/WindModifiers.cpp b/src/renderer/WindModifiers.cpp new file mode 100644 index 00000000..3bd6ac9c --- /dev/null +++ b/src/renderer/WindModifiers.cpp @@ -0,0 +1,52 @@ +#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; + float fade = distFade * heightFade * 0.5f; + dir = (pos - Array[i].m_pos) * fade / 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/renderer/WindModifiers.h b/src/renderer/WindModifiers.h new file mode 100644 index 00000000..7c2e57bd --- /dev/null +++ b/src/renderer/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); +}; |