finished CEntity

This commit is contained in:
aap 2019-06-30 21:06:55 +02:00
parent 6e4df804f7
commit af2e764d81
27 changed files with 665 additions and 76 deletions

View file

@ -1,14 +1,29 @@
#include "common.h"
#include "rpworld.h"
#include "patcher.h"
#include "General.h"
#include "ModelIndices.h"
#include "Timer.h"
#include "Placeable.h"
#include "Entity.h"
#include "Object.h"
#include "ParticleObject.h"
#include "Lights.h"
#include "World.h"
#include "Camera.h"
#include "Glass.h"
#include "Clock.h"
#include "Weather.h"
#include "TimeCycle.h"
#include "Bridge.h"
#include "TrafficLights.h"
#include "Coronas.h"
#include "Pointlights.h"
#include "Shadows.h"
#include "Pickups.h"
#include "SpecialFX.h"
#include "References.h"
#include "TxdStore.h"
#include "Zones.h"
#include "patcher.h"
int gBuildings;
@ -59,7 +74,7 @@ CEntity::CEntity(void)
m_scanCode = 0;
m_modelIndex = -1;
m_rwObject = nil;
m_randomSeed = rand();
m_randomSeed = CGeneral::GetRandomNumber();
m_pFirstReference = nil;
}
@ -339,9 +354,105 @@ CEntity::GetBoundRect(void)
return rect;
}
WRAPPER void
void
CEntity::PreRender(void)
{ EAXJMP(0x474350);
{
switch(m_type){
case ENTITY_TYPE_BUILDING:
if(GetModelIndex() == MI_RAILTRACKS){
CShadows::StoreShadowForPole(this, 0.0f, -10.949f, 5.0f, 8.0f, 1.0f, 0);
CShadows::StoreShadowForPole(this, 0.0f, 10.949f, 5.0f, 8.0f, 1.0f, 1);
}else if(IsTreeModel(GetModelIndex())){
CShadows::StoreShadowForTree(this);
ModifyMatrixForTreeInWind();
}else if(IsBannerModel(GetModelIndex())){
ModifyMatrixForBannerInWind();
}
break;
case ENTITY_TYPE_OBJECT:
if(GetModelIndex() == MI_COLLECTABLE1){
CPickups::DoCollectableEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}else if(GetModelIndex() == MI_MONEY){
CPickups::DoMoneyEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}else if(GetModelIndex() == MI_NAUTICALMINE ||
GetModelIndex() == MI_CARMINE ||
GetModelIndex() == MI_BRIEFCASE){
if(((CObject*)this)->bIsPickup){
CPickups::DoMineEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}
}else if(IsPickupModel(GetModelIndex())){
if(((CObject*)this)->bIsPickup){
CPickups::DoPickUpEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}else if(GetModelIndex() == MI_GRENADE){
CMotionBlurStreaks::RegisterStreak((uintptr)this,
100, 100, 100,
TheCamera.GetPosition() - 0.07f*TheCamera.GetRight(),
TheCamera.GetPosition() + 0.07f*TheCamera.GetRight());
}else if(GetModelIndex() == MI_MOLOTOV){
CMotionBlurStreaks::RegisterStreak((uintptr)this,
0, 100, 0,
TheCamera.GetPosition() - 0.07f*TheCamera.GetRight(),
TheCamera.GetPosition() + 0.07f*TheCamera.GetRight());
}
}else if(GetModelIndex() == MI_MISSILE){
CVector pos = GetPosition();
float flicker = (CGeneral::GetRandomNumber() & 0xF)/(float)0x10;
CShadows::StoreShadowToBeRendered(SHADOWTYPE_2,
gpShadowExplosionTex, &pos,
8.0f, 0.0f, 0.0f, -8.0f,
255, 200.0f*flicker, 160.0f*flicker, 120.0f*flicker,
20.0f, false, 1.0f);
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
8.0f,
1.0f*flicker,
0.8f*flicker,
0.6f*flicker,
CPointLights::FOG_NONE, true);
CCoronas::RegisterCorona((uintptr)this,
255.0f*flicker, 220.0f*flicker, 190.0f*flicker, 255,
pos, 6.0f*flicker, 80.0f, gpCoronaTexture[CCoronas::TYPE_STAR],
CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
}else if(IsGlass(GetModelIndex())){
PreRenderForGlassWindow();
}
// fall through
case ENTITY_TYPE_DUMMY:
if(GetModelIndex() == MI_TRAFFICLIGHTS){
CTrafficLights::DisplayActualLight(this);
CShadows::StoreShadowForPole(this, 2.957f, 0.147f, 0.0f, 16.0f, 0.4f, 0);
}else if(GetModelIndex() == MI_SINGLESTREETLIGHTS1)
CShadows::StoreShadowForPole(this, 0.744f, 0.0f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_SINGLESTREETLIGHTS2)
CShadows::StoreShadowForPole(this, 0.043f, 0.0f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_SINGLESTREETLIGHTS3)
CShadows::StoreShadowForPole(this, 1.143f, 0.145f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_DOUBLESTREETLIGHTS)
CShadows::StoreShadowForPole(this, 0.0f, -0.048f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_STREETLAMP1 ||
GetModelIndex() == MI_STREETLAMP2)
CShadows::StoreShadowForPole(this, 0.0f, 0.0f, 0.0f, 16.0f, 0.4f, 0);
break;
}
if(CModelInfo::GetModelInfo(GetModelIndex())->m_num2dEffects != 0)
ProcessLightsForEntity();
}
void
CEntity::PreRenderForGlassWindow(void)
{
CGlass::AskForObjectToBeRenderedInGlass(this);
bIsVisible = false;
}
void
@ -447,6 +558,313 @@ CEntity::PruneReferences(void)
}
}
void
CEntity::AddSteamsFromGround(CVector *unused)
{
int i, n;
C2dEffect *effect;
CVector pos;
n = CModelInfo::GetModelInfo(GetModelIndex())->m_num2dEffects;
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
CEntity::ProcessLightsForEntity(void)
{
int i, n;
C2dEffect *effect;
CVector pos;
bool lightOn, lightFlickering;
uint32 flashTimer1, flashTimer2, flashTimer3;
if(bRenderDamaged || !bIsVisible || GetUp().z < 0.96f)
return;
flashTimer1 = 0;
flashTimer2 = 0;
flashTimer3 = 0;
n = CModelInfo::GetModelInfo(GetModelIndex())->m_num2dEffects;
for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){
effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
if(effect->type != EFFECT_LIGHT)
continue;
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()>>1 ^ m_randomSeed) & 3)
lightOn = true;
break;
case LIGHT_FLICKER_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7){
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>1 ^ 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)
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)
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)
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()>>1 ^ 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()>>1 ^ 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;
}
// 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);
}
}
// Light shadow
if(effect->light.shadowRange != 0.0f){
if(lightOn){
CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_2,
effect->light.shadow, &pos,
effect->light.shadowRange, 0.0f,
0.0f, -effect->light.shadowRange,
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_2,
effect->light.shadow, &pos,
effect->light.shadowRange, 0.0f,
0.0f, -effect->light.shadowRange,
0, 0.0f, 0.0f, 0.0f,
15.0f, 1.0f, 40.0f, false, 0.0f);
}
}
}
}
float WindTabel[] = {
1.0f, 0.5f, 0.2f, 0.7f, 0.4f, 1.0f, 0.5f, 0.3f,
0.2f, 0.1f, 0.7f, 0.6f, 0.3f, 1.0f, 0.5f, 0.2f,
};
void
CEntity::ModifyMatrixForTreeInWind(void)
{
uint16 t;
float f;
float strength, flutter;
if(CTimer::GetIsPaused())
return;
CMatrix mat(GetMatrix().m_attachment);
if(CWeather::Wind >= 0.5){
t = m_randomSeed + 16*CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = f * WindTabel[(t>>12)+1 & 0xF] +
(1.0f - f) * WindTabel[(t>>12) & 0xF] +
1.0f;
strength = CWeather::Wind < 0.8f ? 0.008f : 0.014f;
}else if(CWeather::Wind >= 0.2){
t = (uintptr)this + CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = sin(f * 6.28f);
strength = 0.008f;
}else{
t = (uintptr)this + CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = sin(f * 6.28f);
strength = 0.005f;
}
mat.GetUp()->x = strength * flutter;
mat.GetUp()->y = mat.GetUp()->x;
mat.UpdateRW();
UpdateRwFrame();
}
float BannerWindTabel[] = {
0.0f, 0.3f, 0.6f, 0.85f, 0.99f, 0.97f, 0.65f, 0.15f,
-0.1f, 0.0f, 0.35f, 0.57f, 0.55f, 0.35f, 0.45f, 0.67f,
0.73f, 0.45f, 0.25f, 0.35f, 0.35f, 0.11f, 0.13f, 0.21f,
0.28f, 0.28f, 0.22f, 0.1f, 0.0f, -0.1f, -0.17f, -0.12f
};
void
CEntity::ModifyMatrixForBannerInWind(void)
{
uint16 t;
float f;
float strength, flutter;
CVector right, up;
if(CTimer::GetIsPaused())
return;
if(CWeather::Wind < 0.1f)
strength = 0.2f;
else if(CWeather::Wind < 0.8f)
strength = 0.43f;
else
strength = 0.66f;
t = ((int)(GetMatrix().GetPosition()->x + GetMatrix().GetPosition()->y) << 10) + 16*CTimer::GetTimeInMilliseconds();
f = (t & 0x7FF)/(float)0x800;
flutter = f * BannerWindTabel[(t>>11)+1 & 0x1F] +
(1.0f - f) * BannerWindTabel[(t>>11) & 0x1F];
flutter *= strength;
right = CrossProduct(GetForward(), GetUp());
right.z = 0.0f;
right.Normalise();
up = right * flutter;
up.z = sqrt(sq(1.0f) - sq(flutter));
GetRight() = CrossProduct(GetForward(), up);
GetUp() = up;
GetMatrix().UpdateRW();
UpdateRwFrame();
}
STARTPATCHES
InjectHook(0x473C30, &CEntity::ctor, PATCH_JUMP);
InjectHook(0x473E40, &CEntity::dtor, PATCH_JUMP);
@ -466,11 +884,18 @@ STARTPATCHES
InjectHook(0x473F10, &CEntity::AttachToRwObject, PATCH_JUMP);
InjectHook(0x473F60, &CEntity::DetachFromRwObject, PATCH_JUMP);
InjectHook(0x475A20, &CEntity::PreRenderForGlassWindow, PATCH_JUMP);
InjectHook(0x50CE40, &CEntity::AddSteamsFromGround, PATCH_JUMP);
InjectHook(0x475670, &CEntity::ModifyMatrixForTreeInWind, PATCH_JUMP);
InjectHook(0x475830, &CEntity::ModifyMatrixForBannerInWind, PATCH_JUMP);
InjectHook(0x4FA530, &CEntity::ProcessLightsForEntity, PATCH_JUMP);
InjectHook(0x475080, &CEntity::Add_, PATCH_JUMP);
InjectHook(0x475310, &CEntity::Remove_, PATCH_JUMP);
InjectHook(0x473EA0, &CEntity::CreateRwObject_, PATCH_JUMP);
InjectHook(0x473F90, &CEntity::DeleteRwObject_, PATCH_JUMP);
InjectHook(0x474000, &CEntity::GetBoundRect_, PATCH_JUMP);
InjectHook(0x474350, &CEntity::PreRender_, PATCH_JUMP);
InjectHook(0x474BD0, &CEntity::Render_, PATCH_JUMP);
InjectHook(0x4A7C60, &CEntity::SetupLighting_, PATCH_JUMP);
ENDPATCHES