summaryrefslogtreecommitdiffstats
path: root/src/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer')
-rw-r--r--src/renderer/2dEffect.h16
-rw-r--r--src/renderer/Clouds.cpp229
-rw-r--r--src/renderer/Clouds.h2
-rw-r--r--src/renderer/Console.cpp2
-rw-r--r--src/renderer/Coronas.cpp474
-rw-r--r--src/renderer/Coronas.h30
-rw-r--r--src/renderer/Credits.cpp1184
-rw-r--r--src/renderer/CutsceneShadow.cpp269
-rw-r--r--src/renderer/CutsceneShadow.h52
-rw-r--r--src/renderer/Draw.cpp34
-rw-r--r--src/renderer/Draw.h11
-rw-r--r--src/renderer/Fluff.cpp1536
-rw-r--r--src/renderer/Fluff.h181
-rw-r--r--src/renderer/Font.cpp1324
-rw-r--r--src/renderer/Font.h77
-rw-r--r--src/renderer/Glass.cpp478
-rw-r--r--src/renderer/Glass.h9
-rw-r--r--src/renderer/Hud.cpp2206
-rw-r--r--src/renderer/Hud.h148
-rw-r--r--src/renderer/MBlur.cpp536
-rw-r--r--src/renderer/MBlur.h22
-rw-r--r--src/renderer/Occlusion.cpp530
-rw-r--r--src/renderer/Occlusion.h62
-rw-r--r--src/renderer/Particle.cpp1628
-rw-r--r--src/renderer/Particle.h40
-rw-r--r--src/renderer/ParticleMgr.cpp12
-rw-r--r--src/renderer/ParticleMgr.h26
-rw-r--r--src/renderer/ParticleType.h19
-rw-r--r--src/renderer/PlayerSkin.cpp14
-rw-r--r--src/renderer/PointLights.cpp57
-rw-r--r--src/renderer/PointLights.h5
-rw-r--r--src/renderer/RenderBuffer.cpp2
-rw-r--r--src/renderer/RenderBuffer.h11
-rw-r--r--src/renderer/Renderer.cpp764
-rw-r--r--src/renderer/Renderer.h20
-rw-r--r--src/renderer/Rubbish.cpp65
-rw-r--r--src/renderer/Rubbish.h2
-rw-r--r--src/renderer/ShadowCamera.cpp549
-rw-r--r--src/renderer/ShadowCamera.h54
-rw-r--r--src/renderer/Shadows.cpp1273
-rw-r--r--src/renderer/Shadows.h108
-rw-r--r--src/renderer/Skidmarks.cpp99
-rw-r--r--src/renderer/Skidmarks.h25
-rw-r--r--src/renderer/SpecialFX.cpp541
-rw-r--r--src/renderer/SpecialFX.h45
-rw-r--r--src/renderer/Sprite.cpp14
-rw-r--r--src/renderer/Sprite.h3
-rw-r--r--src/renderer/Sprite2d.cpp386
-rw-r--r--src/renderer/Sprite2d.h21
-rw-r--r--src/renderer/Timecycle.cpp373
-rw-r--r--src/renderer/Timecycle.h133
-rw-r--r--src/renderer/VarConsole.cpp786
-rw-r--r--src/renderer/VarConsole.h92
-rw-r--r--src/renderer/WaterCannon.cpp26
-rw-r--r--src/renderer/WaterCreatures.cpp275
-rw-r--r--src/renderer/WaterCreatures.h49
-rw-r--r--src/renderer/WaterLevel.cpp2951
-rw-r--r--src/renderer/WaterLevel.h115
-rw-r--r--src/renderer/Weather.cpp496
-rw-r--r--src/renderer/Weather.h38
-rw-r--r--src/renderer/WindModifiers.cpp52
-rw-r--r--src/renderer/WindModifiers.h11
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, &param->entityMatrix);
+
+ /*
+ * Reject backfacing triangles
+ * This reject the triangles parallel to the light as well
+ */
+ if (RwV3dDotProduct(normal, &param->at) > 0.0f)
+ {
+ return points;
+ }
+
+ RwV3dTransformPoints(&vShad[0], &vIn[0], 3, &param->invMatrix);
+
+ /*
+ * Reject triangles behind the camera (z test). Note that any world
+ * triangles lying in front of the camera but before the object may
+ * have a shadow applied. To minimize such artefacts, this test could
+ * be modified to use a specific value rather than 0.0f, perhaps
+ * to reject triangles behind the center plane of the object.
+ *
+ * Reject triangles that lie entirely outside the shadow texture range
+ * (x,y test).
+ */
+ if (((vShad[0].z < 0.0f) && (vShad[1].z < 0.0f)
+ && (vShad[2].z < 0.0f)) || ((vShad[0].x < 0.0f)
+ && (vShad[1].x < 0.0f)
+ && (vShad[2].x < 0.0f))
+ || ((vShad[0].x > 1.0f) && (vShad[1].x > 1.0f)
+ && (vShad[2].x > 1.0f)) || ((vShad[0].y < 0.0f)
+ && (vShad[1].y < 0.0f)
+ && (vShad[2].y < 0.0f))
+ || ((vShad[0].y > 1.0f) && (vShad[1].y > 1.0f)
+ && (vShad[2].y > 1.0f)))
+ {
+ return points;
+ }
+
+ RwIm3DVertex *imv = nil;
+ RwImVertexIndex *imi = nil;
+
+ RenderBuffer::StartStoring(3, 3, &imi, &imv);
+
+ /*
+ * Set the immediate mode vertices for this triangle
+ */
+
+ RwIm3DVertexSetPos(imv, vIn[0].x, vIn[0].y, vIn[0].z);
+ RwIm3DVertexSetPos(imv + 1, vIn[1].x, vIn[1].y, vIn[1].z);
+ RwIm3DVertexSetPos(imv + 2, vIn[2].x, vIn[2].y, vIn[2].z);
+
+ RwIm3DVertexSetU(imv, vShad[0].x);
+ RwIm3DVertexSetU(imv + 1, vShad[1].x);
+ RwIm3DVertexSetU(imv + 2, vShad[2].x);
+
+ RwIm3DVertexSetV(imv, vShad[0].y);
+ RwIm3DVertexSetV(imv + 1, vShad[1].y);
+ RwIm3DVertexSetV(imv + 2, vShad[2].y);
+
+ /*
+ * Do we fade out the shadow with distance?
+ */
+ if (param->fade)
+ {
+ RwReal fadeVal;
+ RwUInt8 val;
+
+ fadeVal = 1.0f - vShad[0].z * vShad[0].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv, val, val, val, val);
+
+ fadeVal = 1.0f - vShad[1].z * vShad[1].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv + 1, val, val, val, val);
+
+ fadeVal = 1.0f - vShad[2].z * vShad[2].z;
+ val =
+ (fadeVal <
+ 0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);
+ RwIm3DVertexSetRGBA(imv + 2, val, val, val, val);
+ }
+ else
+ {
+ RwUInt8 val = param->shadowValue;
+
+ RwIm3DVertexSetRGBA(imv, val, val, val, val);
+ RwIm3DVertexSetRGBA(imv + 1, val, val, val, val);
+ RwIm3DVertexSetRGBA(imv + 2, val, val, val, val);
+ }
+
+ /*
+ * Update buffer position
+ */
+ imi[0] = 0;
+ imi[1] = 1;
+ imi[2] = 2;
+
+ RenderBuffer::StopStoring();
+
+ return points;
+}
+
+void
+CShadows::CastShadowEntityXYZ(CEntity *pEntity, CVector *pPosn,
+ float fFrontX, float fFrontY, float fSideX, float fSideY,
+ int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,
+ float fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)
+{
+ ASSERT(pEntity != nil);
+ ASSERT(pPosn != nil);
+
+ if ( pShadow )
+ {
+ ProjectionParam proj;
+ RwV3d scl;
+ RwV3d tr;
+
+ CShadowCamera *shadow = pShadow->GetShadowCamera();
+ CColModel *collision = pEntity->GetColModel();
+
+ CCollision::CalculateTrianglePlanes(collision);
+
+ RwMatrix mat;
+ mat = *RwFrameGetMatrix(RwCameraGetFrame(shadow->GetRwCamera()));
+
+ RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+
+ RwMatrixRotate(&mat, &Xaxis, -45.0f, rwCOMBINEPRECONCAT);
+
+ proj.at = mat.at;
+ pEntity->GetMatrix().CopyToRwMatrix(&proj.entityMatrix);
+
+ RwMatrixInvert(&proj.invMatrix, &mat);
+ RwReal radius = RwCameraGetViewWindow(shadow->GetRwCamera())->x;
+
+ scl.x = scl.y = -0.5f / (radius*0.9f);
+ scl.z = 1.0f / (radius*0.8f);
+ RwMatrixScale(&proj.invMatrix, &scl, rwCOMBINEPOSTCONCAT);
+
+ tr.x = 0.5f;
+ tr.y = tr.z = 0.0f;
+ RwMatrixTranslate(&proj.invMatrix, &tr, rwCOMBINEPOSTCONCAT);
+
+ proj.shadowValue = nIntensity;
+ proj.fade = 0;
+
+ RwMatrix matrix;
+ pEntity->GetMatrix().CopyToRwMatrix(&matrix);
+ RwMatrix invMatrix;
+ RwMatrixInvert(&invMatrix, &matrix);
+
+
+ CVector center(pShadow->GetBaseSphere().center);
+ center += CVector(-fFrontX * 1.1f, -fFrontY * 1.1f, -0.5f);
+
+ CSphere sphere;
+ sphere.Set(2.0f, center);
+
+ RwV3d point;
+ RwV3dTransformPoints(&point, &center, 1, &invMatrix);
+
+ CColSphere colSphere;
+ colSphere.Set(2.0f, CVector(point), 0, 0);
+
+ int i = 0;
+ while ( i < collision->numTriangles )
+ {
+ CVector p[3];
+
+ collision->GetTrianglePoint(p[0], collision->triangles[i].a);
+ collision->GetTrianglePoint(p[1], collision->triangles[i].b);
+ collision->GetTrianglePoint(p[2], collision->triangles[i].c);
+
+ if ( CCollision::TestSphereTriangle(colSphere, collision->vertices, collision->triangles[i], collision->trianglePlanes[i]) )
+ {
+ CVector n(collision->trianglePlanes[i].GetNormalX(), collision->trianglePlanes[i].GetNormalY(), collision->trianglePlanes[i].GetNormalZ());
+ CVector offset = n * 0.028f;
+
+ p[0] += offset;
+ p[1] += offset;
+ p[2] += offset;
+
+ if ( !ShadowRenderTriangleCB(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);
+};