summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml10
-rw-r--r--gamefiles/models/menu.txdbin10244648 -> 8475176 bytes
-rw-r--r--premake5.lua11
-rw-r--r--src/animation/AnimBlendAssocGroup.cpp53
-rw-r--r--src/animation/AnimBlendAssocGroup.h4
-rw-r--r--src/animation/AnimBlendAssociation.cpp38
-rw-r--r--src/animation/AnimBlendAssociation.h26
-rw-r--r--src/animation/AnimBlendClumpData.cpp1
-rw-r--r--src/animation/AnimBlendClumpData.h7
-rw-r--r--src/animation/AnimBlendHierarchy.cpp57
-rw-r--r--src/animation/AnimBlendHierarchy.h4
-rw-r--r--src/animation/AnimBlendNode.cpp46
-rw-r--r--src/animation/AnimBlendNode.h2
-rw-r--r--src/animation/AnimBlendSequence.cpp19
-rw-r--r--src/animation/AnimBlendSequence.h7
-rw-r--r--src/animation/AnimManager.cpp1054
-rw-r--r--src/animation/AnimManager.h58
-rw-r--r--src/animation/AnimationId.h167
-rw-r--r--src/animation/Bones.cpp73
-rw-r--r--src/animation/Bones.h38
-rw-r--r--src/animation/CutsceneMgr.cpp28
-rw-r--r--src/animation/CutsceneMgr.h1
-rw-r--r--src/animation/FrameUpdate.cpp16
-rw-r--r--src/animation/RpAnimBlend.cpp101
-rw-r--r--src/animation/RpAnimBlend.h5
-rw-r--r--src/audio/AudioLogic.cpp2707
-rw-r--r--src/audio/AudioManager.h78
-rw-r--r--src/audio/MusicManager.cpp3
-rw-r--r--src/audio/PoliceRadio.cpp66
-rw-r--r--src/control/AutoPilot.cpp4
-rw-r--r--src/control/AutoPilot.h14
-rw-r--r--src/control/Bridge.cpp14
-rw-r--r--src/control/CarAI.cpp264
-rw-r--r--src/control/CarAI.h5
-rw-r--r--src/control/CarCtrl.cpp1065
-rw-r--r--src/control/CarCtrl.h64
-rw-r--r--src/control/Curves.cpp18
-rw-r--r--src/control/Garages.cpp880
-rw-r--r--src/control/Garages.h90
-rw-r--r--src/control/PathFind.cpp917
-rw-r--r--src/control/PathFind.h162
-rw-r--r--src/control/Pickups.cpp221
-rw-r--r--src/control/Pickups.h13
-rw-r--r--src/control/Record.cpp426
-rw-r--r--src/control/Replay.cpp32
-rw-r--r--src/control/Replay.h4
-rw-r--r--src/control/Restart.cpp8
-rw-r--r--src/control/RoadBlocks.cpp21
-rw-r--r--src/control/RoadBlocks.h4
-rw-r--r--src/control/SceneEdit.cpp2
-rw-r--r--src/control/Script.cpp2011
-rw-r--r--src/control/Script.h34
-rw-r--r--src/control/ScriptCommands.h301
-rw-r--r--src/control/TrafficLights.cpp9
-rw-r--r--src/core/AnimViewer.cpp8
-rw-r--r--src/core/Cam.cpp22
-rw-r--r--src/core/Camera.cpp44
-rw-r--r--src/core/Camera.h5
-rw-r--r--src/core/ColStore.cpp237
-rw-r--r--src/core/ColStore.h43
-rw-r--r--src/core/Collision.cpp151
-rw-r--r--src/core/Collision.h40
-rw-r--r--src/core/EventList.cpp2
-rw-r--r--src/core/EventList.h6
-rw-r--r--src/core/FileLoader.cpp545
-rw-r--r--src/core/FileLoader.h19
-rw-r--r--src/core/Frontend.cpp411
-rw-r--r--src/core/Frontend.h51
-rw-r--r--src/core/Game.cpp23
-rw-r--r--src/core/Game.h33
-rw-r--r--src/core/General.h2
-rw-r--r--src/core/Pad.cpp61
-rw-r--r--src/core/Placeable.cpp2
-rw-r--r--src/core/Placeable.h1
-rw-r--r--src/core/PlayerInfo.cpp8
-rw-r--r--src/core/PlayerInfo.h6
-rw-r--r--src/core/Pools.cpp16
-rw-r--r--src/core/Pools.h4
-rw-r--r--src/core/Radar.cpp381
-rw-r--r--src/core/Radar.h117
-rw-r--r--src/core/Stats.cpp22
-rw-r--r--src/core/Stats.h7
-rw-r--r--src/core/Streaming.cpp916
-rw-r--r--src/core/Streaming.h30
-rw-r--r--src/core/TempColModels.cpp57
-rw-r--r--src/core/TempColModels.h1
-rw-r--r--src/core/User.cpp4
-rw-r--r--src/core/Wanted.cpp13
-rw-r--r--src/core/Wanted.h3
-rw-r--r--src/core/World.cpp121
-rw-r--r--src/core/World.h20
-rw-r--r--src/core/ZoneCull.cpp435
-rw-r--r--src/core/ZoneCull.h69
-rw-r--r--src/core/Zones.cpp627
-rw-r--r--src/core/Zones.h52
-rw-r--r--src/core/common.h1
-rw-r--r--src/core/config.h87
-rw-r--r--src/core/main.cpp72
-rw-r--r--src/core/re3.cpp35
-rw-r--r--src/core/templates.h9
-rw-r--r--src/entities/Building.cpp22
-rw-r--r--src/entities/Building.h3
-rw-r--r--src/entities/Dummy.cpp15
-rw-r--r--src/entities/Dummy.h3
-rw-r--r--src/entities/Entity.cpp582
-rw-r--r--src/entities/Entity.h33
-rw-r--r--src/entities/Physical.cpp22
-rw-r--r--src/entities/Physical.h15
-rw-r--r--src/entities/Treadable.h5
-rw-r--r--src/math/Matrix.h3
-rw-r--r--src/modelinfo/BaseModelInfo.cpp16
-rw-r--r--src/modelinfo/BaseModelInfo.h40
-rw-r--r--src/modelinfo/ClumpModelInfo.cpp58
-rw-r--r--src/modelinfo/ClumpModelInfo.h14
-rw-r--r--src/modelinfo/MloModelInfo.cpp39
-rw-r--r--src/modelinfo/MloModelInfo.h14
-rw-r--r--src/modelinfo/ModelIndices.h546
-rw-r--r--src/modelinfo/ModelInfo.cpp77
-rw-r--r--src/modelinfo/ModelInfo.h14
-rw-r--r--src/modelinfo/PedModelInfo.cpp305
-rw-r--r--src/modelinfo/PedModelInfo.h43
-rw-r--r--src/modelinfo/SimpleModelInfo.cpp49
-rw-r--r--src/modelinfo/SimpleModelInfo.h20
-rw-r--r--src/modelinfo/TimeModelInfo.h3
-rw-r--r--src/modelinfo/VehicleModelInfo.cpp272
-rw-r--r--src/modelinfo/VehicleModelInfo.h44
-rw-r--r--src/modelinfo/WeaponModelInfo.cpp55
-rw-r--r--src/modelinfo/WeaponModelInfo.h22
-rw-r--r--src/modelinfo/XtraCompsModelInfo.h12
-rw-r--r--src/objects/CutsceneHead.cpp194
-rw-r--r--src/objects/CutsceneHead.h28
-rw-r--r--src/objects/CutsceneObject.cpp44
-rw-r--r--src/objects/CutsceneObject.h17
-rw-r--r--src/objects/DummyObject.cpp1
-rw-r--r--src/objects/DummyObject.h2
-rw-r--r--src/objects/Object.cpp26
-rw-r--r--src/objects/Object.h26
-rw-r--r--src/peds/CivilianPed.cpp109
-rw-r--r--src/peds/CivilianPed.h5
-rw-r--r--src/peds/CopPed.cpp49
-rw-r--r--src/peds/CopPed.h3
-rw-r--r--src/peds/DummyPed.h2
-rw-r--r--src/peds/EmergencyPed.cpp7
-rw-r--r--src/peds/Gangs.cpp69
-rw-r--r--src/peds/Gangs.h31
-rw-r--r--src/peds/Ped.cpp2454
-rw-r--r--src/peds/Ped.h295
-rw-r--r--src/peds/PedAttactor.cpp775
-rw-r--r--src/peds/PedAttractor.h196
-rw-r--r--src/peds/PedIK.cpp482
-rw-r--r--src/peds/PedIK.h2
-rw-r--r--src/peds/PedPlacement.cpp8
-rw-r--r--src/peds/PedPlacement.h2
-rw-r--r--src/peds/PedStats.h5
-rw-r--r--src/peds/PlayerPed.cpp221
-rw-r--r--src/peds/PlayerPed.h25
-rw-r--r--src/peds/Population.cpp286
-rw-r--r--src/peds/Population.h9
-rw-r--r--src/render/2dEffect.h12
-rw-r--r--src/render/Clouds.cpp225
-rw-r--r--src/render/Clouds.h2
-rw-r--r--src/render/Coronas.cpp13
-rw-r--r--src/render/Coronas.h8
-rw-r--r--src/render/Fluff.cpp4
-rw-r--r--src/render/Hud.cpp395
-rw-r--r--src/render/Hud.h39
-rw-r--r--src/render/MBlur.cpp147
-rw-r--r--src/render/MBlur.h6
-rw-r--r--src/render/Occlusion.cpp44
-rw-r--r--src/render/Occlusion.h26
-rw-r--r--src/render/Particle.cpp8
-rw-r--r--src/render/Renderer.cpp436
-rw-r--r--src/render/Renderer.h9
-rw-r--r--src/render/Skidmarks.cpp42
-rw-r--r--src/render/Sprite.cpp8
-rw-r--r--src/render/Sprite2d.cpp17
-rw-r--r--src/render/Sprite2d.h2
-rw-r--r--src/render/Timecycle.cpp131
-rw-r--r--src/render/Timecycle.h46
-rw-r--r--src/render/WaterLevel.cpp89
-rw-r--r--src/render/WaterLevel.h4
-rw-r--r--src/render/Weather.cpp183
-rw-r--r--src/render/Weather.h29
-rw-r--r--src/render/WindModifiers.cpp8
-rw-r--r--src/render/WindModifiers.h7
-rw-r--r--src/rw/Lights.cpp32
-rw-r--r--src/rw/RwHelper.cpp10
-rw-r--r--src/rw/RwHelper.h2
-rw-r--r--src/rw/VisibilityPlugins.cpp360
-rw-r--r--src/rw/VisibilityPlugins.h16
-rw-r--r--src/save/GenericGameStorage.cpp5
-rw-r--r--src/skel/glfw/glfw.cpp4
-rw-r--r--src/skel/win/gta3.icobin2238 -> 0 bytes
-rw-r--r--src/skel/win/gtavc.icobin0 -> 3262 bytes
-rw-r--r--src/skel/win/win.cpp6
-rw-r--r--src/skel/win/win.rc2
-rw-r--r--src/text/Text.cpp250
-rw-r--r--src/text/Text.h41
-rw-r--r--src/vehicles/Automobile.cpp117
-rw-r--r--src/vehicles/Automobile.h9
-rw-r--r--src/vehicles/Bike.h13
-rw-r--r--src/vehicles/Boat.cpp101
-rw-r--r--src/vehicles/Boat.h9
-rw-r--r--src/vehicles/CarGen.cpp127
-rw-r--r--src/vehicles/CarGen.h5
-rw-r--r--src/vehicles/Cranes.cpp5
-rw-r--r--src/vehicles/HandlingMgr.cpp312
-rw-r--r--src/vehicles/HandlingMgr.h160
-rw-r--r--src/vehicles/Heli.cpp18
-rw-r--r--src/vehicles/Heli.h3
-rw-r--r--src/vehicles/Plane.cpp4
-rw-r--r--src/vehicles/Plane.h2
-rw-r--r--src/vehicles/Train.cpp26
-rw-r--r--src/vehicles/Train.h2
-rw-r--r--src/vehicles/Vehicle.cpp178
-rw-r--r--src/vehicles/Vehicle.h40
-rw-r--r--src/weapons/ProjectileInfo.cpp82
-rw-r--r--src/weapons/ProjectileInfo.h1
-rw-r--r--src/weapons/Weapon.cpp620
-rw-r--r--src/weapons/Weapon.h14
-rw-r--r--src/weapons/WeaponInfo.cpp125
-rw-r--r--src/weapons/WeaponInfo.h33
-rw-r--r--src/weapons/WeaponType.h30
223 files changed, 16246 insertions, 12259 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 20adee80..611294a5 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -27,13 +27,13 @@ install:
premake5 vs2019 --with-librw --glewdir=%APPVEYOR_BUILD_FOLDER%/%GLEW_BASE% --glfwdir=%APPVEYOR_BUILD_FOLDER%/%GLFW_BASE%
build:
- project: build/re3.sln
+ project: build/reVC.sln
verbosity: minimal
after_build:
-- 7z a "re3_%configuration%_%platform%_%APPVEYOR_BUILD_VERSION%.zip" bin/%PLATFORM%/%CONFIGURATION%/re3.exe bin/%PLATFORM%/%CONFIGURATION%/re3.pdb
+- 7z a "reVC_%configuration%_%platform%_%APPVEYOR_BUILD_VERSION%.zip" bin/%PLATFORM%/%CONFIGURATION%/reVC.exe bin/%PLATFORM%/%CONFIGURATION%/reVC.pdb
artifacts:
-- path: "re3_%configuration%_%platform%_%APPVEYOR_BUILD_VERSION%.zip"
- name: re3
+- path: "reVC_%configuration%_%platform%_%APPVEYOR_BUILD_VERSION%.zip"
+ name: reVC
deploy:
- provider: BinTray
username: shfil119
@@ -43,7 +43,7 @@ deploy:
repo: re3
package: "%configuration%_%platform%"
version: "%APPVEYOR_BUILD_VERSION%"
- artifact: re3
+ artifact: reVC
publish: true
on:
branch: master
diff --git a/gamefiles/models/menu.txd b/gamefiles/models/menu.txd
index f617bcf8..1ffe750e 100644
--- a/gamefiles/models/menu.txd
+++ b/gamefiles/models/menu.txd
Binary files differ
diff --git a/premake5.lua b/premake5.lua
index c8494884..0f3a03dc 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -39,7 +39,7 @@ function getarch(a)
return a
end
-workspace "re3"
+workspace "reVC"
language "C++"
configurations { "Debug", "Release" }
location "build"
@@ -134,10 +134,11 @@ local function addSrcFiles( prefix )
return prefix .. "/*cpp", prefix .. "/*.h", prefix .. "/*.c", prefix .. "/*.ico", prefix .. "/*.rc"
end
-project "re3"
+project "reVC"
kind "WindowedApp"
- targetname "re3"
+ targetname "reVC"
targetdir "bin/%{cfg.platform}/%{cfg.buildcfg}"
+ defines { "MIAMI" }
files { addSrcFiles("src") }
files { addSrcFiles("src/animation") }
@@ -188,8 +189,8 @@ project "re3"
libdirs { "milessdk/lib" }
- if(os.getenv("GTA_III_RE_DIR")) then
- setpaths("$(GTA_III_RE_DIR)/", "%(cfg.buildtarget.name)", "")
+ if(os.getenv("GTA_VC_RE_DIR")) then
+ setpaths("$(GTA_VC_RE_DIR)/", "%(cfg.buildtarget.name)", "")
end
filter "platforms:win*"
diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp
index fe419f2a..83c1742a 100644
--- a/src/animation/AnimBlendAssocGroup.cpp
+++ b/src/animation/AnimBlendAssocGroup.cpp
@@ -8,16 +8,22 @@
#include "General.h"
#include "RwHelper.h"
+#include "ModelIndices.h"
#include "ModelInfo.h"
#include "AnimManager.h"
#include "RpAnimBlend.h"
#include "AnimBlendAssociation.h"
#include "AnimBlendAssocGroup.h"
+//--MIAMI: file done
+
CAnimBlendAssocGroup::CAnimBlendAssocGroup(void)
{
+ animBlock = nil;
assocList = nil;
numAssociations = 0;
+ firstAnimId = 0;
+ groupId = -1;
}
CAnimBlendAssocGroup::~CAnimBlendAssocGroup(void)
@@ -38,7 +44,7 @@ CAnimBlendAssocGroup::DestroyAssociations(void)
CAnimBlendAssociation*
CAnimBlendAssocGroup::GetAnimation(uint32 id)
{
- return &assocList[id];
+ return &assocList[id - firstAnimId];
}
CAnimBlendAssociation*
@@ -48,6 +54,7 @@ CAnimBlendAssocGroup::GetAnimation(const char *name)
for(i = 0; i < numAssociations; i++)
if(!CGeneral::faststricmp(assocList[i].hierarchy->name, name))
return &assocList[i];
+ debug("\n\nCan't find the fucking animation %s\n\n\n", name);
return nil;
}
@@ -97,7 +104,7 @@ strcmpIgnoringDigits(const char *s1, const char *s2)
c2 = toupper(c2);
#endif
- if(c1 != c2)
+ if(c1 && c2 && c1 != c2)
return false;
}
}
@@ -107,6 +114,15 @@ GetModelFromName(const char *name)
{
int i;
CBaseModelInfo *mi;
+ char playername[32];
+
+ if(strncasecmp(name, "CSplay", 6) == 0 &&
+ strncasecmp(CModelInfo::GetModelInfo(MI_PLAYER)->GetName(), "ig", 2) == 0){
+ strcpy(playername, CModelInfo::GetModelInfo(MI_PLAYER)->GetName());
+ playername[0] = 'C';
+ playername[1] = 'S';
+ name = playername;
+ }
for(i = 0; i < MODELINFOSIZE; i++){
mi = CModelInfo::GetModelInfo(i);
@@ -123,8 +139,7 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name)
int i;
CAnimBlock *animBlock;
- if(assocList)
- DestroyAssociations();
+ DestroyAssociations();
animBlock = CAnimManager::GetAnimationBlock(name);
assocList = new CAnimBlendAssociation[animBlock->numAnims];
@@ -133,17 +148,18 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name)
for(i = 0; i < animBlock->numAnims; i++){
CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(animBlock->firstIndex + i);
CBaseModelInfo *model = GetModelFromName(anim->name);
- assert(model);
- printf("Associated anim %s with model %s\n", anim->name, model->GetName());
- RpClump *clump = (RpClump*)model->CreateInstance();
-#ifdef PED_SKIN
- if(IsClumpSkinned(clump))
- RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
-#endif
- RpAnimBlendClumpInit(clump);
- assocList[i].Init(clump, anim);
- RpClumpDestroy(clump);
- assocList[i].animId = i;
+ if(model){
+ debug("Associated anim %s with model %s\n", anim->name, model->GetName());
+ RpClump *clump = (RpClump*)model->CreateInstance();
+ RpAnimBlendClumpInit(clump);
+ assocList[i].Init(clump, anim);
+ if(IsClumpSkinned(clump))
+ RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
+ RpClumpDestroy(clump);
+ assocList[i].animId = firstAnimId + i;
+ assocList[i].groupId = groupId;
+ }else
+ debug("\n\nCANNOT FIND MODELINFO WITH NAME %s\n\n\n", anim->name);
}
numAssociations = animBlock->numAnims;
}
@@ -153,10 +169,8 @@ void
CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs)
{
int i;
- CAnimBlock *animBlock;
- if(assocList)
- DestroyAssociations();
+ DestroyAssociations();
animBlock = CAnimManager::GetAnimationBlock(blockName);
assocList = new CAnimBlendAssociation[numAssocs];
@@ -164,7 +178,8 @@ CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump,
numAssociations = 0;
for(i = 0; i < numAssocs; i++){
assocList[i].Init(clump, CAnimManager::GetAnimation(animNames[i], animBlock));
- assocList[i].animId = i;
+ assocList[i].animId = firstAnimId + i;
+ assocList[i].groupId = groupId;
}
numAssociations = numAssocs;
}
diff --git a/src/animation/AnimBlendAssocGroup.h b/src/animation/AnimBlendAssocGroup.h
index aa58b0d3..86f0ca18 100644
--- a/src/animation/AnimBlendAssocGroup.h
+++ b/src/animation/AnimBlendAssocGroup.h
@@ -1,12 +1,16 @@
#pragma once
class CAnimBlendAssociation;
+struct CAnimBlock;
class CAnimBlendAssocGroup
{
public:
+ CAnimBlock *animBlock;
CAnimBlendAssociation *assocList;
int32 numAssociations;
+ int32 firstAnimId;
+ int32 groupId; // id of self in ms_aAnimAssocGroups
CAnimBlendAssocGroup(void);
~CAnimBlendAssocGroup(void);
diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp
index 8c99b694..9a29601b 100644
--- a/src/animation/AnimBlendAssociation.cpp
+++ b/src/animation/AnimBlendAssociation.cpp
@@ -7,8 +7,11 @@
#include "AnimBlendAssociation.h"
#include "RwHelper.h"
+//--MIAMI: file done
+
CAnimBlendAssociation::CAnimBlendAssociation(void)
{
+ groupId = -1;
nodes = nil;
blendAmount = 1.0f;
blendDelta = 0.0f;
@@ -54,8 +57,8 @@ CAnimBlendAssociation::AllocateAnimBlendNodeArray(int n)
void
CAnimBlendAssociation::FreeAnimBlendNodeArray(void)
{
- assert(nodes != nil);
- RwFreeAlign(nodes);
+ if(nodes)
+ RwFreeAlign(nodes);
}
void
@@ -75,7 +78,10 @@ CAnimBlendAssociation::Init(RpClump *clump, CAnimBlendHierarchy *hier)
// NB: This is where the order of nodes is defined
for(i = 0; i < hier->numSequences; i++){
CAnimBlendSequence *seq = &hier->sequences[i];
- frame = RpAnimBlendClumpFindFrame(clump, seq->name);
+ if(seq->boneTag == -1)
+ frame = RpAnimBlendClumpFindFrame(clump, seq->name);
+ else
+ frame = RpAnimBlendClumpFindBone(clump, seq->boneTag);
if(frame && seq->numFrames > 0)
nodes[frame - clumpData->frames].sequence = seq;
}
@@ -90,6 +96,7 @@ CAnimBlendAssociation::Init(CAnimBlendAssociation &assoc)
numNodes = assoc.numNodes;
flags = assoc.flags;
animId = assoc.animId;
+ groupId = assoc.groupId;
AllocateAnimBlendNodeArray(numNodes);
for(i = 0; i < numNodes; i++){
nodes[i] = assoc.nodes[i];
@@ -129,9 +136,15 @@ CAnimBlendAssociation::SetCurrentTime(float time)
if(!IsRepeating())
return;
CAnimManager::UncompressAnimation(hierarchy);
- for(i = 0; i < numNodes; i++)
- if(nodes[i].sequence)
- nodes[i].FindKeyFrame(currentTime);
+ if(hierarchy->compressed2){
+ for(i = 0; i < numNodes; i++)
+ if(nodes[i].sequence)
+ nodes[i].SetupKeyFrameCompressed();
+ }else{
+ for(i = 0; i < numNodes; i++)
+ if(nodes[i].sequence)
+ nodes[i].FindKeyFrame(currentTime);
+ }
}
void
@@ -147,13 +160,23 @@ CAnimBlendAssociation::Start(float time)
SetCurrentTime(time);
}
+void
+CAnimBlendAssociation::UpdateTimeStep(float timeDelta, float relSpeed)
+{
+ if(IsRunning())
+ timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
+}
+
bool
CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
{
if(!IsRunning())
return true;
+ if(currentTime >= hierarchy->totalLength){
+ flags &= ~ASSOC_RUNNING;
+ return true;
+ }
- timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
currentTime += timeStep;
if(currentTime >= hierarchy->totalLength){
@@ -163,7 +186,6 @@ CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
currentTime -= hierarchy->totalLength;
else{
currentTime = hierarchy->totalLength;
- flags &= ~ASSOC_RUNNING;
if(flags & ASSOC_FADEOUTWHENDONE){
flags |= ASSOC_DELETEFADEDOUT;
blendDelta = -4.0f;
diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h
index 2dff4391..f6d98fc3 100644
--- a/src/animation/AnimBlendAssociation.h
+++ b/src/animation/AnimBlendAssociation.h
@@ -12,12 +12,13 @@ enum {
ASSOC_PARTIAL = 0x10,
ASSOC_MOVEMENT = 0x20, // ???
ASSOC_HAS_TRANSLATION = 0x40,
- ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void)
- ASSOC_FLAG_XPRESS = 0x100, // only used by xpress scratch, see CPed::Chat(void)
- ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void)
- ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played
- ASSOC_FRONTAL = 0x800, // anims that we fall to front
- ASSOC_HAS_X_TRANSLATION = 0x1000, // for 2d velocity extraction
+ ASSOC_HAS_X_TRANSLATION = 0x80, // for 2d velocity extraction
+ ASSOC_WALK = 0x100, // for CPed::PlayFootSteps(void)
+ ASSOC_FLAG_XPRESS = 0x200, // only used by xpress scratch, see CPed::Chat(void)
+ ASSOC_NOWALK = 0x400, // see CPed::PlayFootSteps(void)
+ ASSOC_BLOCK = 0x800, // unused in assoc description, blocks other anims from being played
+ ASSOC_FRONTAL = 0x1000, // anims that we fall to front
+ ASSOC_DRIVING = 0x2000, // new in VC
};
// Anim hierarchy associated with a clump
@@ -35,7 +36,8 @@ public:
CAnimBlendLink link;
- int numNodes; // taken from CAnimBlendClumpData::numFrames
+ int16 numNodes; // taken from CAnimBlendClumpData::numFrames
+ int16 groupId; // ID of CAnimBlendAssocGroup this is in
// NB: Order of these depends on order of nodes in Clump this was built from
CAnimBlendNode *nodes;
CAnimBlendHierarchy *hierarchy;
@@ -44,8 +46,8 @@ public:
float currentTime;
float speed;
float timeStep;
- int32 animId;
- int32 flags;
+ int16 animId;
+ int16 flags;
int32 callbackType;
void (*callback)(CAnimBlendAssociation*, void*);
void *callbackArg;
@@ -76,16 +78,16 @@ public:
void SetCurrentTime(float time);
void SyncAnimation(CAnimBlendAssociation *other);
void Start(float time);
+ void UpdateTimeStep(float timeDelta, float relSpeed);
bool UpdateTime(float timeDelta, float relSpeed);
bool UpdateBlend(float timeDelta);
void SetRun(void) { flags |= ASSOC_RUNNING; }
- inline float GetTimeLeft() { return hierarchy->totalLength - currentTime; }
+ float GetTimeLeft() { return hierarchy->totalLength - currentTime; }
+ float GetProgress() { return currentTime / hierarchy->totalLength; }
static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) {
return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));
}
};
-
-VALIDATE_SIZE(CAnimBlendAssociation, 0x40);
diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp
index d40e8357..5f7491fe 100644
--- a/src/animation/AnimBlendClumpData.cpp
+++ b/src/animation/AnimBlendClumpData.cpp
@@ -3,6 +3,7 @@
#include "AnimBlendClumpData.h"
#include "RwHelper.h"
+//--MIAMI: file done
CAnimBlendClumpData::CAnimBlendClumpData(void)
{
diff --git a/src/animation/AnimBlendClumpData.h b/src/animation/AnimBlendClumpData.h
index 5c511ab8..b953ee88 100644
--- a/src/animation/AnimBlendClumpData.h
+++ b/src/animation/AnimBlendClumpData.h
@@ -11,6 +11,7 @@ struct AnimBlendFrameData
IGNORE_TRANSLATION = 4,
VELOCITY_EXTRACTION = 8,
VELOCITY_EXTRACTION_3D = 0x10,
+ UPDATE_KEYFRAMES = 0x20,
};
uint8 flag;
@@ -35,9 +36,6 @@ class CAnimBlendClumpData
public:
CAnimBlendLink link;
int32 numFrames;
-#ifdef PED_SKIN
- int32 modelNumber; // doesn't seem to be used
-#endif
CVector *velocity;
// order of frames is determined by RW hierarchy
AnimBlendFrameData *frames;
@@ -50,6 +48,3 @@ public:
#endif
void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);
};
-#ifndef PED_SKIN
-VALIDATE_SIZE(CAnimBlendClumpData, 0x14);
-#endif
diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp
index feeaca3d..7388352f 100644
--- a/src/animation/AnimBlendHierarchy.cpp
+++ b/src/animation/AnimBlendHierarchy.cpp
@@ -2,6 +2,9 @@
#include "AnimBlendSequence.h"
#include "AnimBlendHierarchy.h"
+#include "AnimManager.h"
+
+//--MIAMI: file done
CAnimBlendHierarchy::CAnimBlendHierarchy(void)
{
@@ -15,9 +18,10 @@ CAnimBlendHierarchy::CAnimBlendHierarchy(void)
void
CAnimBlendHierarchy::Shutdown(void)
{
+ CAnimManager::RemoveFromUncompressedCache(this);
RemoveAnimSequences();
+ totalLength = 0.0f;
compressed = 0;
- linkPtr = nil;
}
void
@@ -30,15 +34,44 @@ void
CAnimBlendHierarchy::CalcTotalTime(void)
{
int i, j;
- float totalTime = 0.0f;
+
+ totalLength = 0.0f;
for(i = 0; i < numSequences; i++){
- float seqTime = 0.0f;
- for(j = 0; j < sequences[i].numFrames; j++)
- seqTime += sequences[i].GetKeyFrame(j)->deltaTime;
- totalTime = Max(totalTime, seqTime);
+#ifdef FIX_BUGS
+ if(sequences[i].numFrames == 0)
+ continue;
+#endif
+
+ totalLength = Max(totalLength, sequences[i].GetKeyFrame(sequences[i].numFrames-1)->deltaTime);
+ for(j = sequences[i].numFrames-1; j > 0; j--){
+ KeyFrame *kf1 = sequences[i].GetKeyFrame(j);
+ KeyFrame *kf2 = sequences[i].GetKeyFrame(j-1);
+ kf1->deltaTime -= kf2->deltaTime;
+ }
+ }
+}
+
+void
+CAnimBlendHierarchy::CalcTotalTimeCompressed(void)
+{
+ int i, j;
+
+ totalLength = 0.0f;
+
+ for(i = 0; i < numSequences; i++){
+#ifdef FIX_BUGS
+ if(sequences[i].numFrames == 0)
+ continue;
+#endif
+
+ totalLength = Max(totalLength, sequences[i].GetKeyFrameCompressed(sequences[i].numFrames-1)->deltaTime/60.0f);
+ for(j = sequences[i].numFrames-1; j > 0; j--){
+ KeyFrame *kf1 = sequences[i].GetKeyFrameCompressed(j);
+ KeyFrame *kf2 = sequences[i].GetKeyFrameCompressed(j-1);
+ kf1->deltaTime -= kf2->deltaTime;
+ }
}
- totalLength = totalTime;
}
void
@@ -53,17 +86,19 @@ CAnimBlendHierarchy::RemoveQuaternionFlips(void)
void
CAnimBlendHierarchy::RemoveAnimSequences(void)
{
- if(sequences)
- delete[] sequences;
+ delete[] sequences;
+ sequences = nil;
numSequences = 0;
}
void
CAnimBlendHierarchy::Uncompress(void)
{
- if(totalLength == 0.0f)
- CalcTotalTime();
compressed = 0;
+ if(totalLength == 0.0f){
+ RemoveQuaternionFlips();
+ CalcTotalTime();
+ }
}
void
diff --git a/src/animation/AnimBlendHierarchy.h b/src/animation/AnimBlendHierarchy.h
index 0144108d..45c9217e 100644
--- a/src/animation/AnimBlendHierarchy.h
+++ b/src/animation/AnimBlendHierarchy.h
@@ -11,7 +11,8 @@ public:
char name[24];
CAnimBlendSequence *sequences;
int16 numSequences;
- int16 compressed; // not really used
+ bool compressed; // not really used
+ bool compressed2; // not really used
float totalLength;
CLink<CAnimBlendHierarchy*> *linkPtr;
@@ -19,6 +20,7 @@ public:
void Shutdown(void);
void SetName(char *name);
void CalcTotalTime(void);
+ void CalcTotalTimeCompressed(void);
void RemoveQuaternionFlips(void);
void RemoveAnimSequences(void);
void Uncompress(void);
diff --git a/src/animation/AnimBlendNode.cpp b/src/animation/AnimBlendNode.cpp
index df6cd1d5..4186e994 100644
--- a/src/animation/AnimBlendNode.cpp
+++ b/src/animation/AnimBlendNode.cpp
@@ -3,6 +3,8 @@
#include "AnimBlendAssociation.h"
#include "AnimBlendNode.h"
+//--MIAMI: file done
+
void
CAnimBlendNode::Init(void)
{
@@ -92,7 +94,9 @@ CAnimBlendNode::FindKeyFrame(float t)
frameA = 0;
frameB = frameA;
- if(sequence->numFrames >= 2){
+ if(sequence->numFrames == 1){
+ remainingTime = 0.0f;
+ }else{
frameA++;
// advance until t is between frameB and frameA
@@ -101,8 +105,11 @@ CAnimBlendNode::FindKeyFrame(float t)
frameB = frameA++;
if(frameA >= sequence->numFrames){
// reached end of animation
- if(!association->IsRepeating())
+ if(!association->IsRepeating()){
+ CalcDeltas();
+ remainingTime = 0.0f;
return false;
+ }
frameA = 0;
frameB = 0;
}
@@ -115,6 +122,25 @@ CAnimBlendNode::FindKeyFrame(float t)
return true;
}
+bool
+CAnimBlendNode::SetupKeyFrameCompressed(void)
+{
+ if(sequence->numFrames < 1)
+ return false;
+
+ frameA = 1;
+ frameB = 0;
+
+ if(sequence->numFrames == 1){
+ frameA = 0;
+ remainingTime = 0.0f;
+ }else
+ remainingTime = sequence->GetKeyFrameCompressed(frameA)->deltaTime/60.0f;
+
+ CalcDeltasCompressed();
+ return true;
+}
+
void
CAnimBlendNode::CalcDeltas(void)
{
@@ -130,6 +156,20 @@ CAnimBlendNode::CalcDeltas(void)
}
void
+CAnimBlendNode::CalcDeltasCompressed(void)
+{
+ if((sequence->type & CAnimBlendSequence::KF_ROT) == 0)
+ return;
+ KeyFrame *kfA = sequence->GetKeyFrameCompressed(frameA);
+ KeyFrame *kfB = sequence->GetKeyFrameCompressed(frameB);
+ float cos = DotProduct(kfA->rotation, kfB->rotation);
+ if(cos > 1.0f)
+ cos = 1.0f;
+ theta = Acos(cos);
+ invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
+}
+
+void
CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
{
trans = CVector(0.0f, 0.0f, 0.0f);
@@ -138,7 +178,7 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
if(blend > 0.0f){
KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);
KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);
- float t = (kfA->deltaTime - remainingTime)/kfA->deltaTime;
+ float t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime;
if(sequence->type & CAnimBlendSequence::KF_TRANS){
trans = kfB->translation + t*(kfA->translation - kfB->translation);
trans *= blend;
diff --git a/src/animation/AnimBlendNode.h b/src/animation/AnimBlendNode.h
index 89924d6a..9446e1ae 100644
--- a/src/animation/AnimBlendNode.h
+++ b/src/animation/AnimBlendNode.h
@@ -22,7 +22,9 @@ public:
bool Update(CVector &trans, CQuaternion &rot, float weight);
bool NextKeyFrame(void);
bool FindKeyFrame(float t);
+ bool SetupKeyFrameCompressed(void);
void CalcDeltas(void);
+ void CalcDeltasCompressed(void);
void GetCurrentTranslation(CVector &trans, float weight);
void GetEndTranslation(CVector &trans, float weight);
};
diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp
index 4578ec50..b04d6b41 100644
--- a/src/animation/AnimBlendSequence.cpp
+++ b/src/animation/AnimBlendSequence.cpp
@@ -2,6 +2,8 @@
#include "AnimBlendSequence.h"
+//--MIAMI: file done
+
CAnimBlendSequence::CAnimBlendSequence(void)
{
type = 0;
@@ -17,6 +19,8 @@ CAnimBlendSequence::~CAnimBlendSequence(void)
{
if(keyFrames)
RwFree(keyFrames);
+ if(keyFramesCompressed)
+ RwFree(keyFramesCompressed);
}
void
@@ -26,18 +30,21 @@ CAnimBlendSequence::SetName(char *name)
}
void
-CAnimBlendSequence::SetNumFrames(int numFrames, bool translation)
+CAnimBlendSequence::SetNumFrames(int numFrames, bool translation, bool compressed)
{
- int sz;
-
if(translation){
- sz = sizeof(KeyFrameTrans);
type |= KF_ROT | KF_TRANS;
+ if(compressed)
+ keyFramesCompressed = RwMalloc(sizeof(KeyFrameTrans) * numFrames);
+ else
+ keyFrames = RwMalloc(sizeof(KeyFrameTrans) * numFrames);
}else{
- sz = sizeof(KeyFrame);
type |= KF_ROT;
+ if(compressed)
+ keyFramesCompressed = RwMalloc(sizeof(KeyFrame) * numFrames);
+ else
+ keyFrames = RwMalloc(sizeof(KeyFrame) * numFrames);
}
- keyFrames = RwMalloc(sz * numFrames);
this->numFrames = numFrames;
}
diff --git a/src/animation/AnimBlendSequence.h b/src/animation/AnimBlendSequence.h
index 44ac8886..6d8c98aa 100644
--- a/src/animation/AnimBlendSequence.h
+++ b/src/animation/AnimBlendSequence.h
@@ -33,13 +33,18 @@ public:
CAnimBlendSequence(void);
virtual ~CAnimBlendSequence(void);
void SetName(char *name);
- void SetNumFrames(int numFrames, bool translation);
+ void SetNumFrames(int numFrames, bool translation, bool compressed);
void RemoveQuaternionFlips(void);
KeyFrame *GetKeyFrame(int n) {
return type & KF_TRANS ?
&((KeyFrameTrans*)keyFrames)[n] :
&((KeyFrame*)keyFrames)[n];
}
+ KeyFrame *GetKeyFrameCompressed(int n) {
+ return type & KF_TRANS ?
+ &((KeyFrameTrans*)keyFramesCompressed)[n] :
+ &((KeyFrame*)keyFramesCompressed)[n];
+ }
bool HasTranslation(void) { return !!(type & KF_TRANS); }
// TODO? these are unused
// void Uncompress(void);
diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp
index 444b6d45..16207f54 100644
--- a/src/animation/AnimManager.cpp
+++ b/src/animation/AnimManager.cpp
@@ -10,6 +10,9 @@
#include "AnimBlendAssociation.h"
#include "AnimBlendAssocGroup.h"
#include "AnimManager.h"
+#include "Streaming.h"
+
+//--MIAMI: code done (except for pointless TODO)
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
@@ -32,26 +35,26 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_IDLE_ARMED, ASSOC_REPEAT | ASSOC_PARTIAL },
{ ANIM_IDLE_CHAT, ASSOC_REPEAT | ASSOC_PARTIAL },
{ ANIM_IDLE_TAXI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_KO_SHOT_FRONT1, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
- { ANIM_KO_SHOT_FRONT2, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
- { ANIM_KO_SHOT_FRONT3, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
- { ANIM_KO_SHOT_FRONT4, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
- { ANIM_KO_SHOT_FACE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_FRONT1, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_FRONT2, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_FRONT3, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_FRONT4, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_FACE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
{ ANIM_KO_SHOT_STOM, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
- { ANIM_KO_SHOT_ARML, ASSOC_PARTIAL | ASSOC_FRONTAL },
- { ANIM_KO_SHOT_ARMR, ASSOC_PARTIAL | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_ARML, ASSOC_PARTIAL | ASSOC_FRONTAL },
+ { ANIM_KO_SHOT_ARMR, ASSOC_PARTIAL | ASSOC_FRONTAL },
{ ANIM_KO_SHOT_LEGL, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_KO_SHOT_LEGR, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
- { ANIM_KD_LEFT, ASSOC_PARTIAL | ASSOC_FRONTAL },
- { ANIM_KD_RIGHT, ASSOC_PARTIAL | ASSOC_FRONTAL },
+ { ANIM_KD_LEFT, ASSOC_PARTIAL | ASSOC_FRONTAL },
+ { ANIM_KD_RIGHT, ASSOC_PARTIAL | ASSOC_FRONTAL },
{ ANIM_KO_SKID_FRONT, ASSOC_PARTIAL },
{ ANIM_KO_SPIN_R, ASSOC_PARTIAL },
- { ANIM_KO_SKID_BACK, ASSOC_PARTIAL | ASSOC_FRONTAL },
+ { ANIM_KO_SKID_BACK, ASSOC_PARTIAL | ASSOC_FRONTAL },
{ ANIM_KO_SPIN_L, ASSOC_PARTIAL },
- { ANIM_SHOT_FRONT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_SHOT_LEFT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_SHOT_BACK_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_SHOT_RIGHT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_SHOT_FRONT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_SHOT_LEFT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_SHOT_BACK_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_SHOT_RIGHT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_HIT_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HIT_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_HIT_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@@ -62,29 +65,8 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_HIT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HIT_WALK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HIT_WALL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
- { ANIM_FLOOR_HIT_F, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL },
+ { ANIM_FLOOR_HIT_F, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL },
{ ANIM_HIT_BEHIND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_PUNCH_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_KICK_FLOOR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_BAT_H, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_BAT_V, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_HGUN_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_WEAPON_AK_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_SNIPER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_THROW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_THROWU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_WEAPON_START_THROW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_IDLE, ASSOC_REPEAT },
{ ANIM_FIGHT2_IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_SH_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@@ -96,7 +78,18 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_FIGHT_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_ROUNDHOUSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_FIGHT_LONGKICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
- { ANIM_FIGHT_PPUNCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_FIGHT_PPUNCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_FIGHT_JAB, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_FIGHT_ELBOW_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_FIGHT_ELBOW_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_FIGHT_BKICK_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_FIGHT_BKICK_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_PUNCH_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_FIGHT_PPUNCH2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_KICK_FLOOR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_WEAPON_THROWU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_FIGHT_SH_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_CAR_JACKED_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
{ ANIM_CAR_LJACKED_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
{ ANIM_CAR_JACKED_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
@@ -115,6 +108,7 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_CAR_CLOSEDOOR_LOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_ROLLDOOR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_ROLLDOOR_LOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_CAR_JUMPIN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_GETOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_GETOUT_LOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_CLOSE_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
@@ -130,39 +124,41 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_CAR_CLOSEDOOR_LOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_SHUFFLE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_LSHUFFLE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_CAR_SIT, ASSOC_DELETEFADEDOUT },
- { ANIM_CAR_LSIT, ASSOC_DELETEFADEDOUT },
- { ANIM_CAR_SITP, ASSOC_DELETEFADEDOUT },
- { ANIM_CAR_SITPLO, ASSOC_DELETEFADEDOUT },
- { ANIM_DRIVE_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_DRIVE_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_DRIVE_LOW_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_DRIVE_LOW_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_DRIVEBY_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_DRIVEBY_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_CAR_LB, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_DRIVE_BOAT, ASSOC_DELETEFADEDOUT },
+ { ANIM_CAR_SIT, ASSOC_DELETEFADEDOUT},
+ { ANIM_CAR_LSIT, ASSOC_DELETEFADEDOUT},
+ { ANIM_CAR_SITP, ASSOC_DELETEFADEDOUT},
+ { ANIM_CAR_SITPLO, ASSOC_DELETEFADEDOUT},
+ { ANIM_DRIVE_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVE_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVE_LOW_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVE_LOW_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVEBY_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVEBY_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVEBY_LOW_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVEBY_LOW_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_CAR_LB, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVE_BOAT, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING },
+ { ANIM_DRIVE_BOAT_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_DRIVE_BOAT_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BOAT_LB, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_PICKUP_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_PICKUP_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_PULLUP_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_PULLUP_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_ELBOW_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_ELBOW_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_FALL_OFF, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
+ { ANIM_BIKE_FALL_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_CAR_GETOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_GETOUT_LOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_CLOSE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_HOOKERTALK, ASSOC_REPEAT | ASSOC_PARTIAL },
- { ANIM_COACH_OPEN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_COACH_OPEN_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_COACH_IN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_COACH_IN_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_COACH_OUT_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_TRAIN_GETIN, ASSOC_PARTIAL },
- { ANIM_TRAIN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_IDLE_STANCE2, ASSOC_PARTIAL },
+ { ANIM_IDLE_STANCE3, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_CRAWLOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_CAR_CRAWLOUT_RHS2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_OPEN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_GETIN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_CLOSE_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_GETOUT_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_OPEN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_GETIN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_CLOSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_VAN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_CAR_ROLLOUT_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
+ { ANIM_CAR_ROLLOUT_LHS2, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
{ ANIM_GETUP1, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_GETUP2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_GETUP3, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@@ -174,33 +170,132 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_FALL_GLIDE, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
{ ANIM_FALL_LAND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
+ { ANIM_FALL_BACK, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
+ { ANIM_FALL_FRONT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL },
{ ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
- { ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
- { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG_XPRESS },
+ { ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
+ { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG_XPRESS },
{ ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL },
{ ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_DROWN, ASSOC_PARTIAL },
- { ANIM_CPR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_DUCK_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
{ ANIM_DUCK_LOW, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
+ { ANIM_WEAPON_CROUCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
{ ANIM_RBLOCK_CSHOOT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
- { ANIM_WEAPON_THROWU2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_HANDSUP, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HANDSCOWER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
- { ANIM_FUCKU, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_PHONE_IN, ASSOC_PARTIAL },
+ { ANIM_FUCKU, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_PHONE_IN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_PHONE_OUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_PHONE_TALK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
+ { ANIM_SEAT_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_SEAT_UP, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_SEAT_IDLE, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_SEAT_DOWN2, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_ATM, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_ABSEIL, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
+};
+AnimAssocDesc aVanAnimDescs[] = {
+ { ANIM_VAN_OPEN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_GETIN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_CLOSE_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_GETOUT_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_OPEN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_GETIN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_CLOSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_VAN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+};
+AnimAssocDesc aCoachAnimDescs[] = {
+ { ANIM_COACH_OPEN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_COACH_OPEN_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_COACH_IN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_COACH_IN_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_COACH_OUT_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+};
+AnimAssocDesc aBikeAnimDescs[] = {
+ { ANIM_BIKE_RIDE, ASSOC_DELETEFADEDOUT},
+ { ANIM_BIKE_STILL, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_LEFT, ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_RIGHT, ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_BACK, ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_FWD, ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_PUSHES, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_JUMPON_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_JUMPON_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_KICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_HIT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_GETOFF_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_GETOFF_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_BIKE_GETOFF_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
+ { ANIM_BIKE_DRIVEBY_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_DRIVEBY_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_DRIVEBY_FT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },
+ { ANIM_BIKE_PASSENGER, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING },
+};
+AnimAssocDesc aMeleeAnimDescs[] = {
+ { ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
+ { ANIM_WEAPON_CROUCHRELOAD, ASSOC_REPEAT }, // TODO(Miami): Overload that name for melee/swing
+ { ANIM_WEAPON_SPECIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, // TODO(Miami): Overload that name for melee/swing
+};
+AnimAssocDesc aSwingAnimDescs[] = {
+ { ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_WEAPON_CROUCHRELOAD, ASSOC_REPEAT }, // TODO(Miami): Overload that name for melee/swing
+ { ANIM_WEAPON_SPECIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, // TODO(Miami): Overload that name for melee/swing
+};
+AnimAssocDesc aWeaponAnimDescs[] = {
+ { ANIM_WEAPON_FIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_WEAPON_CROUCHFIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_WEAPON_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_WEAPON_CROUCHRELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_WEAPON_SPECIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+};
+AnimAssocDesc aMedicAnimDescs[] = {
+ { ANIM_CPR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+};
+AnimAssocDesc aSunbatheAnimDescs[] = {
+ { ANIM_SUNBATHE, ASSOC_REPEAT | ASSOC_PARTIAL },
+ { ANIM_SUNBATHE_DOWN, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
+ { ANIM_SUNBATHE_UP, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
+ { ANIM_SUNBATHE_ESCAPE, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
+};
+AnimAssocDesc aPlayerIdleAnimDescs[] = {
+ { ANIM_IDLE_STRETCH, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_IDLE_TIME, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_IDLE_SHOULDER, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_IDLE_STRETCH_LEG, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+};
+AnimAssocDesc aRiotAnimDescs[] = {
+ { ANIM_RIOT_ANGRY, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_RIOT_ANGRY_B, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_RIOT_CHANT, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_RIOT_PUNCHES, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_RIOT_SHOUT, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_RIOT_CHALLENGE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_RIOT_FUKU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+};
+AnimAssocDesc aStripAnimDescs[] = {
+ { ANIM_STRIP_A, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_STRIP_B, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_STRIP_C, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_STRIP_D, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_STRIP_E, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_STRIP_F, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+ { ANIM_STRIP_G, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
};
AnimAssocDesc aStdAnimDescsSide[] = {
- { ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION },
- { ANIM_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION },
- { ANIM_SPRINT, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION },
+ { ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK },
+ { ANIM_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK },
+ { ANIM_SPRINT, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK },
{ ANIM_IDLE_STANCE, ASSOC_REPEAT },
{ ANIM_WALK_START, ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
};
-char const *aStdAnimations[] = {
+
+char const* aStdAnimations[] = {
"walk_civi",
"run_civi",
"sprint_panic",
@@ -208,7 +303,7 @@ char const *aStdAnimations[] = {
"walk_start",
"run_stop",
"run_stopR",
- "idle_cam",
+ "idle_hbhb",
"idle_hbhb",
"idle_tired",
"idle_armed",
@@ -246,27 +341,6 @@ char const *aStdAnimations[] = {
"HIT_wall",
"FLOOR_hit_f",
"HIT_behind",
- "punchR",
- "KICK_floor",
- "WEAPON_bat_h",
- "WEAPON_bat_v",
- "WEAPON_hgun_body",
- "WEAPON_AK_body",
- "WEAPON_pump",
- "WEAPON_sniper",
- "WEAPON_throw",
- "WEAPON_throwu",
- "WEAPON_start_throw",
- "bomber",
- "WEAPON_hgun_rload",
- "WEAPON_AK_rload",
- "FPS_PUNCH",
- "FPS_BAT",
- "FPS_UZI",
- "FPS_PUMP",
- "FPS_AK",
- "FPS_M16",
- "FPS_ROCKET",
"FIGHTIDLE",
"FIGHT2IDLE",
"FIGHTsh_F",
@@ -279,6 +353,17 @@ char const *aStdAnimations[] = {
"FIGHTrndhse",
"FIGHTlngkck",
"FIGHTppunch",
+ "FIGHTjab",
+ "FIGHTelbowL",
+ "FIGHTelbowR",
+ "FIGHTbkickL",
+ "FIGHTbkickR",
+ "bomber",
+ "punchR",
+ "FIGHTppunch",
+ "KICK_floor",
+ "WEAPON_throwu",
+ "FIGHTsh_back",
"car_jackedRHS",
"car_LjackedRHS",
"car_jackedLHS",
@@ -297,6 +382,7 @@ char const *aStdAnimations[] = {
"CAR_closedoorL_LHS",
"CAR_rolldoor",
"CAR_rolldoorLO",
+ "CAR_jumpin_LHS",
"CAR_getout_LHS",
"CAR_getoutL_LHS",
"CAR_close_LHS",
@@ -322,29 +408,31 @@ char const *aStdAnimations[] = {
"Drive_LO_R",
"Driveby_L",
"Driveby_R",
+ "DrivebyL_L",
+ "DrivebyL_R",
"CAR_LB",
"DRIVE_BOAT",
+ "DRIVE_BOAT_L",
+ "DRIVE_BOAT_R",
+ "DRIVE_BOAT_back",
+ "BIKE_pickupR",
+ "BIKE_pickupL",
+ "BIKE_pullupR",
+ "BIKE_pullupL",
+ "BIKE_elbowR",
+ "BIKE_elbowL",
+ "BIKE_fall_off",
+ "BIKE_fallR",
"CAR_getout_RHS",
"CAR_getoutL_RHS",
"CAR_close_RHS",
"car_hookertalk",
- "COACH_opnL",
- "COACH_opnR",
- "COACH_inL",
- "COACH_inR",
- "COACH_outL",
- "TRAIN_getin",
- "TRAIN_getout",
+ "idle_stance",
+ "idle_stance",
"CAR_crawloutRHS",
"CAR_crawloutRHS",
- "VAN_openL",
- "VAN_getinL",
- "VAN_closeL",
- "VAN_getoutL",
- "VAN_open",
- "VAN_getin",
- "VAN_close",
- "VAN_getout",
+ "CAR_rollout_LHS",
+ "CAR_rollout_LHS",
"Getup",
"Getup",
"Getup",
@@ -356,6 +444,8 @@ char const *aStdAnimations[] = {
"FALL_glide",
"FALL_land",
"FALL_collapse",
+ "FALL_back",
+ "FALL_front",
"EV_step",
"EV_dive",
"XPRESSscratch",
@@ -363,201 +453,515 @@ char const *aStdAnimations[] = {
"TURN_180",
"ARRESTgun",
"DROWN",
- "CPR",
"DUCK_down",
"DUCK_low",
+ "WEAPON_crouch",
"RBLOCK_Cshoot",
- "WEAPON_throwu",
"handsup",
"handsCOWER",
"FUCKU",
"PHONE_in",
"PHONE_out",
"PHONE_talk",
+ "SEAT_down",
+ "SEAT_up",
+ "SEAT_idle",
+ "SEAT_down",
+ "ATM",
+ "abseil",
+};
+char const* aVanAnimations[] = {
+ "VAN_openL",
+ "VAN_getinL",
+ "VAN_closeL",
+ "VAN_getoutL",
+ "VAN_open",
+ "VAN_getin",
+ "VAN_close",
+ "VAN_getout",
+};
+char const* aCoachAnimations[] = {
+ "COACH_opnL",
+ "COACH_opnL",
+ "COACH_inL",
+ "COACH_inL",
+ "COACH_outL",
+};
+char const* aBikesAnimations[] = {
+ "BIKEs_Ride",
+ "BIKEs_Still",
+ "BIKEs_Left",
+ "BIKEs_Right",
+ "BIKEs_Back",
+ "BIKEs_Fwd",
+ "BIKEs_pushes",
+ "BIKEs_jumponR",
+ "BIKEs_jumponL",
+ "BIKEs_kick",
+ "BIKEs_hit",
+ "BIKEs_getoffRHS",
+ "BIKEs_getoffLHS",
+ "BIKEs_getoffBACK",
+ "BIKEs_drivebyLHS",
+ "BIKEs_drivebyRHS",
+ "BIKEs_drivebyFT",
+ "BIKEs_passenger",
+};
+char const* aBikevAnimations[] = {
+ "BIKEv_Ride",
+ "BIKEv_Still",
+ "BIKEv_Left",
+ "BIKEv_Right",
+ "BIKEv_Back",
+ "BIKEv_Fwd",
+ "BIKEv_pushes",
+ "BIKEv_jumponR",
+ "BIKEv_jumponL",
+ "BIKEv_kick",
+ "BIKEv_hit",
+ "BIKEv_getoffRHS",
+ "BIKEv_getoffLHS",
+ "BIKEv_getoffBACK",
+ "BIKEv_drivebyLHS",
+ "BIKEv_drivebyRHS",
+ "BIKEv_drivebyFT",
+ "BIKEv_passenger",
+};
+char const* aBikehAnimations[] = {
+ "BIKEh_Ride",
+ "BIKEh_Still",
+ "BIKEh_Left",
+ "BIKEh_Right",
+ "BIKEh_Back",
+ "BIKEh_Fwd",
+ "BIKEh_pushes",
+ "BIKEh_jumponR",
+ "BIKEh_jumponL",
+ "BIKEh_kick",
+ "BIKEh_hit",
+ "BIKEh_getoffRHS",
+ "BIKEh_getoffLHS",
+ "BIKEh_getoffBACK",
+ "BIKEh_drivebyLHS",
+ "BIKEh_drivebyRHS",
+ "BIKEh_drivebyFT",
+ "BIKEh_passenger",
+};
+char const* aBikedAnimations[] = {
+ "BIKEd_Ride",
+ "BIKEd_Still",
+ "BIKEd_Left",
+ "BIKEd_Right",
+ "BIKEd_Back",
+ "BIKEd_Fwd",
+ "BIKEd_pushes",
+ "BIKEd_jumponR",
+ "BIKEd_jumponL",
+ "BIKEd_kick",
+ "BIKEd_hit",
+ "BIKEd_getoffRHS",
+ "BIKEd_getoffLHS",
+ "BIKEd_getoffBACK",
+ "BIKEd_drivebyLHS",
+ "BIKEd_drivebyRHS",
+ "BIKEd_drivebyFT",
+ "BIKEd_passenger",
+};
+char const* aUnarmedAnimations[] = {
+ "punchR",
+ "KICK_floor",
+ "FIGHTppunch",
+};
+char const* aScrewdriverAnimations[] = {
+ "FIGHTbodyblow",
+ "FIGHTbodyblow",
+ "FIGHTppunch",
+ "FIGHTIDLE",
+ "FIGHTbodyblow",
+};
+char const* aKnifeAnimations[] = {
+ "WEAPON_knife_1",
+ "WEAPON_knife_2",
+ "knife_part",
+ "WEAPON_knifeidle",
+ "WEAPON_knife_3",
+};
+char const* aBaseballbatAnimations[] = {
+ "WEAPON_bat_h",
+ "WEAPON_bat_v",
+ "BAT_PART",
+ "WEAPON_bat_h",
+ "WEAPON_golfclub",
+};
+char const* aGolfclubAnimations[] = {
+ "WEAPON_bat_h",
+ "WEAPON_golfclub",
+ "BAT_PART",
+ "WEAPON_bat_h",
+ "WEAPON_bat_v",
};
-char const *aPlayerAnimations[] = {
+char const* aChainsawAnimations[] = {
+ "WEAPON_csaw",
+ "WEAPON_csawlo",
+ "csaw_part",
+};
+char const* aPythonAnimations[] = {
+ "python_fire",
+ "python_crouchfire",
+ "python_reload",
+ "python_crouchreload",
+};
+char const* aColtAnimations[] = {
+ "colt45_fire",
+ "colt45_crouchfire",
+ "colt45_reload",
+ "colt45_crouchreload",
+ "colt45_cop",
+};
+char const* aShotgunAnimations[] = {
+ "shotgun_fire",
+ "shotgun_crouchfire",
+};
+char const* aBuddyAnimations[] = {
+ "buddy_fire",
+ "buddy_crouchfire",
+};
+char const* aTecAnimations[] = {
+ "TEC_fire",
+ "TEC_crouchfire",
+ "TEC_reload",
+ "TEC_crouchreload",
+};
+char const* aUziAnimations[] = {
+ "UZI_fire",
+ "UZI_crouchfire",
+ "UZI_reload",
+ "UZI_crouchreload",
+};
+char const* aRifleAnimations[] = {
+ "RIFLE_fire",
+ "RIFLE_crouchfire",
+ "RIFLE_load",
+ "RIFLE_crouchload",
+};
+char const* aM60Animations[] = {
+ "M60_fire",
+ "M60_fire",
+ "M60_reload",
+};
+char const* aSniperAnimations[] = {
+ "WEAPON_sniper",
+};
+char const* aThrowAnimations[] = {
+ "WEAPON_throw",
+ "WEAPON_throwu",
+ "WEAPON_start_throw",
+};
+char const* aFlamethrowerAnimations[] = {
+ "FLAME_fire",
+};
+char const* aMedicAnimations[] = {
+ "CPR",
+};
+char const* aSunbatheAnimations[] = {
+ "bather",
+ "batherdown",
+ "batherup",
+ "batherscape",
+};
+char const* aPlayerIdleAnimations[] = {
+ "stretch",
+ "time",
+ "shldr",
+ "strleg",
+};
+char const* aRiotAnimations[] = {
+ "riot_angry",
+ "riot_angry_b",
+ "riot_chant",
+ "riot_punches",
+ "riot_shout",
+ "riot_challenge",
+ "riot_fuku",
+};
+char const* aStripAnimations[] = {
+ "strip_A",
+ "strip_B",
+ "strip_C",
+ "strip_D",
+ "strip_E",
+ "strip_F",
+ "strip_G",
+};
+char const* aLanceAnimations[] = {
+ "lance",
+};
+char const* aPlayerAnimations[] = {
"walk_player",
"run_player",
"SPRINT_civi",
"IDLE_STANCE",
"walk_start",
};
-char const *aPlayerWithRocketAnimations[] = {
+char const* aPlayerWithRocketAnimations[] = {
"walk_rocket",
"run_rocket",
"run_rocket",
"idle_rocket",
"walk_start_rocket",
};
-char const *aPlayer1ArmedAnimations[] = {
+char const* aPlayer1ArmedAnimations[] = {
"walk_player",
"run_1armed",
"SPRINT_civi",
"IDLE_STANCE",
"walk_start",
};
-char const *aPlayer2ArmedAnimations[] = {
- "walk_player",
+char const* aPlayer2ArmedAnimations[] = {
+ "walk_armed",
"run_armed",
"run_armed",
- "idle_stance",
- "walk_start",
+ "idle_armed",
+ "walk_start_armed",
};
-char const *aPlayerBBBatAnimations[] = {
+char const* aPlayerBBBatAnimations[] = {
"walk_player",
"run_player",
"run_player",
"IDLE_STANCE",
"walk_start",
};
-char const *aShuffleAnimations[] = {
+char const* aPlayerChainsawAnimations[] = {
+ "walk_csaw",
+ "run_csaw",
+ "run_csaw",
+ "IDLE_csaw",
+ "walk_start_csaw",
+};
+char const* aShuffleAnimations[] = {
"WALK_shuffle",
"RUN_civi",
"SPRINT_civi",
"IDLE_STANCE",
};
-char const *aOldAnimations[] = {
+char const* aOldAnimations[] = {
"walk_old",
"run_civi",
"sprint_civi",
"idle_stance",
};
-char const *aGang1Animations[] = {
+char const* aGang1Animations[] = {
"walk_gang1",
"run_gang1",
"sprint_civi",
"idle_stance",
};
-char const *aGang2Animations[] = {
+char const* aGang2Animations[] = {
"walk_gang2",
"run_gang1",
"sprint_civi",
"idle_stance",
};
-char const *aFatAnimations[] = {
+char const* aFatAnimations[] = {
"walk_fat",
"run_civi",
"woman_runpanic",
"idle_stance",
};
-char const *aOldFatAnimations[] = {
+char const* aOldFatAnimations[] = {
"walk_fatold",
"run_fatold",
"woman_runpanic",
"idle_stance",
};
-char const *aStdWomanAnimations[] = {
+char const* aJoggerAnimations[] = {
+ "JOG_maleA",
+ "run_civi",
+ "sprint_civi",
+ "idle_stance",
+};
+char const* aStdWomanAnimations[] = {
"woman_walknorm",
"woman_run",
"woman_runpanic",
"woman_idlestance",
};
-char const *aWomanShopAnimations[] = {
+char const* aWomanShopAnimations[] = {
"woman_walkshop",
"woman_run",
"woman_run",
"woman_idlestance",
};
-char const *aBusyWomanAnimations[] = {
+char const* aBusyWomanAnimations[] = {
"woman_walkbusy",
"woman_run",
"woman_runpanic",
"woman_idlestance",
};
-char const *aSexyWomanAnimations[] = {
+char const* aSexyWomanAnimations[] = {
"woman_walksexy",
"woman_run",
"woman_runpanic",
"woman_idlestance",
};
-char const *aOldWomanAnimations[] = {
+char const* aFatWomanAnimations[] = {
+ "walk_fat",
+ "woman_run",
+ "woman_runpanic",
+ "woman_idlestance",
+};
+char const* aOldWomanAnimations[] = {
"woman_walkold",
"woman_run",
"woman_runpanic",
"woman_idlestance",
};
-char const *aFatWomanAnimations[] = {
- "walk_fat",
+char const* aJoggerWomanAnimations[] = {
+ "JOG_maleB",
"woman_run",
"woman_runpanic",
"woman_idlestance",
};
-char const *aPanicChunkyAnimations[] = {
+char const* aPanicChunkyAnimations[] = {
"run_fatold",
"woman_runpanic",
"woman_runpanic",
"idle_stance",
};
-char const *aPlayerStrafeBackAnimations[] = {
- "walk_player_back",
- "run_player_back",
- "run_player_back",
+char const* aSkateAnimations[] = {
+ "skate_run",
+ "skate_sprint",
+ "skate_sprint",
+ "skate_idle",
+};
+char const* aPlayerStrafeBackAnimations[] = {
+ "walk_back",
+ "run_back",
+ "run_back",
"IDLE_STANCE",
"walk_start_back",
};
-char const *aPlayerStrafeLeftAnimations[] = {
- "walk_player_left",
+char const* aPlayerStrafeLeftAnimations[] = {
+ "walk_left",
"run_left",
"run_left",
"IDLE_STANCE",
"walk_start_left",
};
-char const *aPlayerStrafeRightAnimations[] = {
- "walk_player_right",
+char const* aPlayerStrafeRightAnimations[] = {
+ "walk_right",
"run_right",
"run_right",
"IDLE_STANCE",
"walk_start_right",
};
-char const *aRocketStrafeBackAnimations[] = {
+char const* aRocketStrafeBackAnimations[] = {
"walk_rocket_back",
"run_rocket_back",
"run_rocket_back",
"idle_rocket",
"walkst_rocket_back",
};
-char const *aRocketStrafeLeftAnimations[] = {
+char const* aRocketStrafeLeftAnimations[] = {
"walk_rocket_left",
"run_rocket_left",
"run_rocket_left",
"idle_rocket",
"walkst_rocket_left",
};
-char const *aRocketStrafeRightAnimations[] = {
+char const* aRocketStrafeRightAnimations[] = {
"walk_rocket_right",
"run_rocket_right",
"run_rocket_right",
"idle_rocket",
"walkst_rocket_right",
};
+char const* aChainsawStrafeBackAnimations[] = {
+ "walk_csaw_back",
+ "run_csaw_back",
+ "run_csaw_back",
+ "idle_csaw",
+ "walkst_csaw_back",
+};
+char const* aChainsawStrafeLeftAnimations[] = {
+ "walk_csaw_left",
+ "run_csaw_left",
+ "run_csaw_left",
+ "idle_csaw",
+ "walkst_csaw_left",
+};
+char const* aChainsawStrafeRightAnimations[] = {
+ "walk_csaw_right",
+ "run_csaw_right",
+ "run_csaw_right",
+ "idle_csaw",
+ "walkst_csaw_right",
+};
+
#define awc(a) ARRAY_SIZE(a), a
const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = {
{ "man", "ped", MI_COP, awc(aStdAnimations), aStdAnimDescs },
+ { "van", "van", MI_COP, awc(aVanAnimations), aVanAnimDescs },
+ { "coach", "coach", MI_COP, awc(aCoachAnimations), aCoachAnimDescs },
+ { "bikes", "bikes", MI_COP, awc(aBikesAnimations), aBikeAnimDescs },
+ { "bikev", "bikev", MI_COP, awc(aBikevAnimations), aBikeAnimDescs },
+ { "bikeh", "bikeh", MI_COP, awc(aBikehAnimations), aBikeAnimDescs },
+ { "biked", "biked", MI_COP, awc(aBikedAnimations), aBikeAnimDescs },
+ { "unarmed", "ped", MI_COP, awc(aUnarmedAnimations), aMeleeAnimDescs },
+ { "screwdrv", "ped", MI_COP, awc(aScrewdriverAnimations), aMeleeAnimDescs },
+ { "knife", "knife", MI_COP, awc(aKnifeAnimations), aMeleeAnimDescs },
+ { "baseball", "baseball", MI_COP, awc(aBaseballbatAnimations), aSwingAnimDescs },
+ { "golfclub", "baseball", MI_COP, awc(aGolfclubAnimations), aSwingAnimDescs },
+ { "chainsaw", "chainsaw", MI_COP, awc(aChainsawAnimations), aMeleeAnimDescs },
+ { "python", "python", MI_COP, awc(aPythonAnimations), aWeaponAnimDescs },
+ { "colt45", "colt45", MI_COP, awc(aColtAnimations), aWeaponAnimDescs },
+ { "shotgun", "shotgun", MI_COP, awc(aShotgunAnimations), aWeaponAnimDescs },
+ { "buddy", "buddy", MI_COP, awc(aBuddyAnimations), aWeaponAnimDescs },
+ { "tec", "tec", MI_COP, awc(aTecAnimations), aWeaponAnimDescs },
+ { "uzi", "uzi", MI_COP, awc(aUziAnimations), aWeaponAnimDescs },
+ { "rifle", "rifle", MI_COP, awc(aRifleAnimations), aWeaponAnimDescs },
+ { "m60", "m60", MI_COP, awc(aM60Animations), aWeaponAnimDescs },
+ { "sniper", "sniper", MI_COP, awc(aSniperAnimations), aWeaponAnimDescs },
+ { "grenade", "grenade", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs },
+ { "flame", "flame", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs },
+ { "medic", "medic", MI_COP, awc(aMedicAnimations), aMedicAnimDescs },
+ { "sunbathe", "sunbathe", MI_COP, 1, aSunbatheAnimations, aSunbatheAnimDescs }, // NB: not using awc here!
+ { "playidles", "playidles", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs },
+ { "riot", "riot", MI_COP, awc(aRiotAnimations), aRiotAnimDescs },
+ { "strip", "strip", MI_COP, awc(aStripAnimations), aStripAnimDescs },
+ { "lance", "lance", MI_COP, awc(aLanceAnimations), aSunbatheAnimDescs },
{ "player", "ped", MI_COP, awc(aPlayerAnimations), aStdAnimDescs },
{ "playerrocket", "ped", MI_COP, awc(aPlayerWithRocketAnimations), aStdAnimDescs },
{ "player1armed", "ped", MI_COP, awc(aPlayer1ArmedAnimations), aStdAnimDescs },
{ "player2armed", "ped", MI_COP, awc(aPlayer2ArmedAnimations), aStdAnimDescs },
{ "playerBBBat", "ped", MI_COP, awc(aPlayerBBBatAnimations), aStdAnimDescs },
+ { "playercsaw", "ped", MI_COP, awc(aPlayerChainsawAnimations), aStdAnimDescs },
{ "shuffle", "ped", MI_COP, awc(aShuffleAnimations), aStdAnimDescs },
{ "oldman", "ped", MI_COP, awc(aOldAnimations), aStdAnimDescs },
{ "gang1", "ped", MI_COP, awc(aGang1Animations), aStdAnimDescs },
{ "gang2", "ped", MI_COP, awc(aGang2Animations), aStdAnimDescs },
{ "fatman", "ped", MI_COP, awc(aFatAnimations), aStdAnimDescs },
{ "oldfatman", "ped", MI_COP, awc(aOldFatAnimations), aStdAnimDescs },
+ { "jogger", "ped", MI_COP, awc(aJoggerAnimations), aStdAnimDescs },
{ "woman", "ped", MI_COP, awc(aStdWomanAnimations), aStdAnimDescs },
{ "shopping", "ped", MI_COP, awc(aWomanShopAnimations), aStdAnimDescs },
{ "busywoman", "ped", MI_COP, awc(aBusyWomanAnimations), aStdAnimDescs },
{ "sexywoman", "ped", MI_COP, awc(aSexyWomanAnimations), aStdAnimDescs },
- { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs },
{ "fatwoman", "ped", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs },
+ { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs },
+ { "jogwoman", "ped", MI_COP, awc(aJoggerWomanAnimations), aStdAnimDescs },
{ "panicchunky", "ped", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs },
+ { "skate", "skate", MI_COP, awc(aSkateAnimations), aStdAnimDescs },
{ "playerback", "ped", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs },
{ "playerleft", "ped", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide },
{ "playerright", "ped", MI_COP, awc(aPlayerStrafeRightAnimations), aStdAnimDescsSide },
{ "rocketback", "ped", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs },
{ "rocketleft", "ped", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide },
{ "rocketright", "ped", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide },
+ { "csawback", "ped", MI_COP, awc(aChainsawStrafeBackAnimations), aStdAnimDescs },
+ { "csawleft", "ped", MI_COP, awc(aChainsawStrafeLeftAnimations), aStdAnimDescsSide },
+ { "csawright", "ped", MI_COP, awc(aChainsawStrafeRightAnimations), aStdAnimDescsSide },
};
#undef awc
@@ -567,8 +971,6 @@ CAnimManager::Initialise(void)
ms_numAnimations = 0;
ms_numAnimBlocks = 0;
ms_animCache.Init(25);
-
-// dumpanimdata();
}
void
@@ -576,31 +978,48 @@ CAnimManager::Shutdown(void)
{
int i;
- ms_animCache.Shutdown();
+ for(i = 0; i < NUMANIMBLOCKS; i++)
+ CStreaming::RemoveAnim(i);
for(i = 0; i < ms_numAnimations; i++)
ms_aAnimations[i].Shutdown();
+ ms_animCache.Shutdown();
+
delete[] ms_aAnimAssocGroups;
}
void
CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier)
{
- if(!hier->compressed){
- if(hier->linkPtr){
- hier->linkPtr->Remove();
- ms_animCache.head.Insert(hier->linkPtr);
- }
+ if(hier->compressed2){
+ if(hier->totalLength == 0.0f)
+ hier->CalcTotalTimeCompressed();
}else{
- CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
- if(link == nil){
- ms_animCache.tail.prev->item->RemoveUncompressedData();
- ms_animCache.Remove(ms_animCache.tail.prev);
- link = ms_animCache.Insert(hier);
+ if(!hier->compressed){
+ if(hier->linkPtr){
+ hier->linkPtr->Remove();
+ ms_animCache.head.Insert(hier->linkPtr);
+ }
+ }else{
+ CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
+ if(link == nil){
+ ms_animCache.tail.prev->item->RemoveUncompressedData();
+ ms_animCache.Remove(ms_animCache.tail.prev);
+ link = ms_animCache.Insert(hier);
+ }
+ hier->linkPtr = link;
+ hier->Uncompress();
}
- hier->linkPtr = link;
- hier->Uncompress();
+ }
+}
+
+void
+CAnimManager::RemoveFromUncompressedCache(CAnimBlendHierarchy *hier)
+{
+ if(hier->linkPtr){
+ ms_animCache.Remove(hier->linkPtr);
+ hier->linkPtr = nil;
}
}
@@ -615,6 +1034,73 @@ CAnimManager::GetAnimationBlock(const char *name)
return nil;
}
+int32
+CAnimManager::GetAnimationBlockIndex(const char *name)
+{
+ int i;
+
+ for(i = 0; i < ms_numAnimBlocks; i++)
+ if(strcasecmp(ms_aAnimBlocks[i].name, name) == 0)
+ return i;
+ return -1;
+}
+
+int32
+CAnimManager::RegisterAnimBlock(const char *name)
+{
+ CAnimBlock *animBlock = GetAnimationBlock(name);
+ if(animBlock == nil){
+ animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
+ strncpy(animBlock->name, name, MAX_ANIMBLOCK_NAME);
+ animBlock->numAnims = 0;
+ assert(animBlock->refCount == 0);
+ }
+ return animBlock - ms_aAnimBlocks;
+}
+
+int32
+CAnimManager::GetNumRefsToAnimBlock(int32 block)
+{
+ return ms_aAnimBlocks[block].refCount;
+}
+
+void
+CAnimManager::AddAnimBlockRef(int32 block)
+{
+ ms_aAnimBlocks[block].refCount++;
+}
+
+void
+CAnimManager::RemoveAnimBlockRefWithoutDelete(int32 block)
+{
+ ms_aAnimBlocks[block].refCount--;
+}
+
+void
+CAnimManager::RemoveAnimBlockRef(int32 block)
+{
+ ms_aAnimBlocks[block].refCount--;
+ if(ms_aAnimBlocks[block].refCount == 0)
+ CStreaming::RemoveAnim(block);
+}
+
+void
+CAnimManager::RemoveAnimBlock(int32 block)
+{
+ int i;
+ CAnimBlock *animblock;
+
+ animblock = &ms_aAnimBlocks[block];
+ debug("Removing ANIMS %s\n", animblock->name);
+ for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++)
+ if(ms_aAnimAssocGroups[i].animBlock == animblock)
+ ms_aAnimAssocGroups[i].DestroyAssociations();
+ for(i = 0; i < animblock->numAnims; i++)
+ ms_aAnimations[animblock->firstIndex + i].Shutdown();
+ animblock->isLoaded = false;
+ animblock->refCount = 0;
+}
+
CAnimBlendHierarchy*
CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
{
@@ -622,7 +1108,7 @@ CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex];
for(i = 0; i < animBlock->numAnims; i++){
- if(!CGeneral::faststricmp(hier->name, name))
+ if(strcasecmp(hier->name, name) == 0)
return hier;
hier++;
}
@@ -743,23 +1229,34 @@ CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId a
void
CAnimManager::LoadAnimFiles(void)
{
- int i, j;
-
LoadAnimFile("ANIM\\PED.IFP");
-
- // Create all assoc groups
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
+ CreateAnimAssocGroups();
+}
+
+void
+CAnimManager::CreateAnimAssocGroups(void)
+{
+ int i, j;
+
for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){
+ CAnimBlock *block = GetAnimationBlock(ms_aAnimAssocDefinitions[i].blockName);
+ if(block == nil || !block->isLoaded || ms_aAnimAssocGroups[i].assocList)
+ continue;
+
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex);
RpClump *clump = (RpClump*)mi->CreateInstance();
RpAnimBlendClumpInit(clump);
CAnimBlendAssocGroup *group = &ms_aAnimAssocGroups[i];
const AnimAssocDefinition *def = &ms_aAnimAssocDefinitions[i];
+ group->groupId = i;
+ group->firstAnimId = def->animDescs[0].animId;
group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims);
for(j = 0; j < group->numAssociations; j++)
- group->GetAnimation(j)->flags |= def->animDescs[j].flags;
+
+ // GetAnimation(i) in III (but it's in LoadAnimFiles), GetAnimation(group->animDesc[j].animId) in VC
+ group->GetAnimation(def->animDescs[j].animId)->flags |= def->animDescs[j].flags;
#ifdef PED_SKIN
- // forgot on xbox/android
if(IsClumpSkinned(clump))
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
#endif
@@ -770,15 +1267,16 @@ CAnimManager::LoadAnimFiles(void)
void
CAnimManager::LoadAnimFile(const char *filename)
{
- int fd;
- fd = CFileMgr::OpenFile(filename, "rb");
- assert(fd > 0);
- LoadAnimFile(fd, true);
- CFileMgr::CloseFile(fd);
+ RwStream *stream;
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
+ assert(stream);
+ LoadAnimFile(stream, true);
+ RwStreamClose(stream, nil);
}
+//--MIAMI: done (except maybe implement some unimplemented compression?)
void
-CAnimManager::LoadAnimFile(int fd, bool compress)
+CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*somename)[32])
{
#define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3)
struct IfpHeader {
@@ -786,127 +1284,122 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
uint32 size;
};
IfpHeader anpk, info, name, dgan, cpan, anim;
- int numANPK;
char buf[256];
- int i, j, k, l;
+ int j, k, l;
float *fbuf = (float*)buf;
- CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
- if(strncmp(anpk.ident, "ANLF", 4) == 0){
- ROUNDSIZE(anpk.size);
- CFileMgr::Read(fd, buf, anpk.size);
- numANPK = *(int*)buf;
- }else if(strncmp(anpk.ident, "ANPK", 4) == 0){
- CFileMgr::Seek(fd, -8, 1);
- numANPK = 1;
+ // block name
+ RwStreamRead(stream, &anpk, sizeof(IfpHeader));
+ ROUNDSIZE(anpk.size);
+ RwStreamRead(stream, &info, sizeof(IfpHeader));
+ ROUNDSIZE(info.size);
+ RwStreamRead(stream, buf, info.size);
+ CAnimBlock *animBlock = GetAnimationBlock(buf+4);
+ if(animBlock){
+ if(animBlock->numAnims == 0){
+ animBlock->numAnims = *(int*)buf;
+ animBlock->firstIndex = ms_numAnimations;
+ }
+ }else{
+ animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
+ strncpy(animBlock->name, buf+4, MAX_ANIMBLOCK_NAME);
+ animBlock->numAnims = *(int*)buf;
+ animBlock->firstIndex = ms_numAnimations;
}
- for(i = 0; i < numANPK; i++){
- // block name
- CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
- ROUNDSIZE(anpk.size);
- CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
- ROUNDSIZE(info.size);
- CFileMgr::Read(fd, buf, info.size);
- CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
- strncpy(animBlock->name, buf+4, 24);
- animBlock->numAnims = *(int*)buf;
+ debug("Loading ANIMS %s\n", animBlock->name);
+ animBlock->isLoaded = true;
- animBlock->firstIndex = ms_numAnimations;
+ int animIndex = animBlock->firstIndex;
+ for(j = 0; j < animBlock->numAnims; j++){
+ assert(animIndex < ARRAY_SIZE(ms_aAnimations));
+ CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];
- for(j = 0; j < animBlock->numAnims; j++){
- CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++];
+ // animation name
+ RwStreamRead(stream, &name, sizeof(IfpHeader));
+ ROUNDSIZE(name.size);
+ RwStreamRead(stream, buf, name.size);
+ hier->SetName(buf);
- // animation name
- CFileMgr::Read(fd, (char*)&name, sizeof(IfpHeader));
- ROUNDSIZE(name.size);
- CFileMgr::Read(fd, buf, name.size);
- hier->SetName(buf);
+ // TODO(MIAMI)? some unused crap here
+ hier->compressed = false;
+ hier->compressed2 = false;
- // DG info has number of nodes/sequences
- CFileMgr::Read(fd, (char*)&dgan, sizeof(IfpHeader));
+ // DG info has number of nodes/sequences
+ RwStreamRead(stream, (char*)&dgan, sizeof(IfpHeader));
+ ROUNDSIZE(dgan.size);
+ RwStreamRead(stream, (char*)&info, sizeof(IfpHeader));
+ ROUNDSIZE(info.size);
+ RwStreamRead(stream, buf, info.size);
+ hier->numSequences = *(int*)buf;
+ hier->sequences = new CAnimBlendSequence[hier->numSequences];
+
+ CAnimBlendSequence *seq = hier->sequences;
+ for(k = 0; k < hier->numSequences; k++, seq++){
+ // Each node has a name and key frames
+ RwStreamRead(stream, &cpan, sizeof(IfpHeader));
ROUNDSIZE(dgan.size);
- CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
- ROUNDSIZE(info.size);
- CFileMgr::Read(fd, buf, info.size);
- hier->numSequences = *(int*)buf;
- hier->sequences = new CAnimBlendSequence[hier->numSequences];
-
- CAnimBlendSequence *seq = hier->sequences;
- for(k = 0; k < hier->numSequences; k++, seq++){
- // Each node has a name and key frames
- CFileMgr::Read(fd, (char*)&cpan, sizeof(IfpHeader));
- ROUNDSIZE(dgan.size);
- CFileMgr::Read(fd, (char*)&anim, sizeof(IfpHeader));
- ROUNDSIZE(anim.size);
- CFileMgr::Read(fd, buf, anim.size);
- int numFrames = *(int*)(buf+28);
+ RwStreamRead(stream, &anim, sizeof(IfpHeader));
+ ROUNDSIZE(anim.size);
+ RwStreamRead(stream, buf, anim.size);
+ int numFrames = *(int*)(buf+28);
#ifdef PED_SKIN
- if(anim.size == 44)
- seq->SetBoneTag(*(int*)(buf+40));
+ if(anim.size == 44)
+ seq->SetBoneTag(*(int*)(buf+40));
#endif
- seq->SetName(buf);
- if(numFrames == 0)
- continue;
-
- CFileMgr::Read(fd, (char*)&info, sizeof(info));
- if(strncmp(info.ident, "KR00", 4) == 0){
- seq->SetNumFrames(numFrames, false);
- KeyFrame *kf = seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x14);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->deltaTime = fbuf[4]; // absolute time here
- }
- }else if(strncmp(info.ident, "KRT0", 4) == 0){
- seq->SetNumFrames(numFrames, true);
- KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x20);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->translation.x = fbuf[4];
- kf->translation.y = fbuf[5];
- kf->translation.z = fbuf[6];
- kf->deltaTime = fbuf[7]; // absolute time here
- }
- }else if(strncmp(info.ident, "KRTS", 4) == 0){
- seq->SetNumFrames(numFrames, true);
- KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x2C);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->translation.x = fbuf[4];
- kf->translation.y = fbuf[5];
- kf->translation.z = fbuf[6];
- // scaling ignored
- kf->deltaTime = fbuf[10]; // absolute time here
- }
- }
+ seq->SetName(buf);
+ if(numFrames == 0)
+ continue;
- // convert absolute time to deltas
- for(l = seq->numFrames-1; l > 0; l--){
- KeyFrame *kf1 = seq->GetKeyFrame(l);
- KeyFrame *kf2 = seq->GetKeyFrame(l-1);
- kf1->deltaTime -= kf2->deltaTime;
+ RwStreamRead(stream, &info, sizeof(info));
+ if(strncmp(info.ident, "KR00", 4) == 0){
+ seq->SetNumFrames(numFrames, false, false);
+ KeyFrame *kf = seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x14);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->deltaTime = fbuf[4]; // absolute time here
+ }
+ }else if(strncmp(info.ident, "KRT0", 4) == 0){
+ seq->SetNumFrames(numFrames, true, false);
+ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x20);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->translation.x = fbuf[4];
+ kf->translation.y = fbuf[5];
+ kf->translation.z = fbuf[6];
+ kf->deltaTime = fbuf[7]; // absolute time here
+ }
+ }else if(strncmp(info.ident, "KRTS", 4) == 0){
+ seq->SetNumFrames(numFrames, true, false);
+ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x2C);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->translation.x = fbuf[4];
+ kf->translation.y = fbuf[5];
+ kf->translation.z = fbuf[6];
+ // scaling ignored
+ kf->deltaTime = fbuf[10]; // absolute time here
}
}
-
- hier->RemoveQuaternionFlips();
- if(compress)
- hier->RemoveUncompressedData();
- else
- hier->CalcTotalTime();
}
+
+ hier->RemoveQuaternionFlips();
+ hier->CalcTotalTime();
}
+ if(animIndex > ms_numAnimations)
+ ms_numAnimations = animIndex;
}
void
@@ -916,5 +1409,6 @@ CAnimManager::RemoveLastAnimFile(void)
ms_numAnimBlocks--;
ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex;
for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++)
- ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].RemoveAnimSequences();
+ ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].Shutdown();
+ ms_aAnimBlocks[ms_numAnimBlocks].isLoaded = false;
}
diff --git a/src/animation/AnimManager.h b/src/animation/AnimManager.h
index de15602c..905cac6c 100644
--- a/src/animation/AnimManager.h
+++ b/src/animation/AnimManager.h
@@ -6,30 +6,66 @@
enum AssocGroupId
{
ASSOCGRP_STD,
+ ASSOCGRP_VAN,
+ ASSOCGRP_COACH,
+ ASSOCGRP_BIKES,
+ ASSOCGRP_BIKEV,
+ ASSOCGRP_BIKEH,
+ ASSOCGRP_BIKED,
+ ASSOCGRP_UNARMED,
+ ASSOCGRP_SCREWDRIVER,
+ ASSOCGRP_KNIFE,
+ ASSOCGRP_BASEBALLBAT,
+ ASSOCGRP_GOLFCLUB,
+ ASSOCGRP_CHAINSAW,
+ ASSOCGRP_PYTHON,
+ ASSOCGRP_COLT,
+ ASSOCGRP_SHOTGUN,
+ ASSOCGRP_BUDDY,
+ ASSOCGRP_TEC,
+ ASSOCGRP_UZI,
+ ASSOCGRP_RIFLE,
+ ASSOCGRP_M60,
+ ASSOCGRP_SNIPER,
+ ASSOCGRP_THROW,
+ ASSOCGRP_FLAMETHROWER,
+ ASSOCGRP_MEDIC,
+ ASSOCGRP_SUNBATHE,
+ ASSOCGRP_PLAYER_IDLE,
+ ASSOCGRP_RIOT,
+ ASSOCGRP_STRIP,
+ ASSOCGRP_LANCE,
ASSOCGRP_PLAYER,
ASSOCGRP_PLAYERROCKET,
ASSOCGRP_PLAYER1ARMED,
ASSOCGRP_PLAYER2ARMED,
ASSOCGRP_PLAYERBBBAT,
+ ASSOCGRP_PLAYERCHAINSAW,
ASSOCGRP_SHUFFLE,
ASSOCGRP_OLD,
ASSOCGRP_GANG1,
ASSOCGRP_GANG2,
ASSOCGRP_FAT,
ASSOCGRP_OLDFAT,
+ ASSOCGRP_JOGGER,
ASSOCGRP_WOMAN,
ASSOCGRP_WOMANSHOP,
ASSOCGRP_BUSYWOMAN,
ASSOCGRP_SEXYWOMAN,
- ASSOCGRP_OLDWOMAN,
ASSOCGRP_FATWOMAN,
+ ASSOCGRP_OLDWOMAN,
+ ASSOCGRP_JOGWOMAN,
ASSOCGRP_PANICCHUNKY,
+ ASSOCGRP_SKATE,
ASSOCGRP_PLAYERBACK,
ASSOCGRP_PLAYERLEFT,
ASSOCGRP_PLAYERRIGHT,
ASSOCGRP_ROCKETBACK,
ASSOCGRP_ROCKETLEFT,
ASSOCGRP_ROCKETRIGHT,
+ ASSOCGRP_CHAINSAWBACK,
+ ASSOCGRP_CHAINSAWLEFT,
+ ASSOCGRP_CHAINSAWRIGHT,
NUM_ANIM_ASSOC_GROUPS
};
@@ -37,11 +73,15 @@ enum AssocGroupId
class CAnimBlendAssociation;
class CAnimBlendAssocGroup;
+#define MAX_ANIMBLOCK_NAME 20
+
// A block of hierarchies
struct CAnimBlock
{
- char name[24];
- int32 firstIndex;
+ char name[MAX_ANIMBLOCK_NAME];
+ bool isLoaded;
+ int16 refCount;
+ int32 firstIndex; // first animtion in ms_aAnimations
int32 numAnims;
};
@@ -75,7 +115,16 @@ public:
static void Initialise(void);
static void Shutdown(void);
static void UncompressAnimation(CAnimBlendHierarchy *anim);
+ static void RemoveFromUncompressedCache(CAnimBlendHierarchy *hier);
+ static CAnimBlock *GetAnimationBlock(int32 block) { return &ms_aAnimBlocks[block]; }
static CAnimBlock *GetAnimationBlock(const char *name);
+ static int32 GetAnimationBlockIndex(const char *name);
+ static int32 RegisterAnimBlock(const char *name);
+ static int32 GetNumRefsToAnimBlock(int32 block);
+ static void AddAnimBlockRef(int32 block);
+ static void RemoveAnimBlockRefWithoutDelete(int32 block);
+ static void RemoveAnimBlockRef(int32 block);
+ static void RemoveAnimBlock(int32 block);
static CAnimBlendHierarchy *GetAnimation(const char *name, CAnimBlock *animBlock);
static CAnimBlendHierarchy *GetAnimation(int32 n) { return &ms_aAnimations[n]; }
static const char *GetAnimGroupName(AssocGroupId groupId);
@@ -87,6 +136,7 @@ public:
static CAnimBlendAssociation *BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta);
static void LoadAnimFiles(void);
static void LoadAnimFile(const char *filename);
- static void LoadAnimFile(int fd, bool compress);
+ static void LoadAnimFile(RwStream *stream, bool compress, char (*somename)[32] = nil);
+ static void CreateAnimAssocGroups(void);
static void RemoveLastAnimFile(void);
};
diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h
index 82fed8bd..a84aa3e8 100644
--- a/src/animation/AnimationId.h
+++ b/src/animation/AnimationId.h
@@ -47,27 +47,6 @@ enum AnimationId
ANIM_HIT_WALL,
ANIM_FLOOR_HIT_F,
ANIM_HIT_BEHIND,
- ANIM_PUNCH_R,
- ANIM_KICK_FLOOR,
- ANIM_WEAPON_BAT_H,
- ANIM_WEAPON_BAT_V,
- ANIM_WEAPON_HGUN_BODY,
- ANIM_WEAPON_AK_BODY,
- ANIM_WEAPON_PUMP,
- ANIM_WEAPON_SNIPER,
- ANIM_WEAPON_THROW,
- ANIM_WEAPON_THROWU,
- ANIM_WEAPON_START_THROW,
- ANIM_BOMBER,
- ANIM_HGUN_RELOAD,
- ANIM_AK_RELOAD,
- ANIM_FPS_PUNCH,
- ANIM_FPS_BAT,
- ANIM_FPS_UZI,
- ANIM_FPS_PUMP,
- ANIM_FPS_AK,
- ANIM_FPS_M16,
- ANIM_FPS_ROCKET,
ANIM_FIGHT_IDLE,
ANIM_FIGHT2_IDLE,
ANIM_FIGHT_SH_F,
@@ -80,6 +59,21 @@ enum AnimationId
ANIM_FIGHT_ROUNDHOUSE,
ANIM_FIGHT_LONGKICK,
ANIM_FIGHT_PPUNCH,
+
+ ANIM_FIGHT_JAB,
+ ANIM_FIGHT_ELBOW_L,
+ ANIM_FIGHT_ELBOW_R,
+ ANIM_FIGHT_BKICK_L,
+ ANIM_FIGHT_BKICK_R,
+
+ ANIM_BOMBER,
+ ANIM_PUNCH_R,
+ ANIM_FIGHT_PPUNCH2,
+ ANIM_KICK_FLOOR,
+
+ ANIM_WEAPON_THROWU,
+ ANIM_FIGHT_SH_BACK,
+
ANIM_CAR_JACKED_RHS,
ANIM_CAR_LJACKED_RHS,
ANIM_CAR_JACKED_LHS,
@@ -98,6 +92,7 @@ enum AnimationId
ANIM_CAR_CLOSEDOOR_LOW_LHS,
ANIM_CAR_ROLLDOOR,
ANIM_CAR_ROLLDOOR_LOW,
+ ANIM_CAR_JUMPIN_LHS,
ANIM_CAR_GETOUT_LHS,
ANIM_CAR_GETOUT_LOW_LHS,
ANIM_CAR_CLOSE_LHS,
@@ -123,29 +118,36 @@ enum AnimationId
ANIM_DRIVE_LOW_R,
ANIM_DRIVEBY_L,
ANIM_DRIVEBY_R,
+ ANIM_DRIVEBY_LOW_L,
+ ANIM_DRIVEBY_LOW_R,
ANIM_CAR_LB,
ANIM_DRIVE_BOAT,
+ ANIM_DRIVE_BOAT_L,
+ ANIM_DRIVE_BOAT_R,
+ ANIM_BOAT_LB,
+
+ ANIM_BIKE_PICKUP_R,
+ ANIM_BIKE_PICKUP_L,
+ ANIM_BIKE_PULLUP_R,
+ ANIM_BIKE_PULLUP_L,
+ ANIM_BIKE_ELBOW_R,
+ ANIM_BIKE_ELBOW_L,
+ ANIM_BIKE_FALL_OFF,
+ ANIM_BIKE_FALL_R,
+
ANIM_CAR_GETOUT_RHS,
ANIM_CAR_GETOUT_LOW_RHS,
ANIM_CAR_CLOSE_RHS,
ANIM_CAR_HOOKERTALK,
- ANIM_COACH_OPEN_L,
- ANIM_COACH_OPEN_R,
- ANIM_COACH_IN_L,
- ANIM_COACH_IN_R,
- ANIM_COACH_OUT_L,
- ANIM_TRAIN_GETIN,
- ANIM_TRAIN_GETOUT,
+
+ ANIM_IDLE_STANCE2,
+ ANIM_IDLE_STANCE3,
+
ANIM_CAR_CRAWLOUT_RHS,
ANIM_CAR_CRAWLOUT_RHS2,
- ANIM_VAN_OPEN_L,
- ANIM_VAN_GETIN_L,
- ANIM_VAN_CLOSE_L,
- ANIM_VAN_GETOUT_L,
- ANIM_VAN_OPEN,
- ANIM_VAN_GETIN,
- ANIM_VAN_CLOSE,
- ANIM_VAN_GETOUT,
+ ANIM_CAR_ROLLOUT_LHS,
+ ANIM_CAR_ROLLOUT_LHS2, // was this meant to be RHS?
+
ANIM_GETUP1,
ANIM_GETUP2,
ANIM_GETUP3,
@@ -157,6 +159,9 @@ enum AnimationId
ANIM_FALL_GLIDE,
ANIM_FALL_LAND,
ANIM_FALL_COLLAPSE,
+ ANIM_FALL_BACK,
+ ANIM_FALL_FRONT,
+
ANIM_EV_STEP,
ANIM_EV_DIVE,
ANIM_XPRESS_SCRATCH,
@@ -164,11 +169,12 @@ enum AnimationId
ANIM_TURN_180,
ANIM_ARREST_GUN,
ANIM_DROWN,
- ANIM_CPR,
ANIM_DUCK_DOWN,
ANIM_DUCK_LOW,
+
+ ANIM_WEAPON_CROUCH,
+
ANIM_RBLOCK_CSHOOT,
- ANIM_WEAPON_THROWU2,
ANIM_HANDSUP,
ANIM_HANDSCOWER,
ANIM_FUCKU,
@@ -176,5 +182,90 @@ enum AnimationId
ANIM_PHONE_OUT,
ANIM_PHONE_TALK,
+ ANIM_SEAT_DOWN,
+ ANIM_SEAT_UP,
+ ANIM_SEAT_IDLE,
+ ANIM_SEAT_DOWN2,
+ ANIM_ATM,
+ ANIM_ABSEIL,
+
+ NUM_STD_ANIMS,
+
+ ANIM_VAN_OPEN_L,
+ ANIM_VAN_GETIN_L,
+ ANIM_VAN_CLOSE_L,
+ ANIM_VAN_GETOUT_L,
+ ANIM_VAN_OPEN,
+ ANIM_VAN_GETIN,
+ ANIM_VAN_CLOSE,
+ ANIM_VAN_GETOUT,
+
+ ANIM_COACH_OPEN_L,
+ ANIM_COACH_OPEN_R,
+ ANIM_COACH_IN_L,
+ ANIM_COACH_IN_R,
+ ANIM_COACH_OUT_L,
+
+ ANIM_BIKE_RIDE,
+ ANIM_BIKE_STILL,
+ ANIM_BIKE_LEFT,
+ ANIM_BIKE_RIGHT,
+ ANIM_BIKE_BACK,
+ ANIM_BIKE_FWD,
+ ANIM_BIKE_PUSHES,
+ ANIM_BIKE_JUMPON_R,
+ ANIM_BIKE_JUMPON_L,
+ ANIM_BIKE_KICK,
+ ANIM_BIKE_HIT,
+ ANIM_BIKE_GETOFF_RHS,
+ ANIM_BIKE_GETOFF_LHS,
+ ANIM_BIKE_GETOFF_BACK,
+ ANIM_BIKE_DRIVEBY_RHS,
+ ANIM_BIKE_DRIVEBY_LHS,
+ ANIM_BIKE_DRIVEBY_FT,
+ ANIM_BIKE_PASSENGER,
+
+ ANIM_WEAPON_FIRE,
+ ANIM_WEAPON_CROUCHFIRE,
+ ANIM_WEAPON_RELOAD,
+ ANIM_WEAPON_CROUCHRELOAD,
+ ANIM_WEAPON_SPECIAL,
+ ANIM_MELEE_ATTACK = ANIM_WEAPON_FIRE,
+ ANIM_MELEE_ATTACK_2ND,
+ ANIM_MELEE_ATTACK_START,
+ ANIM_THROWABLE_THROW = ANIM_WEAPON_FIRE,
+ ANIM_THROWABLE_THROWU,
+ ANIM_THROWABLE_START_THROW,
+ ANIM_WEAPON_FIRE_2ND = ANIM_WEAPON_CROUCHFIRE,
+ ANIM_WEAPON_FIRE_3RD = ANIM_WEAPON_SPECIAL,
+
+ ANIM_SUNBATHE,
+ ANIM_SUNBATHE_DOWN,
+ ANIM_SUNBATHE_UP,
+ ANIM_SUNBATHE_ESCAPE,
+
+ ANIM_CPR,
+
+ ANIM_IDLE_STRETCH,
+ ANIM_IDLE_TIME,
+ ANIM_IDLE_SHOULDER,
+ ANIM_IDLE_STRETCH_LEG,
+
+ ANIM_RIOT_ANGRY,
+ ANIM_RIOT_ANGRY_B,
+ ANIM_RIOT_CHANT,
+ ANIM_RIOT_PUNCHES,
+ ANIM_RIOT_SHOUT,
+ ANIM_RIOT_CHALLENGE,
+ ANIM_RIOT_FUKU,
+
+ ANIM_STRIP_A,
+ ANIM_STRIP_B,
+ ANIM_STRIP_C,
+ ANIM_STRIP_D,
+ ANIM_STRIP_E,
+ ANIM_STRIP_F,
+ ANIM_STRIP_G,
+
NUM_ANIMS
}; \ No newline at end of file
diff --git a/src/animation/Bones.cpp b/src/animation/Bones.cpp
index 1608449d..87f3b6e7 100644
--- a/src/animation/Bones.cpp
+++ b/src/animation/Bones.cpp
@@ -2,26 +2,29 @@
#include "PedModelInfo.h"
#include "Bones.h"
-#ifdef PED_SKIN
-
int
ConvertPedNode2BoneTag(int node)
{
switch(node){
- case PED_TORSO: return BONE_waist;
- case PED_MID: return BONE_torso; // this is what Xbox/Mobile use
- // return BONE_mid; // this is what PS2/PC use
- case PED_HEAD: return BONE_head;
- case PED_UPPERARML: return BONE_upperarml;
- case PED_UPPERARMR: return BONE_upperarmr;
- case PED_HANDL: return BONE_Lhand;
- case PED_HANDR: return BONE_Rhand;
- case PED_UPPERLEGL: return BONE_upperlegl;
- case PED_UPPERLEGR: return BONE_upperlegr;
- case PED_FOOTL: return BONE_footl;
- case PED_FOOTR: return BONE_footr;
- case PED_LOWERLEGR: return BONE_lowerlegl;
+ case PED_MID: return BONE_spine1;
+ case PED_HEAD: return BONE_head;
+ case PED_UPPERARML: return BONE_l_upperarm;
+ case PED_UPPERARMR: return BONE_r_upperarm;
+ case PED_HANDL: return BONE_l_hand;
+ case PED_HANDR: return BONE_r_hand;
+ case PED_UPPERLEGL: return BONE_l_thigh;
+ case PED_UPPERLEGR: return BONE_r_thigh;
+ case PED_FOOTL: return BONE_l_foot;
+ case PED_FOOTR: return BONE_r_foot;
+ case PED_LOWERLEGR: return BONE_r_calf;
+ case PED_LOWERLEGL: return BONE_l_calf;
+ case PED_FOREARML: return BONE_l_forearm;
+ case PED_FOREARMR: return BONE_r_forearm;
+ case PED_CLAVICLEL: return BONE_l_clavicle;
+ case PED_CLAVICLER: return BONE_r_clavicle;
+ case PED_NECK: return BONE_neck;
}
+ assert(0 && "this node has no bone");
return -1;
}
@@ -29,24 +32,28 @@ const char*
ConvertBoneTag2BoneName(int tag)
{
switch(tag){
- case BONE_waist: return "Swaist";
- case BONE_upperlegr: return "Supperlegr";
- case BONE_lowerlegr: return "Slowerlegr";
- case BONE_footr: return "Sfootr";
- case BONE_upperlegl: return "Supperlegl";
- case BONE_lowerlegl: return "Slowerlegl";
- case BONE_footl: return "Sfootl";
- case BONE_mid: return "Smid";
- case BONE_torso: return "Storso";
- case BONE_head: return "Shead";
- case BONE_upperarmr: return "Supperarmr";
- case BONE_lowerarmr: return "Slowerarmr";
- case BONE_Rhand: return "SRhand";
- case BONE_upperarml: return "Supperarml";
- case BONE_lowerarml: return "Slowerarml";
- case BONE_Lhand: return "SLhand";
+ case BONE_root: return "Root";
+ case BONE_pelvis: return "Pelvis";
+ case BONE_spine: return "Spine";
+ case BONE_spine1: return "Spine1";
+ case BONE_neck: return "Neck";
+ case BONE_head: return "Head";
+ case BONE_r_clavicle: return "Bip01 R Clavicle";
+ case BONE_r_upperarm: return "R UpperArm";
+ case BONE_r_forearm: return "R Forearm";
+ case BONE_r_hand: return "R Hand";
+ case BONE_r_finger: return "R Fingers";
+ case BONE_l_clavicle: return "Bip01 L Clavicle";
+ case BONE_l_upperarm: return "L UpperArm";
+ case BONE_l_forearm: return "L Forearm";
+ case BONE_l_hand: return "L Hand";
+ case BONE_l_finger: return "L Fingers";
+ case BONE_l_thigh: return "L Thigh";
+ case BONE_l_calf: return "L Calf";
+ case BONE_l_foot: return "L Foot";
+ case BONE_r_thigh: return "R Thigh";
+ case BONE_r_calf: return "R Calf";
+ case BONE_r_foot: return "R Foot";
}
return nil;
}
-
-#endif
diff --git a/src/animation/Bones.h b/src/animation/Bones.h
index 38d91ba3..e133fd7f 100644
--- a/src/animation/Bones.h
+++ b/src/animation/Bones.h
@@ -2,22 +2,28 @@
enum BoneTag
{
- BONE_waist,
- BONE_upperlegr,
- BONE_lowerlegr,
- BONE_footr,
- BONE_upperlegl,
- BONE_lowerlegl,
- BONE_footl,
- BONE_mid,
- BONE_torso,
- BONE_head,
- BONE_upperarmr,
- BONE_lowerarmr,
- BONE_Rhand,
- BONE_upperarml,
- BONE_lowerarml,
- BONE_Lhand,
+ BONE_root = 0,
+ BONE_pelvis = 1,
+ BONE_spine = 2,
+ BONE_spine1 = 3,
+ BONE_neck = 4,
+ BONE_head = 5,
+ BONE_l_clavicle = 31,
+ BONE_l_upperarm = 32,
+ BONE_l_forearm = 33,
+ BONE_l_hand = 34,
+ BONE_l_finger = 35,
+ BONE_r_clavicle = 21,
+ BONE_r_upperarm = 22,
+ BONE_r_forearm = 23,
+ BONE_r_hand = 24,
+ BONE_r_finger = 25,
+ BONE_l_thigh = 41,
+ BONE_l_calf = 42,
+ BONE_l_foot = 43,
+ BONE_r_thigh = 51,
+ BONE_r_calf = 52,
+ BONE_r_foot = 53,
};
int ConvertPedNode2BoneTag(int node);
diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp
index 230e22fb..8da34dda 100644
--- a/src/animation/CutsceneMgr.cpp
+++ b/src/animation/CutsceneMgr.cpp
@@ -16,7 +16,6 @@
#include "World.h"
#include "PlayerPed.h"
#include "Wanted.h"
-#include "CutsceneHead.h"
#include "RpAnimBlend.h"
#include "ModelIndices.h"
#include "TempColModels.h"
@@ -185,23 +184,28 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
CGame::DrasticTidyUpMemory(true);
strcpy(ms_cutsceneName, szCutsceneName);
- file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
+
+ RwStream *stream;
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
+ assert(stream);
// Load animations
sprintf(gString, "%s.IFP", szCutsceneName);
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
CStreaming::MakeSpaceFor(size << 11);
CStreaming::ImGonnaUseStreamingMemory();
- CFileMgr::Seek(file, offset << 11, SEEK_SET);
- CAnimManager::LoadAnimFile(file, false);
+ RwStreamSkip(stream, offset << 11);
+ CAnimManager::LoadAnimFile(stream, false);
ms_cutsceneAssociations.CreateAssociations(szCutsceneName);
CStreaming::IHaveUsedStreamingMemory();
ms_animLoaded = true;
} else {
ms_animLoaded = false;
}
+ RwStreamClose(stream, nil);
// Load camera data
+ file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
sprintf(gString, "%s.DAT", szCutsceneName);
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
CFileMgr::Seek(file, offset << 11, SEEK_SET);
@@ -235,16 +239,6 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
}
void
-CCutsceneMgr::SetHeadAnim(const char *animName, CObject *pObject)
-{
- CCutsceneHead *pCutsceneHead = (CCutsceneHead*)pObject;
- char szAnim[CUTSCENENAMESIZE * 2];
-
- sprintf(szAnim, "%s_%s", ms_cutsceneName, animName);
- pCutsceneHead->PlayAnimation(szAnim);
-}
-
-void
CCutsceneMgr::FinishCutscene()
{
CCutsceneMgr::ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f;
@@ -302,11 +296,7 @@ CCutsceneMgr::SetCutsceneAnim(const char *animName, CObject *pObject)
CCutsceneHead *
CCutsceneMgr::AddCutsceneHead(CObject *pObject, int modelId)
{
- CCutsceneHead *pHead = new CCutsceneHead(pObject);
- pHead->SetModelIndex(modelId);
- CWorld::Add(pHead);
- ms_pCutsceneObjects[ms_numCutsceneObjs++] = pHead;
- return pHead;
+ return nil;
}
CCutsceneObject *
diff --git a/src/animation/CutsceneMgr.h b/src/animation/CutsceneMgr.h
index bfdcdb57..18eff0e5 100644
--- a/src/animation/CutsceneMgr.h
+++ b/src/animation/CutsceneMgr.h
@@ -41,7 +41,6 @@ public:
static void Shutdown(void);
static void LoadCutsceneData(const char *szCutsceneName);
static void FinishCutscene(void);
- static void SetHeadAnim(const char *animName, CObject *pObject);
static void SetupCutsceneToStart(void);
static void SetCutsceneAnim(const char *animName, CObject *pObject);
static CCutsceneHead *AddCutsceneHead(CObject *pObject, int modelId);
diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp
index a3a2013a..b886e95d 100644
--- a/src/animation/FrameUpdate.cpp
+++ b/src/animation/FrameUpdate.cpp
@@ -6,6 +6,8 @@
#include "AnimBlendAssociation.h"
#include "RpAnimBlend.h"
+//--MIAMI: file done
+
CAnimBlendClumpData *gpAnimBlendClump;
// PS2 names without "NonSkinned"
@@ -17,7 +19,6 @@ void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);
void FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);
void FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);
-
void
FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg)
{
@@ -228,8 +229,6 @@ FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame,
RwMatrixUpdate(mat);
}
-#ifdef PED_SKIN
-
void
FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg)
{
@@ -259,11 +258,9 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg)
(*node)->Update(vec, q, 1.0f-totalBlendAmount);
if((*node)->sequence->HasTranslation())
pos += vec;
-#ifdef FIX_BUGS
if(DotProduct(rot, q) < 0.0f)
rot -= q;
else
-#endif
rot += q;
}
++*node;
@@ -319,11 +316,9 @@ FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void
for(node = updateData->nodes; *node; node++){
if((*node)->sequence){
bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);
-#ifdef FIX_BUGS
if(DotProduct(rot, q) < 0.0f)
rot -= q;
else
-#endif
rot += q;
if((*node)->sequence->HasTranslation()){
pos += vec;
@@ -442,4 +437,9 @@ FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, vo
}
}
-#endif
+void
+FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg)
+{
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity)
+ FrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg);
+}
diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp
index be70ad66..8671e95d 100644
--- a/src/animation/RpAnimBlend.cpp
+++ b/src/animation/RpAnimBlend.cpp
@@ -9,9 +9,9 @@
#include "AnimBlendHierarchy.h"
#include "AnimBlendAssociation.h"
#include "RpAnimBlend.h"
-#ifdef PED_SKIN
#include "PedModelInfo.h"
-#endif
+
+//--MIAMI: file done
RwInt32 ClumpOffset;
@@ -141,7 +141,6 @@ FrameInitCBskin(AnimBlendFrameData *frameData, void*)
frameData->flag = 0;
}
-#ifdef PED_SKIN
void
RpAnimBlendClumpInitSkinned(RpClump *clump)
{
@@ -155,7 +154,7 @@ RpAnimBlendClumpInitSkinned(RpClump *clump)
RpAnimBlendAllocateData(clump);
clumpData = *RPANIMBLENDCLUMPDATA(clump);
- atomic = IsClumpSkinned(clump);
+ atomic = GetFirstAtomic(clump);
assert(atomic);
skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic));
assert(skin);
@@ -175,7 +174,6 @@ RpAnimBlendClumpInitSkinned(RpClump *clump)
clumpData->ForAllFrames(FrameInitCBskin, nil);
clumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION;
}
-#endif
void
RpAnimBlendClumpInitNotSkinned(RpClump *clump)
@@ -199,11 +197,9 @@ RpAnimBlendClumpInitNotSkinned(RpClump *clump)
void
RpAnimBlendClumpInit(RpClump *clump)
{
-#ifdef PED_SKIN
if(IsClumpSkinned(clump))
RpAnimBlendClumpInitSkinned(clump);
else
-#endif
RpAnimBlendClumpInitNotSkinned(clump);
}
@@ -363,7 +359,6 @@ FillFrameArrayCBnonskin(AnimBlendFrameData *frame, void *arg)
frames[CVisibilityPlugins::GetFrameHierarchyId(frame->frame)] = frame;
}
-#ifdef PED_SKIN
void
RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames)
{
@@ -373,22 +368,18 @@ RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames)
for(i = PED_MID; i < PED_NODE_MAX; i++)
frames[i] = &clumpData->frames[RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(i))];
}
-#endif
void
RpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames)
{
-#ifdef PED_SKIN
if(IsClumpSkinned(clump))
RpAnimBlendClumpFillFrameArraySkin(clump, frames);
else
-#endif
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FillFrameArrayCBnonskin, frames);
}
AnimBlendFrameData *pFrameDataFound;
-// FrameFindCallBack on PS2
void
FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
{
@@ -397,7 +388,6 @@ FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
pFrameDataFound = frame;
}
-#ifdef PED_SKIN
void
FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
{
@@ -405,25 +395,55 @@ FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
if(name && CGeneral::faststricmp(name, (char*)arg) == 0)
pFrameDataFound = frame;
}
-#endif
+
+void
+FrameFindByBoneCB(AnimBlendFrameData *frame, void *arg)
+{
+ if(frame->nodeID == (int32)(uintptr)arg)
+ pFrameDataFound = frame;
+}
AnimBlendFrameData*
RpAnimBlendClumpFindFrame(RpClump *clump, const char *name)
{
pFrameDataFound = nil;
-#ifdef PED_SKIN
if(IsClumpSkinned(clump))
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name);
else
-#endif
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name);
return pFrameDataFound;
}
+AnimBlendFrameData*
+RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag)
+{
+ pFrameDataFound = nil;
+ (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByBoneCB, (void*)boneTag);
+ return pFrameDataFound;
+}
+
void
-RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
+RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes)
{
+ CAnimBlendNode **node;
int i;
+
+ for(node = updateData->nodes; *node; node++){
+ CAnimBlendAssociation *a = (*node)->association;
+ for(i = 0; i < numNodes; i++)
+ if((frames[i].flag & AnimBlendFrameData::VELOCITY_EXTRACTION) == 0 ||
+ gpAnimBlendClump->velocity == nil){
+ if((*node)[i].sequence)
+ (*node)[i].FindKeyFrame(a->currentTime - a->timeStep);
+ }
+ }
+}
+
+void
+RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta, bool doRender)
+{
+ int i;
+ CAnimBlendAssociation *assoc;
AnimBlendFrameUpdateData updateData;
float totalLength = 0.0f;
float totalBlend = 0.0f;
@@ -439,30 +459,45 @@ RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
updateData.foobar = 0;
for(link = clumpData->link.next; link; link = next){
next = link->next;
- CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);
+ assoc = CAnimBlendAssociation::FromLink(link);
if(assoc->UpdateBlend(timeDelta)){
- // CAnimManager::UncompressAnimation(v6->hierarchy)
- updateData.nodes[i++] = assoc->GetNode(0);
- if(assoc->flags & ASSOC_MOVEMENT){
- totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount;
- totalBlend += assoc->blendAmount;
+ if(assoc->hierarchy->sequences){
+ //CAnimManager::UncompressAnimation(v6->hierarchy)
+ if(i < 11)
+ updateData.nodes[i++] = assoc->GetNode(0);
+ if(assoc->flags & ASSOC_MOVEMENT){
+ totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount;
+ totalBlend += assoc->blendAmount;
+ }else
+ updateData.foobar = 1;
}else
- updateData.foobar = 1;
+ debug("anim %s is not loaded\n", assoc->hierarchy->name);
}
}
+
+ for(link = clumpData->link.next; link; link = link->next){
+ assoc = CAnimBlendAssociation::FromLink(link);
+ assoc->UpdateTimeStep(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength);
+ }
+
updateData.nodes[i] = nil;
-#ifdef PED_SKIN
- if(IsClumpSkinned(clump))
- clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData);
- else
-#endif
- clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData);
+ if(doRender){
+ if(clumpData->frames[0].flag & AnimBlendFrameData::UPDATE_KEYFRAMES)
+ RpAnimBlendNodeUpdateKeyframes(clumpData->frames, &updateData, clumpData->numFrames);
+ if(IsClumpSkinned(clump))
+ clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData);
+ else
+ clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData);
+ clumpData->frames[0].flag &= ~AnimBlendFrameData::UPDATE_KEYFRAMES;
+ }else{
+ clumpData->ForAllFrames(FrameUpdateCallBackOffscreen, &updateData);
+ clumpData->frames[0].flag |= AnimBlendFrameData::UPDATE_KEYFRAMES;
+ }
for(link = clumpData->link.next; link; link = link->next){
- CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);
- float relSpeed = totalLength == 0.0f ? 1.0f : totalBlend/totalLength;
- assoc->UpdateTime(timeDelta, relSpeed);
+ assoc = CAnimBlendAssociation::FromLink(link);
+ assoc->UpdateTime(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength);
}
RwFrameUpdateObjects(RpClumpGetFrame(clump));
}
diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h
index 838c8816..d0f7a114 100644
--- a/src/animation/RpAnimBlend.h
+++ b/src/animation/RpAnimBlend.h
@@ -26,6 +26,7 @@ void RpAnimBlendClumpInit(RpClump *clump);
bool RpAnimBlendClumpIsInitialized(RpClump *clump);
void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames);
AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name);
+AnimBlendFrameData *RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag);
void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg);
CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id);
CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet);
@@ -34,9 +35,11 @@ CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation_N(RpClump *clump, int
CAnimBlendAssociation *RpAnimBlendClumpGetMainPartialAssociation_N(RpClump *clump, int n);
CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump, uint32 mask);
CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump);
-void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta);
+void RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes);
+void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta, bool doRender = true);
extern CAnimBlendClumpData *gpAnimBlendClump;
void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg);
void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg);
diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp
index 6f1a3432..9080a2dd 100644
--- a/src/audio/AudioLogic.cpp
+++ b/src/audio/AudioLogic.cpp
@@ -329,13 +329,13 @@ enum eVehicleModel {
LINERUN,
PEREN,
SENTINEL,
- PATRIOT,
+ RIO,
FIRETRUK,
TRASH,
STRETCH,
MANANA,
INFERNUS,
- BLISTA,
+ VOODOO,
PONY,
MULE,
CHEETAH,
@@ -344,11 +344,11 @@ enum eVehicleModel {
MOONBEAM,
ESPERANT,
TAXI,
- KURUMA,
+ WASHING,
BOBCAT,
MRWHOOP,
BFINJECT,
- CORPSE,
+ HUNTER,
POLICE,
ENFORCER,
SECURICA,
@@ -357,43 +357,83 @@ enum eVehicleModel {
BUS,
RHINO,
BARRACKS,
- TRAIN,
+ CUBAN,
CHOPPER,
- DODO,
+ ANGEL,
COACH,
CABBIE,
STALLION,
RUMPO,
RCBANDIT,
- BELLYUP,
- MRWONGS,
- MAFIA,
- YARDIE,
- YAKUZA,
- DIABLOS,
- COLUMB,
- HOODS,
+ ROMERO,
+ PACKER,
+ SENTXS,
+ ADMIRAL,
+ SQUALO,
+ SEASPAR,
+ PIZZABOY,
+ GANGBUR,
AIRTRAIN,
DEADDODO,
SPEEDER,
REEFER,
- PANLANT,
+ TROPIC,
FLATBED,
YANKEE,
- ESCAPE,
- BORGNINE,
- TOYZ,
- GHOST,
- CAR151,
- CAR152,
- CAR153,
- CAR154,
- CAR155,
- CAR156,
- CAR157,
- CAR158,
- CAR159,
- MAX_CARS
+ CADDY,
+ ZEBRA,
+ TOPFUN,
+ SKIMMER,
+ PCJ600,
+ FAGGIO,
+ FREEWAY,
+ RCBARON,
+ RCRAIDER,
+ GLENDALE,
+ OCEANIC,
+ SANCHEZ,
+ SPARROW,
+ PATRIOT,
+ LOVEFIST,
+ COASTG,
+ DINGHY,
+ HERMES,
+ SABRE,
+ SABRETUR,
+ PHEONIX,
+ WALTON,
+ REGINA,
+ COMET,
+ DELUXO,
+ BURRITO,
+ SPAND,
+ MARQUIS,
+ BAGGAGE,
+ KAUFMAN,
+ MAVERICK,
+ VCNMAV,
+ RANCHER,
+ FBIRANCH,
+ VIRGO,
+ GREENWOO,
+ JETMAX,
+ HOTRING,
+ SANDKING,
+ BLISTAC,
+ POLMAV,
+ BOXVILLE,
+ BENSON,
+ MESA,
+ RCGOBLIN,
+ HOTRINA,
+ HOTRINB,
+ BLOODRA,
+ BLOODRB,
+ VICECHEE,
+
+ // HACK so this compiles
+ // TODO(MIAMI): check it out
+ DODO = -1
};
@@ -407,76 +447,116 @@ struct tVehicleSampleData {
uint8 m_bDoorType;
};
-const tVehicleSampleData aVehicleSettings[MAX_CARS] = {{SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 10928, 1},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_ALARM_1, 8941, 0},
- {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_ALARM_1, 11922, 1},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 7948, 2},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_ALARM_1, 8941, 2},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_ALARM_1, 12220, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_ALARM_1, 12200, 1},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 13600, 1},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2},
- {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_ALARM_1, 8000, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_ALARM_1, 8543, 1},
- {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0},
- {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 10000, 0},
- {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_ALARM_1, 10123, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_ALARM_1, 10554, 3},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 8000, 2},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 3},
- {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_ALARM_1, 7500, 3},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_ALARM_1, 8935, 0},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 8935, 0},
- {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_ALARM_1, 17000, 0},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_ALARM_1, 9935, 1},
- {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9000, 0},
- {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0},
- {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}};
+const tVehicleSampleData aVehicleSettings[110] = { {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_HORN_JEEP, 10928, 1},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_HORN_JEEP, 8941, 0},
+ {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_HORN_JEEP, 11922, 1},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 7948, 2},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_HORN_JEEP, 8941, 2},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_HORN_JEEP, 12220, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_HORN_JEEP, 12200, 1},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 13400, 1},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_HORN_JEEP, 13600, 1},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2},
+ {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_HORN_JEEP, 8000, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_HORN_JEEP, 8543, 1},
+ {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0},
+ {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 10000, 0},
+ {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_HORN_JEEP, 10123, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_HORN_JEEP, 10554, 3},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 8000, 2},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9935, 3},
+ {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_HORN_JEEP, 7500, 3},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_HORN_JEEP, 8935, 0},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_HORN_JEEP, 8935, 0},
+ {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_HORN_JEEP, 17000, 0},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_HORN_JEEP, 9935, 1},
+ {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9000, 0},
+ {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_HORN_JEEP, 9935, 2},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 13400, 1},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0},
+ {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0} };
bool bPlayerJustEnteredCar;
@@ -2936,63 +3016,10 @@ cAudioManager::ProcessPed(CPhysical *ped)
// params.m_bDistanceCalculated = false;
params.m_pPed = (CPed *)ped;
params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);
- if (ped->GetModelIndex() == MI_FATMALE02)
- ProcessPedHeadphones(&params);
ProcessPedOneShots(&params);
}
void
-cAudioManager::ProcessPedHeadphones(cPedParams *params)
-{
- CPed *ped;
- CAutomobile *veh;
- uint8 emittingVol;
-
- if (params->m_fDistance < 49.f) {
- ped = params->m_pPed;
- if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- if (ped->bInVehicle && ped->m_nPedState == PED_DRIVING) {
- emittingVol = 10;
- veh = (CAutomobile *)ped->m_pMyVehicle;
- if (veh && veh->IsCar()) {
- for (int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) {
- if (!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) {
- emittingVol = 42;
- break;
- }
- }
- }
- } else {
- emittingVol = 42;
- }
-
- m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 7.f, m_sQueueSample.m_fDistance);
- if (m_sQueueSample.m_nVolume) {
- m_sQueueSample.m_nCounter = 64;
- m_sQueueSample.m_nSampleIndex = SFX_HEADPHONES;
- m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_nReleasingVolumeModificator = 5;
- m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_HEADPHONES);
- m_sQueueSample.m_nLoopCount = 0;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_fSpeedMultiplier = 4.0f;
- m_sQueueSample.m_fSoundIntensity = 7.0f;
- m_sQueueSample.m_bReleasingSoundFlag = false;
- m_sQueueSample.m_nReleasingVolumeDivider = 5;
- m_sQueueSample.m_bReverbFlag = true;
- m_sQueueSample.m_bRequireReflection = false;
- AddSampleToRequestedQueue();
- }
- return;
- }
- }
-}
-
-void
cAudioManager::ProcessPedOneShots(cPedParams *params)
{
uint8 emittingVol;
@@ -3819,158 +3846,12 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound)
int32
cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound)
{
- if (ped->IsPlayer())
- return GetPlayerTalkSfx(sound);
-
- switch (ped->GetModelIndex()) {
- case MI_COP:
- return GetCopTalkSfx(sound);
- case MI_SWAT:
- return GetSwatTalkSfx(sound);
- case MI_FBI:
- return GetFBITalkSfx(sound);
- case MI_ARMY:
- return GetArmyTalkSfx(sound);
- case MI_MEDIC:
- return GetMedicTalkSfx(sound);
- case MI_FIREMAN:
- return GetFiremanTalkSfx(sound);
- case MI_MALE01:
- return GetNormalMaleTalkSfx(sound);
- case MI_TAXI_D:
- return GetTaxiDriverTalkSfx(sound);
- case MI_PIMP:
- return GetPimpTalkSfx(sound);
- case MI_GANG01:
- case MI_GANG02:
- return GetMafiaTalkSfx(sound);
- case MI_GANG03:
- case MI_GANG04:
- return GetTriadTalkSfx(sound);
- case MI_GANG05:
- case MI_GANG06:
- return GetDiabloTalkSfx(sound);
- case MI_GANG07:
- case MI_GANG08:
- return GetYakuzaTalkSfx(sound);
- case MI_GANG09:
- case MI_GANG10:
- return GetYardieTalkSfx(sound);
- case MI_GANG11:
- case MI_GANG12:
- return GetColumbianTalkSfx(sound);
- case MI_GANG13:
- case MI_GANG14:
- return GetHoodTalkSfx(sound);
- case MI_CRIMINAL01:
- return GetBlackCriminalTalkSfx(sound);
- case MI_CRIMINAL02:
- return GetWhiteCriminalTalkSfx(sound);
- case MI_SPECIAL01:
- case MI_SPECIAL02:
- case MI_SPECIAL03:
- case MI_SPECIAL04:
- return GetSpecialCharacterTalkSfx(ped->GetModelIndex(), sound);
- case MI_MALE02:
- return GetMaleNo2TalkSfx(sound);
- case MI_MALE03:
- case MI_P_MAN1:
- case MI_P_MAN2:
- return GetBlackProjectMaleTalkSfx(sound, ped->GetModelIndex());
- case MI_FATMALE01:
- return GetWhiteFatMaleTalkSfx(sound);
- case MI_FATMALE02:
- return GetBlackFatMaleTalkSfx(sound);
- case MI_FEMALE01:
- return GetBlackCasualFemaleTalkSfx(sound);
- case MI_FEMALE02:
- case MI_CAS_WOM:
- return GetWhiteCasualFemaleTalkSfx(sound);
- case MI_FEMALE03:
- return GetFemaleNo3TalkSfx(sound);
- case MI_FATFEMALE01:
- return GetBlackFatFemaleTalkSfx(sound);
- case MI_FATFEMALE02:
- return GetWhiteFatFemaleTalkSfx(sound);
- case MI_PROSTITUTE:
- return GetBlackFemaleProstituteTalkSfx(sound);
- case MI_PROSTITUTE2:
- return GetWhiteFemaleProstituteTalkSfx(sound);
- case MI_P_WOM1:
- return GetBlackProjectFemaleOldTalkSfx(sound);
- case MI_P_WOM2:
- return GetBlackProjectFemaleYoungTalkSfx(sound);
- case MI_CT_MAN1:
- return GetChinatownMaleOldTalkSfx(sound);
- case MI_CT_MAN2:
- return GetChinatownMaleYoungTalkSfx(sound);
- case MI_CT_WOM1:
- return GetChinatownFemaleOldTalkSfx(sound);
- case MI_CT_WOM2:
- return GetChinatownFemaleYoungTalkSfx(sound);
- case MI_LI_MAN1:
- case MI_LI_MAN2:
- return GetLittleItalyMaleTalkSfx(sound);
- case MI_LI_WOM1:
- return GetLittleItalyFemaleOldTalkSfx(sound);
- case MI_LI_WOM2:
- return GetLittleItalyFemaleYoungTalkSfx(sound);
- case MI_DOCKER1:
- return GetWhiteDockerMaleTalkSfx(sound);
- case MI_DOCKER2:
- return GetBlackDockerMaleTalkSfx(sound);
- case MI_SCUM_MAN:
- return GetScumMaleTalkSfx(sound);
- case MI_SCUM_WOM:
- return GetScumFemaleTalkSfx(sound);
- case MI_WORKER1:
- return GetWhiteWorkerMaleTalkSfx(sound);
- case MI_WORKER2:
- return GetBlackWorkerMaleTalkSfx(sound);
- case MI_B_MAN1:
- case MI_B_MAN3:
- return GetBusinessMaleYoungTalkSfx(sound, ped->GetModelIndex());
- case MI_B_MAN2:
- return GetBusinessMaleOldTalkSfx(sound);
- case MI_B_WOM1:
- case MI_B_WOM2:
- return GetWhiteBusinessFemaleTalkSfx(sound, ped->GetModelIndex());
- case MI_B_WOM3:
- return GetBlackBusinessFemaleTalkSfx(sound);
- case MI_MOD_MAN:
- return GetSupermodelMaleTalkSfx(sound);
- case MI_MOD_WOM:
- return GetSupermodelFemaleTalkSfx(sound);
- case MI_ST_MAN:
- return GetStewardMaleTalkSfx(sound);
- case MI_ST_WOM:
- return GetStewardFemaleTalkSfx(sound);
- case MI_FAN_MAN1:
- case MI_FAN_MAN2:
- return GetFanMaleTalkSfx(sound, ped->GetModelIndex());
- case MI_FAN_WOM:
- return GetFanFemaleTalkSfx(sound);
- case MI_HOS_MAN:
- return GetHospitalMaleTalkSfx(sound);
- case MI_HOS_WOM:
- return GetHospitalFemaleTalkSfx(sound);
- case MI_CONST1:
- return GetWhiteConstructionWorkerTalkSfx(sound);
- case MI_CONST2:
- return GetBlackConstructionWorkerTalkSfx(sound);
- case MI_SHOPPER1:
- case MI_SHOPPER2:
- case MI_SHOPPER3:
- return GetShopperFemaleTalkSfx(sound, ped->GetModelIndex());
- case MI_STUD_MAN:
- return GetStudentMaleTalkSfx(sound);
- case MI_STUD_WOM:
- return GetStudentFemaleTalkSfx(sound);
- case MI_CAS_MAN:
- return GetCasualMaleOldTalkSfx(sound);
- default:
- return GetGenericMaleTalkSfx(sound);
- }
+ //if (ped->IsPlayer())
+ // return GetPlayerTalkSfx(sound);
+
+ // TODO: miami peds
+
+ return TOTAL_AUDIO_SAMPLES;
}
void
@@ -3986,2223 +3867,7 @@ cAudioManager::GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint
}
#pragma region PED_COMMENTS
-
-uint32
-cAudioManager::GetPlayerTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_DAMAGE:
- GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11);
- break;
- case SOUND_PED_HIT:
- GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_LOW_DAMAGE_GRUNT_1, 10);
- break;
- case SOUND_PED_LAND:
- GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6);
- break;
- default:
- sfx = NO_SAMPLE;
- break;
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetCopTalkSfx(int16 sound)
-{
- uint32 sfx;
- PedState pedState;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound == SOUND_PED_ARREST_COP) {
- GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6);
- } else {
- if (sound != SOUND_PED_PURSUIT_COP) {
- return GetGenericMaleTalkSfx(sound);
- }
-
- pedState = FindPlayerPed()->m_nPedState;
- if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE)
- return NO_SAMPLE;
- GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_CHASE_1, 7);
- }
-
- return (SFX_COP_VOICE_2_ARREST_1 - SFX_COP_VOICE_1_ARREST_1) * (m_sQueueSample.m_nEntityIndex % 5) + sfx;
-}
-
-uint32
-cAudioManager::GetSwatTalkSfx(int16 sound)
-{
- uint32 sfx;
- PedState pedState;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound == SOUND_PED_ARREST_SWAT) {
- GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6);
- } else {
- if (sound != SOUND_PED_PURSUIT_SWAT) {
- return GetGenericMaleTalkSfx(sound);
- }
-
- pedState = FindPlayerPed()->m_nPedState;
- if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE)
- return NO_SAMPLE;
- GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6);
- }
-
- return (SFX_SWAT_VOICE_2_CHASE_1 - SFX_SWAT_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 4) + sfx;
-}
-
-uint32
-cAudioManager::GetFBITalkSfx(int16 sound)
-{
- uint32 sfx;
- PedState pedState;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound == SOUND_PED_ARREST_FBI) {
- GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6);
- } else {
- if (sound != SOUND_PED_PURSUIT_FBI) {
- return GetGenericMaleTalkSfx(sound);
- }
-
- pedState = FindPlayerPed()->m_nPedState;
- if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE)
- return NO_SAMPLE;
- GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6);
- }
-
- return (SFX_FBI_VOICE_2_CHASE_1 - SFX_FBI_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx;
-}
-
-uint32
-cAudioManager::GetArmyTalkSfx(int16 sound)
-{
- uint32 sfx;
- PedState pedState;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound != SOUND_PED_PURSUIT_ARMY) {
- return GetGenericMaleTalkSfx(sound);
- }
-
- pedState = FindPlayerPed()->m_nPedState;
- if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE)
- return NO_SAMPLE;
- GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15);
-
- return (SFX_ARMY_VOICE_2_CHASE_1 - SFX_ARMY_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetMedicTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_CARJACKED_1, 5);
- break;
- case SOUND_PED_HEALING:
- GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_AT_VICTIM_1, 12);
- break;
- case SOUND_PED_LEAVE_VEHICLE:
- GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1, 9);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_MEDIC_VOICE_2_GUN_PANIC_1 - SFX_MEDIC_VOICE_1_GUN_PANIC_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetFiremanTalkSfx(int16 sound)
-{
- return GetGenericMaleTalkSfx(sound);
-}
-
-uint32
-cAudioManager::GetNormalMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DODGE_1, 9);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_EYING_1, 8);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CHAT_1, 25);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetTaxiDriverTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound == SOUND_PED_CAR_JACKED) {
- GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7);
- } else {
- if (sound != SOUND_PED_CAR_COLLISION)
- return GetGenericMaleTalkSfx(sound);
- GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6);
- }
- return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetPimpTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_GUN_COOL_1, 7);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_CARJACKED_1, 4);
- break;
- case SOUND_PED_DEFEND:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_FIGHT_1, 9);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_SHOCKED_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_CHAT_1, 17);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetMafiaTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_MAFIA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx;
-}
-
-uint32
-cAudioManager::GetTriadTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3);
- break;
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetDiabloTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4);
- break;
- case SOUND_PED_HANDS_COWER:
- sound = SOUND_PED_FLEE_SPRINT;
- return GetGenericMaleTalkSfx(sound);
- break;
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_EYING_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_DIABLO_MALE_VOICE_2_CHAT_1 - SFX_DIABLO_MALE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetYakuzaTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_YAKUZA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetYardieTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- sfx = SFX_YARDIE_MALE_VOICE_1_GUN_COOL_1;
- break;
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- sfx = SFX_YARDIE_MALE_VOICE_1_CARJACKED_1;
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_FIGHT_1, 6);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_EYING_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_YARDIE_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetColumbianTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_EYING_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_COLUMBIAN_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetHoodTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5);
- break;
- case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKING_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_FIGHT_1, 6);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_EYING_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6);
- break;
-
- default:
- return GetGenericMaleTalkSfx(sound);
- break;
- }
- return (SFX_HOOD_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetBlackCriminalTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4);
- break;
- case SOUND_PED_CAR_JACKING:
- sfx = SFX_BLACK_CRIMINAL_VOICE_1_CARJACKING_1;
- break;
- case SOUND_PED_MUGGING:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_MUGGING_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- break;
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteCriminalTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3);
- break;
- case SOUND_PED_CAR_JACKING:
- sfx = SFX_WHITE_CRIMINAL_VOICE_1_CARJACKING_1;
- break;
- case SOUND_PED_MUGGING:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_MUGGING_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- break;
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetMaleNo2TalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_MUGGED_1, 4);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_EYING_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6);
- default:
- return GetGenericMaleTalkSfx(sound);
- }
-
- if (model == MI_P_MAN2)
- sfx += (SFX_BLACK_PROJECT_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1);
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9);
- break;
- case SOUND_PED_WAIT_DOUBLEBACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9);
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackFatMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_WAIT_DOUBLEBACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_MUGGED_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- sfx = SFX_WHITE_CASUAL_FEMALE_VOICE_1_MUGGED_1;
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DODGE_1, 3);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_SHOCKED_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetFemaleNo3TalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CARJACKED_1, 3);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_MUGGED_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_SHOCKED_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8);
- break;
- case SOUND_PED_WAIT_DOUBLEBACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_LOST_1, 2);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4);
- break;
- case SOUND_PED_ROBBED:
- sfx = SFX_BLACK_PROSTITUTE_VOICE_1_MUGGED_1;
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_SOLICIT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_SOLICIT_1, 8);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return (SFX_BLACK_PROSTITUTE_VOICE_2_CHAT_1 - SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_SOLICIT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_SOLICIT_1, 8);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return (SFX_WHITE_PROSTITUTE_VOICE_2_CHAT_1 - SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DODGE_1, 10);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_SHOCKED_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_CAR_JACKED:
- sfx = SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CARJACKED_1;
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_SHOCKED_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_FIGHT_1, 6);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_EVENT:
- sfx = SFX_CHINATOWN_OLD_FEMALE_VOICE_1_SHOCKED_1;
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return (SFX_LITTLE_ITALY_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_FIGHT_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetScumMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5);
- break;
- case SOUND_PED_ROBBED:
- sfx = SFX_SCUM_MALE_VOICE_1_MUGGED_1;
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_FIGHT_1, 10);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_WAIT_DOUBLEBACK:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_LOST_1, 3);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_EYING_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetScumFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_FIGHT_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_EYING_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_FIGHT_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
-
- if (model == MI_B_MAN3)
- sfx += (SFX_BUSINESS_MALE_YOUNG_VOICE_2_DRIVER_ABUSE_1 - SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1);
- return sfx;
-}
-
-uint32
-cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
-
- if (model == MI_B_WOM2)
- sfx += (SFX_WHITE_BUSINESS_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1);
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CARAJACKED_1, 4);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetSupermodelMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_MUGGED_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_SHOCKED_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetStewardMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetStewardFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return (SFX_STEWARD_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_SHOCKED_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
-
- if (model == MI_FAN_MAN2)
- sfx += (SFX_FOOTBALL_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1);
- return sfx;
-}
-
-uint32
-cAudioManager::GetFanFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_ROBBED:
- sfx = SFX_FOOTBALL_FEMALE_VOICE_1_MUGGED_1;
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_SHOCKED_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return (SFX_FOOTBALL_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx;
-}
-
-uint32
-cAudioManager::GetHospitalMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetHospitalFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- sfx = SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CARJACKED_1;
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_EYING_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3);
- break;
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_FIGHT_1, 5);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
- break;
- case SOUND_PED_CHAT_SEXY:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_EYING_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_SHOCKED_1, 4);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
-
- if (model == MI_SHOPPER2) {
- sfx += (SFX_SHOPPER_VOICE_2_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1);
- } else if (model == MI_SHOPPER3) {
- sfx += (SFX_SHOPPER_VOICE_3_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetStudentMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_SHOCKED_1, 3);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetStudentFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4);
- break;
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4);
- break;
- case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_SHOCKED_1, 2);
- break;
- case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetCasualMaleOldTalkSfx(int16 sound)
-{
- return GetGenericMaleTalkSfx(sound);
-}
-
-uint32
-cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound)
-{
- char *modelName = CModelInfo::GetModelInfo(modelIndex)->GetName();
- if (!CGeneral::faststricmp(modelName, "eight") || !CGeneral::faststricmp(modelName, "eight2")) {
- return GetEightTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "frankie")) {
- return GetFrankieTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "misty")) {
- return GetMistyTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "ojg") || !CGeneral::faststricmp(modelName, "ojg_p")) {
- return GetOJGTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "cat")) {
- return GetCatatalinaTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "bomber")) {
- return GetBomberTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "s_guard")) {
- return GetSecurityGuardTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "chunky")) {
- return GetChunkyTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "asuka")) {
- return GetGenericFemaleTalkSfx(sound);
- }
- if (!CGeneral::faststricmp(modelName, "maria")) {
- return GetGenericFemaleTalkSfx(sound);
- }
-
- return GetGenericMaleTalkSfx(sound);
-}
-uint32
-cAudioManager::GetEightTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_GUN_COOL_1, 2);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_FIGHT_1, 6);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_DODGE_1, 7);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetFrankieTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_GUN_COOL_1, 4);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_FIGHT_1, 6);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_DODGE_1, 3);
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetMistyTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_GUN_COOL_1, 5);
- break;
- case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_MUGGED_1, 2);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_FIGHT_1, 4);
- break;
- case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_DODGE_1, 5);
- break;
- case SOUND_PED_TAXI_CALL:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_HERE_1, 4);
- break;
- default:
- return GetGenericFemaleTalkSfx(sound);
- break;
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetOJGTalkSfx(int16 sound)
-{
- return GetGenericMaleTalkSfx(sound);
-}
-
-uint32
-cAudioManager::GetCatatalinaTalkSfx(int16 sound)
-{
- return GetGenericFemaleTalkSfx(sound);
-}
-
-uint32
-cAudioManager::GetBomberTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound != SOUND_PED_BOMBER)
- return GetGenericMaleTalkSfx(sound);
-
- GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7);
- return sfx;
-}
-
-uint32
-cAudioManager::GetSecurityGuardTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2);
- break;
- case SOUND_PED_HANDS_COWER:
- sfx = SFX_SECURITY_GUARD_VOICE_1_GUN_PANIC_1;
- break;
- case SOUND_PED_CAR_JACKED:
- case SOUND_PED_CAR_COLLISION:
- GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6);
- break;
- case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_FIGHT_1, 2);
- break;
- case SOUND_PED_FLEE_RUN:
-#ifdef FIX_BUGS
- sfx = SFX_SECURITY_GUARD_VOICE_1_RUN_FROM_FIGHT_1;
-#else
- GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12);
-#endif
- break;
- default:
- return GetGenericMaleTalkSfx(sound);
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetChunkyTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- if (sound == SOUND_PED_DEATH)
- return SFX_CHUNKY_DEATH;
-
- if (sound != SOUND_PED_FLEE_RUN)
- return GetGenericMaleTalkSfx(sound);
-
- GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5);
- return sfx;
-}
-
-uint32
-cAudioManager::GetGenericMaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_DEATH:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_DEATH_1, 8);
- break;
- case SOUND_PED_BULLET_HIT:
- case SOUND_PED_DEFEND:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15);
- break;
- case SOUND_PED_BURNING:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_FIRE_1, 8);
- break;
- case SOUND_PED_FLEE_SPRINT:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_PANIC_1, 6);
- break;
- default:
- return NO_SAMPLE;
- }
- return sfx;
-}
-
-uint32
-cAudioManager::GetGenericFemaleTalkSfx(int16 sound)
-{
- uint32 sfx;
- static uint32 lastSfx = NO_SAMPLE;
-
- switch (sound) {
- case SOUND_PED_DEATH:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10);
- break;
- case SOUND_PED_BULLET_HIT:
- case SOUND_PED_DEFEND:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11);
- break;
- case SOUND_PED_BURNING:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9);
- break;
- case SOUND_PED_FLEE_SPRINT:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8);
- break;
- default:
- return NO_SAMPLE;
- }
- return sfx;
-}
-
-
+// TODO: all the ped comment funcs should follow here
void
cPedComments::Add(tPedComment *com)
diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h
index b2b44c07..ba7db091 100644
--- a/src/audio/AudioManager.h
+++ b/src/audio/AudioManager.h
@@ -241,82 +241,7 @@ public:
// functions returning talk sfx,
// order from GetPedCommentSfx
- uint32 GetPlayerTalkSfx(int16 sound);
- uint32 GetCopTalkSfx(int16 sound);
- uint32 GetSwatTalkSfx(int16 sound);
- uint32 GetFBITalkSfx(int16 sound);
- uint32 GetArmyTalkSfx(int16 sound);
- uint32 GetMedicTalkSfx(int16 sound);
- uint32 GetFiremanTalkSfx(int16 sound);
- uint32 GetNormalMaleTalkSfx(int16 sound);
- uint32 GetTaxiDriverTalkSfx(int16 sound);
- uint32 GetPimpTalkSfx(int16 sound);
- uint32 GetMafiaTalkSfx(int16 sound);
- uint32 GetTriadTalkSfx(int16 sound);
- uint32 GetDiabloTalkSfx(int16 sound);
- uint32 GetYakuzaTalkSfx(int16 sound);
- uint32 GetYardieTalkSfx(int16 sound);
- uint32 GetColumbianTalkSfx(int16 sound);
- uint32 GetHoodTalkSfx(int16 sound);
- uint32 GetBlackCriminalTalkSfx(int16 sound);
- uint32 GetWhiteCriminalTalkSfx(int16 sound);
- uint32 GetMaleNo2TalkSfx(int16 sound);
- uint32 GetBlackProjectMaleTalkSfx(int16 sound, int32 model);
- uint32 GetWhiteFatMaleTalkSfx(int16 sound);
- uint32 GetBlackFatMaleTalkSfx(int16 sound);
- uint32 GetBlackCasualFemaleTalkSfx(int16 sound);
- uint32 GetWhiteCasualFemaleTalkSfx(int16 sound);
- uint32 GetFemaleNo3TalkSfx(int16 sound);
- uint32 GetBlackFatFemaleTalkSfx(int16 sound);
- uint32 GetWhiteFatFemaleTalkSfx(int16 sound);
- uint32 GetBlackFemaleProstituteTalkSfx(int16 sound);
- uint32 GetWhiteFemaleProstituteTalkSfx(int16 sound);
- uint32 GetBlackProjectFemaleOldTalkSfx(int16 sound);
- uint32 GetBlackProjectFemaleYoungTalkSfx(int16 sound);
- uint32 GetChinatownMaleOldTalkSfx(int16 sound);
- uint32 GetChinatownMaleYoungTalkSfx(int16 sound);
- uint32 GetChinatownFemaleOldTalkSfx(int16 sound);
- uint32 GetChinatownFemaleYoungTalkSfx(int16 sound);
- uint32 GetLittleItalyMaleTalkSfx(int16 sound);
- uint32 GetLittleItalyFemaleOldTalkSfx(int16 sound);
- uint32 GetLittleItalyFemaleYoungTalkSfx(int16 sound);
- uint32 GetWhiteDockerMaleTalkSfx(int16 sound);
- uint32 GetBlackDockerMaleTalkSfx(int16 sound);
- uint32 GetScumMaleTalkSfx(int16 sound);
- uint32 GetScumFemaleTalkSfx(int16 sound);
- uint32 GetWhiteWorkerMaleTalkSfx(int16 sound);
- uint32 GetBlackWorkerMaleTalkSfx(int16 sound);
- uint32 GetBusinessMaleYoungTalkSfx(int16 sound, int32 model);
- uint32 GetBusinessMaleOldTalkSfx(int16 sound);
- uint32 GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model);
- uint32 GetBlackBusinessFemaleTalkSfx(int16 sound);
- uint32 GetSupermodelMaleTalkSfx(int16 sound);
- uint32 GetSupermodelFemaleTalkSfx(int16 sound);
- uint32 GetStewardMaleTalkSfx(int16 sound);
- uint32 GetStewardFemaleTalkSfx(int16 sound);
- uint32 GetFanMaleTalkSfx(int16 sound, int32 model);
- uint32 GetFanFemaleTalkSfx(int16 sound);
- uint32 GetHospitalMaleTalkSfx(int16 sound);
- uint32 GetHospitalFemaleTalkSfx(int16 sound);
- uint32 GetWhiteConstructionWorkerTalkSfx(int16 sound);
- uint32 GetBlackConstructionWorkerTalkSfx(int16 sound);
- uint32 GetShopperFemaleTalkSfx(int16 sound, int32 model);
- uint32 GetStudentMaleTalkSfx(int16 sound);
- uint32 GetStudentFemaleTalkSfx(int16 sound);
- uint32 GetCasualMaleOldTalkSfx(int16 sound);
-
- uint32 GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound);
- uint32 GetEightTalkSfx(int16 sound);
- uint32 GetFrankieTalkSfx(int16 sound);
- uint32 GetMistyTalkSfx(int16 sound);
- uint32 GetOJGTalkSfx(int16 sound);
- uint32 GetCatatalinaTalkSfx(int16 sound);
- uint32 GetBomberTalkSfx(int16 sound);
- uint32 GetSecurityGuardTalkSfx(int16 sound);
- uint32 GetChunkyTalkSfx(int16 sound);
-
- uint32 GetGenericMaleTalkSfx(int16 sound);
- uint32 GetGenericFemaleTalkSfx(int16 sound);
+ // TODO: miami
// end of functions returning talk sfx
void GenerateIntegerRandomNumberTable();
@@ -397,7 +322,6 @@ public:
void ProcessModelCarEngine(cVehicleParams *params);
void ProcessOneShotScriptObject(uint8 sound);
void ProcessPed(CPhysical *ped);
- void ProcessPedHeadphones(cPedParams *params);
void ProcessPedOneShots(cPedParams *params);
void ProcessPhysical(int32 id);
void ProcessPlane(cVehicleParams *params);
diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp
index 8e8e9c24..afe31bf0 100644
--- a/src/audio/MusicManager.cpp
+++ b/src/audio/MusicManager.cpp
@@ -64,7 +64,8 @@ cMusicManager::PlayerInCar()
case MI_TRAIN:
case MI_SPEEDER:
case MI_REEFER:
- case MI_GHOST: return false;
+// case MI_GHOST:
+ return false;
default: return true;
}
}
diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp
index af346479..c8baec25 100644
--- a/src/audio/PoliceRadio.cpp
+++ b/src/audio/PoliceRadio.cpp
@@ -56,6 +56,7 @@ cAudioManager::InitialisePoliceRadioZones()
SETZONESFX(11, "PROJECT", SFX_POLICE_RADIO_WICHITA_GARDENS);
SETZONESFX(12, "AIRPORT", SFX_POLICE_RADIO_FRANCIS_INTERNATIONAL_AIRPORT);
SETZONESFX(13, "PORT_W", SFX_POLICE_RADIO_CALLAHAN_POINT);
+ /*
SETZONESFX(14, "PORT_S", SFX_POLICE_RADIO_ATLANTIC_QUAYS);
SETZONESFX(15, "PORT_E", SFX_POLICE_RADIO_PORTLAND_HARBOUR);
SETZONESFX(16, "PORT_I", SFX_POLICE_RADIO_TRENTON);
@@ -77,6 +78,7 @@ cAudioManager::InitialisePoliceRadioZones()
SETZONESFX(32, "A", SFX_POLICE_RADIO_ROCKFORD);
SETZONESFX(33, "A", SFX_POLICE_RADIO_ROCKFORD);
SETZONESFX(34, "A", SFX_POLICE_RADIO_ROCKFORD);
+ */
#undef SETZONESFX
@@ -538,39 +540,41 @@ cAudioManager::SetupSuspectLastSeenReport()
color_pre_modifier = gCarColourTable[color1][0];
color_post_modifier = gCarColourTable[color1][2];
switch (veh->GetModelIndex()) {
+// TODO(MIAMI): just making this compile
#ifdef FIX_BUGS
- case MI_COLUMB:
- main_color = SFX_POLICE_RADIO_BLUE;
- color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
+ // case MI_COLUMB:
+ // main_color = SFX_POLICE_RADIO_BLUE;
+ // color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
#endif
case MI_LANDSTAL:
- case MI_BLISTA: sample = SFX_POLICE_RADIO_CRUISER; break;
+ // case MI_BLISTA:
+ sample = SFX_POLICE_RADIO_CRUISER; break;
#ifdef FIX_BUGS
- case MI_YARDIE:
- color_pre_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_RED;
- color_post_modifier = SFX_POLICE_RADIO_YELLOW;
- sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
- case MI_DIABLOS:
- main_color = SFX_POLICE_RADIO_BLACK;
+ // case MI_YARDIE:
+ // color_pre_modifier = TOTAL_AUDIO_SAMPLES;
+ // main_color = SFX_POLICE_RADIO_RED;
+ // color_post_modifier = SFX_POLICE_RADIO_YELLOW;
+ // sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
+ // case MI_DIABLOS:
+ // main_color = SFX_POLICE_RADIO_BLACK;
#endif
case MI_IDAHO:
case MI_STALLION: sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
#ifdef FIX_BUGS
- case MI_YAKUZA:
- color_pre_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_SILVER;
- color_post_modifier = SFX_POLICE_RADIO_RED;
+ // case MI_YAKUZA:
+ // color_pre_modifier = TOTAL_AUDIO_SAMPLES;
+ // main_color = SFX_POLICE_RADIO_SILVER;
+ // color_post_modifier = SFX_POLICE_RADIO_RED;
#endif
case MI_STINGER:
case MI_INFERNUS:
case MI_CHEETAH:
case MI_BANSHEE: sample = SFX_POLICE_RADIO_SPORTS_CAR; break;
#ifdef FIX_BUGS
- case MI_MAFIA:
- color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_GREY;
- case MI_KURUMA:
+ // case MI_MAFIA:
+ // color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
+ // main_color = SFX_POLICE_RADIO_GREY;
+ case MI_WASHING:
#endif
case MI_PEREN:
case MI_SENTINEL:
@@ -585,21 +589,18 @@ cAudioManager::SetupSuspectLastSeenReport()
case MI_TRASH:
case MI_BARRACKS: sample = SFX_POLICE_RADIO_TRUCK; break;
case MI_STRETCH: sample = SFX_POLICE_RADIO_LIMO; break;
-#ifdef FIX_BUGS
- case MI_CORPSE:
-#endif
case MI_MANANA:
case MI_ESPERANT: sample = SFX_POLICE_RADIO_2_DOOR; break;
#ifdef FIX_BUGS
- case MI_HOODS:
- color_pre_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_BLUE;
- color_post_modifier = SFX_POLICE_RADIO_GREEN;
- case MI_BELLYUP:
+ // case MI_HOODS:
+ // color_pre_modifier = TOTAL_AUDIO_SAMPLES;
+ // main_color = SFX_POLICE_RADIO_BLUE;
+ // color_post_modifier = SFX_POLICE_RADIO_GREEN;
+ // case MI_BELLYUP:
case MI_YANKEE:
- case MI_TOYZ:
- case MI_MRWONGS:
- case MI_PANLANT:
+ case MI_TOPFUN:
+ // case MI_MRWONGS:
+ // case MI_PANLANT:
#endif
case MI_PONY:
case MI_MULE:
@@ -610,7 +611,8 @@ cAudioManager::SetupSuspectLastSeenReport()
case MI_AMBULAN: sample = SFX_POLICE_RADIO_AMBULANCE; break;
case MI_TAXI:
case MI_CABBIE:
- case MI_BORGNINE: sample = SFX_POLICE_RADIO_TAXI; break;
+ case MI_ZEBRA: sample = SFX_POLICE_RADIO_TAXI; break;
+ case MI_KAUFMAN: sample = SFX_POLICE_RADIO_TAXI; break;
case MI_MRWHOOP:
sample = SFX_POLICE_RADIO_ICE_CREAM_VAN;
break;
@@ -619,7 +621,7 @@ cAudioManager::SetupSuspectLastSeenReport()
#ifdef FIX_BUGS
case MI_SPEEDER:
case MI_REEFER:
- case MI_GHOST:
+ // case MI_GHOST:
#endif
case MI_PREDATOR: sample = SFX_POLICE_RADIO_BOAT; break;
case MI_BUS:
diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp
index b1fce95f..da661b8c 100644
--- a/src/control/AutoPilot.cpp
+++ b/src/control/AutoPilot.cpp
@@ -6,6 +6,7 @@
#include "Curves.h"
#include "PathFind.h"
+//--MIAMI: done
void CAutoPilot::ModifySpeed(float speed)
{
m_fMaxTrafficSpeed = Max(0.01f, speed);
@@ -39,6 +40,7 @@ void CAutoPilot::ModifySpeed(float speed)
#endif
}
+//--MIAMI: done
void CAutoPilot::RemoveOnePathNode()
{
--m_nPathFindNodesCount;
@@ -47,6 +49,7 @@ void CAutoPilot::RemoveOnePathNode()
}
#ifdef COMPATIBLE_SAVES
+//--MIAMI: TODO
void CAutoPilot::Save(uint8*& buf)
{
WriteSaveBuf<int32>(buf, m_nCurrentRouteNode);
@@ -86,6 +89,7 @@ void CAutoPilot::Save(uint8*& buf)
SkipSaveBuf(buf, 6);
}
+//--MIAMI: TODO
void CAutoPilot::Load(uint8*& buf)
{
m_nCurrentRouteNode = ReadSaveBuf<int32>(buf);
diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h
index 337a93c1..25feb72d 100644
--- a/src/control/AutoPilot.h
+++ b/src/control/AutoPilot.h
@@ -26,6 +26,13 @@ enum eCarMission : uint8
MISSION_BLOCKCAR_FARAWAY,
MISSION_BLOCKCAR_CLOSE,
MISSION_BLOCKCAR_HANDBRAKESTOP,
+ MISSION_HELI_FLYTOCOORS,
+ MISSION_ATTACKPLAYER,
+ MISSION_PLANE_FLYTOCOORS,
+ MISSION_HELI_LAND,
+ MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1,
+ MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2,
+ MISSION_BLOCKPLAYER_FORWARDANDBACK
};
enum eCarTempAction : uint8
@@ -75,11 +82,14 @@ public:
uint32 m_nTimeTempAction;
float m_fMaxTrafficSpeed;
uint8 m_nCruiseSpeed;
+ uint8 m_nCruiseSpeedMultiplierType;
+ float m_fCruiseSpeedMultiplier;
uint8 m_bSlowedDownBecauseOfCars : 1;
uint8 m_bSlowedDownBecauseOfPeds : 1;
uint8 m_bStayInCurrentLevel : 1;
uint8 m_bStayInFastLane : 1;
uint8 m_bIgnorePathfinding : 1;
+ uint8 m_nSwitchDistance;
CVector m_vecDestinationCoors;
CPathNode *m_aPathFindNodesInfo[NUM_PATH_NODES_IN_AUTOPILOT];
int16 m_nPathFindNodesCount;
@@ -109,6 +119,8 @@ public:
m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
m_nAntiReverseTimer = m_nTimeToStartMission;
m_bStayInFastLane = false;
+ m_nCruiseSpeedMultiplierType = 0;
+ m_fCruiseSpeedMultiplier = 1.0f;
}
void ModifySpeed(float);
@@ -118,6 +130,8 @@ public:
void Load(uint8*& buf);
#endif
+ float GetCruiseSpeed(void) { return m_nCruiseSpeed * m_fCruiseSpeedMultiplier; }
+
};
VALIDATE_SIZE(CAutoPilot, 0x70);
diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp
index e873062b..1e63cf30 100644
--- a/src/control/Bridge.cpp
+++ b/src/control/Bridge.cpp
@@ -23,6 +23,7 @@ uint32 CBridge::TimeOfBridgeBecomingOperational;
void CBridge::Init()
{
+#ifdef GTA_BRIDGE
FindBridgeEntities();
OldLift = -1.0f;
if (pLiftPart && pWeight)
@@ -35,10 +36,12 @@ void CBridge::Init()
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
}
+#endif
}
void CBridge::Update()
{
+#ifdef GTA_BRIDGE
if (!pLiftPart || !pWeight)
return;
@@ -113,15 +116,21 @@ void CBridge::Update()
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN)
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false);
+#endif
}
bool CBridge::ShouldLightsBeFlashing()
{
+#ifdef GTA_BRIDGE
return State != STATE_LIFT_PART_IS_DOWN;
+#else
+ return false;
+#endif
}
void CBridge::FindBridgeEntities()
{
+#ifdef GTA_BRIDGE
pWeight = nil;
pLiftRoad = nil;
pLiftPart = nil;
@@ -138,12 +147,17 @@ void CBridge::FindBridgeEntities()
pWeight = entry;
}
}
+#endif
}
bool CBridge::ThisIsABridgeObjectMovingUp(int index)
{
+#ifdef GTA_BRIDGE
if (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT)
return false;
return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP;
+#else
+ return false;
+#endif
}
diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp
index b3fc85ae..a4406da9 100644
--- a/src/control/CarAI.cpp
+++ b/src/control/CarAI.cpp
@@ -13,6 +13,7 @@
#include "DMAudio.h"
#include "Fire.h"
#include "Pools.h"
+#include "Population.h"
#include "Timer.h"
#include "TrafficLights.h"
#include "Vehicle.h"
@@ -21,16 +22,19 @@
#define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f
+//--MIAMI: done
float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle)
{
- return 30.0f;
+ return pVehicle->AutoPilot.m_nSwitchDistance;
}
+//--MIAMI: done
float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle)
{
return FindSwitchDistanceClose(pVehicle) + 5.0f;
}
+//--MIAMI: done
float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer)
@@ -38,6 +42,21 @@ float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
return FindSwitchDistanceFarNormalVehicle(pVehicle);
}
+//--MIAMI: done
+void CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle)
+{
+ if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
+ (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
+ pVehicle->m_bSirenOrAlarm = false;
+ if (CCullZones::NoPolice())
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
+}
+
+//--MIAMI: done
void CCarAI::UpdateCarAI(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer){
@@ -67,15 +86,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
pVehicle->m_bSirenOrAlarm = true;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_RAMPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@@ -120,18 +131,9 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())){
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
-
- else if (pVehicle->bIsLawEnforcer)
+ if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_BLOCKPLAYER_FARAWAY:
if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@@ -140,20 +142,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
pVehicle->m_bSirenOrAlarm = true;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_BLOCKPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
pVehicle->AutoPilot.m_bIgnorePathfinding) {
- if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f)
+ if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f)
#ifdef FIX_BUGS
pVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds();
#else
@@ -162,7 +156,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
else
pVehicle->m_nTimeBlocked = 0;
if (!FindPlayerVehicle() || FindPlayerVehicle()->IsUpsideDown() ||
- FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {
+ FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {
if (pVehicle->bIsLawEnforcer &&
(pVehicle->GetModelIndex() != MI_RHINO || pVehicle->m_randomSeed > 10000) &&
(FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() < 10.0f) {
@@ -178,20 +172,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_GOTOCOORDS:
- if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < DISTANCE_TO_SWITCH_DISTANCE_GOTO ||
+ if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding)
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
break;
@@ -203,6 +189,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 5.0f){
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ if (pVehicle->bParking) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->bParking = false;
+ }
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@@ -259,6 +249,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 1.0f) {
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ if (pVehicle->bParking) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->bParking = false;
+ }
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@@ -278,23 +272,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
break;
case MISSION_RAMCAR_CLOSE:
if (pVehicle->AutoPilot.m_pTargetCar){
- if
-#ifdef FIX_BUGS
- (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar &&
-#endif
- (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice()))
-#ifdef FIX_BUGS
- )
+#ifdef FIX_BUGS // btw fixed in SA
+ if (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar)
#endif
- {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding){
if (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){
@@ -336,6 +317,40 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
break;
+ case MISSION_ATTACKPLAYER:
+ if (pVehicle->bIsLawEnforcer)
+ MellowOutChaseSpeedBoat(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
+ break;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:
+ if (((CVector2D)(pVehicle->AutoPilot.m_vecDestinationCoors) - pVehicle->GetPosition()).Magnitude() < 1.5f)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2;
+ BackToCruisingIfNoWantedLevel(pVehicle);
+ break;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:
+ {
+ float distance = ((CVector2D)FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();
+ if (distance < 13.0f) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
+ }
+ if (distance > 70.0f || FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone ||
+ (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
+ }
+ break;
+ }
+ case MISSION_BLOCKPLAYER_FORWARDANDBACK:
+ {
+ CVector2D diff = (CVector2D)FindPlayerCoors() - pVehicle->GetPosition();
+ float distance = Max(0.001f, diff.Magnitude());
+ if (!FindPlayerVehicle() || DotProduct2D(CVector2D(diff.x / distance, diff.y / distance), FindPlayerSpeed()) > 0.05f)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE;
+ BackToCruisingIfNoWantedLevel(pVehicle);
+ }
default:
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && !CCullZones::NoPolice()){
if (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f ||
@@ -343,7 +358,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nCarMission =
- FindPoliceCarMissionForWantedLevel();
+ pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel();
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
}else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){
@@ -364,6 +379,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
break;
}
+ if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel >= 1 && CCullZones::PoliceAbandonCars()) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
float flatSpeed = pVehicle->GetMoveSpeed().MagnitudeSqr2D();
if (flatSpeed > SQR(0.018f)){
pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
@@ -372,9 +392,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){
if (pVehicle->AutoPilot.m_nCarMission != MISSION_NONE){
if (pVehicle->AutoPilot.m_nCarMission != MISSION_STOP_FOREVER &&
+ pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_HANDBRAKESTOP &&
pVehicle->AutoPilot.m_nCruiseSpeed != 0 &&
(pVehicle->VehicleCreatedBy != RANDOM_VEHICLE || pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE)){
if (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS
+ && pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS ||
+ pVehicle->VehicleCreatedBy == MISSION_VEHICLE
) {
if (CTimer::GetTimeInMilliseconds() - pVehicle->m_nLastTimeCollided > 500)
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
@@ -406,6 +429,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400;
}
}
+ if (pVehicle->bIsLawEnforcer) {
+ if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||
+ pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) {
+ if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;
+ }
+ }
if (pVehicle->GetUp().z < 0.7f){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
@@ -446,13 +476,43 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if ((uint8)(pVehicle->m_randomSeed ^ CGeneral::GetRandomNumber()) == 0xAD)
pVehicle->m_nCarHornTimer = 45;
}
+ float target = 1.0f;
+ if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE)
+ target = CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(pVehicle->AutoPilot.m_nCruiseSpeedMultiplierType);
+ float change = CTimer::GetTimeStep() * 0.01f;
+ if (Abs(pVehicle->AutoPilot.m_fCruiseSpeedMultiplier - target) < change)
+ pVehicle->AutoPilot.m_fCruiseSpeedMultiplier = target;
+ else if (pVehicle->AutoPilot.m_fCruiseSpeedMultiplier > target)
+ pVehicle->AutoPilot.m_fCruiseSpeedMultiplier -= change;
+ else
+ pVehicle->AutoPilot.m_fCruiseSpeedMultiplier += change;
+
+ if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0) {
+ if (!FindPlayerVehicle() ||
+ FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||
+ FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {
+ if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
+ }
+ }
+ else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {
+ if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||
+ pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
+ }
+ }
+ }
}
+//--MIAMI: done
void CCarAI::CarHasReasonToStop(CVehicle* pVehicle)
{
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
}
+//--MIAMI: done
float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
{
if (pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS && pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT){
@@ -470,6 +530,16 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
}
+//--MIAMI: done
+float CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget)
+{
+ GetCarToGoToCoors(pVehicle, pTarget);
+ pVehicle->bParking = true;
+ pVehicle->AutoPilot.m_nCruiseSpeed = 10;
+ return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
+}
+
+//--MIAMI: TODO: MI_VICECHEE
void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
{
if (pVehicle->bOccupantsHaveBeenGenerated)
@@ -489,23 +559,38 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 1)
pVehicle->SetupPassenger(0);
return;
+ case MI_PREDATOR:
+ pVehicle->SetUpDriver();
+ return;
+ case MI_VICECHEE:
+ {
+ pVehicle->SetUpDriver()->bMiamiViceCop = true;
+ pVehicle->SetupPassenger(0)->bMiamiViceCop = true;
+ CPopulation::NumMiamiViceCops += 2;
+ CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;
+ CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
default:
return;
}
}
+//--MIAMI: done
void CCarAI::AddAmbulanceOccupants(CVehicle* pVehicle)
{
pVehicle->SetUpDriver();
pVehicle->SetupPassenger(1);
}
+//--MIAMI: done
void CCarAI::AddFiretruckOccupants(CVehicle* pVehicle)
{
pVehicle->SetUpDriver();
pVehicle->SetupPassenger(0);
}
+//--MIAMI: done
void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
{
if (pVehicle->pDriver){
@@ -516,11 +601,32 @@ void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
int timer = 100;
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++){
if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->m_leaveCarTimer = timer;
pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ timer += CGeneral::GetRandomNumberInRange(200, 400);
+ }
+ }
+}
+
+//--MIAMI: done
+void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle)
+{
+ if (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ if (pVehicle->GetModelIndex() != MI_FIRETRUCK && pVehicle->GetModelIndex() == MI_AMBULAN)
+ pVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);
+ }
+ int timer = 100;
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->m_leaveCarTimer = timer;
+ pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ timer += CGeneral::GetRandomNumberInRange(200, 400);
}
}
}
+//--MIAMI: done
void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
{
pVehicle->AutoPilot.m_pTargetCar = pTarget;
@@ -530,6 +636,7 @@ void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
}
+//--MIAMI: done
void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
{
pVehicle->AutoPilot.m_pTargetCar = pTarget;
@@ -539,6 +646,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
}
+//--MIAMI: done
eCarMission CCarAI::FindPoliceCarMissionForWantedLevel()
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){
@@ -553,6 +661,22 @@ eCarMission CCarAI::FindPoliceCarMissionForWantedLevel()
}
}
+//--MIAMI: done
+eCarMission CCarAI::FindPoliceBoatMissionForWantedLevel()
+{
+ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
+ case 0:
+ case 1: return MISSION_BLOCKPLAYER_FARAWAY;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6: return MISSION_ATTACKPLAYER;
+ default: return MISSION_BLOCKPLAYER_FARAWAY;
+ }
+}
+
+//--MIAMI: done
int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
@@ -567,6 +691,7 @@ int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
}
}
+//--MIAMI: done
void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
{
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel == 1){
@@ -605,8 +730,27 @@ void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 34;
}
}
+ if (!FindPlayerVehicle() && FindPlayerPed()->GetMoveSpeed().Magnitude() < 0.07f) {
+ if ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() < 30.0f)
+ pVehicle->AutoPilot.m_nCruiseSpeed = Min(10, pVehicle->AutoPilot.m_nCruiseSpeed);
+ }
+}
+
+//--MIAMI: done
+void CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle)
+{
+ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
+ case 0: pVehicle->AutoPilot.m_nCruiseSpeed = 8; break;
+ case 1: pVehicle->AutoPilot.m_nCruiseSpeed = 10; break;
+ case 2: pVehicle->AutoPilot.m_nCruiseSpeed = 15; break;
+ case 3: pVehicle->AutoPilot.m_nCruiseSpeed = 20; break;
+ case 4: pVehicle->AutoPilot.m_nCruiseSpeed = 25; break;
+ case 5: pVehicle->AutoPilot.m_nCruiseSpeed = 30; break;
+ case 6: pVehicle->AutoPilot.m_nCruiseSpeed = 40; break;
+ }
}
+//--MIAMI: done
void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
{
float flatSpeed = pVehicle->GetMoveSpeed().Magnitude2D();
@@ -629,6 +773,8 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
continue;
if (vehicle == pVehicle)
continue;
+ if (vehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
+ return;
if (Abs(pVehicle->GetPosition().z - vehicle->GetPosition().z) >= 5.0f)
continue;
CVector2D distance = vehicle->GetPosition() - pVehicle->GetPosition();
diff --git a/src/control/CarAI.h b/src/control/CarAI.h
index e88807c8..d4af1806 100644
--- a/src/control/CarAI.h
+++ b/src/control/CarAI.h
@@ -10,17 +10,22 @@ public:
static float FindSwitchDistanceClose(CVehicle*);
static float FindSwitchDistanceFarNormalVehicle(CVehicle*);
static float FindSwitchDistanceFar(CVehicle*);
+ static void BackToCruisingIfNoWantedLevel(CVehicle*);
static void UpdateCarAI(CVehicle*);
static void CarHasReasonToStop(CVehicle*);
static float GetCarToGoToCoors(CVehicle*, CVector*);
+ static float GetCarToParkAtCoors(CVehicle*, CVector*);
static void AddPoliceCarOccupants(CVehicle*);
static void AddAmbulanceOccupants(CVehicle*);
static void AddFiretruckOccupants(CVehicle*);
static void TellOccupantsToLeaveCar(CVehicle*);
+ static void TellOccupantsToFleeCar(CVehicle*);
static void TellCarToRamOtherCar(CVehicle*, CVehicle*);
static void TellCarToBlockOtherCar(CVehicle*, CVehicle*);
static eCarMission FindPoliceCarMissionForWantedLevel();
+ static eCarMission FindPoliceBoatMissionForWantedLevel();
static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);
static void MellowOutChaseSpeed(CVehicle*);
+ static void MellowOutChaseSpeedBoat(CVehicle*);
static void MakeWayForCarWithSiren(CVehicle *veh);
};
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index cd86ce4c..920fba81 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -11,6 +11,7 @@
#include "Curves.h"
#include "CutsceneMgr.h"
#include "Gangs.h"
+#include "Game.h"
#include "Garages.h"
#include "General.h"
#include "IniFile.h"
@@ -19,6 +20,7 @@
#include "Ped.h"
#include "PlayerInfo.h"
#include "PlayerPed.h"
+#include "Population.h"
#include "Wanted.h"
#include "Pools.h"
#include "Renderer.h"
@@ -29,43 +31,54 @@
#include "VisibilityPlugins.h"
#include "Vehicle.h"
#include "Fire.h"
+#include "WaterLevel.h"
#include "World.h"
#include "Zones.h"
-#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS 51.0f
-#define DISTANCE_TO_SCAN_FOR_DANGER 11.0f
-#define SAFE_DISTANCE_TO_PED 3.0f
-#define INFINITE_Z 1000000000.0f
-
-#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING 4.0f
-#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING 4.0f
-#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING 8.0f
-#define WIDTH_COEF_TO_WEAVE_SAFELY 1.2f
-#define OBJECT_WIDTH_TO_WEAVE 0.3f
-#define PED_WIDTH_TO_WEAVE 0.8f
-
-#define PATH_DIRECTION_NONE 0
-#define PATH_DIRECTION_STRAIGHT 1
-#define PATH_DIRECTION_RIGHT 2
-#define PATH_DIRECTION_LEFT 4
-
-#define ATTEMPTS_TO_FIND_NEXT_NODE 15
-
-#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP 5.0f
-#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK 10.0f
-#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING 0.13f
-#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN 40.0f
-#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED 0.2f
-#define MIN_SPEED_TO_START_LIMITING_STEER 0.45f
-#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW 5.0f
-#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW 8.0f
-#define DEFAULT_MAX_STEER_ANGLE 0.5f
-#define MIN_LOWERING_SPEED_COEFFICIENT 0.4f
-#define MAX_ANGLE_FOR_SPEED_LIMITING 1.2f
-#define MIN_ANGLE_FOR_SPEED_LIMITING 0.4f
-#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES 0.1f
-#define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f
-#define MIN_SPEED_TO_APPLY_HANDBRAKE 0.3f
+#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS (51.0f)
+#define DISTANCE_TO_SCAN_FOR_DANGER (14.0f)
+#define SAFE_DISTANCE_TO_PED (3.0f)
+#define INFINITE_Z (1000000000.0f)
+
+#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)
+#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)
+#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING (8.0f)
+#define WIDTH_COEF_TO_WEAVE_SAFELY (1.2f)
+#define OBJECT_WIDTH_TO_WEAVE (0.3f)
+#define PED_WIDTH_TO_WEAVE (0.8f)
+
+#define PATH_DIRECTION_NONE (0)
+#define PATH_DIRECTION_STRAIGHT (1)
+#define PATH_DIRECTION_RIGHT (2)
+#define PATH_DIRECTION_LEFT (4)
+
+#define ATTEMPTS_TO_FIND_NEXT_NODE (15)
+
+#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP (5.0f)
+#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK (10.0f)
+#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING (0.13f)
+#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN (40.0f)
+#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED (0.2f)
+#define MIN_SPEED_TO_START_LIMITING_STEER (0.45f)
+#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW (5.0f)
+#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW (8.0f)
+#define DEFAULT_MAX_STEER_ANGLE (0.5f)
+#define MIN_LOWERING_SPEED_COEFFICIENT (0.4f)
+#define MAX_ANGLE_FOR_SPEED_LIMITING (1.2f)
+#define MIN_ANGLE_FOR_SPEED_LIMITING (0.4f)
+#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES (0.1f)
+#define MIN_ANGLE_TO_APPLY_HANDBRAKE (0.7f)
+#define MIN_SPEED_TO_APPLY_HANDBRAKE (0.3f)
+
+#define PROBABILITY_OF_DEAD_PED_ACCIDENT (0.005f)
+#define DISTANCE_BETWEEN_CAR_AND_DEAD_PED (6.0f)
+#define PROBABILITY_OF_PASSENGER_IN_VEHICLE (0.125f)
+
+#define ONSCREEN_DESPAWN_RANGE (120.0f)
+#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (100.0f)
+#define REQUEST_ONSCREEN_DISTANCE ((ONSCREEN_DESPAWN_RANGE + MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) / 2)
+#define OFFSCREEN_DESPAWN_RANGE (40.0f)
+#define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f)
int CCarCtrl::NumLawEnforcerCars;
int CCarCtrl::NumAmbulancesOnDuty;
@@ -81,23 +94,29 @@ int32 CCarCtrl::MaxNumberOfCarsInUse = 12;
uint32 CCarCtrl::LastTimeLawEnforcerCreated;
uint32 CCarCtrl::LastTimeFireTruckCreated;
uint32 CCarCtrl::LastTimeAmbulanceCreated;
+int32 CCarCtrl::MiamiViceCycle;
+uint32 CCarCtrl::LastTimeMiamiViceGenerated;
int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
-int32 CCarCtrl::NextCarOfRating[TOTAL_CUSTOM_CLASSES];
int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP];
void
CCarCtrl::GenerateRandomCars()
{
- if (CCutsceneMgr::IsRunning())
+ if (CCutsceneMgr::IsRunning()) {
+ CountDownToCarsAtStart = 2;
return;
+ }
if (NumRandomCars < 30){
- if (CountDownToCarsAtStart == 0){
+ if (CountDownToCarsAtStart == 0)
GenerateOneRandomCar();
- }
else if (--CountDownToCarsAtStart == 0) {
- for (int i = 0; i < 50; i++)
+ for (int i = 0; i < 100; i++)
GenerateOneRandomCar();
CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20;
}
@@ -111,6 +130,7 @@ void
CCarCtrl::GenerateOneRandomCar()
{
static int32 unk = 0;
+ bool bTopDownCamera = false;
CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
CVector vecTargetPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
CVector2D vecPlayerSpeed = FindPlayerSpeed();
@@ -125,7 +145,7 @@ CCarCtrl::GenerateOneRandomCar()
int carClass;
int carModel;
if (pWanted->m_nWantedLevel > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
- pWanted->m_CurrentCops < pWanted->m_MaxCops && (
+ pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
pWanted->m_nWantedLevel > 3 ||
pWanted->m_nWantedLevel > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||
pWanted->m_nWantedLevel > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {
@@ -135,7 +155,7 @@ CCarCtrl::GenerateOneRandomCar()
carModel = ChoosePoliceCarModel();
}else{
carModel = ChooseModel(&zone, &vecTargetPos, &carClass);
- if (carClass == COPS && pWanted->m_nWantedLevel >= 1)
+ if (carClass == COPS && pWanted->m_nWantedLevel >= 1 || carModel < 0)
/* All cop spawns with wanted level are handled by condition above. */
/* In particular it means that cop cars never spawn if player has wanted level of 1. */
return;
@@ -159,8 +179,9 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn essentially anywhere. */
frontX = frontY = 0.707f; /* 45 degrees */
angleLimit = -1.0f;
+ bTopDownCamera = true;
invertAngleLimitTest = true;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE + 15.0f;
/* BUG: testForCollision not initialized in original game. */
testForCollision = false;
}else if (!pPlayerVehicle){
@@ -174,14 +195,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else if (fPlayerVehicleSpeed > 0.4f){ /* 72 km/h */
@@ -196,21 +217,21 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 2:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 3:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else if (fPlayerVehicleSpeed > 0.1f){ /* 18 km/h */
@@ -224,14 +245,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 2:
case 3:
@@ -239,7 +260,7 @@ CCarCtrl::GenerateOneRandomCar()
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else{
@@ -254,14 +275,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}
@@ -269,17 +290,45 @@ CCarCtrl::GenerateOneRandomCar()
preferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId,
&positionBetweenNodes, carClass == COPS && pWanted->m_nWantedLevel >= 1))
return;
+ CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
+ CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+ bool bBoatGenerated = false;
+ if ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate))
+ return;
+ if (pCurNode->bWaterPath) {
+ bBoatGenerated = true;
+ if (carClass == COPS) {
+ carModel = MI_PREDATOR;
+ carClass = COPS_BOAT;
+ if (!CStreaming::HasModelLoaded(MI_PREDATOR)) {
+ CStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY);
+ return;
+ }
+ }
+ else {
+ int i;
+ carModel = -1;
+ for (i = 10; i > 0 && (carModel == -1 || !CStreaming::HasModelLoaded(carModel)); i--) {
+ carModel = ChooseBoatModel(ChooseBoatRating(&zone));
+ }
+ if (i == 0)
+ return;
+ }
+ if (pCurNode->bOnlySmallBoats || pNextNode->bOnlySmallBoats) {
+ if (BoatWithTallMast(carModel))
+ return;
+ }
+ }
int16 colliding;
- CWorld::FindObjectsKindaColliding(spawnPosition, 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+ CWorld::FindObjectsKindaColliding(spawnPosition, bBoatGenerated ? 40.0f : 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
if (colliding)
/* If something is already present in spawn position, do not create vehicle*/
return;
- if (!ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
+ if (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
/* Testing if spawn position can reach target position via valid path. */
return;
int16 idInNode = 0;
- CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
- CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+
while (idInNode < pCurNode->numLinks &&
ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId)
idInNode++;
@@ -287,48 +336,20 @@ CCarCtrl::GenerateOneRandomCar()
CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId];
int16 lanesOnCurrentRoad = pPathLink->pathNodeIndex == nextNodeId ? pPathLink->numLeftLanes : pPathLink->numRightLanes;
CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel);
- if (lanesOnCurrentRoad == 0 || pModelInfo->m_vehicleType == VEHICLE_TYPE_BIKE)
+ if (lanesOnCurrentRoad == 0)
/* Not spawning vehicle if road is one way and intended direction is opposide to that way. */
- /* Also not spawning bikes but they don't exist in final game. */
return;
- CAutomobile* pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
+ CVehicle* pVehicle;
+ if (CModelInfo::IsBoatModel(carModel))
+ pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
+ else if (CModelInfo::IsBikeModel(carModel))
+ return; // TODO(MIAMI): spawn bikes
+ else
+ pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
pVehicle->AutoPilot.m_nPrevRouteNode = 0;
pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId;
pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- {
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
- if (carClass == EXEC)
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
- else if (carClass == POOR || carClass == SPECIAL)
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
- CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo();
- if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
- pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
- pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
- }
- pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- break;
- }
case COPS:
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){
@@ -345,16 +366,37 @@ CCarCtrl::GenerateOneRandomCar()
if (carModel == MI_FBICAR){
pVehicle->m_currentColour1 = 0;
pVehicle->m_currentColour2 = 0;
- /* FBI cars are gray in carcols, but we want them black if they going after player. */
}
+ pVehicle->bCreatedAsPoliceVehicle = true;
+ break;
+ case COPS_BOAT:
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4.0f, 16.0f);
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel();
+ pVehicle->bCreatedAsPoliceVehicle = true;
+ break;
default:
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
+ if (carClass == EXEC)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
+ else if (carClass == POOR)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
+ if (pVehicle->GetColModel()->boundingBox.max.y - pVehicle->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
+ pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
+ pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
+ }
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
break;
}
if (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP)
pVehicle->m_bSirenOrAlarm = true;
pVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId;
pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
- CColBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;
+ CBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;
float distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D();
/* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */
@@ -393,11 +435,6 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->GetRight() = CVector(forwardY, -forwardX, 0.0f);
pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);
- float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();
- float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();
- float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX();
- float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY();
-
#ifdef FIX_BUGS
CCarPathLink* pCurrentLink;
CCarPathLink* pNextLink;
@@ -492,6 +529,7 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;
#endif
+
CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f);
CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f);
CVector positionIncludingCurve;
@@ -513,62 +551,69 @@ CCarCtrl::GenerateOneRandomCar()
float groundZ = INFINITE_Z;
CColPoint colPoint;
CEntity* pEntity;
- if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
- groundZ = colPoint.point.z;
- if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)){
- if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ if (bBoatGenerated) {
+ if (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) {
+ delete pVehicle;
+ return;
+ }
+ }
+ else {
+ if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
groundZ = colPoint.point.z;
+ if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {
+ if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ groundZ = colPoint.point.z;
+ }
}
if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) {
/* Failed to find ground or too far from expected position. */
delete pVehicle;
return;
}
- finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
+ if (CModelInfo::IsBoatModel(carModel)) {
+ finalPosition.z = groundZ;
+ pVehicle->bExtendedRange = true;
+ }
+ else
+ finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
pVehicle->SetPosition(finalPosition);
pVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);
CVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed;
CVector2D distanceToTarget = positionIncludingCurve - vecTargetPos;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- pVehicle->SetStatus(STATUS_SIMPLE);
- break;
case COPS:
pVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS);
pVehicle->ChangeLawEnforcerState(1);
break;
+ case COPS_BOAT:
+ pVehicle->ChangeLawEnforcerState(1);
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ break;
default:
+ bBoatGenerated ? pVehicle->SetStatus(STATUS_PHYSICS) : pVehicle->SetStatus(STATUS_SIMPLE);
break;
}
CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
if (!pVehicle->GetIsOnScreen()){
- if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > 50.0f) {
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > OFFSCREEN_DESPAWN_RANGE * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f)) {
/* Too far away cars that are not visible aren't needed. */
delete pVehicle;
return;
}
- }else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * 130.0f ||
- (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 110.0f){
- delete pVehicle;
- return;
- }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 90.0f * TheCamera.GenerationDistMultiplier){
- delete pVehicle;
- return;
+ }else{
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE ||
+ (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) {
+ delete pVehicle;
+ return;
+ }
+ if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
+ delete pVehicle;
+ return;
+ }
+ if (pVehicle->GetModelIndex() == MI_MARQUIS) { // so marquis can only spawn if player doesn't see it?
+ delete pVehicle;
+ return;
+ }
}
CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();
float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;
@@ -591,58 +636,152 @@ CCarCtrl::GenerateOneRandomCar()
}
pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2);
CWorld::Add(pVehicle);
- if (carClass == COPS)
+ if (carClass == COPS || carClass == COPS_BOAT)
CCarAI::AddPoliceCarOccupants(pVehicle);
- else
+ else {
pVehicle->SetUpDriver();
- if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */
+ int32 passengers = 0;
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)
+ passengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;
+ if (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex("van") && passengers >= 1))
+ passengers = 1;
+ for (int i = 0; i < passengers; i++) {
+ CPed* pPassenger = pVehicle->SetupPassenger(i);
+ if (pPassenger) {
+ ++CPopulation::ms_nTotalCarPassengerPeds;
+ pPassenger->bCarPassenger = true;
+ }
+ }
+ }
+ int nMadDrivers;
+ switch (pVehicle->GetVehicleAppearance()) {
+ case VEHICLE_APPEARANCE_BIKE:
+ nMadDrivers = 30;
+ break;
+ case VEHICLE_APPEARANCE_BOAT:
+ nMadDrivers = 40;
+ break;
+ default:
+ nMadDrivers = 6;
+ break;
+ }
+ if ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers /* TODO(MIAMI): || mad drivers cheat */) {
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
pVehicle->AutoPilot.m_nCruiseSpeed += 10;
}
if (carClass == COPS)
LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();
+ if (pVehicle->GetModelIndex() == MI_CADDY) {
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ if (carClass == COPS && pVehicle->GetModelIndex() == MI_VICECHEE) {
+ CVehicleModelInfo* pVehicleModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_VICECHEE);
+ switch (MiamiViceCycle) {
+ case 0:
+ pVehicleModel->SetVehicleColour(53, 77);
+ break;
+ case 1:
+ pVehicleModel->SetVehicleColour(15, 77);
+ break;
+ case 2:
+ pVehicleModel->SetVehicleColour(41, 77);
+ break;
+ case 3:
+ pVehicleModel->SetVehicleColour(61, 77);
+ break;
+ default:
+ break;
+ }
+ }
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= (1 - PROBABILITY_OF_DEAD_PED_ACCIDENT)) {
+ if (CModelInfo::IsCarModel(pVehicle->GetModelIndex()) && !pVehicle->bIsLawEnforcer) {
+ if (CPopulation::AddDeadPedInFrontOfCar(pVehicle->GetPosition() + pVehicle->GetForward() * DISTANCE_BETWEEN_CAR_AND_DEAD_PED, pVehicle)) {
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < pVehicle->m_nNumPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ pVehicle->pPassengers[i]->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pPassengers[i]->m_vehicleInAccident = pVehicle;
+ pVehicle->pPassengers[i]->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pPassengers[i]->m_vehicleInAccident);
+ }
+ }
+ if (pVehicle->pDriver) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ pVehicle->pDriver->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pDriver->m_vehicleInAccident = pVehicle;
+ pVehicle->pDriver->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pDriver->m_vehicleInAccident);
+ }
+ }
+ }
+ }
+}
+
+bool
+CCarCtrl::BoatWithTallMast(int32 mi)
+{
+ return mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;
+}
+
+int32
+CCarCtrl::ChooseBoatModel(int32 rating)
+{
+ ++NumRequestsOfCarRating[rating];
+ return ChooseCarModel(rating);
+}
+
+int32
+CCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_BOAT_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->boatThreshold[i])
+ return FIRST_BOAT_RATING + i;
+ }
+ return FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1;
+}
+
+int32
+CCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_CAR_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->carThreshold[i])
+ return i;
+ }
+ return FIRST_CAR_RATING + NUM_CAR_CLASSES - 1;
}
int32
CCarCtrl::ChooseModel(CZoneInfo* pZone, CVector* pPos, int* pClass) {
int32 model = -1;
- while (model == -1 || !CStreaming::HasModelLoaded(model)){
+ for (int i = 0; i < 10 && (model == -1 || !CStreaming::HasModelLoaded(model)); i++) {
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
- if (rnd < pZone->carThreshold[0])
- model = CCarCtrl::ChooseCarModel((*pClass = POOR));
- else if (rnd < pZone->carThreshold[1])
- model = CCarCtrl::ChooseCarModel((*pClass = RICH));
- else if (rnd < pZone->carThreshold[2])
- model = CCarCtrl::ChooseCarModel((*pClass = EXEC));
- else if (rnd < pZone->carThreshold[3])
- model = CCarCtrl::ChooseCarModel((*pClass = WORKER));
- else if (rnd < pZone->carThreshold[4])
- model = CCarCtrl::ChooseCarModel((*pClass = SPECIAL));
- else if (rnd < pZone->carThreshold[5])
- model = CCarCtrl::ChooseCarModel((*pClass = BIG));
- else if (rnd < pZone->copThreshold)
- *pClass = COPS, model = CCarCtrl::ChoosePoliceCarModel();
- else if (rnd < pZone->gangThreshold[0])
- model = CCarCtrl::ChooseGangCarModel((*pClass = MAFIA) - MAFIA);
- else if (rnd < pZone->gangThreshold[1])
- model = CCarCtrl::ChooseGangCarModel((*pClass = TRIAD) - MAFIA);
- else if (rnd < pZone->gangThreshold[2])
- model = CCarCtrl::ChooseGangCarModel((*pClass = DIABLO) - MAFIA);
- else if (rnd < pZone->gangThreshold[3])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YAKUZA) - MAFIA);
- else if (rnd < pZone->gangThreshold[4])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YARDIE) - MAFIA);
- else if (rnd < pZone->gangThreshold[5])
- model = CCarCtrl::ChooseGangCarModel((*pClass = COLOMB) - MAFIA);
- else if (rnd < pZone->gangThreshold[6])
- model = CCarCtrl::ChooseGangCarModel((*pClass = NINES) - MAFIA);
- else if (rnd < pZone->gangThreshold[7])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG8) - MAFIA);
- else if (rnd < pZone->gangThreshold[8])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG9) - MAFIA);
- else
- model = CCarCtrl::ChooseCarModel((*pClass = TAXI));
+
+ if (rnd < pZone->copThreshold) {
+ *pClass = COPS;
+ model = ChoosePoliceCarModel();
+ continue;
+ }
+
+ int j;
+ for (j = 0; j < NUM_GANG_CAR_CLASSES; j++) {
+ if (rnd < pZone->gangThreshold[i]) {
+ *pClass = j + FIRST_GANG_CAR_RATING;
+ model = ChooseGangCarModel(j);
+ break;
+ }
+ }
+
+ if (j != NUM_GANG_CAR_CLASSES)
+ continue;
+
+ *pClass = ChooseCarRating(pZone);
+ model = ChooseCarModel(*pClass);
}
return model;
}
@@ -651,34 +790,86 @@ int32
CCarCtrl::ChooseCarModel(int32 vehclass)
{
int32 model = -1;
- switch (vehclass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- {
- if (TotalNumOfCarsOfRating[vehclass] == 0)
- debug("ChooseCarModel : No cars of type %d have been declared\n", vehclass);
- model = CarArrays[vehclass][NextCarOfRating[vehclass]];
- int32 total = TotalNumOfCarsOfRating[vehclass];
- NextCarOfRating[vehclass] += CGeneral::GetRandomNumberInRange(1, total);
- while (NextCarOfRating[vehclass] >= total)
- NextCarOfRating[vehclass] -= total;
- //NextCarOfRating[vehclass] %= total;
- TotalNumOfCarsOfRating[vehclass] = total; /* why... */
- }
- default:
- break;
- }
- return model;
+ ++NumRequestsOfCarRating[vehclass];
+ if (NumOfLoadedCarsOfRating[vehclass] == 0)
+ return -1;
+ int32 rnd = CGeneral::GetRandomNumberInRange(0, CarFreqArrays[vehclass][NumOfLoadedCarsOfRating[vehclass] - 1]);
+ int32 index = 0;
+ while (rnd > CarFreqArrays[vehclass][index])
+ index++;
+ assert(LoadedCarsArray[vehclass][index]);
+ return LoadedCarsArray[vehclass][index];
+}
+
+void
+CCarCtrl::AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq)
+{
+ LoadedCarsArray[rating][NumOfLoadedCarsOfRating[rating]] = mi;
+ assert(mi >= 130);
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] = freq;
+ if (NumOfLoadedCarsOfRating[rating])
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] += CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating] - 1];
+ NumOfLoadedCarsOfRating[rating]++;
+}
+
+void
+CCarCtrl::RemoveFromLoadedVehicleArray(int mi, int32 rating)
+{
+ int index = 0;
+ while (LoadedCarsArray[rating][index] != -1) {
+ if (LoadedCarsArray[rating][index] == mi)
+ break;
+ index++;
+ }
+ assert(LoadedCarsArray[rating][index] == mi);
+ int32 freq = CarFreqArrays[rating][index];
+ if (index > 0)
+ freq -= CarFreqArrays[rating][index - 1];
+ while (LoadedCarsArray[rating][index + 1] != -1) {
+ LoadedCarsArray[rating][index] = LoadedCarsArray[rating][index + 1];
+ CarFreqArrays[rating][index] = CarFreqArrays[rating][index + 1] - freq;
+ index++;
+ }
+ --NumOfLoadedCarsOfRating[rating];
+}
+
+int32
+CCarCtrl::ChooseCarModelToLoad(int rating)
+{
+ return CarArrays[rating][CGeneral::GetRandomNumberInRange(0, TotalNumOfCarsOfRating[rating])];
}
int32
CCarCtrl::ChoosePoliceCarModel(void)
{
+ if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired() &&
+#ifdef FIX_BUGS
+ (CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 || LastTimeMiamiViceGenerated == 0) &&
+#else
+ CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 &&
+#endif
+ CStreaming::HasModelLoaded(MI_VICECHEE)) {
+ switch (MiamiViceCycle) {
+ case 0:
+ if (CStreaming::HasModelLoaded(MI_VICE1) && CStreaming::HasModelLoaded(MI_VICE2))
+ return MI_VICECHEE;
+ break;
+ case 1:
+ if (CStreaming::HasModelLoaded(MI_VICE3) && CStreaming::HasModelLoaded(MI_VICE4))
+ return MI_VICECHEE;
+ break;
+ case 2:
+ if (CStreaming::HasModelLoaded(MI_VICE5) && CStreaming::HasModelLoaded(MI_VICE6))
+ return MI_VICECHEE;
+ break;
+ case 3:
+ if (CStreaming::HasModelLoaded(MI_VICE7) && CStreaming::HasModelLoaded(MI_VICE8))
+ return MI_VICECHEE;
+ break;
+ default:
+ break;
+ }
+ }
if (FindPlayerPed()->m_pWanted->AreSwatRequired() &&
CStreaming::HasModelLoaded(MI_ENFORCER) &&
CStreaming::HasModelLoaded(MI_POLICE))
@@ -698,8 +889,7 @@ CCarCtrl::ChoosePoliceCarModel(void)
int32
CCarCtrl::ChooseGangCarModel(int32 gang)
{
- if (CStreaming::HasModelLoaded(MI_GANG01 + 2 * gang) &&
- CStreaming::HasModelLoaded(MI_GANG02 + 2 * gang))
+ if (CGangs::HaveGangModelsLoaded(gang))
return CGangs::GetGangVehicleModel(gang);
return -1;
}
@@ -707,6 +897,7 @@ CCarCtrl::ChooseGangCarModel(int32 gang)
void
CCarCtrl::AddToCarArray(int32 id, int32 vehclass)
{
+ assert(TotalNumOfCarsOfRating[vehclass] < MAX_CAR_MODELS_IN_ARRAY);
CarArrays[vehclass][TotalNumOfCarsOfRating[vehclass]++] = id;
}
@@ -728,6 +919,36 @@ CCarCtrl::RemoveDistantCars()
}
void
+CCarCtrl::RemoveCarsIfThePoolGetsFull(void)
+{
+ if ((CTimer::GetFrameCounter() & 7) != 3)
+ return;
+ if (CPools::GetVehiclePool()->GetNoOfFreeSpaces() >= 8)
+ return;
+ int i = CPools::GetVehiclePool()->GetSize();
+ float md = 999999.9f;
+ CVehicle* pClosestVehicle = nil;
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (IsThisVehicleInteresting(pVehicle) || pVehicle->bIsLocked)
+ continue;
+ if (!pVehicle->CanBeDeleted() || CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle))
+ continue;
+ float distance = (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude();
+ if (distance < md) {
+ md = distance;
+ pClosestVehicle = pVehicle;
+ }
+ }
+ if (pClosestVehicle) {
+ CWorld::Remove(pClosestVehicle);
+ delete pClosestVehicle;
+ }
+}
+
+void
CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
{
CVector vecPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
@@ -740,7 +961,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
- float threshold = 50.0f;
+ float threshold = OFFSCREEN_DESPAWN_RANGE;
if (pVehicle->GetIsOnScreen() ||
TheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||
TheCamera.Cams[TheCamera.ActiveCam].LookingRight ||
@@ -752,12 +973,14 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
pVehicle->bIsLawEnforcer ||
pVehicle->bIsCarParkVehicle
){
- threshold = 130.0f * TheCamera.GenerationDistMultiplier;
+ threshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier;
}
+ if (TheCamera.GetForward().z < -0.9f)
+ threshold = 70.0f;
if (pVehicle->bExtendedRange)
- threshold *= 1.5f;
+ threshold *= EXTENDED_RANGE_DESPAWN_MULTIPLIER;
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
- if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) {
+ if (pVehicle->GetIsOnScreen()){
pVehicle->bFadeOut = true;
}else{
CWorld::Remove(pVehicle);
@@ -766,7 +989,8 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
}
- if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) &&
+ if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS &&
+ (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)) &&
CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 5000 &&
!pVehicle->GetIsOnScreen() &&
(pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 25.0f &&
@@ -783,7 +1007,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)
return;
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
- !(pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) ){
+ !pVehicle->GetIsOnScreen()){
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){
if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
CWorld::Remove(pVehicle);
@@ -807,6 +1031,16 @@ CCarCtrl::CountCarsOfType(int32 mi)
return total;
}
+static CVector GetRandomOffsetForVehicle(CVehicle* pVehicle, bool bNext)
+{
+ CVector offset;
+ int32 seed = ((bNext ? pVehicle->AutoPilot.m_nNextPathNodeInfo : pVehicle->AutoPilot.m_nCurrentPathNodeInfo) + pVehicle->m_randomSeed) & 7;
+ offset.x = (seed - 3) * 0.009f;
+ offset.y = ((seed >> 3) - 3) * 0.009f;
+ offset.z = 0.0f;
+ return offset;
+}
+
void
CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
{
@@ -839,8 +1073,12 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f);
- CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
- CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
+ CVector directionCurrentLink = GetRandomOffsetForVehicle(pVehicle, false);
+ directionCurrentLink += CVector(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
+ directionCurrentLink.Normalise();
+ CVector directionNextLink = GetRandomOffsetForVehicle(pVehicle, true);
+ directionNextLink += CVector(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
+ directionNextLink.Normalise();
CVector positionIncludingCurve;
CVector directionIncludingCurve;
CCurves::CalcCurvePoint(
@@ -863,7 +1101,7 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
{
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS ||
pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH)
- return pVehicle->AutoPilot.m_nCruiseSpeed;
+ return pVehicle->AutoPilot.GetCruiseSpeed();
float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER;
float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER;
float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER;
@@ -875,23 +1113,23 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
assert(xstart <= xend);
assert(ystart <= yend);
- float maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ float maxSpeed = pVehicle->AutoPilot.GetCruiseSpeed();
CWorld::AdvanceCurrentScanCode();
for (int y = ystart; y <= yend; y++){
for (int x = xstart; x <= xend; x++){
CSector* s = CWorld::GetSector(x, y);
- SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
+ SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
}
}
pVehicle->bWarnedPeds = true;
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS)
return maxSpeed;
- return (maxSpeed + pVehicle->AutoPilot.m_nCruiseSpeed) / 2;
+ return (maxSpeed + pVehicle->AutoPilot.GetCruiseSpeed()) / 2;
}
void
@@ -1093,8 +1331,8 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle,
float proximityA = TestCollisionBetween2MovingRects(pOtherVehicle, pVehicle, projectionX, projectionY, &forwardA, &forwardB, 0);
float proximityB = TestCollisionBetween2MovingRects(pVehicle, pOtherVehicle, -projectionX, -projectionY, &forwardB, &forwardA, 1);
float minProximity = Min(proximityA, proximityB);
- if (minProximity >= 0.0f && minProximity < 1.0f){
- minProximity = Max(0.0f, (minProximity - 0.2f) * 1.25f);
+ if (minProximity >= 0.0f && minProximity < 1.5f){
+ minProximity = Max(0.0f, (minProximity - 0.2f) / 1.3f);
pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true;
*pSpeed = Min(*pSpeed, minProximity * curSpeed);
}
@@ -1320,19 +1558,21 @@ void CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh
void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)
{
+ CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
+ if (pVehicle->bPartOfConvoy && pOtherCar->bPartOfConvoy)
+ return;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerVehicle())
return;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar)
return;
- CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
CVector2D vecDiff = pOtherCar->GetPosition() - pVehicle->GetPosition();
float angleBetweenVehicles = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);
float distance = vecDiff.Magnitude();
if (distance < 1.0f)
return;
if (DotProduct2D(pVehicle->GetMoveSpeed() - pOtherCar->GetMoveSpeed(), vecDiff) * 110.0f -
- pOtherCar->GetModelInfo()->GetColModel()->boundingSphere.radius -
- pVehicle->GetModelInfo()->GetColModel()->boundingSphere.radius < distance)
+ pOtherCar->GetColModel()->boundingSphere.radius -
+ pVehicle->GetColModel()->boundingSphere.radius < distance)
return;
CVector2D forward = pVehicle->GetForward();
forward.Normalise();
@@ -1506,23 +1746,30 @@ bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle)
return false;
default:
PickNextNodeRandomly(pVehicle);
+ if (ThePaths.GetNode(pVehicle->AutoPilot.m_nNextRouteNode)->bOnlySmallBoats && BoatWithTallMast(pVehicle->GetModelIndex()))
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
return false;
}
}
void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode;
uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks;
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
-#ifdef FIX_BUGS
- uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ?
- pCurLink->numLeftLanes : pCurLink->numRightLanes;
-#else
- uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ?
- pCurLink->numRightLanes : pCurLink->numLeftLanes;
-#endif
+ uint8 lanesOnCurrentPath;
+ bool isOnOneWayRoad;
+ if (pCurLink->pathNodeIndex == curNode) {
+ lanesOnCurrentPath = pCurLink->numLeftLanes;
+ isOnOneWayRoad = pCurLink->numRightLanes == 0;
+ }
+ else {
+ lanesOnCurrentPath = pCurLink->numRightLanes;
+ isOnOneWayRoad = pCurLink->numLeftLanes == 0;
+ }
uint8 allowedDirections = PATH_DIRECTION_NONE;
uint8 nextLane = pVehicle->AutoPilot.m_nNextLane;
if (nextLane == 0)
@@ -1544,6 +1791,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
CCarPathLink* pNextLink;
CPathNode* pNextPathNode;
bool goingAgainstOneWayRoad;
+ bool nextNodeIsOneWayRoad;
uint8 direction;
for(attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++){
if (attempt != 0){
@@ -1553,7 +1801,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
if ((!pNextPathNode->bDeadEnd || pPrevPathNode->bDeadEnd) &&
(!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&
(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel) &&
- !goingAgainstOneWayRoad)
+ !goingAgainstOneWayRoad && (!isOnOneWayRoad || !nextNodeIsOneWayRoad))
break;
}
}
@@ -1563,9 +1811,10 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
direction = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode);
pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;
+ nextNodeIsOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numLeftLanes == 0 : pNextLink->numRightLanes == 0;
}
if (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) {
- /* If we failed 15 times, then remove dead end and current lane limitations */
+ /* If we failed 15 times, then remove dead end, one way road and current lane limitations */
for (attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++) {
if (attempt != 0) {
if (pVehicle->AutoPilot.m_nNextRouteNode != prevNode) {
@@ -1646,6 +1895,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
}
if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0;
+#ifdef FIX_BUGS
CVector positionOnCurrentLinkIncludingLane(
pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
@@ -1654,6 +1904,16 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f);
+#else
+ CVector positionOnCurrentLinkIncludingLane(
+ pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH),
+ pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
+ 0.0f);
+ CVector positionOnNextLinkIncludingLane(
+ pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
+ pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
+ 0.0f);
+#endif
float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
@@ -1704,74 +1964,57 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float targetY, CVehicle* pTarget)
#endif
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNode];
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
- CPathNode* pTargetNode;
+ CPathNode* pTargetNode[2];
int16 numNodes;
float distanceToTargetNode;
- if (pTarget && pTarget->m_pCurGroundEntity &&
- pTarget->m_pCurGroundEntity->IsBuilding() &&
- ((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() &&
- ((CTreadable*)pTarget->m_pCurGroundEntity)->m_nodeIndices[0][0] >= 0){
- CTreadable* pCurrentMapObject = (CTreadable*)pTarget->m_pCurGroundEntity;
- int closestNode = -1;
- float minDist = 100000.0f;
- for (int i = 0; i < 12; i++){
- int node = pCurrentMapObject->m_nodeIndices[0][i];
- if (node < 0)
- break;
- float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude();
- if (dist < minDist){
- minDist = dist;
- closestNode = node;
- }
- }
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
+ ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
+ CVector(targetX, targetY, targetZ),
#else
- CVector(targetX, targetY, 0.0f),
+ CVector(targetX, targetY, 0.0f),
#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode);
- }else
- {
-
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
-#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
-#else
- CVector(targetX, targetY, 0.0f),
-#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
- }
+ pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 999999.9f, -1);
int newNextNode;
int nextLink;
- if (numNodes != 1 || pTargetNode == pCurNode){
- float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
- nextLink = 0;
- float lowestAngleChange = 10.0f;
- int numLinks = pCurNode->numLinks;
- newNextNode = 0;
- for (int i = 0; i < numLinks; i++){
- int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);
- if (conNode == prevNode && i > 1)
- continue;
- CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
- float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
- angle = LimitRadianAngle(angle - currentAngle);
- angle = ABS(angle);
- if (angle < lowestAngleChange){
- lowestAngleChange = angle;
- newNextNode = conNode;
- nextLink = i;
+ if (numNodes != 1 && numNodes != 2 || pTargetNode[0] == pCurNode){
+ if (numNodes != 2 || pTargetNode[1] == pCurNode) {
+ float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ nextLink = 0;
+ float lowestAngleChange = 10.0f;
+ int numLinks = pCurNode->numLinks;
+ newNextNode = 0;
+ for (int i = 0; i < numLinks; i++) {
+ int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);
+ if (conNode == prevNode && i > 1)
+ continue;
+ CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
+ float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
+ angle = LimitRadianAngle(angle - currentAngle);
+ angle = ABS(angle);
+ if (angle < lowestAngleChange) {
+ lowestAngleChange = angle;
+ newNextNode = conNode;
+ nextLink = i;
+ }
}
}
- }else{
+ else {
+ nextLink = 0;
+ newNextNode = pTargetNode[1] - ThePaths.m_pathNodes;
+ for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)
+ ;
+ }
+ }
+ else {
nextLink = 0;
- newNextNode = pTargetNode - ThePaths.m_pathNodes;
+ newNextNode = pTargetNode[0] - ThePaths.m_pathNodes;
for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)
;
}
@@ -1791,11 +2034,11 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
int8 lanesOnNextNode;
if (curNode >= pVehicle->AutoPilot.m_nNextRouteNode) {
pVehicle->AutoPilot.m_nNextDirection = 1;
- lanesOnNextNode = pNextLink->numLeftLanes;
+ lanesOnNextNode = pNextLink->numRightLanes;
}
else {
pVehicle->AutoPilot.m_nNextDirection = -1;
- lanesOnNextNode = pNextLink->numRightLanes;
+ lanesOnNextNode = pNextLink->numLeftLanes;
}
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();
@@ -1850,6 +2093,8 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
if (pVehicle->AutoPilot.m_nPathFindNodesCount == 0){
@@ -1942,6 +2187,7 @@ void CCarCtrl::Init(void)
LastTimeAmbulanceCreated = 0;
#ifdef FIX_BUGS
LastTimeLawEnforcerCreated = 0;
+ LastTimeMiamiViceGenerated = 0;
#endif
bCarsGeneratedAroundCamera = false;
CountDownToCarsAtStart = 2;
@@ -1949,9 +2195,11 @@ void CCarCtrl::Init(void)
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++){
- for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++)
- CarArrays[i][j] = 0;
- NextCarOfRating[i] = 0;
+ for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++) {
+ LoadedCarsArray[i][j] = -1;
+ }
+ NumOfLoadedCarsOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
TotalNumOfCarsOfRating[i] = 0;
}
}
@@ -1969,13 +2217,14 @@ void CCarCtrl::ReInit(void)
LastTimeFireTruckCreated = 0;
LastTimeAmbulanceCreated = 0;
LastTimeLawEnforcerCreated = 0;
+ LastTimeMiamiViceGenerated = 0;
#endif
CountDownToCarsAtStart = 2;
CarDensityMultiplier = 1.0f;
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++)
- NextCarOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
}
void CCarCtrl::DragCarToPoint(CVehicle* pVehicle, CVector* pPoint)
@@ -2085,7 +2334,7 @@ void CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
break;
case TEMPACT_HANDBRAKETURNLEFT:
- swerve = -1.0f; // It seems like this should be swerve = 1.0f (fixed in VC)
+ swerve = 1.0f;
accel = 0.0f;
brake = 0.0f;
handbrake = true;
@@ -2093,7 +2342,7 @@ void CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
break;
case TEMPACT_HANDBRAKETURNRIGHT:
- swerve = 1.0f; // It seems like this should be swerve = -1.0f (fixed in VC)
+ swerve = -1.0f;
accel = 0.0f;
brake = 0.0f;
handbrake = true;
@@ -2204,6 +2453,9 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
SteerAICarWithPhysicsTryingToBlockTarget_Stop(pVehicle, FindPlayerCoors().x, FindPlayerCoors().y,
FindPlayerSpeed().x, FindPlayerSpeed().y, pSwerve, pAccel, pBrake, pHandbrake);
return;
+ case MISSION_WAITFORDELETION:
+ case MISSION_HELI_LAND:
+ return;
case MISSION_GOTOCOORDS_STRAIGHT:
case MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:
SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,
@@ -2217,6 +2469,12 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
*pHandbrake = true;
*pBrake = 0.5f;
return;
+ case MISSION_GOTOCOORDS_ASTHECROWSWIMS:
+ SteerAIBoatWithPhysicsHeadingForTarget(pVehicle,
+ pVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,
+ pSwerve, pAccel, pBrake);
+ *pHandbrake = false;
+ return;
case MISSION_RAMCAR_CLOSE:
SteerAICarWithPhysicsHeadingForTarget(pVehicle, pVehicle->AutoPilot.m_pTargetCar,
pVehicle->AutoPilot.m_pTargetCar->GetPosition().x, pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,
@@ -2238,26 +2496,93 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
pVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().y,
pSwerve, pAccel, pBrake, pHandbrake);
return;
+ case MISSION_HELI_FLYTOCOORS:
+ //SteerAIHeliTowardsTargetCoors((CAutomobile*)pVehicle);
+ return;
+ case MISSION_ATTACKPLAYER:
+ SteerAIBoatWithPhysicsAttackingPlayer(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_PLANE_FLYTOCOORS:
+ //SteerAIPlaneTowardsTargetCoors((CAutomobile*)pVehicle);
+ return;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,
+ pVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,
+ pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, FindPlayerCoors().x, FindPlayerCoors().y,
+ pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_BLOCKPLAYER_FORWARDANDBACK:
+ //SteerAICarBlockingPlayerForwardAndBack(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ return;
default:
+ assert(0);
return;
}
}
-void CCarCtrl::SteerAIBoatWithPhysics(CBoat* pBoat)
+void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)
{
- if (pBoat->AutoPilot.m_nCarMission == MISSION_GOTOCOORDS_ASTHECROWSWIMS){
- SteerAIBoatWithPhysicsHeadingForTarget(pBoat,
- pBoat->AutoPilot.m_vecDestinationCoors.x, pBoat->AutoPilot.m_vecDestinationCoors.y,
- &pBoat->m_fSteeringLeftRight, &pBoat->m_fAccelerate, &pBoat->m_fBrake);
- }else if (pBoat->AutoPilot.m_nCarMission == MISSION_NONE){
- pBoat->m_fSteeringLeftRight = 0.0f;
- pBoat->m_fAccelerate = 0.0f;
- pBoat->m_fBrake = 0.0f;
+ CVector2D forward = pVehicle->GetForward();
+ forward.Normalise();
+ float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
+ float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
+ steerAngle = clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);
+#ifdef FIX_BUGS
+ float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;
+#endif
+ float currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;
+ float speedDiff = speedTarget - currentSpeed;
+ if (speedDiff <= 0.0f) {
+ speedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;
+ steerAngle *= -1;
+ }
+ else if (speedDiff / currentSpeed > 0.25f) {
+ *pAccel = 1.0f;
}
- pBoat->m_fSteerAngle = pBoat->m_fSteeringLeftRight;
- pBoat->m_fGasPedal = pBoat->m_fAccelerate;
- pBoat->m_fBrakePedal = pBoat->m_fBrake;
- pBoat->bIsHandbrakeOn = false;
+ else {
+ *pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;
+ }
+ *pBrake = 0.0f;
+ *pSwerve = steerAngle;
+}
+
+void CCarCtrl::SteerAIBoatWithPhysicsAttackingPlayer(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
+{
+ float distanceToPlayer = (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();
+ float projection = Min(distanceToPlayer * 0.05f, 2.0f);
+ CVector2D forward = pVehicle->GetForward();
+ forward.Normalise();
+ CVector2D vecToProjection = FindPlayerCoors() + FindPlayerSpeed() * projection * GAME_SPEED_TO_CARAI_SPEED;
+ float angleToTarget = CGeneral::GetATanOfXY(vecToProjection.x - pVehicle->GetPosition().x, vecToProjection.y - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
+ float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
+#ifdef FIX_BUGS
+ float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;
+#endif
+ float currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;
+ float speedDiff = speedTarget - currentSpeed;
+ if (speedDiff <= 0.0f) {
+ speedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;
+ }
+ else if (speedDiff / currentSpeed > 0.25f) {
+ *pAccel = 1.0f;
+ }
+ else {
+ *pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;
+ }
+ *pBrake = 0.0f;
+ *pSwerve = steerAngle;
+ *pHandbrake = false;
+ if (pVehicle->GetModelIndex() == MI_PREDATOR && distanceToPlayer < 40.0f && steerAngle < 0.15f)
+ pVehicle->FireFixedMachineGuns();
}
float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)
@@ -2265,6 +2590,50 @@ float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)
return pVehicle->GetModelIndex() == MI_ENFORCER ? 0.7f : DEFAULT_MAX_STEER_ANGLE;
}
+void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli)
+{
+ if (pHeli->m_aWheelSpeed[1] < 0.22f)
+ pHeli->m_aWheelSpeed[1] += 0.001f;
+ if (pHeli->m_aWheelSpeed[1] < 0.22f)
+ return;
+ CVector2D vecToTarget = pHeli->AutoPilot.m_vecDestinationCoors - pHeli->GetPosition();
+ float distanceToTarget = vecToTarget.Magnitude();
+#ifdef FIX_BUGS
+ float speed = pHeli->AutoPilot.GetCruiseSpeed() * 0.01f;
+#else
+ float speed = pHeli->AutoPilot.m_nCruiseSpeed * 0.01f;
+#endif
+ if (distanceToTarget >= 100.0f)
+ {
+ if (distanceToTarget > 75.0f)
+ speed *= 0.7f;
+ else if (distanceToTarget > 10.0f)
+ speed *= 0.4f;
+ else
+ speed *= 0.2f;
+ }
+ CVector2D vecAdvanceThisFrame = vecToTarget;
+ vecAdvanceThisFrame.Normalise();
+ vecAdvanceThisFrame *= speed;
+ float resistance = Pow(0.997f, CTimer::GetTimeStep());
+ pHeli->m_vecMoveSpeed.x *= resistance;
+ pHeli->m_vecMoveSpeed.y *= resistance;
+ vecAdvanceThisFrame -= pHeli->m_vecMoveSpeed;
+ CVector2D vecSpeedChange = vecAdvanceThisFrame - pHeli->m_vecMoveSpeed;
+ float vecSpeedChangeLength = vecSpeedChange.Magnitude();
+ vecSpeedChange.Normalise();
+ float changeMultiplier = 0.002f * CTimer::GetTimeStep();
+ if (distanceToTarget < 5.0f)
+ changeMultiplier /= 5.0f;
+ if (vecSpeedChangeLength < changeMultiplier)
+ pHeli->AddToMoveSpeed(vecAdvanceThisFrame);
+ else
+ pHeli->AddToMoveSpeed(vecSpeedChange * changeMultiplier);
+ pHeli->SetPosition(pHeli->GetPosition() + CVector(CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.x, CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.y, 0.0f));
+ assert(0);
+ // This is not finished yet. Heli fields in CAutomobile required
+}
+
void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
CVector2D forward = pVehicle->GetForward();
@@ -2292,18 +2661,12 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
if (PickNextNodeAccordingStrategy(pVehicle)) {
switch (pVehicle->AutoPilot.m_nCarMission){
case MISSION_GOTOCOORDS:
- pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
- *pSwerve = 0.0f;
- *pAccel = 0.0f;
- *pBrake = 0.0f;
- *pHandbrake = false;
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,
+ pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);
return;
case MISSION_GOTOCOORDS_ACCURATE:
- pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
- *pSwerve = 0.0f;
- *pAccel = 0.0f;
- *pBrake = 0.0f;
- *pHandbrake = false;
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,
+ pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);
return;
default: break;
}
@@ -2340,6 +2703,7 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
switch (pVehicle->AutoPilot.m_nDrivingStyle) {
case DRIVINGSTYLE_STOP_FOR_CARS:
case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS:
+ case DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS:
speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle) / pVehicle->AutoPilot.m_nCruiseSpeed;
break;
default:
@@ -2445,6 +2809,7 @@ void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget(CVehicle* pVehicle, floa
pVehicle->AutoPilot.m_nCarMission = (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_CLOSE) ?
MISSION_BLOCKCAR_HANDBRAKESTOP : MISSION_BLOCKPLAYER_HANDBRAKESTOP;
}
+
void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle, float targetX, float targetY, float targetSpeedX, float targetSpeedY, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
*pSwerve = 0.0f;
@@ -2486,26 +2851,6 @@ void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle,
}
}
-void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CBoat* pBoat, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)
-{
- CVector2D forward(pBoat->GetForward());
- forward.Normalise();
- CVector2D distanceToTarget = CVector2D(targetX, targetY) - pBoat->GetPosition();
- float angleToTarget = CGeneral::GetATanOfXY(distanceToTarget.x, distanceToTarget.y);
- float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
- float angleDiff = LimitRadianAngle(angleToTarget - angleForward);
- angleDiff = Min(DEFAULT_MAX_STEER_ANGLE, Max(-DEFAULT_MAX_STEER_ANGLE, angleDiff));
- float currentSpeed = pBoat->GetMoveSpeed().Magnitude2D(); // +0.0f for some reason
- float speedDiff = pBoat->AutoPilot.m_nCruiseSpeed - currentSpeed * 60.0f;
- if (speedDiff > 0.0f){
- float accRemaining = speedDiff / pBoat->AutoPilot.m_nCruiseSpeed;
- *pAccel = (accRemaining > 0.25f) ? 1.0f : 1.0f - (0.25f - accRemaining) * 4.0f;
- }else
- *pAccel = (speedDiff < -5.0f) ? -0.2f : -0.1f;
- *pBrake = 0.0f;
- *pSwerve = angleDiff;
-}
-
void
CCarCtrl::RegisterVehicleOfInterest(CVehicle* pVehicle)
{
@@ -2627,6 +2972,8 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int nextLink;
CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];
for (nextLink = 0; nextLink < 12; nextLink++)
@@ -2640,11 +2987,21 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
curLink = 0;
curConnection = ThePaths.m_carPathConnections[pCurNode->firstLink];
}else{
- curConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo;
- while (curConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){
- curLink = CGeneral::GetRandomNumber() % pCurNode->numLinks;
- curConnection = ThePaths.m_carPathConnections[curLink + pCurNode->firstLink];
+ int closestLink = -1;
+ float md = 999999.9f;
+
+ for (curLink = 0; curLink < pCurNode->numLinks; curLink++) {
+ int node = ThePaths.ConnectedNode(curLink + pCurNode->firstLink);
+ CPathNode* pNode = &ThePaths.m_pathNodes[node];
+ if (node == pVehicle->AutoPilot.m_nNextRouteNode)
+ continue;
+ float dist = CCollision::DistToLine(&pCurNode->GetPosition(), &pNode->GetPosition(), &pVehicle->GetPosition());
+ if (dist < md) {
+ md = dist;
+ closestLink = curLink;
+ }
}
+ curConnection = ThePaths.m_carPathConnections[closestLink + pCurNode->firstLink];
}
pVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection;
pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1;
@@ -2654,6 +3011,8 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
{
if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 3)
return;
+ if (CGame::IsInInterior())
+ return;
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars +
NumLawEnforcerCars + NumRandomCars > MaxNumberOfCarsInUse)
return;
@@ -2709,9 +3068,11 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
if (ThePaths.NewGenerateCarCreationCoors(pPlayerPos.x, pPlayerPos.y, 0.707f, 0.707f,
120.0f, -1.0f, true, &spawnPos, &curNode, &nextNode, &posBetweenNodes, false)){
int16 colliding[2];
- CWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);
- if (colliding[0] == 0)
- created = true;
+ if (!ThePaths.GetNode(curNode)->bWaterPath) {
+ CWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);
+ if (colliding[0] == 0)
+ created = true;
+ }
}
attempts += 1;
}
@@ -2770,18 +3131,24 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
if (remove){
switch (pVehicle->VehicleCreatedBy){
case RANDOM_VEHICLE:
- if (pVehicle->bIsLawEnforcer)
- --NumLawEnforcerCars;
- --NumRandomCars;
+ if (pVehicle->bIsLawEnforcer) {
+ if (--NumLawEnforcerCars < 0)
+ NumLawEnforcerCars = 0;
+ }
+ if (--NumRandomCars < 0)
+ NumRandomCars = 0;
return;
case MISSION_VEHICLE:
- --NumMissionCars;
+ if (--NumMissionCars < 0)
+ NumMissionCars = 0;
return;
case PARKED_VEHICLE:
- --NumParkedCars;
+ if (--NumParkedCars < 0)
+ NumParkedCars = 0;
return;
case PERMANENT_VEHICLE:
- --NumPermanentCars;;
+ if (--NumPermanentCars < 0)
+ NumPermanentCars = 0;
return;
}
}
@@ -2799,7 +3166,7 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
++NumParkedCars;
return;
case PERMANENT_VEHICLE:
- ++NumPermanentCars;;
+ ++NumPermanentCars;
return;
}
}
@@ -2807,12 +3174,30 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
bool CCarCtrl::ThisRoadObjectCouldMove(int16 mi)
{
+#ifdef GTA_BRIDGE
return mi == MI_BRIDGELIFT || mi == MI_BRIDGEROADSEGMENT;
+#else
+ return false;
+#endif
}
bool CCarCtrl::MapCouldMoveInThisArea(float x, float y)
{
+#ifdef GTA_BRIDGE // actually they forgot that in VC...
// bridge moves up and down
return x > -342.0f && x < -219.0f &&
y > -677.0f && y < -580.0f;
+#else
+ return false;
+#endif
+}
+
+float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
+{
+ switch (type)
+ {
+ case 1: return 1.5f;
+ case 2: return 2.0f;
+ }
+ return 1.0f;
}
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 457224fb..ed63a0e2 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -9,10 +9,11 @@
#define TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING 2500
class CZoneInfo;
+class CAutomobile;
enum{
MAX_CARS_TO_KEEP = 2,
- MAX_CAR_MODELS_IN_ARRAY = 256,
+ MAX_CAR_MODELS_IN_ARRAY = 25,
};
#define LANE_WIDTH 5.0f
@@ -25,24 +26,37 @@ class CCarCtrl
{
public:
enum eCarClass {
- POOR = 0,
+ NORMAL = 0,
+ POOR,
RICH,
EXEC,
WORKER,
- SPECIAL,
BIG,
TAXI,
- TOTAL_CUSTOM_CLASSES,
- MAFIA,
- TRIAD,
- DIABLO,
- YAKUZA,
- YARDIE,
- COLOMB,
- NINES,
- GANG8,
+ MOPED,
+ MOTORBIKE,
+
+ LEISUREBOAT,
+ WORKERBOAT,
+
+ COPS,
+ CUBAN,
+ HAITIAN,
+ STREET,
+ DIAZ,
+ BIKER,
+ SECURITY,
+ PLAYER,
+ GOLFERS,
GANG9,
- COPS
+ COPS_BOAT,
+ FIRST_CAR_RATING = NORMAL,
+ FIRST_BOAT_RATING = LEISUREBOAT,
+ FIRST_GANG_CAR_RATING = CUBAN,
+ NUM_CAR_CLASSES = MOTORBIKE - FIRST_CAR_RATING + 1,
+ NUM_BOAT_CLASSES = WORKERBOAT - FIRST_BOAT_RATING + 1,
+ NUM_GANG_CAR_CLASSES = GANG9 - FIRST_GANG_CAR_RATING + 1,
+ TOTAL_CUSTOM_CLASSES = NUM_CAR_CLASSES + NUM_BOAT_CLASSES
};
static void SwitchVehicleToRealPhysics(CVehicle*);
@@ -94,17 +108,29 @@ public:
static float FindSpeedMultiplier(float, float, float, float);
static void SteerAICarWithPhysics(CVehicle*);
static void SteerAICarWithPhysics_OnlyMission(CVehicle*, float*, float*, float*, bool*);
- static void SteerAIBoatWithPhysics(CBoat*);
static float FindMaxSteerAngle(CVehicle*);
static void SteerAICarWithPhysicsFollowPath(CVehicle*, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsHeadingForTarget(CVehicle*, CPhysical*, float, float, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsTryingToBlockTarget(CVehicle*, float, float, float, float, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle*, float, float, float, float, float*, float*, float*, bool*);
- static void SteerAIBoatWithPhysicsHeadingForTarget(CBoat*, float, float, float*, float*, float*);
static bool ThisRoadObjectCouldMove(int16);
static void ClearInterestingVehicleList();
static void FindLinksToGoWithTheseNodes(CVehicle*);
static bool GenerateOneEmergencyServicesCar(uint32, CVector);
+ static float FindSpeedMultiplierWithSpeedFromNodes(int8);
+ static int32 ChooseBoatModel(int32);
+ static int32 ChooseBoatRating(CZoneInfo* pZoneInfo);
+ static int32 ChooseCarRating(CZoneInfo* pZoneInfo);
+ static void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq);
+ static void RemoveFromLoadedVehicleArray(int32 mi, int32 rating);
+ static int32 ChooseCarModelToLoad(int32 rating);
+ static bool BoatWithTallMast(int32 mi);
+ static void RemoveCarsIfThePoolGetsFull(void);
+ static void SteerAIBoatWithPhysicsHeadingForTarget(CVehicle*, float, float, float*, float*, float*);
+ static void SteerAIHeliTowardsTargetCoors(CAutomobile*);
+ static void SteerAIPlaneTowardsTargetCoors(CAutomobile*);
+ static void SteerAIBoatWithPhysicsAttackingPlayer(CVehicle*, float*, float*, float*, bool*);
+ static void SteerAICarBlockingPlayerForwardAndBack(CVehicle*, float*, float*, float*, bool*);
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
@@ -136,8 +162,14 @@ public:
static uint32 LastTimeFireTruckCreated;
static uint32 LastTimeAmbulanceCreated;
static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
- static int32 NextCarOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+
+ static int32 MiamiViceCycle;
+ static uint32 LastTimeMiamiViceGenerated;
+ static int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+ static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+ static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+ static int32 LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
};
extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; \ No newline at end of file
diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp
index 0a01a7aa..31a2767a 100644
--- a/src/control/Curves.cpp
+++ b/src/control/Curves.cpp
@@ -11,7 +11,7 @@ float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float di
if (dp > 0.9f)
return distance + Abs((pPoint1->x * dir1Y - pPoint1->y * dir1X) - (pPoint2->x * dir1Y - pPoint2->y * dir1X));
else
- return ((1.0f - dp) * 0.2f + 1.0f) * distance;
+ return ((1.0f - dp) * 0.25f + 1.0f) * distance;
}
void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVector* pDir2, float between, int32 timeOnCurve, CVector* pOutPos, CVector* pOutDir)
@@ -19,7 +19,21 @@ void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVe
float actualFactor = CalcSpeedScaleFactor(pPos1, pPos2, pDir1->x, pDir1->y, pDir2->x, pDir2->y);
CVector2D dir1 = *pDir1 * actualFactor;
CVector2D dir2 = *pDir2 * actualFactor;
- float curveCoef = 0.5f - 0.5f * Cos(3.1415f * between);
+ float t1 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir1));
+ float t2 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir2));
+ float curveCoef;
+ if (t1 > t2) {
+ if (between < (t1 - t2) / (t1 + t2))
+ curveCoef = 0.0f;
+ else
+ curveCoef = 0.5f - 0.5f * Cos(3.1415f * (t1 + t2) / (2 * t2) * (between - (t1 - t2) / (t1 + t2)));
+ }
+ else {
+ if (2 * t1 / (t1 + t2) < between)
+ curveCoef = 1.0f;
+ else
+ curveCoef = 0.5f - 0.5f * Cos(3.1415f * between * (t1 + t2) / (2 * t1));
+ }
*pOutPos = CVector(
(pPos1->x + between * dir1.x) * (1.0f - curveCoef) + (pPos2->x - (1 - between) * dir2.x) * curveCoef,
(pPos1->y + between * dir1.y) * (1.0f - curveCoef) + (pPos2->y - (1 - between) * dir2.y) * curveCoef,
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index 5fc44974..a177343b 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -39,8 +39,8 @@
#define CRUSHER_CRANE_SPEED (0.005f)
// Prices
-#define BOMB_PRICE (1000)
-#define RESPRAY_PRICE (1000)
+#define BOMB_PRICE (500)
+#define RESPRAY_PRICE (100)
// Distances
#define DISTANCE_TO_CALL_OFF_CHASE (10.0f)
@@ -50,10 +50,10 @@
#define DISTANCE_TO_CLOSE_MISSION_GARAGE (30.0f)
#define DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE (25.0f)
#define DISTANCE_TO_CLOSE_COLLECTCARS_GARAGE (40.0f)
-#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (2.2f)
+#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (3.2f)
#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR (15.0f)
#define DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE (70.0f)
-#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (1.7f)
+#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (2.8f)
#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR (10.0f)
#define DISTANCE_TO_SHOW_HIDEOUT_MESSAGE (5.0f)
@@ -68,7 +68,7 @@
// Respray stuff
#define FREE_RESPRAY_HEALTH_THRESHOLD (970.0f)
#define NUM_PARTICLES_IN_RESPRAY (200)
-#define RESPRAY_CENTERING_COEFFICIENT (0.75f)
+#define RESPRAY_CENTERING_COEFFICIENT (0.4f)
// Bomb stuff
#define KGS_OF_EXPLOSIVES_IN_BOMB (10)
@@ -81,8 +81,8 @@
// Collect cars stuff
#define MAX_SPEED_TO_SHOW_COLLECTED_MESSAGE (0.03f)
-#define IMPORT_REWARD (1000)
-#define IMPORT_ALLCARS_REWARD (200000)
+#define IMPORT_REWARD (500)
+#define IMPORT_ALLCARS_REWARD (20500)
// Crusher stuff
#define CRUSHER_VEHICLE_TEST_SPAN (8)
@@ -91,26 +91,23 @@
#define CRUSHER_REWARD_COEFFICIENT (1.0f/500000)
// Hideout stuff
-#define MAX_STORED_CARS_IN_INDUSTRIAL (1)
-#define MAX_STORED_CARS_IN_COMMERCIAL (NUM_GARAGE_STORED_CARS)
-#define MAX_STORED_CARS_IN_SUBURBAN (NUM_GARAGE_STORED_CARS)
-#define LIMIT_CARS_IN_INDUSTRIAL (1)
-#define LIMIT_CARS_IN_COMMERCIAL (2)
-#define LIMIT_CARS_IN_SUBURBAN (3)
#define HIDEOUT_DOOR_SPEED_COEFFICIENT (1.7f)
#define TIME_BETWEEN_HIDEOUT_MESSAGES (18000)
// Camera stuff
-#define MARGIN_FOR_CAMERA_COLLECTCARS (1.3f)
-#define MARGIN_FOR_CAMERA_DEFAULT (4.0f)
+#define MARGIN_FOR_CAMERA_COLLECTCARS (0.5f)
+#define MARGIN_FOR_CAMERA_DEFAULT (0.5f)
const int32 gaCarsToCollectInCraigsGarages[TOTAL_COLLECTCARS_GARAGES][TOTAL_COLLECTCARS_CARS] =
{
- { MI_SECURICA, MI_MOONBEAM, MI_COACH, MI_FLATBED, MI_LINERUN, MI_TRASH, MI_PATRIOT, MI_MRWHOOP, MI_BLISTA, MI_MULE, MI_YANKEE, MI_BOBCAT, MI_DODO, MI_BUS, MI_RUMPO, MI_PONY },
- { MI_SENTINEL, MI_CHEETAH, MI_BANSHEE, MI_IDAHO, MI_INFERNUS, MI_TAXI, MI_KURUMA, MI_STRETCH, MI_PEREN, MI_STINGER, MI_MANANA, MI_LANDSTAL, MI_STALLION, MI_BFINJECT, MI_CABBIE, MI_ESPERANT },
- { MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO }
+ { MI_LANDSTAL, MI_IDAHO, MI_ESPERANT, MI_STALLION, MI_RANCHER, MI_BLISTAC },
+ { MI_SABRE, MI_VIRGO, MI_SENTINEL, MI_STRETCH, MI_WASHING, MI_ADMIRAL },
+ { MI_CHEETAH, MI_INFERNUS, MI_BANSHEE, MI_PHEONIX, MI_COMET, MI_STINGER },
+ { MI_VOODOO, MI_CUBAN, MI_CADDY, MI_BAGGAGE, MI_MRWHOOP, MI_PIZZABOY }
};
+const int32 gaCarsToCollectIn60Seconds[] = { MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO }; // what is this?
+
int32 CGarages::BankVansCollected;
bool CGarages::BombsAreFree;
bool CGarages::RespraysAreFree;
@@ -126,9 +123,7 @@ uint32 CGarages::MessageEndTime;
uint32 CGarages::NumGarages;
bool CGarages::PlayerInGarage;
int32 CGarages::PoliceCarsCollected;
-CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
-CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
-CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
+CStoredCar CGarages::aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][CGarages::MAX_NUM_CARS_IN_HIDEOUT_GARAGE];
int32 CGarages::AudioEntity = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde;
@@ -147,22 +142,15 @@ void CGarages::Init(void)
for (int i = 0; i < TOTAL_COLLECTCARS_GARAGES; i++)
CarTypesCollected[i] = 0;
LastTimeHelpMessage = 0;
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse1[i].Init();
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse2[i].Init();
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse3[i].Init();
+ for (int i = 0; i < TOTAL_HIDEOUT_GARAGES; i++) {
+ for (int j = 0; j < MAX_NUM_CARS_IN_HIDEOUT_GARAGE; j++)
+ aCarsInSafeHouses[i][j].Init();
+ }
AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);
if (AudioEntity >= 0)
DMAudio.SetEntityStatus(AudioEntity, 1);
- AddOne(
- CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1,
- CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2,
- GARAGE_CRUSHER, 0);
}
-#ifndef PS2
void CGarages::Shutdown(void)
{
NumGarages = 0;
@@ -171,7 +159,6 @@ void CGarages::Shutdown(void)
DMAudio.DestroyEntity(AudioEntity);
AudioEntity = AEHANDLE_NONE;
}
-#endif
void CGarages::Update(void)
{
@@ -199,19 +186,27 @@ void CGarages::Update(void)
aGarages[GarageToBeTidied].TidyUpGarage();
}
-int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId)
+int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, eGarageType type, int32 targetId)
{
if (NumGarages >= NUM_GARAGES) {
assert(0);
return NumGarages++;
}
CGarage* pGarage = &aGarages[NumGarages];
- pGarage->m_fX1 = Min(X1, X2);
- pGarage->m_fX2 = Max(X1, X2);
- pGarage->m_fY1 = Min(Y1, Y2);
- pGarage->m_fY2 = Max(Y1, Y2);
- pGarage->m_fZ1 = Min(Z1, Z2);
- pGarage->m_fZ2 = Max(Z1, Z2);
+ pGarage->m_fInfX = Min(Min(Min(X1, X2), X3), X2 + X3 - X1);
+ pGarage->m_fSupX = Max(Max(X1, X2), X3);
+ pGarage->m_fInfY = Min(Min(Min(Y1, Y2), Y3), Y2 + Y3 - Y1);
+ pGarage->m_fSupY = Max(Max(Y1, Y2), Y3);
+ pGarage->m_vecCorner1 = CVector(X1, Y1, Z1);
+ pGarage->m_fInfZ = Z1;
+ pGarage->m_vDir1 = CVector2D(X2 - X1, Y2 - Y1);
+ pGarage->m_vDir2 = CVector2D(X3 - X1, Y3 - Y1);
+ pGarage->m_fSupZ = Z2;
+ pGarage->m_nMaxStoredCars = NUM_GARAGE_STORED_CARS;
+ pGarage->m_fDir1Len = pGarage->m_vDir1.Magnitude();
+ pGarage->m_fDir2Len = pGarage->m_vDir2.Magnitude();
+ pGarage->m_vDir1 /= pGarage->m_fDir1Len;
+ pGarage->m_vDir2 /= pGarage->m_fDir2Len;
pGarage->m_pDoor1 = nil;
pGarage->m_pDoor2 = nil;
pGarage->m_fDoor1Z = Z1;
@@ -258,6 +253,17 @@ int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z
case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:
case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
+ case GARAGE_COLLECTCARS_4:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
pGarage->m_eGarageState = GS_FULLYCLOSED;
pGarage->m_fDoorPos = 0.0f;
break;
@@ -311,10 +317,10 @@ void CGarage::Update()
TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = this;
if (pVehicle->GetModelIndex() == MI_MRWHOOP) {
if (pVehicle->IsWithinArea(
- m_fX1 - DISTANCE_FOR_MRWHOOP_HACK,
- m_fY1 + DISTANCE_FOR_MRWHOOP_HACK,
- m_fX2 - DISTANCE_FOR_MRWHOOP_HACK,
- m_fY2 + DISTANCE_FOR_MRWHOOP_HACK)) {
+ m_fInfX - DISTANCE_FOR_MRWHOOP_HACK,
+ m_fInfY - DISTANCE_FOR_MRWHOOP_HACK,
+ m_fSupX + DISTANCE_FOR_MRWHOOP_HACK,
+ m_fSupY + DISTANCE_FOR_MRWHOOP_HACK)) {
TheCamera.pToGarageWeAreIn = this;
CGarages::bCamShouldBeOutisde = true;
}
@@ -332,7 +338,7 @@ void CGarage::Update()
case GARAGE_RESPRAY:
switch (m_eGarageState) {
case GS_OPENED:
- if (IsStaticPlayerCarEntirelyInside() && !IsAnyOtherCarTouchingGarage(FindPlayerVehicle())) {
+ if (IsStaticPlayerCarEntirelyInside()) {
if (CGarages::IsCarSprayable(FindPlayerVehicle())) {
if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= RESPRAY_PRICE || CGarages::RespraysAreFree) {
m_eGarageState = GS_CLOSING;
@@ -354,13 +360,15 @@ void CGarage::Update()
if (FindPlayerVehicle()) {
if (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
}
break;
case GS_CLOSING:
+ if (FindPlayerVehicle())
+ ThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -376,19 +384,20 @@ void CGarage::Update()
#endif
((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
break;
case GS_FULLYCLOSED:
if (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {
m_eGarageState = GS_OPENING;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_OPENING, 1);
bool bTakeMoney = false;
- if (FindPlayerPed()->m_pWanted->m_nWantedLevel != 0)
+ if (FindPlayerPed()->m_pWanted->m_nWantedLevel != 0) {
bTakeMoney = true;
- FindPlayerPed()->m_pWanted->Reset();
+ FindPlayerPed()->m_pWanted->Suspend();
+ }
CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
#ifdef FIX_BUGS
@@ -396,18 +405,29 @@ void CGarage::Update()
#else
bool bChangedColour;
#endif
- if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) {
+ if (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {
if (FindPlayerVehicle()->m_fHealth < FREE_RESPRAY_HEALTH_THRESHOLD)
bTakeMoney = true;
FindPlayerVehicle()->m_fHealth = 1000.0f;
- ((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
- ((CAutomobile*)(FindPlayerVehicle()))->Fix();
+ if (FindPlayerVehicle()->IsCar()) {
+ ((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
+ ((CAutomobile*)(FindPlayerVehicle()))->Fix();
+ }
+ else {
+ // TODO(MIAMI): Bike Fix
+ }
+ FindPlayerVehicle()->m_nDoorLock = CARLOCK_UNLOCKED;
+ ++CStats::Sprayings;
if (FindPlayerVehicle()->GetUp().z < 0.0f) {
FindPlayerVehicle()->GetUp() = -FindPlayerVehicle()->GetUp();
FindPlayerVehicle()->GetRight() = -FindPlayerVehicle()->GetRight();
}
bChangedColour = false;
+#ifdef FIX_BUGS
+ if (!FindPlayerVehicle()->IsCar() || !((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
+#else
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
+#endif
uint8 colour1, colour2;
uint16 attempt;
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
@@ -422,16 +442,9 @@ void CGarage::Update()
if (bChangedColour) {
for (int i = 0; i < NUM_PARTICLES_IN_RESPRAY; i++) {
CVector pos;
-#ifdef FIX_BUGS
- pos.x = CGeneral::GetRandomNumberInRange(m_fX1 + 0.5f, m_fX2 - 0.5f);
- pos.y = CGeneral::GetRandomNumberInRange(m_fY1 + 0.5f, m_fY2 - 0.5f);
+ pos.x = CGeneral::GetRandomNumberInRange(m_fInfX + 0.5f, m_fSupX - 0.5f);
+ pos.y = CGeneral::GetRandomNumberInRange(m_fInfY + 0.5f, m_fSupY - 0.5f);
pos.z = CGeneral::GetRandomNumberInRange(m_fDoor1Z - 3.0f, m_fDoor1Z + 1.0f);
-#else
- // wtf is this
- pos.x = m_fX1 + 0.5f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * (m_fX2 - m_fX1 - 1.0f);
- pos.y = m_fY1 + 0.5f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * (m_fY2 - m_fY1 - 1.0f);
- pos.z = m_fDoor1Z - 3.0f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * 4.0f;
-#endif
CParticle::AddParticle(PARTICLE_GARAGEPAINT_SPRAY, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, CVehicleModelInfo::ms_vehicleColourTable[colour1]);
}
}
@@ -439,8 +452,10 @@ void CGarage::Update()
CenterCarInGarage(FindPlayerVehicle());
}
if (bTakeMoney) {
- if (!CGarages::RespraysAreFree)
+ if (!CGarages::RespraysAreFree) {
CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - RESPRAY_PRICE);
+ CStats::AutoPaintingBudget += RESPRAY_PRICE;
+ }
CGarages::TriggerMessage("GA_2", -1, 4000, -1); // New engine and paint job. The cops won't recognize you!
}
else if (bChangedColour) {
@@ -452,10 +467,10 @@ void CGarage::Update()
m_bResprayHappened = true;
}
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
break;
case GS_OPENING:
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
@@ -480,12 +495,8 @@ void CGarage::Update()
case GARAGE_BOMBSHOP3:
switch (m_eGarageState) {
case GS_OPENED:
- if (IsStaticPlayerCarEntirelyInside() && !IsAnyOtherCarTouchingGarage(FindPlayerVehicle())) {
-#ifdef FIX_BUGS // FindPlayerVehicle() can never be NULL here because IsStaticPlayerCarEntirelyInside() is true, and there is no IsCar() check
- if (FindPlayerVehicle()->IsCar() && ((CAutomobile*)FindPlayerVehicle())->m_bombType) {
-#else
- if (!FindPlayerVehicle() || ((CAutomobile*)FindPlayerVehicle())->m_bombType) {
-#endif
+ if (IsStaticPlayerCarEntirelyInside()) {
+ if (!FindPlayerVehicle() || FindPlayerVehicle()->m_bombType) {
CGarages::TriggerMessage("GA_5", -1, 4000, -1); //"Your car is already fitted with a bomb"
m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB_ALREADY_SET, 1);
@@ -503,6 +514,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (FindPlayerVehicle())
+ ThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -510,62 +523,69 @@ void CGarage::Update()
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
UpdateDoorsHeight();
+ if (m_eGarageType == GARAGE_BOMBSHOP3)
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
break;
case GS_FULLYCLOSED:
if (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {
- switch (m_eGarageType) {
- case GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;
- case GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;
- case GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;
+ if (m_eGarageType != GARAGE_BOMBSHOP3 || CStreaming::HasModelLoaded(MI_BOMB)) {
+ switch (m_eGarageType) {
+ case GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;
+ case GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;
+ case GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;
default: break;
- }
- m_eGarageState = GS_OPENING;
- if (!CGarages::BombsAreFree)
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);
- if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) {
- ((CAutomobile*)(FindPlayerVehicle()))->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
- ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
- if (m_eGarageType == GARAGE_BOMBSHOP3)
- CGarages::GivePlayerDetonator();
- CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
- }
+ }
+ m_eGarageState = GS_OPENING;
+ if (!CGarages::BombsAreFree)
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);
+ if (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {
+ FindPlayerVehicle()->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
+ FindPlayerVehicle()->m_pBombRigger = FindPlayerPed();
+ if (m_eGarageType == GARAGE_BOMBSHOP3)
+ CGarages::GivePlayerDetonator();
+ CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
+ }
#ifdef DETECT_PAD_INPUT_SWITCH
- int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
+ int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
#else
- int16 Mode = CPad::GetPad(0)->Mode;
+ int16 Mode = CPad::GetPad(0)->Mode;
#endif
- switch (m_eGarageType) {
- case GARAGE_BOMBSHOP1:
- switch (Mode) {
- case 0:
- case 1:
- case 2:
- CHud::SetHelpMessage(TheText.Get("GA_6"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
- break;
- case 3:
- CHud::SetHelpMessage(TheText.Get("GA_6B"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ switch (m_eGarageType) {
+ case GARAGE_BOMBSHOP1:
+ switch (Mode) {
+ case 0:
+ case 1:
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("GA_6"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("GA_6B"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ break;
+ }
break;
- }
- break;
- case GARAGE_BOMBSHOP2:
- switch (Mode) {
- case 0:
- case 1:
- case 2:
- CHud::SetHelpMessage(TheText.Get("GA_7"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ case GARAGE_BOMBSHOP2:
+ switch (Mode) {
+ case 0:
+ case 1:
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("GA_7"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("GA_7B"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ break;
+ }
break;
- case 3:
- CHud::SetHelpMessage(TheText.Get("GA_7B"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ case GARAGE_BOMBSHOP3:
+ CHud::SetHelpMessage(TheText.Get("GA_8"), false); // Use the detonator to activate the bomb.
break;
- }
- break;
- case GARAGE_BOMBSHOP3:
- CHud::SetHelpMessage(TheText.Get("GA_8"), false); // Use the detonator to activate the bomb.
- break;
default: break;
+ }
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
+ FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
+ }
+ else {
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
}
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
}
break;
case GS_OPENING:
@@ -604,6 +624,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
@@ -648,92 +670,10 @@ void CGarage::Update()
}
break;
case GARAGE_COLLECTSPECIFICCARS:
- switch (m_eGarageState) {
- case GS_OPENED:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- m_pTarget = FindPlayerVehicle();
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- if (!FindPlayerVehicle()) {
- if (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyOtherCarTouchingGarage(m_pTarget)) {
- if (IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) {
- CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
- m_eGarageState = GS_CLOSING;
- }
- }
- else if (Abs(FindPlayerCoors().x - GetGarageCenterX()) > DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE ||
- Abs(FindPlayerCoors().y - GetGarageCenterY()) > DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE) {
- m_eGarageState = GS_CLOSING;
- m_pTarget = nil;
- }
- }
- break;
- case GS_CLOSING:
- m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
- if (m_fDoorPos == 0.0f) {
- m_eGarageState = GS_FULLYCLOSED;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
- if (m_pTarget) {
- DestroyVehicleAndDriverAndPassengers(m_pTarget);
- m_pTarget = nil;
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
- int16 reward;
- switch (m_nTargetModelIndex) {
- case MI_POLICE:
- reward = REWARD_FOR_FIRST_POLICE_CAR * (MAX_POLICE_CARS_TO_COLLECT - CGarages::PoliceCarsCollected++) / MAX_POLICE_CARS_TO_COLLECT;
- break;
- case MI_SECURICA:
- reward = REWARD_FOR_FIRST_BANK_VAN * (MAX_BANK_VANS_TO_COLLECT - CGarages::BankVansCollected++) / MAX_BANK_VANS_TO_COLLECT;
- break;
-#ifdef FIX_BUGS // not possible though
- default:
- reward = 0;
- break;
-#endif
- }
- if (reward > 0) {
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward;
- CGarages::TriggerMessage("GA_10", reward, 4000, -1); // Nice one. Here's your $~1~
- DMAudio.PlayFrontEndSound(SOUND_GARAGE_VEHICLE_ACCEPTED, 1);
- }
- else {
- CGarages::TriggerMessage("GA_11", -1, 4000, -1); // We got these wheels already. It's worthless to us!
- DMAudio.PlayFrontEndSound(SOUND_GARAGE_VEHICLE_DECLINED, 1);
- }
- }
- }
- UpdateDoorsHeight();
- break;
- case GS_FULLYCLOSED:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- if (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))
- m_eGarageState = GS_OPENING;
- }
- break;
- case GS_OPENING:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- m_pTarget = FindPlayerVehicle();
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
- if (m_fDoorPos == m_fDoorHeight) {
- m_eGarageState = GS_OPENED;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
- }
- UpdateDoorsHeight();
- break;
- //case GS_OPENEDCONTAINSCAR:
- //case GS_CLOSEDCONTAINSCAR:
- //case GS_AFTERDROPOFF:
- default:
- break;
- }
- break;
case GARAGE_COLLECTCARS_1:
case GARAGE_COLLECTCARS_2:
case GARAGE_COLLECTCARS_3:
+ case GARAGE_COLLECTCARS_4:
switch (m_eGarageState) {
case GS_OPENED:
if (FindPlayerVehicle() && DoesCraigNeedThisCar(FindPlayerVehicle()->GetModelIndex())) {
@@ -766,6 +706,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -853,75 +795,6 @@ void CGarage::Update()
}
break;
case GARAGE_CRUSHER:
- switch (m_eGarageState) {
- case GS_OPENED:
- {
- int i = CPools::GetVehiclePool()->GetSize() * (CTimer::GetFrameCounter() % CRUSHER_VEHICLE_TEST_SPAN) / CRUSHER_VEHICLE_TEST_SPAN;
- int end = CPools::GetVehiclePool()->GetSize() * (CTimer::GetFrameCounter() % CRUSHER_VEHICLE_TEST_SPAN + 1) / CRUSHER_VEHICLE_TEST_SPAN;
- for (; i < end; i++) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- if (pVehicle->IsCar() && IsEntityEntirelyInside3D(pVehicle, 0.0f)) {
- m_eGarageState = GS_CLOSING;
- m_pTarget = pVehicle;
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- }
- break;
- }
- case GS_CLOSING:
- if (m_pTarget) {
- m_fDoorPos = Max(0.0f, m_fDoorPos - CRUSHER_CRANE_SPEED * CTimer::GetTimeStep());
- if (m_fDoorPos < TWOPI / 5) {
- m_pTarget->bUsesCollision = false;
- m_pTarget->bAffectedByGravity = false;
- m_pTarget->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- }
- else {
- m_pTarget->SetMoveSpeed(m_pTarget->GetMoveSpeed() * Pow(0.8f, CTimer::GetTimeStep()));
- }
- if (m_fDoorPos == 0.0f) {
- CGarages::CrushedCarId = CPools::GetVehiclePool()->GetIndex(m_pTarget);
- float reward = Min(CRUSHER_MAX_REWARD, CRUSHER_MIN_REWARD + m_pTarget->pHandling->nMonetaryValue * m_pTarget->m_fHealth * CRUSHER_REWARD_COEFFICIENT);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward;
- DestroyVehicleAndDriverAndPassengers(m_pTarget);
- ++CStats::CarsCrushed;
- m_pTarget = nil;
- m_eGarageState = GS_AFTERDROPOFF;
- m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_CRUSH_CAR;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
- }
- }
- else
- m_eGarageState = GS_OPENING;
- UpdateCrusherAngle();
- break;
- case GS_AFTERDROPOFF:
- if (CTimer::GetTimeInMilliseconds() <= m_nTimeToStartAction) {
- UpdateCrusherShake((myrand() & 0xFF - 128) * 0.0002f, (myrand() & 0xFF - 128) * 0.0002f);
- }
- else {
- UpdateCrusherShake(0.0f, 0.0f);
- m_eGarageState = GS_OPENING;
- }
- break;
- case GS_OPENING:
- m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED);
- if (m_fDoorPos == HALFPI) {
- m_eGarageState = GS_OPENED;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
- }
- UpdateCrusherAngle();
- break;
- //case GS_FULLYCLOSED:
- //case GS_CLOSEDCONTAINSCAR:
- //case GS_OPENEDCONTAINSCAR:
- default:
- break;
- }
- if (!FindPlayerVehicle() && (CTimer::GetFrameCounter() & 0x1F) == 0x17 && IsEntityEntirelyInside(FindPlayerPed()))
- FindPlayerPed()->InflictDamage(nil, WEAPONTYPE_RAMMEDBYCAR, 300.0f, PEDPIECE_TORSO, 0);
break;
case GARAGE_MISSION_KEEPCAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
@@ -940,6 +813,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
@@ -1035,6 +910,15 @@ void CGarage::Update()
case GARAGE_HIDEOUT_ONE:
case GARAGE_HIDEOUT_TWO:
case GARAGE_HIDEOUT_THREE:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
switch (m_eGarageState) {
case GS_OPENED:
{
@@ -1047,7 +931,7 @@ void CGarage::Update()
m_eGarageState = GS_CLOSING;
else if (FindPlayerVehicle() &&
CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >=
- CGarages::FindMaxNumStoredCarsForGarage(m_eGarageType)) {
+ FindMaxNumStoredCarsForGarage()) {
m_eGarageState = GS_CLOSING;
}
else if (distance > SQR(DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE)) {
@@ -1063,12 +947,7 @@ void CGarage::Update()
else if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
m_eGarageState = GS_FULLYCLOSED;
- switch (m_eGarageType) {
- case GARAGE_HIDEOUT_ONE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse1, MAX_STORED_CARS_IN_INDUSTRIAL); break;
- case GARAGE_HIDEOUT_TWO: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse2, MAX_STORED_CARS_IN_COMMERCIAL); break;
- case GARAGE_HIDEOUT_THREE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse3, MAX_STORED_CARS_IN_SUBURBAN); break;
- default: break;
- }
+ StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)], NUM_GARAGE_STORED_CARS);
}
UpdateDoorsHeight();
break;
@@ -1077,30 +956,19 @@ void CGarage::Update()
float distance = CalcDistToGarageRectangleSquared(FindPlayerCoors().x, FindPlayerCoors().y);
if (distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT) ||
distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR) && FindPlayerVehicle()) {
- if (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= CGarages::FindMaxNumStoredCarsForGarage(m_eGarageType)) {
+ if (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= FindMaxNumStoredCarsForGarage()) {
if (m_pDoor1) {
if (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) &&
CTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) {
- CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
- CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
+ if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE) {
+ CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
+ CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
+ }
}
}
}
- else {
-#ifdef FIX_BUGS
- bool bCreatedAllCars = false;
-#else
- bool bCreatedAllCars;
-#endif
- switch (m_eGarageType) {
- case GARAGE_HIDEOUT_ONE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse1); break;
- case GARAGE_HIDEOUT_TWO: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse2); break;
- case GARAGE_HIDEOUT_THREE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse3); break;
- default: break;
- }
- if (bCreatedAllCars)
- m_eGarageState = GS_OPENING;
- }
+ else if (RestoreCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)]))
+ m_eGarageState = GS_OPENING;
}
break;
}
@@ -1130,6 +998,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -1162,11 +1032,64 @@ void CGarage::Update()
break;
//case GARAGE_COLLECTORSITEMS:
//case GARAGE_60SECONDS:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ switch (m_eGarageState) {
+ case GS_OPENED:
+ if (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyCarBlockingDoor() && IsPlayerOutsideGarage()) {
+ CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
+ m_eGarageState = GS_CLOSING;
+ m_bClosingWithoutTargetCar = false;
+ }
+ case GS_CLOSING:
+ m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
+ if (m_fDoorPos == 0.0f) {
+ m_eGarageState = GS_FULLYCLOSED;
+ DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
+ }
+ case GS_FULLYCLOSED:
+ break;
+ case GS_OPENING:
+ m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
+ if (m_fDoorPos == m_fDoorHeight) {
+ m_eGarageState = GS_OPENED;
+ DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
+ }
+ UpdateDoorsHeight();
+ break;
+ //case GS_OPENEDCONTAINSCAR:
+ //case GS_CLOSEDCONTAINSCAR:
+ //case GS_AFTERDROPOFF:
+ default:
+ break;
+ }
default:
break;
}
}
+void CGarage::ThrowCarsNearDoorOutOfGarage(CVehicle* pException)
+{
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle || pVehicle == pException)
+ continue;
+ if (!IsEntityTouching3D(pVehicle))
+ continue;
+ CColModel* pColModel = pVehicle->GetColModel();
+ for (int i = 0; i < pColModel->numSpheres; i++) {
+ CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
+ float radius = pColModel->spheres[i].radius;
+ if (!IsPointInsideGarage(pos, 0.0f)) {
+ CVector vecDirectionAway(pVehicle->GetPosition().x - GetGarageCenterX(), pVehicle->GetPosition().y - GetGarageCenterY(), 0.0f);
+ vecDirectionAway.Normalise();
+ pVehicle->AddToMoveSpeed(vecDirectionAway * CTimer::GetTimeStepInSeconds());
+ }
+ }
+ }
+}
+
bool CGarage::IsStaticPlayerCarEntirelyInside()
{
if (!FindPlayerVehicle())
@@ -1178,8 +1101,8 @@ bool CGarage::IsStaticPlayerCarEntirelyInside()
if (FindPlayerPed()->m_objective == OBJECTIVE_LEAVE_VEHICLE)
return false;
CVehicle* pVehicle = FindPlayerVehicle();
- if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 ||
- pVehicle->GetPosition().y < m_fY1 || pVehicle->GetPosition().y > m_fY2)
+ if (pVehicle->GetPosition().x < m_fInfX || pVehicle->GetPosition().x > m_fSupX ||
+ pVehicle->GetPosition().y < m_fInfY || pVehicle->GetPosition().y > m_fSupY)
return false;
if (Abs(pVehicle->GetSpeed().x) > 0.01f ||
Abs(pVehicle->GetSpeed().y) > 0.01f ||
@@ -1190,35 +1113,58 @@ bool CGarage::IsStaticPlayerCarEntirelyInside()
return IsEntityEntirelyInside3D(pVehicle, 0.0f);
}
-bool CGarage::IsEntityEntirelyInside(CEntity * pEntity)
+bool CGarage::IsPointInsideGarage(CVector pos)
{
- if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
- pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
+ // is it IsPointInsideGarage(pos, 0.0f)?
+ if (pos.z < m_fInfZ)
+ return false;
+ if (pos.z > m_fSupZ)
+ return false;
+ CVector2D vecToTarget((CVector2D)pos - m_vecCorner1);
+ float dp = DotProduct2D(m_vDir1, vecToTarget);
+ if (dp < 0.0f)
+ return false;
+ if (m_fDir1Len < dp)
+ return false;
+ dp = DotProduct2D(m_vDir2, vecToTarget);
+ if (dp < 0.0f)
+ return false;
+ if (m_fDir2Len < dp)
+ return false;
+ return true;
+}
+
+bool CGarage::IsPointInsideGarage(CVector pos, float m_fMargin)
+{
+ if (pos.z < m_fInfZ - m_fMargin)
+ return false;
+ if (pos.z > m_fSupZ + m_fMargin)
+ return false;
+ CVector2D vecToTarget((CVector2D)pos - m_vecCorner1);
+ float dp = DotProduct2D(m_vDir1, vecToTarget);
+ if (dp < -m_fMargin)
+ return false;
+ if (m_fDir1Len + m_fMargin < dp)
+ return false;
+ dp = DotProduct2D(m_vDir2, vecToTarget);
+ if (dp < -m_fMargin)
+ return false;
+ if (m_fDir2Len + m_fMargin < dp)
return false;
- CColModel* pColModel = pEntity->GetColModel();
- for (int i = 0; i < pColModel->numSpheres; i++) {
- CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
- float radius = pColModel->spheres[i].radius;
- if (pos.x - radius < m_fX1 || pos.x + radius > m_fX2 ||
- pos.y - radius < m_fY1 || pos.y + radius > m_fY2)
- return false;
- }
return true;
}
bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
{
- if (pEntity->GetPosition().x < m_fX1 - fMargin || pEntity->GetPosition().x > m_fX2 + fMargin ||
- pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
- pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
+ if (pEntity->GetPosition().x < m_fInfX - fMargin || pEntity->GetPosition().x > m_fSupX + fMargin ||
+ pEntity->GetPosition().y < m_fInfY - fMargin || pEntity->GetPosition().y > m_fSupY + fMargin ||
+ pEntity->GetPosition().z < m_fInfZ - fMargin || pEntity->GetPosition().z > m_fSupZ + fMargin)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 - fMargin || pos.x - radius > m_fX2 + fMargin ||
- pos.y + radius < m_fY1 - fMargin || pos.y - radius > m_fY2 + fMargin ||
- pos.z + radius < m_fZ1 - fMargin || pos.z - radius > m_fZ2 + fMargin)
+ if (!IsPointInsideGarage(pos, fMargin - radius))
return false;
}
return true;
@@ -1226,15 +1172,14 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
{
- if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
- pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
+ if (pEntity->GetPosition().x > m_fInfX - fMargin && pEntity->GetPosition().x < m_fSupX + fMargin &&
+ pEntity->GetPosition().y > m_fInfY - fMargin && pEntity->GetPosition().y < m_fSupY + fMargin)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 - fMargin && pos.x - radius < m_fX2 + fMargin &&
- pos.y + radius > m_fY1 - fMargin && pos.y - radius < m_fY2 + fMargin)
+ if (IsPointInsideGarage(pos, fMargin + radius))
return false;
}
return true;
@@ -1243,8 +1188,15 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
bool CGarage::IsGarageEmpty()
{
int16 num;
- CWorld::FindObjectsIntersectingCube(CVector(m_fX1, m_fY1, m_fZ1), CVector(m_fX2, m_fY2, m_fZ2), &num, 2, nil, false, true, true, false, false);
- return num == 0;
+ CEntity* pEntities[16];
+ CWorld::FindObjectsIntersectingCube(CVector(m_fInfX, m_fInfY, m_fInfZ), CVector(m_fSupX, m_fSupY, m_fSupZ), &num, 16, pEntities, false, true, true, false, false);
+ if (num <= 0)
+ return true;
+ for (int i = 0; i < 16; i++) {
+ if (IsEntityTouching3D(pEntities[i]))
+ return false;
+ }
+ return true;
}
bool CGarage::IsPlayerOutsideGarage()
@@ -1257,20 +1209,18 @@ bool CGarage::IsPlayerOutsideGarage()
bool CGarage::IsEntityTouching3D(CEntity * pEntity)
{
float radius = pEntity->GetBoundRadius();
- if (pEntity->GetPosition().x - radius < m_fX1 || pEntity->GetPosition().x + radius > m_fX2 ||
- pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 ||
- pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2)
+ if (pEntity->GetPosition().x - radius < m_fInfX || pEntity->GetPosition().x + radius > m_fSupX ||
+ pEntity->GetPosition().y - radius < m_fInfY || pEntity->GetPosition().y + radius > m_fSupY ||
+ pEntity->GetPosition().z - radius < m_fInfZ || pEntity->GetPosition().z + radius > m_fSupZ)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
- return false;
+ if (IsPointInsideGarage(pos, radius))
+ return true;
}
- return true;
+ return false;
}
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
@@ -1279,9 +1229,7 @@ bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius + fMargin < m_fX1 || pos.x - radius - fMargin > m_fX2 ||
- pos.y + radius + fMargin < m_fY1 || pos.y - radius - fMargin > m_fY2 ||
- pos.z + radius + fMargin < m_fZ1 || pos.z - radius - fMargin > m_fZ2)
+ if (!IsPointInsideGarage(pos, fMargin + radius))
return true;
}
return false;
@@ -1300,9 +1248,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1322,9 +1268,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1344,9 +1288,7 @@ bool CGarage::IsAnyCarBlockingDoor()
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 || pos.x - radius > m_fX2 ||
- pos.y + radius < m_fY1 || pos.y - radius > m_fY2 ||
- pos.z + radius < m_fZ1 || pos.z - radius > m_fZ2)
+ if (!IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1361,9 +1303,7 @@ int32 CGarage::CountCarsWithCenterPointWithinGarage(CEntity * pException)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle || pVehicle == pException)
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2)
+ if (IsPointInsideGarage(pVehicle->GetPosition()))
total++;
}
return total;
@@ -1378,9 +1318,7 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
continue;
if (!IsEntityTouching3D(pVehicle))
continue;
- if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 ||
- pVehicle->GetPosition().y < m_fY1 || pVehicle->GetPosition().y > m_fY2 ||
- pVehicle->GetPosition().z < m_fZ1 || pVehicle->GetPosition().z > m_fZ2) {
+ if (!IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
CWorld::Remove(pVehicle);
delete pVehicle;
@@ -1399,7 +1337,7 @@ void CGarages::PrintMessages()
CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f));
CFont::SetCentreOn();
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
+ CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // TODO(MIAMI): redo it
CFont::SetColor(CRGBA(0, 0, 0, 255));
#if defined(PS2) || defined (FIX_BUGS)
@@ -1412,7 +1350,7 @@ void CGarages::PrintMessages()
if (MessageNumberInString < 0) {
CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
- CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
}
else {
@@ -1420,7 +1358,7 @@ void CGarages::PrintMessages()
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
- CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
@@ -1428,7 +1366,7 @@ void CGarages::PrintMessages()
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
- CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
@@ -1458,15 +1396,27 @@ void CGarage::UpdateDoorsHeight()
RefreshDoorPointers(false);
if (m_pDoor1) {
m_pDoor1->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor1Z;
- if (m_bRotatedDoor)
+ if (m_bRotatedDoor) {
+ CVector pos;
+ pos.x = m_fDoor1X + m_fDoorPos * m_pDoor1->GetForward().y * 5.0f / 6.0f;
+ pos.y = m_fDoor1Y - m_fDoorPos * m_pDoor1->GetForward().x * 5.0f / 6.0f;
+ pos.z = m_pDoor1->GetPosition().z;
+ m_pDoor1->SetPosition(pos);
BuildRotatedDoorMatrix(m_pDoor1, m_fDoorPos / m_fDoorHeight);
+ }
m_pDoor1->GetMatrix().UpdateRW();
m_pDoor1->UpdateRwFrame();
}
if (m_pDoor2) {
m_pDoor2->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor2Z;
- if (m_bRotatedDoor)
+ if (m_bRotatedDoor) {
+ CVector pos;
+ pos.x = m_fDoor2X + m_fDoorPos * m_pDoor2->GetForward().y * 5.0f / 6.0f;
+ pos.y = m_fDoor2Y - m_fDoorPos * m_pDoor2->GetForward().x * 5.0f / 6.0f;
+ pos.z = m_pDoor2->GetPosition().z;
+ m_pDoor2->SetPosition(pos);
BuildRotatedDoorMatrix(m_pDoor2, m_fDoorPos / m_fDoorHeight);
+ }
m_pDoor2->GetMatrix().UpdateRW();
m_pDoor2->UpdateRwFrame();
}
@@ -1568,6 +1518,7 @@ void CGarages::SetTargetCarForMissonGarage(int16 garage, CVehicle * pVehicle)
assert(garage >= 0 && garage < NUM_GARAGES);
if (pVehicle) {
aGarages[garage].m_pTarget = pVehicle;
+ aGarages[garage].m_pTarget->RegisterReference((CEntity**)&aGarages[garage].m_pTarget);
if (aGarages[garage].m_eGarageState == GS_CLOSEDCONTAINSCAR)
aGarages[garage].m_eGarageState = GS_FULLYCLOSED;
}
@@ -1619,11 +1570,9 @@ bool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id)
bool CGarage::DoesCraigNeedThisCar(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
for (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][i])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))
return (CGarages::CarTypesCollected[ct] & BIT(i)) == 0;
}
return false;
@@ -1631,11 +1580,9 @@ bool CGarage::DoesCraigNeedThisCar(int32 mi)
bool CGarage::HasCraigCollectedThisCar(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
for (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][i])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))
return CGarages::CarTypesCollected[ct] & BIT(i);
}
return false;
@@ -1643,12 +1590,10 @@ bool CGarage::HasCraigCollectedThisCar(int32 mi)
bool CGarage::MarkThisCarAsCollectedForCraig(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
int index;
for (index = 0; index < TOTAL_COLLECTCARS_CARS; index++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][index])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][index] || (gaCarsToCollectInCraigsGarages[ct][index] == MI_CHEETAH && mi == MI_VICECHEE))
break;
}
if (index >= TOTAL_COLLECTCARS_CARS)
@@ -1681,16 +1626,16 @@ void CGarage::CloseThisGarage()
float CGarage::CalcDistToGarageRectangleSquared(float X, float Y)
{
float distX, distY;
- if (X < m_fX1)
- distX = m_fX1 - X;
- else if (X > m_fX2)
- distX = X - m_fX2;
+ if (X < m_fInfX)
+ distX = m_fInfX - X;
+ else if (X > m_fSupX)
+ distX = X - m_fSupX;
else
distX = 0.0f;
- if (Y < m_fY1)
- distY = m_fY1 - Y;
- else if (Y > m_fY2)
- distY = Y - m_fY2;
+ if (Y < m_fInfY)
+ distY = m_fInfY - Y;
+ else if (Y > m_fSupY)
+ distY = Y - m_fSupY;
else
distY = 0.0f;
return SQR(distX) + SQR(distY);
@@ -1711,10 +1656,10 @@ void CGarage::FindDoorsEntities()
{
m_pDoor1 = nil;
m_pDoor2 = nil;
- int xstart = Max(0, CWorld::GetSectorIndexX(m_fX1));
- int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
- int ystart = Max(0, CWorld::GetSectorIndexY(m_fY1));
- int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fY2));
+ int xstart = Max(0, CWorld::GetSectorIndexX(m_fInfX));
+ int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fSupX));
+ int ystart = Max(0, CWorld::GetSectorIndexY(m_fInfY));
+ int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fSupY));
assert(xstart <= xend);
assert(ystart <= yend);
@@ -1729,20 +1674,22 @@ void CGarage::FindDoorsEntities()
FindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_DUMMIES_OVERLAP], true);
}
}
- if (!m_pDoor1 || !m_pDoor2)
- return;
- if (m_pDoor1->GetModelIndex() == MI_CRUSHERBODY || m_pDoor1->GetModelIndex() == MI_CRUSHERLID)
- return;
- CVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());
- CVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());
- if (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {
- if (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {
- m_pDoor1 = m_pDoor2;
- m_bDoor1IsDummy = m_bDoor2IsDummy;
+ if (m_pDoor1 && m_pDoor2) {
+ CVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());
+ CVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());
+ if (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {
+ if (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {
+ m_pDoor1 = m_pDoor2;
+ m_bDoor1IsDummy = m_bDoor2IsDummy;
+ }
+ m_pDoor2 = nil;
+ m_bDoor2IsDummy = false;
}
- m_pDoor2 = nil;
- m_bDoor2IsDummy = false;
}
+ if (m_pDoor1)
+ m_pDoor1->bUsesCollision = true;
+ if (m_pDoor2)
+ m_pDoor2->bUsesCollision = true;
}
void CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)
@@ -1755,29 +1702,8 @@ void CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)
pEntity->m_scanCode = CWorld::GetCurrentScanCode();
if (!pEntity || !CGarages::IsModelIndexADoor(pEntity->GetModelIndex()))
continue;
- if (Abs(pEntity->GetPosition().x - GetGarageCenterX()) >= DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE)
- continue;
- if (Abs(pEntity->GetPosition().y - GetGarageCenterY()) >= DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE)
- continue;
- if (pEntity->GetModelIndex() == MI_CRUSHERBODY) {
- m_pDoor1 = pEntity;
- m_bDoor1IsDummy = dummy;
- // very odd pool operations, they could have used GetJustIndex
- if (dummy)
- m_bDoor1PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;
- else
- m_bDoor1PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;
- continue;
- }
- if (pEntity->GetModelIndex() == MI_CRUSHERLID) {
- m_pDoor2 = pEntity;
- m_bDoor2IsDummy = dummy;
- if (dummy)
- m_bDoor2PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;
- else
- m_bDoor2PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;
+ if (!IsPointInsideGarage(pEntity->GetPosition(), 2.0f))
continue;
- }
if (!m_pDoor1) {
m_pDoor1 = pEntity;
m_bDoor1IsDummy = dummy;
@@ -1812,6 +1738,8 @@ void CGarages::SetGarageDoorToRotate(int16 garage)
aGarages[garage].m_bRotatedDoor = true;
aGarages[garage].m_fDoorHeight /= 2.0f;
aGarages[garage].m_fDoorHeight -= 0.1f;
+ aGarages[garage].m_fDoorPos = Min(aGarages[garage].m_fDoorHeight, aGarages[garage].m_fDoorPos);
+ aGarages[garage].UpdateDoorsHeight();
}
void CGarages::SetLeaveCameraForThisGarage(int16 garage)
@@ -1854,15 +1782,12 @@ CVehicle* CStoredCar::RestoreCar()
if (!CStreaming::HasModelLoaded(m_nModelIndex))
return nil;
CVehicleModelInfo::SetComponentsToUse(m_nVariationA, m_nVariationB);
-#ifdef FIX_BUGS
CVehicle* pVehicle;
if (CModelInfo::IsBoatModel(m_nModelIndex))
pVehicle = new CBoat(m_nModelIndex, RANDOM_VEHICLE);
+ // else if bike - TODO(MIAMI)
else
pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);
-#else
- CVehicle* pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);
-#endif
pVehicle->SetPosition(m_vecPos);
pVehicle->SetStatus(STATUS_ABANDONED);
pVehicle->GetForward() = m_vecAngle;
@@ -1896,9 +1821,7 @@ void CGarage::StoreAndRemoveCarsForThisHideout(CStoredCar* aCars, int32 nMax)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) {
+ if (IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) {
if (index < Max(NUM_GARAGE_STORED_CARS, nMax) && !EntityHasASphereWayOutsideGarage(pVehicle, 1.0f))
aCars[index++].StoreCar(pVehicle);
@@ -1940,17 +1863,12 @@ bool CGarages::IsPointInAGarageCameraZone(CVector point)
case GARAGE_COLLECTCARS_1:
case GARAGE_COLLECTCARS_2:
case GARAGE_COLLECTCARS_3:
- if (aGarages[i].m_fX1 - MARGIN_FOR_CAMERA_COLLECTCARS <= point.x &&
- aGarages[i].m_fX2 + MARGIN_FOR_CAMERA_COLLECTCARS >= point.x &&
- aGarages[i].m_fY1 - MARGIN_FOR_CAMERA_COLLECTCARS <= point.y &&
- aGarages[i].m_fY2 + MARGIN_FOR_CAMERA_COLLECTCARS >= point.y)
+ case GARAGE_COLLECTCARS_4:
+ if (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_COLLECTCARS))
return true;
break;
default:
- if (aGarages[i].m_fX1 - MARGIN_FOR_CAMERA_DEFAULT <= point.x &&
- aGarages[i].m_fX2 + MARGIN_FOR_CAMERA_DEFAULT >= point.x &&
- aGarages[i].m_fY1 - MARGIN_FOR_CAMERA_DEFAULT <= point.y &&
- aGarages[i].m_fY2 + MARGIN_FOR_CAMERA_DEFAULT >= point.y)
+ if (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_DEFAULT))
return true;
break;
}
@@ -1981,9 +1899,7 @@ void CGarage::TidyUpGarage()
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle || !pVehicle->IsCar())
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) {
+ if (IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) {
CWorld::Remove(pVehicle);
delete pVehicle;
@@ -2007,11 +1923,8 @@ void CGarage::TidyUpGarageClose()
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 || pos.x - radius > m_fX2 ||
- pos.y + radius < m_fY1 || pos.y - radius > m_fY2 ||
- pos.z + radius < m_fZ1 || pos.z - radius > m_fZ2) {
+ if (!IsPointInsideGarage(pos, radius))
bRemove = true;
- }
}
}
else
@@ -2054,6 +1967,17 @@ void CGarage::PlayerArrestedOrDied()
case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:
case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
+ case GARAGE_COLLECTCARS_4:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
switch (m_eGarageState) {
case GS_OPENED:
case GS_CLOSING:
@@ -2105,36 +2029,19 @@ void CGarage::CenterCarInGarage(CVehicle* pVehicle)
pVehicle->GetMatrix().GetPosition().x += offsetX * RESPRAY_CENTERING_COEFFICIENT / distance;
pVehicle->GetMatrix().GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance;
}
- if (!IsEntityEntirelyInside3D(pVehicle, 0.1f))
+ if (!IsEntityEntirelyInside3D(pVehicle, 0.3f))
pVehicle->SetPosition(pos);
}
void CGarages::CloseHideOutGaragesBeforeSave()
{
for (int i = 0; i < NUM_GARAGES; i++) {
- if (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_TWO &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
+ if (!IsThisGarageTypeSafehouse(aGarages[i].m_eGarageType))
continue;
- if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
- (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
+ if (aGarages[i].m_eGarageState != GS_FULLYCLOSED) {
aGarages[i].m_eGarageState = GS_FULLYCLOSED;
- switch (aGarages[i].m_eGarageType) {
- case GARAGE_HIDEOUT_ONE:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse1, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- case GARAGE_HIDEOUT_TWO:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse2, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- case GARAGE_HIDEOUT_THREE:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse3, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- default:
- break;
- }
+ aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouses[FindSafeHouseIndexForGarageType(aGarages[i].m_eGarageType)], NUM_GARAGE_STORED_CARS);
+ aGarages[i].RemoveCarsBlockingDoorNotInside();
}
aGarages[i].m_fDoorPos = 0.0f;
aGarages[i].UpdateDoorsHeight();
@@ -2145,36 +2052,11 @@ int32 CGarages::CountCarsInHideoutGarage(eGarageType type)
{
int32 total = 0;
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- switch (type) {
- case GARAGE_HIDEOUT_ONE:
- total += (aCarsInSafeHouse1[i].HasCar());
- break;
- case GARAGE_HIDEOUT_TWO:
- total += (aCarsInSafeHouse2[i].HasCar());
- break;
- case GARAGE_HIDEOUT_THREE:
- total += (aCarsInSafeHouse3[i].HasCar());
- break;
- default: break;
- }
+ total += aCarsInSafeHouses[FindSafeHouseIndexForGarageType(type)][i].HasCar();
}
return total;
}
-int32 CGarages::FindMaxNumStoredCarsForGarage(eGarageType type)
-{
- switch (type) {
- case GARAGE_HIDEOUT_ONE:
- return LIMIT_CARS_IN_INDUSTRIAL;
- case GARAGE_HIDEOUT_TWO:
- return LIMIT_CARS_IN_COMMERCIAL;
- case GARAGE_HIDEOUT_THREE:
- return LIMIT_CARS_IN_SUBURBAN;
- default: break;
- }
- return 0;
-}
-
bool CGarages::IsPointWithinHideOutGarage(Const CVector& point)
{
for (int i = 0; i < NUM_GARAGES; i++) {
@@ -2182,9 +2064,7 @@ bool CGarages::IsPointWithinHideOutGarage(Const CVector& point)
case GARAGE_HIDEOUT_ONE:
case GARAGE_HIDEOUT_TWO:
case GARAGE_HIDEOUT_THREE:
- if (point.x > aGarages[i].m_fX1 && point.x < aGarages[i].m_fX2 &&
- point.y > aGarages[i].m_fY1 && point.y < aGarages[i].m_fY2 &&
- point.z > aGarages[i].m_fZ1 && point.z < aGarages[i].m_fZ2)
+ if (aGarages[i].IsPointInsideGarage(point))
return true;
default: break;
}
@@ -2199,9 +2079,7 @@ bool CGarages::IsPointWithinAnyGarage(Const CVector& point)
case GARAGE_NONE:
continue;
default:
- if (point.x > aGarages[i].m_fX1 && point.x < aGarages[i].m_fX2 &&
- point.y > aGarages[i].m_fY1 && point.y < aGarages[i].m_fY2 &&
- point.z > aGarages[i].m_fZ1 && point.z < aGarages[i].m_fZ2)
+ if (aGarages[i].IsPointInsideGarage(point))
return true;
}
}
@@ -2238,6 +2116,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
}
}
+// TODO(MIAMI)
void CGarages::Save(uint8 * buf, uint32 * size)
{
#ifdef FIX_GARAGE_SIZE
@@ -2257,9 +2136,9 @@ void CGarages::Save(uint8 * buf, uint32 * size)
WriteSaveBuf(buf, CarTypesCollected[i]);
WriteSaveBuf(buf, LastTimeHelpMessage);
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- WriteSaveBuf(buf, aCarsInSafeHouse1[i]);
- WriteSaveBuf(buf, aCarsInSafeHouse2[i]);
- WriteSaveBuf(buf, aCarsInSafeHouse3[i]);
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {
+ WriteSaveBuf(buf, aCarsInSafeHouses[j][i]);
+ }
}
for (int i = 0; i < NUM_GARAGES; i++)
WriteSaveBuf(buf, aGarages[i]);
@@ -2287,6 +2166,7 @@ const CStoredCar &CStoredCar::operator=(const CStoredCar & other)
return *this;
}
+//TODO(MIAMI)
void CGarages::Load(uint8* buf, uint32 size)
{
#ifdef FIX_GARAGE_SIZE
@@ -2306,9 +2186,9 @@ void CGarages::Load(uint8* buf, uint32 size)
CarTypesCollected[i] = ReadSaveBuf<uint32>(buf);
LastTimeHelpMessage = ReadSaveBuf<uint32>(buf);
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- aCarsInSafeHouse1[i] = ReadSaveBuf<CStoredCar>(buf);
- aCarsInSafeHouse2[i] = ReadSaveBuf<CStoredCar>(buf);
- aCarsInSafeHouse3[i] = ReadSaveBuf<CStoredCar>(buf);
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {
+ aCarsInSafeHouses[j][i] = ReadSaveBuf<CStoredCar>(buf);
+ }
}
for (int i = 0; i < NUM_GARAGES; i++) {
aGarages[i] = ReadSaveBuf<CGarage>(buf);
@@ -2335,8 +2215,7 @@ void CGarages::Load(uint8* buf, uint32 size)
bool
CGarages::IsModelIndexADoor(uint32 id)
{
- return id == MI_GARAGEDOOR1 ||
- id == MI_GARAGEDOOR2 ||
+ return id == MI_GARAGEDOOR2 ||
id == MI_GARAGEDOOR3 ||
id == MI_GARAGEDOOR4 ||
id == MI_GARAGEDOOR5 ||
@@ -2350,7 +2229,6 @@ CGarages::IsModelIndexADoor(uint32 id)
id == MI_GARAGEDOOR14 ||
id == MI_GARAGEDOOR15 ||
id == MI_GARAGEDOOR16 ||
- id == MI_GARAGEDOOR17 ||
id == MI_GARAGEDOOR18 ||
id == MI_GARAGEDOOR19 ||
id == MI_GARAGEDOOR20 ||
@@ -2359,13 +2237,5 @@ CGarages::IsModelIndexADoor(uint32 id)
id == MI_GARAGEDOOR23 ||
id == MI_GARAGEDOOR24 ||
id == MI_GARAGEDOOR25 ||
- id == MI_GARAGEDOOR26 ||
- id == MI_GARAGEDOOR27 ||
- id == MI_GARAGEDOOR28 ||
- id == MI_GARAGEDOOR29 ||
- id == MI_GARAGEDOOR30 ||
- id == MI_GARAGEDOOR31 ||
- id == MI_GARAGEDOOR32 ||
- id == MI_CRUSHERBODY ||
- id == MI_CRUSHERLID;
+ id == MI_GARAGEDOOR26;
}
diff --git a/src/control/Garages.h b/src/control/Garages.h
index 00020eb3..c5bede2b 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -42,12 +42,24 @@ enum eGarageType : int8
GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE,
GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR,
GARAGE_MISSION_KEEPCAR_REMAINCLOSED,
+ GARAGE_COLLECTCARS_4,
+ GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR,
+ GARAGE_HIDEOUT_FOUR,
+ GARAGE_HIDEOUT_FIVE,
+ GARAGE_HIDEOUT_SIX,
+ GARAGE_HIDEOUT_SEVEN,
+ GARAGE_HIDEOUT_EIGHT,
+ GARAGE_HIDEOUT_NINE,
+ GARAGE_HIDEOUT_TEN,
+ GARAGE_HIDEOUT_ELEVEN,
+ GARAGE_HIDEOUT_TWELVE
};
enum
{
- TOTAL_COLLECTCARS_GARAGES = GARAGE_COLLECTCARS_3 - GARAGE_COLLECTCARS_1 + 1,
- TOTAL_COLLECTCARS_CARS = 16
+ TOTAL_COLLECTCARS_GARAGES = 4,
+ TOTAL_HIDEOUT_GARAGES = 12,
+ TOTAL_COLLECTCARS_CARS = 6
};
class CStoredCar
@@ -83,6 +95,7 @@ class CGarage
{
eGarageType m_eGarageType;
eGarageState m_eGarageState;
+ uint8 m_nMaxStoredCars;
bool field_2; // unused
bool m_bClosingWithoutTargetCar;
bool m_bDeactivated;
@@ -97,12 +110,17 @@ class CGarage
bool m_bRecreateDoorOnNextRefresh;
bool m_bRotatedDoor;
bool m_bCameraFollowsPlayer;
- float m_fX1;
- float m_fX2;
- float m_fY1;
- float m_fY2;
- float m_fZ1;
- float m_fZ2;
+ CVector2D m_vecCorner1;
+ float m_fInfZ;
+ CVector2D m_vDir1;
+ CVector2D m_vDir2;
+ float m_fSupZ;
+ float m_fDir1Len;
+ float m_fDir2Len;
+ float m_fInfX;
+ float m_fSupX;
+ float m_fInfY;
+ float m_fSupY;
float m_fDoorPos;
float m_fDoorHeight;
float m_fDoor1X;
@@ -123,8 +141,8 @@ class CGarage
bool IsClosed() { return m_eGarageState == GS_FULLYCLOSED; }
bool IsUsed() { return m_eGarageType != GARAGE_NONE; }
void Update();
- float GetGarageCenterX() { return (m_fX1 + m_fX2) / 2; }
- float GetGarageCenterY() { return (m_fY1 + m_fY2) / 2; }
+ float GetGarageCenterX() { return (m_fInfX + m_fSupX) / 2; }
+ float GetGarageCenterY() { return (m_fInfY + m_fSupY) / 2; }
bool IsFar()
{
#ifdef FIX_BUGS
@@ -142,7 +160,6 @@ class CGarage
void UpdateDoorsHeight();
bool IsEntityEntirelyInside3D(CEntity*, float);
bool IsEntityEntirelyOutside(CEntity*, float);
- bool IsEntityEntirelyInside(CEntity*);
float CalcDistToGarageRectangleSquared(float, float);
float CalcSmallestDistToGarageDoorSquared(float, float);
bool IsAnyOtherCarTouchingGarage(CVehicle* pException);
@@ -167,17 +184,22 @@ class CGarage
void FindDoorsEntitiesSectorList(CPtrList&, bool);
void PlayerArrestedOrDied();
+ bool IsPointInsideGarage(CVector);
+ bool IsPointInsideGarage(CVector, float);
+ void ThrowCarsNearDoorOutOfGarage(CVehicle*);
+
+ int32 FindMaxNumStoredCarsForGarage() { return Max(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }
+
friend class CGarages;
friend class cAudioManager;
friend class CCamera;
};
-VALIDATE_SIZE(CGarage, 140);
-
class CGarages
{
enum {
- MESSAGE_LENGTH = 8
+ MESSAGE_LENGTH = 8,
+ MAX_NUM_CARS_IN_HIDEOUT_GARAGE = 4
};
static int32 BankVansCollected;
static bool BombsAreFree;
@@ -195,9 +217,7 @@ class CGarages
static bool PlayerInGarage;
static int32 PoliceCarsCollected;
static CGarage aGarages[NUM_GARAGES];
- static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
- static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
- static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
+ static CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][MAX_NUM_CARS_IN_HIDEOUT_GARAGE];
static int32 AudioEntity;
static bool bCamShouldBeOutisde;
@@ -208,7 +228,7 @@ public:
#endif
static void Update(void);
- static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId);
+ static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, eGarageType type, int32 targetId);
static void ChangeGarageType(int16, eGarageType, int32);
static void PrintMessages(void);
static void TriggerMessage(const char* text, int16, uint16 time, int16);
@@ -240,15 +260,45 @@ public:
static bool IsModelIndexADoor(uint32 id);
static void SetFreeBombs(bool bValue) { BombsAreFree = bValue; }
static void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }
+ static void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }
private:
static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void);
static int32 CountCarsInHideoutGarage(eGarageType);
- static int32 FindMaxNumStoredCarsForGarage(eGarageType);
static int32 GetBombTypeForGarageType(eGarageType type) { return type - GARAGE_BOMBSHOP1 + 1; }
- static int32 GetCarsCollectedIndexForGarageType(eGarageType type) { return type - GARAGE_COLLECTCARS_1; }
+ static int32 GetCarsCollectedIndexForGarageType(eGarageType type)
+ {
+ switch (type) {
+ case GARAGE_COLLECTCARS_1: return 0;
+ case GARAGE_COLLECTCARS_2: return 1;
+ case GARAGE_COLLECTCARS_3: return 2;
+ case GARAGE_COLLECTCARS_4: return 3;
+ default: assert(0);
+ }
+ return 0;
+ }
+ static int32 FindSafeHouseIndexForGarageType(eGarageType type)
+ {
+ switch (type) {
+ case GARAGE_HIDEOUT_ONE: return 0;
+ case GARAGE_HIDEOUT_TWO: return 1;
+ case GARAGE_HIDEOUT_THREE: return 2;
+ case GARAGE_HIDEOUT_FOUR: return 3;
+ case GARAGE_HIDEOUT_FIVE: return 4;
+ case GARAGE_HIDEOUT_SIX: return 5;
+ case GARAGE_HIDEOUT_SEVEN: return 6;
+ case GARAGE_HIDEOUT_EIGHT: return 7;
+ case GARAGE_HIDEOUT_NINE: return 8;
+ case GARAGE_HIDEOUT_TEN: return 9;
+ case GARAGE_HIDEOUT_ELEVEN: return 10;
+ case GARAGE_HIDEOUT_TWELVE: return 11;
+ default: assert(0);
+ }
+ return -1;
+ }
+ static bool IsThisGarageTypeSafehouse(eGarageType type) { return FindSafeHouseIndexForGarageType(type) >= 0; }
friend class cAudioManager;
friend class CGarage;
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index ee15b82f..4a948032 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -18,21 +18,21 @@ CPathFind ThePaths;
#define MIN_PED_ROUTE_DISTANCE 23.8f
-#define NUMTEMPNODES 4000
-#define NUMDETACHED_CARS 100
-#define NUMDETACHED_PEDS 50
+#define NUMTEMPNODES 5000
+#define NUMDETACHED_CARS 1024
+#define NUMDETACHED_PEDS 1214
+#define NUMTEMPEXTERNALNODES 4600
-// object flags:
-// 1 UseInRoadBlock
-// 2 east/west road(?)
-
CPathInfoForObject *InfoForTileCars;
CPathInfoForObject *InfoForTilePeds;
-// unused
-CTempDetachedNode *DetachedNodesCars;
-CTempDetachedNode *DetachedNodesPeds;
+CPathInfoForObject *DetachedInfoForTileCars;
+CPathInfoForObject *DetachedInfoForTilePeds;
+CTempNodeExternal *TempExternalNodes;
+int32 NumTempExternalNodes;
+int32 NumDetachedPedNodeGroups;
+int32 NumDetachedCarNodeGroups;
bool
CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints)
@@ -197,7 +197,7 @@ CPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CV
void
CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition)
{
- const CColBox& boundingBox = pEntity->GetColModel()->boundingBox;
+ const CBox& boundingBox = pEntity->GetColModel()->boundingBox;
const float fBoundMaxY = boundingBox.max.y + 0.3f;
const float fBoundMinY = boundingBox.min.y - 0.3f;
const float fBoundMaxX = boundingBox.max.x + 0.3f;
@@ -227,6 +227,27 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p
}
}
+//--MIAMI: done
+// Make sure all externals link TO an internal
+void
+CPathInfoForObject::SwapConnectionsToBeRightWayRound(void)
+{
+ int e, i;
+ CPathInfoForObject *tile = this;
+
+ for(e = 0; e < 12; e++)
+ if(tile[e].type == NodeTypeExtern && tile[e].next < 0)
+ for(i = 0; i < 12; i++)
+ if(tile[i].type == NodeTypeIntern && tile[i].next == e){
+ tile[e].next = i;
+ tile[i].next = -1;
+ bool tmp = !!tile[e].crossing;
+ tile[e].crossing = tile[i].crossing;
+ tile[i].crossing = tmp;
+ }
+}
+
+//--MIAMI: done
void
CPathFind::Init(void)
{
@@ -237,11 +258,13 @@ CPathFind::Init(void)
m_numConnections = 0;
m_numCarPathLinks = 0;
unk = 0;
+ NumTempExternalNodes = 0;
for(i = 0; i < NUM_PATHNODES; i++)
m_pathNodes[i].distance = MAX_DIST;
}
+//--MIAMI: done
void
CPathFind::AllocatePathFindInfoMem(int16 numPathGroups)
{
@@ -250,93 +273,172 @@ CPathFind::AllocatePathFindInfoMem(int16 numPathGroups)
delete[] InfoForTilePeds;
InfoForTilePeds = nil;
- // NB: MIAMI doesn't use numPathGroups here but hardcodes 4500
- InfoForTileCars = new CPathInfoForObject[12*numPathGroups];
- memset(InfoForTileCars, 0, 12*numPathGroups*sizeof(CPathInfoForObject));
- InfoForTilePeds = new CPathInfoForObject[12*numPathGroups];
- memset(InfoForTilePeds, 0, 12*numPathGroups*sizeof(CPathInfoForObject));
-
- // unused
- delete[] DetachedNodesCars;
- DetachedNodesCars = nil;
- delete[] DetachedNodesPeds;
- DetachedNodesPeds = nil;
- DetachedNodesCars = new CTempDetachedNode[NUMDETACHED_CARS];
- memset(DetachedNodesCars, 0, NUMDETACHED_CARS*sizeof(CTempDetachedNode));
- DetachedNodesPeds = new CTempDetachedNode[NUMDETACHED_PEDS];
- memset(DetachedNodesPeds, 0, NUMDETACHED_PEDS*sizeof(CTempDetachedNode));
+ // NB: MIAMI doesn't use numPathGroups here but hardcodes PATHNODESIZE
+ InfoForTileCars = new CPathInfoForObject[12*PATHNODESIZE];
+ memset(InfoForTileCars, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));
+ InfoForTilePeds = new CPathInfoForObject[12*PATHNODESIZE];
+ memset(InfoForTilePeds, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));
+
+ delete[] DetachedInfoForTileCars;
+ DetachedInfoForTileCars = nil;
+ delete[] DetachedInfoForTilePeds;
+ DetachedInfoForTilePeds = nil;
+ DetachedInfoForTileCars = new CPathInfoForObject[12*NUMDETACHED_CARS];
+ memset(DetachedInfoForTileCars, 0, 12*NUMDETACHED_CARS*sizeof(CPathInfoForObject));
+ DetachedInfoForTilePeds = new CPathInfoForObject[12*NUMDETACHED_PEDS];
+ memset(DetachedInfoForTilePeds, 0, 12*NUMDETACHED_PEDS*sizeof(CPathInfoForObject));
+
+ TempExternalNodes = new CTempNodeExternal[NUMTEMPEXTERNALNODES];
+ memset(TempExternalNodes, 0, NUMTEMPEXTERNALNODES*sizeof(CTempNodeExternal));
+ NumTempExternalNodes = 0;
+ NumDetachedPedNodeGroups = 0;
+ NumDetachedCarNodeGroups = 0;
}
+//--MIAMI: done
void
CPathFind::RegisterMapObject(CTreadable *mapObject)
{
m_mapObjects[m_numMapObjects++] = mapObject;
}
+//--MIAMI: done
void
-CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing)
+CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate)
{
- int i, j;
+ int i;
i = id*12 + node;
InfoForTilePeds[i].type = type;
InfoForTilePeds[i].next = next;
- InfoForTilePeds[i].x = x;
- InfoForTilePeds[i].y = y;
- InfoForTilePeds[i].z = z;
+ InfoForTilePeds[i].x = x/16.0f;
+ InfoForTilePeds[i].y = y/16.0f;
+ InfoForTilePeds[i].z = z/16.0f;
+ InfoForTilePeds[i].width = 8.0f*Min(width, 15.0f);
InfoForTilePeds[i].numLeftLanes = 0;
InfoForTilePeds[i].numRightLanes = 0;
InfoForTilePeds[i].crossing = crossing;
-
- if(type)
- for(i = 0; i < node; i++){
- j = id*12 + i;
- if(x == InfoForTilePeds[j].x && y == InfoForTilePeds[j].y){
- printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n");
- printf("Several ped nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n",
- x, InfoForTilePeds[j].x, y, InfoForTilePeds[j].y);
- printf("Modelindex of cullprit: %d\n\n", id);
- }
- }
+ InfoForTilePeds[i].speedLimit = 0;
+ InfoForTilePeds[i].roadBlock = false;
+ InfoForTilePeds[i].disabled = false;
+ InfoForTilePeds[i].waterPath = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
+ InfoForTilePeds[i].betweenLevels = false;
+ InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11)
+ InfoForTilePeds[id*12].SwapConnectionsToBeRightWayRound();
}
+//--MIAMI: done
void
-CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight)
+CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate)
{
- int i, j;
+ int i;
i = id*12 + node;
InfoForTileCars[i].type = type;
InfoForTileCars[i].next = next;
- InfoForTileCars[i].x = x;
- InfoForTileCars[i].y = y;
- InfoForTileCars[i].z = z;
+ InfoForTileCars[i].x = x/16.0f;
+ InfoForTileCars[i].y = y/16.0f;
+ InfoForTileCars[i].z = z/16.0f;
+ InfoForTilePeds[i].width = 8.0f*Min(width, 15.0f);
InfoForTileCars[i].numLeftLanes = numLeft;
InfoForTileCars[i].numRightLanes = numRight;
+ InfoForTilePeds[i].crossing = false;
+ InfoForTilePeds[i].speedLimit = 0;
+ InfoForTilePeds[i].roadBlock = false;
+ InfoForTilePeds[i].disabled = false;
+ InfoForTilePeds[i].waterPath = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
+ InfoForTilePeds[i].betweenLevels = false;
+ InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11)
+ InfoForTileCars[id*12].SwapConnectionsToBeRightWayRound();
+}
+
+//--MIAMI: done
+void
+CPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
+ bool disabled, bool betweenLevels, uint8 spawnRate)
+{
+ int i;
+ if(NumDetachedPedNodeGroups >= NUMDETACHED_PEDS)
+ return;
- if(type)
- for(i = 0; i < node; i++){
- j = id*12 + i;
- if(x == InfoForTileCars[j].x && y == InfoForTileCars[j].y){
- printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n");
- printf("Several car nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n",
- x, InfoForTileCars[j].x, y, InfoForTileCars[j].y);
- printf("Modelindex of cullprit: %d\n\n", id);
- }
- }
+ i = NumDetachedPedNodeGroups*12 + node;
+ DetachedInfoForTilePeds[i].type = type;
+ DetachedInfoForTilePeds[i].next = next;
+ DetachedInfoForTilePeds[i].x = x/16.0f;
+ DetachedInfoForTilePeds[i].y = y/16.0f;
+ DetachedInfoForTilePeds[i].z = z/16.0f;
+ DetachedInfoForTilePeds[i].width = 8.0f*Min(width, 31.0f);
+ DetachedInfoForTilePeds[i].numLeftLanes = 0;
+ DetachedInfoForTilePeds[i].numRightLanes = 0;
+ DetachedInfoForTilePeds[i].crossing = crossing;
+ DetachedInfoForTilePeds[i].speedLimit = 0;
+ DetachedInfoForTilePeds[i].roadBlock = false;
+ DetachedInfoForTilePeds[i].disabled = disabled;
+ DetachedInfoForTilePeds[i].waterPath = false;
+ DetachedInfoForTilePeds[i].onlySmallBoats = false;
+ DetachedInfoForTilePeds[i].betweenLevels = betweenLevels;
+ DetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11){
+ DetachedInfoForTilePeds[NumDetachedPedNodeGroups*12].SwapConnectionsToBeRightWayRound();
+ NumDetachedPedNodeGroups++;
+ }
}
+//--MIAMI: done
void
-CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out)
+CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool onlySmallBoats)
+{
+ int i;
+
+ if(NumDetachedCarNodeGroups >= NUMDETACHED_CARS)
+ return;
+
+ i = NumDetachedCarNodeGroups*12 + node;
+ DetachedInfoForTileCars[i].type = type;
+ DetachedInfoForTileCars[i].next = next;
+ DetachedInfoForTileCars[i].x = x/16.0f;
+ DetachedInfoForTileCars[i].y = y/16.0f;
+ DetachedInfoForTileCars[i].z = z/16.0f;
+ DetachedInfoForTileCars[i].width = 8.0f*Min(width, 15.0f);
+ DetachedInfoForTileCars[i].numLeftLanes = numLeft;
+ DetachedInfoForTileCars[i].numRightLanes = numRight;
+ DetachedInfoForTileCars[i].crossing = false;
+ DetachedInfoForTileCars[i].speedLimit = speedLimit;
+ DetachedInfoForTileCars[i].roadBlock = roadBlock;
+ DetachedInfoForTileCars[i].disabled = disabled;
+ DetachedInfoForTileCars[i].waterPath = waterPath;
+ DetachedInfoForTileCars[i].onlySmallBoats = onlySmallBoats;
+ DetachedInfoForTileCars[i].betweenLevels = betweenLevels;
+ DetachedInfoForTileCars[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11){
+ DetachedInfoForTileCars[NumDetachedCarNodeGroups*12].SwapConnectionsToBeRightWayRound();
+ NumDetachedCarNodeGroups++;
+ }
+}
+
+//--MIAMI: done
+void
+CPathFind::CalcNodeCoors(float x, float y, float z, int id, CVector *out)
{
CVector pos;
- pos.x = x / 16.0f;
- pos.y = y / 16.0f;
- pos.z = z / 16.0f;
+ pos.x = x;
+ pos.y = y;
+ pos.z = z;
*out = m_mapObjects[id]->GetMatrix() * pos;
}
+//--MIAMI: done
bool
CPathFind::LoadPathFindData(void)
{
@@ -344,26 +446,22 @@ CPathFind::LoadPathFindData(void)
return false;
}
+//--MIAMI: done
void
CPathFind::PreparePathData(void)
{
- int i, j, k;
- int numExtern, numIntern, numLanes;
- float maxX, maxY;
+ int i, j;
+ int numExtern, numIntern;
CTempNode *tempNodes;
printf("PreparePathData\n");
if(!CPathFind::LoadPathFindData() && // empty
InfoForTileCars && InfoForTilePeds &&
- DetachedNodesCars && DetachedNodesPeds
- ){
+ DetachedInfoForTileCars && DetachedInfoForTilePeds && TempExternalNodes){
tempNodes = new CTempNode[NUMTEMPNODES];
m_numConnections = 0;
- for(i = 0; i < PATHNODESIZE; i++)
- m_pathNodes[i].unkBits = 0;
-
for(i = 0; i < PATHNODESIZE; i++){
numExtern = 0;
numIntern = 0;
@@ -377,6 +475,19 @@ CPathFind::PreparePathData(void)
printf("ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\n", i);
}
+ int numExternDetached, numInternDetached;
+ for(i = 0; i < NUMDETACHED_CARS; i++){
+ numExternDetached = 0;
+ numInternDetached = 0;
+ for(j = 0; j < 12; j++){
+ if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern)
+ numExternDetached++;
+ if(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeIntern)
+ numInternDetached++;
+ }
+ // no diagnostic here
+ }
+
for(i = 0; i < PATHNODESIZE; i++)
for(j = 0; j < 12; j++)
if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){
@@ -388,52 +499,24 @@ CPathFind::PreparePathData(void)
if(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0)
printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i);
}
+ for(i = 0; i < NUMDETACHED_CARS; i++)
+ for(j = 0; j < 12; j++)
+ if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern){
+ // MI:%d here but no argument for it
+ if(DetachedInfoForTileCars[i*12 + j].numLeftLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTileCars[i*12 + j].numRightLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTileCars[i*12 + j].numLeftLanes + DetachedInfoForTileCars[i*12 + j].numRightLanes <= 0)
+ printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i);
+ }
m_numPathNodes = 0;
- PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, NUMDETACHED_CARS);
+ PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedInfoForTileCars, NumDetachedCarNodeGroups);
m_numCarPathNodes = m_numPathNodes;
- PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, NUMDETACHED_PEDS);
+ PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedInfoForTilePeds, NumDetachedPedNodeGroups);
m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes;
- // TODO: figure out what exactly is going on here
- // Some roads seem to get a west/east flag
- for(i = 0; i < m_numMapObjects; i++){
- numExtern = 0;
- numIntern = 0;
- numLanes = 0;
- maxX = 0.0f;
- maxY = 0.0f;
- for(j = 0; j < 12; j++){
- k = i*12 + j;
- if(InfoForTileCars[k].type == NodeTypeExtern){
- numExtern++;
- if(InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes > numLanes)
- numLanes = InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes;
- maxX = Max(maxX, Abs(InfoForTileCars[k].x));
- maxY = Max(maxY, Abs(InfoForTileCars[k].y));
- }else if(InfoForTileCars[k].type == NodeTypeIntern)
- numIntern++;
- }
-
- if(numIntern == 1 && numExtern == 2){
- if(numLanes < 4){
- if((i & 7) == 4){ // WHAT?
- m_objectFlags[i] |= UseInRoadBlock;
- if(maxX > maxY)
- m_objectFlags[i] |= ObjectEastWest;
- else
- m_objectFlags[i] &= ~ObjectEastWest;
- }
- }else{
- m_objectFlags[i] |= UseInRoadBlock;
- if(maxX > maxY)
- m_objectFlags[i] |= ObjectEastWest;
- else
- m_objectFlags[i] &= ~ObjectEastWest;
- }
- }
- }
-
delete[] tempNodes;
CountFloodFillGroups(PATH_CAR);
@@ -444,14 +527,17 @@ CPathFind::PreparePathData(void)
delete[] InfoForTilePeds;
InfoForTilePeds = nil;
- delete[] DetachedNodesCars;
- DetachedNodesCars = nil;
- delete[] DetachedNodesPeds;
- DetachedNodesPeds = nil;
+ delete[] DetachedInfoForTileCars;
+ DetachedInfoForTileCars = nil;
+ delete[] DetachedInfoForTilePeds;
+ DetachedInfoForTilePeds = nil;
+ delete[] TempExternalNodes;
+ TempExternalNodes = nil;
}
printf("Done with PreparePathData\n");
}
+//--MIAMI: done
/* String together connected nodes in a list by a flood fill algorithm */
void
CPathFind::CountFloodFillGroups(uint8 type)
@@ -494,8 +580,8 @@ CPathFind::CountFloodFillGroups(uint8 type)
if(node->numLinks == 0){
if(type == PATH_CAR)
- printf("Single car node: %f %f %f (%d)\n",
- node->GetX(), node->GetY(), node->GetZ(), m_mapObjects[node->objectIndex]->GetModelIndex());
+ printf("Single car node: %f %f %f\n",
+ node->GetX(), node->GetY(), node->GetZ());
else
printf("Single ped node: %f %f %f\n",
node->GetX(), node->GetY(), node->GetZ());
@@ -523,34 +609,31 @@ CPathFind::CountFloodFillGroups(uint8 type)
int32 TempListLength;
+//--MIAMI: done
void
CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
- float maxdist, CTempDetachedNode *detachednodes, int numDetached)
+ float maxdist, CPathInfoForObject *detachednodes, int numDetached)
{
static CVector CoorsXFormed;
- int i, j, k, l;
+ int i, j, k;
int l1, l2;
int start;
float posx, posy;
float dx, dy, mag;
float nearestDist;
int nearestId;
- int next;
int oldNumPathNodes, oldNumLinks;
float dist;
int iseg, jseg;
- int istart, jstart;
int done, cont;
int tileStart;
oldNumPathNodes = m_numPathNodes;
oldNumLinks = m_numConnections;
-#define OBJECTINDEX(n) (m_pathNodes[(n)].objectIndex)
- // Initialize map objects
- for(i = 0; i < m_numMapObjects; i++)
- for(j = 0; j < 12; j++)
- m_mapObjects[i]->m_nodeIndices[type][j] = -1;
+#define OBJECTINDEX(n) (mapObjIndices[(n)])
+ int16 *mapObjIndices = new int16[NUM_PATHNODES];
+ NumTempExternalNodes = 0;
// Calculate internal nodes, store them and connect them to defining object
for(i = 0; i < m_numMapObjects; i++){
@@ -566,89 +649,125 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
&CoorsXFormed);
m_pathNodes[m_numPathNodes].SetPosition(CoorsXFormed);
OBJECTINDEX(m_numPathNodes) = i;
- m_pathNodes[m_numPathNodes].unkBits = 1;
- m_mapObjects[i]->m_nodeIndices[type][j] = m_numPathNodes;
+ m_pathNodes[m_numPathNodes].width = objectpathinfo[start + j].width;
+ m_pathNodes[m_numPathNodes].speedLimit = objectpathinfo[start + j].speedLimit;
+ m_pathNodes[m_numPathNodes].spawnRate = objectpathinfo[start + j].spawnRate;
+ m_pathNodes[m_numPathNodes].bUseInRoadBlock = objectpathinfo[start + j].roadBlock;
+ m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled;
+ m_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = objectpathinfo[start + j].onlySmallBoats;
+ m_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels;
m_numPathNodes++;
}
+ else if(objectpathinfo[start + j].type == NodeTypeExtern){
+ CalcNodeCoors(
+ objectpathinfo[start + j].x,
+ objectpathinfo[start + j].y,
+ objectpathinfo[start + j].z,
+ i,
+ &CoorsXFormed);
+ TempExternalNodes[NumTempExternalNodes].pos = CoorsXFormed;
+ assert(objectpathinfo[start + j].next >= 0);
+ TempExternalNodes[NumTempExternalNodes].next = tileStart + objectpathinfo[start + j].next;
+ TempExternalNodes[NumTempExternalNodes].numLeftLanes = objectpathinfo[start + j].numLeftLanes;
+ TempExternalNodes[NumTempExternalNodes].numRightLanes = objectpathinfo[start + j].numRightLanes;
+ TempExternalNodes[NumTempExternalNodes].width = objectpathinfo[start + j].width;
+ TempExternalNodes[NumTempExternalNodes].isCross = !!objectpathinfo[start + j].crossing;
+ NumTempExternalNodes++;
+ }
}
}
+ // Same thing for detached nodes
+ for(i = 0; i < numDetached; i++){
+ tileStart = m_numPathNodes;
+ start = 12*i;
+ for(j = 0; j < 12; j++){
+ if(detachednodes[start + j].type == NodeTypeIntern){
+ CVector pos;
+ pos.x = detachednodes[start + j].x;
+ pos.y = detachednodes[start + j].y;
+ pos.z = detachednodes[start + j].z;
+ m_pathNodes[m_numPathNodes].SetPosition(pos);
+ mapObjIndices[m_numPathNodes] = -(i+1);
+ m_pathNodes[m_numPathNodes].width = detachednodes[start + j].width;
+ m_pathNodes[m_numPathNodes].speedLimit = detachednodes[start + j].speedLimit;
+ m_pathNodes[m_numPathNodes].spawnRate = detachednodes[start + j].spawnRate;
+ m_pathNodes[m_numPathNodes].bUseInRoadBlock = detachednodes[start + j].roadBlock;
+ m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled;
+ m_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = detachednodes[start + j].onlySmallBoats;
+ m_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels;
+ m_numPathNodes++;
+ }else if(detachednodes[start + j].type == NodeTypeExtern){
+ TempExternalNodes[NumTempExternalNodes].pos.x = detachednodes[start + j].x;
+ TempExternalNodes[NumTempExternalNodes].pos.y = detachednodes[start + j].y;
+ TempExternalNodes[NumTempExternalNodes].pos.z = detachednodes[start + j].z;
+ assert(detachednodes[start + j].next >= 0);
+ TempExternalNodes[NumTempExternalNodes].next = tileStart + detachednodes[start + j].next;
+ TempExternalNodes[NumTempExternalNodes].numLeftLanes = detachednodes[start + j].numLeftLanes;
+ TempExternalNodes[NumTempExternalNodes].numRightLanes = detachednodes[start + j].numRightLanes;
+ TempExternalNodes[NumTempExternalNodes].width = detachednodes[start + j].width;
+ TempExternalNodes[NumTempExternalNodes].isCross = !!detachednodes[start + j].crossing;
+ NumTempExternalNodes++;
+ }
+ }
+ }
// Insert external nodes into TempList
TempListLength = 0;
- for(i = 0; i < m_numMapObjects; i++){
- start = 12 * m_mapObjects[i]->GetModelIndex();
- for(j = 0; j < 12; j++){
- if(objectpathinfo[start + j].type != NodeTypeExtern)
+ for(i = 0; i < NumTempExternalNodes; i++){
+ // find closest unconnected node
+ nearestId = -1;
+ nearestDist = maxdist;
+ for(k = 0; k < TempListLength; k++){
+ if(tempnodes[k].linkState != 1)
continue;
- CalcNodeCoors(
- objectpathinfo[start + j].x,
- objectpathinfo[start + j].y,
- objectpathinfo[start + j].z,
- i,
- &CoorsXFormed);
-
- // find closest unconnected node
- nearestId = -1;
- nearestDist = maxdist;
- for(k = 0; k < TempListLength; k++){
- if(tempnodes[k].linkState != 1)
- continue;
- dx = tempnodes[k].pos.x - CoorsXFormed.x;
- if(Abs(dx) < nearestDist){
- dy = tempnodes[k].pos.y - CoorsXFormed.y;
- if(Abs(dy) < nearestDist){
- nearestDist = Max(Abs(dx), Abs(dy));
- nearestId = k;
- }
+ dx = tempnodes[k].pos.x - TempExternalNodes[i].pos.x;
+ if(Abs(dx) < nearestDist){
+ dy = tempnodes[k].pos.y - TempExternalNodes[i].pos.y;
+ if(Abs(dy) < nearestDist){
+ nearestDist = Max(Abs(dx), Abs(dy));
+ nearestId = k;
}
}
+ }
- if(nearestId < 0){
- // None found, add this one to temp list
- tempnodes[TempListLength].pos = CoorsXFormed;
- next = objectpathinfo[start + j].next;
- if(next < 0){
- // no link from this node, find link to this node
- next = 0;
- for(k = start; j != objectpathinfo[k].next; k++)
- next++;
- }
- // link to connecting internal node
- tempnodes[TempListLength].link1 = m_mapObjects[i]->m_nodeIndices[type][next];
- if(type == PATH_CAR){
- tempnodes[TempListLength].numLeftLanes = objectpathinfo[start + j].numLeftLanes;
- tempnodes[TempListLength].numRightLanes = objectpathinfo[start + j].numRightLanes;
- }
- tempnodes[TempListLength++].linkState = 1;
- }else{
- // Found nearest, connect it to our neighbour
- next = objectpathinfo[start + j].next;
- if(next < 0){
- // no link from this node, find link to this node
- next = 0;
- for(k = start; j != objectpathinfo[k].next; k++)
- next++;
- }
- tempnodes[nearestId].link2 = m_mapObjects[i]->m_nodeIndices[type][next];
- tempnodes[nearestId].linkState = 2;
-
- // collapse this node with nearest we found
- dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();
- dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();
- tempnodes[nearestId].pos = (tempnodes[nearestId].pos + CoorsXFormed)*0.5f;
- mag = Sqrt(dx*dx + dy*dy);
- tempnodes[nearestId].dirX = dx/mag;
- tempnodes[nearestId].dirY = dy/mag;
- // do something when number of lanes doesn't agree
- if(type == PATH_CAR)
- if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&
- (objectpathinfo[start + j].numLeftLanes == 0 || objectpathinfo[start + j].numRightLanes == 0)){
- // why switch left and right here?
- tempnodes[nearestId].numLeftLanes = objectpathinfo[start + j].numRightLanes;
- tempnodes[nearestId].numRightLanes = objectpathinfo[start + j].numLeftLanes;
- }
+ if(nearestId < 0){
+ // None found, add this one to temp list
+ tempnodes[TempListLength].pos = TempExternalNodes[i].pos;
+ // link to connecting internal node
+ tempnodes[TempListLength].link1 = TempExternalNodes[i].next;
+ if(type == PATH_CAR){
+ tempnodes[TempListLength].numLeftLanes = TempExternalNodes[i].numLeftLanes;
+ tempnodes[TempListLength].numRightLanes = TempExternalNodes[i].numRightLanes;
}
+ tempnodes[TempListLength].width = TempExternalNodes[i].width;
+ tempnodes[TempListLength].isCross = TempExternalNodes[i].isCross;
+ tempnodes[TempListLength++].linkState = 1;
+ }else{
+ // Found nearest, connect it to our neighbour
+ tempnodes[nearestId].link2 = TempExternalNodes[i].next;
+ tempnodes[nearestId].linkState = 2;
+
+ // collapse this node with nearest we found
+ dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();
+ dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();
+ tempnodes[nearestId].pos = (tempnodes[nearestId].pos + TempExternalNodes[i].pos)*0.5f;
+ mag = Sqrt(dx*dx + dy*dy);
+ tempnodes[nearestId].dirX = dx/mag * 100;
+ tempnodes[nearestId].dirY = dy/mag * 100;
+ tempnodes[nearestId].width = Max(tempnodes[nearestId].width, TempExternalNodes[i].width);
+ if(TempExternalNodes[i].isCross)
+ tempnodes[nearestId].isCross = true; // TODO: is this guaranteed to be false otherwise?
+ // do something when number of lanes doesn't agree
+ if(type == PATH_CAR)
+ if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&
+ (TempExternalNodes[i].numLeftLanes == 0 || TempExternalNodes[i].numRightLanes == 0)){
+ // why switch left and right here?
+ tempnodes[nearestId].numLeftLanes = TempExternalNodes[i].numRightLanes;
+ tempnodes[nearestId].numRightLanes = TempExternalNodes[i].numLeftLanes;
+ }
}
}
@@ -673,27 +792,30 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
continue;
dist = (m_pathNodes[i].GetPosition() - m_pathNodes[ConnectedNode(m_numConnections)].GetPosition()).Magnitude();
- m_distances[m_numConnections] = dist;
- m_connectionFlags[m_numConnections].flags = 0;
+ m_distances[m_numConnections] = Min(dist, 255);
+ if(tempnodes[j].isCross)
+ m_connections[j] |= 0x8000; // crosses road flag
if(type == PATH_CAR){
// IMPROVE: use a goto here
// Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){
- if(m_carPathLinks[k].dir.x == tempnodes[j].dirX &&
- m_carPathLinks[k].dir.y == tempnodes[j].dirY &&
- m_carPathLinks[k].pos.x == tempnodes[j].pos.x &&
- m_carPathLinks[k].pos.y == tempnodes[j].pos.y){
+ if(m_carPathLinks[k].dirX == tempnodes[j].dirX &&
+ m_carPathLinks[k].dirY == tempnodes[j].dirY &&
+ m_carPathLinks[k].x == (int)(tempnodes[j].pos.x*8.0f) &&
+ m_carPathLinks[k].y == (int)(tempnodes[j].pos.y*8.0f)){
m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks;
}
}
// k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){
- m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX;
- m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY;
- m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x;
- m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y;
+ m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX;
+ m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY;
+ m_carPathLinks[m_numCarPathLinks].x = tempnodes[j].pos.x*8.0f;
+ m_carPathLinks[m_numCarPathLinks].y = tempnodes[j].pos.y*8.0f;
+ m_carPathLinks[m_numCarPathLinks].flag1 = false;
+ m_carPathLinks[m_numCarPathLinks].width = tempnodes[j].width;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;
m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;
@@ -707,6 +829,18 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_numConnections++;
}
+ CPathInfoForObject *tile;
+ if(mapObjIndices[i] < 0){
+ if(type == PATH_CAR)
+ tile = &DetachedInfoForTileCars[12 * (-1 - mapObjIndices[i])];
+ else
+ tile = &DetachedInfoForTilePeds[12 * (-1 - mapObjIndices[i])];
+ }else{
+ if(type == PATH_CAR)
+ tile = &InfoForTileCars[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];
+ else
+ tile = &InfoForTilePeds[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];
+ }
// Find i inside path segment
iseg = 0;
@@ -714,7 +848,6 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
if(OBJECTINDEX(j) == OBJECTINDEX(i))
iseg++;
- istart = 12 * m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex();
// Add links to other internal nodes
for(j = Max(oldNumPathNodes, i-12); j < Min(m_numPathNodes, i+12); j++){
if(OBJECTINDEX(i) != OBJECTINDEX(j) || i == j)
@@ -722,14 +855,13 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// N.B.: in every path segment, the externals have to be at the end
jseg = j-i + iseg;
- jstart = 12 * m_mapObjects[m_pathNodes[j].objectIndex]->GetModelIndex();
- if(objectpathinfo[istart + iseg].next == jseg ||
- objectpathinfo[jstart + jseg].next == iseg){
+ if(tile[iseg].next == jseg ||
+ tile[jseg].next == iseg){
// Found a link between i and jConnectionSetCrossesRoad
// NB this clears the flags in MIAMI
m_connections[m_numConnections] = j;
dist = (m_pathNodes[i].GetPosition() - m_pathNodes[j].GetPosition()).Magnitude();
- m_distances[m_numConnections] = dist;
+ m_distances[m_numConnections] = Min(dist, 255);
if(type == PATH_CAR){
posx = (m_pathNodes[i].GetX() + m_pathNodes[j].GetX())*0.5f;
@@ -739,6 +871,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
mag = Sqrt(dx*dx + dy*dy);
dx /= mag;
dy /= mag;
+ int width = Max(m_pathNodes[i].width, m_pathNodes[j].width);
if(i < j){
dx = -dx;
dy = -dy;
@@ -746,20 +879,22 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here
// Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){
- if(m_carPathLinks[k].dir.x == dx &&
- m_carPathLinks[k].dir.y == dy &&
- m_carPathLinks[k].pos.x == posx &&
- m_carPathLinks[k].pos.y == posy){
+ if(m_carPathLinks[k].dirX == (int)(dx*100.0f) &&
+ m_carPathLinks[k].dirY == (int)(dy*100.0f) &&
+ m_carPathLinks[k].x == (int)(posx*8.0f) &&
+ m_carPathLinks[k].y == (int)(posy*8.0f)){
m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks;
}
}
// k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){
- m_carPathLinks[m_numCarPathLinks].dir.x = dx;
- m_carPathLinks[m_numCarPathLinks].dir.y = dy;
- m_carPathLinks[m_numCarPathLinks].pos.x = posx;
- m_carPathLinks[m_numCarPathLinks].pos.y = posy;
+ m_carPathLinks[m_numCarPathLinks].dirX = dx*100.0f;
+ m_carPathLinks[m_numCarPathLinks].dirY = dy*100.0f;
+ m_carPathLinks[m_numCarPathLinks].x = posx*8.0f;
+ m_carPathLinks[m_numCarPathLinks].y = posy*8.0f;
+ m_carPathLinks[m_numCarPathLinks].flag1 = false;
+ m_carPathLinks[m_numCarPathLinks].width = width;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;
m_carPathLinks[m_numCarPathLinks].numRightLanes = -1;
@@ -769,11 +904,9 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
}
}else{
// Crosses road
- if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].crossing ||
- objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].crossing)
- m_connectionFlags[m_numConnections].bCrossesRoad = true;
- else
- m_connectionFlags[m_numConnections].bCrossesRoad = false;
+ if(tile[iseg].next == jseg && tile[iseg].crossing ||
+ tile[jseg].next == iseg && tile[jseg].crossing)
+ m_connections[m_numConnections] |= 0x8000; // crosses road flag
}
m_pathNodes[i].numLinks++;
@@ -786,7 +919,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
done = 0;
// Set number of lanes for all nodes somehow
// very strange code
- for(k = 0; !done && k < 10; k++){
+ for(k = 0; !done && k < 12; k++){
done = 1;
for(i = 0; i < m_numPathNodes; i++){
if(m_pathNodes[i].numLinks != 2)
@@ -794,33 +927,50 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
l1 = m_carPathConnections[m_pathNodes[i].firstLink];
l2 = m_carPathConnections[m_pathNodes[i].firstLink+1];
- if(m_carPathLinks[l1].numLeftLanes == -1 &&
- m_carPathLinks[l2].numLeftLanes != -1){
+ int8 l1Left = m_carPathLinks[l1].numLeftLanes;
+ int8 l1Right = m_carPathLinks[l1].numRightLanes;
+ int8 l2Left = m_carPathLinks[l2].numLeftLanes;
+ int8 l2Right = m_carPathLinks[l2].numRightLanes;
+ int8 *l1Leftp, *l1Rightp;
+ int8 *l2Leftp, *l2Rightp;
+ if(m_carPathLinks[l1].pathNodeIndex == i){
+ l1Leftp = &l1Left;
+ l1Rightp = &l1Right;
+ }else{
+ l1Leftp = &l1Right;
+ l1Rightp = &l1Left;
+ }
+ if(m_carPathLinks[l2].pathNodeIndex == i){
+ l2Leftp = &l2Left;
+ l2Rightp = &l2Right;
+ }else{
+ l2Leftp = &l2Right;
+ l2Rightp = &l2Left;
+ }
+ if(*l1Leftp == -1 && *l2Rightp != -1){
+ *l1Leftp = *l2Rightp;
done = 0;
- if(m_carPathLinks[l2].pathNodeIndex == i){
- // why switch left and right here?
- m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numRightLanes;
- m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numLeftLanes;
- }else{
- m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numLeftLanes;
- m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numRightLanes;
- }
- m_carPathLinks[l1].pathNodeIndex = i;
- }else if(m_carPathLinks[l1].numLeftLanes != -1 &&
- m_carPathLinks[l2].numLeftLanes == -1){
+ }
+ if(*l1Rightp == -1 && *l2Leftp != -1){
+ *l1Rightp = *l2Leftp;
done = 0;
- if(m_carPathLinks[l1].pathNodeIndex == i){
- // why switch left and right here?
- m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numRightLanes;
- m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numLeftLanes;
- }else{
- m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numLeftLanes;
- m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numRightLanes;
- }
- m_carPathLinks[l2].pathNodeIndex = i;
- }else if(m_carPathLinks[l1].numLeftLanes == -1 &&
- m_carPathLinks[l2].numLeftLanes == -1)
+ }
+ if(*l2Leftp == -1 && *l1Rightp != -1){
+ *l2Leftp = *l1Rightp;
+ done = 0;
+ }
+ if(*l2Rightp == -1 && *l1Leftp != -1){
+ *l2Rightp = *l1Leftp;
+ done = 0;
+ }
+ if(*l1Leftp == -1 && *l2Rightp == -1)
done = 0;
+ if(*l2Leftp == -1 && *l1Rightp == -1)
+ done = 0;
+ m_carPathLinks[l1].numLeftLanes = l1Left;
+ m_carPathLinks[l1].numRightLanes = l1Right;
+ m_carPathLinks[l2].numLeftLanes = l2Left;
+ m_carPathLinks[l2].numRightLanes = l2Right;
}
}
@@ -828,10 +978,10 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
for(i = 0; i < m_numPathNodes; i++)
for(j = 0; j < m_pathNodes[i].numLinks; j++){
k = m_carPathConnections[m_pathNodes[i].firstLink + j];
- if(m_carPathLinks[k].numLeftLanes < 0)
- m_carPathLinks[k].numLeftLanes = 1;
- if(m_carPathLinks[k].numRightLanes < 0)
- m_carPathLinks[k].numRightLanes = 1;
+ if(m_carPathLinks[k].numLeftLanes == -1)
+ m_carPathLinks[k].numLeftLanes = 0;
+ if(m_carPathLinks[k].numRightLanes == -1)
+ m_carPathLinks[k].numRightLanes = 0;
}
}
@@ -840,8 +990,6 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
do{
cont = 0;
for(i = 0; i < m_numPathNodes; i++){
- m_pathNodes[i].bDisabled = false;
- m_pathNodes[i].bBetweenLevels = false;
// See if node is a dead end, if so, we're not done yet
if(!m_pathNodes[i].bDeadEnd){
k = 0;
@@ -874,23 +1022,14 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_connections[j] = node-1;
}
- // Also in treadables
- for(j = 0; j < m_numMapObjects; j++)
- for(k = 0; k < 12; k++){
- if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] == i){
- // remove this one
- for(l = k; l < 12-1; l++)
- m_mapObjects[j]->m_nodeIndices[PATH_PED][l] = m_mapObjects[j]->m_nodeIndices[PATH_PED][l+1];
- m_mapObjects[j]->m_nodeIndices[PATH_PED][11] = -1;
- }else if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] > i)
- m_mapObjects[j]->m_nodeIndices[PATH_PED][k]--;
- }
-
i--;
m_numPathNodes--;
}
+
+ delete[] mapObjIndices;
}
+//--MIAMI: done
float
CPathFind::CalcRoadDensity(float x, float y)
{
@@ -907,21 +1046,13 @@ CPathFind::CalcRoadDensity(float x, float y)
next = m_carPathConnections[m_pathNodes[i].firstLink + j];
density += m_carPathLinks[next].numLeftLanes * dist;
density += m_carPathLinks[next].numRightLanes * dist;
-
- if(m_carPathLinks[next].numLeftLanes < 0)
- printf("Link from object %d to %d (MIs)\n",
- m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(),
- m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex());
- if(m_carPathLinks[next].numRightLanes < 0)
- printf("Link from object %d to %d (MIs)\n",
- m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(),
- m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex());
}
}
}
return density/2500.0f;
}
+//--MIAMI: done
bool
CPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2)
{
@@ -932,6 +1063,7 @@ CPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2)
return false;
}
+//--MIAMI: done
bool
CPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2)
{
@@ -942,6 +1074,7 @@ CPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2)
return false;
}
+//--MIAMI: done
void
CPathFind::AddNodeToList(CPathNode *node, int32 listId)
{
@@ -954,6 +1087,7 @@ CPathFind::AddNodeToList(CPathNode *node, int32 listId)
node->distance = listId;
}
+//--MIAMI: done
void
CPathFind::RemoveNodeFromList(CPathNode *node)
{
@@ -962,6 +1096,7 @@ CPathFind::RemoveNodeFromList(CPathNode *node)
node->GetNext()->SetPrev(node->GetPrev());
}
+//--MIAMI: done
void
CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n)
{
@@ -975,6 +1110,7 @@ CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n)
}
}
+#ifdef GTA_BRIDGE
void
CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool enable)
{
@@ -986,7 +1122,9 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena
m_carPathLinks[i].bBridgeLights = enable;
}
}
+#endif
+//--MIAMI: done
void
CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable)
{
@@ -1002,6 +1140,7 @@ CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable)
}
}
+//--MIAMI: done
void
CPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable)
{
@@ -1017,6 +1156,7 @@ CPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1
}
}
+//--MIAMI: done
void
CPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable)
{
@@ -1032,6 +1172,7 @@ CPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float y2, float z2, float length, uint8 type, uint8 mode)
{
@@ -1083,6 +1224,7 @@ CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId)
{
@@ -1098,6 +1240,7 @@ CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId)
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2)
{
@@ -1112,6 +1255,7 @@ CPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2,
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2)
{
@@ -1126,8 +1270,9 @@ CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y
}
}
+//--MIAMI: done
int32
-CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels)
+CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, bool ignoreFlagB4, bool bWaterPath)
{
int i;
int firstNode, lastNode;
@@ -1149,22 +1294,20 @@ CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bo
for(i = firstNode; i < lastNode; i++){
if(ignoreDisabled && m_pathNodes[i].bDisabled) continue;
if(ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue;
- switch(m_pathNodes[i].unkBits){
- case 1:
- case 2:
- dist = Abs(m_pathNodes[i].GetX() - coors.x) +
- Abs(m_pathNodes[i].GetY() - coors.y) +
- 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
- if(dist < closestDist){
- closestDist = dist;
- closestNode = i;
- }
- break;
+ if(ignoreFlagB4 && m_pathNodes[i].flagB4) continue;
+ if(bWaterPath != m_pathNodes[i].bWaterPath) continue;
+ dist = Abs(m_pathNodes[i].GetX() - coors.x) +
+ Abs(m_pathNodes[i].GetY() - coors.y) +
+ 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ if(dist < closestDist){
+ closestDist = dist;
+ closestNode = i;
}
}
return closestDist < distLimit ? closestNode : -1;
}
+//--MIAMI: done
int32
CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY)
{
@@ -1187,27 +1330,23 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa
}
for(i = firstNode; i < lastNode; i++){
- switch(m_pathNodes[i].unkBits){
- case 1:
- case 2:
- dX = m_pathNodes[i].GetX() - coors.x;
- dY = m_pathNodes[i].GetY() - coors.y;
- dist = Abs(dX) + Abs(dY) +
- 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ dX = m_pathNodes[i].GetX() - coors.x;
+ dY = m_pathNodes[i].GetY() - coors.y;
+ dist = Abs(dX) + Abs(dY) +
+ 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ if(dist < closestDist){
+ NormalizeXY(dX, dY);
+ dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;
if(dist < closestDist){
- NormalizeXY(dX, dY);
- dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;
- if(dist < closestDist){
- closestDist = dist;
- closestNode = i;
- }
+ closestDist = dist;
+ closestNode = i;
}
- break;
}
}
return closestNode;
}
+//--MIAMI: done
float
CPathFind::FindNodeOrientationForCarPlacement(int32 nodeId)
{
@@ -1219,6 +1358,7 @@ CPathFind::FindNodeOrientationForCarPlacement(int32 nodeId)
return RADTODEG(dir.Heading());
}
+//--MIAMI: unused (still needed for script here)
float
CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards)
{
@@ -1262,6 +1402,8 @@ CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, flo
return RADTODEG(dir.Heading());
}
+// no "New" in MIAMI
+//--MIAMI: TODO
bool
CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled)
{
@@ -1277,14 +1419,14 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY,
if(m_pathNodes[node1].bDisabled && !ignoreDisabled)
continue;
dist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y);
- if(dist1 < spawnDist + 60.0f){
- d1 = dist1 - spawnDist;
+ if(dist1 < Max(spawnDist + 70.0f, spawnDist * 1.7f)){
+ d1 = m_pathNodes[node1].bWaterPath ? (dist1 - spawnDist * 1.5f) : (dist1 - spawnDist);
for(j = 0; j < m_pathNodes[node1].numLinks; j++){
node2 = ConnectedNode(m_pathNodes[node1].firstLink + j);
if(m_pathNodes[node2].bDisabled && !ignoreDisabled)
continue;
dist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y);
- d2 = dist2 - spawnDist;
+ d2 = m_pathNodes[node2].bWaterPath ? (dist2 - spawnDist * 1.5f) : (dist2 - spawnDist);
if(d1*d2 < 0.0f){
// nodes are on different sides of spawn distance
float f2 = Abs(d1)/(Abs(d1) + Abs(d2));
@@ -1316,6 +1458,7 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY,
return false;
}
+//--MIAMI: TODO
bool
CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix)
{
@@ -1375,42 +1518,7 @@ CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDi
return false;
}
-CTreadable*
-CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type)
-{
- int i, j, k;
- int node1, node2;
- CTreadable *closestMapObj = nil;
- float closestDist = 10000.0f;
-
- for(i = 0; i < m_numMapObjects; i++){
- CTreadable *mapObj = m_mapObjects[i];
- if(mapObj->m_nodeIndices[type][0] < 0)
- continue;
- CVector vDist = mapObj->GetPosition() - coors;
- float fDist = Abs(vDist.x) + Abs(vDist.y) + Abs(vDist.z);
- if(fDist < 200.0f || fDist < closestDist)
- for(j = 0; j < 12; j++){
- node1 = mapObj->m_nodeIndices[type][j];
- if(node1 < 0)
- break;
- // FIX: game uses ThePaths here explicitly
- for(k = 0; k < m_pathNodes[node1].numLinks; k++){
- node2 = ConnectedNode(m_pathNodes[node1].firstLink + k);
- float lineDist = CCollision::DistToLine(&m_pathNodes[node1].GetPosition(), &m_pathNodes[node2].GetPosition(), &coors);
- if(lineDist < closestDist){
- closestDist = lineDist;
- if((coors - m_pathNodes[node1].GetPosition()).MagnitudeSqr() < (coors - m_pathNodes[node2].GetPosition()).MagnitudeSqr())
- closestMapObj = m_mapObjects[m_pathNodes[node1].objectIndex];
- else
- closestMapObj = m_mapObjects[m_pathNodes[node2].objectIndex];
- }
- }
- }
- }
- return closestMapObj;
-}
-
+//--MIAMI: done
void
CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode, CPathNode **nextNode, uint8 curDir, uint8 *nextDir)
{
@@ -1418,19 +1526,8 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode
CPathNode *node;
if(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->GetPosition()).MagnitudeSqr() > 7.0f){
- // need to find the node we're coming from
- node = nil;
- CTreadable *obj = FindRoadObjectClosestToCoors(coors, type);
- float nodeDist = 1000000000.0f;
- for(i = 0; i < 12; i++){
- if(obj->m_nodeIndices[type][i] < 0)
- break;
- float dist = (coors - m_pathNodes[obj->m_nodeIndices[type][i]].GetPosition()).MagnitudeSqr();
- if(dist < nodeDist){
- nodeDist = dist;
- node = &m_pathNodes[obj->m_nodeIndices[type][i]];
- }
- }
+ int32 nodeIdx = FindNodeClosestToCoors(coors, type, 999999.88f);
+ node = &m_pathNodes[nodeIdx];
}
CVector2D vCurDir(Sin(curDir*PI/4.0f), Cos(curDir * PI / 4.0f));
@@ -1486,8 +1583,9 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode
}
}
-static CPathNode *apNodesToBeCleared[4995];
+static CPathNode *apNodesToBeCleared[6525];
+//--MIAMI: done
void
CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 targetNodeId)
{
@@ -1503,42 +1601,22 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
}
// Find start
- int numPathsToTry;
- CTreadable *startObj;
- if(startNodeId < 0){
- if(vehicle == nil || (startObj = vehicle->m_treadable[type]) == nil)
- startObj = FindRoadObjectClosestToCoors(start, type);
- numPathsToTry = 0;
- for(i = 0; i < 12; i++){
- if(startObj->m_nodeIndices[type][i] < 0)
- break;
- if(m_pathNodes[startObj->m_nodeIndices[type][i]].group == m_pathNodes[targetNodeId].group)
- numPathsToTry++;
- }
- }else{
- numPathsToTry = 1;
- startObj = m_mapObjects[m_pathNodes[startNodeId].objectIndex];
- }
- if(numPathsToTry == 0) {
+ if(startNodeId < 0)
+ startNodeId = FindNodeClosestToCoors(start, type, 999999.88f);
+ if(startNodeId < 0) {
*pNumNodes = 0;
if(pDist) *pDist = 100000.0f;
return;
}
-
- if(startNodeId < 0){
- // why only check node 0?
- if(m_pathNodes[startObj->m_nodeIndices[type][0]].group !=
- m_pathNodes[targetNodeId].group) {
- *pNumNodes = 0;
- if(pDist) *pDist = 100000.0f;
- return;
- }
- }else{
- if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {
- *pNumNodes = 0;
- if(pDist) *pDist = 100000.0f;
- return;
- }
+ if(startNodeId == targetNodeId){
+ *pNumNodes = 0;
+ if(pDist) *pDist = 0.0f;
+ return;
+ }
+ if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {
+ *pNumNodes = 0;
+ if(pDist) *pDist = 100000.0f;
+ return;
}
for(i = 0; i < ARRAY_SIZE(m_searchNodes); i++)
@@ -1550,14 +1628,11 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
// Dijkstra's algorithm
// Find distances
int numPathsFound = 0;
- if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNodeId].objectIndex] == startObj)
- numPathsFound++;
- for(i = 0; numPathsFound < numPathsToTry; i = (i+1) & 0x1FF){
+ for(i = 0; numPathsFound == 0; i = (i+1) & 0x1FF){
CPathNode *node;
for(node = m_searchNodes[i].GetNext(); node; node = node->GetNext()){
- if(m_mapObjects[node->objectIndex] == startObj &&
- (startNodeId < 0 || node == &m_pathNodes[startNodeId]))
- numPathsFound++;
+ if(node == &m_pathNodes[startNodeId])
+ numPathsFound = 1;
for(j = 0; j < node->numLinks; j++){
int next = ConnectedNode(node->firstLink + j);
@@ -1577,34 +1652,12 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
// Find out whence to start tracing back
CPathNode *curNode;
- if(startNodeId < 0){
- int minDist = MAX_DIST;
- *pNumNodes = 1;
- for(i = 0; i < 12; i++){
- if(startObj->m_nodeIndices[type][i] < 0)
- break;
- int dist = (m_pathNodes[startObj->m_nodeIndices[type][i]].GetPosition() - start).Magnitude();
- if(m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist < minDist){
- minDist = m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist;
- curNode = &m_pathNodes[startObj->m_nodeIndices[type][i]];
- }
- }
- if(maxNumNodes == 0){
- *pNumNodes = 0;
- }else{
- nodes[0] = curNode;
- *pNumNodes = 1;
- }
- if(pDist)
- *pDist = minDist;
- }else
- {
- curNode = &m_pathNodes[startNodeId];
- *pNumNodes = 0;
- if(pDist)
- *pDist = m_pathNodes[startNodeId].distance;
- }
+ curNode = &m_pathNodes[startNodeId];
+ *pNumNodes = 0;
+ if(pDist)
+ *pDist = m_pathNodes[startNodeId].distance;
+ nodes[(*pNumNodes)++] = curNode;
// Trace back to target and update list of nodes
while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNodeId])
for(i = 0; i < curNode->numLinks; i++){
@@ -1618,13 +1671,13 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
for(i = 0; i < numNodesToBeCleared; i++)
apNodesToBeCleared[i]->distance = MAX_DIST;
- return;
}
static CPathNode *pNodeList[32];
static int16 DummyResult;
static int16 DummyResult2;
+//--MIAMI: done
bool
CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
{
@@ -1635,11 +1688,12 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
else
DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1);
if(type == PATH_CAR)
- return dist < 160.0f;
+ return dist < 150.0f;
else
return dist < 100.0f;
}
+//--MIAMI: done
void
CPathFind::Save(uint8 *buf, uint32 *size)
{
@@ -1661,6 +1715,7 @@ CPathFind::Save(uint8 *buf, uint32 *size)
buf[i/8 + n] &= ~(1 << i%8);
}
+//--MIAMI: done
void
CPathFind::Load(uint8 *buf, uint32 size)
{
@@ -1805,3 +1860,23 @@ CPathFind::DisplayPathData(void)
}
}
}
+
+CPathNode*
+CPathFind::GetNode(int16 index)
+{
+ if(index < 0)
+ return nil;
+ if(index < ARRAY_SIZE(ThePaths.m_searchNodes))
+ return &ThePaths.m_searchNodes[index];
+ return &ThePaths.m_pathNodes[index - ARRAY_SIZE(ThePaths.m_searchNodes)];
+}
+int16
+CPathFind::GetIndex(CPathNode *node)
+{
+ if(node == nil)
+ return -1;
+ if(node >= &ThePaths.m_searchNodes[0] && node < &ThePaths.m_searchNodes[ARRAY_SIZE(ThePaths.m_searchNodes)])
+ return node - ThePaths.m_searchNodes;
+ else
+ return (node - ThePaths.m_pathNodes) + ARRAY_SIZE(ThePaths.m_searchNodes);
+}
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index bbfdf7b7..7abc455a 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -9,9 +9,6 @@ enum
{
NodeTypeExtern = 1,
NodeTypeIntern = 2,
-
- UseInRoadBlock = 1,
- ObjectEastWest = 2,
};
enum
@@ -56,31 +53,42 @@ public:
struct CPathNode
{
- CVector pos;
- CPathNode *prev;
- CPathNode *next;
+ int16 prevIndex;
+ int16 nextIndex;
+ int16 x;
+ int16 y;
+ int16 z;
int16 distance; // in path search
- int16 objectIndex;
int16 firstLink;
- uint8 numLinks;
+ int8 width;
+ int8 group;
- uint8 unkBits : 2;
+ uint8 numLinks : 4;
uint8 bDeadEnd : 1;
uint8 bDisabled : 1;
uint8 bBetweenLevels : 1;
-
- int8 group;
-
- CVector &GetPosition(void) { return pos; }
- void SetPosition(const CVector &p) { pos = p; }
- float GetX(void) { return pos.x; }
- float GetY(void) { return pos.y; }
- float GetZ(void) { return pos.z; }
-
- CPathNode *GetPrev(void) { return prev; }
- CPathNode *GetNext(void) { return next; }
- void SetPrev(CPathNode *node) { prev = node; }
- void SetNext(CPathNode *node) { next = node; }
+ uint8 bUseInRoadBlock : 1;
+
+ uint8 bWaterPath : 1;
+ uint8 bOnlySmallBoats : 1;
+ uint8 flagB4 : 1; // where is this set?
+ uint8 speedLimit : 2;
+ //uint8 flagB20 : 1;
+ //uint8 flagB40 : 1;
+ //uint8 flagB80 : 1;
+
+ uint8 spawnRate : 4;
+ uint8 flagsC : 4;
+
+ CVector GetPosition(void) { return CVector(x/8.0f, y/8.0f, z/8.0f); }
+ void SetPosition(const CVector &p) { x = p.x*8.0f; y = p.y*8.0f; z = p.z*8.0f; }
+ float GetX(void) { return x/8.0f; }
+ float GetY(void) { return y/8.0f; }
+ float GetZ(void) { return z/8.0f; }
+ CPathNode *GetPrev(void);
+ CPathNode *GetNext(void);
+ void SetPrev(CPathNode *node);
+ void SetNext(CPathNode *node);
};
union CConnectionFlags
@@ -94,22 +102,25 @@ union CConnectionFlags
struct CCarPathLink
{
- CVector2D pos;
- CVector2D dir;
+ int16 x;
+ int16 y;
int16 pathNodeIndex;
- int8 numLeftLanes;
- int8 numRightLanes;
- uint8 trafficLightType;
-
- uint8 bBridgeLights : 1;
- // more?
-
- CVector2D &GetPosition(void) { return pos; }
- CVector2D &GetDirection(void) { return dir; }
- float GetX(void) { return pos.x; }
- float GetY(void) { return pos.y; }
- float GetDirX(void) { return dir.x; }
- float GetDirY(void) { return dir.y; }
+ int8 dirX;
+ int8 dirY;
+ int8 numLeftLanes : 3;
+ int8 numRightLanes : 3;
+ uint8 flag1 : 1;
+ uint8 trafficLightType : 2;
+ uint8 bBridgeLights : 1; // at least in LCS...
+ int8 width;
+
+ CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); }
+ CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); }
+ float GetX(void) { return x/8.0f; }
+ float GetY(void) { return y/8.0f; }
+ float GetDirX(void) { return dirX/100.0f; }
+ float GetDirY(void) { return dirY/100.0f; }
+ float GetLaneOffset(void) { return width/80.0f; }
float OneWayLaneOffset()
{
@@ -117,21 +128,33 @@ struct CCarPathLink
return 0.5f - 0.5f * numRightLanes;
if (numRightLanes == 0)
return 0.5f - 0.5f * numLeftLanes;
- return 0.5f;
+ return 0.5f + GetLaneOffset();
}
};
// This is what we're reading from the files, only temporary
struct CPathInfoForObject
{
- int16 x;
- int16 y;
- int16 z;
+ float x;
+ float y;
+ float z;
int8 type;
int8 next;
int8 numLeftLanes;
int8 numRightLanes;
+ int8 speedLimit;
+ int8 width;
+
uint8 crossing : 1;
+ uint8 onlySmallBoats : 1;
+ uint8 roadBlock : 1;
+ uint8 disabled : 1;
+ uint8 waterPath : 1;
+ uint8 betweenLevels : 1;
+
+ uint8 spawnRate : 4;
+
+ void SwapConnectionsToBeRightWayRound(void);
};
extern CPathInfoForObject *InfoForTileCars;
extern CPathInfoForObject *InfoForTilePeds;
@@ -139,18 +162,25 @@ extern CPathInfoForObject *InfoForTilePeds;
struct CTempNode
{
CVector pos;
- float dirX;
- float dirY;
+ int8 dirX; // *100
+ int8 dirY;
int16 link1;
int16 link2;
int8 numLeftLanes;
int8 numRightLanes;
+ int8 width;
+ bool isCross;
int8 linkState;
};
-struct CTempDetachedNode // unused
+struct CTempNodeExternal // made up name
{
- uint8 foo[20];
+ CVector pos;
+ int16 next;
+ int8 numLeftLanes;
+ int8 numRightLanes;
+ int8 width;
+ bool isCross;
};
class CPathFind
@@ -159,10 +189,8 @@ public:
CPathNode m_pathNodes[NUM_PATHNODES];
CCarPathLink m_carPathLinks[NUM_CARPATHLINKS];
CTreadable *m_mapObjects[NUM_MAPOBJECTS];
- uint8 m_objectFlags[NUM_MAPOBJECTS];
- int16 m_connections[NUM_PATHCONNECTIONS];
- int16 m_distances[NUM_PATHCONNECTIONS];
- CConnectionFlags m_connectionFlags[NUM_PATHCONNECTIONS];
+ uint16 m_connections[NUM_PATHCONNECTIONS]; // and flags
+ uint8 m_distances[NUM_PATHCONNECTIONS];
int16 m_carPathConnections[NUM_PATHCONNECTIONS];
int32 m_numPathNodes;
@@ -178,14 +206,19 @@ public:
void Init(void);
void AllocatePathFindInfoMem(int16 numPathGroups);
void RegisterMapObject(CTreadable *mapObject);
- void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing);
- void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight);
- void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out);
+ void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate);
+ void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate);
+ void StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
+ bool disabled, bool betweenLevels, uint8 spawnRate);
+ void StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool unk);
+ void CalcNodeCoors(float x, float y, float z, int32 id, CVector *out);
bool LoadPathFindData(void);
void PreparePathData(void);
void CountFloodFillGroups(uint8 type);
void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
- float maxdist, CTempDetachedNode *detachednodes, int32 numDetached);
+ float maxdist, CPathInfoForObject *detachednodes, int32 numDetached);
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
@@ -203,30 +236,37 @@ public:
void MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId);
void MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
void PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
- int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false);
+// TODO(MIAMI): check callers for new arguments
+ int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreFlagB4 = false, bool bWaterPath = false);
int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);
float FindNodeOrientationForCarPlacement(int32 nodeId);
float FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards);
bool NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled = false);
bool GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix);
- CTreadable *FindRoadObjectClosestToCoors(CVector coors, uint8 type);
void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*);
void DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode);
bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
void Save(uint8 *buf, uint32 *size);
void Load(uint8 *buf, uint32 size);
- uint16 ConnectedNode(int id) { return m_connections[id]; }
- bool ConnectionCrossesRoad(int id) { return m_connectionFlags[id].bCrossesRoad; }
- bool ConnectionHasTrafficLight(int id) { return m_connectionFlags[id].bTrafficLight; }
- void ConnectionSetTrafficLight(int id) { m_connectionFlags[id].bTrafficLight = true; }
+
+ CPathNode *GetNode(int16 index);
+ int16 GetIndex(CPathNode *node);
+
+ uint16 ConnectedNode(int id) { return m_connections[id] & 0x3FFF; }
+ bool ConnectionCrossesRoad(int id) { return !!(m_connections[id] & 0x8000); }
+ bool ConnectionHasTrafficLight(int id) { return !!(m_connections[id] & 0x4000); }
+ void ConnectionSetTrafficLight(int id) { m_connections[id] |= 0x4000; }
void DisplayPathData(void);
};
-VALIDATE_SIZE(CPathFind, 0x49bf4);
-
extern CPathFind ThePaths;
+inline CPathNode *CPathNode::GetPrev(void) { return ThePaths.GetNode(prevIndex); }
+inline CPathNode *CPathNode::GetNext(void) { return ThePaths.GetNode(nextIndex); }
+inline void CPathNode::SetPrev(CPathNode *node) { prevIndex = ThePaths.GetIndex(node); }
+inline void CPathNode::SetNext(CPathNode *node) { nextIndex = ThePaths.GetIndex(node); }
+
extern bool gbShowPedPaths;
extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks;
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 32bffa17..b5e20e41 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -44,15 +44,58 @@ uint32 CPickups::StaticCamStartTime;
tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
-// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
+// TODO(Miami)
uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
-uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
+uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS] = {
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 4,
+ 4,
+ 4,
+ 4,
+ 34,
+ 16,
+ 100,
+ 60,
+ 60,
+ 60,
+ 60,
+ 60,
+ 20,
+ 4,
+ 14,
+ 1,
+ 400,
+};
uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
-uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 };
-uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
-uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
-float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
+// TODO(Miami): Those are all placeholders!!
+uint8 aWeaponReds[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255,
+255, 255, 255, 255, 255, 255, 255, 255,
+255, 128, 0, 255, 0 };
+uint8 aWeaponGreens[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255,
+0, 255, 0, 255, 0 };
+uint8 aWeaponBlues[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255,
+255, 255, 255, 255, 255, 255, 255, 255,
+0, 128, 255, 0, 0 };
+float aWeaponScale[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f,
+1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+1.0f, 1.0f, 1.0f, 1.0f };
void
CPickup::RemoveKeepType()
@@ -129,12 +172,12 @@ CPickup::GiveUsAPickUpObject(int32 handle)
}
bool
-CPickup::CanBePickedUp(CPlayerPed *player)
+CPickup::CanBePickedUp(CPlayerPed *player, int playerId)
{
assert(m_pObject != nil);
bool cannotBePickedUp =
- (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
- || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
+ (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > CWorld::Players[playerId].m_nMaxArmour - 0.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > CWorld::Players[playerId].m_nMaxHealth - 0.5f)
|| (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
|| (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
return !cannotBePickedUp;
@@ -190,7 +233,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
}
// if we didn't then we've got nothing to do
- if (isPickupTouched && CanBePickedUp(player)) {
+ if (isPickupTouched && CanBePickedUp(player, playerId)) {
CPad::GetPad(0)->StartShake(120, 100);
switch (m_eType)
{
@@ -380,6 +423,30 @@ CPickups::Init(void)
CollectedPickUpIndex = 0;
}
+// --MIAMI: Done
+bool
+CPickups::TestForPickupsInBubble(CVector pos, float range)
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if ((aPickUps[i].m_vecPos - pos).Magnitude() < range)
+ return true;
+ }
+ return false;
+}
+
+// --MIAMI: Done
+bool
+CPickups::TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused) {
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType == type && aPickUps[i].m_eModelIndex == ModelForWeapon(weapon))
+ if ((aPickUps[i].m_vecPos - pos).Magnitude() < 7.5f) {
+ aPickUps[i].m_nQuantity += quantity;
+ return true;
+ }
+ }
+ return false;
+}
+
bool
CPickups::IsPickUpPickedUp(int32 pickupId)
{
@@ -430,14 +497,14 @@ CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
return true;
} else if (modelIndex == MI_PICKUP_BODYARMOUR) {
- player->m_fArmour = 100.0f;
+ player->m_fArmour = CWorld::Players[playerIndex].m_nMaxArmour;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
return true;
} else if (modelIndex == MI_PICKUP_INFO) {
DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
return true;
} else if (modelIndex == MI_PICKUP_HEALTH) {
- player->m_fHealth = 100.0f;
+ player->m_fHealth = CWorld::Players[playerIndex].m_nMaxHealth;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
return true;
} else if (modelIndex == MI_PICKUP_BONUS) {
@@ -486,7 +553,7 @@ CPickups::RemovePickUp(int32 pickupIndex)
}
int32
-CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
+CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate, bool highPriority, wchar* pText)
{
bool bFreeFound = false;
int32 slot = 0;
@@ -561,53 +628,22 @@ CPickups::GetNewUniquePickupIndex(int32 slot)
return slot | (aPickUps[slot].m_nIndex << 16);
}
+// --MIAMI: Done
int32
CPickups::ModelForWeapon(eWeaponType weaponType)
{
- switch (weaponType)
- {
- case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
- case WEAPONTYPE_COLT45: return MI_COLT;
- case WEAPONTYPE_UZI: return MI_UZI;
- case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
- case WEAPONTYPE_AK47: return MI_AK47;
- case WEAPONTYPE_M16: return MI_M16;
- case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
- case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
- case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
- case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
- case WEAPONTYPE_GRENADE: return MI_GRENADE;
- default: break;
- }
- return 0;
+ return CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId;
}
+// --MIAMI: Done
eWeaponType
CPickups::WeaponForModel(int32 model)
{
if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
- switch (model)
- {
- case MI_GRENADE: return WEAPONTYPE_GRENADE;
- case MI_AK47: return WEAPONTYPE_AK47;
- case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
- case MI_COLT: return WEAPONTYPE_COLT45;
- case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
- case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
- case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
- case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
- case MI_UZI: return WEAPONTYPE_UZI;
- case MI_MISSILE: return WEAPONTYPE_UNARMED;
- case MI_M16: return WEAPONTYPE_M16;
- case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
- }
- return WEAPONTYPE_UNARMED;
-}
-
-int32
-CPickups::FindColourIndexForWeaponMI(int32 model)
-{
- return WeaponForModel(model) - 1;
+ if (model == MI_PICKUP_HEALTH) return WEAPONTYPE_HEALTH;
+ if (model == MI_PICKUP_ADRENALINE) return WEAPONTYPE_ARMOUR;
+ if (model == -1) return WEAPONTYPE_UNARMED;
+ return (eWeaponType)((CWeaponModelInfo*)CModelInfo::GetModelInfo(model))->GetWeaponInfo();
}
void
@@ -685,15 +721,15 @@ CPickups::DoPickUpEffects(CEntity *entity)
int16 colorId;
if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
- colorId = 11;
+ colorId = WEAPONTYPE_LAST_WEAPONTYPE;
else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
- colorId = 12;
+ colorId = WEAPONTYPE_LAST_WEAPONTYPE + 1;
else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
- colorId = 13;
+ colorId = WEAPONTYPE_LAST_WEAPONTYPE + 2;
else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
- colorId = 14;
+ colorId = WEAPONTYPE_LAST_WEAPONTYPE + 3;
else
- colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
+ colorId = WeaponForModel(entity->GetModelIndex());
assert(colorId >= 0);
@@ -1126,45 +1162,6 @@ CPacManPickups::Update()
void
CPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, uint8 type)
{
- int i = 0;
- while (count > 0) {
- while (aPMPickUps[i].m_eType != PACMAN_NONE)
- i++;
-
- bool bPickupCreated = false;
- while (!bPickupCreated) {
- CVector newPos = pos;
- CColPoint colPoint;
- CEntity *pRoad;
- uint16 nRand = CGeneral::GetRandomNumber();
- newPos.x += ((nRand & 0xFF) - 128) * scrambleMult / 128.0f;
- newPos.y += (((nRand >> 8) & 0xFF) - 128) * scrambleMult / 128.0f;
- newPos.z = 1000.0f;
- if (CWorld::ProcessVerticalLine(newPos, -1000.0f, colPoint, pRoad, true, false, false, false, true, false, nil) && pRoad->IsBuilding() && ((CBuilding*)pRoad)->GetIsATreadable()) {
- newPos.z = 0.7f + colPoint.point.z;
- aPMPickUps[i].m_eType = type;
- aPMPickUps[i].m_vecPosn = newPos;
- CObject *obj = new CObject(MI_BULLION, true);
- if (obj != nil) {
- obj->ObjectCreatedBy = MISSION_OBJECT;
- obj->SetPosition(aPMPickUps[i].m_vecPosn);
- obj->SetOrientation(0.0f, 0.0f, -HALFPI);
- obj->GetMatrix().UpdateRW();
- obj->UpdateRwFrame();
-
- obj->bAffectedByGravity = false;
- obj->bExplosionProof = true;
- obj->bUsesCollision = false;
- obj->bIsPickup = false;
- CWorld::Add(obj);
- }
- aPMPickUps[i].m_pObject = obj;
- bPickupCreated = true;
- }
- }
- count--;
- }
- bPMActive = true;
}
// diablo porn mission pickups
@@ -1281,40 +1278,6 @@ static const CVector aRacePoints1[] = {
void
CPacManPickups::GeneratePMPickUpsForRace(int32 race)
{
- const CVector *pPos = nil;
- int i = 0;
-
- if (race == 0) pPos = aRacePoints1; // there's only one available
- assert(pPos != nil);
-
- while (!pPos->IsZero()) {
- while (aPMPickUps[i].m_eType != PACMAN_NONE)
- i++;
-
- aPMPickUps[i].m_eType = PACMAN_RACE;
- aPMPickUps[i].m_vecPosn = *(pPos++);
- if (race == 0) {
- CObject* obj = new CObject(MI_DONKEYMAG, true);
- if (obj != nil) {
- obj->ObjectCreatedBy = MISSION_OBJECT;
-
- obj->SetPosition(aPMPickUps[i].m_vecPosn);
- obj->SetOrientation(0.0f, 0.0f, -HALFPI);
- obj->GetMatrix().UpdateRW();
- obj->UpdateRwFrame();
-
- obj->bAffectedByGravity = false;
- obj->bExplosionProof = true;
- obj->bUsesCollision = false;
- obj->bIsPickup = false;
-
- CWorld::Add(obj);
- }
- aPMPickUps[i].m_pObject = obj;
- } else
- aPMPickUps[i].m_pObject = nil;
- }
- bPMActive = true;
}
void
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index b05f5db7..810f3dff 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -8,6 +8,7 @@ enum ePickupType : uint8
PICKUP_ON_STREET,
PICKUP_ONCE,
PICKUP_ONCE_TIMEOUT,
+ PICKUP_ONCE_TIMEOUT_SLOW,
PICKUP_COLLECTABLE1,
PICKUP_IN_SHOP_OUT_OF_STOCK,
PICKUP_MONEY,
@@ -18,6 +19,9 @@ enum ePickupType : uint8
PICKUP_FLOATINGPACKAGE,
PICKUP_FLOATINGPACKAGE_FLOATING,
PICKUP_ON_STREET_SLOW,
+ PICKUP_ASSET_REVENUE,
+ PICKUP_PROPERTY_LOCKED,
+ PICKUP_PROPERTY_FORSALE,
PICKUP_NUMOFTYPES
};
@@ -42,7 +46,7 @@ public:
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
- inline bool CanBePickedUp(CPlayerPed *player);
+ inline bool CanBePickedUp(CPlayerPed *player, int playerId);
void RemoveKeepType();
void Remove();
};
@@ -73,7 +77,7 @@ public:
static void DoMoneyEffects(CEntity *ent);
static void DoMineEffects(CEntity *ent);
static void DoPickUpEffects(CEntity *ent);
- static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
+ static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate = 0, bool highPriority = false, wchar* pText = nil);
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
static void RemovePickUp(int32 pickupIndex);
static void RemoveAllFloatingPickups();
@@ -81,11 +85,12 @@ public:
static bool IsPickUpPickedUp(int32 pickupId);
static int32 ModelForWeapon(eWeaponType weaponType);
static enum eWeaponType WeaponForModel(int32 model);
- static int32 FindColourIndexForWeaponMI(int32 model);
static int32 GetActualPickupIndex(int32 index);
static int32 GetNewUniquePickupIndex(int32 slot);
static void PassTime(uint32 time);
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
+ static bool TestForPickupsInBubble(CVector pos, float range);
+ static bool TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused);
static void Load(uint8 *buf, uint32 size);
static void Save(uint8 *buf, uint32 *size);
@@ -99,7 +104,7 @@ public:
};
extern uint16 AmmoForWeapon[20];
-extern uint16 AmmoForWeapon_OnStreet[20];
+extern uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS];
extern uint16 CostOfWeapon[20];
enum ePacmanPickupType
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index d086543f..5e6c7cdb 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -11,513 +11,97 @@
#include "World.h"
uint16 CRecordDataForGame::RecordingState;
-uint8* CRecordDataForGame::pDataBuffer;
-uint8* CRecordDataForGame::pDataBufferPointer;
-int CRecordDataForGame::FId;
-tGameBuffer CRecordDataForGame::pDataBufferForFrame;
-
-#define MEMORY_FOR_GAME_RECORD (150000)
void CRecordDataForGame::Init(void)
{
RecordingState = STATE_NONE;
- delete[] pDataBuffer;
- pDataBufferPointer = nil;
- pDataBuffer = nil;
-#ifndef GTA_PS2 // this stuff is not present on PS2
- FId = CFileMgr::OpenFile("playback.dat", "r");
- if (FId <= 0) {
- if ((FId = CFileMgr::OpenFile("record.dat", "r")) <= 0)
- RecordingState = STATE_NONE;
- else {
- CFileMgr::CloseFile(FId);
- FId = CFileMgr::OpenFileForWriting("record.dat");
- RecordingState = STATE_RECORD;
- }
- }
- else {
- RecordingState = STATE_PLAYBACK;
- }
- if (RecordingState == STATE_PLAYBACK) {
- pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
- pDataBuffer = pDataBufferPointer;
- pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
- CFileMgr::CloseFile(FId);
- }
-#else
- RecordingState = STATE_NONE; // second time to make sure
-#endif
}
void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
{
- switch (RecordingState) {
- case STATE_RECORD:
- {
- pDataBufferForFrame.m_fTimeStep = CTimer::GetTimeStep();
- pDataBufferForFrame.m_nTimeInMilliseconds = CTimer::GetTimeInMilliseconds();
- pDataBufferForFrame.m_nSizeOfPads[0] = 0;
- pDataBufferForFrame.m_nSizeOfPads[1] = 0;
- pDataBufferForFrame.m_nChecksum = CalcGameChecksum();
- uint8* pController1 = PackCurrentPadValues(pDataBufferForFrame.m_ControllerBuffer, &CPad::GetPad(0)->OldState, &CPad::GetPad(0)->NewState);
- pDataBufferForFrame.m_nSizeOfPads[0] = (pController1 - pDataBufferForFrame.m_ControllerBuffer) / 2;
- uint8* pController2 = PackCurrentPadValues(pController1, &CPad::GetPad(1)->OldState, &CPad::GetPad(1)->NewState);
- pDataBufferForFrame.m_nSizeOfPads[1] = (pController2 - pController1) / 2;
- uint8* pEndPtr = pController2;
- if ((pDataBufferForFrame.m_nSizeOfPads[0] + pDataBufferForFrame.m_nSizeOfPads[1]) & 1)
- pEndPtr += 2;
- CFileMgr::Write(FId, (char*)&pDataBufferForFrame, pEndPtr - (uint8*)&pDataBufferForFrame);
- break;
- }
- case STATE_PLAYBACK:
- if (pDataBufferPointer[8] == (uint8)-1)
- CPad::GetPad(0)->NewState.Clear();
- else {
- tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
- CTimer::SetTimeInMilliseconds(pData->m_nTimeInMilliseconds);
- CTimer::SetTimeStep(pData->m_fTimeStep);
- uint8 size1 = pData->m_nSizeOfPads[0];
- uint8 size2 = pData->m_nSizeOfPads[1];
- pDataBufferPointer = (uint8*)&pData->m_ControllerBuffer;
- pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size1, &CPad::GetPad(0)->NewState);
- pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size2, &CPad::GetPad(1)->NewState);
- if ((size1 + size2) & 1)
- pDataBufferPointer += 2;
- if (pData->m_nChecksum != CalcGameChecksum())
- printf("Playback out of sync\n");
- }
- }
}
-#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
- do { \
- if (os->field != ns->field){ \
- *buf++ = id; \
- *buf++ = ns->field; \
- } \
- } while (0);
-
uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns)
{
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder1, 6);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder2, 7);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadUp, 8);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadDown, 9);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadLeft, 10);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadRight, 11);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Start, 12);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Select, 13);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Square, 14);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Triangle, 15);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Cross, 16);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Circle, 17);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShock, 18);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShock, 19);
- return buf;
+ return nil;
}
-#undef PROCESS_BUTTON_STATE_STORE
-
-#define PROCESS_BUTTON_STATE_RESTORE(buf, state, field, id) case id: state->field = *buf++; break;
uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state)
{
- for (uint8 i = 0; i < total; i++) {
- switch (*buf++) {
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder1, 6);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder2, 7);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadUp, 8);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadDown, 9);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadLeft, 10);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadRight, 11);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Start, 12);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Select, 13);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Square, 14);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Triangle, 15);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Cross, 16);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Circle, 17);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShock, 18);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShock, 19);
- }
- }
- return buf;
+ return nil;
}
-#undef PROCESS_BUTTON_STATE_RESTORE
-
uint16 CRecordDataForGame::CalcGameChecksum(void)
{
- uint32 checksum = 0;
- int i = CPools::GetPedPool()->GetSize();
- while (i--) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- checksum ^= pPed->GetModelIndex() ^ *(uint32*)&pPed->GetPosition().z ^ *(uint32*)&pPed->GetPosition().y ^ *(uint32*)&pPed->GetPosition().x;
- }
- i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- checksum ^= pVehicle->GetModelIndex() ^ *(uint32*)&pVehicle->GetPosition().z ^ *(uint32*)&pVehicle->GetPosition().y ^ *(uint32*)&pVehicle->GetPosition().x;
- }
- return checksum ^ checksum >> 16;
+ return 0;
}
uint8 CRecordDataForChase::Status;
-int CRecordDataForChase::PositionChanges;
-uint8 CRecordDataForChase::CurrentCar;
-CAutomobile* CRecordDataForChase::pChaseCars[NUM_CHASE_CARS];
-uint32 CRecordDataForChase::AnimStartTime;
-float CRecordDataForChase::AnimTime;
-CCarStateEachFrame* CRecordDataForChase::pBaseMemForCar[NUM_CHASE_CARS];
-float CRecordDataForChase::TimeMultiplier;
-int CRecordDataForChase::FId2;
-
-#define CHASE_SCENE_LENGTH_IN_SECONDS (80)
-#define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame
-#define CHASE_SCENE_FRAMES_IN_RECORDING (CHASE_SCENE_LENGTH_IN_SECONDS * CHASE_SCENE_FRAMES_PER_SECOND)
-#define CHASE_SCENE_LENGTH_IN_FRAMES (CHASE_SCENE_FRAMES_IN_RECORDING * 2)
void CRecordDataForChase::Init(void)
{
Status = STATE_NONE;
- PositionChanges = 0;
- CurrentCar = 0;
- for (int i = 0; i < NUM_CHASE_CARS; i++)
- pChaseCars[i] = nil;
- AnimStartTime = 0;
}
void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void)
{
- switch (Status) {
- case STATE_NONE:
- return;
- case STATE_RECORD:
- {
- if ((CTimer::GetFrameCounter() & 1) == 0)
- StoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2]);
- if (CTimer::GetFrameCounter() < CHASE_SCENE_LENGTH_IN_FRAMES * 2)
- return;
- CFileMgr::SetDir("data\\paths");
- sprintf(gString, "chase%d.dat", CurrentCar);
- int fid = CFileMgr::OpenFileForWriting(gString);
- uint32 fs = CHASE_SCENE_LENGTH_IN_FRAMES * sizeof(CCarStateEachFrame);
- printf("FileSize:%d\n", fs);
- CFileMgr::Write(fid, (char*)pBaseMemForCar[CurrentCar], fs);
- CFileMgr::CloseFile(fid);
- CFileMgr::SetDir("");
- sprintf(gString, "car%d.max", CurrentCar);
- int fid2 = CFileMgr::OpenFileForWriting(gString);
- for (int i = 0; i < CHASE_SCENE_FRAMES_IN_RECORDING; i++) {
- // WTF? Was it ever used?
-#ifdef FIX_BUGS
- CCarStateEachFrame* pState = pBaseMemForCar[CurrentCar];
-#else
- CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar];
-#endif
- CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
- CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
- CVector up = CrossProduct(right, forward);
- sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", right.x, right.y, right.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", forward.x, forward.y, forward.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", up.x, up.y, up.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- }
- CFileMgr::CloseFile(fid2);
- }
- case STATE_PLAYBACK:
- case STATE_PLAYBACK_BEFORE_RECORDING:
- case STATE_PLAYBACK_INIT:
- break;
- }
}
-struct tCoors {
- CVector pos;
- float angle;
-};
-
-// I guess developer was filling this with actual data before running the game
-tCoors NewCoorsForRecordedCars[7];
-
void CRecordDataForChase::SaveOrRetrieveCarPositions(void)
{
- switch (Status) {
- case STATE_NONE:
- return;
- case STATE_RECORD:
- case STATE_PLAYBACK_BEFORE_RECORDING:
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (i != CurrentCar && CTimer::GetFrameCounter()) {
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CTimer::GetFrameCounter() / 2], false);
- pChaseCars[i]->GetMatrix().UpdateRW();
- pChaseCars[i]->UpdateRwFrame();
- }
- }
- if (Status == STATE_PLAYBACK_BEFORE_RECORDING && CTimer::GetFrameCounter()) {
- RestoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2], false);
- pChaseCars[CurrentCar]->GetMatrix().UpdateRW();
- pChaseCars[CurrentCar]->UpdateRwFrame();
- }
- if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) {
- if (!CPad::GetPad(0)->GetRightShockJustDown()) {
- pChaseCars[CurrentCar]->SetPosition(NewCoorsForRecordedCars[PositionChanges].pos);
- pChaseCars[CurrentCar]->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pChaseCars[CurrentCar]->GetMatrix().SetRotateZOnly(DEGTORAD(NewCoorsForRecordedCars[PositionChanges].angle));
- ++PositionChanges;
- }
- if (Status == STATE_PLAYBACK_BEFORE_RECORDING) {
- Status = STATE_RECORD;
- pChaseCars[CurrentCar]->SetStatus(STATUS_PLAYER);
- }
- }
- break;
- case STATE_PLAYBACK_INIT:
- Status = STATE_PLAYBACK;
- break;
- case STATE_PLAYBACK:
- {
- TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds();
- float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * Min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier);
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (!pBaseMemForCar[i])
- continue;
- if (!pChaseCars[i])
- continue;
- if (EndOfFrameTime < CHASE_SCENE_FRAMES_IN_RECORDING - 1) {
- int FlooredEOFTime = EndOfFrameTime;
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][FlooredEOFTime], false);
- CMatrix tmp;
- float dp = EndOfFrameTime - FlooredEOFTime;
- RestoreInfoForMatrix(tmp, &pBaseMemForCar[i][FlooredEOFTime + 1]);
- pChaseCars[i]->GetRight() += (tmp.GetRight() - pChaseCars[i]->GetRight()) * dp;
- pChaseCars[i]->GetForward() += (tmp.GetForward() - pChaseCars[i]->GetForward()) * dp;
- pChaseCars[i]->GetUp() += (tmp.GetUp() - pChaseCars[i]->GetUp()) * dp;
- pChaseCars[i]->GetMatrix().GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * dp;
- }
- else{
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CHASE_SCENE_FRAMES_IN_RECORDING - 1], true);
- if (i == 0)
- pChaseCars[i]->GetMatrix().GetPosition().z += 0.2f;
- }
- pChaseCars[i]->GetMatrix().UpdateRW();
- pChaseCars[i]->UpdateRwFrame();
- pChaseCars[i]->RemoveAndAdd();
- }
- break;
- }
- }
}
void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState)
{
- pState->rightX = INT8_MAX * pCar->GetRight().x;
- pState->rightY = INT8_MAX * pCar->GetRight().y;
- pState->rightZ = INT8_MAX * pCar->GetRight().z;
- pState->forwardX = INT8_MAX * pCar->GetForward().x;
- pState->forwardY = INT8_MAX * pCar->GetForward().y;
- pState->forwardZ = INT8_MAX * pCar->GetForward().z;
- pState->pos = pCar->GetPosition();
- pState->velX = 0.5f * INT16_MAX * pCar->GetMoveSpeed().x;
- pState->velY = 0.5f * INT16_MAX * pCar->GetMoveSpeed().y;
- pState->velZ = 0.5f * INT16_MAX * pCar->GetMoveSpeed().z;
- pState->wheel = 20 * pCar->m_fSteerAngle;
- pState->gas = 100 * pCar->m_fGasPedal;
- pState->brake = 100 * pCar->m_fBrakePedal;
- pState->handbrake = pCar->bIsHandbrakeOn;
}
void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState)
{
- matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
- matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
- matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward());
- matrix.GetPosition() = pState->pos;
}
void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop)
{
- CVector oldPos = pCar->GetPosition();
- RestoreInfoForMatrix(pCar->GetMatrix(), pState);
- pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) / INT16_MAX / 0.5f);
- pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f);
- pCar->m_fSteerAngle = pState->wheel / 20.0f;
- pCar->m_fGasPedal = pState->gas / 100.0f;
- pCar->m_fBrakePedal = pState->brake / 100.0f;
- pCar->bIsHandbrakeOn = pState->handbrake;
- if ((oldPos - pCar->GetPosition()).Magnitude() > 15.0f) {
- if (pCar == pChaseCars[14]) {
- pCar->m_currentColour1 = 58;
- pCar->m_currentColour2 = 1;
- }
- else
- pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2);
- }
- pCar->m_fHealth = Min(pCar->m_fHealth, 500.0f);
- if (stop) {
- pCar->m_fGasPedal = 0.0f;
- pCar->m_fBrakePedal = 0.0f;
- pCar->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pCar->bIsHandbrakeOn = false;
- }
}
void CRecordDataForChase::ProcessControlCars(void)
{
- if (Status != STATE_PLAYBACK)
- return;
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (pChaseCars[i])
- pChaseCars[i]->ProcessControl();
- }
}
-#if (defined(GTA_PS2) || defined(FIX_BUGS))
bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)
{
- // may be wrong
- if (Status == STATE_NONE || Status == STATE_PLAYBACK)
- return false;
- return pad != 0;
+ return false;
}
-#endif
void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)
{
- CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
- CStreaming::LoadAllRequestedModels(false);
- if (!CStreaming::HasModelLoaded(mi))
- return;
- CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE);
- pCar->SetPosition(pos);
- pCar->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);
- pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle));
- pCar->pDriver = nil;
- pCar->m_currentColour1 = colour1;
- pCar->m_currentColour2 = colour2;
- CWorld::Add(pCar);
- *ppCar = pCar;
}
void RemoveUnusedCollision(void)
{
- static const char* dontDeleteArray[] = {
- "rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22",
- "road_broadway02", "road_broadway01", "com_21way5", "com_21way50",
- "cm1waycrosscom", "com_21way20", "com_21way10", "road_broadway04",
- "com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22"
- };
- for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
- CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_NONE;
- CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE);
- for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
- CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL;
}
void CRecordDataForChase::StartChaseScene(float startTime)
{
- char filename[28];
- SetUpCarsForChaseScene();
- Status = STATE_PLAYBACK;
- AnimTime = startTime;
- AnimStartTime = CTimer::GetTimeInMilliseconds();
- RemoveUnusedCollision();
- CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
- CGame::TidyUpMemory(true, true);
- CStreaming::ImGonnaUseStreamingMemory();
- CFileMgr::SetDir("data\\paths");
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (!pChaseCars[i]) {
- pBaseMemForCar[i] = nil;
- continue;
- }
- sprintf(filename, "chase%d.dat", i);
- FId2 = CFileMgr::OpenFile(filename, "rb");
- if (FId2 <= 0) {
- pBaseMemForCar[i] = nil;
- continue;
- }
- pBaseMemForCar[i] = new CCarStateEachFrame[CHASE_SCENE_FRAMES_IN_RECORDING];
- for (int j = 0; j < CHASE_SCENE_FRAMES_IN_RECORDING; j++) {
- CFileMgr::Read(FId2, (char*)&pBaseMemForCar[i][j], sizeof(CCarStateEachFrame));
- CFileMgr::Seek(FId2, sizeof(CCarStateEachFrame), 1);
- }
- CFileMgr::CloseFile(FId2);
- }
- CFileMgr::SetDir("");
- CStreaming::IHaveUsedStreamingMemory();
- TimeMultiplier = 0.0f;
}
void CRecordDataForChase::CleanUpChaseScene(void)
{
- if (Status != STATE_PLAYBACK_INIT && Status != STATE_PLAYBACK)
- return;
- Status = STATE_NONE;
- CleanUpCarsForChaseScene();
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (pBaseMemForCar[i]) {
- delete[] pBaseMemForCar[i];
- pBaseMemForCar[i] = nil;
- }
- }
}
void CRecordDataForChase::SetUpCarsForChaseScene(void)
{
- GiveUsACar(MI_POLICE, CVector(273.54221f, -1167.1907f, 24.880601f), 63.0f, &pChaseCars[0], 2, 1);
- GiveUsACar(MI_ENFORCER, CVector(231.1783f, -1388.8322f, 25.978201f), 90.0f, &pChaseCars[1], 2, 1);
- GiveUsACar(MI_TAXI, CVector(184.3156f, -1473.251f, 25.978201f), 0.0f, &pChaseCars[4], 6, 6);
- GiveUsACar(MI_CHEETAH, CVector(173.8868f, -1377.6514f, 25.978201f), 0.0f, &pChaseCars[6], 4, 5);
- GiveUsACar(MI_STINGER, CVector(102.5946f, -943.93628f, 25.9781f), 270.0f, &pChaseCars[7], 53, 53);
- GiveUsACar(MI_CHEETAH, CVector(-177.7157f, -862.18652f, 25.978201f), 155.0f, &pChaseCars[10], 41, 1);
- GiveUsACar(MI_STINGER, CVector(-170.56979f, -889.02362f, 25.978201f), 154.0f, &pChaseCars[11], 10, 10);
- GiveUsACar(MI_KURUMA, CVector(402.60809f, -917.49628f, 37.381001f), 90.0f, &pChaseCars[14], 34, 1);
- GiveUsACar(MI_TAXI, CVector(-33.496201f, -938.4563f, 25.9781f), 266.0f, &pChaseCars[16], 6, 6);
- GiveUsACar(MI_KURUMA, CVector(49.363098f, -987.60498f, 25.9781f), 0.0f, &pChaseCars[18], 51, 1);
- GiveUsACar(MI_TAXI, CVector(179.0049f, -1154.6686f, 25.9781f), 0.0f, &pChaseCars[19], 6, 76);
- GiveUsACar(MI_RUMPO, CVector(-28.9762f, -1031.3367f, 25.990601f), 242.0f, &pChaseCars[2], 1, 75);
- GiveUsACar(MI_PATRIOT, CVector(114.1564f, -796.69379f, 24.978201f), 180.0f, &pChaseCars[3], 0, 0);
}
void CRecordDataForChase::CleanUpCarsForChaseScene(void)
{
- for (int i = 0; i < NUM_CHASE_CARS; i++)
- RemoveCarFromChase(i);
}
void CRecordDataForChase::RemoveCarFromChase(int32 i)
{
- if (!pChaseCars[i])
- return;
- CWorld::Remove(pChaseCars[i]);
- delete pChaseCars[i];
- pChaseCars[i] = nil;
}
CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i)
{
- CVehicle* pVehicle = pChaseCars[i];
- pChaseCars[i] = nil;
- pVehicle->SetStatus(STATUS_PHYSICS);
- return pVehicle;
+ return nil;
}
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 707f1d87..28b999f8 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -17,6 +17,7 @@
#include "ModelInfo.h"
#include "Object.h"
#include "Pad.h"
+#include "PedAttractor.h"
#include "Phones.h"
#include "Pickups.h"
#include "Plane.h"
@@ -47,7 +48,7 @@ CAutomobile *CReplay::pBuf1;
uint8 *CReplay::pBuf2;
CPlayerPed *CReplay::pBuf3;
uint8 *CReplay::pBuf4;
-CCutsceneHead *CReplay::pBuf5;
+CCutsceneObject *CReplay::pBuf5;
uint8 *CReplay::pBuf6;
CPtrNode *CReplay::pBuf7;
uint8 *CReplay::pBuf8;
@@ -510,8 +511,12 @@ void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayB
}
RetrievePedAnimation(ped, &pp->anim_state);
ped->RemoveWeaponModel(-1);
- if (pp->weapon_model != (uint8)-1)
- ped->AddWeaponModel(pp->weapon_model);
+ if (pp->weapon_model != (uint16)-1) {
+ if (CStreaming::HasModelLoaded(pp->weapon_model))
+ ped->AddWeaponModel(pp->weapon_model);
+ else
+ CStreaming::RequestModel(pp->weapon_model, 0);
+ }
CWorld::Remove(ped);
CWorld::Add(ped);
buffer->m_nOffset += sizeof(tPedUpdatePacket);
@@ -835,13 +840,14 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
CStreaming::RequestModel(mi, 0);
}
else {
+// TODO(MIAMI): don't hardcode model indices
if (mi == MI_DEADDODO || mi == MI_AIRTRAIN) {
new_v = new(vp->index << 8) CPlane(mi, 2);
}
else if (mi == MI_TRAIN) {
new_v = new(vp->index << 8) CTrain(mi, 2);
}
- else if (mi == MI_CHOPPER || mi == MI_ESCAPE) {
+ else if (mi == MI_CHOPPER) {
new_v = new(vp->index << 8) CHeli(mi, 2);
}
else if (CModelInfo::IsBoatModel(mi)){
@@ -1115,6 +1121,14 @@ void CReplay::StoreStuffInMem(void)
for (int i = 0; i < NUMPLAYERS; i++)
nHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed);
#endif
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i >= 0) {
+ CPed* ped = CPools::GetPedPool()->GetSlot(i);
+ if (!ped)
+ continue;
+ if (ped->m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(ped, ped->m_attractor);
+ }
CPools::GetVehiclePool()->Store(pBuf0, pBuf1);
CPools::GetPedPool()->Store(pBuf2, pBuf3);
CPools::GetObjectPool()->Store(pBuf4, pBuf5);
@@ -1210,6 +1224,16 @@ void CReplay::RestoreStuffFromMem(void)
ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped);
DMAudio.SetEntityStatus(ped->m_audioEntityId, true);
CPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false);
+ for (int j = 0; j < TOTAL_WEAPON_SLOTS; j++) {
+ int mi1 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModelId;
+ if (mi1 != -1)
+ CStreaming::RequestModel(mi1, STREAMFLAGS_DEPENDENCY);
+ int mi2 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModel2Id;
+ if (mi2 != -1)
+ CStreaming::RequestModel(mi2, STREAMFLAGS_DEPENDENCY);
+ CStreaming::LoadAllRequestedModels(false);
+ ped->m_weapons[j].Initialise(ped->m_weapons[j].m_eWeaponType, ped->m_weapons[j].m_nAmmoTotal);
+ }
if (ped->m_wepModelID >= 0)
ped->AddWeaponModel(ped->m_wepModelID);
}
diff --git a/src/control/Replay.h b/src/control/Replay.h
index 66bee3bf..b369c13d 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -176,7 +176,7 @@ class CReplay
CStoredAnimationState anim_state;
CCompressedMatrixNotAligned matrix;
int8 assoc_group_id;
- uint8 weapon_model;
+ uint16 weapon_model;
};
VALIDATE_SIZE(tPedUpdatePacket, 40);
@@ -214,7 +214,7 @@ private:
static uint8* pBuf2;
static CPlayerPed* pBuf3;
static uint8* pBuf4;
- static CCutsceneHead* pBuf5;
+ static CCutsceneObject* pBuf5;
static uint8* pBuf6;
static CPtrNode* pBuf7;
static uint8* pBuf8;
diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp
index 5a322cdb..64cabf5d 100644
--- a/src/control/Restart.cpp
+++ b/src/control/Restart.cpp
@@ -80,13 +80,13 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
return;
}
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ eLevelName curlevel = CTheZones::GetLevelFromPosition(&pos);
float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
- if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
+ if (CTheZones::GetLevelFromPosition(&HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
@@ -127,13 +127,13 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo
return;
}
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ eLevelName curlevel = CTheZones::GetLevelFromPosition(&pos);
float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
- if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
+ if (CTheZones::GetLevelFromPosition(&PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index 572f8134..0261cd4a 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -15,22 +15,23 @@
#include "CarCtrl.h"
#include "General.h"
-#define ROADBLOCKDIST (80.0f)
+#define ROADBLOCKDIST (90.0f)
int16 CRoadBlocks::NumRoadBlocks;
-int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS];
+int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];
bool CRoadBlocks::InOrOut[NUMROADBLOCKS];
+//--MIAMI: TODO
void
CRoadBlocks::Init(void)
{
int i;
NumRoadBlocks = 0;
- for (i = 0; i < ThePaths.m_numMapObjects; i++) {
- if (ThePaths.m_objectFlags[i] & UseInRoadBlock) {
+ for(i = 0; i < ThePaths.m_numCarPathNodes; i++){
+ if(ThePaths.m_pathNodes[i].bUseInRoadBlock && ThePaths.m_pathNodes[i].numLinks == 2){
if (NumRoadBlocks < NUMROADBLOCKS) {
InOrOut[NumRoadBlocks] = true;
- RoadBlockObjects[NumRoadBlocks] = i;
+ RoadBlockNodes[NumRoadBlocks] = i;
NumRoadBlocks++;
} else {
#ifndef MASTER
@@ -41,6 +42,8 @@ CRoadBlocks::Init(void)
}
}
}
+
+ // TODO(MIAMI): script roadblocks
}
void
@@ -102,6 +105,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
}
}
+//--MIAMI: TODO: implement this
void
CRoadBlocks::GenerateRoadBlocks(void)
{
@@ -110,14 +114,14 @@ CRoadBlocks::GenerateRoadBlocks(void)
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {
- CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]];
- CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
+ CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition();
if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST &&
vecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST &&
vecDistance.Magnitude() < ROADBLOCKDIST) {
if (!InOrOut[nRoadblockNode]) {
InOrOut[nRoadblockNode] = true;
if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
+#ifndef MIAMI
CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
int32 vehicleId = MI_POLICE;
@@ -187,10 +191,13 @@ CRoadBlocks::GenerateRoadBlocks(void)
}
}
}
+#endif
}
}
} else {
InOrOut[nRoadblockNode] = false;
}
}
+
+ // TODO(MIAMI): script roadblocks
}
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 0f0c1882..439fd6e7 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -7,7 +7,11 @@ class CRoadBlocks
{
public:
static int16 NumRoadBlocks;
+#ifndef MIAMI
static int16 RoadBlockObjects[NUMROADBLOCKS];
+#else
+ static int16 RoadBlockNodes[NUMROADBLOCKS];
+#endif
static bool InOrOut[NUMROADBLOCKS];
static void Init(void);
diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp
index be8c5519..f7dcaa3c 100644
--- a/src/control/SceneEdit.cpp
+++ b/src/control/SceneEdit.cpp
@@ -88,7 +88,7 @@ static int32 NextValidModelId(int32 mi, int32 step)
continue;
if (pInfo->GetModelType() == MITYPE_PED
#ifdef FIX_BUGS
- && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL04)
+ && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL21)
#endif
|| pInfo->GetModelType() == MITYPE_VEHICLE &&
#ifdef FIX_BUGS
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index e8aa3266..1ea68dd3 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -13,6 +13,7 @@
#include "CarGen.h"
#include "CivilianPed.h"
#include "Clock.h"
+#include "ColStore.h"
#include "CopPed.h"
#include "Coronas.h"
#include "Cranes.h"
@@ -53,15 +54,20 @@
#include "Remote.h"
#include "Replay.h"
#include "Restart.h"
+#include "RoadBlocks.h"
#include "RpAnimBlend.h"
#include "Rubbish.h"
+#include "SimpleModelInfo.h"
#include "Shadows.h"
#include "SpecialFX.h"
+#include "Sprite.h"
#include "Stats.h"
#include "Streaming.h"
#include "Text.h"
+#include "Timecycle.h"
#include "TxdStore.h"
#include "User.h"
+#include "VisibilityPlugins.h"
#include "WaterLevel.h"
#include "Weather.h"
#include "World.h"
@@ -69,7 +75,7 @@
#include "main.h"
#define PICKUP_PLACEMENT_OFFSET 0.5f
-#define PED_FIND_Z_OFFSET 5.0f
+#define PED_FIND_Z_OFFSET 10.0f
#define SPHERE_MARKER_R 0
#define SPHERE_MARKER_G 128
@@ -88,13 +94,10 @@
uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE];
CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS];
-int32 CTheScripts::BaseBriefIdForContact[MAX_NUM_CONTACTS];
-int32 CTheScripts::OnAMissionForContactFlag[MAX_NUM_CONTACTS];
intro_text_line CTheScripts::IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
intro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
CSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
script_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
-tCollectiveData CTheScripts::CollectiveArray[MAX_NUM_COLLECTIVES];
tUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS];
int32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
tBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@@ -115,8 +118,6 @@ uint16 CTheScripts::NumberOfMissionScripts;
uint32 CTheScripts::LargestMissionScriptSize;
uint32 CTheScripts::MainScriptSize;
uint8 CTheScripts::FailCurrentMission;
-uint8 CTheScripts::CountdownToMakePlayerUnsafe;
-uint8 CTheScripts::DelayMakingPlayerUnsafeThisTime;
uint16 CTheScripts::NumScriptDebugLines;
uint16 CTheScripts::NumberOfIntroRectanglesThisFrame;
uint16 CTheScripts::NumberOfIntroTextLinesThisFrame;
@@ -127,6 +128,11 @@ CStuckCarCheck CTheScripts::StuckCars;
uint16 CTheScripts::CommandsExecuted;
uint16 CTheScripts::ScriptsUpdated;
int32 ScriptParams[32];
+uint8 CTheScripts::RiotIntensity;
+uint32 CTheScripts::LastMissionPassedTime;
+uint16 CTheScripts::NumberOfExclusiveMissionScripts;
+bool CTheScripts::bPlayerHasMetDebbieHarry;
+bool CTheScripts::bPlayerIsInTheStatium;
const uint32 CRunningScript::nSaveStructSize =
@@ -170,10 +176,46 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type)
m_nCount++;
}
+static void PossiblyWakeThisEntity(CPhysical* pEntity)
+{
+ if (!pEntity->bIsStaticWaitingForCollision)
+ return;
+ if (CColStore::HasCollisionLoaded(pEntity->GetPosition())) {
+ pEntity->bIsStaticWaitingForCollision = false;
+ if (!pEntity->IsStatic())
+ pEntity->AddToMovingList();
+ }
+}
+
void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
{
for (int i = 0; i < MAX_CLEANUP; i++){
if (m_sEntities[i].type == type && m_sEntities[i].id == id){
+ switch (m_sEntities[i].type) {
+ case CLEANUP_CAR:
+ {
+ CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (v)
+ PossiblyWakeThisEntity(v);
+ break;
+ }
+ case CLEANUP_CHAR:
+ {
+ CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (p)
+ PossiblyWakeThisEntity(p);
+ break;
+ }
+ case CLEANUP_OBJECT:
+ {
+ CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (o)
+ PossiblyWakeThisEntity(o);
+ break;
+ }
+ default:
+ break;
+ }
m_sEntities[i].id = 0;
m_sEntities[i].type = CLEANUP_UNUSED;
m_nCount--;
@@ -181,14 +223,70 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
}
}
+void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObject()
+{
+ for (int i = 0; i < MAX_CLEANUP; i++) {
+ switch (m_sEntities[i].type) {
+ case CLEANUP_CAR:
+ {
+ CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (v)
+ PossiblyWakeThisEntity(v);
+ break;
+ }
+ case CLEANUP_CHAR:
+ {
+ CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (p)
+ PossiblyWakeThisEntity(p);
+ break;
+ }
+ case CLEANUP_OBJECT:
+ {
+ CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (o)
+ PossiblyWakeThisEntity(o);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i)
+{
+ if (m_sEntities[i].type == CLEANUP_CAR) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (pVehicle && pVehicle->GetStatus() != STATUS_WRECKED)
+ return pVehicle;
+ }
+ else if (m_sEntities[i].type == CLEANUP_CHAR) {
+ CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (pPed && !pPed->DyingOrDead())
+ return pPed;
+ }
+ return nil;
+}
+
void CMissionCleanup::Process()
{
CPopulation::m_AllRandomPedsThisType = -1;
CPopulation::PedDensityMultiplier = 1.0f;
CCarCtrl::CarDensityMultiplier = 1.0f;
+ CPed::nThreatReactionRangeMultiplier = 1;
+ CPed::nEnterCarRangeMultiplier = 1;
FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f;
- TheCamera.Restore();
+ //CRoadBlocks::ClearScriptRoadblocks() // TODO(MIAMI)
+ CRouteNode::Initialise();
+ if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
+ TheCamera.Restore();
TheCamera.SetWideScreenOff();
+ // TODO(MIAMI)
+ //CSpecialFX::bLiftCam = false;
+ //CSpecialFX::bVideoCam = false;
+ //CTimeCycle::StopExtraColour(0);
+ // TODO(MIAMI): change this to loop when it supports parameters
DMAudio.ClearMissionAudio();
CWeather::ReleaseWeather();
for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++)
@@ -197,11 +295,18 @@ void CMissionCleanup::Process()
CStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i);
CStreaming::ms_disableStreaming = false;
CHud::m_ItemToFlash = -1;
- CHud::SetHelpMessage(nil, false);
+ CHud::SetHelpMessage(nil, false); // TODO(MIAMI): third parameter is false
CUserDisplay::OnscnTimer.m_bDisabled = false;
+ CTheScripts::RemoveScriptTextureDictionary();
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false;
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CWorld::Players[0].MakePlayerSafe(false);
+ //TODO(MIAMI): drunkenness, enable drive by
+ //DMAudio::ShutUpPlayerTalking(0);
+ CVehicle::bDisableRemoteDetonation = false;
+ //CVehicle::bDisableRemoteDetonationOnContact = false; // TODO(MIAMI)
+ //CGameLogic::ClearShortCut(); // TODO(MIAMI)
+ CTheScripts::RiotIntensity = 0;
CTheScripts::StoreVehicleIndex = -1;
CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::UpsideDownCars.Init();
@@ -391,11 +496,11 @@ bool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id)
void CRunningScript::CollectParameters(uint32* pIp, int16 total)
{
for (int16 i = 0; i < total; i++){
- float tmp;
uint16 varIndex;
switch (CTheScripts::Read1ByteFromScript(pIp))
{
case ARGUMENT_INT32:
+ case ARGUMENT_FLOAT:
ScriptParams[i] = CTheScripts::Read4BytesFromScript(pIp);
break;
case ARGUMENT_GLOBALVAR:
@@ -414,10 +519,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
case ARGUMENT_INT16:
ScriptParams[i] = CTheScripts::Read2BytesFromScript(pIp);
break;
- case ARGUMENT_FLOAT:
- tmp = CTheScripts::ReadFloatFromScript(pIp);
- ScriptParams[i] = *(int32*)&tmp;
- break;
default:
assert(0);
break;
@@ -428,7 +529,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
{
uint32* pIp = &ip;
- float tmp;
switch (CTheScripts::Read1ByteFromScript(pIp))
{
case ARGUMENT_INT32:
@@ -442,8 +542,7 @@ int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
case ARGUMENT_INT16:
return CTheScripts::Read2BytesFromScript(pIp);
case ARGUMENT_FLOAT:
- tmp = CTheScripts::ReadFloatFromScript(pIp);
- return *(int32*)&tmp;
+ return CTheScripts::Read4BytesFromScript(pIp);
default:
assert(0);
}
@@ -504,9 +603,12 @@ void CRunningScript::Init()
}
#ifdef USE_DEBUG_SCRIPT_LOADER
+
+const char* scriptfile = "main.scm";
+
int open_script()
{
- static int scriptToLoad = 0;
+ static int scriptToLoad = 1;
#ifdef _WIN32
if (GetAsyncKeyState('G') & 0x8000)
@@ -517,11 +619,11 @@ int open_script()
scriptToLoad = 2;
#endif
switch (scriptToLoad) {
- case 0: return CFileMgr::OpenFile("main.scm", "rb");
- case 1: return CFileMgr::OpenFile("main_freeroam.scm", "rb");
- case 2: return CFileMgr::OpenFile("main_d.scm", "rb");
+ case 0: scriptfile = "main.scm"; break;
+ case 1: scriptfile = "freeroam_miami.scm"; break;
+ case 2: scriptfile = "main_d.scm"; break;
}
- return CFileMgr::OpenFile("main.scm", "rb");
+ return CFileMgr::OpenFile(scriptfile, "rb");
}
#endif
@@ -549,14 +651,7 @@ void CTheScripts::Init()
StoreVehicleIndex = -1;
StoreVehicleWasRandom = true;
OnAMissionFlag = 0;
- for (int i = 0; i < MAX_NUM_CONTACTS; i++){
- BaseBriefIdForContact[i] = 0;
- OnAMissionForContactFlag[i] = 0;
- }
- for (int i = 0; i < MAX_NUM_COLLECTIVES; i++){
- CollectiveArray[i].index = -1;
- CollectiveArray[i].unk_data = 0;
- }
+ LastMissionPassedTime = (uint32)-1;
NextFreeCollectiveIndex = 0;
LastRandomPedId = -1;
for (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){
@@ -570,15 +665,17 @@ void CTheScripts::Init()
bUsingAMultiScriptFile = true;
for (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++)
MultiScriptArray[i] = 0;
+ NumberOfExclusiveMissionScripts = 0;
NumberOfMissionScripts = 0;
LargestMissionScriptSize = 0;
MainScriptSize = 0;
ReadMultiScriptFileOffsetsFromScript();
FailCurrentMission = 0;
- CountdownToMakePlayerUnsafe = 0;
DbgFlag = false;
- DelayMakingPlayerUnsafeThisTime = 1;
NumScriptDebugLines = 0;
+ RiotIntensity = 0;
+ bPlayerHasMetDebbieHarry = false;
+ bPlayerIsInTheStatium = false;
for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){
ScriptSphereArray[i].m_bInUse = false;
ScriptSphereArray[i].m_Index = 1;
@@ -599,6 +696,7 @@ void CTheScripts::Init()
IntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255);
}
NumberOfIntroRectanglesThisFrame = 0;
+ RemoveScriptTextureDictionary();
for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){
BuildingSwapArray[i].m_pBuilding = nil;
BuildingSwapArray[i].m_nNewModel = -1;
@@ -608,6 +706,15 @@ void CTheScripts::Init()
InvisibilitySettingArray[i] = nil;
}
+void CTheScripts::RemoveScriptTextureDictionary()
+{
+ for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)
+ CTheScripts::ScriptSprites[i].Delete();
+ int slot = CTxdStore::FindTxdSlot("script");
+ if (slot != -1)
+ CTxdStore::RemoveTxd(slot);
+}
+
void CRunningScript::RemoveScriptFromList(CRunningScript** ppScript)
{
if (prev)
@@ -647,13 +754,10 @@ void CTheScripts::Process()
float timeStep = CTimer::GetTimeStepInMilliseconds();
UpsideDownCars.UpdateTimers();
StuckCars.Process();
+ MissionCleanup.CheckIfCollisionHasLoadedForMissionObject();
DrawScriptSpheres();
if (FailCurrentMission)
--FailCurrentMission;
- if (CountdownToMakePlayerUnsafe){
- if (--CountdownToMakePlayerUnsafe == 0)
- CWorld::Players[0].MakePlayerSafe(false);
- }
if (UseTextCommands){
for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++)
IntroTextLines[i].Reset();
@@ -737,15 +841,16 @@ int8 CRunningScript::ProcessOneCommand()
return ProcessCommands800To899(command);
if (command < 1000)
return ProcessCommands900To999(command);
-#ifdef GTA_PS2
- if (command < 1200)
- return ProcessCommands1000To1099(command);
-#else
if (command < 1100)
return ProcessCommands1000To1099(command);
if (command < 1200)
return ProcessCommands1100To1199(command);
-#endif
+ if (command < 1300)
+ return ProcessCommands1200To1299(command);
+ if (command < 1400)
+ return ProcessCommands1300To1399(command);
+ if (command < 1500)
+ return ProcessCommands1400To1499(command);
return -1;
}
@@ -1173,13 +1278,11 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
UpdateCompareFlag(*ptr1 == *ptr2);
return 0;
}
- /* Following commands are not implemented, and go to default case
- case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR:
- case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR:
- case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR:
- */
+ //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR:
+ //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR:
+ //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR:
case COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER:
{
int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
@@ -1215,19 +1318,18 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
UpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2);
return 0;
}
- /* Following commands are not implemented, and go to default case
- case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR:
- case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR:
- case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR:
- */
+ //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR:
+ //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR:
+ //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR:
+ /*
case COMMAND_GOTO_IF_TRUE:
CollectParameters(&m_nIp, 1);
if (m_bCondResult)
SetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);
- /* Check COMMAND_GOTO note. */
return 0;
+ */
case COMMAND_GOTO_IF_FALSE:
CollectParameters(&m_nIp, 1);
if (!m_bCondResult)
@@ -1239,12 +1341,14 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
CTheScripts::bAlreadyRunningAMissionScript = false;
RemoveScriptFromList(&CTheScripts::pActiveScripts);
AddScriptToList(&CTheScripts::pIdleScripts);
+ m_bIsActive = false;
return 1;
case COMMAND_START_NEW_SCRIPT:
{
CollectParameters(&m_nIp, 1);
assert(ScriptParams[0] >= 0);
CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]);
+ m_bIsActive = true;
int8 type = CTheScripts::Read1ByteFromScript(&m_nIp);
float tmp;
for (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) {
@@ -1292,7 +1396,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
{
CollectParameters(&m_nIp, 4);
int32 index = ScriptParams[0];
- assert(index < 1); /* Constant? Also no more double player glitch */
+ assert(index < NUMPLAYERS);
printf("&&&&&&&&&&&&&Creating player: %d\n", index);
if (!CStreaming::HasModelLoaded(MI_PLAYER)) {
CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
@@ -1332,20 +1436,49 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
CPlayerPed* ped = CWorld::Players[index].m_pPed;
- if (!ped->bInVehicle) {
- pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
- ped->Teleport(pos);
- CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (ped->bInVehicle) {
+ pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
+ ped->m_pMyVehicle->Teleport(pos); // removed dumb stuff that was present here
+ CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle);
return 0;
}
- pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
- if (ped->m_pMyVehicle->IsBoat())
- ped->m_pMyVehicle->Teleport(pos);
- else
- ped->m_pMyVehicle->Teleport(pos);
- /* I'll keep this condition here but obviously it is absolutely pointless */
- /* It's clearly present in disassembly so it had to be in original code */
- CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle);
+ pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
+ CVector vOldPos = ped->GetPosition();
+ ped->Teleport(pos);
+ CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (ped) { // great time to check
+ for (int i = 0; i < ped->m_numNearPeds; i++) {
+ CPed* pTestedPed = ped->m_nearPeds[i];
+ if (!pTestedPed || !IsPedPointerValid(pTestedPed))
+ continue;
+ if (pTestedPed->m_pedInObjective == ped && pTestedPed->m_objective == OBJ_15) {
+ CVector vFollowerPos = pTestedPed->GetFormationPosition();
+ CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);
+ bool bFound = false;
+ vFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f;
+ if (bFound) {
+ if (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) {
+ pTestedPed->Teleport(vFollowerPos);
+ }
+ }
+ }
+ else if (pTestedPed->m_leader == ped) {
+ CVector vFollowerPos;
+ if (pTestedPed->m_pedFormation)
+ vFollowerPos = pTestedPed->GetFormationPosition();
+ else
+ vFollowerPos = ped->GetPosition() + pTestedPed->GetPosition() - vOldPos;
+ CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);
+ bool bFound = false;
+ vFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f;
+ if (bFound) {
+ if (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) {
+ pTestedPed->Teleport(vFollowerPos);
+ }
+ }
+ }
+ }
+ }
return 0;
}
case COMMAND_IS_PLAYER_IN_AREA_2D:
@@ -1767,6 +1900,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->CharCreatedBy = MISSION_CHAR;
ped->bRespondsToThreats = false;
ped->bAllowMedicsToReviveMe = false;
+ ped->bIsPlayerFriend = false;
CVector pos = *(CVector*)&ScriptParams[2];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -1774,6 +1908,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->SetPosition(pos);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (m_bIsMissionScript)
+ ped->bIsStaticWaitingForCollision = true;
CWorld::Add(ped);
ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
CPopulation::ms_nTotalMissionPeds++;
@@ -1787,24 +1923,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- if (ped) {
- if (ped->InVehicle()) {
- if (ped->m_pMyVehicle->pDriver == ped) {
- ped->m_pMyVehicle->RemoveDriver();
- ped->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- if (ped->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- ped->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- if (ped->m_nPedType == PEDTYPE_COP && ped->m_pMyVehicle->IsLawEnforcementVehicle())
- ped->m_pMyVehicle->ChangeLawEnforcerState(0);
- }
- else {
- ped->m_pMyVehicle->RemovePassenger(ped);
- }
- }
- CWorld::RemoveReferencesToDeletedObject(ped);
- delete ped;
- --CPopulation::ms_nTotalMissionPeds;
- }
+ CTheScripts::RemoveThisPed(ped);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
@@ -1821,19 +1940,26 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->SetWanderPath(path);
return 0;
}
- /* Not implemented.
- case COMMAND_CHAR_WANDER_RANGE:
- */
+ //case COMMAND_CHAR_WANDER_RANGE:
case COMMAND_CHAR_FOLLOW_PATH:
{
- CollectParameters(&m_nIp, 4);
+ CollectParameters(&m_nIp, 6);
CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
assert(ped);
+ if (ped->GetPedState() == PED_ATTACK || ped->GetPedState() == PED_FIGHT || !ped->IsPedInControl())
+ return 0;
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = *(float*)&ScriptParams[4];
+ eMoveState state;
+ switch (ScriptParams[5]) {
+ case 0: state = PEDMOVE_WALK;
+ case 1: state = PEDMOVE_SPRINT;
+ default: assert(0);
+ }
ped->ClearAll();
- ped->SetFollowPath(pos);
+ ped->SetFollowPath(pos, radius, state, nil, nil, 999999);
return 0;
}
case COMMAND_CHAR_SET_IDLE:
@@ -1878,44 +2004,27 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- /* The following block was once again written
- * by someone not familiar with virtual functions.
- * It doesn't require any ifs at all.
- * To keep as close to original as possible, I'll keep it.
- * Maybe there was more commented out/debug
- * stuff, but I doubt it.
- */
+ // removed dumb stuff again
if (!vehicle) {
pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
ped->Teleport(pos);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
- }
- else if (vehicle->IsBoat()) {
- pos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel();
- vehicle->Teleport(pos);
- CTheScripts::ClearSpaceForMissionEntity(pos, vehicle);
+ for (int i = 0; i < ped->m_numNearPeds; i++) {
+ CPed* pNearPed = ped->m_nearPeds[i];
+ if (pNearPed->m_leader == ped) {
+ pNearPed->Teleport(pos);
+ pNearPed->PositionPedOutOfCollision(); // TODO(MIAMI): this is PositionAnyPedOutOfCollision!!!
+ }
+ }
}
else {
pos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel();
vehicle->Teleport(pos);
CTheScripts::ClearSpaceForMissionEntity(pos, vehicle);
}
- /* Short version of this command.
- *
- * CollectParameters(&m_nIp, 4);
- * CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- * assert(ped);
- * CEntity* entityToMove = ped->bInVehicle ? ped->m_pMyVehicle : ped;
- * CVector pos = *(CVector*)&ScriptParams[1];
- * if (pos.z <= MAP_Z_LOW_LIMIT)
- * pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- * pos.z += entityToMove->GetDistanceFromCentreOfMassToBaseOfModel();
- * entityToMove->Teleport(pos);
- * CTheScripts::ClearSpaceForMissionEntity(pos, entityToMove);
- *
- */
return 0;
}
+ /*
case COMMAND_IS_CHAR_STILL_ALIVE:
{
CollectParameters(&m_nIp, 1);
@@ -1923,6 +2032,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
UpdateCompareFlag(ped && ped->GetPedState() != PED_DEAD && ped->GetPedState() != PED_DIE);
return 0;
}
+ */
case COMMAND_IS_CHAR_IN_AREA_2D:
{
CollectParameters(&m_nIp, 6);
@@ -1990,15 +2100,19 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
boat->SetStatus(STATUS_ABANDONED);
boat->bIsLocked = true;
boat->AutoPilot.m_nCarMission = MISSION_NONE;
- boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
+ boat->AutoPilot.m_nTempAction = TEMPACT_NONE;
boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f;
+ if (m_bIsMissionScript)
+ boat->bIsStaticWaitingForCollision = true;
CWorld::Add(boat);
handle = CPools::GetVehiclePool()->GetIndex(boat);
}
else {
CVehicle* car;
- if (!CModelInfo::IsBikeModel(ScriptParams[0]))
- car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE);
+
+ // TODO(MIAMI)
+ //if (!CModelInfo::IsBikeModel(ScriptParams[0]))
+ car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE);
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -2009,13 +2123,15 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
car->bIsLocked = true;
CCarCtrl::JoinCarWithRoadSystem(car);
car->AutoPilot.m_nCarMission = MISSION_NONE;
- car->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
+ car->AutoPilot.m_nTempAction = TEMPACT_NONE;
car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;
car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0;
car->bEngineOn = false;
car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
car->bHasBeenOwnedByPlayer = true;
+ if (m_bIsMissionScript)
+ car->bIsStaticWaitingForCollision = true;
CWorld::Add(car);
handle = CPools::GetVehiclePool()->GetIndex(car);
}
@@ -2137,6 +2253,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
}
return 0;
}
+ /*
case COMMAND_IS_CAR_STILL_ALIVE:
{
CollectParameters(&m_nIp, 1);
@@ -2144,6 +2261,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
UpdateCompareFlag(car && car->GetStatus() != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater));
return 0;
}
+ */
case COMMAND_SET_CAR_CRUISE_SPEED:
{
CollectParameters(&m_nIp, 2);
@@ -2218,32 +2336,28 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
return 0;
case COMMAND_PRINT_BIG:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddBigMessage(key, ScriptParams[0], ScriptParams[1] - 1);
return 0;
}
case COMMAND_PRINT:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddMessage(key, ScriptParams[0], ScriptParams[1]);
return 0;
}
case COMMAND_PRINT_NOW:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddMessageJumpQ(key, ScriptParams[0], ScriptParams[1]);
return 0;
}
case COMMAND_PRINT_SOON:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddMessageSoon(key, ScriptParams[0], ScriptParams[1]);
return 0;
@@ -2280,15 +2394,15 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
case COMMAND_DEBUG_OFF:
CTheScripts::DbgFlag = false;
return 0;
+ /*
case COMMAND_RETURN_TRUE:
UpdateCompareFlag(true);
return 0;
case COMMAND_RETURN_FALSE:
UpdateCompareFlag(false);
return 0;
- /* Special command only used by compiler.
- case COMMAND_VAR_INT:
*/
+ //case COMMAND_VAR_INT:
default:
assert(0);
break;
@@ -2341,8 +2455,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
if (!m_bIsMissionScript)
return 0;
- if (strcmp(m_abScriptName, "love3") == 0) /* A Drop in the Ocean */
- CPickups::RemoveAllFloatingPickups();
CTheScripts::MissionCleanup.Process();
return 0;
}
@@ -2485,29 +2597,23 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(pPed->bInVehicle);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle);
return 0;
}
case COMMAND_IS_PLAYER_IN_ANY_CAR:
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- UpdateCompareFlag(pPed->bInVehicle);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle);
return 0;
}
case COMMAND_IS_BUTTON_PRESSED:
{
CollectParameters(&m_nIp, 2);
- bool value = GetPadState(ScriptParams[0], ScriptParams[1]) != 0;
- if (CGame::playingIntro && ScriptParams[0] == 0 && ScriptParams[1] == 12) {
- if (CPad::GetPad(0)->GetLeftMouseJustDown() ||
- CPad::GetPad(0)->GetEnterJustDown() ||
- CPad::GetPad(0)->GetCharJustDown(' '))
- value = true;
- }
- UpdateCompareFlag(value);
+ UpdateCompareFlag(GetPadState(ScriptParams[0], ScriptParams[1]) != 0);
return 0;
}
+ /*
case COMMAND_GET_PAD_STATE:
{
CollectParameters(&m_nIp, 1);
@@ -2515,6 +2621,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D:
case COMMAND_LOCATE_PLAYER_ON_FOOT_2D:
case COMMAND_LOCATE_PLAYER_IN_CAR_2D:
@@ -2581,6 +2688,9 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pObj->SetOrientation(0.0f, 0.0f, 0.0f);
pObj->GetMatrix().UpdateRW();
pObj->UpdateRwFrame();
+ CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi);
+ if (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding)
+ pObj->SetupBigBuilding();
CTheScripts::ClearSpaceForMissionEntity(pos, pObj);
CWorld::Add(pObj);
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
@@ -2605,6 +2715,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
case COMMAND_ADD_SCORE:
CollectParameters(&m_nIp, 2);
CWorld::Players[ScriptParams[0]].m_nMoney += ScriptParams[1];
+ if (CWorld::Players[ScriptParams[0]].m_nMoney < 0)
+ CWorld::Players[ScriptParams[0]].m_nMoney = 0;
return 0;
case COMMAND_IS_SCORE_GREATER:
CollectParameters(&m_nIp, 2);
@@ -2647,12 +2759,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
case COMMAND_HAS_DEATHARREST_BEEN_EXECUTED:
UpdateCompareFlag(m_bDeatharrestExecuted);
return 0;
+ /*
case COMMAND_ADD_AMMO_TO_PLAYER:
{
CollectParameters(&m_nIp, 3);
CWorld::Players[ScriptParams[0]].m_pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
return 0;
}
+ */
case COMMAND_ADD_AMMO_TO_CHAR:
{
CollectParameters(&m_nIp, 3);
@@ -2661,10 +2775,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
return 0;
}
- /* Not implemented
- case COMMAND_ADD_AMMO_TO_CAR:
- case COMMAND_IS_PLAYER_STILL_ALIVE:
- */
+ //case COMMAND_ADD_AMMO_TO_CAR:
+ //case COMMAND_IS_PLAYER_STILL_ALIVE:
case COMMAND_IS_PLAYER_DEAD:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_WASTED);
@@ -2673,14 +2785,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(!pPed || pPed->GetPedState() == PED_DIE || pPed->GetPedState() == PED_DEAD);
+ UpdateCompareFlag(!pPed || pPed->DyingOrDead());
return 0;
}
case COMMAND_IS_CAR_DEAD:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || !pVehicle->IsBoat() && pVehicle->bIsInWater);
+ UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->bIsDrowning);
return 0;
}
case COMMAND_SET_CHAR_THREAT_SEARCH:
@@ -2691,9 +2803,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->m_fearFlags |= ScriptParams[1];
return 0;
}
- /* Not implemented.
- case COMMAND_SET_CHAR_THREAT_REACTION:
- */
+ //case COMMAND_SET_CHAR_THREAT_REACTION:
case COMMAND_SET_CHAR_OBJ_NO_OBJ:
{
CollectParameters(&m_nIp, 1);
@@ -2703,23 +2813,21 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->ClearObjective();
return 0;
}
- /* Not implemented.
- case COMMAND_ORDER_DRIVER_OUT_OF_CAR:
- case COMMAND_ORDER_CHAR_TO_DRIVE_CAR:
- case COMMAND_ADD_PATROL_POINT:
- case COMMAND_IS_PLAYER_IN_GANGZONE:
- */
+ //case COMMAND_ORDER_DRIVER_OUT_OF_CAR:
+ //case COMMAND_ORDER_CHAR_TO_DRIVE_CAR:
+ //case COMMAND_ADD_PATROL_POINT:
+ //case COMMAND_IS_PLAYER_IN_GANGZONE:
case COMMAND_IS_PLAYER_IN_ZONE:
{
CollectParameters(&m_nIp, 1);
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);
if (zoneToCheck != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT; /* why only if zone != 1? */
CVector pos = pPlayer->GetPos();
- CZone* pZone = CTheZones::GetZone(zoneToCheck);
+ CZone* pZone = CTheZones::GetNavigationZone(zoneToCheck);
UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, pZone));
return 0;
}
@@ -2727,8 +2835,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_pPed->GetPedState() == PED_DRIVING &&
CPad::GetPad(ScriptParams[0])->GetHorn());
- /* Is it correct that same parameter is used both as index of Players */
- /* and as ID of pad? Pratically this parameter is always 0 anyway of course. */
return 0;
case COMMAND_HAS_CHAR_SPOTTED_PLAYER:
{
@@ -2738,10 +2844,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
UpdateCompareFlag(pPed->OurPedCanSeeThisOne(CWorld::Players[ScriptParams[1]].m_pPed));
return 0;
}
- /* Not implemented.
- case COMMAND_ORDER_CHAR_TO_BACKDOOR:
- case COMMAND_ADD_CHAR_TO_GANG:
- */
+ //case COMMAND_ORDER_CHAR_TO_BACKDOOR:
+ //case COMMAND_ADD_CHAR_TO_GANG:
case COMMAND_IS_CHAR_OBJECTIVE_PASSED:
{
CollectParameters(&m_nIp, 1);
@@ -2797,6 +2901,9 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->CharCreatedBy = MISSION_CHAR;
pPed->bRespondsToThreats = false;
pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
pPed->SetPosition(pVehicle->GetPosition());
pPed->SetOrientation(0.0f, 0.0f, 0.0f);
pPed->SetPedState(PED_DRIVING);
@@ -2812,13 +2919,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
pVehicle->bEngineOn = true;
pPed->bUsesCollision = false;
-#ifdef FIX_BUGS
- AnimationId anim = pVehicle->GetDriverAnim();
-#else
- AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT;
-#endif
- pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f);
- pPed->StopNonPartialAnims();
+ pPed->AddInCarAnims(pVehicle, true);
pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
CWorld::Add(pPed);
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
@@ -2852,7 +2953,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPlayer->m_pPed->SetPedState(PED_IDLE);
pPlayer->m_pPed->bUsesCollision = true;
pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pPlayer->m_pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPlayer->m_pPed->GetWeapon()->m_eWeaponType)->m_nModelId);
+ pPlayer->m_pPed->ReplaceWeaponWhenExitingVehicle();
pPlayer->m_pPed->RemoveInCarAnims();
if (pPlayer->m_pPed->m_pVehicleAnim)
pPlayer->m_pPed->m_pVehicleAnim->blendDelta = -1000.0f;
@@ -2866,9 +2967,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayer->m_pPed);
return 0;
}
- /* Not implemented.
- case COMMAND_MAKE_CHAR_DO_NOTHING:
- */
+ //case COMMAND_MAKE_CHAR_DO_NOTHING:
default:
assert(0);
break;
@@ -3044,18 +3143,27 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_SET_ZONE_CAR_INFO:
{
char label[12];
+ int16 gangDensities[NUM_GANGS] = { 0 };
+ int i;
+
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 16);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ CollectParameters(&m_nIp, 12);
+ for (i = 0; i < NUM_GANGS; i++)
+ gangDensities[i] = ScriptParams[i + 2];
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ for (int i = 0; i < NUM_GANGS; i++) {
+ if (gangDensities[i] != 0 && CGangs::GetGangInfo(i)->m_nVehicleMI == -1)
+ debug("SET_ZONE_CAR_INFO - Gang %d car ratio should be 0 in %s zone\n", i + 1, label);
+ }
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
}
- CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0,
- ScriptParams[9], ScriptParams[10], ScriptParams[11], ScriptParams[12],
- ScriptParams[13], ScriptParams[14], ScriptParams[15]);
+ while (zone >= 0) {
+ CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[11], gangDensities);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
return 0;
}
/* Not implemented.
@@ -3068,41 +3176,17 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
assert(pPed);
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);
if (zone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetZone(zone)));
+ UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetNavigationZone(zone)));
return 0;
}
+ /* Not implemented.
case COMMAND_SET_CAR_DENSITY:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- m_nIp += 8;
- CollectParameters(&m_nIp, 2);
- if (zone < 0) {
- debug("Couldn't find zone - %s\n", label);
- return 0;
- }
- CTheZones::SetCarDensity(zone, ScriptParams[0], ScriptParams[1]);
- return 0;
- }
case COMMAND_SET_PED_DENSITY:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 2);
- if (zone < 0) {
- debug("Couldn't find zone - %s\n", label);
- return 0;
- }
- CTheZones::SetPedDensity(zone, ScriptParams[0], ScriptParams[1]);
- return 0;
- }
+ */
case COMMAND_POINT_CAMERA_AT_PLAYER:
{
CollectParameters(&m_nIp, 3);
@@ -3137,14 +3221,17 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 10);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ CollectParameters(&m_nIp, 12);
+ int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
}
- CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, ScriptParams[9]);
+ while (zone >= 0) {
+ CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
+ ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
return 0;
}
case COMMAND_SET_TIME_SCALE:
@@ -3429,14 +3516,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_DECLARE_MISSION_FLAG:
CTheScripts::OnAMissionFlag = CTheScripts::Read2BytesFromScript(&++m_nIp);
return 0;
- case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
- CollectParameters(&m_nIp, 1);
- CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = CTheScripts::Read2BytesFromScript(&++m_nIp);
- return 0;
- case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:
- CollectParameters(&m_nIp, 2);
- CTheScripts::BaseBriefIdForContact[ScriptParams[0]] = ScriptParams[1];
- return 0;
+ //case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
+ //case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:
case COMMAND_IS_PLAYER_HEALTH_GREATER:
{
CollectParameters(&m_nIp, 2);
@@ -3751,13 +3832,8 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
if (ScriptParams[1]){
- if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){
- CTheScripts::CountdownToMakePlayerUnsafe = 50;
- if (CTheScripts::DelayMakingPlayerUnsafeThisTime)
- CTheScripts::DelayMakingPlayerUnsafeThisTime--;
- }else{
- pPlayer->MakePlayerSafe(false);
- }
+ pPlayer->MakePlayerSafe(false);
+ // TODO(MIAMI): Four Iron hack
}else{
pPlayer->MakePlayerSafe(true);
if (strcmp(m_abScriptName, "camera") == 0){
@@ -3783,7 +3859,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
{
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++){
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++){
if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
pPed->m_nSelectedWepSlot = i;
}
@@ -3793,7 +3869,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
{
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
pPed->SetCurrentWeapon(i);
}
@@ -4003,13 +4079,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetPedState(PED_DRIVING);
pVehicle->SetStatus(STATUS_PHYSICS);
pPed->bUsesCollision = false;
-#ifdef FIX_BUGS
- AnimationId anim = pVehicle->GetDriverAnim();
-#else
- AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT;
-#endif
- pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f);
- pPed->StopNonPartialAnims();
+ pPed->AddInCarAnims(pVehicle, false);
pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
CWorld::Add(pPed);
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
@@ -4637,51 +4707,31 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
}
case COMMAND_SET_GARAGE:
{
- CollectParameters(&m_nIp, 7);
+ CollectParameters(&m_nIp, 9);
float infX = *(float*)&ScriptParams[0];
float infY = *(float*)&ScriptParams[1];
float infZ = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- float supZ = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[0];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[1];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[2];
- }
- ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], 0);
+ float X2 = *(float*)&ScriptParams[3];
+ float Y2 = *(float*)&ScriptParams[4];
+ float supX = *(float*)&ScriptParams[5];
+ float supY = *(float*)&ScriptParams[6];
+ float supZ = *(float*)&ScriptParams[7];
+ ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, (eGarageType)ScriptParams[8], 0);
StoreParameters(&m_nIp, 1);
return 0;
}
case COMMAND_SET_GARAGE_WITH_CAR_MODEL:
{
- CollectParameters(&m_nIp, 8);
+ CollectParameters(&m_nIp, 10);
float infX = *(float*)&ScriptParams[0];
float infY = *(float*)&ScriptParams[1];
float infZ = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- float supZ = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[0];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[1];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[2];
- }
- ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], ScriptParams[7]);
+ float X2 = *(float*)&ScriptParams[3];
+ float Y2 = *(float*)&ScriptParams[4];
+ float supX = *(float*)&ScriptParams[5];
+ float supY = *(float*)&ScriptParams[6];
+ float supZ = *(float*)&ScriptParams[7];
+ ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, (eGarageType)ScriptParams[8], ScriptParams[9]);
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -4764,7 +4814,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
assert(pPed);
- pPed->m_fHealth = ScriptParams[1];
+ pPed->m_fHealth = Min(ScriptParams[1], CWorld::Players[ScriptParams[0]].m_nMaxHealth);
return 0;
}
case COMMAND_SET_CHAR_HEALTH:
@@ -4950,7 +5000,10 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
//case COMMAND_SET_GANG_ATTITUDE:
//case COMMAND_SET_GANG_GANG_ATTITUDE:
//case COMMAND_SET_GANG_PLAYER_ATTITUDE:
- //case COMMAND_SET_GANG_PED_MODELS:
+ case COMMAND_SET_GANG_PED_MODELS:
+ CollectParameters(&m_nIp, 3);
+ CGangs::SetGangPedModels(ScriptParams[0], ScriptParams[1], ScriptParams[2]);
+ return 0;
case COMMAND_SET_GANG_CAR_MODEL:
CollectParameters(&m_nIp, 2);
CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]);
@@ -5188,12 +5241,8 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true);
return 0;
}
- case COMMAND_STORE_WEATHER:
- CWeather::StoreWeatherState();
- return 0;
- case COMMAND_RESTORE_WEATHER:
- CWeather::RestoreWeatherState();
- return 0;
+ //case COMMAND_STORE_WEATHER:
+ //case COMMAND_RESTORE_WEATHER:
case COMMAND_STORE_CLOCK:
CClock::StoreClock();
return 0;
@@ -5325,8 +5374,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
assert(pVehicle);
- int mi = pVehicle->GetModelIndex();
- UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE);
+ UpdateCompareFlag(pVehicle->IsTaxi());
return 0;
}
case COMMAND_UNLOAD_SPECIAL_CHARACTER:
@@ -5870,8 +5918,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pPed->bFadeOut)
continue;
- if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
- continue;
+// if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+// continue;
if (!ThisIsAValidRandomPed(pPed->m_nPedType))
continue;
if (pPed->bIsLeader || pPed->m_leader)
@@ -5898,10 +5946,10 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
{
char zone[KEY_LENGTH_IN_SCRIPT];
strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (nZone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
+ CZone* pZone = CTheZones::GetNavigationZone(nZone);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
int i = CPools::GetPedPool()->GetSize();
@@ -5919,8 +5967,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pPed->bFadeOut)
continue;
- if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
- continue;
+// if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+// continue;
if (!ThisIsAValidRandomPed(pPed->m_nPedType))
continue;
if (pPed->bIsLeader || pPed->m_leader)
@@ -6142,25 +6190,12 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
}
case COMMAND_CREATE_CUTSCENE_HEAD:
{
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- assert(pObject);
- CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]);
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead);
- StoreParameters(&m_nIp, 1);
+ assert(0);
return 0;
}
case COMMAND_SET_CUTSCENE_HEAD_ANIM:
{
- CollectParameters(&m_nIp, 1);
- CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- assert(pCutHead);
- char name[KEY_LENGTH_IN_SCRIPT];
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CTimer::Stop();
- CCutsceneMgr::SetHeadAnim(name, pCutHead);
- CTimer::Update();
+ assert(0);
return 0;
}
case COMMAND_SIN:
@@ -6506,7 +6541,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
m_nIp += KEY_LENGTH_IN_SCRIPT;
CollectParameters(&m_nIp, 2);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_INFO);
if (zone_id < 0) {
printf("Couldn't find zone - %s\n", zone);
return 0;
@@ -6566,10 +6601,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
{
char zone[KEY_LENGTH_IN_SCRIPT];
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+// TODO(MIAMI): just getting this to compile with new argument
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (zone_id != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
+ CZone* pZone = CTheZones::GetNavigationZone(zone_id);
CollectParameters(&m_nIp, 1);
int handle = -1;
uint32 i = CPools::GetVehiclePool()->GetSize();
@@ -6972,28 +7008,16 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
if (pPed && pPed->CharCreatedBy == MISSION_CHAR){
CWorld::RemoveReferencesToDeletedObject(pPed);
- if (pPed->bInVehicle){
- if (pPed->m_pMyVehicle){
- if (pPed == pPed->m_pMyVehicle->pDriver){
- pPed->m_pMyVehicle->RemoveDriver();
- pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle())
- pPed->m_pMyVehicle->ChangeLawEnforcerState(0);
- }else{
- pPed->m_pMyVehicle->RemovePassenger(pPed);
- }
- }
- delete pPed;
- --CPopulation::ms_nTotalMissionPeds;
- }else{
+ if (pPed->bInVehicle && pPed->m_pMyVehicle)
+ CTheScripts::RemoveThisPed(pPed);
+ else{
pPed->CharCreatedBy = RANDOM_CHAR;
pPed->bRespondsToThreats = true;
pPed->bScriptObjectiveCompleted = false;
pPed->ClearLeader();
--CPopulation::ms_nTotalMissionPeds;
pPed->bFadeOut = true;
+ CWorld::RemoveReferencesToDeletedObject(pPed);
}
}
if (m_bIsMissionScript)
@@ -7080,10 +7104,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
char zone[KEY_LENGTH_IN_SCRIPT];
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+// TODO(MIAMI): just getting this to compile with new argument
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (zone_id != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
+ CZone* pZone = CTheZones::GetNavigationZone(zone_id);
UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));
return 0;
@@ -7103,12 +7128,13 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
}
case COMMAND_CREATE_FLOATING_PACKAGE:
{
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
- ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0);
- StoreParameters(&m_nIp, 1);
+// removed in MIAMI
+// CollectParameters(&m_nIp, 3);
+// CVector pos = *(CVector*)&ScriptParams[0];
+// if (pos.z <= MAP_Z_LOW_LIMIT)
+// pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+// ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0);
+// StoreParameters(&m_nIp, 1);
return 0;
}
case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:
@@ -7137,7 +7163,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
assert(pPlayerPed);
- pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
+ pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, CWorld::Players[ScriptParams[0]].m_nMaxArmour);
return 0;
}
case COMMAND_ADD_ARMOUR_TO_CHAR:
@@ -7188,7 +7214,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->m_nLastPedState = PED_NONE;
pPed->bUsesCollision = true;
pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);
+ pPed->ReplaceWeaponWhenExitingVehicle();
pPed->RemoveInCarAnims();
if (pPed->m_pVehicleAnim)
pPed->m_pVehicleAnim->blendDelta = -1000.0f;
@@ -7215,7 +7241,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
if (total == 0)
CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_NONE), pos, range, true, &total, 16, apEntities);
if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities);
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, range, true, &total, 16, apEntities);
CEntity* pClosestEntity = nil;
float min_dist = 2.0f * range;
for (int i = 0; i < total; i++) {
@@ -7399,6 +7425,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
ped->SetPosition(pos);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (m_bIsMissionScript)
+ ped->bIsStaticWaitingForCollision = true;
CWorld::Add(ped);
ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
CPopulation::ms_nTotalMissionPeds++;
@@ -7686,9 +7714,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
}
case COMMAND_REMOVE_TEXTURE_DICTIONARY:
{
- for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)
- CTheScripts::ScriptSprites[i].Delete();
- CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script"));
+ CTheScripts::RemoveScriptTextureDictionary();
return 0;
}
case COMMAND_SET_OBJECT_DYNAMIC:
@@ -7967,7 +7993,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (total == 0)
CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_NONE), pos, radius, true, &total, 16, apEntities);
if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities);
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, radius, true, &total, 16, apEntities);
CEntity* pClosestEntity = nil;
float min_dist = 2.0f * radius;
for (int i = 0; i < total; i++) {
@@ -8141,7 +8167,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_FBICAR:
case MI_MRWHOOP:
case MI_BFINJECT:
- case MI_CORPSE:
+ // case MI_CORPSE:
case MI_POLICE:
case MI_ENFORCER:
case MI_SECURICA:
@@ -8154,27 +8180,27 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_DODO:
case MI_COACH:
case MI_RCBANDIT:
- case MI_BELLYUP:
- case MI_MRWONGS:
- case MI_MAFIA:
- case MI_YARDIE:
- case MI_YAKUZA:
- case MI_DIABLOS:
- case MI_COLUMB:
- case MI_HOODS:
+ // case MI_BELLYUP:
+ // case MI_MRWONGS:
+ // case MI_MAFIA:
+ case MI_VOODOO:
+ // case MI_YAKUZA:
+ // case MI_DIABLOS:
+ // case MI_COLUMB:
+ // case MI_HOODS:
case MI_AIRTRAIN:
case MI_DEADDODO:
case MI_SPEEDER:
case MI_REEFER:
- case MI_PANLANT:
+ // case MI_PANLANT:
case MI_FLATBED:
case MI_YANKEE:
- case MI_ESCAPE:
- case MI_BORGNINE:
- case MI_TOYZ:
- case MI_GHOST:
- case MI_MIAMI_RCBARON:
- case MI_MIAMI_RCRAIDER:
+ // case MI_ESCAPE:
+ case MI_ZEBRA:
+ case MI_TOPFUN:
+ // case MI_GHOST:
+ case MI_RCBARON:
+ case MI_RCRAIDER:
model = -1;
break;
case MI_IDAHO:
@@ -8184,21 +8210,21 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_PATRIOT:
case MI_MANANA:
case MI_INFERNUS:
- case MI_BLISTA:
+ // case MI_BLISTA:
case MI_PONY:
case MI_CHEETAH:
case MI_MOONBEAM:
case MI_ESPERANT:
case MI_TAXI:
- case MI_KURUMA:
+ case MI_WASHING:
case MI_BOBCAT:
case MI_BANSHEE:
case MI_CABBIE:
case MI_STALLION:
case MI_RUMPO:
- case 151:
- case 152:
- case 153:
+// case 151:
+// case 152:
+// case 153:
break;
default:
printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]);
@@ -8293,14 +8319,34 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
DMAudio.PreloadMissionAudio(str);
return 0;
case COMMAND_HAS_MISSION_AUDIO_LOADED:
- UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1);
+ {
+ CollectParameters(&m_nIp, 1);
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("HAS_MISSION_AUDIO_LOADED not implemented, default to TRUE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(true);
+ //UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1);
return 0;
+ }
case COMMAND_PLAY_MISSION_AUDIO:
- DMAudio.PlayLoadedMissionAudio();
+ CollectParameters(&m_nIp, 1);
+ debug("PLAY_MISSION_AUDIO doesn't support parameter yet, skipping\n");
+ //DMAudio.PlayLoadedMissionAudio();
return 0;
case COMMAND_HAS_MISSION_AUDIO_FINISHED:
- UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished());
+ {
+ CollectParameters(&m_nIp, 1);
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("HAS_MISSION_AUDIO_FINISHED not implemented, default to TRUE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(true);
+ //UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished());
return 0;
+ }
case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING:
{
CollectParameters(&m_nIp, 3);
@@ -8395,10 +8441,15 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages;
StoreParameters(&m_nIp, 1);
return 0;
- case COMMAND_REGISTER_EL_BURRO_TIME:
+ case COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR:
+ {
CollectParameters(&m_nIp, 1);
- CStats::RegisterElBurroTime(ScriptParams[0]);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pPed->m_pMyVehicle);
return 0;
+ }
case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:
CollectParameters(&m_nIp, 1);
CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0;
@@ -8537,8 +8588,8 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
return 0;
}
case COMMAND_GET_BODY_CAST_HEALTH:
- ScriptParams[0] = CObject::nBodyCastHealth;
- StoreParameters(&m_nIp, 1);
+ // ScriptParams[0] = CObject::nBodyCastHealth;
+ // StoreParameters(&m_nIp, 1);
return 0;
case COMMAND_SET_CHARS_CHATTING:
{
@@ -8573,21 +8624,17 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->m_nZoneLevel = LEVEL_NONE;
return 0;
}
- case COMMAND_REGISTER_4X4_ONE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4OneTime(ScriptParams[0]);
+ case COMMAND_SET_DRUNK_INPUT_DELAY:
+ assert(0 && "SET_DRUNK_INPUT_DELAY not yet implemented");
return 0;
- case COMMAND_REGISTER_4X4_TWO_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4TwoTime(ScriptParams[0]);
+ case COMMAND_SET_CHAR_MONEY:
+ assert(0 && "SET_CHAR_MONEY not yet implemented");
return 0;
- case COMMAND_REGISTER_4X4_THREE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4ThreeTime(ScriptParams[0]);
+ case COMMAND_INCREASE_CHAR_MONEY:
+ assert(0 && "INCREASE_CHAR_MONEY not yet implemented");
return 0;
- case COMMAND_REGISTER_4X4_MAYHEM_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4MayhemTime(ScriptParams[0]);
+ case COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS:
+ assert(0 && "GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS not yet implemented");
return 0;
case COMMAND_REGISTER_LIFE_SAVED:
CStats::AnotherLifeSavedWithAmbulance();
@@ -8610,10 +8657,16 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
CStats::RegisterLongestFlightInDodo(ScriptParams[0]);
return 0;
- case COMMAND_REGISTER_DEFUSE_BOMB_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]);
+ case COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ CVector result = pVehicle->GetMatrix() * *(CVector*)&ScriptParams[1] + pVehicle->GetPosition();
+ *(CVector*)&ScriptParams[0] = result;
+ StoreParameters(&m_nIp, 3);
return 0;
+ }
case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:
CollectParameters(&m_nIp, 1);
CStats::SetTotalNumberKillFrenzies(ScriptParams[0]);
@@ -8687,8 +8740,14 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
CTimer::Suspend();
int offset = CTheScripts::MultiScriptArray[ScriptParams[0]];
+#ifdef USE_DEBUG_SCRIPT_LOADER
+ CFileMgr::ChangeDir("\\data\\");
+ int handle = CFileMgr::OpenFile(scriptfile, "rb");
+ CFileMgr::ChangeDir("\\");
+#else
CFileMgr::ChangeDir("\\");
int handle = CFileMgr::OpenFile("data\\main.scm", "rb");
+#endif
CFileMgr::Seek(handle, offset, 0);
CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);
CFileMgr::CloseFile(handle);
@@ -9125,7 +9184,6 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
return 0;
}
-#ifndef GTA_PS2
default:
assert(0);
}
@@ -9136,8 +9194,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
{
char tmp[48];
switch (command) {
-#endif
- case COMMAND_LOAD_COLLISION_WITH_SCREEN:
+ case COMMAND_LOAD_COLLISION_WITH_SCREEN: // NB: not actually implemented
CollectParameters(&m_nIp, 1);
CTimer::Stop();
CGame::currLevel = (eLevelName)ScriptParams[0];
@@ -9164,7 +9221,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
m_nIp += 8;
LoadSplash(tmp);
return 0;
- case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS:
+ case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: // NB: not actually implemented
{
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
@@ -9175,7 +9232,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
return 0;
}
- case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER:
+ case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: // NB: not actually implemented
{
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
@@ -9199,12 +9256,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED);
printf("End preload end of game audio\n");
return 0;
- case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:
+ case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: // NB: not actually implemented
CPad::GetPad(0)->DisablePlayerControls &= PLAYERCONTROL_DISABLED_1;
return 0;
-#ifndef GTA_PS2
- // To be precise, on PS2 previous handlers were in 1000-1099 function
- // These are "beta" VC commands (with bugs)
case COMMAND_SET_OBJECT_ROTATION:
{
CollectParameters(&m_nIp, 4);
@@ -9224,11 +9278,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source;
StoreParameters(&m_nIp, 3);
return 0;
- case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR:
+ case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: // NB: not actually implemented
*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front;
StoreParameters(&m_nIp, 3);
return 0;
- case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR:
+ case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: // NB: not actually implemented
{
CollectParameters(&m_nIp, 1);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
@@ -9245,10 +9299,38 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
assert(pTestedPed);
CEntity* pTarget = pPed->m_pPointGunAt;
- UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed);
+ bool bTargetting = pTarget && pTarget->IsPed() && pTarget == pTestedPed;
+ // PC shit
+ static int nCounter = 0;
+ nCounter = Max(0, nCounter - 1);
+ if (!pPed->GetWeapon()->IsTypeMelee() && !bTargetting) {
+ if ((pTarget->GetPosition() - TheCamera.GetPosition()).Magnitude() < 10.0f) {
+ CVector vTestedPos(pTarget->GetPosition().x, pTarget->GetPosition().y, pTarget->GetPosition().z + 0.4);
+ CVector vScreenPos;
+ float w, h;
+ if (CSprite::CalcScreenCoors(vTestedPos, vScreenPos, &w, &h, false)) {
+ CVector2D vCrosshairPosition(CCamera::m_f3rdPersonCHairMultX * RsGlobal.maximumWidth, CCamera::m_f3rdPersonCHairMultY * RsGlobal.maximumHeight);
+ float fScreenDistance = ((CVector2D)vScreenPos - vCrosshairPosition).Magnitude();
+ if (SCREEN_STRETCH_X(0.45f) > fScreenDistance / w) {
+ CColPoint point;
+ CEntity* entity;
+ if (!CWorld::ProcessLineOfSight(TheCamera.GetPosition() + 2.0f * TheCamera.GetForward(),
+ vTestedPos, point, entity, true, true, true, true, true, false) ||
+ entity == pTarget) {
+ nCounter += 2;
+ if (nCounter > 20) {
+ bTargetting = true;
+ nCounter = 20;
+ }
+ }
+ }
+ }
+ }
+ }
+ UpdateCompareFlag(bTargetting);
return 0;
}
- case COMMAND_IS_PLAYER_TARGETTING_OBJECT:
+ case COMMAND_IS_PLAYER_TARGETTING_OBJECT: // NB: not actually implemented
{
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
@@ -9301,7 +9383,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
case COMMAND_FAIL_CURRENT_MISSION:
CTheScripts::FailCurrentMission = 2;
return 0;
- case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE:
+ case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: // NB: actually does nothing
{
CollectParameters(&m_nIp, 5);
CVector pos = *(CVector*)&ScriptParams[0];
@@ -9347,7 +9429,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
- case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT:
+ case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: // NB: not actually implemented
{
CollectParameters(&m_nIp, 5);
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
@@ -9363,24 +9445,14 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
assert(pVehicle);
- if (pVehicle->pDriver) {
- pVehicle->pDriver->bScriptObjectiveCompleted = false;
- pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
- }
- for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++)
- {
- if (pVehicle->pPassengers[i]) {
- pVehicle->pPassengers[i]->bScriptObjectiveCompleted = false;
- pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
- }
- }
+ CCarAI::TellOccupantsToLeaveCar(pVehicle);
return 0;
}
case COMMAND_SET_INTERPOLATION_PARAMETERS:
CollectParameters(&m_nIp, 2);
- TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]);
+ TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 100.0f - *(float*)&ScriptParams[0], ScriptParams[1]);
return 0;
- case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT:
+ case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: // NB: not actually implemented
{
CollectParameters(&m_nIp, 5);
CVector pos = *(CVector*)&ScriptParams[0];
@@ -9395,7 +9467,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 4);
return 0;
}
- case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT:
+ case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: // NB: not actually implemented
{
CollectParameters(&m_nIp, 5);
CVector pos = *(CVector*)&ScriptParams[0];
@@ -9415,10 +9487,12 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 3);
return 0;
case COMMAND_ATTACH_CHAR_TO_CAR:
- // empty implementation
+ // TODO(MIAMI)
+ assert(0);
return 0;
case COMMAND_DETACH_CHAR_FROM_CAR:
- // empty implementation
+ // TODO(MIAMI)
+ assert(0);
return 0;
case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA
{
@@ -9432,15 +9506,20 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- assert(pPed);
- pPed->m_lastWepDam = -1;
+ if (pPed)
+ pPed->m_lastWepDam = -1;
+ else
+ debug("CLEAR_CHAR_LAST_WEAPON_DAMAGE - Character doesn't exist\n");
return 0;
}
case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- pVehicle->m_nLastWeaponDamage = -1;
+ if (pVehicle)
+ pVehicle->m_nLastWeaponDamage = -1;
+ else
+ debug("CLEAR_CAR_LAST_WEAPON_DAMAGE - Vehicle doesn't exist\n");
return 0;
}
case COMMAND_GET_RANDOM_COP_IN_AREA:
@@ -9461,9 +9540,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
continue;
if (pPed->m_nPedType != PEDTYPE_COP)
continue;
+ if (!ThisIsAValidRandomCop(pPed->GetModelIndex(), ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]))
+ continue;
if (pPed->CharCreatedBy != RANDOM_CHAR)
continue;
- if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)
+ if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING /* && pPed->GetPedState() != PED_ONROPE */) // TODO(MIAMI)!
continue;
if (pPed->bRemoveFromWorld)
continue;
@@ -9489,14 +9570,15 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
- case COMMAND_GET_RANDOM_COP_IN_ZONE:
+ case COMMAND_GET_RANDOM_COP_IN_ZONE: // NB: not actually implemented
{
char zone[KEY_LENGTH_IN_SCRIPT];
strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+// TODO(MIAMI): just getting this to compile with new argument
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (nZone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
+ CZone* pZone = CTheZones::GetNavigationZone(nZone);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
int i = CPools::GetPedPool()->GetSize();
@@ -9592,7 +9674,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
assert(pPed);
- ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
+ ScriptParams[0] = pPed->GetWeapon()->m_eWeaponType;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -9601,7 +9683,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
assert(pPed);
- ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
+ ScriptParams[0] = pPed->GetWeapon()->m_eWeaponType;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -9613,16 +9695,16 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
LocateCharObjectCommand(command, &m_nIp);
return 0;
- case COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT: // this will be changed in final VC version to a more general SET_TEMP_ACTION
+ case COMMAND_SET_CAR_TEMP_ACTION:
{
- CollectParameters(&m_nIp, 2);
+ CollectParameters(&m_nIp, 3);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
assert(pVehicle);
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT;
- pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
+ pVehicle->AutoPilot.m_nTempAction = (eCarTempAction)ScriptParams[1];
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[2];
return 0;
}
- case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:
+ case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: // NB: not actually implemented
{
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
@@ -9631,7 +9713,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
return 0;
}
- case COMMAND_SET_CAR_HANDBRAKE_STOP:
+ case COMMAND_SET_CAR_HANDBRAKE_STOP: // NB: not actually implemented
{
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
@@ -9645,11 +9727,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);
return 0;
}
- case COMMAND_LOCATE_SNIPER_BULLET_2D:
- case COMMAND_LOCATE_SNIPER_BULLET_3D:
+ case COMMAND_LOCATE_SNIPER_BULLET_2D: // NB: not actually implemented
+ case COMMAND_LOCATE_SNIPER_BULLET_3D: // NB: not actually implemented
LocateSniperBulletCommand(command, &m_nIp);
return 0;
case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL:
@@ -9662,10 +9744,10 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);
return 0;
}
- case COMMAND_IS_CHAR_LYING_DOWN:
+ case COMMAND_IS_CHAR_LYING_DOWN: // NB: not actually implemented
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
@@ -9690,29 +9772,1033 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
}
case COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER:
CollectParameters(&m_nIp, 1);
-#ifdef FIX_BUGS
CPed::nEnterCarRangeMultiplier = *(float*)&ScriptParams[0];
-#else
- CPed::nEnterCarRangeMultiplier = (float)ScriptParams[0];
-#endif
return 0;
-#endif
-#ifndef GTA3_1_1_PATCH
case COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER:
CollectParameters(&m_nIp, 1);
-#ifdef FIX_BUGS
CPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0];
-#else
- CPed::nThreatReactionRangeMultiplier = (float)ScriptParams[0];
-#endif
return 0;
-#endif
+ case COMMAND_SET_CHAR_CEASE_ATTACK_TIMER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ pPed->m_ceaseAttackTimer = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_REMOTE_CONTROLLED_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CWorld::Players[ScriptParams[0]].m_pRemoteVehicle;
+ if (pVehicle)
+ ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ else
+ ScriptParams[0] = -1;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_PC_VERSION:
+ UpdateCompareFlag(true);
+ return 0;
+ //case COMMAND_REPLAY:
+ //case COMMAND_IS_REPLAY_PLAYING:
+ case COMMAND_IS_MODEL_AVAILABLE:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CModelInfo::GetModelInfo(ScriptParams[0]) != nil);
+ return 0;
+ case COMMAND_SHUT_CHAR_UP:
+ assert("SHUT_CHAR_UP not implemented"); // TODO(MIAMI)
+ case COMMAND_SET_ENABLE_RC_DETONATE:
+ CollectParameters(&m_nIp, 1);
+ CVehicle::bDisableRemoteDetonation = ScriptParams[0];
+ return 0;
+ case COMMAND_SET_CAR_RANDOM_ROUTE_SEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ pVehicle->m_nRouteSeed = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_IS_ANY_PICKUP_AT_COORDS:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ CRunningScript::UpdateCompareFlag(CPickups::TestForPickupsInBubble(pos, 0.5f));
+ return 0;
+ }
+ case COMMAND_GET_FIRST_PICKUP_COORDS:
+ case COMMAND_GET_NEXT_PICKUP_COORDS:
+ case COMMAND_REMOVE_ALL_CHAR_WEAPONS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ pPed->ClearWeapons();
+ return 0;
+ }
+ case COMMAND_HAS_PLAYER_GOT_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ assert(pPed);
+ bool bFound = false;
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
+ if (pPed->GetWeapon(i).m_eWeaponType == ScriptParams[1]) {
+ bFound = true;
+ break;
+ }
+ }
+ UpdateCompareFlag(bFound);
+ return 0;
+ }
+ //case COMMAND_HAS_CHAR_GOT_WEAPON:
+ //case COMMAND_IS_PLAYER_FACING_CHAR:
+ case COMMAND_SET_TANK_DETONATE_CARS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle && pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ ((CAutomobile*)pVehicle)->bTankDetonateCars = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_POSITION_OF_ANALOGUE_STICKS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPad* pPad = CPad::GetPad(ScriptParams[0]);
+ ScriptParams[0] = pPad->NewState.LeftStickX;
+ ScriptParams[1] = pPad->NewState.LeftStickY;
+ ScriptParams[2] = pPad->NewState.RightStickX;
+ ScriptParams[3] = pPad->NewState.RightStickY;
+ StoreParameters(&m_nIp, 4);
+ return 0;
+ }
+ case COMMAND_IS_CAR_ON_FIRE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ bool bOnFire = false;
+ if (pVehicle->m_pCarFire)
+ bOnFire = true;
+ if (pVehicle->m_vehType == VEHICLE_TYPE_CAR && ((CAutomobile*)pVehicle)->Damage.GetEngineStatus() >= ENGINE_STATUS_ON_FIRE)
+ bOnFire = true;
+ if (pVehicle->m_fHealth < 250.0f)
+ bOnFire = true;
+ UpdateCompareFlag(bOnFire);
+ return 0;
+ }
+ case COMMAND_IS_CAR_TYRE_BURST:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ bool bIsBurst = false;
+ if (pVehicle->m_vehType == VEHICLE_APPEARANCE_BIKE) {
+ assert("IS_CAR_TYPE_BURST not yet implemented for bikes");
+ }
+ else {
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ if (ScriptParams[1] == 4) {
+ for (int i = 0; i < 4; i++) {
+ if (pCar->Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST)
+ bIsBurst = true;
+ }
+ }
+ else
+ bIsBurst = pCar->Damage.GetWheelStatus(ScriptParams[1] == WHEEL_STATUS_BURST);
+ }
+ UpdateCompareFlag(bIsBurst);
+ }
+ //case COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD:
+ //case COMMAND_SET_CAR_WAIT:
+ //case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE:
+ //case COMMAND_IS_PLAYER_FOOT_DOWN:
+ //case COMMAND_IS_CHAR_FOOT_DOWN:
+ case COMMAND_INITIALISE_OBJECT_PATH:
+ // TODO(MIAMI): script path
+ CollectParameters(&m_nIp, 2);
+ debug("INITALISE_OBJECT_PATH not yet implemented, skipping\n");
+ ScriptParams[0] = 0;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_START_OBJECT_ON_PATH:
+ {
+ CollectParameters(&m_nIp, 2);
+ debug("START_OBJECT_ON_PATH not yet implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_PATH_SPEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ debug("SET_OBJECT_PATH_SPEED not yet implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_PATH_POSITION:
+ {
+ CollectParameters(&m_nIp, 2);
+ debug("SET_OBJECT_PATH_POSITION not yet implemented, skipping\n");
+ return 0;
+ }
+ //case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH:
+ case COMMAND_CLEAR_OBJECT_PATH:
+ {
+ CollectParameters(&m_nIp, 1);
+ debug("CLEAR_OBJECT_PATH not yet implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_HELI_GOTO_COORDS:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle && pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ ((CAutomobile*)pVehicle)->TellHeliToGoToCoors(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], ScriptParams[4]);
+ return 0;
+ }
+ case COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr = ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr = ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_GET_DEAD_CHAR_PICKUP_COORDS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CVector pos;
+ pTarget->CreateDeadPedPickupCoors(&pos.x, &pos.y, &pos.z);
+ *(CVector*)&ScriptParams[0] = pos;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_CREATE_PROTECTION_PICKUP:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_REVENUE, PICKUP_ASSET_REVENUE, ScriptParams[3], ScriptParams[4]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_BOAT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANY_BOAT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_HELI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANY_HELI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_PLANE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANY_PLANE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_WATER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(pPed && pPed->bIsInWater);
+ return 0;
+ }
+ case COMMAND_SET_VAR_INT_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ *ptr = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_LVAR_INT_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ *ptr = ScriptParams[0];
+ return 0;
+ }
default:
assert(0);
}
return -1;
}
+
+int8 CRunningScript::ProcessCommands1200To1299(int32 command)
+{
+ switch (command) {
+ case COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr > ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr > ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ UpdateCompareFlag(ScriptParams[0] > *ptr);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ UpdateCompareFlag(ScriptParams[0] > *ptr);
+ return 0;
+ }
+ case COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr >= ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr >= ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ UpdateCompareFlag(ScriptParams[0] >= *ptr);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ UpdateCompareFlag(ScriptParams[0] >= *ptr);
+ return 0;
+ }
+ case COMMAND_GET_CHAR_WEAPON_IN_SLOT:
+ case COMMAND_GET_CLOSEST_STRAIGHT_ROAD:
+ assert(0);
+ case COMMAND_SET_CAR_FORWARD_SPEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ float speed = *(float*)&ScriptParams[1] / GAME_SPEED_TO_CARAI_SPEED;
+ pVehicle->SetMoveSpeed(pVehicle->GetForward() * speed);
+ // TODO(MIAMI): heli hack!
+ return 0;
+ }
+ case COMMAND_SET_AREA_VISIBLE:
+ CollectParameters(&m_nIp, 1);
+ CGame::currArea = ScriptParams[0];
+ // TODO(MIAMI) !!
+ //CStreaming::RemoveBuildingsNotInArea(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_CUTSCENE_ANIM_TO_LOOP:
+ {
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ debug("SET_CUTSCENE_ANIM_TO_LOOP not implemented yet, skipping\n");
+ return 0;
+ }
+ case COMMAND_MARK_CAR_AS_CONVOY_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ pVehicle->bPartOfConvoy = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER:
+ case COMMAND_GET_HAVOC_CAUSED_BY_PLAYER:
+ case COMMAND_CREATE_SCRIPT_ROADBLOCK:
+ case COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS:
+ case COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR:
+ case COMMAND_IS_PICKUP_IN_ZONE:
+ case COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS:
+ case COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED:
+ case COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR:
+ case COMMAND_SWITCH_SECURITY_CAMERA:
+ case COMMAND_IS_CHAR_IN_FLYING_VEHICLE:
+ assert(0);
+ case COMMAND_IS_PLAYER_IN_FLYING_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && (pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE));
+ return 0;
+ }
+ case COMMAND_HAS_SONY_CD_BEEN_READ:
+ case COMMAND_GET_NUMBER_OF_SONY_CDS_READ:
+ case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD:
+ case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD:
+ assert(0);
+ case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_MONEY_SPENT_ON_CLOTHES:
+ CollectParameters(&m_nIp, 1);
+ CStats::MoneySpentOnFashion(ScriptParams[0]);
+ return 0;
+
+ case COMMAND_SET_HELI_ORIENTATION:
+ case COMMAND_CLEAR_HELI_ORIENTATION:
+ case COMMAND_PLANE_GOTO_COORDS:
+ case COMMAND_GET_NTH_CLOSEST_CAR_NODE:
+ case COMMAND_GET_NTH_CLOSEST_CHAR_NODE:
+ case COMMAND_DRAW_WEAPONSHOP_CORONA:
+ case COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT:
+ case COMMAND_FREEZE_CHAR_POSITION:
+ case COMMAND_SET_CHAR_DROWNS_IN_WATER:
+ case COMMAND_SET_OBJECT_RECORDS_COLLISIONS:
+ case COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING:
+ case COMMAND_REMOVE_RC_BUGGY:
+ case COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN:
+ case COMMAND_GET_CHAR_ARMOUR:
+ case COMMAND_SET_CHAR_ARMOUR:
+ case COMMAND_SET_HELI_STABILISER:
+ case COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE:
+ case COMMAND_POP_CAR_BOOT:
+ case COMMAND_SHUT_PLAYER_UP:
+ case COMMAND_SET_PLAYER_MOOD:
+ assert(0);
+ case COMMAND_REQUEST_COLLISION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVector2D pos;
+ pos.x = *(float*)&ScriptParams[0];
+ pos.y = *(float*)&ScriptParams[1];
+ CColStore::RequestCollision(pos);
+ return 0;
+ }
+ case COMMAND_LOCATE_OBJECT_2D:
+ case COMMAND_LOCATE_OBJECT_3D:
+ case COMMAND_IS_OBJECT_IN_WATER:
+ case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR:
+ case COMMAND_IS_OBJECT_IN_AREA_2D:
+ case COMMAND_IS_OBJECT_IN_AREA_3D:
+ case COMMAND_TASK_TOGGLE_DUCK:
+ assert(0);
+ case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO:
+ {
+ char label[12];
+ int16 carDensities[CCarCtrl::NUM_CAR_CLASSES] = { 0 };
+ int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES] = { 0 };
+ int i;
+
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CollectParameters(&m_nIp, 12);
+ for (i = 0; i < CCarCtrl::NUM_CAR_CLASSES; i++)
+ carDensities[i] = ScriptParams[i + 1];
+ for (i = 0; i < CCarCtrl::NUM_BOAT_CLASSES; i++)
+ boatDensities[i] = ScriptParams[i + 1 + CCarCtrl::NUM_CAR_CLASSES];
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ if (zone < 0) {
+ debug("Couldn't find zone - %s\n", label);
+ return 0;
+ }
+ while (zone >= 0) {
+ CTheZones::SetZoneCivilianCarInfo(zone, ScriptParams[0], carDensities, boatDensities);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
+ return 0;
+ }
+ case COMMAND_REQUEST_ANIMATION:
+ case COMMAND_HAS_ANIMATION_LOADED:
+ case COMMAND_REMOVE_ANIMATION:
+ case COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION:
+ case COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION:
+ case COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION:
+ case COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT:
+ case COMMAND_ATTACH_CHAR_TO_OBJECT:
+ case COMMAND_SET_CHAR_AS_PLAYER_FRIEND:
+ case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER:
+ case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING:
+ assert(0);
+ case COMMAND_ADD_SET_PIECE:
+ {
+ CollectParameters(&m_nIp, 13);
+ debug("ADD_SET_PIECE not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_SET_EXTRA_COLOURS:
+ {
+ CollectParameters(&m_nIp, 2);
+ debug("SET_EXTRA_COLOURS not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_CLEAR_EXTRA_COLOURS:
+ {
+ CollectParameters(&m_nIp, 1);
+ debug("CLEAR_EXTRA_COLOURS not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_CLOSE_CAR_BOOT:
+ assert(0);
+ case COMMAND_GET_WHEELIE_STATS:
+ {
+ CollectParameters(&m_nIp, 1);
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("GET_WHEELIE_STATS not implemented\n");
+ bShowed = true;
+ }
+ for (int i = 0; i < 6; i++)
+ ScriptParams[i] = 0;
+ StoreParameters(&m_nIp, 6);
+ return 0;
+ }
+ case COMMAND_DISARM_CHAR:
+ case COMMAND_BURST_CAR_TYRE:
+ case COMMAND_IS_CHAR_OBJ_NO_OBJ:
+ case COMMAND_IS_PLAYER_WEARING:
+ case COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY:
+ case COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD:
+ case COMMAND_CREATE_SWAT_ROPE:
+ case COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA:
+ case COMMAND_GET_NEAREST_TYRE_TO_POINT:
+ case COMMAND_SET_CAR_MODEL_COMPONENTS:
+ case COMMAND_SWITCH_LIFT_CAMERA:
+ case COMMAND_CLOSE_ALL_CAR_DOORS:
+ case COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D:
+ case COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D:
+ case COMMAND_POP_CAR_BOOT_USING_PHYSICS:
+ case COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA:
+ case COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE:
+ case COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR:
+ case COMMAND_GET_MAX_WANTED_LEVEL:
+ case COMMAND_IS_CHAR_WANDER_PATH_CLEAR:
+ case COMMAND_PRINT_HELP_WITH_NUMBER:
+ case COMMAND_PRINT_HELP_FOREVER:
+ case COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER:
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands1300To1399(int32 command)
+{
+ switch (command) {
+ case COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ uint8 flag = 1 << (uint8)ScriptParams[1];
+ if (ScriptParams[2])
+ pTarget->m_gangFlags |= flag;
+ else
+ pTarget->m_gangFlags &= ~flag;
+
+ return 0;
+ }
+ case COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE:
+ case COMMAND_IS_MISSION_AUDIO_PLAYING:
+ assert(0);
+ case COMMAND_CREATE_LOCKED_PROPERTY_PICKUP:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ // TODO(MIAMI) - add text
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY, PICKUP_PROPERTY_LOCKED, 0, 0, false, text);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CREATE_FORSALE_PROPERTY_PICKUP:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ // TODO(MIAMI) - add text
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY_FORSALE, PICKUP_PROPERTY_FORSALE, ScriptParams[3], 0, false, text);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_FREEZE_CAR_POSITION:
+ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR:
+ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR:
+ case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR:
+ case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR:
+ case COMMAND_GET_RADIO_CHANNEL:
+ case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS:
+ case COMMAND_IS_CAR_DROWNING_IN_WATER:
+ case COMMAND_IS_CHAR_DROWNING_IN_WATER:
+ assert(0);
+ case COMMAND_DISABLE_CUTSCENE_SHADOWS:
+ {
+ debug("DISABLE_CUTSCENE_SHADOWS not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY:
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE:
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT:
+ case COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED:
+ case COMMAND_IS_MISSION_AUDIO_LOADING:
+ case COMMAND_ADD_MONEY_SPENT_ON_WEAPONS:
+ case COMMAND_ADD_MONEY_SPENT_ON_PROPERTY:
+ case COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING:
+ case COMMAND_SET_CHAR_ANSWERING_MOBILE:
+ case COMMAND_SET_PLAYER_DRUNKENNESS:
+ case COMMAND_GET_PLAYER_DRUNKENNESS:
+ case COMMAND_SET_PLAYER_DRUG_LEVEL:
+ case COMMAND_GET_PLAYER_DRUG_LEVEL:
+ case COMMAND_ADD_LOAN_SHARK_VISITS:
+ case COMMAND_ADD_STORES_KNOCKED_OFF:
+ case COMMAND_ADD_MOVIE_STUNTS:
+ case COMMAND_ADD_NUMBER_OF_ASSASSINATIONS:
+ case COMMAND_ADD_PIZZAS_DELIVERED:
+ case COMMAND_ADD_GARBAGE_PICKUPS:
+ case COMMAND_ADD_ICE_CREAMS_SOLD:
+ case COMMAND_SET_TOP_SHOOTING_RANGE_SCORE:
+ case COMMAND_ADD_SHOOTING_RANGE_RANK:
+ case COMMAND_ADD_MONEY_SPENT_ON_GAMBLING:
+ case COMMAND_ADD_MONEY_WON_ON_GAMBLING:
+ case COMMAND_SET_LARGEST_GAMBLING_WIN:
+ case COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT:
+ case COMMAND_CLEAR_CHAR_WAIT_STATE:
+ case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE:
+ case COMMAND_SET_CAN_BURST_CAR_TYRES:
+ case COMMAND_SET_PLAYER_AUTO_AIM:
+ case COMMAND_FIRE_HUNTER_GUN:
+ case COMMAND_SET_PROPERTY_AS_OWNED:
+ case COMMAND_ADD_BLOOD_RING_KILLS:
+ case COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING:
+ assert(0);
+ case COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE:
+ {
+ debug("REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_TOUCHING_VEHICLE:
+ case COMMAND_IS_CHAR_TOUCHING_VEHICLE:
+ case COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER:
+ case COMMAND_CLEAR_CHAR_FOLLOW_PATH:
+ case COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE:
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE:
+ assert(0);
+ case COMMAND_LOAD_MISSION_TEXT:
+ {
+ char key[8];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ TheText.LoadMissionText(key);
+ return 0;
+ }
+ case COMMAND_SET_TONIGHTS_EVENT:
+ {
+ CollectParameters(&m_nIp, 1);
+ debug("skipping SET_TONIGHTS_EVENT\n");
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY:
+ case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY:
+ case COMMAND_FREEZE_OBJECT_POSITION:
+ case COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY:
+ case COMMAND_SET_RIOT_INTENSITY:
+ case COMMAND_IS_CAR_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_CAR_IN_ANGLED_AREA_3D:
+ case COMMAND_REMOVE_WEAPON_FROM_CHAR:
+ case COMMAND_SET_UP_TAXI_SHORTCUT:
+ case COMMAND_CLEAR_TAXI_SHORTCUT:
+ case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT:
+ case COMMAND_GET_CLOSEST_WATER_NODE:
+ case COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH:
+ assert(0);
+ case COMMAND_CREATE_CLOTHES_PICKUP:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_CLOTHES, PICKUP_ON_STREET, ScriptParams[3]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CHANGE_BLIP_THRESHOLD:
+ assert(0);
+ case COMMAND_MAKE_PLAYER_FIRE_PROOF:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_bFireproof = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_INCREASE_PLAYER_MAX_HEALTH:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_nMaxHealth += ScriptParams[1];
+ pPlayerInfo->m_pPed->m_fHealth = pPlayerInfo->m_nMaxHealth;
+ return 0;
+ }
+ case COMMAND_INCREASE_PLAYER_MAX_ARMOUR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_nMaxArmour += ScriptParams[1];
+ pPlayerInfo->m_pPed->m_fArmour = pPlayerInfo->m_nMaxArmour;
+ return 0;
+ }
+ case COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ CPed* pPed = CPopulation::AddPedInCar(pVehicle, true);
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
+ pPed->SetPosition(pVehicle->GetPosition());
+ pPed->SetOrientation(0.0f, 0.0f, 0.0f);
+ pPed->SetPedState(PED_DRIVING);
+ pPed->m_pMyVehicle = pVehicle;
+ pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
+ pVehicle->pDriver = pPed;
+ pVehicle->pDriver->RegisterReference((CEntity**)&pVehicle->pDriver);
+ pPed->bInVehicle = true;
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ if (pVehicle->m_vehType == VEHICLE_TYPE_BOAT)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->bEngineOn = true;
+ pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
+ CPopulation::ms_nTotalMissionPeds++;
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ CPed* pPed = CPopulation::AddPedInCar(pVehicle, false);
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
+ pPed->SetPosition(pVehicle->GetPosition());
+ pPed->SetOrientation(0.0f, 0.0f, 0.0f);
+ CPopulation::ms_nTotalMissionPeds++;
+ pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
+ if (ScriptParams[1] >= 0)
+ pVehicle->AddPassenger(pPed, ScriptParams[1]);
+ else
+ pVehicle->AddPassenger(pPed);
+
+ pPed->m_pMyVehicle = pVehicle;
+ pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
+ pPed->bInVehicle = true;
+ pPed->SetPedState(PED_DRIVING);
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS:
+ case COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON:
+ case COMMAND_MAKE_HELI_COME_CRASHING_DOWN:
+ case COMMAND_ADD_EXPLOSION_NO_SOUND:
+ assert(0);
+ case COMMAND_SET_OBJECT_AREA_VISIBLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ assert(pObject);
+ pObject->m_area = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_WAS_VEHICLE_EVER_POLICE:
+ case COMMAND_SET_CHAR_NEVER_TARGETTED:
+ case COMMAND_LOAD_UNCOMPRESSED_ANIM:
+ assert(0);
+ case COMMAND_WAS_CUTSCENE_SKIPPED:
+ {
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("COMMAND_WAS_CUTSCENE_SKIPPED not implemented, default to TRUE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(true);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ debug("SET_CHAR_CROUCH_WHEN_THREATENED not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 1);
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("IS_CHAR_IN_ANY_POLICE_VEHICLE not implemented, default to FALSE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(false);
+ return 0;
+ }
+ case COMMAND_DOES_CHAR_EXIST:
+ case COMMAND_DOES_VEHICLE_EXIST:
+ case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT:
+ assert(0);
+ case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 2, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_STUCK:
+ case COMMAND_SET_ALL_TAXIS_HAVE_NITRO:
+ case COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY:
+ case COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION:
+ case COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION:
+ case COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION:
+ case COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION:
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands1400To1499(int32 command)
+{
+ switch (command) {
+ case COMMAND_REGISTER_VIGILANTE_LEVEL:
+ case COMMAND_CLEAR_ALL_CHAR_ANIMS:
+ assert(0);
+ case COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE:
+ CollectParameters(&m_nIp, 2);
+ CGarages::SetMaxNumStoredCarsForGarage(ScriptParams[0], ScriptParams[1]);
+ break;
+ case COMMAND_WANTED_STARS_ARE_FLASHING:
+ {
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("WANTED_STARS_ARE_FLASHING not implemented, default to FALSE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(false);
+ return 0;
+ }
+ case COMMAND_SET_ALLOW_HURRICANES:
+ CollectParameters(&m_nIp, 1);
+ CStats::NoMoreHurricanes = ScriptParams[0];
+ return 0;
+ case COMMAND_PLAY_ANNOUNCEMENT:
+ {
+ CollectParameters(&m_nIp, 1);
+ debug("PLAY_ANNOUNCEMENT not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_IS_IN_STADIUM:
+ case COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER:
+ case COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM:
+ case COMMAND_DISPLAY_RADAR:
+ case COMMAND_REGISTER_BEST_POSITION:
+ assert(0);
+ case COMMAND_IS_PLAYER_IN_INFO_ZONE:
+ {
+ CollectParameters(&m_nIp, 1);
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("IS_PLAYER_IN_INFO_ZONE not implemented, default to FALSE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(false);
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE:
+ case COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED:
+ case COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR:
+ case COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG:
+ case COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG:
+ case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG:
+ case COMMAND_ADD_BIG_GUN_FLASH:
+ case COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM:
+ assert(0);
+ case COMMAND_GET_PROGRESS_PERCENTAGE:
+ *(float*)&ScriptParams[0] = CStats::GetPercentageProgress();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SET_SHORTCUT_PICKUP_POINT:
+ {
+ CollectParameters(&m_nIp, 4);
+ debug("SET_SHORTCUT_PICKUP_POINT not implemented, skipping\n");
+ return 0;
+ }
+ case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION:
+ {
+ CollectParameters(&m_nIp, 4);
+ debug("SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION not implemented, skipping");
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA:
+ case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE:
+ case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA:
+ assert(0);
+ case COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS:
+ CollectParameters(&m_nIp, 2);
+ CGangs::SetWillAttackPlayerWithCops((ePedType)((int)PEDTYPE_GANG1 + ScriptParams[0]), !!ScriptParams[1]);
+ return 0;
+ case COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR:
+ assert(0);
+ case COMMAND_SET_VEHICLE_TO_FADE_IN:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_REGISTER_ODDJOB_MISSION_PASSED:
+ assert(0);
+ case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI:
+ {
+ CollectParameters(&m_nIp, 1);
+ static bool bShowed = false;
+ if (!bShowed) {
+ debug("IS_PLAYER_IN_SHORTCUT_TAXI not implemented, default to FALSE\n");
+ bShowed = true;
+ }
+ UpdateCompareFlag(false);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_DUCKING:
+ case COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI:
+ case COMMAND_REGISTER_FIRE_LEVEL:
+ case COMMAND_IS_AUSTRALIAN_GAME:
+ case COMMAND_DISARM_CAR_BOMB:
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+bool CRunningScript::ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami)
+{
+ switch (mi)
+ {
+ case MI_COP: if (cop) return true;
+ case MI_SWAT: if (swat) return true;
+ case MI_FBI: if (fbi) return true;
+ case MI_ARMY: if (army) return true;
+ default:
+ return miami && (mi >= MI_VICE1 && mi <= MI_VICE8);
+ }
+}
+
+void CTheScripts::RemoveThisPed(CPed* pPed)
+{
+ if (pPed) {
+ bool bWasMissionPed = pPed->CharCreatedBy == MISSION_CHAR;
+ if (pPed->InVehicle() && pPed->m_pMyVehicle) {
+ if (pPed->m_pMyVehicle->pDriver == pPed) {
+ pPed->m_pMyVehicle->RemoveDriver();
+ pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+ pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle())
+ pPed->m_pMyVehicle->ChangeLawEnforcerState(0);
+ }
+ else {
+ pPed->m_pMyVehicle->RemovePassenger(pPed);
+ }
+ }
+ CWorld::RemoveReferencesToDeletedObject(pPed);
+ delete pPed;
+ if (bWasMissionPed)
+ --CPopulation::ms_nTotalMissionPeds;
+ }
+}
+
int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index)
{
if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1)
@@ -11077,29 +12163,6 @@ void CRunningScript::DoDeatharrestCheck()
while (m_nStackPointer > 1)
--m_nStackPointer;
m_nIp = m_anStack[--m_nStackPointer];
- int16 messageId;
- if (pPlayer->IsRestartingAfterDeath())
- messageId = 0;
- else if (pPlayer->IsRestartingAfterArrest())
- messageId = 5;
- else
- messageId = 10;
- messageId += CGeneral::GetRandomNumberInRange(0, 5);
- bool found = false;
- for (int16 contact = 0; !found && contact < MAX_NUM_CONTACTS; contact++) {
- int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact];
- if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) {
- messageId += CTheScripts::BaseBriefIdForContact[contact];
- found = true;
- }
- }
- if (!found)
- messageId = 8001;
- char tmp[16];
- sprintf(tmp, "%d", messageId);
- CMessages::ClearSmallMessagesOnly();
- wchar* text = TheText.Get(tmp);
- // ...and do nothing about it
*(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0;
m_bDeatharrestExecuted = true;
m_nWakeTime = 0;
@@ -11243,8 +12306,8 @@ void CTheScripts::RenderTheScriptDebugLines()
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0);
}
-#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\
- sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32)
+#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) +\
+ 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32)
void CTheScripts::SaveAllScripts(uint8* buf, uint32* size)
{
@@ -11264,12 +12327,6 @@ INITSAVEBUF
uint32 script_data_size = SCRIPT_DATA_SIZE;
WriteSaveBuf(buf, script_data_size);
WriteSaveBuf(buf, OnAMissionFlag);
- for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) {
- WriteSaveBuf(buf, OnAMissionForContactFlag[i]);
- WriteSaveBuf(buf, BaseBriefIdForContact[i]);
- }
- for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++)
- WriteSaveBuf(buf, CollectiveArray[i]);
WriteSaveBuf(buf, NextFreeCollectiveIndex);
for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding;
@@ -11342,12 +12399,6 @@ INITSAVEBUF
ScriptSpace[i] = ReadSaveBuf<uint8>(buf);
assert(ReadSaveBuf<uint32>(buf) == SCRIPT_DATA_SIZE);
OnAMissionFlag = ReadSaveBuf<uint32>(buf);
- for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) {
- OnAMissionForContactFlag[i] = ReadSaveBuf<uint32>(buf);
- BaseBriefIdForContact[i] = ReadSaveBuf<uint32>(buf);
- }
- for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++)
- CollectiveArray[i] = ReadSaveBuf<tCollectiveData>(buf);
NextFreeCollectiveIndex = ReadSaveBuf<uint32>(buf);
for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
uint32 type = ReadSaveBuf<uint32>(buf);
diff --git a/src/control/Script.h b/src/control/Script.h
index acab66cc..3393467e 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -6,6 +6,7 @@
class CEntity;
class CBuilding;
+class CPhysical;
class CVehicle;
class CPed;
class CObject;
@@ -131,6 +132,8 @@ public:
void AddEntityToList(int32, uint8);
void RemoveEntityFromList(int32, uint8);
void Process();
+ void CheckIfCollisionHasLoadedForMissionObject();
+ CPhysical* DoesThisEntityWaitForCollision(int i);
};
struct CUpsideDownCarCheckEntry
@@ -218,19 +221,17 @@ enum {
};
enum {
- SIZE_MAIN_SCRIPT = 128 * 1024,
- SIZE_MISSION_SCRIPT = 32 * 1024,
+ SIZE_MAIN_SCRIPT = 225512,
+ SIZE_MISSION_SCRIPT = 35000,
SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT
};
enum {
MAX_NUM_SCRIPTS = 128,
- MAX_NUM_CONTACTS = 16,
MAX_NUM_INTRO_TEXT_LINES = 2,
MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16,
- MAX_NUM_COLLECTIVES = 32,
MAX_NUM_USED_OBJECTS = 200,
MAX_NUM_MISSION_SCRIPTS = 120,
MAX_NUM_BUILDING_SWAPS = 25,
@@ -242,13 +243,10 @@ class CTheScripts
{
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];
- static int32 BaseBriefIdForContact[MAX_NUM_CONTACTS];
- static int32 OnAMissionForContactFlag[MAX_NUM_CONTACTS];
static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
- static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES];
static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS];
static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@@ -272,14 +270,17 @@ class CTheScripts
static uint32 LargestMissionScriptSize;
static uint32 MainScriptSize;
static uint8 FailCurrentMission;
- static uint8 CountdownToMakePlayerUnsafe;
- static uint8 DelayMakingPlayerUnsafeThisTime;
static uint16 NumScriptDebugLines;
static uint16 NumberOfIntroRectanglesThisFrame;
static uint16 NumberOfIntroTextLinesThisFrame;
static uint8 UseTextCommands;
static uint16 CommandsExecuted;
static uint16 ScriptsUpdated;
+ static uint8 RiotIntensity;
+ static uint32 LastMissionPassedTime;
+ static uint16 NumberOfExclusiveMissionScripts;
+ static bool bPlayerIsInTheStatium;
+ static bool bPlayerHasMetDebbieHarry;
public:
static void Init();
@@ -303,9 +304,6 @@ public:
static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; }
- static void ResetCountdownToMakePlayerUnsafe() { CountdownToMakePlayerUnsafe = 0; }
- static bool IsCountdownToMakePlayerUnsafeOn() { return CountdownToMakePlayerUnsafe != 0; }
-
static int32 Read4BytesFromScript(uint32* pIp) {
int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
*pIp += 4;
@@ -368,10 +366,13 @@ private:
static int32 AddScriptSphere(int32 id, CVector pos, float radius);
static int32 GetNewUniqueScriptSphereIndex(int32 index);
static void RemoveScriptSphere(int32 index);
+ static void RemoveScriptTextureDictionary();
+ static void RemoveThisPed(CPed* pPed);
friend class CRunningScript;
friend class CHud;
friend void CMissionCleanup::Process();
+ friend class CColStore;
};
@@ -410,6 +411,7 @@ class CRunningScript
uint32 m_anStack[MAX_STACK_DEPTH];
uint16 m_nStackPointer;
int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS];
+ bool m_bIsActive;
bool m_bCondResult;
bool m_bIsMissionScript;
bool m_bSkipWakeTime;
@@ -462,9 +464,11 @@ private:
int8 ProcessCommands800To899(int32);
int8 ProcessCommands900To999(int32);
int8 ProcessCommands1000To1099(int32);
-#ifndef GTA_PS2
int8 ProcessCommands1100To1199(int32);
-#endif
+ int8 ProcessCommands1200To1299(int32);
+ int8 ProcessCommands1300To1399(int32);
+ int8 ProcessCommands1400To1499(int32);
+
void LocatePlayerCommand(int32, uint32*);
void LocatePlayerCharCommand(int32, uint32*);
void LocatePlayerCarCommand(int32, uint32*);
@@ -501,4 +505,6 @@ private:
return false;
}
}
+
+ static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami);
};
diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h
index 77cf3f0f..67b1b9bc 100644
--- a/src/control/ScriptCommands.h
+++ b/src/control/ScriptCommands.h
@@ -995,7 +995,7 @@ enum {
COMMAND_FORCE_RANDOM_PED_TYPE,
COMMAND_SET_TEXT_DRAW_BEFORE_FADE,
COMMAND_GET_COLLECTABLE1S_COLLECTED,
- COMMAND_REGISTER_EL_BURRO_TIME,
+ COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR,
COMMAND_SET_SPRITES_DRAW_BEFORE_FADE,
COMMAND_SET_TEXT_RIGHT_JUSTIFY,
COMMAND_PRINT_HELP,
@@ -1022,17 +1022,17 @@ enum {
COMMAND_MAKE_PLAYER_SAFE,
COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL,
COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL,
- COMMAND_REGISTER_4X4_ONE_TIME,
- COMMAND_REGISTER_4X4_TWO_TIME,
- COMMAND_REGISTER_4X4_THREE_TIME,
- COMMAND_REGISTER_4X4_MAYHEM_TIME,
+ COMMAND_SET_DRUNK_INPUT_DELAY,
+ COMMAND_SET_CHAR_MONEY,
+ COMMAND_INCREASE_CHAR_MONEY,
+ COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS,
COMMAND_REGISTER_LIFE_SAVED,
COMMAND_REGISTER_CRIMINAL_CAUGHT,
COMMAND_REGISTER_AMBULANCE_LEVEL,
COMMAND_REGISTER_FIRE_EXTINGUISHED,
COMMAND_TURN_PHONE_ON,
COMMAND_REGISTER_LONGEST_DODO_FLIGHT,
- COMMAND_REGISTER_DEFUSE_BOMB_TIME,
+ COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS,
COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES,
COMMAND_BLOW_UP_RC_BUGGY,
COMMAND_REMOVE_CAR_FROM_CHASE,
@@ -1108,7 +1108,6 @@ enum {
COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER,
COMMAND_LOAD_END_OF_GAME_TUNE,
COMMAND_ENABLE_PLAYER_CONTROL_CAMERA,
-#ifndef GTA_PS2
COMMAND_SET_OBJECT_ROTATION,
COMMAND_GET_DEBUG_CAMERA_COORDINATES,
COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR,
@@ -1145,7 +1144,7 @@ enum {
COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D,
COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D,
COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D,
- COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT,
+ COMMAND_SET_CAR_TEMP_ACTION,
COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT,
COMMAND_SET_CAR_HANDBRAKE_STOP,
COMMAND_IS_CHAR_ON_ANY_BIKE,
@@ -1156,8 +1155,286 @@ enum {
COMMAND_IS_CHAR_LYING_DOWN,
COMMAND_CAN_CHAR_SEE_DEAD_CHAR,
COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER,
-#ifndef GTA3_1_1_PATCH
- COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER
-#endif
-#endif
+ COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER,
+ COMMAND_SET_CHAR_CEASE_ATTACK_TIMER,
+ COMMAND_GET_REMOTE_CONTROLLED_CAR,
+ COMMAND_IS_PC_VERSION,
+ COMMAND_REPLAY,
+ COMMAND_IS_REPLAY_PLAYING,
+ COMMAND_IS_MODEL_AVAILABLE,
+ COMMAND_SHUT_CHAR_UP,
+ COMMAND_SET_ENABLE_RC_DETONATE,
+ COMMAND_SET_CAR_RANDOM_ROUTE_SEED,
+ COMMAND_IS_ANY_PICKUP_AT_COORDS,
+ COMMAND_GET_FIRST_PICKUP_COORDS,
+ COMMAND_GET_NEXT_PICKUP_COORDS,
+ COMMAND_REMOVE_ALL_CHAR_WEAPONS,
+ COMMAND_HAS_PLAYER_GOT_WEAPON,
+ COMMAND_HAS_CHAR_GOT_WEAPON,
+ COMMAND_IS_PLAYER_FACING_CHAR,
+ COMMAND_SET_TANK_DETONATE_CARS,
+ COMMAND_GET_POSITION_OF_ANALOGUE_STICKS,
+ COMMAND_IS_CAR_ON_FIRE,
+ COMMAND_IS_CAR_TYRE_BURST,
+ COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD,
+ COMMAND_SET_CAR_WAIT,
+ COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE,
+ COMMAND_IS_PLAYER_FOOT_DOWN,
+ COMMAND_IS_CHAR_FOOT_DOWN,
+ COMMAND_INITIALISE_OBJECT_PATH,
+ COMMAND_START_OBJECT_ON_PATH,
+ COMMAND_SET_OBJECT_PATH_SPEED,
+ COMMAND_SET_OBJECT_PATH_POSITION,
+ COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH,
+ COMMAND_CLEAR_OBJECT_PATH,
+ COMMAND_HELI_GOTO_COORDS,
+ COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT,
+ COMMAND_GET_DEAD_CHAR_PICKUP_COORDS,
+ COMMAND_CREATE_PROTECTION_PICKUP,
+ COMMAND_IS_CHAR_IN_ANY_BOAT,
+ COMMAND_IS_PLAYER_IN_ANY_BOAT,
+ COMMAND_IS_CHAR_IN_ANY_HELI,
+ COMMAND_IS_PLAYER_IN_ANY_HELI,
+ COMMAND_IS_CHAR_IN_ANY_PLANE,
+ COMMAND_IS_PLAYER_IN_ANY_PLANE,
+ COMMAND_IS_CHAR_IN_WATER,
+ COMMAND_SET_VAR_INT_TO_CONSTANT,
+ COMMAND_SET_LVAR_INT_TO_CONSTANT,
+ COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT,
+ COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT,
+ COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR,
+ COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR,
+ COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR,
+ COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR,
+ COMMAND_GET_CHAR_WEAPON_IN_SLOT,
+ COMMAND_GET_CLOSEST_STRAIGHT_ROAD,
+ COMMAND_SET_CAR_FORWARD_SPEED,
+ COMMAND_SET_AREA_VISIBLE,
+ COMMAND_SET_CUTSCENE_ANIM_TO_LOOP,
+ COMMAND_MARK_CAR_AS_CONVOY_CAR,
+ COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER,
+ COMMAND_GET_HAVOC_CAUSED_BY_PLAYER,
+ COMMAND_CREATE_SCRIPT_ROADBLOCK,
+ COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS,
+ COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR,
+ COMMAND_IS_PICKUP_IN_ZONE,
+ COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS,
+ COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED,
+ COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR,
+ COMMAND_SWITCH_SECURITY_CAMERA,
+ COMMAND_IS_CHAR_IN_FLYING_VEHICLE,
+ COMMAND_IS_PLAYER_IN_FLYING_VEHICLE,
+ COMMAND_HAS_SONY_CD_BEEN_READ,
+ COMMAND_GET_NUMBER_OF_SONY_CDS_READ,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD,
+ COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD,
+ COMMAND_ADD_MONEY_SPENT_ON_CLOTHES,
+ COMMAND_SET_HELI_ORIENTATION,
+ COMMAND_CLEAR_HELI_ORIENTATION,
+ COMMAND_PLANE_GOTO_COORDS,
+ COMMAND_GET_NTH_CLOSEST_CAR_NODE,
+ COMMAND_GET_NTH_CLOSEST_CHAR_NODE,
+ COMMAND_DRAW_WEAPONSHOP_CORONA,
+ COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT,
+ COMMAND_FREEZE_CHAR_POSITION,
+ COMMAND_SET_CHAR_DROWNS_IN_WATER,
+ COMMAND_SET_OBJECT_RECORDS_COLLISIONS,
+ COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING,
+ COMMAND_REMOVE_RC_BUGGY,
+ COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN,
+ COMMAND_GET_CHAR_ARMOUR,
+ COMMAND_SET_CHAR_ARMOUR,
+ COMMAND_SET_HELI_STABILISER,
+ COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE,
+ COMMAND_POP_CAR_BOOT,
+ COMMAND_SHUT_PLAYER_UP,
+ COMMAND_SET_PLAYER_MOOD,
+ COMMAND_REQUEST_COLLISION,
+ COMMAND_LOCATE_OBJECT_2D,
+ COMMAND_LOCATE_OBJECT_3D,
+ COMMAND_IS_OBJECT_IN_WATER,
+ COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR,
+ COMMAND_IS_OBJECT_IN_AREA_2D,
+ COMMAND_IS_OBJECT_IN_AREA_3D,
+ COMMAND_TASK_TOGGLE_DUCK,
+ COMMAND_SET_ZONE_CIVILIAN_CAR_INFO,
+ COMMAND_REQUEST_ANIMATION,
+ COMMAND_HAS_ANIMATION_LOADED,
+ COMMAND_REMOVE_ANIMATION,
+ COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT,
+ COMMAND_ATTACH_CHAR_TO_OBJECT,
+ COMMAND_SET_CHAR_AS_PLAYER_FRIEND,
+ COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER,
+ COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING,
+ COMMAND_ADD_SET_PIECE,
+ COMMAND_SET_EXTRA_COLOURS,
+ COMMAND_CLEAR_EXTRA_COLOURS,
+ COMMAND_CLOSE_CAR_BOOT,
+ COMMAND_GET_WHEELIE_STATS,
+ COMMAND_DISARM_CHAR,
+ COMMAND_BURST_CAR_TYRE,
+ COMMAND_IS_CHAR_OBJ_NO_OBJ,
+ COMMAND_IS_PLAYER_WEARING,
+ COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY,
+ COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD,
+ COMMAND_CREATE_SWAT_ROPE,
+ COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA,
+ COMMAND_GET_NEAREST_TYRE_TO_POINT,
+ COMMAND_SET_CAR_MODEL_COMPONENTS,
+ COMMAND_SWITCH_LIFT_CAMERA,
+ COMMAND_CLOSE_ALL_CAR_DOORS,
+ COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D,
+ COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D,
+ COMMAND_POP_CAR_BOOT_USING_PHYSICS,
+ COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA,
+ COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE,
+ COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR,
+ COMMAND_GET_MAX_WANTED_LEVEL,
+ COMMAND_IS_CHAR_WANDER_PATH_CLEAR,
+ COMMAND_PRINT_HELP_WITH_NUMBER,
+ COMMAND_PRINT_HELP_FOREVER,
+ COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER,
+ COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG,
+ COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE,
+ COMMAND_IS_MISSION_AUDIO_PLAYING,
+ COMMAND_CREATE_LOCKED_PROPERTY_PICKUP,
+ COMMAND_CREATE_FORSALE_PROPERTY_PICKUP,
+ COMMAND_FREEZE_CAR_POSITION,
+ COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR,
+ COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR,
+ COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR,
+ COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR,
+ COMMAND_GET_RADIO_CHANNEL,
+ COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS,
+ COMMAND_IS_CAR_DROWNING_IN_WATER,
+ COMMAND_IS_CHAR_DROWNING_IN_WATER,
+ COMMAND_DISABLE_CUTSCENE_SHADOWS,
+ COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT,
+ COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED,
+ COMMAND_IS_MISSION_AUDIO_LOADING,
+ COMMAND_ADD_MONEY_SPENT_ON_WEAPONS,
+ COMMAND_ADD_MONEY_SPENT_ON_PROPERTY,
+ COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING,
+ COMMAND_SET_CHAR_ANSWERING_MOBILE,
+ COMMAND_SET_PLAYER_DRUNKENNESS,
+ COMMAND_GET_PLAYER_DRUNKENNESS,
+ COMMAND_SET_PLAYER_DRUG_LEVEL,
+ COMMAND_GET_PLAYER_DRUG_LEVEL,
+ COMMAND_ADD_LOAN_SHARK_VISITS,
+ COMMAND_ADD_STORES_KNOCKED_OFF,
+ COMMAND_ADD_MOVIE_STUNTS,
+ COMMAND_ADD_NUMBER_OF_ASSASSINATIONS,
+ COMMAND_ADD_PIZZAS_DELIVERED,
+ COMMAND_ADD_GARBAGE_PICKUPS,
+ COMMAND_ADD_ICE_CREAMS_SOLD,
+ COMMAND_SET_TOP_SHOOTING_RANGE_SCORE,
+ COMMAND_ADD_SHOOTING_RANGE_RANK,
+ COMMAND_ADD_MONEY_SPENT_ON_GAMBLING,
+ COMMAND_ADD_MONEY_WON_ON_GAMBLING,
+ COMMAND_SET_LARGEST_GAMBLING_WIN,
+ COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT,
+ COMMAND_CLEAR_CHAR_WAIT_STATE,
+ COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE,
+ COMMAND_SET_CAN_BURST_CAR_TYRES,
+ COMMAND_SET_PLAYER_AUTO_AIM,
+ COMMAND_FIRE_HUNTER_GUN,
+ COMMAND_SET_PROPERTY_AS_OWNED,
+ COMMAND_ADD_BLOOD_RING_KILLS,
+ COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING,
+ COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE,
+ COMMAND_IS_PLAYER_TOUCHING_VEHICLE,
+ COMMAND_IS_CHAR_TOUCHING_VEHICLE,
+ COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER,
+ COMMAND_CLEAR_CHAR_FOLLOW_PATH,
+ COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE,
+ COMMAND_LOAD_MISSION_TEXT,
+ COMMAND_SET_TONIGHTS_EVENT,
+ COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY,
+ COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY,
+ COMMAND_FREEZE_OBJECT_POSITION,
+ COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY,
+ COMMAND_SET_RIOT_INTENSITY,
+ COMMAND_IS_CAR_IN_ANGLED_AREA_2D,
+ COMMAND_IS_CAR_IN_ANGLED_AREA_3D,
+ COMMAND_REMOVE_WEAPON_FROM_CHAR,
+ COMMAND_SET_UP_TAXI_SHORTCUT,
+ COMMAND_CLEAR_TAXI_SHORTCUT,
+ COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT,
+ COMMAND_GET_CLOSEST_WATER_NODE,
+ COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH,
+ COMMAND_CREATE_CLOTHES_PICKUP,
+ COMMAND_CHANGE_BLIP_THRESHOLD,
+ COMMAND_MAKE_PLAYER_FIRE_PROOF,
+ COMMAND_INCREASE_PLAYER_MAX_HEALTH,
+ COMMAND_INCREASE_PLAYER_MAX_ARMOUR,
+ COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER,
+ COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER,
+ COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS,
+ COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON,
+ COMMAND_MAKE_HELI_COME_CRASHING_DOWN,
+ COMMAND_ADD_EXPLOSION_NO_SOUND,
+ COMMAND_SET_OBJECT_AREA_VISIBLE,
+ COMMAND_WAS_VEHICLE_EVER_POLICE,
+ COMMAND_SET_CHAR_NEVER_TARGETTED,
+ COMMAND_LOAD_UNCOMPRESSED_ANIM,
+ COMMAND_WAS_CUTSCENE_SKIPPED,
+ COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED,
+ COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE,
+ COMMAND_DOES_CHAR_EXIST,
+ COMMAND_DOES_VEHICLE_EXIST,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT,
+ COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT,
+ COMMAND_IS_CHAR_STUCK,
+ COMMAND_SET_ALL_TAXIS_HAVE_NITRO,
+ COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY,
+ COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION,
+ COMMAND_REGISTER_VIGILANTE_LEVEL,
+ COMMAND_CLEAR_ALL_CHAR_ANIMS,
+ COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE,
+ COMMAND_WANTED_STARS_ARE_FLASHING,
+ COMMAND_SET_ALLOW_HURRICANES,
+ COMMAND_PLAY_ANNOUNCEMENT,
+ COMMAND_SET_PLAYER_IS_IN_STADIUM,
+ COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER,
+ COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM,
+ COMMAND_DISPLAY_RADAR,
+ COMMAND_REGISTER_BEST_POSITION,
+ COMMAND_IS_PLAYER_IN_INFO_ZONE,
+ COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE,
+ COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED,
+ COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR,
+ COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG,
+ COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG,
+ COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG,
+ COMMAND_ADD_BIG_GUN_FLASH,
+ COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM,
+ COMMAND_GET_PROGRESS_PERCENTAGE,
+ COMMAND_SET_SHORTCUT_PICKUP_POINT,
+ COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION,
+ COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA,
+ COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE,
+ COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA,
+ COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS,
+ COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR,
+ COMMAND_SET_VEHICLE_TO_FADE_IN,
+ COMMAND_REGISTER_ODDJOB_MISSION_PASSED,
+ COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI,
+ COMMAND_IS_CHAR_DUCKING,
+ COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI,
+ COMMAND_REGISTER_FIRE_LEVEL,
+ COMMAND_IS_AUSTRALIAN_GAME,
+ COMMAND_DISARM_CAR_BOMB,
}; \ No newline at end of file
diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp
index 278366a3..b1816936 100644
--- a/src/control/TrafficLights.cpp
+++ b/src/control/TrafficLights.cpp
@@ -145,7 +145,10 @@ CTrafficLights::ScanForLightsOnMap(void)
CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES];
for(node = list.first; node; node = node->next){
CEntity *light = (CEntity*)node->item;
- if(light->GetModelIndex() != MI_TRAFFICLIGHTS)
+ if(light->GetModelIndex() != MI_TRAFFICLIGHTS &&
+ light->GetModelIndex() != MI_TRAFFICLIGHTS_VERTICAL &&
+ light->GetModelIndex() != MI_TRAFFICLIGHTS_MIAMI &&
+ light->GetModelIndex() != MI_TRAFFICLIGHTS_TWOVERTICAL)
continue;
// Check cars
@@ -274,8 +277,12 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
bool
CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)
{
+#ifdef GTA_BRIDGE
return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&
!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;
+#else
+ return false;
+#endif
}
int
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp
index f49f811f..35106a6b 100644
--- a/src/core/AnimViewer.cpp
+++ b/src/core/AnimViewer.cpp
@@ -368,13 +368,7 @@ CAnimViewer::Update(void)
} else {
// Originally it was GetPad(1)->LeftShoulder2
if (pad->NewState.Triangle) {
-#ifdef PED_SKIN
- if(IsClumpSkinned(pTarget->GetClump()))
- ((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump());
- else
-#endif
- CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->GetHitColModel(),
- RpClumpGetFrame(pTarget->GetClump()));
+ ((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump());
AsciiToUnicode("Ped Col model will be animated as long as you hold the button", gUString);
CMessages::AddMessage(gUString, 100, 0);
}
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index 6c79604c..afa153f9 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -280,12 +280,12 @@ CCam::Process(void)
if(DirectionWasLooking != LOOKING_BEHIND)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_BEHIND;
- }else if(CPad::GetPad(0)->GetLookLeft()){
+ }else if(!((CVehicle*)CamTargetEntity)->IsRealHeli() && CPad::GetPad(0)->GetLookLeft()){
LookLeft();
if(DirectionWasLooking != LOOKING_LEFT)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_LEFT;
- }else if(CPad::GetPad(0)->GetLookRight()){
+ }else if(!((CVehicle*)CamTargetEntity)->IsRealHeli() && CPad::GetPad(0)->GetLookRight()){
LookRight();
if(DirectionWasLooking != LOOKING_RIGHT)
TheCamera.m_bJust_Switched = true;
@@ -1627,20 +1627,6 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
entity = nil;
}
- if(CamTargetEntity->m_rwObject){
- // what's going on here?
- if(RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_PUMP) ||
- RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_THROW) ||
- RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_THROWU) ||
- RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_START_THROW)){
- CPed *player = FindPlayerPed();
- float PlayerDist = (Source - player->GetPosition()).Magnitude();
- if(PlayerDist < 2.75f)
- Near = PlayerDist/2.75f * DEFAULT_NEAR - 0.3f;
- RwCameraSetNearClipPlane(Scene.camera, Max(Near, 0.1f));
- }
- }
-
TheCamera.m_bCamDirectlyInFront = false;
TheCamera.m_bCamDirectlyBehind = false;
@@ -4539,6 +4525,8 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
Rotating = false;
}
+ if(TheCamera.m_bUseTransitionBeta)
+ Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));
if(TheCamera.m_bUseTransitionBeta)
Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));
@@ -4908,7 +4896,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
bool correctAlpha = true;
// if (SA checks if we aren't in work car, why?) {
- if (!isCar || car->GetModelIndex() != MI_YARDIE) {
+ if (!isCar || car->GetModelIndex() != MI_VOODOO) {
correctAlpha = false;
}
else {
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 35d230dc..fa5e44bb 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -61,6 +61,8 @@ enum
CCamera TheCamera;
bool CCamera::m_bUseMouse3rdPerson = true;
bool bDidWeProcessAnyCinemaCam;
+float CCamera::m_f3rdPersonCHairMultX;
+float CCamera::m_f3rdPersonCHairMultY;
#ifdef IMPROVED_CAMERA
#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)
@@ -80,10 +82,6 @@ CCamera::CCamera(void)
Init();
}
-CCamera::CCamera(float)
-{
-}
-
void
CCamera::Init(void)
{
@@ -91,12 +89,7 @@ CCamera::Init(void)
float fMouseAccelHorzntl = m_fMouseAccelHorzntl;
float fMouseAccelVertical = m_fMouseAccelVertical;
#endif
-#ifdef FIX_BUGS
- static const CCamera DummyCamera = CCamera(0.f);
- *this = DummyCamera;
-#else
- memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh?
-#endif
+ memset(this, 0, sizeof(CCamera)); // this is fine, no vtable
#ifdef GTA3_1_1_PATCH
m_fMouseAccelHorzntl = fMouseAccelHorzntl;
m_fMouseAccelVertical = fMouseAccelVertical;
@@ -642,7 +635,11 @@ CCamera::CamControl(void)
m_bInitialNodeFound = false;
m_bInitialNoNodeStaticsSet = false;
}
+#ifdef GTA_TRAIN
Process_Train_Camera_Control();
+#else
+ assert(0 && "this can't happen");
+#endif
}else{
if(((CVehicle*)pTargetEntity)->IsBoat())
boatTarget = true;
@@ -701,8 +698,8 @@ CCamera::CamControl(void)
garageDoorPos2.z = 0.0f;
#endif
}
- garageCenter.x = (pToGarageWeAreIn->m_fX1 + pToGarageWeAreIn->m_fX2)/2.0f;
- garageCenter.y = (pToGarageWeAreIn->m_fY1 + pToGarageWeAreIn->m_fY2)/2.0f;
+ garageCenter.x = pToGarageWeAreIn->GetGarageCenterX();
+ garageCenter.y = pToGarageWeAreIn->GetGarageCenterY();
garageCenter.z = 0.0f;
if(whichDoor == 1)
garageCenterToDoor = garageDoorPos1 - garageCenter;
@@ -940,11 +937,13 @@ CCamera::CamControl(void)
if(CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer())
stairs = true;
// Some hack for Mr Whoopee in a bomb shop
+#ifndef MIAMI // uhh, check this
if(Cams[ActiveCam].Using3rdPersonMouseCam() && CCollision::ms_collisionInMemory == LEVEL_COMMERCIAL){
if(pTargetEntity->GetPosition().x < 83.0f && pTargetEntity->GetPosition().x > 18.0f &&
pTargetEntity->GetPosition().y < -305.0f && pTargetEntity->GetPosition().y > -390.0f)
disableGarageCam = true;
}
+#endif
if(!disableGarageCam && (CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs)){
if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){
if(pToGarageWeAreIn || stairs){
@@ -983,8 +982,8 @@ CCamera::CamControl(void)
}
if(pToGarageWeAreIn){
- garageCenter.x = (pToGarageWeAreIn->m_fX1 + pToGarageWeAreIn->m_fX2)/2.0f;
- garageCenter.y = (pToGarageWeAreIn->m_fY1 + pToGarageWeAreIn->m_fY2)/2.0f;
+ garageCenter.x = pToGarageWeAreIn->GetGarageCenterX();
+ garageCenter.y = pToGarageWeAreIn->GetGarageCenterY();
garageCenter.z = 0.0f;
}else{
garageDoorPos1.z = 0.0f;
@@ -1017,8 +1016,8 @@ CCamera::CamControl(void)
if(PedZoomIndicator == CAM_ZOOM_TOPDOWN && !stairs){
garageCamPos = garageCenter;
garageCamPos.z += FindPlayerPed()->GetPosition().z + 2.1f;
- if(pToGarageWeAreIn && garageCamPos.z > pToGarageWeAreIn->m_fX2) // What?
- garageCamPos.z = pToGarageWeAreIn->m_fX2;
+ if(pToGarageWeAreIn && garageCamPos.z > pToGarageWeAreIn->m_fSupX) // What?
+ garageCamPos.z = pToGarageWeAreIn->m_fSupX;
}else
garageCamPos.z = ground + 3.1f;
SetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f));
@@ -1533,7 +1532,6 @@ CCamera::UpdateTargetEntity(void)
pTargetEntity = FindPlayerVehicle();
else{
pTargetEntity = FindPlayerPed();
-#ifndef GTA_PS2_STUFF
// this keeps the camera on the player while entering cars
if(PLAYER->GetPedState() == PED_ENTER_CAR ||
PLAYER->GetPedState() == PED_CARJACK ||
@@ -1543,7 +1541,6 @@ CCamera::UpdateTargetEntity(void)
if(!enteringCar)
if(Cams[ActiveCam].CamTargetEntity != pTargetEntity)
Cams[ActiveCam].CamTargetEntity = pTargetEntity;
-#endif
}
bool cantOpen = true;
@@ -1562,16 +1559,9 @@ CCamera::UpdateTargetEntity(void)
if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){
if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS)
-#ifdef GTA_PS2_STUFF
-// dunno if this has any amazing effects
- {
-#endif
pTargetEntity = PLAYER->m_pMyVehicle;
if(PLAYER->m_pMyVehicle == nil)
pTargetEntity = PLAYER;
-#ifdef GTA_PS2_STUFF
- }
-#endif
}
if(PLAYER->GetPedState() == PED_EXIT_CAR)
@@ -2717,6 +2707,7 @@ CCamera::DontProcessObbeCinemaCamera(void)
bDidWeProcessAnyCinemaCam = false;
}
+#ifdef GTA_TRAIN
void
CCamera::LoadTrainCamNodes(char const *name)
{
@@ -2894,6 +2885,7 @@ CCamera::Process_Train_Camera_Control(void)
}
}
}
+#endif
void
@@ -3189,7 +3181,7 @@ CCamera::RenderMotionBlur(void)
CMBlur::MotionBlurRender(m_pRwCamera,
m_BlurRed, m_BlurGreen, m_BlurBlue,
- m_motionBlur, m_BlurType, m_imotionBlurAddAlpha);
+ m_motionBlur, m_BlurType);
}
void
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 80fc878e..135f9d8f 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -472,8 +472,8 @@ public:
// not static yet
float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls
- float m_f3rdPersonCHairMultX;
- float m_f3rdPersonCHairMultY;
+ static float m_f3rdPersonCHairMultX;
+ static float m_f3rdPersonCHairMultY;
CCam Cams[3];
@@ -549,7 +549,6 @@ public:
// High level and misc
CCamera(void);
- CCamera(float);
void Init(void);
void Process(void);
void CamControl(void);
diff --git a/src/core/ColStore.cpp b/src/core/ColStore.cpp
new file mode 100644
index 00000000..80bbdc77
--- /dev/null
+++ b/src/core/ColStore.cpp
@@ -0,0 +1,237 @@
+#include "common.h"
+
+#include "templates.h"
+#include "General.h"
+#include "ModelInfo.h"
+#include "Streaming.h"
+#include "FileLoader.h"
+#include "Script.h"
+#include "Timer.h"
+#include "Camera.h"
+#include "Frontend.h"
+#include "Physical.h"
+#include "ColStore.h"
+
+CPool<ColDef,ColDef> *CColStore::ms_pColPool;
+
+void
+CColStore::Initialise(void)
+{
+ if(ms_pColPool == nil)
+ ms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, "CollisionFiles");
+ AddColSlot("generic"); // slot 0. not streamed
+}
+
+void
+CColStore::Shutdown(void)
+{
+ int i;
+ for(i = 0; i < COLSTORESIZE; i++)
+ RemoveColSlot(i);
+ if(ms_pColPool)
+ delete ms_pColPool;
+ ms_pColPool = nil;
+}
+
+int
+CColStore::AddColSlot(const char *name)
+{
+ ColDef *def = ms_pColPool->New();
+ assert(def);
+ def->isLoaded = false;
+ def->unused = 0;
+ def->bounds.left = 1000000.0f;
+ def->bounds.top = 1000000.0f;
+ def->bounds.right = -1000000.0f;
+ def->bounds.bottom = -1000000.0f;
+ def->minIndex = INT16_MAX;
+ def->maxIndex = INT16_MIN;
+ strcpy(def->name, name);
+ return ms_pColPool->GetJustIndex(def);
+}
+
+void
+CColStore::RemoveColSlot(int slot)
+{
+ if(GetSlot(slot)){
+ if(GetSlot(slot)->isLoaded)
+ RemoveCol(slot);
+ ms_pColPool->Delete(GetSlot(slot));
+ }
+}
+
+int
+CColStore::FindColSlot(const char *name)
+{
+ ColDef *def;
+ int size = ms_pColPool->GetSize();
+ for(int i = 0; i < size; i++){
+ def = GetSlot(i);
+ if(def && !CGeneral::faststricmp(def->name, name))
+ return i;
+ }
+ return -1;
+}
+
+char*
+CColStore::GetColName(int32 slot)
+{
+ return GetSlot(slot)->name;
+}
+
+CRect&
+CColStore::GetBoundingBox(int32 slot)
+{
+ return GetSlot(slot)->bounds;
+}
+
+void
+CColStore::IncludeModelIndex(int32 slot, int32 modelIndex)
+{
+ ColDef *def = GetSlot(slot);
+ if(modelIndex < def->minIndex)
+ def->minIndex = modelIndex;
+ if(modelIndex > def->maxIndex)
+ def->maxIndex = modelIndex;
+}
+
+bool
+CColStore::LoadCol(int32 slot, uint8 *buffer, int32 bufsize)
+{
+ bool success;
+ ColDef *def = GetSlot(slot);
+ if(def->minIndex > def->maxIndex)
+ success = CFileLoader::LoadCollisionFileFirstTime(buffer, bufsize, slot);
+ else
+ success = CFileLoader::LoadCollisionFile(buffer, bufsize, slot);
+ if(success)
+ def->isLoaded = true;
+ else
+ debug("Failed to load Collision\n");
+ return success;
+}
+
+void
+CColStore::RemoveCol(int32 slot)
+{
+ int id;
+ GetSlot(slot)->isLoaded = false;
+ for(id = 0; id < MODELINFOSIZE; id++){
+ CBaseModelInfo *mi = CModelInfo::GetModelInfo(id);
+ if(mi){
+ CColModel *col = mi->GetColModel();
+ if(col && col->level == slot)
+ col->RemoveCollisionVolumes();
+ }
+ }
+}
+
+void
+CColStore::LoadAllCollision(void)
+{
+ int i;
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i))
+ CStreaming::RequestCol(i, 0);
+
+ CStreaming::LoadAllRequestedModels(false);
+}
+
+void
+CColStore::RemoveAllCollision(void)
+{
+ int i;
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i))
+ if(CStreaming::CanRemoveCol(i))
+ CStreaming::RemoveCol(i);
+}
+
+static bool bLoadAtSecondPosition;
+static CVector2D secondPosition;
+
+void
+CColStore::AddCollisionNeededAtPosn(const CVector2D &pos)
+{
+ bLoadAtSecondPosition = true;
+ secondPosition = pos;
+}
+
+void
+CColStore::LoadCollision(const CVector2D &pos)
+{
+ int i;
+
+ if(CStreaming::ms_disableStreaming)
+ return;
+
+ for(i = 1; i < COLSTORESIZE; i++){
+ if(GetSlot(i) == nil)
+ continue;
+
+ bool wantThisOne = false;
+
+ if(GetBoundingBox(i).IsPointInside(pos) ||
+ bLoadAtSecondPosition && GetBoundingBox(i).IsPointInside(secondPosition, -119.0f) ||
+ CGeneral::faststrcmp(GetColName(i), "yacht") == 0){
+ wantThisOne = true;
+ }else{
+ for (int j = 0; j < MAX_CLEANUP; j++) {
+ CPhysical* pEntity = CTheScripts::MissionCleanup.DoesThisEntityWaitForCollision(j);
+ if (pEntity /* !pEntity->bDontLoadCollision && !pEntity->bIsFrozen */) {
+ if (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f))
+ wantThisOne = true;
+ }
+ }
+ }
+
+ if(wantThisOne)
+ CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);
+ else
+ CStreaming::RemoveCol(i);
+ }
+ bLoadAtSecondPosition = false;
+}
+
+void
+CColStore::RequestCollision(const CVector2D &pos)
+{
+ int i;
+
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f))
+ CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);
+}
+
+void
+CColStore::EnsureCollisionIsInMemory(const CVector2D &pos)
+{
+ int i;
+
+ if(CStreaming::ms_disableStreaming)
+ return;
+
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -110.0f) &&
+ !CStreaming::HasColLoaded(i)){
+ CStreaming::RequestCol(i, 0);
+ if(TheCamera.GetScreenFadeStatus() == FADE_0)
+ FrontEndMenuManager.MessageScreen("LOADCOL", false);
+ CTimer::Suspend();
+ CStreaming::LoadAllRequestedModels(false);
+ CTimer::Resume();
+ }
+}
+
+//--MIAMI: done
+bool
+CColStore::HasCollisionLoaded(const CVector2D &pos)
+{
+ int i;
+
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f) &&
+ !GetSlot(i)->isLoaded)
+ return false;
+ return true;
+}
diff --git a/src/core/ColStore.h b/src/core/ColStore.h
new file mode 100644
index 00000000..8e2a3a70
--- /dev/null
+++ b/src/core/ColStore.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "templates.h"
+
+struct ColDef { // made up name
+ int32 unused;
+ bool isLoaded;
+ CRect bounds;
+ char name[20];
+ int16 minIndex;
+ int16 maxIndex;
+};
+
+class CColStore
+{
+ static CPool<ColDef,ColDef> *ms_pColPool;
+
+public:
+ static void Initialise(void);
+ static void Shutdown(void);
+ static int AddColSlot(const char *name);
+ static void RemoveColSlot(int32 slot);
+ static int FindColSlot(const char *name);
+ static char *GetColName(int32 slot);
+ static CRect &GetBoundingBox(int32 slot);
+ static void IncludeModelIndex(int32 slot, int32 modelIndex);
+ static bool LoadCol(int32 storeID, uint8 *buffer, int32 bufsize);
+ static void RemoveCol(int32 slot);
+ static void AddCollisionNeededAtPosn(const CVector2D &pos);
+ static void LoadAllCollision(void);
+ static void RemoveAllCollision(void);
+ static void LoadCollision(const CVector2D &pos);
+ static void RequestCollision(const CVector2D &pos);
+ static void EnsureCollisionIsInMemory(const CVector2D &pos);
+ static bool HasCollisionLoaded(const CVector2D &pos);
+
+ static ColDef *GetSlot(int slot) {
+ assert(slot >= 0);
+ assert(ms_pColPool);
+ assert(slot < ms_pColPool->GetSize());
+ return ms_pColPool->GetSlot(slot);
+ }
+};
diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp
index 01cc323a..c29c1d28 100644
--- a/src/core/Collision.cpp
+++ b/src/core/Collision.cpp
@@ -20,6 +20,8 @@
#include "SurfaceTable.h"
#include "Lines.h"
#include "Collision.h"
+#include "Camera.h"
+#include "ColStore.h"
enum Direction
{
@@ -34,57 +36,30 @@ enum Direction
eLevelName CCollision::ms_collisionInMemory;
CLinkList<CColModel*> CCollision::ms_colModelCache;
+//--MIAMI: done
void
CCollision::Init(void)
{
ms_colModelCache.Init(NUMCOLCACHELINKS);
ms_collisionInMemory = LEVEL_NONE;
+ CColStore::Initialise();
}
+//--MIAMI: done
void
CCollision::Shutdown(void)
{
ms_colModelCache.Shutdown();
+ CColStore::Shutdown();
}
+//--MIAMI: done
void
CCollision::Update(void)
{
- CVector playerCoors;
- playerCoors = FindPlayerCoors();
- eLevelName level = CTheZones::m_CurrLevel;
- bool forceLevelChange = false;
-
- if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing())
- return;
-
- // hardcode a level if there are no zones
- if(level == LEVEL_NONE){
- if(CGame::currLevel == LEVEL_INDUSTRIAL &&
- playerCoors.x < 400.0f){
- level = LEVEL_COMMERCIAL;
- forceLevelChange = true;
- }else if(CGame::currLevel == LEVEL_SUBURBAN &&
- playerCoors.x > -450.0f && playerCoors.y < -1400.0f){
- level = LEVEL_COMMERCIAL;
- forceLevelChange = true;
- }else{
- if(playerCoors.x > 800.0f){
- level = LEVEL_INDUSTRIAL;
- forceLevelChange = true;
- }else if(playerCoors.x < -800.0f){
- level = LEVEL_SUBURBAN;
- forceLevelChange = true;
- }
- }
- }
- if(level != LEVEL_NONE && level != CGame::currLevel)
- CGame::currLevel = level;
- if(ms_collisionInMemory != CGame::currLevel)
- LoadCollisionWhenINeedIt(forceLevelChange);
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
}
+//--MIAMI: unused
eLevelName
GetCollisionInSectorList(CPtrList &list)
{
@@ -101,6 +76,7 @@ GetCollisionInSectorList(CPtrList &list)
return LEVEL_NONE;
}
+//--MIAMI: unused
// Get a level this sector is in based on collision models
eLevelName
GetCollisionInSector(CSector &sect)
@@ -121,111 +97,16 @@ GetCollisionInSector(CSector &sect)
return (eLevelName)level;
}
+//--MIAMI: done
void
CCollision::LoadCollisionWhenINeedIt(bool forceChange)
{
- eLevelName level, l;
- bool multipleLevels;
- CVector playerCoors;
- CVehicle *veh;
- CEntryInfoNode *ei;
- int sx, sy;
- int xmin, xmax, ymin, ymax;
- int x, y;
-
- level = LEVEL_NONE;
-
- playerCoors = FindPlayerCoors();
- sx = CWorld::GetSectorIndexX(playerCoors.x);
- sy = CWorld::GetSectorIndexY(playerCoors.y);
- multipleLevels = false;
-
- veh = FindPlayerVehicle();
- if(veh && veh->IsTrain()){
- if(((CTrain*)veh)->m_nDoorState != TRAIN_DOOR_OPEN)
- return;
- }else if(playerCoors.z < -4.0f && !CCullZones::DoINeedToLoadCollision())
- return;
-
- // Figure out whose level's collisions we're most likely to be interested in
- if(!forceChange){
- if(veh && veh->IsBoat()){
- // on water we expect to be between levels
- multipleLevels = true;
- }else{
- xmin = Max(sx - 1, 0);
- xmax = Min(sx + 1, NUMSECTORS_X-1);
- ymin = Max(sy - 1, 0);
- ymax = Min(sy + 1, NUMSECTORS_Y-1);
-
- for(x = xmin; x <= xmax; x++)
- for(y = ymin; y <= ymax; y++){
- l = GetCollisionInSector(*CWorld::GetSector(x, y));
- if(l != LEVEL_NONE){
- if(level == LEVEL_NONE)
- level = l;
- if(level != l)
- multipleLevels = true;
- }
- }
- }
-
- if(multipleLevels && veh && veh->IsBoat())
- for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){
- level = GetCollisionInSector(*ei->sector);
- if(level != LEVEL_NONE)
- break;
- }
- }
-
- if(level == CGame::currLevel || forceChange){
- CTimer::Stop();
- DMAudio.SetEffectsFadeVol(0);
- CPad::StopPadsShaking();
- LoadCollisionScreen(CGame::currLevel);
- DMAudio.Service();
-
- CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false);
- CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
- CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
- CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
- CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
- CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
- CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
- CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
- CStreaming::RemoveUnusedModelsInLoadedList();
- CGame::TidyUpMemory(true, true);
- CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
- ms_collisionInMemory = CGame::currLevel;
- CReplay::EmptyReplayBuffer();
- if(CGame::currLevel != LEVEL_NONE)
- LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
- CStreaming::RemoveUnusedBuildings(CGame::currLevel);
- CStreaming::RequestBigBuildings(CGame::currLevel);
- CStreaming::LoadAllRequestedModels(true);
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
-
- CGame::TidyUpMemory(true, true);
- CTimer::Update();
- DMAudio.SetEffectsFadeVol(127);
- }
}
+//--MIAMI: done
void
CCollision::SortOutCollisionAfterLoad(void)
{
- if(ms_collisionInMemory == CGame::currLevel)
- return;
-
- CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
- if(CGame::currLevel != LEVEL_NONE){
- CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
- if(!CGame::playingIntro)
- LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- }
- ms_collisionInMemory = CGame::currLevel;
- CGame::TidyUpMemory(true, false);
}
void
@@ -249,14 +130,14 @@ CCollision::LoadCollisionScreen(eLevelName level)
bool
-CCollision::TestSphereSphere(const CColSphere &s1, const CColSphere &s2)
+CCollision::TestSphereSphere(const CSphere &s1, const CSphere &s2)
{
float d = s1.radius + s2.radius;
return (s1.center - s2.center).MagnitudeSqr() < d*d;
}
bool
-CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box)
+CCollision::TestSphereBox(const CSphere &sph, const CBox &box)
{
if(sph.center.x + sph.radius < box.min.x) return false;
if(sph.center.x - sph.radius > box.max.x) return false;
@@ -268,7 +149,7 @@ CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box)
}
bool
-CCollision::TestLineBox(const CColLine &line, const CColBox &box)
+CCollision::TestLineBox(const CColLine &line, const CBox &box)
{
float t, x, y, z;
// If either line point is in the box, we have a collision
@@ -353,7 +234,7 @@ CCollision::TestLineBox(const CColLine &line, const CColBox &box)
}
bool
-CCollision::TestVerticalLineBox(const CColLine &line, const CColBox &box)
+CCollision::TestVerticalLineBox(const CColLine &line, const CBox &box)
{
if(line.p0.x <= box.min.x) return false;
if(line.p0.y <= box.min.y) return false;
@@ -1974,7 +1855,7 @@ CColModel::CColModel(void)
vertices = nil;
triangles = nil;
trianglePlanes = nil;
- level = CGame::currLevel;
+ level = 0; // generic col slot
ownsCollisionVolumes = true;
}
diff --git a/src/core/Collision.h b/src/core/Collision.h
index 895f012a..4b0c2fb9 100644
--- a/src/core/Collision.h
+++ b/src/core/Collision.h
@@ -10,26 +10,37 @@
#define MAX_COLLISION_POINTS 32
#endif
-struct CColSphere
+struct CSphere
{
CVector center;
float radius;
+ void Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }
+};
+
+struct CBox
+{
+ CVector min;
+ CVector max;
+ CVector GetSize(void) { return max - min; }
+ void Set(const CVector &min, const CVector &max) { this->min = min; this->max = max; }
+};
+
+struct CColSphere : public CSphere
+{
uint8 surface;
uint8 piece;
void Set(float radius, const CVector &center, uint8 surf, uint8 piece);
- void Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }
+ using CSphere::Set;
};
-struct CColBox
+struct CColBox : public CBox
{
- CVector min;
- CVector max;
uint8 surface;
uint8 piece;
void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
- CVector GetSize(void) { return max - min; }
+ using CBox::Set;
};
struct CColLine
@@ -85,15 +96,16 @@ struct CStoredCollPoly
bool valid;
};
+//--MIAMI: done struct
struct CColModel
{
- CColSphere boundingSphere;
- CColBox boundingBox;
+ CSphere boundingSphere;
+ CBox boundingBox;
int16 numSpheres;
- int16 numLines;
int16 numBoxes;
int16 numTriangles;
- int32 level;
+ int8 numLines;
+ uint8 level; // colstore slot but probably still named level
bool ownsCollisionVolumes;
CColSphere *spheres;
CColLine *lines;
@@ -132,10 +144,10 @@ public:
static void CalculateTrianglePlanes(CColModel *model);
// all these return true if there's a collision
- static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2);
- static bool TestSphereBox(const CColSphere &sph, const CColBox &box);
- static bool TestLineBox(const CColLine &line, const CColBox &box);
- static bool TestVerticalLineBox(const CColLine &line, const CColBox &box);
+ static bool TestSphereSphere(const CSphere &s1, const CSphere &s2);
+ static bool TestSphereBox(const CSphere &sph, const CBox &box);
+ static bool TestLineBox(const CColLine &line, const CBox &box);
+ static bool TestVerticalLineBox(const CColLine &line, const CBox &box);
static bool TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
static bool TestSphereTriangle(const CColSphere &sphere, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp
index 675040ea..c3508a51 100644
--- a/src/core/EventList.cpp
+++ b/src/core/EventList.cpp
@@ -67,8 +67,6 @@ CEventList::RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent
switch(entityType){
case EVENT_ENTITY_PED:
ref = CPools::GetPedRef((CPed*)ent);
- if(ent->GetModelIndex() >= MI_GANG01 && ent->GetModelIndex() <= MI_CRIMINAL02)
- copsDontCare = true;
break;
case EVENT_ENTITY_VEHICLE:
ref = CPools::GetVehicleRef((CVehicle*)ent);
diff --git a/src/core/EventList.h b/src/core/EventList.h
index 8840afc4..f2c3d7a8 100644
--- a/src/core/EventList.h
+++ b/src/core/EventList.h
@@ -22,10 +22,12 @@ enum eEventType
EVENT_PED_SET_ON_FIRE,
EVENT_COP_SET_ON_FIRE,
EVENT_CAR_SET_ON_FIRE,
- EVENT_ASSAULT_NASTYWEAPON, // not sure
+ EVENT_ASSAULT_NASTYWEAPON,
+ EVENT_ASSAULT_NASTYWEAPON_POLICE,
EVENT_ICECREAM,
EVENT_ATM,
- EVENT_SHOPSTALL, // used on graffitis
+ EVENT_SHOPSTALL,
+ EVENT_SHOPWINDOW,
EVENT_LAST_EVENT
};
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index 6e7188c5..1463b4a5 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -1,4 +1,5 @@
#include "common.h"
+#include <ctype.h>
#include "main.h"
#include "Quaternion.h"
@@ -24,6 +25,11 @@
#include "ZoneCull.h"
#include "CdStream.h"
#include "FileLoader.h"
+#include "Streaming.h"
+#include "ColStore.h"
+#include "Occlusion.h"
+
+//--MIAMI: file done
char CFileLoader::ms_line[256];
@@ -46,14 +52,12 @@ CFileLoader::LoadLevel(const char *filename)
{
int fd;
RwTexDictionary *savedTxd;
- eLevelName savedLevel;
bool objectsLoaded;
char *line;
char txdname[64];
savedTxd = RwTexDictionaryGetCurrent();
objectsLoaded = false;
- savedLevel = CGame::currLevel;
if(savedTxd == nil){
savedTxd = RwTexDictionaryCreate();
RwTexDictionarySetCurrent(savedTxd);
@@ -77,12 +81,8 @@ CFileLoader::LoadLevel(const char *filename)
AddTexDictionaries(savedTxd, txd);
RwTexDictionaryDestroy(txd);
}else if(strncmp(line, "COLFILE", 7) == 0){
- int level;
- sscanf(line+8, "%d", &level);
- CGame::currLevel = (eLevelName)level;
LoadingScreenLoadingFile(line+10);
- LoadCollisionFile(line+10);
- CGame::currLevel = savedLevel;
+ LoadCollisionFile(line+10, 0);
}else if(strncmp(line, "MODELFILE", 9) == 0){
LoadingScreenLoadingFile(line + 10);
LoadModelFile(line + 10);
@@ -94,15 +94,17 @@ CFileLoader::LoadLevel(const char *filename)
LoadObjectTypes(line + 4);
}else if(strncmp(line, "IPL", 3) == 0){
if(!objectsLoaded){
- CModelInfo::ConstructMloClumps();
+ LoadingScreenLoadingFile("Collision");
CObjectData::Initialise("DATA\\OBJECT.DAT");
+ CStreaming::Init();
+ CColStore::LoadAllCollision();
+ for(int i = 0; i < MODELINFOSIZE; i++)
+ if(CModelInfo::GetModelInfo(i))
+ CModelInfo::GetModelInfo(i)->ConvertAnimFileIndex();
objectsLoaded = true;
}
LoadingScreenLoadingFile(line + 4);
LoadScene(line + 4);
- }else if(strncmp(line, "MAPZONE", 7) == 0){
- LoadingScreenLoadingFile(line + 8);
- LoadMapZones(line + 8);
}else if(strncmp(line, "SPLASH", 6) == 0){
LoadSplash(GetRandomSplashScreen());
}else if(strncmp(line, "CDIMAGE", 7) == 0){
@@ -112,30 +114,13 @@ CFileLoader::LoadLevel(const char *filename)
CFileMgr::CloseFile(fd);
RwTexDictionarySetCurrent(savedTxd);
-}
-
-void
-CFileLoader::LoadCollisionFromDatFile(int currlevel)
-{
- int fd;
- char *line;
-
- fd = CFileMgr::OpenFile(CGame::aDatFile, "r");
- assert(fd > 0);
-
- for(line = LoadLine(fd); line; line = LoadLine(fd)){
- if(*line == '#')
- continue;
-
- if(strncmp(line, "COLFILE", 7) == 0){
- int level;
- sscanf(line+8, "%d", &level);
- if(currlevel == level)
- LoadCollisionFile(line+10);
- }
- }
- CFileMgr::CloseFile(fd);
+ int i;
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(CColStore::GetSlot(i))
+ CColStore::GetBoundingBox(i).Grow(120.0f);
+ CWorld::RepositionCertainDynamicObjects();
+ CColStore::RemoveAllCollision();
}
char*
@@ -179,7 +164,7 @@ struct ColHeader
};
void
-CFileLoader::LoadCollisionFile(const char *filename)
+CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot)
{
int fd;
char modelname[24];
@@ -188,6 +173,7 @@ CFileLoader::LoadCollisionFile(const char *filename)
debug("Loading collision file %s\n", filename);
fd = CFileMgr::OpenFile(filename, "rb");
+ assert(fd > 0);
while(CFileMgr::Read(fd, (char*)&header, sizeof(header))){
assert(strncmp(header.ident, "COLL", 4) == 0);
@@ -196,10 +182,11 @@ CFileLoader::LoadCollisionFile(const char *filename)
mi = CModelInfo::GetModelInfo(modelname, nil);
if(mi){
- if(mi->GetColModel()){
+ if(mi->GetColModel() && mi->DoesOwnColModel()){
LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname);
}else{
CColModel *model = new CColModel;
+ model->level = colSlot;
LoadCollisionModel(work_buff+24, *model, modelname);
mi->SetColModel(model, true);
}
@@ -211,6 +198,79 @@ CFileLoader::LoadCollisionFile(const char *filename)
CFileMgr::CloseFile(fd);
}
+
+bool
+CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot)
+{
+ uint32 modelsize;
+ char modelname[24];
+ CBaseModelInfo *mi;
+ ColHeader *header;
+ int modelIndex;
+
+ while(size > 8){
+ header = (ColHeader*)buffer;
+ modelsize = header->size;
+ if(strncmp(header->ident, "COLL", 4) != 0)
+ return size-8 < CDSTREAM_SECTOR_SIZE;
+ memcpy(modelname, buffer+8, 24);
+ memcpy(work_buff, buffer+32, modelsize-24);
+ size -= 32 + (modelsize-24);
+ buffer += 32 + (modelsize-24);
+ if(modelsize > 15*1024)
+ debug("colmodel %s is huge, size %d\n", modelname, modelsize);
+
+ mi = CModelInfo::GetModelInfo(modelname, &modelIndex);
+ if(mi){
+ CColStore::IncludeModelIndex(colSlot, modelIndex);
+ CColModel *model = new CColModel;
+ model->level = colSlot;
+ LoadCollisionModel(work_buff, *model, modelname);
+ mi->SetColModel(model, true);
+ }else{
+ debug("colmodel %s can't find a modelinfo\n", modelname);
+ }
+ }
+ return true;
+}
+
+bool
+CFileLoader::LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot)
+{
+ uint32 modelsize;
+ char modelname[24];
+ CBaseModelInfo *mi;
+ ColHeader *header;
+
+ while(size > 8){
+ header = (ColHeader*)buffer;
+ modelsize = header->size;
+ if(strncmp(header->ident, "COLL", 4) != 0)
+ return size-8 < CDSTREAM_SECTOR_SIZE;
+ memcpy(modelname, buffer+8, 24);
+ memcpy(work_buff, buffer+32, modelsize-24);
+ size -= 32 + (modelsize-24);
+ buffer += 32 + (modelsize-24);
+ if(modelsize > 15*1024)
+ debug("colmodel %s is huge, size %d\n", modelname, modelsize);
+
+ mi = CModelInfo::GetModelInfo(modelname, CColStore::GetSlot(colSlot)->minIndex, CColStore::GetSlot(colSlot)->maxIndex);
+ if(mi){
+ if(mi->GetColModel()){
+ LoadCollisionModel(work_buff, *mi->GetColModel(), modelname);
+ }else{
+ CColModel *model = new CColModel;
+ model->level = colSlot;
+ LoadCollisionModel(work_buff, *model, modelname);
+ mi->SetColModel(model, true);
+ }
+ }else{
+ debug("colmodel %s can't find a modelinfo\n", modelname);
+ }
+ }
+ return true;
+}
+
void
CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
{
@@ -240,13 +300,15 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.numLines = *(int16*)buf;
buf += 4;
if(model.numLines > 0){
- model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine));
+ //model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine));
for(i = 0; i < model.numLines; i++){
- model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12));
+ //model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12));
buf += 24;
}
}else
model.lines = nil;
+ model.numLines = 0;
+ model.lines = nil;
model.numBoxes = *(int16*)buf;
buf += 4;
@@ -265,10 +327,12 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector));
for(i = 0; i < numVertices; i++){
model.vertices[i] = *(CVector*)buf;
+#if 0
if(Abs(model.vertices[i].x) >= 256.0f ||
Abs(model.vertices[i].y) >= 256.0f ||
Abs(model.vertices[i].z) >= 256.0f)
printf("%s:Collision volume too big\n", modelname);
+#endif
buf += 12;
}
}else
@@ -291,7 +355,7 @@ GetNameAndLOD(char *nodename, char *name, int *n)
{
char *underscore = nil;
for(char *s = nodename; *s != '\0'; s++){
- if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L'))
+ if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L') && isdigit(s[2]))
underscore = s;
}
if(underscore){
@@ -317,11 +381,11 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil);
if(mi){
assert(mi->IsSimple());
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
mi->SetAtomic(n, atomic);
RpClumpRemoveAtomic(clump, atomic);
RpAtomicSetFrame(atomic, RwFrameCreate());
CVisibilityPlugins::SetAtomicModelInfo(atomic, mi);
- CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
}else{
debug("Can't find Atomic %s\n", name);
}
@@ -387,14 +451,6 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id)
return false;
mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);
mi->SetClump(clump);
- if (mi->GetModelType() == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) {
- // Read LOD ped
- clump = RpClumpStreamRead(stream);
- if(clump){
- ((CPedModelInfo*)mi)->SetLowDetailClump(clump);
- RpClumpDestroy(clump);
- }
- }
return true;
}
@@ -456,11 +512,11 @@ CFileLoader::SetRelatedModelInfoCB(RpAtomic *atomic, void *data)
nodename = GetFrameNodeName(RpAtomicGetFrame(atomic));
GetNameAndLOD(nodename, name, &n);
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
gpRelatedModelInfo->SetAtomic(n, atomic);
RpClumpRemoveAtomic(clump, atomic);
RpAtomicSetFrame(atomic, RwFrameCreate());
CVisibilityPlugins::SetAtomicModelInfo(atomic, gpRelatedModelInfo);
- CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
return atomic;
}
@@ -498,8 +554,9 @@ CFileLoader::LoadObjectTypes(const char *filename)
enum {
NONE,
OBJS,
- MLO,
+ MLO, // unused but enum still has it
TOBJ,
+ WEAP,
HIER,
CARS,
PEDS,
@@ -510,16 +567,17 @@ CFileLoader::LoadObjectTypes(const char *filename)
int fd;
int section;
int pathIndex;
- char pathTypeStr[20];
int id, pathType;
- int mlo;
+ int minID, maxID;
section = NONE;
+ minID = INT32_MAX;
+ maxID = -1;
pathIndex = -1;
- mlo = 0;
debug("Loading object types from %s...\n", filename);
fd = CFileMgr::OpenFile(filename, "rb");
+ assert(fd > 0);
for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){
if(*line == '\0' || *line == '#')
continue;
@@ -527,25 +585,27 @@ CFileLoader::LoadObjectTypes(const char *filename)
if(section == NONE){
if(strncmp(line, "objs", 4) == 0) section = OBJS;
else if(strncmp(line, "tobj", 4) == 0) section = TOBJ;
+ else if(strncmp(line, "weap", 4) == 0) section = WEAP;
else if(strncmp(line, "hier", 4) == 0) section = HIER;
else if(strncmp(line, "cars", 4) == 0) section = CARS;
else if(strncmp(line, "peds", 4) == 0) section = PEDS;
else if(strncmp(line, "path", 4) == 0) section = PATH;
else if(strncmp(line, "2dfx", 4) == 0) section = TWODFX;
}else if(strncmp(line, "end", 3) == 0){
- section = section == MLO ? OBJS : NONE;
+ section = NONE;
}else switch(section){
case OBJS:
- if(strncmp(line, "sta", 3) == 0)
- mlo = LoadMLO(line);
- else
- LoadObject(line);
- break;
- case MLO:
- LoadMLOInstance(mlo, line);
+ id = LoadObject(line);
+ if(id > maxID) maxID = id;
+ if(id < minID) minID = id;
break;
case TOBJ:
- LoadTimeObject(line);
+ id = LoadTimeObject(line);
+ if(id > maxID) maxID = id;
+ if(id < minID) minID = id;
+ break;
+ case WEAP:
+ LoadWeaponObject(line);
break;
case HIER:
LoadClumpObject(line);
@@ -558,17 +618,15 @@ CFileLoader::LoadObjectTypes(const char *filename)
break;
case PATH:
if(pathIndex == -1){
- id = LoadPathHeader(line, pathTypeStr);
- if(strncmp(pathTypeStr, "ped", 4) == 0)
- pathType = 1;
- else if(strncmp(pathTypeStr, "car", 4) == 0)
- pathType = 0;
+ id = LoadPathHeader(line, pathType);
pathIndex = 0;
}else{
- if(pathType == 1)
+ if(pathType == 0)
LoadPedPathNode(line, id, pathIndex);
- else if(pathType == 0)
- LoadCarPathNode(line, id, pathIndex);
+ else if (pathType == 1)
+ LoadCarPathNode(line, id, pathIndex, false);
+ else if (pathType == 2)
+ LoadCarPathNode(line, id, pathIndex, true);
pathIndex++;
if(pathIndex == 12)
pathIndex = -1;
@@ -581,26 +639,30 @@ CFileLoader::LoadObjectTypes(const char *filename)
}
CFileMgr::CloseFile(fd);
- for(id = 0; id < MODELINFOSIZE; id++){
+ for(id = minID; id <= maxID; id++){
CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
- if(mi && mi->IsSimple())
- mi->SetupBigBuilding();
+ if(mi && mi->IsBuilding())
+ mi->SetupBigBuilding(minID, maxID);
}
}
void
SetModelInfoFlags(CSimpleModelInfo *mi, uint32 flags)
{
- mi->m_normalCull = !!(flags & 1);
+ mi->m_wetRoadReflection = !!(flags & 1);
mi->m_noFade = !!(flags & 2);
mi->m_drawLast = !!(flags & (4|8));
mi->m_additive = !!(flags & 8);
mi->m_isSubway = !!(flags & 0x10);
mi->m_ignoreLight = !!(flags & 0x20);
mi->m_noZwrite = !!(flags & 0x40);
+ mi->m_noShadows = !!(flags & 0x80);
+ mi->m_ignoreDrawDist = !!(flags & 0x100);
+ mi->m_isCodeGlass = !!(flags & 0x200);
+ mi->m_isArtistGlass = !!(flags & 0x400);
}
-void
+int
CFileLoader::LoadObject(const char *line)
{
int id, numObjs;
@@ -611,7 +673,7 @@ CFileLoader::LoadObject(const char *line)
CSimpleModelInfo *mi;
if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4)
- return;
+ return 0; // game returns return value
switch(numObjs){
case 1:
@@ -643,60 +705,11 @@ CFileLoader::LoadObject(const char *line)
mi->m_firstDamaged = damaged;
mi->SetTexDictionary(txd);
MatchModelString(model, id);
-}
-int
-CFileLoader::LoadMLO(const char *line)
-{
- char smth[8];
- char name[24];
- int modelIndex;
- float someFloat;
-
- sscanf(line, "%s %s %d %f", smth, name, &modelIndex, &someFloat);
- CMloModelInfo *minfo = CModelInfo::AddMloModel(modelIndex);
- minfo->SetName(name);
- minfo->field_34 = someFloat;
- int instId = CModelInfo::GetMloInstanceStore().allocPtr;
- minfo->firstInstance = instId;
- minfo->lastInstance = instId;
- minfo->SetTexDictionary("generic");
- return modelIndex;
-}
-
-void
-CFileLoader::LoadMLOInstance(int id, const char *line)
-{
- char name[24];
- RwV3d pos, scale, rot;
- float angle;
- int modelIndex;
-
- CMloModelInfo *minfo = (CMloModelInfo*)CModelInfo::GetModelInfo(id);
- sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f",
- &modelIndex,
- name,
- &pos.x, &pos.y, &pos.z,
- &scale.x, &scale.y, &scale.z,
- &rot.x, &rot.y, &rot.z,
- &angle);
- float rad = Acos(angle) * 2.0f;
- CInstance *inst = CModelInfo::GetMloInstanceStore().alloc();
- minfo->lastInstance++;
-
- RwMatrix *matrix = RwMatrixCreate();
- RwMatrixScale(matrix, &scale, rwCOMBINEREPLACE);
- RwMatrixRotate(matrix, &rot, -RADTODEG(rad), rwCOMBINEPOSTCONCAT);
- RwMatrixTranslate(matrix, &pos, rwCOMBINEPOSTCONCAT);
-
- inst->GetMatrix() = CMatrix(matrix);
- inst->GetMatrix().UpdateRW();
-
- inst->m_modelIndex = modelIndex;
- RwMatrixDestroy(matrix);
+ return id;
}
-void
+int
CFileLoader::LoadTimeObject(const char *line)
{
int id, numObjs;
@@ -708,7 +721,7 @@ CFileLoader::LoadTimeObject(const char *line)
CTimeModelInfo *mi, *other;
if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4)
- return;
+ return 0; // game returns return value
switch(numObjs){
case 1:
@@ -744,6 +757,29 @@ CFileLoader::LoadTimeObject(const char *line)
if(other)
other->SetOtherTimeModel(id);
MatchModelString(model, id);
+
+ return id;
+}
+
+int
+CFileLoader::LoadWeaponObject(const char *line)
+{
+ int id, numObjs;
+ char model[24], txd[24], animFile[16];
+ float dist;
+ CWeaponModelInfo *mi;
+
+ sscanf(line, "%d %s %s %s %d %f", &id, model, txd, animFile, &numObjs, &dist);
+
+ mi = CModelInfo::AddWeaponModel(id);
+ mi->SetName(model);
+ mi->SetNumAtomics(1);
+ mi->m_lodDistances[0] = dist;
+ mi->SetTexDictionary(txd);
+ mi->SetAnimFile(animFile);
+ mi->SetColModel(&CTempColModels::ms_colModelWeapon);
+ MatchModelString(model, id);
+ return id;
}
void
@@ -766,21 +802,22 @@ CFileLoader::LoadVehicleObject(const char *line)
{
int id;
char model[24], txd[24];
- char type[8], handlingId[16], gamename[32], vehclass[12];
+ char type[8], handlingId[16], gamename[32], animFile[16], vehclass[12];
uint32 frequency, comprules;
int32 level, misc;
float wheelScale;
CVehicleModelInfo *mi;
char *p;
- sscanf(line, "%d %s %s %s %s %s %s %d %d %x %d %f",
+ sscanf(line, "%d %s %s %s %s %s %s %s %d %d %x %d %f",
&id, model, txd,
- type, handlingId, gamename, vehclass,
+ type, handlingId, gamename, animFile, vehclass,
&frequency, &level, &comprules, &misc, &wheelScale);
mi = CModelInfo::AddVehicleModel(id);
mi->SetName(model);
mi->SetTexDictionary(txd);
+ mi->SetAnimFile(animFile);
for(p = gamename; *p; p++)
if(*p == '_') *p = ' ';
strcpy(mi->m_gameName, gamename);
@@ -810,36 +847,34 @@ CFileLoader::LoadVehicleObject(const char *line)
mi->m_handlingId = mod_HandlingManager.GetHandlingId(handlingId);
- // Well this is kinda dumb....
- if(strncmp(vehclass, "poorfamily", 11) == 0){
+ if(strncmp(vehclass, "normal", 7) == 0)
+ mi->m_vehicleClass = CCarCtrl::NORMAL;
+ else if(strncmp(vehclass, "poorfamily", 11) == 0)
mi->m_vehicleClass = CCarCtrl::POOR;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::POOR);
- }else if(strncmp(vehclass, "richfamily", 11) == 0){
+ else if(strncmp(vehclass, "richfamily", 11) == 0)
mi->m_vehicleClass = CCarCtrl::RICH;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::RICH);
- }else if(strncmp(vehclass, "executive", 10) == 0){
+ else if(strncmp(vehclass, "executive", 10) == 0)
mi->m_vehicleClass = CCarCtrl::EXEC;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::EXEC);
- }else if(strncmp(vehclass, "worker", 7) == 0){
+ else if(strncmp(vehclass, "worker", 7) == 0)
mi->m_vehicleClass = CCarCtrl::WORKER;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::WORKER);
- }else if(strncmp(vehclass, "special", 8) == 0){
- mi->m_vehicleClass = CCarCtrl::SPECIAL;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::SPECIAL);
- }else if(strncmp(vehclass, "big", 4) == 0){
+ else if(strncmp(vehclass, "big", 4) == 0)
mi->m_vehicleClass = CCarCtrl::BIG;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::BIG);
- }else if(strncmp(vehclass, "taxi", 5) == 0){
+ else if(strncmp(vehclass, "taxi", 5) == 0)
mi->m_vehicleClass = CCarCtrl::TAXI;
- while(frequency-- > 0)
- CCarCtrl::AddToCarArray(id, CCarCtrl::TAXI);
+ else if(strncmp(vehclass, "moped", 6) == 0)
+ mi->m_vehicleClass = CCarCtrl::MOPED;
+ else if(strncmp(vehclass, "motorbike", 10) == 0)
+ mi->m_vehicleClass = CCarCtrl::MOTORBIKE;
+ else if(strncmp(vehclass, "leisureboat", 12) == 0)
+ mi->m_vehicleClass = CCarCtrl::LEISUREBOAT;
+ else if(strncmp(vehclass, "workerboat", 11) == 0)
+ mi->m_vehicleClass = CCarCtrl::WORKERBOAT;
+ else if(strncmp(vehclass, "ignore", 11) == 0){
+ mi->m_vehicleClass = -1;
+ return;
}
+ CCarCtrl::AddToCarArray(id, mi->m_vehicleClass);
+ mi->m_frequency = frequency;
}
void
@@ -847,67 +882,87 @@ CFileLoader::LoadPedObject(const char *line)
{
int id;
char model[24], txd[24];
- char pedType[24], pedStats[24], animGroup[24];
+ char pedType[24], pedStats[24], animGroup[24], animFile[16];
int carsCanDrive;
CPedModelInfo *mi;
int animGroupId;
+ int radio1, radio2;
- if(sscanf(line, "%d %s %s %s %s %s %x",
+ sscanf(line, "%d %s %s %s %s %s %x %s %d %d",
&id, model, txd,
- pedType, pedStats, animGroup, &carsCanDrive) != 7)
- return;
+ pedType, pedStats, animGroup, &carsCanDrive,
+ animFile, &radio1, &radio2);
mi = CModelInfo::AddPedModel(id);
mi->SetName(model);
mi->SetTexDictionary(txd);
+ mi->SetAnimFile(animFile);
mi->SetColModel(&CTempColModels::ms_colModelPed1);
mi->m_pedType = CPedType::FindPedType(pedType);
mi->m_pedStatType = CPedStats::GetPedStatType(pedStats);
for(animGroupId = 0; animGroupId < NUM_ANIM_ASSOC_GROUPS; animGroupId++)
if(strcmp(animGroup, CAnimManager::GetAnimGroupName((AssocGroupId)animGroupId)) == 0)
break;
+ assert(animGroupId < NUM_ANIM_ASSOC_GROUPS);
mi->m_animGroup = animGroupId;
mi->m_carsCanDrive = carsCanDrive;
-
- // ???
- CModelInfo::GetModelInfo(MI_LOPOLYGUY)->SetColModel(&CTempColModels::ms_colModelPed1);
+ mi->radio1 = radio1;
+ mi->radio2 = radio2;
}
int
-CFileLoader::LoadPathHeader(const char *line, char *type)
+CFileLoader::LoadPathHeader(const char *line, int &type)
{
int id;
char modelname[32];
- sscanf(line, "%s %d %s", type, &id, modelname);
+ sscanf(line, "%d %d %s", &type, &id, modelname);
return id;
}
void
CFileLoader::LoadPedPathNode(const char *line, int id, int node)
{
- int type, next, cross;
- float x, y, z, width;
-
- sscanf(line, "%d %d %d %f %f %f %f", &type, &next, &cross, &x, &y, &z, &width);
- ThePaths.StoreNodeInfoPed(id, node, type, next, x, y, z, 0, !!cross);
+ int type, next, cross, numLeft, numRight, speed, flags;
+ float x, y, z, width, spawnRate;
+
+ if(sscanf(line, "%d %d %d %f %f %f %f %d %d %d %d %f",
+ &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight,
+ &speed, &flags, &spawnRate) != 12)
+ spawnRate = 1.0f;
+
+ if(id == -1)
+ ThePaths.StoreDetachedNodeInfoPed(node, type, next, x, y, z,
+ width, !!cross, !!(flags&1), !!(flags&4), spawnRate*15.0f);
+ else
+ ThePaths.StoreNodeInfoPed(id, node, type, next, x, y, z,
+ width, !!cross, spawnRate*15.0f);
}
void
-CFileLoader::LoadCarPathNode(const char *line, int id, int node)
+CFileLoader::LoadCarPathNode(const char *line, int id, int node, bool waterPath)
{
- int type, next, cross, numLeft, numRight;
- float x, y, z, width;
-
- sscanf(line, "%d %d %d %f %f %f %f %d %d", &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight);
- ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight);
+ int type, next, cross, numLeft, numRight, speed, flags;
+ float x, y, z, width, spawnRate;
+
+ if(sscanf(line, "%d %d %d %f %f %f %f %d %d %d %d %f",
+ &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight,
+ &speed, &flags, &spawnRate) != 12)
+ spawnRate = 1.0f;
+
+ if(id == -1)
+ ThePaths.StoreDetachedNodeInfoCar(node, type, next, x, y, z, width, numLeft, numRight,
+ !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15, false);
+ else
+ ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight,
+ !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15);
}
void
CFileLoader::Load2dEffect(const char *line)
{
- int id, r, g, b, a, type;
+ int id, r, g, b, a, type, ptype;
float x, y, z;
char corona[32], shadow[32];
int shadowIntens, lightType, roadReflection, flare, flags, probability;
@@ -980,6 +1035,18 @@ CFileLoader::Load2dEffect(const char *line)
effect->attractor.flags = flags;
effect->attractor.probability = probability;
break;
+ case EFFECT_PED_ATTRACTOR:
+ sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f",
+ &id, &x, &y, &z, &r, &g, &b, &a, &type,
+ &ptype,
+ &effect->pedattr.queueDir.x,
+ &effect->pedattr.queueDir.y,
+ &effect->pedattr.queueDir.z,
+ &effect->pedattr.useDir.x,
+ &effect->pedattr.useDir.y,
+ &effect->pedattr.useDir.z);
+ effect->pedattr.type = ptype;
+ break;
}
CTxdStore::PopCurrentTxd();
@@ -993,20 +1060,21 @@ CFileLoader::LoadScene(const char *filename)
INST,
ZONE,
CULL,
+ OCCL,
PICK,
PATH,
};
char *line;
int fd;
int section;
- int pathIndex;
- char pathTypeStr[20];
+ int pathType, pathIndex;
section = NONE;
pathIndex = -1;
debug("Creating objects from %s...\n", filename);
fd = CFileMgr::OpenFile(filename, "rb");
+ assert(fd > 0);
for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){
if(*line == '\0' || *line == '#')
continue;
@@ -1017,6 +1085,7 @@ CFileLoader::LoadScene(const char *filename)
else if(strncmp(line, "cull", 4) == 0) section = CULL;
else if(strncmp(line, "pick", 4) == 0) section = PICK;
else if(strncmp(line, "path", 4) == 0) section = PATH;
+ else if(strncmp(line, "occl", 4) == 0) section = OCCL;
}else if(strncmp(line, "end", 3) == 0){
section = NONE;
}else switch(section){
@@ -1029,18 +1098,24 @@ CFileLoader::LoadScene(const char *filename)
case CULL:
LoadCullZone(line);
break;
+ case OCCL:
+ LoadOcclusionVolume(line);
+ break;
case PICK:
// unused
LoadPickup(line);
break;
case PATH:
- // unfinished in the game
if(pathIndex == -1){
- LoadPathHeader(line, pathTypeStr);
- // type not set
+ LoadPathHeader(line, pathType);
pathIndex = 0;
}else{
- // nodes not loaded
+ if(pathType == 0)
+ LoadPedPathNode(line, -1, pathIndex);
+ else if (pathType == 1)
+ LoadCarPathNode(line, -1, pathIndex, false);
+ else if (pathType == 2)
+ LoadCarPathNode(line, -1, pathIndex, true);
pathIndex++;
if(pathIndex == 12)
pathIndex = -1;
@@ -1063,18 +1138,30 @@ CFileLoader::LoadObjectInstance(const char *line)
CSimpleModelInfo *mi;
RwMatrix *xform;
CEntity *entity;
- if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f",
- &id, name,
+ float area;
+
+ if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f %f",
+ &id, name, &area,
&trans.x, &trans.y, &trans.z,
&scale.x, &scale.y, &scale.z,
- &axis.x, &axis.y, &axis.z, &angle) != 12)
- return;
+ &axis.x, &axis.y, &axis.z, &angle) != 13){
+ if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f",
+ &id, name,
+ &trans.x, &trans.y, &trans.z,
+ &scale.x, &scale.y, &scale.z,
+ &axis.x, &axis.y, &axis.z, &angle) != 12)
+ return;
+ area = 0;
+ }
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
if(mi == nil)
return;
assert(mi->IsSimple());
+ if(!CStreaming::IsObjectInCdImage(id))
+ debug("Not in cdimage %s\n", mi->GetName());
+
angle = -RADTODEG(2.0f * acosf(angle));
xform = RwMatrixCreate();
RwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE);
@@ -1089,7 +1176,8 @@ CFileLoader::LoadObjectInstance(const char *line)
entity->SetModelIndexNoCreate(id);
entity->GetMatrix() = CMatrix(xform);
entity->m_level = CTheZones::GetLevelFromPosition(&entity->GetPosition());
- if(mi->IsSimple()){
+ entity->m_area = area;
+ if(mi->IsBuilding()){
if(mi->m_isBigBuilding)
entity->SetupBigBuilding();
if(mi->m_isSubway)
@@ -1098,14 +1186,25 @@ CFileLoader::LoadObjectInstance(const char *line)
if(mi->GetLargestLodDistance() < 2.0f)
entity->bIsVisible = false;
CWorld::Add(entity);
+
+ CColModel *col = entity->GetColModel();
+ if(col->numSpheres || col->numBoxes || col->numTriangles){
+ if(col->level != 0)
+ CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect());
+ }else
+ entity->bUsesCollision = false;
+
+ if(entity->GetPosition().z + col->boundingBox.min.z < 6.0f)
+ entity->bUnderwater = true;
}else{
entity = new CDummyObject;
entity->SetModelIndexNoCreate(id);
entity->GetMatrix() = CMatrix(xform);
CWorld::Add(entity);
- if(IsGlass(entity->GetModelIndex()))
+ if(IsGlass(entity->GetModelIndex()) && !mi->m_isArtistGlass)
entity->bIsVisible = false;
entity->m_level = CTheZones::GetLevelFromPosition(&entity->GetPosition());
+ entity->m_area = area;
}
RwMatrixDestroy(xform);
@@ -1151,53 +1250,21 @@ CFileLoader::LoadPickup(const char *line)
}
void
-CFileLoader::LoadMapZones(const char *filename)
+CFileLoader::LoadOcclusionVolume(const char *line)
{
- enum {
- NONE,
- INST,
- ZONE,
- CULL,
- PICK,
- PATH,
- };
- char *line;
- int fd;
- int section;
-
- section = NONE;
- debug("Creating zones from %s...\n", filename);
-
- fd = CFileMgr::OpenFile(filename, "rb");
- for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){
- if(*line == '\0' || *line == '#')
- continue;
-
- if(section == NONE){
- if(strncmp(line, "zone", 4) == 0) section = ZONE;
- }else if(strncmp(line, "end", 3) == 0){
- section = NONE;
- }else switch(section){
- case ZONE: {
- char name[24];
- int type, level;
- float minx, miny, minz;
- float maxx, maxy, maxz;
- if(sscanf(line, "%s %d %f %f %f %f %f %f %d",
- name, &type,
- &minx, &miny, &minz,
- &maxx, &maxy, &maxz,
- &level) == 9)
- CTheZones::CreateMapZone(name, (eZoneType)type, minx, miny, minz, maxx, maxy, maxz, (eLevelName)level);
- }
- break;
- }
- }
- CFileMgr::CloseFile(fd);
+ float x, y, z;
+ float width, length, height;
+ float angle;
- debug("Finished loading IPL\n");
+ sscanf(line, "%f %f %f %f %f %f %f",
+ &x, &y, &z,
+ &width, &length, &height,
+ &angle);
+ COcclusion::AddOne(x, y, z, width, length, z + height/2.0f, angle);
}
+
+//--MIAMI: unused
void
CFileLoader::ReloadPaths(const char *filename)
{
@@ -1208,10 +1275,10 @@ CFileLoader::ReloadPaths(const char *filename)
char *line;
int section = NONE;
int id, pathType, pathIndex = -1;
- char pathTypeStr[20];
debug("Reloading paths from %s...\n", filename);
int fd = CFileMgr::OpenFile(filename, "r");
+ assert(fd > 0);
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
if (*line == '\0' || *line == '#')
continue;
@@ -1227,17 +1294,15 @@ CFileLoader::ReloadPaths(const char *filename)
switch (section) {
case PATH:
if (pathIndex == -1) {
- id = LoadPathHeader(line, pathTypeStr);
- if (strncmp(pathTypeStr, "ped", 4) == 0)
- pathType = 1;
- else if (strncmp(pathTypeStr, "car", 4) == 0)
- pathType = 0;
+ id = LoadPathHeader(line, pathType);
pathIndex = 0;
} else {
- if (pathType == 1)
+ if(pathType == 0)
LoadPedPathNode(line, id, pathIndex);
- else if (pathType == 0)
- LoadCarPathNode(line, id, pathIndex);
+ else if (pathType == 1)
+ LoadCarPathNode(line, id, pathIndex, false);
+ else if (pathType == 2)
+ LoadCarPathNode(line, id, pathIndex, true);
pathIndex++;
if (pathIndex == 12)
pathIndex = -1;
@@ -1267,6 +1332,7 @@ CFileLoader::ReloadObjectTypes(const char *filename)
CFileMgr::ChangeDir("\\DATA\\MAPS\\");
int fd = CFileMgr::OpenFile(filename, "r");
+ assert(fd > 0);
CFileMgr::ChangeDir("\\");
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
if (*line == '\0' || *line == '#')
@@ -1342,6 +1408,7 @@ CFileLoader::ReLoadScene(const char *filename)
char *line;
CFileMgr::ChangeDir("\\DATA\\");
int fd = CFileMgr::OpenFile(filename, "r");
+ assert(fd > 0);
CFileMgr::ChangeDir("\\");
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
diff --git a/src/core/FileLoader.h b/src/core/FileLoader.h
index 87b8fe61..077e7bdd 100644
--- a/src/core/FileLoader.h
+++ b/src/core/FileLoader.h
@@ -5,10 +5,11 @@ class CFileLoader
static char ms_line[256];
public:
static void LoadLevel(const char *filename);
- static void LoadCollisionFromDatFile(int currlevel);
static char *LoadLine(int fd);
static RwTexDictionary *LoadTexDictionary(const char *filename);
- static void LoadCollisionFile(const char *filename);
+ static void LoadCollisionFile(const char *filename, uint8 colSlot);
+ static bool LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot);
+ static bool LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot);
static void LoadCollisionModel(uint8 *buf, struct CColModel &model, char *name);
static void LoadModelFile(const char *filename);
static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data);
@@ -22,16 +23,15 @@ public:
static void AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src);
static void LoadObjectTypes(const char *filename);
- static void LoadObject(const char *line);
- static int LoadMLO(const char *line);
- static void LoadMLOInstance(int id, const char *line);
- static void LoadTimeObject(const char *line);
+ static int LoadObject(const char *line);
+ static int LoadTimeObject(const char *line);
+ static int LoadWeaponObject(const char *line);
static void LoadClumpObject(const char *line);
static void LoadVehicleObject(const char *line);
static void LoadPedObject(const char *line);
- static int LoadPathHeader(const char *line, char *type);
+ static int LoadPathHeader(const char *line, int &type);
static void LoadPedPathNode(const char *line, int id, int node);
- static void LoadCarPathNode(const char *line, int id, int node);
+ static void LoadCarPathNode(const char *line, int id, int node, bool waterPath);
static void Load2dEffect(const char *line);
static void LoadScene(const char *filename);
@@ -39,8 +39,7 @@ public:
static void LoadZone(const char *line);
static void LoadCullZone(const char *line);
static void LoadPickup(const char *line);
-
- static void LoadMapZones(const char *filename);
+ static void LoadOcclusionVolume(const char *line);
static void ReloadPaths(const char *filename);
static void ReloadObjectTypes(const char *filename);
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index d58d0576..dd840bdc 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -37,6 +37,18 @@
#include "Messages.h"
#include "FileLoader.h"
+// Similar story to Hud.cpp:
+// Game has colors inlined in code.
+// For easier modification we collect them here:
+CRGBA LABEL_COLOR(255, 150, 225, 255);
+CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255);
+CRGBA MENUOPTION_COLOR(255, 150, 225, 255);
+CRGBA SELECTEDMENUOPTION_COLOR(255, 150, 225, 255);
+CRGBA HEADER_COLOR(255, 150, 255, 255);
+CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255);
+CRGBA SLIDERON_COLOR(97, 194, 247, 255);
+CRGBA SLIDEROFF_COLOR(27, 89, 130, 255);
+
#define TIDY_UP_PBP // ProcessButtonPresses
#define MAX_VISIBLE_LIST_ROW 30
#define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result
@@ -149,53 +161,7 @@ bool CMenuManager::m_PrefsMarketing = false;
bool CMenuManager::m_PrefsDisableTutorials = false;
#endif // !MASTER
-// 0x5F311C
-const char* FrontendFilenames[][2] = {
- {"fe2_mainpanel_ul", "" },
- {"fe2_mainpanel_ur", "" },
- {"fe2_mainpanel_dl", "" },
- {"fe2_mainpanel_dr", "" },
- {"fe2_mainpanel_dr2", "" },
- {"fe2_tabactive", "" },
- {"fe_iconbrief", "" },
- {"fe_iconstats", "" },
- {"fe_iconcontrols", "" },
- {"fe_iconsave", "" },
- {"fe_iconaudio", "" },
- {"fe_icondisplay", "" },
- {"fe_iconlanguage", "" },
- {"fe_controller", "" },
- {"fe_controllersh", "" },
- {"fe_arrows1", "" },
- {"fe_arrows2", "" },
- {"fe_arrows3", "" },
- {"fe_arrows4", "" },
- {"fe_radio1", "" },
- {"fe_radio2", "" },
- {"fe_radio3", "" },
- {"fe_radio4", "" },
- {"fe_radio5", "" },
- {"fe_radio6", "" },
- {"fe_radio7", "" },
- {"fe_radio8", "" },
- {"fe_radio9", "" },
-};
-
-#ifdef MENU_MAP
-const char* MapFilenames[][2] = {
- {"mapMid01", "mapMid01A"},
- {"mapMid02", "mapMid02A"},
- {"mapMid03", "mapMid03A"},
- {"mapBot01", "mapBot01A"},
- {"mapBot02", "mapBot02A"},
- {"mapBot03", "mapBot03A"},
- {"mapTop01", "mapTop01A"},
- {"mapTop02", "mapTop02A"},
- {"mapTop03", "mapTop03A"},
-};
-CSprite2d CMenuManager::m_aMapSprites[NUM_MAP_SPRITES];
-#endif
-
+/*
// 0x5F3344
const char* MenuFilenames[][2] = {
{"connection24", ""},
@@ -219,6 +185,37 @@ const char* MenuFilenames[][2] = {
{"gta3logo256", "gta3logo256m"},
{ nil, nil }
};
+*/
+
+// 0x68C144
+const char* FrontendFilenames[][2] = {
+ {"background", ""},
+ {"vc_logo", "vc_logom"},
+ {"mouse", "mousea"},
+ {"mapTop01", "mapTop01A"},
+ {"mapTop02", "mapTop02A"},
+ {"mapTop03", "mapTop03A"},
+ {"mapMid01", "mapMid01A"},
+ {"mapMid02", "mapMid02A"},
+ {"mapMid03", "mapMid03A"},
+ {"mapBot01", "mapBot01A"},
+ {"mapBot02", "mapBot02A"},
+ {"mapBot03", "mapBot03A"},
+ {"wildstyle", "wildstyleA"},
+ {"flash", "flashA"},
+ {"kchat", "kchatA"},
+ {"fever", "feverA"},
+ {"vrock", "vrockA"},
+ {"vcpr", "vcprA"},
+ {"espantoso", "espantosoA"},
+ {"emotion", "emotionA"},
+ {"wave103", "wave103A"},
+ {"mp3", "mp3A"},
+ {"downOff", "buttonA"},
+ {"downOn", "buttonA"},
+ {"upOff", "buttonA"},
+ {"upOn", "buttonA"}
+};
#ifdef ASPECT_RATIO_SCALE
// All of the defines below replace the StretchX function. Otherwise use SCREEN_SCALE_X.
@@ -284,7 +281,7 @@ ScaleAndCenterX(float x)
#endif
#define PREPARE_MENU_HEADER \
- CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \
+ CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \
CFont::SetRightJustifyOn(); \
CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
@@ -306,9 +303,10 @@ ScaleAndCenterX(float x)
m_nHoverOption = HOVEROPTION_NOT_HOVERING; \
} while(0)
+// TODO: this is COMPLETELY different in VC
#define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \
do { \
- sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \
+ sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(255, 255, 255, 100)); \
if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \
m_nHoverOption = hoverOpt; \
} while (0)
@@ -651,15 +649,15 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR
int lastActiveBarX = 0;
float curBarX = 0.0f;
- float spacing = SCREEN_SCALE_X(10.0f);
+ float spacing = SCREEN_SCALE_X(4.0f); // TODO: find actual numbers used in the game
for (int i = 0; i < 16; i++) {
- curBarX = i * rectSize/16.0f + x;
+ curBarX = i * rectSize/32.0f + x;
if (i / 16.0f + 1 / 32.0f < progress) {
- color = CRGBA(255, 217, 106, FadeIn(255));
+ color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255));
lastActiveBarX = curBarX;
} else
- color = CRGBA(185, 120, 0, FadeIn(255));
+ color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255));
maxBarHeight = Max(mostLeftBarSize, mostRightBarSize);
@@ -700,8 +698,10 @@ CMenuManager::Draw()
CFont::SetCentreOff();
CFont::SetJustifyOn();
CFont::SetBackGroundOnlyTextOn();
-#ifdef GTA3_1_1_PATCH
- CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255)));
+
+ // no V1.1 text in vc obv
+#if 0 //def GTA3_1_1_PATCH
+ CFont::SetColor(CRGBA(255, 150, 225, FadeIn(255)));
CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING);
CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f));
@@ -711,6 +711,7 @@ CMenuManager::Draw()
AsciiToUnicode(gString, gUString);
CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString);
#endif
+
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
@@ -736,9 +737,13 @@ CMenuManager::Draw()
if(!m_bRenderGameInMenu)
#endif
if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') {
-
+
PREPARE_MENU_HEADER
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
+ CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
+
+ PREPARE_MENU_HEADER
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
// Weird place to put that.
nextYToUse += 24.0f + 10.0f;
@@ -747,7 +752,7 @@ CMenuManager::Draw()
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y));
CFont::SetRightJustifyOff();
- CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255)));
+ CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255)));
// Label
wchar *str;
@@ -845,7 +850,7 @@ CMenuManager::Draw()
break;
case MENUPAGE_START_MENU:
columnWidth = 320;
- headerHeight = 140;
+ headerHeight = 110;
lineHeight = 24;
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE));
@@ -898,7 +903,7 @@ CMenuManager::Draw()
}
float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider
- float smallestSliderBar = lineHeight * 0.1f;
+ float smallestSliderBar = lineHeight * 0.25f; // TODO: find actual number
bool foundTheHoveringItem = false;
wchar unicodeTemp[64];
char asciiTemp[32];
@@ -1084,16 +1089,16 @@ CMenuManager::Draw()
rightText = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? "FEM_ON" : "FEM_OFF");
break;
case MENUACTION_PEDROADGROUPS:
- rightText = TheText.Get(gbShowPedRoadGroups ? "FEM_ON" : "FEM_OFF");
+ // REMOVED(MIAMI)
break;
case MENUACTION_CARROADGROUPS:
- rightText = TheText.Get(gbShowCarRoadGroups ? "FEM_ON" : "FEM_OFF");
+ // REMOVED(MIAMI)
break;
case MENUACTION_COLLISIONPOLYS:
rightText = TheText.Get(gbShowCollisionPolys ? "FEM_ON" : "FEM_OFF");
break;
case MENUACTION_SHOWCULL:
- rightText = TheText.Get(gbShowCullZoneDebugStuff ? "FEM_ON" : "FEM_OFF");
+ // REMOVED(MIAMI)
break;
case MENUACTION_SHOWHEADBOB:
rightText = TheText.Get(TheCamera.m_bHeadBob ? "FEM_ON" : "FEM_OFF");
@@ -1226,7 +1231,7 @@ CMenuManager::Draw()
// We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background
CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY),
SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)),
- CRGBA(100, 200, 50, FadeIn(50)));
+ CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255)));
}
CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90)));
@@ -1245,14 +1250,14 @@ CMenuManager::Draw()
if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES")
&& !m_bGameNotLoaded && textLayer == 1) {
- CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255)));
+ CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));
}
CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText);
}
if (i == m_nCurrOption && itemsAreSelectable){
- CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255)));
+ CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));
} else {
- CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255)));
+ CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255)));
}
}
@@ -1321,18 +1326,18 @@ CMenuManager::Draw()
// Radio icons
if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) {
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO1], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO2], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO5], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO7], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO8], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO3], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO4], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO6], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7);
- ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO9], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WILDSTYLE], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FLASH], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_KCHAT], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FEVER], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VROCK], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VCPR], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_ESPANTOSO], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_EMOTION], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WAVE], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8);
if (DMAudio.IsMP3RadioChannelAvailable())
- ProcessRadioIcon(m_aMenuSprites[MENUSPRITE_MP3LOGO], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9);
+ ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_MP3], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9);
nextYToUse += 70.0f;
}
@@ -1813,11 +1818,21 @@ CMenuManager::DrawControllerSetupScreen()
switch (m_ControlMethod) {
case CONTROL_STANDARD:
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y),
+ CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f),
+ TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
+
+ PREPARE_MENU_HEADER
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y),
TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
break;
case CONTROL_CLASSIC:
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y),
+ CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f),
+ TheText.Get("FET_CTI"));
+
+ PREPARE_MENU_HEADER
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y),
TheText.Get("FET_CTI"));
break;
default:
@@ -2079,13 +2094,13 @@ CMenuManager::DrawFrontEndSaveZone()
mouse.Translate(m_nMousePosX, m_nMousePosY);
shad.Translate(m_nMousePosX, m_nMousePosY);
if(field_518 == 4){
- m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}else{
- m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}
}
}
@@ -2273,13 +2288,13 @@ CMenuManager::DrawFrontEndNormal()
mouse.Translate(m_nMousePosX, m_nMousePosY);
shad.Translate(m_nMousePosX, m_nMousePosY);
if(field_518 == 4){
- m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50));
+ m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255));
}else{
- m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}
}
}
@@ -2293,65 +2308,24 @@ CMenuManager::DrawFrontEndNormal()
LoadSplash(nil);
- eMenuSprites previousSprite;
+ eMenuSprites previousSprite = MENUSPRITE_BACKGROUND;
+
if (m_nMenuFadeAlpha < 255) {
- switch (m_nPrevScreen) {
- case MENUPAGE_STATS:
- case MENUPAGE_START_MENU:
- case MENUPAGE_PAUSE_MENU:
- previousSprite = MENUSPRITE_MAINMENU;
- break;
- case MENUPAGE_NEW_GAME:
- case MENUPAGE_CHOOSE_LOAD_SLOT:
- case MENUPAGE_CHOOSE_DELETE_SLOT:
- case MENUPAGE_NEW_GAME_RELOAD:
- case MENUPAGE_LOAD_SLOT_CONFIRM:
- case MENUPAGE_DELETE_SLOT_CONFIRM:
- case MENUPAGE_EXIT:
- previousSprite = MENUSPRITE_SINGLEPLAYER;
- break;
- case MENUPAGE_MULTIPLAYER_MAIN:
- previousSprite = MENUSPRITE_MULTIPLAYER;
- break;
- case MENUPAGE_MULTIPLAYER_MAP:
- case MENUPAGE_MULTIPLAYER_FIND_GAME:
- case MENUPAGE_SKIN_SELECT:
- case MENUPAGE_KEYBOARD_CONTROLS:
- case MENUPAGE_MOUSE_CONTROLS:
- previousSprite = MENUSPRITE_FINDGAME;
- break;
- case MENUPAGE_MULTIPLAYER_CONNECTION:
- case MENUPAGE_MULTIPLAYER_MODE:
- previousSprite = MENUSPRITE_CONNECTION;
- break;
- case MENUPAGE_MULTIPLAYER_CREATE:
- previousSprite = MENUSPRITE_HOSTGAME;
- break;
- case MENUPAGE_SKIN_SELECT_OLD:
- case MENUPAGE_OPTIONS:
- previousSprite = MENUSPRITE_PLAYERSET;
- break;
- default:
- previousSprite = MENUSPRITE_MAINMENU;
- break;
- }
-
if (m_nPrevScreen == m_nCurrScreen)
CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255 - m_nMenuFadeAlpha));
else
- m_aMenuSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha));
+ m_aFrontEndSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha));
}
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- eMenuSprites currentSprite = MENUSPRITE_MAINMENU; // actually uninitialized
+ eMenuSprites currentSprite = MENUSPRITE_BACKGROUND; // actually uninitialized
+
switch (m_nCurrScreen) {
case MENUPAGE_STATS:
case MENUPAGE_START_MENU:
case MENUPAGE_PAUSE_MENU:
- currentSprite = MENUSPRITE_MAINMENU;
- break;
case MENUPAGE_NEW_GAME:
case MENUPAGE_CHOOSE_LOAD_SLOT:
case MENUPAGE_CHOOSE_DELETE_SLOT:
@@ -2359,28 +2333,18 @@ CMenuManager::DrawFrontEndNormal()
case MENUPAGE_LOAD_SLOT_CONFIRM:
case MENUPAGE_DELETE_SLOT_CONFIRM:
case MENUPAGE_EXIT:
- currentSprite = MENUSPRITE_SINGLEPLAYER;
- break;
case MENUPAGE_MULTIPLAYER_MAIN:
- currentSprite = MENUSPRITE_MULTIPLAYER;
- break;
case MENUPAGE_MULTIPLAYER_MAP:
case MENUPAGE_MULTIPLAYER_FIND_GAME:
case MENUPAGE_SKIN_SELECT:
case MENUPAGE_KEYBOARD_CONTROLS:
case MENUPAGE_MOUSE_CONTROLS:
- currentSprite = MENUSPRITE_FINDGAME;
- break;
case MENUPAGE_MULTIPLAYER_CONNECTION:
case MENUPAGE_MULTIPLAYER_MODE:
- currentSprite = MENUSPRITE_CONNECTION;
- break;
case MENUPAGE_MULTIPLAYER_CREATE:
- currentSprite = MENUSPRITE_HOSTGAME;
- break;
case MENUPAGE_SKIN_SELECT_OLD:
case MENUPAGE_OPTIONS:
- currentSprite = MENUSPRITE_PLAYERSET;
+ currentSprite = MENUSPRITE_BACKGROUND;
break;
}
@@ -2404,13 +2368,13 @@ CMenuManager::DrawFrontEndNormal()
#endif
if (m_nMenuFadeAlpha > 255){
- m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
} else {
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha));
+ m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha));
}
} else {
- m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
// TODO: what is this? waiting mouse?
if(field_518 == 4){
if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 ||
@@ -2422,15 +2386,20 @@ CMenuManager::DrawFrontEndNormal()
}
}
+ m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
+
// GTA LOGO
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ /*
if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) {
if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame)
- m_aMenuSprites[MENUSPRITE_GTA3LOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255)));
+ m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255)));
else
- m_aMenuSprites[MENUSPRITE_GTALOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255)));
+ m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255)));
}
+ */
+ m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_SCALE_X(27.0f), MENU_Y(8.0f), SCREEN_SCALE_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255)));
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
@@ -2457,19 +2426,19 @@ CMenuManager::DrawFrontEndNormal()
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f));
- CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f));
+ CRect mouse(0.0f, 0.0f, MENU_X(40.0f), MENU_Y(40.0f));
+ CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(55.0f), MENU_Y(43.0f));
mouse.Translate(m_nMousePosX, m_nMousePosY);
shad.Translate(m_nMousePosX, m_nMousePosY);
if(field_518 == 4){
- m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}else{
- m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
+ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}
}
}
@@ -2711,21 +2680,21 @@ CMenuManager::DrawPlayerSetupScreen()
// 2 - leaves gap between button and scrollbar
if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) {
#ifdef FIX_BUGS
- m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
+ m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255)));
#else
- m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
+ m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)),
CRGBA(255, 255, 255, FadeIn(255)));
#endif
} else {
#ifdef FIX_BUGS
- m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),
+ m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255)));
#else
- m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),
+ m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)),
CRGBA(255, 255, 255, FadeIn(255)));
#endif
@@ -2733,21 +2702,21 @@ CMenuManager::DrawPlayerSetupScreen()
if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) {
#ifdef FIX_BUGS
- m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),
+ m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255)));
#else
- m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f),
+ m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f),
MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)),
CRGBA(255, 255, 255, FadeIn(255)));
#endif
} else {
#ifdef FIX_BUGS
- m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),
+ m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255)));
#else
- m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f),
+ m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f),
MENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)),
CRGBA(255, 255, 255, FadeIn(255)));
#endif
@@ -3021,51 +2990,59 @@ CMenuManager::LoadAllTextures()
CStreaming::ImGonnaUseStreamingMemory();
CGame::TidyUpMemory(false, true);
CTxdStore::PushCurrentTxd();
- int frontendTxdSlot = CTxdStore::FindTxdSlot("frontend");
+ int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1");
- if(frontendTxdSlot == -1)
- frontendTxdSlot = CTxdStore::AddTxdSlot("frontend");
+ if(frontendTxdSlot1 == -1)
+ frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1");
- printf("LOAD frontend\n");
- CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD");
- CTxdStore::AddRef(frontendTxdSlot);
- CTxdStore::SetCurrentTxd(frontendTxdSlot);
-#ifndef GTA3_1_1_PATCH
- CStreaming::IHaveUsedStreamingMemory();
- CTimer::Update();
-#endif
+ printf("LOAD frontend1\n");
+ CTxdStore::LoadTxd(frontendTxdSlot1, "MODELS/FRONTEN1.TXD");
+ CTxdStore::AddRef(frontendTxdSlot1);
+ CTxdStore::SetCurrentTxd(frontendTxdSlot1);
- for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); i++) {
+ for (int i = 0; i < 3; i++) {
m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);
m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
}
- int menuTxdSlot = CTxdStore::FindTxdSlot("menu");
+ CTxdStore::PopCurrentTxd();
+ CStreaming::IHaveUsedStreamingMemory();
+
+
+ // if ( !*(_BYTE *)(v1 + 124) )
- if (menuTxdSlot == -1)
- menuTxdSlot = CTxdStore::AddTxdSlot("menu");
+ CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile
+ CStreaming::ImGonnaUseStreamingMemory();
+ CTxdStore::PushCurrentTxd();
+
+ int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2");
- printf("LOAD sprite\n");
- CTxdStore::LoadTxd(menuTxdSlot, "MODELS/MENU.TXD");
- CTxdStore::AddRef(menuTxdSlot);
- CTxdStore::SetCurrentTxd(menuTxdSlot);
+ if (frontendTxdSlot2 == -1)
+ frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2");
- for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) {
- m_aMenuSprites[i].SetTexture(MenuFilenames[i][0], MenuFilenames[i][1]);
- m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
+ printf("LOAD frontend2\n");
+ CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD");
+ CTxdStore::AddRef(frontendTxdSlot2);
+ CTxdStore::SetCurrentTxd(frontendTxdSlot2);
+
+ for (int i = 3; i < NUM_MENU_SPRITES; i++) {
+ m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);
+ m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
}
-#ifdef MENU_MAP
+
+ CTxdStore::PopCurrentTxd();
+ CStreaming::IHaveUsedStreamingMemory();
+
+
+#if 0 //MENU_MAP
for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) {
m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]);
m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
}
#endif
-#ifdef GTA3_1_1_PATCH
- CStreaming::IHaveUsedStreamingMemory();
- CTimer::Update();
-#endif
+
m_bSpritesLoaded = true;
- CTxdStore::PopCurrentTxd();
+ CTimer::Update();
}
void
@@ -4468,7 +4445,7 @@ CMenuManager::ProcessButtonPresses(void)
CGame::ReloadIPLs();
break;
case MENUACTION_SHOWCULL:
- gbShowCullZoneDebugStuff = !gbShowCullZoneDebugStuff;
+ // REMOVED(MIAMI)
break;
case MENUACTION_MEMCARDSAVECONFIRM:
return;
@@ -4938,11 +4915,11 @@ CMenuManager::ProcessOnOffMenuOptions()
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0);
break;
case MENUACTION_PEDROADGROUPS:
- gbShowPedRoadGroups = !gbShowPedRoadGroups;
+ // REMOVED(MIAMI)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0);
break;
case MENUACTION_CARROADGROUPS:
- gbShowCarRoadGroups = !gbShowCarRoadGroups;
+ // REMOVED(MIAMI)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0);
break;
case MENUACTION_COLLISIONPOLYS:
@@ -5147,18 +5124,16 @@ CMenuManager::UnloadTextures()
for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i)
m_aFrontEndSprites[i].Delete();
- int frontend = CTxdStore::FindTxdSlot("frontend");
+ int frontend = CTxdStore::FindTxdSlot("frontend1");
CTxdStore::RemoveTxd(frontend);
- printf("REMOVE menu textures\n");
- for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i)
- m_aMenuSprites[i].Delete();
-#ifdef MENU_MAP
+ int frontend2 = CTxdStore::FindTxdSlot("frontend2");
+ CTxdStore::RemoveTxd(frontend2);
+
+#ifdef false //MENU_MAP
for (int i = 0; i < ARRAY_SIZE(MapFilenames); ++i)
m_aMapSprites[i].Delete();
#endif
- int menu = CTxdStore::FindTxdSlot("menu");
- CTxdStore::RemoveTxd(menu);
m_bSpritesLoaded = false;
}
@@ -5197,6 +5172,9 @@ CMenuManager::PrintController(void)
// FIX: Originally this function doesn't have StretchX/Y, everything had constant pixel size (due to screen was abandoned early?)
// Also texts and their alignment were very bad, so I tried to make them readable (commented out the original code, and marked the ones I added with X)
+ // sorry!
+
+ /*
m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(240.0f), MENU_Y(180.0f), CRGBA(0, 0, 0, 255));
m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255));
if (m_DisplayControllerOnFoot) {
@@ -5210,6 +5188,7 @@ CMenuManager::PrintController(void)
else
m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255));
}
+ */
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // X
@@ -5468,47 +5447,47 @@ CMenuManager::PrintMap(void)
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - fMapSize) {
- m_aMapSprites[MAPTOP1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize,
+ m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize,
fMapCenterX - halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) {
- m_aMapSprites[MAPTOP2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize,
+ m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize,
fMapCenterX + halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) {
- m_aMapSprites[MAPTOP3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize,
+ m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize,
fMapCenterX + fMapSize, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - halfTile) {
- m_aMapSprites[MAPMID1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile,
+ m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile,
fMapCenterX - halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) {
- m_aMapSprites[MAPMID2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile,
+ m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile,
fMapCenterX + halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) {
- m_aMapSprites[MAPMID3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile,
+ m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile,
fMapCenterX + fMapSize, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY + halfTile) {
- m_aMapSprites[MAPBOT1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile,
+ m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile,
fMapCenterX - halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) {
- m_aMapSprites[MAPBOT2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile,
+ m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile,
fMapCenterX + halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255)));
}
if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) {
- m_aMapSprites[MAPBOT3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile,
+ m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile,
fMapCenterX + fMapSize, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255)));
}
@@ -5536,9 +5515,10 @@ CMenuManager::PrintMap(void)
if (mapPoint.y > fMapCenterY - fMapSize && mapPoint.y < fMapCenterY + fMapSize &&
mapPoint.x > fMapCenterX - fMapSize && mapPoint.x < fMapCenterX + fMapSize) {
+ // Don't ask me the meanings, I don't know. Found them by trying
float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize;
- float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * 4000.0f - 2000.0f;
- float y = 2000.0f - ((mapPoint.y - diffY) / (fMapSize * 2)) * 4000.0f;
+ float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT);
+ float y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapPoint.y - diffY) / (fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE);
CRadar::ToggleTargetMarker(x, y);
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0);
}
@@ -5584,7 +5564,8 @@ CMenuManager::PrintMap(void)
if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f))
fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize;
- fMapCenterY = Min(fMapCenterY, fMapSize); // To not show beyond north border
+ if (fMapCenterY - fMapSize > SCREEN_HEIGHT / 2)
+ fMapCenterY = SCREEN_HEIGHT / 2 + fMapSize;
bMenuMapActive = false;
@@ -5654,9 +5635,7 @@ CMenuManager::ConstructStatLine(int rowIdx)
STAT_LINE("PL_STAT", nil, false, nil);
- int percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 :
- CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1));
- percentCompleted = Min(percentCompleted, 100);
+ int percentCompleted = CStats::GetPercentageProgress();
STAT_LINE("PER_COM", &percentCompleted, false, nil);
STAT_LINE("NMISON", &CStats::MissionsGiven, false, nil);
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 89517528..114ea6ba 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -7,8 +7,8 @@
#define MENUHEADER_POS_Y 75.0f
#define MENUHEADER_HEIGHT 1.3f
#else
-#define MENUHEADER_POS_X 35.0f
-#define MENUHEADER_POS_Y 93.0f
+#define MENUHEADER_POS_X 10.0f
+#define MENUHEADER_POS_Y 10.0f
#define MENUHEADER_HEIGHT 1.6f
#endif
#define MENUHEADER_WIDTH 0.84f
@@ -20,7 +20,7 @@
#define MENURADIO_ICON_SCALE 60.0f
-#define MENUSLIDER_X 256.0f
+#define MENUSLIDER_X 128.0f
#define MENUSLIDER_UNK 256.0f
#define BIGTEXT_X_SCALE 0.75f
@@ -95,6 +95,7 @@ enum eLanguages
#endif
};
+/*
enum eFrontendSprites
{
FE2_MAINPANEL_UL,
@@ -128,29 +129,36 @@ enum eFrontendSprites
NUM_FE_SPRITES
};
+*/
enum eMenuSprites
{
- MENUSPRITE_CONNECTION,
- MENUSPRITE_FINDGAME,
- MENUSPRITE_HOSTGAME,
- MENUSPRITE_MAINMENU,
- MENUSPRITE_PLAYERSET,
- MENUSPRITE_SINGLEPLAYER,
- MENUSPRITE_MULTIPLAYER,
- MENUSPRITE_DMALOGO,
- MENUSPRITE_GTALOGO,
- MENUSPRITE_RSTARLOGO,
- MENUSPRITE_GAMESPY,
+ MENUSPRITE_BACKGROUND,
+ MENUSPRITE_VCLOGO,
MENUSPRITE_MOUSE,
- MENUSPRITE_MOUSET,
- MENUSPRITE_MP3LOGO,
+ MENUSPRITE_MAPTOP01,
+ MENUSPRITE_MAPTOP02,
+ MENUSPRITE_MAPTOP03,
+ MENUSPRITE_MAPMID01,
+ MENUSPRITE_MAPMID02,
+ MENUSPRITE_MAPMID03,
+ MENUSPRITE_MAPBOT01,
+ MENUSPRITE_MAPBOT02,
+ MENUSPRITE_MAPBOT03,
+ MENUSPRITE_WILDSTYLE,
+ MENUSPRITE_FLASH,
+ MENUSPRITE_KCHAT,
+ MENUSPRITE_FEVER,
+ MENUSPRITE_VROCK,
+ MENUSPRITE_VCPR,
+ MENUSPRITE_ESPANTOSO,
+ MENUSPRITE_EMOTION,
+ MENUSPRITE_WAVE,
+ MENUSPRITE_MP3,
MENUSPRITE_DOWNOFF,
MENUSPRITE_DOWNON,
MENUSPRITE_UPOFF,
MENUSPRITE_UPON,
- MENUSPRITE_GTA3LOGO,
- MENUSPRITE_UNUSED,
NUM_MENU_SPRITES
};
@@ -509,8 +517,9 @@ public:
char field_455;
bool m_bStartWaitingForKeyBind;
bool m_bSpritesLoaded;
- CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES];
- CSprite2d m_aMenuSprites[NUM_MENU_SPRITES];
+ //CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES];
+ //CSprite2d m_aMenuSprites[NUM_MENU_SPRITES];
+ CSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES];
int32 field_518;
int32 m_nMenuFadeAlpha;
bool m_bPressedPgUpOnList;
@@ -624,6 +633,8 @@ public:
void LoadAllTextures();
void LoadSettings();
void MessageScreen(const char *);
+ // TODO(MIAMI): implement the second argument
+ void MessageScreen(const char *str, bool) { MessageScreen(str); }
void PickNewPlayerColour();
void PrintBriefs();
static void PrintErrorMessage();
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 33afc956..3f4a3217 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -84,11 +84,13 @@
#include "World.h"
#include "ZoneCull.h"
#include "Zones.h"
+#include "Occlusion.h"
#include "debugmenu.h"
eLevelName CGame::currLevel;
+int32 CGame::currArea;
bool CGame::bDemoMode = true;
bool CGame::nastyGame = true;
bool CGame::frenchGame;
@@ -251,7 +253,7 @@ bool CGame::Initialise(const char* datFile)
strcpy(aDatFile, datFile);
CPools::Initialise();
CIniFile::LoadIniFile();
- currLevel = LEVEL_INDUSTRIAL;
+ currLevel = LEVEL_BEACH;
LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen());
gameTxdSlot = CTxdStore::AddTxdSlot("generic");
CTxdStore::Create(gameTxdSlot);
@@ -271,6 +273,7 @@ bool CGame::Initialise(const char* datFile)
ThePaths.AllocatePathFindInfoMem(4500);
CWeather::Init();
CCullZones::Init();
+ COcclusion::Init();
CCollision::Init();
CTheZones::Init();
CUserDisplay::Init();
@@ -306,7 +309,6 @@ bool CGame::Initialise(const char* datFile)
CDraw::SetFOV(120.0f);
CDraw::ms_fLODDistance = 500.0f;
LoadingScreen("Loading the Game", "Setup streaming", nil);
- CStreaming::Init();
CStreaming::LoadInitialVehicles();
CStreaming::LoadInitialPeds();
CStreaming::RequestBigBuildings(LEVEL_NONE);
@@ -314,6 +316,7 @@ bool CGame::Initialise(const char* datFile)
printf("Streaming uses %dK of its memory", CStreaming::ms_memoryUsed / 1024);
LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen());
CAnimManager::LoadAnimFiles();
+ CStreaming::LoadInitialWeapons();
CPed::Initialise();
CRouteNode::Initialise();
CEventList::Initialise();
@@ -354,10 +357,7 @@ bool CGame::Initialise(const char* datFile)
CWaterCannons::Init();
CBridge::Init();
CGarages::Init();
- LoadingScreen("Loading the Game", "Position dynamic objects", nil);
- CWorld::RepositionCertainDynamicObjects();
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
- CCullZones::ResolveVisibilities();
CTrain::InitTrains();
CPlane::InitPlanes();
CCredits::Init();
@@ -368,7 +368,6 @@ bool CGame::Initialise(const char* datFile)
CTheScripts::Process();
TheCamera.Process();
LoadingScreen("Loading the Game", "Load scene", nil);
- CModelInfo::RemoveColModelsFromOtherLevels(currLevel);
CCollision::ms_collisionInMemory = currLevel;
for (int i = 0; i < MAX_PADS; i++)
CPad::GetPad(i)->Clear(true);
@@ -474,7 +473,6 @@ void CGame::ReInitGameObjectVariables(void)
CSpecialFX::Init();
CWaterCannons::Init();
CParticle::ReloadConfig();
- CCullZones::ResolveVisibilities();
if ( !FrontEndMenuManager.m_bWantToLoad )
{
@@ -506,8 +504,6 @@ void CGame::ReloadIPLs(void)
CRoadBlocks::Init();
CCranes::InitCranes();
CGarages::Init();
- CWorld::RepositionCertainDynamicObjects();
- CCullZones::ResolveVisibilities();
CRenderer::SortBIGBuildings();
CTimer::Update();
}
@@ -579,7 +575,7 @@ void CGame::InitialiseWhenRestarting(void)
CTimer::Initialise();
FrontEndMenuManager.m_bWantToLoad = false;
ReInitGameObjectVariables();
- currLevel = LEVEL_INDUSTRIAL;
+ currLevel = LEVEL_NONE;
CCollision::SortOutCollisionAfterLoad();
}
}
@@ -668,6 +664,13 @@ void CGame::Process(void)
}
}
+bool
+CGame::CanSeeOutSideFromCurrArea(void)
+{
+ return currArea == AREA_MAIN_MAP || currArea == AREA_MALL ||
+ currArea == AREA_MANSION || currArea == AREA_HOTEL;
+}
+
void CGame::DrasticTidyUpMemory(bool)
{
#ifdef PS2
diff --git a/src/core/Game.h b/src/core/Game.h
index 48f31abc..6efacf8d 100644
--- a/src/core/Game.h
+++ b/src/core/Game.h
@@ -3,15 +3,37 @@
enum eLevelName {
LEVEL_IGNORE = -1, // beware, this is only used in CPhysical's m_nZoneLevel
LEVEL_NONE = 0,
- LEVEL_INDUSTRIAL,
- LEVEL_COMMERCIAL,
- LEVEL_SUBURBAN
+ LEVEL_BEACH,
+ LEVEL_MAINLAND
+};
+
+enum eAreaName {
+ AREA_MAIN_MAP,
+ AREA_HOTEL,
+ AREA_MANSION,
+ AREA_BANK,
+ AREA_MALL,
+ AREA_STRIP_CLUB,
+ AREA_LAWYERS,
+ AREA_COFFEE_SHOP,
+ AREA_CONCERT_HALL,
+ AREA_STUDIO,
+ AREA_RIFLE_RANGE,
+ AREA_BIKER_BAR,
+ AREA_POLICE_STATION,
+ AREA_EVERYWHERE,
+ AREA_DIRT,
+ AREA_BLOOD,
+ AREA_OVALRING,
+ AREA_MALIBU_CLUB,
+ AREA_PRINT_WORKS
};
class CGame
{
public:
static eLevelName currLevel;
+ static int32 currArea;
static bool bDemoMode;
static bool nastyGame;
static bool frenchGame;
@@ -36,9 +58,14 @@ public:
static void ShutDownForRestart(void);
static void InitialiseWhenRestarting(void);
static void Process(void);
+
+ static bool IsInInterior(void) { return currArea != AREA_MAIN_MAP; }
+ static bool CanSeeOutSideFromCurrArea(void);
// NB: these do something on PS2
static void TidyUpMemory(bool, bool);
static void DrasticTidyUpMemory(bool);
static void ProcessTidyUpMemory(void);
};
+
+inline bool IsAreaVisible(int area) { return area == CGame::currArea || area == AREA_EVERYWHERE; }
diff --git a/src/core/General.h b/src/core/General.h
index 7ffa99de..3188d82b 100644
--- a/src/core/General.h
+++ b/src/core/General.h
@@ -145,4 +145,6 @@ public:
static int32 GetRandomNumberInRange(int32 low, int32 high)
{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }
+ static void SetRandomSeed(int32 seed)
+ { mysrand(seed); }
};
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index 924d4724..ae7fcdb4 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -65,23 +65,42 @@ extern bool gbFastTime;
void WeaponCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT2"), true);
+
+ CStreaming::RequestModel(MI_GRENADE, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_AK47, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_BASEBALL_BAT, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_COLT, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_ROCKETLAUNCHER, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_SNIPER, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_MP5, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::LoadAllRequestedModels(false);
+
FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0);
FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100);
- FindPlayerPed()->GiveWeapon(WEAPONTYPE_UZI, 100);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_MP5, 100);
FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20);
FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200);
- FindPlayerPed()->GiveWeapon(WEAPONTYPE_M16, 200);
FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5);
FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5);
- FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 5);
- FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 5);
- FindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_DETONATOR_GRENADE, 5);
+
+ CStreaming::SetModelIsDeletable(MI_GRENADE);
+ CStreaming::SetModelIsDeletable(MI_BOMB);
+ CStreaming::SetModelIsDeletable(MI_AK47);
+ CStreaming::SetModelIsDeletable(MI_BASEBALL_BAT);
+ CStreaming::SetModelIsDeletable(MI_COLT);
+ CStreaming::SetModelIsDeletable(MI_ROCKETLAUNCHER);
+ CStreaming::SetModelIsDeletable(MI_SHOTGUN);
+ CStreaming::SetModelIsDeletable(MI_SNIPER);
+ CStreaming::SetModelIsDeletable(MI_MP5);
}
void HealthCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT3"), true);
- FindPlayerPed()->m_fHealth = 100.0f;
+ FindPlayerPed()->m_fHealth = CWorld::Players[0].m_nMaxHealth;
if (FindPlayerVehicle()) {
FindPlayerVehicle()->m_fHealth = 1000.0f;
if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR)
@@ -140,9 +159,9 @@ void ChangePlayerCheat()
do
{
do
- modelId = CGeneral::GetRandomNumberInRange(0, MI_CAS_WOM+1);
+ modelId = CGeneral::GetRandomNumberInRange(0, MI_WFYG2+1);
while (!CModelInfo::GetModelInfo(modelId));
- } while (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL04 || modelId == MI_TAXI_D);
+ } while (modelId == MI_TAXI_D);
uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags;
ped->DeleteRwObject();
@@ -205,7 +224,7 @@ void MoneyCheat()
void ArmourCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT4"), true);
- FindPlayerPed()->m_fArmour = 100.0f;
+ FindPlayerPed()->m_fArmour = CWorld::Players[0].m_nMaxArmour;
}
void WantedLevelUpCheat()
@@ -273,6 +292,20 @@ void NastyLimbsCheat()
{
CPed::bNastyLimbsCheat = !CPed::bNastyLimbsCheat;
}
+
+void BlackCarsCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ gbBlackCars = true;
+ gbPinkCars = false;
+}
+
+void PinkCarsCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ gbBlackCars = false;
+ gbPinkCars = true;
+}
//////////////////////////////////////////////////////////////////////////
#ifdef KANGAROO_CHEAT
@@ -951,6 +984,14 @@ void CPad::AddToPCCheatString(char c)
if ( !_CHEATCMP("TAEHCSBMILYTSAN") )
NastyLimbsCheat();
+ // "IWANTITPAINTEDBLACK"
+ if ( !_CHEATCMP("KCALBDETNIAPTITNAWI") )
+ BlackCarsCheat();
+
+ // "AHAIRDRESSERSCAR"
+ if ( !_CHEATCMP("RACSRESSERDRIAHA") )
+ PinkCarsCheat();
+
#ifdef KANGAROO_CHEAT
// "KANGAROO"
if (!_CHEATCMP("OORAGNAK"))
@@ -2336,6 +2377,8 @@ void CPad::ResetCheats(void)
CVehicle::bCheat3 = false;
CVehicle::bCheat4 = false;
CVehicle::bCheat5 = false;
+ gbBlackCars = false;
+ gbPinkCars = false;
gbFastTime = false;
CTimer::SetTimeScale(1.0f);
diff --git a/src/core/Placeable.cpp b/src/core/Placeable.cpp
index 69b3d3ea..6efc1540 100644
--- a/src/core/Placeable.cpp
+++ b/src/core/Placeable.cpp
@@ -7,8 +7,6 @@ CPlaceable::CPlaceable(void)
m_matrix.SetScale(1.0f);
}
-CPlaceable::~CPlaceable(void) = default;
-
void
CPlaceable::SetHeading(float angle)
{
diff --git a/src/core/Placeable.h b/src/core/Placeable.h
index 970c0d48..22f7583c 100644
--- a/src/core/Placeable.h
+++ b/src/core/Placeable.h
@@ -9,7 +9,6 @@ public:
CMatrix m_matrix;
CPlaceable(void);
- virtual ~CPlaceable(void);
const CVector &GetPosition(void) { return m_matrix.GetPosition(); }
void SetPosition(float x, float y, float z) {
m_matrix.GetPosition().x = x;
diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp
index 487f536f..37a62adf 100644
--- a/src/core/PlayerInfo.cpp
+++ b/src/core/PlayerInfo.cpp
@@ -140,8 +140,10 @@ CPlayerInfo::Clear(void)
m_nUpsideDownCounter = 0;
m_bInfiniteSprint = false;
m_bFastReload = false;
+ m_nMaxHealth = m_nMaxArmour = 100;
m_bGetOutOfJailFree = false;
m_bGetOutOfHospitalFree = false;
+ m_bDriveByAllowed = true;
m_nPreviousTimeRewardedForExplosion = 0;
m_nExplosionsSinceLastReward = 0;
}
@@ -171,7 +173,6 @@ void
CPlayerInfo::MakePlayerSafe(bool toggle)
{
if (toggle) {
- CTheScripts::ResetCountdownToMakePlayerUnsafe();
m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
CWorld::StopAllLawEnforcersInTheirTracks();
CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
@@ -192,7 +193,8 @@ CPlayerInfo::MakePlayerSafe(bool toggle)
CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
CReplay::DisableReplays();
- } else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) {
+ }
+ else {
m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
m_pPed->bBulletProof = false;
@@ -348,7 +350,7 @@ CPlayerInfo::Process(void)
bool startTaxiTimer = true;
if (m_bUnusedTaxiThing && m_pPed->bInVehicle) {
CVehicle *veh = m_pPed->m_pMyVehicle;
- if ((veh->GetModelIndex() == MI_TAXI || veh->GetModelIndex() == MI_CABBIE || veh->GetModelIndex() == MI_BORGNINE)
+ if (veh->IsTaxi()
&& veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {
for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {
timePassed -= 1000;
diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h
index 94410753..ea9d563a 100644
--- a/src/core/PlayerInfo.h
+++ b/src/core/PlayerInfo.h
@@ -52,8 +52,12 @@ public:
int32 field_272;
bool m_bInfiniteSprint;
bool m_bFastReload;
+ bool m_bFireproof;
+ uint8 m_nMaxHealth;
+ uint8 m_nMaxArmour;
bool m_bGetOutOfJailFree;
bool m_bGetOutOfHospitalFree;
+ bool m_bDriveByAllowed;
char m_aSkinName[32];
RwTexture *m_pSkinTexture;
@@ -80,5 +84,3 @@ public:
~CPlayerInfo() { };
};
-
-VALIDATE_SIZE(CPlayerInfo, 0x13C);
diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp
index 17b9e08d..6838ef8e 100644
--- a/src/core/Pools.cpp
+++ b/src/core/Pools.cpp
@@ -499,8 +499,20 @@ INITSAVEBUF
pPed->CharCreatedBy = pBufferPlayer->CharCreatedBy;
pPed->m_currentWeapon = 0;
pPed->m_maxWeaponTypeAllowed = pBufferPlayer->m_maxWeaponTypeAllowed;
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++)
- pPed->m_weapons[i] = pBufferPlayer->m_weapons[i];
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
+ if (pBufferPlayer->HasWeaponSlot(i)) {
+ int modelId = CWeaponInfo::GetWeaponInfo(pBufferPlayer->GetWeapon(i).m_eWeaponType)->m_nModelId;
+ if (modelId != -1) {
+ CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY);
+ int modelId2 = CWeaponInfo::GetWeaponInfo(pBufferPlayer->GetWeapon(i).m_eWeaponType)->m_nModel2Id;
+ if (modelId2 != -1)
+ CStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);
+
+ CStreaming::LoadAllRequestedModels(false);
+ }
+ pPed->GiveWeapon(pBufferPlayer->GetWeapon(i).m_eWeaponType, pBufferPlayer->GetWeapon(i).m_nAmmoTotal);
+ }
+ }
if (pedtype == PEDTYPE_PLAYER1) {
pPed->m_wepAccuracy = 100;
diff --git a/src/core/Pools.h b/src/core/Pools.h
index b0ba6598..2f0537ff 100644
--- a/src/core/Pools.h
+++ b/src/core/Pools.h
@@ -4,7 +4,7 @@
#include "Lists.h"
#include "Treadable.h"
#include "Object.h"
-#include "CutsceneHead.h"
+#include "CutsceneObject.h"
#include "PlayerPed.h"
#include "Automobile.h"
#include "DummyPed.h"
@@ -16,7 +16,7 @@ typedef CPool<CPed,CPlayerPed> CPedPool;
typedef CPool<CVehicle,CAutomobile> CVehiclePool;
typedef CPool<CBuilding> CBuildingPool;
typedef CPool<CTreadable> CTreadablePool;
-typedef CPool<CObject, CCutsceneHead> CObjectPool;
+typedef CPool<CObject, CCutsceneObject> CObjectPool;
typedef CPool<CDummy, CDummyPed> CDummyPool;
typedef CPool<cAudioScriptObject> CAudioScriptObjectPool;
diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp
index 9406f1bd..1267896a 100644
--- a/src/core/Radar.cpp
+++ b/src/core/Radar.cpp
@@ -21,49 +21,87 @@ sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS];
CVector2D vec2DRadarOrigin;
int32 gRadarTxdIds[64];
-CSprite2d CRadar::AsukaSprite;
-CSprite2d CRadar::BombSprite;
-CSprite2d CRadar::CatSprite;
CSprite2d CRadar::CentreSprite;
-CSprite2d CRadar::CopcarSprite;
-CSprite2d CRadar::DonSprite;
-CSprite2d CRadar::EightSprite;
-CSprite2d CRadar::ElSprite;
-CSprite2d CRadar::IceSprite;
-CSprite2d CRadar::JoeySprite;
-CSprite2d CRadar::KenjiSprite;
-CSprite2d CRadar::LizSprite;
-CSprite2d CRadar::LuigiSprite;
+CSprite2d CRadar::MapHereSprite;
CSprite2d CRadar::NorthSprite;
-CSprite2d CRadar::RaySprite;
-CSprite2d CRadar::SalSprite;
-CSprite2d CRadar::SaveSprite;
+CSprite2d CRadar::AverySprite;
+CSprite2d CRadar::BikerSprite;
+CSprite2d CRadar::CortezSprite;
+CSprite2d CRadar::DiazSprite;
+CSprite2d CRadar::KentSprite;
+CSprite2d CRadar::LawyerSprite;
+CSprite2d CRadar::PhilSprite;
+CSprite2d CRadar::BikersSprite;
+CSprite2d CRadar::BoatyardSprite;
+CSprite2d CRadar::MalibuClubSprite;
+CSprite2d CRadar::CubansSprite;
+CSprite2d CRadar::FilmSprite;
+CSprite2d CRadar::GunSprite;
+CSprite2d CRadar::HaitiansSprite;
+CSprite2d CRadar::HardwareSprite;
+CSprite2d CRadar::SaveHouseSprite;
+CSprite2d CRadar::StripSprite;
+CSprite2d CRadar::IceSprite;
+CSprite2d CRadar::KCabsSprite;
+CSprite2d CRadar::LovefistSprite;
+CSprite2d CRadar::PrintworksSprite;
+CSprite2d CRadar::PropertySprite;
+CSprite2d CRadar::SunYardSprite;
CSprite2d CRadar::SpraySprite;
-CSprite2d CRadar::TonySprite;
-CSprite2d CRadar::WeaponSprite;
+CSprite2d CRadar::TShirtSprite;
+CSprite2d CRadar::TommySprite;
+CSprite2d CRadar::PhoneSprite;
+CSprite2d CRadar::RadioWildstyleSprite;
+CSprite2d CRadar::RadioFlashSprite;
+CSprite2d CRadar::RadioKChatSprite;
+CSprite2d CRadar::RadioFeverSprite;
+CSprite2d CRadar::RadioVRockSprite;
+CSprite2d CRadar::RadioVCPRSprite;
+CSprite2d CRadar::RadioEspantosoSprite;
+CSprite2d CRadar::RadioEmotionSprite;
+CSprite2d CRadar::RadioWaveSprite;
CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = {
nil,
- &AsukaSprite,
- &BombSprite,
- &CatSprite,
&CentreSprite,
- &CopcarSprite,
- &DonSprite,
- &EightSprite,
- &ElSprite,
- &IceSprite,
- &JoeySprite,
- &KenjiSprite,
- &LizSprite,
- &LuigiSprite,
+ &MapHereSprite,
&NorthSprite,
- &RaySprite,
- &SalSprite,
- &SaveSprite,
+ &AverySprite,
+ &BikerSprite,
+ &CortezSprite,
+ &DiazSprite,
+ &KentSprite,
+ &LawyerSprite,
+ &PhilSprite,
+ &BikersSprite,
+ &BoatyardSprite,
+ &MalibuClubSprite,
+ &CubansSprite,
+ &FilmSprite,
+ &GunSprite,
+ &HaitiansSprite,
+ &HardwareSprite,
+ &SaveHouseSprite,
+ &StripSprite,
+ &IceSprite,
+ &KCabsSprite,
+ &LovefistSprite,
+ &PrintworksSprite,
+ &PropertySprite,
+ &SunYardSprite,
&SpraySprite,
- &TonySprite,
- &WeaponSprite
+ &TShirtSprite,
+ &TommySprite,
+ &PhoneSprite,
+ &RadioWildstyleSprite,
+ &RadioFlashSprite,
+ &RadioKChatSprite,
+ &RadioFeverSprite,
+ &RadioVRockSprite,
+ &RadioVCPRSprite,
+ &RadioEspantosoSprite,
+ &RadioEmotionSprite,
+ &RadioWaveSprite
};
// Why this doesn't coincide with world coordinates i don't know
@@ -87,12 +125,11 @@ static_assert(RADAR_TILE_SIZE == (RADAR_SIZE_Y / RADAR_NUM_TILES), "CRadar: not
CRGBA CRadar::ArrowBlipColour1;
CRGBA CRadar::ArrowBlipColour2;
uint16 CRadar::MapLegendCounter;
-uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS];
+int16 CRadar::MapLegendList[NUM_MAP_LEGENDS];
int CRadar::TargetMarkerId = -1;
CVector CRadar::TargetMarkerPos;
#endif
-// taken from VC
float CRadar::cachedCos;
float CRadar::cachedSin;
@@ -273,12 +310,9 @@ void CRadar::ClearBlip(int32 i)
if (index != -1) {
SetRadarMarkerState(index, false);
ms_RadarTrace[index].m_bInUse = false;
-#ifndef MENU_MAP
- // Ssshhh
ms_RadarTrace[index].m_eBlipType = BLIP_NONE;
ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE;
-#endif
}
}
@@ -378,9 +412,8 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect)
bool CRadar::DisplayThisBlip(int32 counter)
{
switch (ms_RadarTrace[counter].m_eRadarSprite) {
- case RADAR_SPRITE_BOMB:
case RADAR_SPRITE_SPRAY:
- case RADAR_SPRITE_WEAPON:
+ case RADAR_SPRITE_GUN:
return true;
default:
return false;
@@ -481,11 +514,6 @@ void CRadar::DrawBlips()
CEntity *blipEntity = nil;
for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
-#ifdef MENU_MAP
- // A little hack to reuse cleared blips in menu map. hehe
- if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR ||
- ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT)
-#endif
if (!ms_RadarTrace[blipId].m_bInUse)
continue;
@@ -493,8 +521,8 @@ void CRadar::DrawBlips()
case BLIP_CAR:
case BLIP_CHAR:
case BLIP_OBJECT:
- if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
- || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) {
+ if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
+ || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_GUN) {
switch (ms_RadarTrace[blipId].m_eBlipType) {
case BLIP_CAR:
@@ -527,21 +555,24 @@ void CRadar::DrawBlips()
TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
float dist = LimitRadarPoint(in);
TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- } else {
-#ifdef TRIANGULAR_BLIPS
- const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- const CVector &blipPos = blipEntity->GetPosition();
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
+ if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) {
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
}
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+ else {
+#ifdef TRIANGULAR_BLIPS
+ const CVector& pos = FindPlayerCentreOfWorld_NoSniperShift();
+ const CVector& blipPos = blipEntity->GetPosition();
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
#endif
+ }
}
}
}
@@ -549,8 +580,8 @@ void CRadar::DrawBlips()
break;
case BLIP_COORD:
case BLIP_CONTACT_POINT:
- if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
- || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON)
+ if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
+ || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_GUN)
&& (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
@@ -566,21 +597,24 @@ void CRadar::DrawBlips()
TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
float dist = LimitRadarPoint(in);
TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- } else {
-#ifdef TRIANGULAR_BLIPS
- const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- const CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
+ if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) {
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
}
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+ else {
+#ifdef TRIANGULAR_BLIPS
+ const CVector& pos = FindPlayerCentreOfWorld_NoSniperShift();
+ const CVector& blipPos = ms_RadarTrace[blipId].m_vecPos;
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
#endif
+ }
}
}
}
@@ -597,8 +631,8 @@ void CRadar::DrawBlips()
case BLIP_CAR:
case BLIP_CHAR:
case BLIP_OBJECT:
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
- && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) {
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
+ && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN) {
switch (ms_RadarTrace[blipId].m_eBlipType) {
case BLIP_CAR:
@@ -632,23 +666,25 @@ void CRadar::DrawBlips()
TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
float dist = LimitRadarPoint(in);
TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- else
+ if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) {
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ else
#ifdef TRIANGULAR_BLIPS
- {
- const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- const CVector &blipPos = blipEntity->GetPosition();
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
+ {
+ const CVector& pos = FindPlayerCentreOfWorld_NoSniperShift();
+ const CVector& blipPos = blipEntity->GetPosition();
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
}
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
- }
#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
#endif
+ }
}
}
}
@@ -664,8 +700,8 @@ void CRadar::DrawBlips()
switch (ms_RadarTrace[blipId].m_eBlipType) {
case BLIP_COORD:
case BLIP_CONTACT_POINT:
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
- && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
+ && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN
&& (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
@@ -681,23 +717,25 @@ void CRadar::DrawBlips()
TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
float dist = LimitRadarPoint(in);
TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- else
+ if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) {
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ else
#ifdef TRIANGULAR_BLIPS
- {
- const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- const CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
+ {
+ const CVector& pos = FindPlayerCentreOfWorld_NoSniperShift();
+ const CVector& blipPos = ms_RadarTrace[blipId].m_vecPos;
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
}
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
- }
#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
#endif
+ }
}
}
break;
@@ -992,6 +1030,7 @@ CRadar::Initialise()
ms_RadarTrace[i].m_BlipIndex = 1;
SetRadarMarkerState(i, false);
ms_RadarTrace[i].m_bInUse = false;
+ ms_RadarTrace[i].m_bShortRange = false;
ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
@@ -1036,26 +1075,45 @@ CRadar::LoadTextures()
{
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud"));
- AsukaSprite.SetTexture("radar_asuka");
- BombSprite.SetTexture("radar_bomb");
- CatSprite.SetTexture("radar_cat");
CentreSprite.SetTexture("radar_centre");
- CopcarSprite.SetTexture("radar_copcar");
- DonSprite.SetTexture("radar_don");
- EightSprite.SetTexture("radar_eight");
- ElSprite.SetTexture("radar_el");
- IceSprite.SetTexture("radar_ice");
- JoeySprite.SetTexture("radar_joey");
- KenjiSprite.SetTexture("radar_kenji");
- LizSprite.SetTexture("radar_liz");
- LuigiSprite.SetTexture("radar_luigi");
+ MapHereSprite.SetTexture("arrow");
NorthSprite.SetTexture("radar_north");
- RaySprite.SetTexture("radar_ray");
- SalSprite.SetTexture("radar_sal");
- SaveSprite.SetTexture("radar_save");
- SpraySprite.SetTexture("radar_spray");
- TonySprite.SetTexture("radar_tony");
- WeaponSprite.SetTexture("radar_weapon");
+ AverySprite.SetTexture("radar_avery");
+ BikerSprite.SetTexture("radar_biker");
+ CortezSprite.SetTexture("radar_cortez");
+ DiazSprite.SetTexture("radar_diaz");
+ KentSprite.SetTexture("radar_kent");
+ LawyerSprite.SetTexture("radar_lawyer");
+ PhilSprite.SetTexture("radar_phil");
+ BikersSprite.SetTexture("bikers");
+ BoatyardSprite.SetTexture("boatyard");
+ MalibuClubSprite.SetTexture("club");
+ CubansSprite.SetTexture("cubans");
+ FilmSprite.SetTexture("filmstudio");
+ GunSprite.SetTexture("gun");
+ HaitiansSprite.SetTexture("haitians");
+ HardwareSprite.SetTexture("hardware");
+ SaveHouseSprite.SetTexture("radar_save");
+ StripSprite.SetTexture("radar_strip");
+ IceSprite.SetTexture("icecream");
+ KCabsSprite.SetTexture("kcabs");
+ LovefistSprite.SetTexture("lovefist");
+ PrintworksSprite.SetTexture("printworks");
+ PropertySprite.SetTexture("property");
+ SunYardSprite.SetTexture("SunYard");
+ SpraySprite.SetTexture("spray");
+ TShirtSprite.SetTexture("tshirt");
+ TommySprite.SetTexture("tommy");
+ PhoneSprite.SetTexture("phone");
+ RadioWildstyleSprite.SetTexture("RWildstyle");
+ RadioFlashSprite.SetTexture("RFlash");
+ RadioKChatSprite.SetTexture("RKchat");
+ RadioFeverSprite.SetTexture("RFever");
+ RadioVRockSprite.SetTexture("RVRock");
+ RadioVCPRSprite.SetTexture("RVCPR");
+ RadioEspantosoSprite.SetTexture("REspantoso");
+ RadioEmotionSprite.SetTexture("REmotion");
+ RadioWaveSprite.SetTexture("RWave");
CTxdStore::PopCurrentTxd();
}
@@ -1102,8 +1160,9 @@ int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay
}
ms_RadarTrace[nextBlip].m_eBlipType = type;
ms_RadarTrace[nextBlip].m_nColor = color;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_bDim = true;
+ ms_RadarTrace[nextBlip].m_bInUse = true;
+ ms_RadarTrace[nextBlip].m_bShortRange = false;
ms_RadarTrace[nextBlip].m_Radius = 1.0f;
ms_RadarTrace[nextBlip].m_vec2DPos = pos;
ms_RadarTrace[nextBlip].m_vecPos = pos;
@@ -1114,6 +1173,15 @@ int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay
return CRadar::GetNewUniqueBlipIndex(nextBlip);
}
+int CRadar::SetShortRangeCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay display)
+{
+ int index = SetCoordBlip(type, pos, color, display);
+ if (index == -1)
+ return -1;
+ ms_RadarTrace[GetActualBlipArrayIndex(index)].m_bShortRange = true;
+ return index;
+}
+
int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDisplay display)
{
int nextBlip;
@@ -1123,8 +1191,9 @@ int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDispla
}
ms_RadarTrace[nextBlip].m_eBlipType = type;
ms_RadarTrace[nextBlip].m_nColor = color;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_bDim = true;
+ ms_RadarTrace[nextBlip].m_bInUse = true;
+ ms_RadarTrace[nextBlip].m_bShortRange = false;
ms_RadarTrace[nextBlip].m_Radius = 1.0f;
ms_RadarTrace[nextBlip].m_nEntityHandle = handle;
ms_RadarTrace[nextBlip].m_wScale = 1;
@@ -1226,26 +1295,45 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red,
void CRadar::Shutdown()
{
- AsukaSprite.Delete();
- BombSprite.Delete();
- CatSprite.Delete();
CentreSprite.Delete();
- CopcarSprite.Delete();
- DonSprite.Delete();
- EightSprite.Delete();
- ElSprite.Delete();
- IceSprite.Delete();
- JoeySprite.Delete();
- KenjiSprite.Delete();
- LizSprite.Delete();
- LuigiSprite.Delete();
+ MapHereSprite.Delete();
NorthSprite.Delete();
- RaySprite.Delete();
- SalSprite.Delete();
- SaveSprite.Delete();
+ AverySprite.Delete();
+ BikerSprite.Delete();
+ CortezSprite.Delete();
+ DiazSprite.Delete();
+ KentSprite.Delete();
+ LawyerSprite.Delete();
+ PhilSprite.Delete();
+ BikersSprite.Delete();
+ BoatyardSprite.Delete();
+ MalibuClubSprite.Delete();
+ CubansSprite.Delete();
+ FilmSprite.Delete();
+ GunSprite.Delete();
+ HaitiansSprite.Delete();
+ HardwareSprite.Delete();
+ SaveHouseSprite.Delete();
+ StripSprite.Delete();
+ IceSprite.Delete();
+ KCabsSprite.Delete();
+ LovefistSprite.Delete();
+ PrintworksSprite.Delete();
+ PropertySprite.Delete();
+ SunYardSprite.Delete();
SpraySprite.Delete();
- TonySprite.Delete();
- WeaponSprite.Delete();
+ TShirtSprite.Delete();
+ TommySprite.Delete();
+ PhoneSprite.Delete();
+ RadioWildstyleSprite.Delete();
+ RadioFlashSprite.Delete();
+ RadioKChatSprite.Delete();
+ RadioFeverSprite.Delete();
+ RadioVRockSprite.Delete();
+ RadioVCPRSprite.Delete();
+ RadioEspantosoSprite.Delete();
+ RadioEmotionSprite.Delete();
+ RadioWaveSprite.Delete();
RemoveRadarSections();
}
@@ -1316,9 +1404,8 @@ void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &i
{
#ifdef MENU_MAP
if (CMenuManager::bMenuMapActive) {
- // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0.
- out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f;
- out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f;
+ out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * CMenuManager::fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH;
+ out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * CMenuManager::fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH;
} else
#endif
{
@@ -1406,7 +1493,7 @@ CRadar::InitFrontEndMap()
CalculateCachedSinCos();
vec2DRadarOrigin.x = 0.0f;
vec2DRadarOrigin.y = 0.0f;
- m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace
+ m_radarRange = MENU_MAP_LENGTH_UNIT; // just affects the multiplier in TransformRadarPointToScreenSpace
for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
MapLegendList[i] = RADAR_SPRITE_NONE;
}
diff --git a/src/core/Radar.h b/src/core/Radar.h
index ec2bacd0..f68d290c 100644
--- a/src/core/Radar.h
+++ b/src/core/Radar.h
@@ -1,6 +1,13 @@
#pragma once
#include "Sprite2d.h"
+#define MENU_MAP_LENGTH_UNIT 1190.0f // in game unit
+#define MENU_MAP_WIDTH_SCALE 1.112f // in game unit (originally 1.112494151260504f)
+#define MENU_MAP_HEIGHT_SCALE 1.119f // in game unit (originally 1.118714268907563f)
+#define MENU_MAP_TOP_OFFSET 0.28f // in length unit defined above - ~333 game unit
+#define MENU_MAP_LEFT_OFFSET 0.185f // in length unit defined above - ~220 game unit
+#define MENU_MAP_LENGTH (4000.f / MENU_MAP_LENGTH_UNIT)
+
enum eBlipType
{
BLIP_NONE,
@@ -26,26 +33,46 @@ enum eRadarSprite
RADAR_SPRITE_COORD_BLIP = -1,
#endif
RADAR_SPRITE_NONE = 0,
- RADAR_SPRITE_ASUKA,
- RADAR_SPRITE_BOMB,
- RADAR_SPRITE_CAT,
RADAR_SPRITE_CENTRE,
- RADAR_SPRITE_COPCAR,
- RADAR_SPRITE_DON,
- RADAR_SPRITE_EIGHT,
- RADAR_SPRITE_EL,
- RADAR_SPRITE_ICE,
- RADAR_SPRITE_JOEY,
- RADAR_SPRITE_KENJI,
- RADAR_SPRITE_LIZ,
- RADAR_SPRITE_LUIGI,
+ RADAR_SPRITE_MAP_HERE,
RADAR_SPRITE_NORTH,
- RADAR_SPRITE_RAY,
- RADAR_SPRITE_SAL,
+ RADAR_SPRITE_AVERY,
+ RADAR_SPRITE_BIKER,
+ RADAR_SPRITE_CORTEZ,
+ RADAR_SPRITE_DIAZ,
+ RADAR_SPRITE_KENT,
+ RADAR_SPRITE_LAWYER,
+ RADAR_SPRITE_PHIL,
+ RADAR_SPRITE_BIKERS,
+ RADAR_SPRITE_BOATYARD,
+ RADAR_SPRITE_MALIBU_CLUB,
+ RADAR_SPRITE_CUBANS,
+ RADAR_SPRITE_FILM,
+ RADAR_SPRITE_GUN,
+ RADAR_SPRITE_HAITIANS,
+ RADAR_SPRITE_HARDWARE,
RADAR_SPRITE_SAVE,
+ RADAR_SPRITE_STRIP,
+ RADAR_SPRITE_ICE,
+ RADAR_SPRITE_KCABS,
+ RADAR_SPRITE_LOVEFIST,
+ RADAR_SPRITE_PRINTWORKS,
+ RADAR_SPRITE_PROPERTY,
+ RADAR_SPRITE_SUNYARD,
RADAR_SPRITE_SPRAY,
- RADAR_SPRITE_TONY,
- RADAR_SPRITE_WEAPON,
+ RADAR_SPRITE_TSHIRT,
+ RADAR_SPRITE_TOMMY,
+ RADAR_SPRITE_PHONE,
+ RADAR_SPRITE_RADIO_WILDSTYLE,
+ RADAR_SPRITE_RADIO_FLASH,
+ RADAR_SPRITE_RADIO_KCHAT,
+ RADAR_SPRITE_RADIO_FEVER,
+ RADAR_SPRITE_RADIO_VROCK,
+ RADAR_SPRITE_RADIO_VCPR,
+ RADAR_SPRITE_RADIO_ESPANTOSO,
+ RADAR_SPRITE_RADIO_EMOTION,
+ RADAR_SPRITE_RADIO_WAVE,
+
RADAR_SPRITE_COUNT
};
@@ -66,12 +93,12 @@ struct sRadarTrace
uint16 m_BlipIndex;
bool m_bDim;
bool m_bInUse;
+ bool m_bShortRange;
float m_Radius;
int16 m_wScale;
uint16 m_eBlipDisplay; // eBlipDisplay
uint16 m_eRadarSprite; // eRadarSprite
};
-VALIDATE_SIZE(sRadarTrace, 0x30);
// Values for screen space
#define RADAR_LEFT (40.0f)
@@ -84,26 +111,45 @@ class CRadar
public:
static float m_radarRange;
static sRadarTrace ms_RadarTrace[NUMRADARBLIPS];
- static CSprite2d AsukaSprite;
- static CSprite2d BombSprite;
- static CSprite2d CatSprite;
static CSprite2d CentreSprite;
- static CSprite2d CopcarSprite;
- static CSprite2d DonSprite;
- static CSprite2d EightSprite;
- static CSprite2d ElSprite;
- static CSprite2d IceSprite;
- static CSprite2d JoeySprite;
- static CSprite2d KenjiSprite;
- static CSprite2d LizSprite;
- static CSprite2d LuigiSprite;
+ static CSprite2d MapHereSprite;
static CSprite2d NorthSprite;
- static CSprite2d RaySprite;
- static CSprite2d SalSprite;
- static CSprite2d SaveSprite;
+ static CSprite2d AverySprite;
+ static CSprite2d BikerSprite;
+ static CSprite2d CortezSprite;
+ static CSprite2d DiazSprite;
+ static CSprite2d KentSprite;
+ static CSprite2d LawyerSprite;
+ static CSprite2d PhilSprite;
+ static CSprite2d BikersSprite;
+ static CSprite2d BoatyardSprite;
+ static CSprite2d MalibuClubSprite;
+ static CSprite2d CubansSprite;
+ static CSprite2d FilmSprite;
+ static CSprite2d GunSprite;
+ static CSprite2d HaitiansSprite;
+ static CSprite2d HardwareSprite;
+ static CSprite2d SaveHouseSprite;
+ static CSprite2d StripSprite;
+ static CSprite2d IceSprite;
+ static CSprite2d KCabsSprite;
+ static CSprite2d LovefistSprite;
+ static CSprite2d PrintworksSprite;
+ static CSprite2d PropertySprite;
+ static CSprite2d SunYardSprite;
static CSprite2d SpraySprite;
- static CSprite2d TonySprite;
- static CSprite2d WeaponSprite;
+ static CSprite2d TShirtSprite;
+ static CSprite2d TommySprite;
+ static CSprite2d PhoneSprite;
+ static CSprite2d RadioWildstyleSprite;
+ static CSprite2d RadioFlashSprite;
+ static CSprite2d RadioKChatSprite;
+ static CSprite2d RadioFeverSprite;
+ static CSprite2d RadioVRockSprite;
+ static CSprite2d RadioVCPRSprite;
+ static CSprite2d RadioEspantosoSprite;
+ static CSprite2d RadioEmotionSprite;
+ static CSprite2d RadioWaveSprite;
static CSprite2d *RadarSprites[RADAR_SPRITE_COUNT];
static float cachedCos;
static float cachedSin;
@@ -111,7 +157,7 @@ public:
#define NUM_MAP_LEGENDS 75
static CRGBA ArrowBlipColour1;
static CRGBA ArrowBlipColour2;
- static uint16 MapLegendList[NUM_MAP_LEGENDS];
+ static int16 MapLegendList[NUM_MAP_LEGENDS];
static uint16 MapLegendCounter;
static int TargetMarkerId;
static CVector TargetMarkerPos;
@@ -149,6 +195,7 @@ public:
static void SetBlipSprite(int32 i, int32 icon);
static int32 SetCoordBlip(eBlipType type, CVector pos, int32, eBlipDisplay);
static int32 SetEntityBlip(eBlipType type, int32, int32, eBlipDisplay);
+ static int32 SetShortRangeCoordBlip(eBlipType type, CVector pos, int32, eBlipDisplay);
static void SetRadarMarkerState(int32 i, bool flag);
static void ShowRadarMarker(CVector pos, uint32 color, float radius);
static void ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha);
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 99274e04..32148476 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -58,6 +58,11 @@ int32 CStats::CarsCrushed;
int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES];
int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES];
+int32 CStats::Sprayings;
+float CStats::AutoPaintingBudget;
+int32 CStats::NoMoreHurricanes;
+float CStats::FashionBudget;
+
void CStats::Init()
{
PeopleKilledByOthers = 0;
@@ -113,6 +118,10 @@ void CStats::Init()
IndustrialPassed = 0;
CommercialPassed = 0;
SuburbanPassed = 0;
+
+ Sprayings = 0;
+ AutoPaintingBudget = 0.0f;
+ NoMoreHurricanes = 0;
}
void CStats::RegisterFastestTime(int32 index, int32 time)
@@ -241,6 +250,19 @@ int32 CStats::FindCriminalRatingNumber()
return rating;
}
+float CStats::GetPercentageProgress()
+{
+ float percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 :
+ CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1.0f));
+
+ return Min(percentCompleted, 100.0f);
+}
+
+void CStats::MoneySpentOnFashion(int32 money)
+{
+ FashionBudget += money;
+}
+
void CStats::SaveStats(uint8 *buf, uint32 *size)
{
CheckPointReachedSuccessfully();
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 4445ecf4..67ee86f7 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -62,6 +62,10 @@ public:
static int32 CarsCrushed;
static int32 FastestTimes[TOTAL_FASTEST_TIMES];
static int32 HighestScores[TOTAL_HIGHEST_SCORES];
+ static int32 Sprayings;
+ static float AutoPaintingBudget;
+ static int32 NoMoreHurricanes;
+ static float FashionBudget;
public:
static void Init(void);
@@ -87,4 +91,7 @@ public:
static int32 FindCriminalRatingNumber();
static void SaveStats(uint8 *buf, uint32 *size);
static void LoadStats(uint8 *buf, uint32 size);
+ static float GetPercentageProgress();
+
+ static void MoneySpentOnFashion(int32);
};
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index c961f53d..0ce8b50e 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -18,7 +18,6 @@
#include "FileMgr.h"
#include "FileLoader.h"
#include "Zones.h"
-#include "ZoneCull.h"
#include "Radar.h"
#include "Camera.h"
#include "Record.h"
@@ -28,10 +27,10 @@
#include "CutsceneMgr.h"
#include "CdStream.h"
#include "Streaming.h"
-#ifdef FIX_BUGS
#include "Replay.h"
-#endif
#include "main.h"
+#include "ColStore.h"
+#include "DMAudio.h"
bool CStreaming::ms_disableStreaming;
bool CStreaming::ms_bLoadingBigModel;
@@ -51,9 +50,9 @@ int32 CStreaming::ms_channelError;
int32 CStreaming::ms_numVehiclesLoaded;
int32 CStreaming::ms_vehiclesLoaded[MAXVEHICLESLOADED];
int32 CStreaming::ms_lastVehicleDeleted;
+bool CStreaming::ms_bIsPedFromPedGroupLoaded[NUMMODELSPERPEDGROUP];
CDirectory *CStreaming::ms_pExtraObjectsDir;
int32 CStreaming::ms_numPriorityRequests;
-bool CStreaming::ms_hasLoadedLODs;
int32 CStreaming::ms_currentPedGrp;
int32 CStreaming::ms_currentPedLoading;
int32 CStreaming::ms_lastCullZone;
@@ -66,17 +65,12 @@ uint32 CStreaming::ms_memoryAvailable;
int32 desiredNumVehiclesLoaded = 12;
-CEntity *pIslandLODindustEntity;
-CEntity *pIslandLODcomIndEntity;
-CEntity *pIslandLODcomSubEntity;
-CEntity *pIslandLODsubIndEntity;
-CEntity *pIslandLODsubComEntity;
-int32 islandLODindust;
-int32 islandLODcomInd;
-int32 islandLODcomSub;
-int32 islandLODsubInd;
-int32 islandLODsubCom;
+CEntity *pIslandLODmainlandEntity;
+CEntity *pIslandLODbeachEntity;
+int32 islandLODmainland;
+int32 islandLODbeach;
+//--MIAMI: done
bool
CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
{
@@ -87,6 +81,7 @@ CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
return true;
}
+//--MIAMI: done
void
CStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size)
{
@@ -94,6 +89,7 @@ CStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size)
m_size = size;
}
+//--MIAMI: done
void
CStreamingInfo::AddToList(CStreamingInfo *link)
{
@@ -104,6 +100,7 @@ CStreamingInfo::AddToList(CStreamingInfo *link)
m_next->m_prev = this;
}
+//--MIAMI: done
void
CStreamingInfo::RemoveFromList(void)
{
@@ -113,6 +110,7 @@ CStreamingInfo::RemoveFromList(void)
m_prev = nil;
}
+//--MIAMI: done
void
CStreaming::Init2(void)
{
@@ -182,13 +180,15 @@ CStreaming::Init2(void)
ms_vehiclesLoaded[i] = -1;
ms_numVehiclesLoaded = 0;
+ for(i = 0; i < ARRAY_SIZE(ms_bIsPedFromPedGroupLoaded); i++)
+ ms_bIsPedFromPedGroupLoaded[i] = false;
+
ms_pExtraObjectsDir = new CDirectory(EXTRADIRSIZE);
ms_numPriorityRequests = 0;
- ms_hasLoadedLODs = true;
ms_currentPedGrp = -1;
ms_lastCullZone = -1; // unused because RemoveModelsNotVisibleFromCullzone is gone
ms_loadedGangs = 0;
- ms_currentPedLoading = 8; // unused, whatever it is
+ ms_currentPedLoading = NUMMODELSPERPEDGROUP; // unused, whatever it is
LoadCdDirectory();
@@ -199,48 +199,20 @@ CStreaming::Init2(void)
ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
debug("Streaming buffer size is %d sectors", ms_streamingBufferSize);
- // PC only, figure out how much memory we got
-#ifdef GTA_PC
#define MB (1024*1024)
- extern unsigned long _dwMemAvailPhys;
- ms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2;
- if(ms_memoryAvailable < 50*MB)
- ms_memoryAvailable = 50*MB;
- desiredNumVehiclesLoaded = (ms_memoryAvailable/MB - 50)/3 + 12;
- if(desiredNumVehiclesLoaded > MAXVEHICLESLOADED)
- desiredNumVehiclesLoaded = MAXVEHICLESLOADED;
+ ms_memoryAvailable = 65*MB;
+ desiredNumVehiclesLoaded = 25;
debug("Memory allocated to Streaming is %dMB", ms_memoryAvailable/MB);
#undef MB
-#endif
// find island LODs
- pIslandLODindustEntity = nil;
- pIslandLODcomIndEntity = nil;
- pIslandLODcomSubEntity = nil;
- pIslandLODsubIndEntity = nil;
- pIslandLODsubComEntity = nil;
- islandLODindust = -1;
- islandLODcomInd = -1;
- islandLODcomSub = -1;
- islandLODsubInd = -1;
- islandLODsubCom = -1;
- CModelInfo::GetModelInfo("IslandLODInd", &islandLODindust);
- CModelInfo::GetModelInfo("IslandLODcomIND", &islandLODcomInd);
- CModelInfo::GetModelInfo("IslandLODcomSUB", &islandLODcomSub);
- CModelInfo::GetModelInfo("IslandLODsubIND", &islandLODsubInd);
- CModelInfo::GetModelInfo("IslandLODsubCOM", &islandLODsubCom);
-
- for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){
- CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
- if(building == nil)
- continue;
- if(building->GetModelIndex() == islandLODindust) pIslandLODindustEntity = building;
- if(building->GetModelIndex() == islandLODcomInd) pIslandLODcomIndEntity = building;
- if(building->GetModelIndex() == islandLODcomSub) pIslandLODcomSubEntity = building;
- if(building->GetModelIndex() == islandLODsubInd) pIslandLODsubIndEntity = building;
- if(building->GetModelIndex() == islandLODsubCom) pIslandLODsubComEntity = building;
- }
+ pIslandLODmainlandEntity = nil;
+ pIslandLODbeachEntity = nil;
+ islandLODmainland = -1;
+ islandLODbeach = -1;
+ CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland);
+ CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach);
}
void
@@ -266,6 +238,7 @@ CStreaming::Init(void)
#endif
}
+//--MIAMI: done
void
CStreaming::Shutdown(void)
{
@@ -275,10 +248,10 @@ CStreaming::Shutdown(void)
delete ms_pExtraObjectsDir;
}
+//--MIAMI: done
void
CStreaming::Update(void)
{
- CEntity *train;
CStreamingInfo *si, *prev;
bool requestedSubway = false;
@@ -292,31 +265,32 @@ CStreaming::Update(void)
if(CTimer::GetIsPaused())
return;
- train = FindPlayerTrain();
- if(train && train->GetPosition().z < 0.0f){
- RequestSubway();
- requestedSubway = true;
- }else if(!ms_disableStreaming)
+ LoadBigBuildingsWhenNeeded();
+ if(!ms_disableStreaming && TheCamera.GetPosition().z < 55.0f)
AddModelsToRequestList(TheCamera.GetPosition());
DeleteFarAwayRwObjects(TheCamera.GetPosition());
if(!ms_disableStreaming &&
- !CCutsceneMgr::IsRunning() &&
- !requestedSubway &&
- !CGame::playingIntro &&
+ !CCutsceneMgr::IsCutsceneProcessing() &&
ms_numModelsRequested < 5 &&
- !CRenderer::m_loadingPriority
-#ifdef FIX_BUGS
- && !CReplay::IsPlayingBack()
-#endif
- ){
+ !CRenderer::m_loadingPriority &&
+ CGame::currArea == AREA_MAIN_MAP &&
+ !CReplay::IsPlayingBack()){
StreamVehiclesAndPeds();
StreamZoneModels(FindPlayerCoors());
}
LoadRequestedModels();
+ if(CWorld::Players[0].m_pRemoteVehicle){
+ CColStore::AddCollisionNeededAtPosn(FindPlayerCoors());
+ CColStore::LoadCollision(CWorld::Players[0].m_pRemoteVehicle->GetPosition());
+ CColStore::EnsureCollisionIsInMemory(CWorld::Players[0].m_pRemoteVehicle->GetPosition());
+ }else{
+ CColStore::LoadCollision(FindPlayerCoors());
+ CColStore::EnsureCollisionIsInMemory(FindPlayerCoors());
+ }
for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){
prev = si->m_prev;
@@ -325,6 +299,7 @@ CStreaming::Update(void)
}
}
+//--MIAMI: done
void
CStreaming::LoadCdDirectory(void)
{
@@ -338,12 +313,6 @@ CStreaming::LoadCdDirectory(void)
ms_imageOffsets[3] = -1;
ms_imageOffsets[4] = -1;
ms_imageOffsets[5] = -1;
- ms_imageOffsets[6] = -1;
- ms_imageOffsets[7] = -1;
- ms_imageOffsets[8] = -1;
- ms_imageOffsets[9] = -1;
- ms_imageOffsets[10] = -1;
- ms_imageOffsets[11] = -1;
ms_imageSize = GetGTA3ImgSize();
// PS2 uses CFileMgr::GetCdFile on all IMG files to fill the array
#endif
@@ -359,12 +328,12 @@ CStreaming::LoadCdDirectory(void)
ms_imageSize /= CDSTREAM_SECTOR_SIZE;
}
+//--MIAMI: done
void
CStreaming::LoadCdDirectory(const char *dirname, int n)
{
int fd, lastID, imgSelector;
- int modelId, txdId;
- uint32 posn, size;
+ int modelId;
CDirectory::DirectoryInfo direntry;
char *dot;
@@ -375,23 +344,23 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
imgSelector = n<<24;
assert(sizeof(direntry) == 32);
while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){
- dot = strchr(direntry.name, '.');
- if(dot) *dot = '\0';
+ bool bAddToStreaming = false;
+
if(direntry.size > (uint32)ms_streamingBufferSize)
ms_streamingBufferSize = direntry.size;
+ direntry.name[23] = '\0';
+ dot = strchr(direntry.name, '.');
+ if(dot == nil || dot-direntry.name > 20){
+ debug("%s is too long\n", direntry.name);
+ lastID = -1;
+ continue;
+ }
+
+ *dot = '\0';
- if(!CGeneral::faststrcmp(dot+1, "DFF") || !CGeneral::faststrcmp(dot+1, "dff")){
+ if(strncasecmp(dot+1, "DFF", 3) == 0){
if(CModelInfo::GetModelInfo(direntry.name, &modelId)){
- if(ms_aInfoForModel[modelId].GetCdPosnAndSize(posn, size)){
- debug("%s appears more than once in %s\n", direntry.name, dirname);
- lastID = -1;
- }else{
- direntry.offset |= imgSelector;
- ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size);
- if(lastID != -1)
- ms_aInfoForModel[lastID].m_nextID = modelId;
- lastID = modelId;
- }
+ bAddToStreaming = true;
}else{
#ifdef FIX_BUGS
// remember which cdimage this came from
@@ -401,27 +370,63 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
#endif
lastID = -1;
}
- }else if(!CGeneral::faststrcmp(dot+1, "TXD") || !CGeneral::faststrcmp(dot+1, "txd")){
- txdId = CTxdStore::FindTxdSlot(direntry.name);
- if(txdId == -1)
- txdId = CTxdStore::AddTxdSlot(direntry.name);
- if(ms_aInfoForModel[txdId + STREAM_OFFSET_TXD].GetCdPosnAndSize(posn, size)){
- debug("%s appears more than once in %s\n", direntry.name, dirname);
+ }else if(strncasecmp(dot+1, "TXD", 3) == 0){
+ modelId = CTxdStore::FindTxdSlot(direntry.name);
+ if(modelId == -1)
+ modelId = CTxdStore::AddTxdSlot(direntry.name);
+ modelId += STREAM_OFFSET_TXD;
+ bAddToStreaming = true;
+ }else if(strncasecmp(dot+1, "COL", 3) == 0){
+ modelId = CColStore::FindColSlot(direntry.name);
+ if(modelId == -1)
+ modelId = CColStore::AddColSlot(direntry.name);
+ modelId += STREAM_OFFSET_COL;
+ bAddToStreaming = true;
+ }else if(strncasecmp(dot+1, "IFP", 3) == 0){
+ modelId = CAnimManager::RegisterAnimBlock(direntry.name);
+ modelId += STREAM_OFFSET_ANIM;
+ bAddToStreaming = true;
+ }else{
+ *dot = '.';
+ lastID = -1;
+ }
+
+ if(bAddToStreaming){
+ if(ms_aInfoForModel[modelId].GetCdSize()){
+ debug("%s.%s appears more than once in %s\n", direntry.name, dot+1, dirname);
lastID = -1;
}else{
direntry.offset |= imgSelector;
- ms_aInfoForModel[txdId + STREAM_OFFSET_TXD].SetCdPosnAndSize(direntry.offset, direntry.size);
+ ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size);
if(lastID != -1)
- ms_aInfoForModel[lastID].m_nextID = txdId + STREAM_OFFSET_TXD;
- lastID = txdId + STREAM_OFFSET_TXD;
+ ms_aInfoForModel[lastID].m_nextID = modelId;
+ lastID = modelId;
}
- }else
- lastID = -1;
+ }
}
CFileMgr::CloseFile(fd);
}
+static char*
+GetObjectName(int streamId)
+{
+ static char objname[32];
+ if(streamId < STREAM_OFFSET_TXD)
+ sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetName());
+ else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL)
+ sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD));
+ else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM)
+ sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL));
+ else{
+ assert(streamId < NUMSTREAMINFO);
+ sprintf(objname, "%s.ifp", CAnimManager::GetAnimationBlock(streamId-STREAM_OFFSET_ANIM)->name);
+ }
+ return objname;
+}
+
+
+//--MIAMI: done
bool
CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
{
@@ -443,22 +448,25 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Model
mi = CModelInfo::GetModelInfo(streamId);
- // Txd has to be loaded
- if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil){
- debug("failed to load %s because TXD %s is not in memory\n", mi->GetName(), CTxdStore::GetTxdName(mi->GetTxdSlot()));
+ // Txd and anim have to be loaded
+ int animId = mi->GetAnimFileIndex();
+ if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil ||
+ animId != -1 && !CAnimManager::GetAnimationBlock(animId)->isLoaded){
RemoveModel(streamId);
- RemoveTxd(mi->GetTxdSlot());
ReRequestModel(streamId);
RwStreamClose(stream, &mem);
return false;
}
- // Set Txd to use
+ // Set Txd and anims to use
CTxdStore::AddRef(mi->GetTxdSlot());
+ if(animId != -1)
+ CAnimManager::AddAnimBlockRef(animId);
CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
if(mi->IsSimple()){
success = CFileLoader::LoadAtomicFile(stream, streamId);
+ // TODO(MIAMI)? complain if file is not pre-instanced. we hardly are interested in that
} else if (mi->GetModelType() == MITYPE_VEHICLE) {
// load vehicles in two parts
CModelInfo::GetModelInfo(streamId)->AddRef();
@@ -470,9 +478,12 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
}
UpdateMemoryUsed();
- // Txd no longer needed unless we only read part of the file
- if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED)
+ // Txd and anims no longer needed unless we only read part of the file
+ if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){
CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());
+ if(animId != -1)
+ CAnimManager::RemoveAnimBlockRefWithoutDelete(animId);
+ }
if(!success){
debug("Failed to load %s\n", CModelInfo::GetModelInfo(streamId)->GetName());
@@ -481,9 +492,8 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
RwStreamClose(stream, &mem);
return false;
}
- }else{
+ }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){
// Txd
- assert(streamId < NUMSTREAMINFO);
if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 &&
!IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){
RemoveModel(streamId);
@@ -506,20 +516,28 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
RwStreamClose(stream, &mem);
return false;
}
+ }else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM){
+ if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){
+ debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL));
+ RemoveModel(streamId);
+ ReRequestModel(streamId);
+ RwStreamClose(stream, &mem);
+ return false;
+ }
+ }else if(streamId >= STREAM_OFFSET_ANIM){
+ assert(streamId < NUMSTREAMINFO);
+ if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 &&
+ !AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)){
+ RemoveModel(streamId);
+ RwStreamClose(stream, &mem);
+ return false;
+ }
+ CAnimManager::LoadAnimFile(stream, true, nil);
+ CAnimManager::CreateAnimAssocGroups();
}
RwStreamClose(stream, &mem);
- // We shouldn't even end up here unless load was successful
- if(!success){
- ReRequestModel(streamId);
- if(streamId < STREAM_OFFSET_TXD)
- debug("Failed to load %s.dff\n", mi->GetName());
- else
- debug("Failed to load %s.txd\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD));
- return false;
- }
-
if(streamId < STREAM_OFFSET_TXD){
// Model
// Vehicles and Peds not in loaded list
@@ -534,12 +552,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
smi->m_alpha = 0;
}
- if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0)
+ if(CanRemoveModel(streamId))
ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList);
}
- }else{
- // Txd
- if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0)
+ }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL ||
+ streamId >= STREAM_OFFSET_ANIM){
+ assert(streamId < NUMSTREAMINFO);
+ // Txd and anims
+ if(CanRemoveModel(streamId))
ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList);
}
@@ -551,17 +571,13 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
timeDiff = endTime - startTime;
- if(timeDiff > 5){
- if(streamId < STREAM_OFFSET_TXD)
- debug("model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetName(), timeDiff);
- else
- debug("txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff);
- }
+ if(timeDiff > 5)
+ debug("%s took %d ms\n", GetObjectName(streamId), timeDiff);
return true;
}
-
+//--MIAMI: done
bool
CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)
{
@@ -592,11 +608,15 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)
success = AddToLoadedVehiclesList(streamId);
mi->RemoveRef();
CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());
- }else{
+ if(mi->GetAnimFileIndex() != -1)
+ CAnimManager::RemoveAnimBlockRefWithoutDelete(mi->GetAnimFileIndex());
+ }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){
// Txd
CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD);
success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD);
+ }else{
+ assert(0 && "invalid streamId");
}
RwStreamClose(stream, &mem);
@@ -614,16 +634,13 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
timeDiff = endTime - startTime;
- if(timeDiff > 5){
- if(streamId < STREAM_OFFSET_TXD)
- debug("finish model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetName(), timeDiff);
- else
- debug("finish txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff);
- }
+ if(timeDiff > 5)
+ debug("%s took %d ms\n", GetObjectName(streamId), timeDiff);
return true;
}
+//--MIAMI: done
void
CStreaming::RequestModel(int32 id, int32 flags)
{
@@ -652,15 +669,20 @@ CStreaming::RequestModel(int32 id, int32 flags)
// reinsert into list
if(ms_aInfoForModel[id].m_next){
ms_aInfoForModel[id].RemoveFromList();
- if((ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0)
+ if(CanRemoveModel(id))
ms_aInfoForModel[id].AddToList(&ms_startLoadedList);
}
}else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED ||
ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){ // how can this be true again?
if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED){
- if(id < STREAM_OFFSET_TXD)
- RequestTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot(), flags);
+ if(id < STREAM_OFFSET_TXD){
+ mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
+ RequestTxd(mi->GetTxdSlot(), flags);
+ int anim = mi->GetAnimFileIndex();
+ if(anim != -1)
+ RequestAnim(anim, STREAMFLAGS_DEPENDENCY);
+ }
ms_aInfoForModel[id].AddToList(&ms_startRequestedList);
ms_numModelsRequested++;
if(flags & STREAMFLAGS_PRIORITY)
@@ -672,52 +694,28 @@ CStreaming::RequestModel(int32 id, int32 flags)
}
}
+#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE
+
+//--MIAMI: done
void
-CStreaming::RequestSubway(void)
-{
- RequestModel(MI_SUBWAY1, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY2, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY3, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY4, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY5, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY6, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY7, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY8, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY9, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY10, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY11, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY12, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY13, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY14, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY15, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY16, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY17, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBWAY18, STREAMFLAGS_NOFADE);
-
- switch(CGame::currLevel){
- case LEVEL_INDUSTRIAL:
- RequestModel(MI_SUBPLATFORM_IND, STREAMFLAGS_NOFADE);
- break;
- case LEVEL_COMMERCIAL:
- if(FindPlayerTrain()->GetPosition().y < -700.0f){
- RequestModel(MI_SUBPLATFORM_COMS, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBPLATFORM_COMS2, STREAMFLAGS_NOFADE);
- }else{
- RequestModel(MI_SUBPLATFORM_COMN, STREAMFLAGS_NOFADE);
- }
- break;
- case LEVEL_SUBURBAN:
- RequestModel(MI_SUBPLATFORM_SUB, STREAMFLAGS_NOFADE);
- RequestModel(MI_SUBPLATFORM_SUB2, STREAMFLAGS_NOFADE);
- break;
- default: break;
+CStreaming::RequestBigBuildings(eLevelName level)
+{
+ int i, n;
+ CBuilding *b;
+
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
+ b = CPools::GetBuildingPool()->GetSlot(i);
+ if(b && b->bIsBIGBuilding && b->m_level == level)
+ if(!b->bStreamBIGBuilding)
+ RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);
}
+ RequestIslands(level);
}
-#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY
-
+//--MIAMI: done
void
-CStreaming::RequestBigBuildings(eLevelName level)
+CStreaming::RequestBigBuildings(eLevelName level, const CVector &pos)
{
int i, n;
CBuilding *b;
@@ -726,32 +724,91 @@ CStreaming::RequestBigBuildings(eLevelName level)
for(i = n; i >= 0; i--){
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding && b->m_level == level)
- RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);
+ if(b->bStreamBIGBuilding){
+ if(CRenderer::ShouldModelBeStreamed(b, pos))
+ RequestModel(b->GetModelIndex(), 0);
+ }else
+ RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);
}
RequestIslands(level);
- ms_hasLoadedLODs = false;
}
+//--MIAMI: done
+void
+CStreaming::InstanceBigBuildings(eLevelName level, const CVector &pos)
+{
+ int i, n;
+ CBuilding *b;
+
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
+ b = CPools::GetBuildingPool()->GetSlot(i);
+ if(b && b->bIsBIGBuilding && b->m_level == level &&
+ b->bStreamBIGBuilding && b->m_rwObject == nil)
+ if(CRenderer::ShouldModelBeStreamed(b, pos))
+ b->CreateRwObject();
+ }
+}
+
+//--MIAMI: done
+void
+CStreaming::InstanceLoadedModelsInSectorList(CPtrList &list)
+{
+ CPtrNode *node;
+ CEntity *e;
+ for(node = list.first; node; node = node->next) {
+ e = (CEntity *)node->item;
+ if(IsAreaVisible(e->m_area) && e->m_rwObject == nil)
+ e->CreateRwObject();
+ }
+}
+
+//--MIAMI: done
+void
+CStreaming::InstanceLoadedModels(const CVector &pos)
+{
+ int minX = CWorld::GetSectorIndexX(pos.x - 80.0f);
+ if(minX <= 0) minX = 0;
+
+ int minY = CWorld::GetSectorIndexY(pos.y - 80.0f);
+ if(minY <= 0) minY = 0;
+
+ int maxX = CWorld::GetSectorIndexX(pos.x + 80.0f);
+ if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
+
+ int maxY = CWorld::GetSectorIndexY(pos.y + 80.0f);
+ if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
+
+ int x, y;
+ for(y = minY; y <= maxY; y++){
+ for(x = minX; x <= maxX; x++){
+ CSector *sector = CWorld::GetSector(x, y);
+ InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_BUILDINGS]);
+ InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);
+ InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_OBJECTS]);
+ InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_DUMMIES]);
+ }
+ }
+}
+
+//--MIAMI: done
void
CStreaming::RequestIslands(eLevelName level)
{
switch(level){
- case LEVEL_INDUSTRIAL:
- RequestModel(islandLODcomInd, BIGBUILDINGFLAGS);
- RequestModel(islandLODsubInd, BIGBUILDINGFLAGS);
- break;
- case LEVEL_COMMERCIAL:
- RequestModel(islandLODindust, BIGBUILDINGFLAGS);
- RequestModel(islandLODsubCom, BIGBUILDINGFLAGS);
+ case LEVEL_MAINLAND:
+ if(islandLODbeach != -1)
+ RequestModel(islandLODbeach, BIGBUILDINGFLAGS);
break;
- case LEVEL_SUBURBAN:
- RequestModel(islandLODindust, BIGBUILDINGFLAGS);
- RequestModel(islandLODcomSub, BIGBUILDINGFLAGS);
+ case LEVEL_BEACH:
+ if(islandLODmainland != -1)
+ RequestModel(islandLODmainland, BIGBUILDINGFLAGS);
break;
default: break;
}
}
+//--MIAMI: TODO
void
CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flags)
{
@@ -793,24 +850,28 @@ CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flag
RequestModel(modelId, flags);
}
+//--MIAMI: done
void
CStreaming::RequestSpecialChar(int32 charId, const char *modelName, int32 flags)
{
RequestSpecialModel(charId + MI_SPECIAL01, modelName, flags);
}
+//--MIAMI: done
bool
CStreaming::HasSpecialCharLoaded(int32 id)
{
return HasModelLoaded(id + MI_SPECIAL01);
}
+//--MIAMI: done
void
CStreaming::SetMissionDoesntRequireSpecialChar(int32 id)
{
return SetMissionDoesntRequireModel(id + MI_SPECIAL01);
}
+//--MIAMI: done
void
CStreaming::DecrementRef(int32 id)
{
@@ -821,6 +882,7 @@ CStreaming::DecrementRef(int32 id)
}
}
+//--MIAMI: done
void
CStreaming::RemoveModel(int32 id)
{
@@ -832,8 +894,14 @@ CStreaming::RemoveModel(int32 id)
if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){
if(id < STREAM_OFFSET_TXD)
CModelInfo::GetModelInfo(id)->DeleteRwObject();
- else
+ else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+ else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)
+ CColStore::RemoveCol(id - STREAM_OFFSET_COL);
+ else if(id >= STREAM_OFFSET_ANIM){
+ assert(id < NUMSTREAMINFO);
+ CAnimManager::RemoveAnimBlock(id - STREAM_OFFSET_ANIM);
+ }
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
}
@@ -854,24 +922,30 @@ CStreaming::RemoveModel(int32 id)
if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){
if(id < STREAM_OFFSET_TXD)
RpClumpGtaCancelStream();
- else
+ else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+ else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)
+ CColStore::RemoveCol(id - STREAM_OFFSET_COL);
+ else if(id >= STREAM_OFFSET_ANIM){
+ assert(id < NUMSTREAMINFO);
+ CAnimManager::RemoveAnimBlock(id - STREAM_OFFSET_ANIM);
+ }
}
ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED;
}
+//--MIAMI: done
void
CStreaming::RemoveUnusedBuildings(eLevelName level)
{
- if(level != LEVEL_INDUSTRIAL)
- RemoveBuildings(LEVEL_INDUSTRIAL);
- if(level != LEVEL_COMMERCIAL)
- RemoveBuildings(LEVEL_COMMERCIAL);
- if(level != LEVEL_SUBURBAN)
- RemoveBuildings(LEVEL_SUBURBAN);
+ if(level != LEVEL_BEACH)
+ RemoveBuildings(LEVEL_BEACH);
+ if(level != LEVEL_MAINLAND)
+ RemoveBuildings(LEVEL_MAINLAND);
}
+//--MIAMI: done
void
CStreaming::RemoveBuildings(eLevelName level)
{
@@ -932,18 +1006,18 @@ CStreaming::RemoveBuildings(eLevelName level)
}
}
+//--MIAMI: done
void
CStreaming::RemoveUnusedBigBuildings(eLevelName level)
{
- if(level != LEVEL_INDUSTRIAL)
- RemoveBigBuildings(LEVEL_INDUSTRIAL);
- if(level != LEVEL_COMMERCIAL)
- RemoveBigBuildings(LEVEL_COMMERCIAL);
- if(level != LEVEL_SUBURBAN)
- RemoveBigBuildings(LEVEL_SUBURBAN);
+ if(level != LEVEL_BEACH)
+ RemoveBigBuildings(LEVEL_BEACH);
+ if(level != LEVEL_MAINLAND)
+ RemoveBigBuildings(LEVEL_MAINLAND);
RemoveIslandsNotUsed(level);
}
+//--MIAMI: done
void
DeleteIsland(CEntity *island)
{
@@ -957,35 +1031,33 @@ DeleteIsland(CEntity *island)
}
}
+//--MIAMI: done
void
CStreaming::RemoveIslandsNotUsed(eLevelName level)
{
+ int i;
+ if(pIslandLODmainlandEntity == nil)
+ for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){
+ CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
+ if(building == nil)
+ continue;
+ if(building->GetModelIndex() == islandLODmainland)
+ pIslandLODmainlandEntity = building;
+ if(building->GetModelIndex() == islandLODbeach)
+ pIslandLODbeachEntity = building;
+ }
+
switch(level){
- case LEVEL_INDUSTRIAL:
- DeleteIsland(pIslandLODindustEntity);
- DeleteIsland(pIslandLODcomSubEntity);
- DeleteIsland(pIslandLODsubComEntity);
- break;
- case LEVEL_COMMERCIAL:
- DeleteIsland(pIslandLODcomIndEntity);
- DeleteIsland(pIslandLODcomSubEntity);
- DeleteIsland(pIslandLODsubIndEntity);
- break;
- case LEVEL_SUBURBAN:
- DeleteIsland(pIslandLODsubIndEntity);
- DeleteIsland(pIslandLODsubComEntity);
- DeleteIsland(pIslandLODcomIndEntity);
+ case LEVEL_MAINLAND:
+ DeleteIsland(pIslandLODmainlandEntity);
break;
- default:
- DeleteIsland(pIslandLODindustEntity);
- DeleteIsland(pIslandLODcomIndEntity);
- DeleteIsland(pIslandLODcomSubEntity);
- DeleteIsland(pIslandLODsubIndEntity);
- DeleteIsland(pIslandLODsubComEntity);
+ case LEVEL_BEACH:
+ DeleteIsland(pIslandLODbeachEntity);
break;
}
}
+//--MIAMI: done
void
CStreaming::RemoveBigBuildings(eLevelName level)
{
@@ -1017,8 +1089,7 @@ CStreaming::RemoveLoadedVehicle(void)
if(ms_lastVehicleDeleted == MAXVEHICLESLOADED)
ms_lastVehicleDeleted = 0;
id = ms_vehiclesLoaded[ms_lastVehicleDeleted];
- if(id != -1 &&
- (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0 &&
+ if(id != -1 && CanRemoveModel(id) && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0 &&
ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED)
goto found;
}
@@ -1027,33 +1098,47 @@ found:
RemoveModel(ms_vehiclesLoaded[ms_lastVehicleDeleted]);
ms_numVehiclesLoaded--;
ms_vehiclesLoaded[ms_lastVehicleDeleted] = -1;
+ CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
+ if (pVehicleInfo->m_vehicleClass != -1)
+ CCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass);
return true;
}
+//--MIAMI: done
bool
-CStreaming::RemoveLeastUsedModel(void)
+CStreaming::RemoveLeastUsedModel(uint32 excludeMask)
{
CStreamingInfo *si;
int streamId;
for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){
+ if(si->m_flags & excludeMask)
+ continue;
streamId = si - ms_aInfoForModel;
if(streamId < STREAM_OFFSET_TXD){
if (CModelInfo::GetModelInfo(streamId)->GetNumRefs() == 0) {
RemoveModel(streamId);
return true;
}
- }else{
+ }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){
if(CTxdStore::GetNumRefs(streamId - STREAM_OFFSET_TXD) == 0 &&
!IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){
RemoveModel(streamId);
return true;
}
+ }else if(streamId >= STREAM_OFFSET_ANIM){
+ assert(streamId < NUMSTREAMINFO);
+ if(CAnimManager::GetNumRefsToAnimBlock(streamId - STREAM_OFFSET_ANIM) == 0 &&
+ !AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)){
+ RemoveModel(streamId);
+ return true;
+ }
}
}
- return ms_numVehiclesLoaded > 7 && RemoveLoadedVehicle();
+ return (ms_numVehiclesLoaded > 7 || CGame::currArea != AREA_MAIN_MAP && ms_numVehiclesLoaded > 4) && RemoveLoadedVehicle();
}
+//--MIAMI: done
void
CStreaming::RemoveAllUnusedModels(void)
{
@@ -1064,7 +1149,6 @@ CStreaming::RemoveAllUnusedModels(void)
for(i = NUM_DEFAULT_MODELS; i < MODELINFOSIZE; i++){
if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED &&
- ms_aInfoForModel[i].m_flags & STREAMFLAGS_DONT_REMOVE &&
CModelInfo::GetModelInfo(i)->GetNumRefs() == 0) {
RemoveModel(i);
ms_aInfoForModel[i].m_loadState = STREAMSTATE_NOTLOADED;
@@ -1072,30 +1156,14 @@ CStreaming::RemoveAllUnusedModels(void)
}
}
-bool
-CStreaming::RemoveReferencedTxds(int32 mem)
-{
- CStreamingInfo *si;
- int streamId;
-
- for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){
- streamId = si - ms_aInfoForModel;
- if(streamId >= STREAM_OFFSET_TXD &&
- CTxdStore::GetNumRefs(streamId-STREAM_OFFSET_TXD) == 0){
- RemoveModel(streamId);
- if(ms_memoryUsed < mem)
- return true;
- }
- }
- return false;
-}
-
+//--MIAMI: done
void
CStreaming::RemoveUnusedModelsInLoadedList(void)
{
// empty
}
+//--MIAMI: done
bool
CStreaming::IsTxdUsedByRequestedModels(int32 txdId)
{
@@ -1124,6 +1192,34 @@ CStreaming::IsTxdUsedByRequestedModels(int32 txdId)
return false;
}
+bool
+CStreaming::AreAnimsUsedByRequestedModels(int32 animId)
+{
+ CStreamingInfo *si;
+ int streamId;
+ int i;
+
+ for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = si->m_next){
+ streamId = si - ms_aInfoForModel;
+ if(streamId < STREAM_OFFSET_TXD &&
+ CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId)
+ return true;
+ }
+
+ for(i = 0; i < 4; i++){
+ streamId = ms_channel[0].streamIds[i];
+ if(streamId != -1 && streamId < STREAM_OFFSET_TXD &&
+ CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId)
+ return true;
+ streamId = ms_channel[1].streamIds[i];
+ if(streamId != -1 && streamId < STREAM_OFFSET_TXD &&
+ CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId)
+ return true;
+ }
+
+ return false;
+}
+
int32
CStreaming::GetAvailableVehicleSlot(void)
{
@@ -1155,8 +1251,8 @@ CStreaming::AddToLoadedVehiclesList(int32 modelId)
// find vehicle we can remove
for(i = 0; i < MAXVEHICLESLOADED; i++){
id = ms_vehiclesLoaded[ms_lastVehicleDeleted];
- if(id != -1 &&
- (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0)
+ if(id != -1 && CanRemoveModel(id) &&
+ CModelInfo::GetModelInfo(id)->GetNumRefs() == 0)
goto found;
ms_lastVehicleDeleted++;
if(ms_lastVehicleDeleted == MAXVEHICLESLOADED)
@@ -1172,13 +1268,21 @@ found:
ms_lastVehicleDeleted = id;
// this is more that we wanted actually
ms_numVehiclesLoaded++;
- }else
+ }
+ else{
RemoveModel(id);
+ CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
+ if (pVehicleInfo->m_vehicleClass != -1)
+ CCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass);
+ }
}
ms_vehiclesLoaded[ms_lastVehicleDeleted++] = modelId;
if(ms_lastVehicleDeleted == MAXVEHICLESLOADED)
ms_lastVehicleDeleted = 0;
+ CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(modelId);
+ if (pVehicleInfo->m_vehicleClass != -1)
+ CCarCtrl::AddToLoadedVehicleArray(modelId, pVehicleInfo->m_vehicleClass, pVehicleInfo->m_frequency);
return true;
}
@@ -1190,41 +1294,6 @@ CStreaming::IsObjectInCdImage(int32 id)
}
void
-CStreaming::HaveAllBigBuildingsLoaded(eLevelName level)
-{
- int i, n;
- CEntity *e;
-
- if(ms_hasLoadedLODs)
- return;
-
- if(level == LEVEL_INDUSTRIAL){
- if(ms_aInfoForModel[islandLODcomInd].m_loadState != STREAMSTATE_LOADED ||
- ms_aInfoForModel[islandLODsubInd].m_loadState != STREAMSTATE_LOADED)
- return;
- }else if(level == LEVEL_COMMERCIAL){
- if(ms_aInfoForModel[islandLODindust].m_loadState != STREAMSTATE_LOADED ||
- ms_aInfoForModel[islandLODsubCom].m_loadState != STREAMSTATE_LOADED)
- return;
- }else if(level == LEVEL_SUBURBAN){
- if(ms_aInfoForModel[islandLODindust].m_loadState != STREAMSTATE_LOADED ||
- ms_aInfoForModel[islandLODcomSub].m_loadState != STREAMSTATE_LOADED)
- return;
- }
-
- n = CPools::GetBuildingPool()->GetSize()-1;
- for(i = n; i >= 0; i--){
- e = CPools::GetBuildingPool()->GetSlot(i);
- if(e && e->bIsBIGBuilding && e->m_level == level &&
- ms_aInfoForModel[e->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)
- return;
- }
-
- RemoveUnusedBigBuildings(level);
- ms_hasLoadedLODs = true;
-}
-
-void
CStreaming::SetModelIsDeletable(int32 id)
{
ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_DONT_REMOVE;
@@ -1243,6 +1312,7 @@ CStreaming::SetModelTxdIsDeletable(int32 id)
SetModelIsDeletable(CModelInfo::GetModelInfo(id)->GetTxdSlot() + STREAM_OFFSET_TXD);
}
+//--MIAMI: done
void
CStreaming::SetMissionDoesntRequireModel(int32 id)
{
@@ -1265,6 +1335,13 @@ CStreaming::LoadInitialPeds(void)
}
void
+CStreaming::LoadInitialWeapons(void)
+{
+ CStreaming::RequestModel(MI_NIGHTSTICK, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::RequestModel(MI_MISSILE, STREAMFLAGS_DONT_REMOVE);
+}
+
+void
CStreaming::LoadInitialVehicles(void)
{
int id;
@@ -1327,28 +1404,72 @@ CStreaming::StreamVehiclesAndPeds(void)
else
SetModelIsDeletable(MI_CHOPPER);
+ if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired()) {
+ SetModelIsDeletable(MI_VICE1);
+ SetModelIsDeletable(MI_VICE2);
+ SetModelIsDeletable(MI_VICE3);
+ SetModelIsDeletable(MI_VICE4);
+ SetModelIsDeletable(MI_VICE5);
+ SetModelIsDeletable(MI_VICE6);
+ SetModelIsDeletable(MI_VICE7);
+ SetModelIsDeletable(MI_VICE8);
+ switch (CCarCtrl::MiamiViceCycle) {
+ case 0:
+ RequestModel(MI_VICE1, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_VICE2, STREAMFLAGS_DONT_REMOVE);
+ break;
+ case 1:
+ RequestModel(MI_VICE3, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_VICE4, STREAMFLAGS_DONT_REMOVE);
+ break;
+ case 2:
+ RequestModel(MI_VICE5, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_VICE6, STREAMFLAGS_DONT_REMOVE);
+ break;
+ case 3:
+ RequestModel(MI_VICE7, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_VICE8, STREAMFLAGS_DONT_REMOVE);
+ break;
+ }
+ RequestModel(MI_VICECHEE, STREAMFLAGS_DONT_REMOVE);
+ }
+ else {
+ SetModelIsDeletable(MI_VICECHEE);
+ SetModelIsDeletable(MI_VICE1);
+ SetModelIsDeletable(MI_VICE2);
+ SetModelIsDeletable(MI_VICE3);
+ SetModelIsDeletable(MI_VICE4);
+ SetModelIsDeletable(MI_VICE5);
+ SetModelIsDeletable(MI_VICE6);
+ SetModelIsDeletable(MI_VICE7);
+ SetModelIsDeletable(MI_VICE8);
+ }
+
if(timeBeforeNextLoad >= 0)
timeBeforeNextLoad--;
else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){
- for(i = 1; i <= 10; i++){
- model = CCarCtrl::ChooseCarModel(modelQualityClass);
- modelQualityClass++;
- if(modelQualityClass >= CCarCtrl::TOTAL_CUSTOM_CLASSES)
- modelQualityClass = 0;
-
- // check if we want to load this model
- if(ms_aInfoForModel[model].m_loadState == STREAMSTATE_NOTLOADED &&
- ((CVehicleModelInfo*)CModelInfo::GetModelInfo(model))->m_level & (1 << (CGame::currLevel-1)))
- break;
+ CZoneInfo zone;
+ CTheZones::GetZoneInfoForTimeOfDay(&FindPlayerCoors(), &zone);
+ int32 maxReq = -1;
+ int32 mostRequestedRating = 0;
+ for(i = 0; i < CCarCtrl::TOTAL_CUSTOM_CLASSES; i++){
+ if(CCarCtrl::NumRequestsOfCarRating[i] > maxReq &&
+ ((i == 0 && zone.carThreshold[0] != 0) ||
+ (i != 0 && zone.carThreshold[i] != zone.carThreshold[i-1]))) {
+ maxReq = CCarCtrl::NumRequestsOfCarRating[i];
+ mostRequestedRating = i;
+ }
}
-
- if(i <= 10){
+ model = CCarCtrl::ChooseCarModelToLoad(mostRequestedRating);
+ if(!HasModelLoaded(model)){
RequestModel(model, STREAMFLAGS_DEPENDENCY);
- timeBeforeNextLoad = 500;
+ timeBeforeNextLoad = 350;
}
+ CCarCtrl::NumRequestsOfCarRating[mostRequestedRating] = 0;
}
}
+//--MIAMI: TODO
void
CStreaming::StreamZoneModels(const CVector &pos)
{
@@ -1374,58 +1495,54 @@ CStreaming::StreamZoneModels(const CVector &pos)
for(i = 0; i < NUMMODELSPERPEDGROUP; i++){
if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1)
break;
- RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i], STREAMFLAGS_DONT_REMOVE);
+ RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i], STREAMFLAGS_DEPENDENCY);
}
}
RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE);
+ //RequestModel(MI_HMOCA, STREAMFLAGS_DONT_REMOVE);
gangsToLoad = 0;
gangCarsToLoad = 0;
- if(info.gangDensity[0] != 0) gangsToLoad |= 1<<0;
- if(info.gangDensity[1] != 0) gangsToLoad |= 1<<1;
- if(info.gangDensity[2] != 0) gangsToLoad |= 1<<2;
- if(info.gangDensity[3] != 0) gangsToLoad |= 1<<3;
- if(info.gangDensity[4] != 0) gangsToLoad |= 1<<4;
- if(info.gangDensity[5] != 0) gangsToLoad |= 1<<5;
- if(info.gangDensity[6] != 0) gangsToLoad |= 1<<6;
- if(info.gangDensity[7] != 0) gangsToLoad |= 1<<7;
- if(info.gangDensity[8] != 0) gangsToLoad |= 1<<8;
- if(info.gangThreshold[0] != info.copDensity) gangCarsToLoad |= 1<<0;
- if(info.gangThreshold[1] != info.gangThreshold[0]) gangCarsToLoad |= 1<<1;
- if(info.gangThreshold[2] != info.gangThreshold[1]) gangCarsToLoad |= 1<<2;
- if(info.gangThreshold[3] != info.gangThreshold[2]) gangCarsToLoad |= 1<<3;
- if(info.gangThreshold[4] != info.gangThreshold[3]) gangCarsToLoad |= 1<<4;
- if(info.gangThreshold[5] != info.gangThreshold[4]) gangCarsToLoad |= 1<<5;
- if(info.gangThreshold[6] != info.gangThreshold[5]) gangCarsToLoad |= 1<<6;
- if(info.gangThreshold[7] != info.gangThreshold[6]) gangCarsToLoad |= 1<<7;
- if(info.gangThreshold[8] != info.gangThreshold[7]) gangCarsToLoad |= 1<<8;
+ if(info.gangPedThreshold[0] != info.copPedThreshold)
+ gangsToLoad = 1;
+ for(i = 1; i < NUM_GANGS; i++)
+ if(info.gangPedThreshold[i] != info.gangPedThreshold[i-1])
+ gangsToLoad |= 1<<i;
+ if(info.gangThreshold[0] != info.copThreshold)
+ gangCarsToLoad = 1;
+ for(i = 1; i < NUM_GANGS; i++)
+ if(info.gangThreshold[i] != info.gangThreshold[i-1])
+ gangCarsToLoad |= 1<<i;
if(gangsToLoad == ms_loadedGangs && gangCarsToLoad == ms_loadedGangCars)
return;
- // This makes things simpler than the game does it
gangsToLoad |= gangCarsToLoad;
for(i = 0; i < NUM_GANGS; i++){
bit = 1<<i;
if(gangsToLoad & bit && (ms_loadedGangs & bit) == 0){
- RequestModel(MI_GANG01 + i*2, STREAMFLAGS_DONT_REMOVE);
- RequestModel(MI_GANG01 + i*2 + 1, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(CGangs::GetGangPedModel1(i), STREAMFLAGS_DEPENDENCY);
+ RequestModel(CGangs::GetGangPedModel2(i), STREAMFLAGS_DEPENDENCY);
ms_loadedGangs |= bit;
}else if((gangsToLoad & bit) == 0 && ms_loadedGangs & bit){
- SetModelIsDeletable(MI_GANG01 + i*2);
- SetModelIsDeletable(MI_GANG01 + i*2 + 1);
- SetModelTxdIsDeletable(MI_GANG01 + i*2);
- SetModelTxdIsDeletable(MI_GANG01 + i*2 + 1);
+ SetModelIsDeletable(CGangs::GetGangPedModel1(i));
+ SetModelIsDeletable(CGangs::GetGangPedModel2(i));
+ SetModelTxdIsDeletable(CGangs::GetGangPedModel1(i));
+ SetModelTxdIsDeletable(CGangs::GetGangPedModel2(i));
ms_loadedGangs &= ~bit;
}
- if(gangCarsToLoad & bit && (ms_loadedGangCars & bit) == 0){
- RequestModel(CGangs::GetGangInfo(i)->m_nVehicleMI, STREAMFLAGS_DONT_REMOVE);
+ // TODO(MIAMI): check this
+ if(CGangs::GetGangVehicleModel(i) < 0)
+ continue;
+
+ if((gangCarsToLoad & bit) && (ms_loadedGangCars & bit) == 0){
+ RequestModel(CGangs::GetGangVehicleModel(i), STREAMFLAGS_DEPENDENCY);
}else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){
- SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI);
- SetModelTxdIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI);
+ SetModelIsDeletable(CGangs::GetGangVehicleModel(i));
+ SetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i));
}
}
ms_loadedGangCars = gangCarsToLoad;
@@ -1437,7 +1554,7 @@ CStreaming::RemoveCurrentZonesModels(void)
int i;
if(ms_currentPedGrp != -1)
- for(i = 0; i < 8; i++){
+ for(i = 0; i < NUMMODELSPERPEDGROUP; i++){
if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1)
break;
if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != MI_MALE01)
@@ -1445,10 +1562,10 @@ CStreaming::RemoveCurrentZonesModels(void)
}
for(i = 0; i < NUM_GANGS; i++){
- SetModelIsDeletable(MI_GANG01 + i*2);
- SetModelIsDeletable(MI_GANG01 + i*2 + 1);
- if(CGangs::GetGangInfo(i)->m_nVehicleMI != -1)
- SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI);
+ SetModelIsDeletable(CGangs::GetGangPedModel1(i));
+ SetModelIsDeletable(CGangs::GetGangPedModel2(i));
+ if(CGangs::GetGangVehicleModel(i) != -1)
+ SetModelIsDeletable(CGangs::GetGangVehicleModel(i));
}
ms_currentPedGrp = -1;
@@ -1456,6 +1573,42 @@ CStreaming::RemoveCurrentZonesModels(void)
ms_loadedGangCars = 0;
}
+void
+CStreaming::LoadBigBuildingsWhenNeeded(void)
+{
+ // Very much like CCollision::Update and CCollision::LoadCollisionWhenINeedIt
+ if(CCutsceneMgr::IsCutsceneProcessing())
+ return;
+
+ if(CTheZones::m_CurrLevel == LEVEL_NONE ||
+ CTheZones::m_CurrLevel == CGame::currLevel)
+ return;
+
+ CTimer::Suspend();
+ CGame::currLevel = CTheZones::m_CurrLevel;
+ DMAudio.SetEffectsFadeVol(0);
+ CPad::StopPadsShaking();
+ CCollision::LoadCollisionScreen(CGame::currLevel);
+ DMAudio.Service();
+
+ // CPopulation::DealWithZoneChange is unused in VC
+ RemoveUnusedBigBuildings(CGame::currLevel);
+ RemoveUnusedBuildings(CGame::currLevel);
+ RemoveUnusedModelsInLoadedList();
+ CGame::TidyUpMemory(true, true);
+
+ CReplay::EmptyReplayBuffer();
+ if(CGame::currLevel != LEVEL_NONE)
+ LoadSplash(GetLevelSplashScreen(CGame::currLevel));
+
+ CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition());
+ CStreaming::LoadAllRequestedModels(true);
+
+ CGame::TidyUpMemory(true, true);
+ CTimer::Resume();
+ DMAudio.SetEffectsFadeVol(127);
+}
+
// Find starting offset of the cdimage we next want to read
// Not useful at all on PC...
@@ -1502,6 +1655,7 @@ ModelNotLoaded(int32 modelId)
}
inline bool TxdNotLoaded(int32 txdId) { return ModelNotLoaded(txdId + STREAM_OFFSET_TXD); }
+inline bool AnimNotLoaded(int32 animId) { return animId != -1 && ModelNotLoaded(animId + STREAM_OFFSET_ANIM); }
// Find stream id of next requested file in cdimage
int32
@@ -1526,14 +1680,20 @@ CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority)
if(priority && ms_numPriorityRequests != 0 && !si->IsPriority())
continue;
- // request Txd if necessary
+ // request Txds or anims if necessary
if(streamId < STREAM_OFFSET_TXD){
int txdId = CModelInfo::GetModelInfo(streamId)->GetTxdSlot();
if(TxdNotLoaded(txdId)){
ReRequestTxd(txdId);
continue;
}
- }
+ int animId = CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex();
+ if(AnimNotLoaded(animId)){
+ ReRequestAnim(animId);
+ continue;
+ }
+ }else if(streamId >= STREAM_OFFSET_ANIM && CCutsceneMgr::IsCutsceneProcessing())
+ continue;
if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){
if(posn < posnFirst){
@@ -1576,6 +1736,7 @@ CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority)
* TODO: two-part files
*/
+//--MIAMI: done
// Make channel read from disc
void
CStreaming::RequestModelStream(int32 ch)
@@ -1590,13 +1751,18 @@ CStreaming::RequestModelStream(int32 ch)
imgOffset = GetCdImageOffset(lastPosn);
streamId = GetNextFileOnCd(lastPosn - imgOffset, true);
- if(streamId == -1)
- return;
-
- // remove Txds that aren't requested anymore
- while(streamId >= STREAM_OFFSET_TXD){
- if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY ||
- IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD))
+ // remove Txds and Anims that aren't requested anymore
+ while(streamId != -1){
+ if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY)
+ break;
+ if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){
+ if(IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD))
+ break;
+ }else if(streamId >= STREAM_OFFSET_ANIM){
+ assert(streamId < NUMSTREAMINFO);
+ if(AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM))
+ break;
+ }else
break;
RemoveModel(streamId);
// so try next file
@@ -1633,7 +1799,8 @@ CStreaming::RequestModelStream(int32 ch)
if(streamId < STREAM_OFFSET_TXD){
if (havePed && CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_PED ||
haveBigFile && CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_VEHICLE ||
- TxdNotLoaded(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()))
+ TxdNotLoaded(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()) ||
+ AnimNotLoaded(CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex()))
break;
}else{
if(haveBigFile && size > 200)
@@ -1680,6 +1847,7 @@ CStreaming::RequestModelStream(int32 ch)
ms_channel[ch].numTries = 0;
}
+//--MIAMI: done
// Load data previously read from disc
bool
CStreaming::ProcessLoadingChannel(int32 ch)
@@ -1714,10 +1882,10 @@ CStreaming::ProcessLoadingChannel(int32 ch)
if(id < STREAM_OFFSET_TXD && CModelInfo::GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&
ms_numVehiclesLoaded >= desiredNumVehiclesLoaded &&
!RemoveLoadedVehicle() &&
- ((ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 || GetAvailableVehicleSlot() == -1)){
+ (CanRemoveModel(id) || GetAvailableVehicleSlot() == -1)){
// can't load vehicle
RemoveModel(id);
- if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE)
+ if(!CanRemoveModel(id))
ReRequestModel(id);
else if(CTxdStore::GetNumRefs(CModelInfo::GetModelInfo(id)->GetTxdSlot()) == 0)
RemoveTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot());
@@ -1749,6 +1917,7 @@ CStreaming::ProcessLoadingChannel(int32 ch)
return true;
}
+//--MIAMI: done
void
CStreaming::RetryLoadFile(int32 ch)
{
@@ -1785,6 +1954,7 @@ CStreaming::RetryLoadFile(int32 ch)
}
}
+//--MIAMI: done
void
CStreaming::LoadRequestedModels(void)
{
@@ -1809,6 +1979,7 @@ CStreaming::LoadRequestedModels(void)
}
}
+//--MIAMI: done
void
CStreaming::LoadAllRequestedModels(bool priority)
{
@@ -1862,6 +2033,7 @@ CStreaming::LoadAllRequestedModels(bool priority)
bInsideLoadAll = false;
}
+//--MIAMI: done
void
CStreaming::FlushChannels(void)
{
@@ -1883,6 +2055,7 @@ CStreaming::FlushChannels(void)
ProcessLoadingChannel(1);
}
+//--MIAMI: done
void
CStreaming::FlushRequestList(void)
{
@@ -1991,8 +2164,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float
if(xmin < pos.x && pos.x < xmax &&
ymin < pos.y && pos.y < ymax &&
(CVector2D(x, y) - pos).MagnitudeSqr() < lodDistSq)
- if(CRenderer::IsEntityCullZoneVisible(e))
- RequestModel(e->GetModelIndex(), 0);
+ RequestModel(e->GetModelIndex(), 0);
}
}
}
@@ -2015,8 +2187,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list)
(!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){
CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());
if (mi->GetModelType() != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))
- if(CRenderer::IsEntityCullZoneVisible(e))
- RequestModel(e->GetModelIndex(), 0);
+ RequestModel(e->GetModelIndex(), 0);
}
}
}
@@ -2254,9 +2425,6 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
}
}
- if(RemoveReferencedTxds(mem))
- return;
-
// As last resort, delete objects from the last step more aggressively
for(y = ymin; y <= ymax; y++){
for(x = xmax; x != xmin; x -= inc){
@@ -2318,9 +2486,6 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
}
}
- if(RemoveReferencedTxds(mem))
- return;
-
// As last resort, delete objects from the last step more aggressively
for(x = xmin; x <= xmax; x++){
for(y = ymax; y != ymin; y -= inc){
@@ -2419,12 +2584,13 @@ CStreaming::MakeSpaceFor(int32 size)
// but it's not nice....
while((uint32)ms_memoryUsed >= ms_memoryAvailable - size)
- if(!RemoveLeastUsedModel()){
+ if(!RemoveLeastUsedModel(STREAMFLAGS_20)){
DeleteRwObjectsBehindCamera(ms_memoryAvailable - size);
return;
}
}
+//--MIAMI: done
void
CStreaming::LoadScene(const CVector &pos)
{
@@ -2439,16 +2605,44 @@ CStreaming::LoadScene(const CVector &pos)
RemoveModel(si - ms_aInfoForModel);
}
CRenderer::m_loadingPriority = false;
- CCullZones::ForceCullZoneCoors(pos);
DeleteAllRwObjects();
+ if(level == LEVEL_NONE)
+ level = CGame::currLevel;
+ CGame::currLevel = level;
+ RemoveUnusedBigBuildings(level);
+ RequestBigBuildings(level, pos);
+ RequestBigBuildings(LEVEL_NONE, pos);
+ RemoveIslandsNotUsed(level);
+ LoadAllRequestedModels(false);
+ InstanceBigBuildings(level, pos);
+ InstanceBigBuildings(LEVEL_NONE, pos);
AddModelsToRequestList(pos);
CRadar::StreamRadarSections(pos);
- RemoveUnusedBigBuildings(level);
- RequestBigBuildings(level);
+
+ if (!CGame::IsInInterior()) {
+ for (int i = 0; i < 5; i++) {
+ CZoneInfo zone;
+ CTheZones::GetZoneInfoForTimeOfDay(&pos, &zone);
+ int32 model = CCarCtrl::ChooseCarModelToLoad(CCarCtrl::ChooseCarRating(&zone));
+ CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY);
+ }
+ }
LoadAllRequestedModels(false);
+ InstanceLoadedModels(pos);
+
+ for(int i = 0; i < NUMSTREAMINFO; i++)
+ ms_aInfoForModel[i].m_flags &= ~STREAMFLAGS_20;
debug("End load scene\n");
}
+//--MIAMI: done
+void
+CStreaming::LoadSceneCollision(const CVector &pos)
+{
+ CColStore::LoadCollision(pos);
+ CStreaming::LoadAllRequestedModels(false);
+}
+
void
CStreaming::MemoryCardSave(uint8 *buf, uint32 *size)
{
diff --git a/src/core/Streaming.h b/src/core/Streaming.h
index 84434769..8a92266f 100644
--- a/src/core/Streaming.h
+++ b/src/core/Streaming.h
@@ -4,7 +4,9 @@
enum {
STREAM_OFFSET_TXD = MODELINFOSIZE,
- NUMSTREAMINFO = STREAM_OFFSET_TXD+TXDSTORESIZE
+ STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE,
+ STREAM_OFFSET_ANIM = STREAM_OFFSET_COL+COLSTORESIZE,
+ NUMSTREAMINFO = STREAM_OFFSET_ANIM+NUMANIMBLOCKS
};
enum StreamFlags
@@ -14,6 +16,7 @@ enum StreamFlags
STREAMFLAGS_DEPENDENCY = 0x04, // Is this right?
STREAMFLAGS_PRIORITY = 0x08,
STREAMFLAGS_NOFADE = 0x10,
+ STREAMFLAGS_20 = 0x20, // TODO(MIAMI): what's this
STREAMFLAGS_CANT_REMOVE = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED,
STREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY,
@@ -92,9 +95,9 @@ public:
static int32 ms_numVehiclesLoaded;
static int32 ms_vehiclesLoaded[MAXVEHICLESLOADED];
static int32 ms_lastVehicleDeleted;
+ static bool ms_bIsPedFromPedGroupLoaded[NUMMODELSPERPEDGROUP];
static CDirectory *ms_pExtraObjectsDir;
static int32 ms_numPriorityRequests;
- static bool ms_hasLoadedLODs;
static int32 ms_currentPedGrp;
static int32 ms_lastCullZone;
static uint16 ms_loadedGangs;
@@ -115,14 +118,25 @@ public:
static bool FinishLoadingLargeFile(int8 *buf, int32 streamId);
static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); }
+ static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); }
+ static bool HasAnimLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_ANIM); }
static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; }
static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); }
+ static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); }
+ static bool CanRemoveAnim(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_ANIM); }
static void RequestModel(int32 model, int32 flags);
static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }
static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }
static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }
- static void RequestSubway(void);
+ static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); }
+ static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); }
+ static void RequestAnim(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_ANIM, flags); }
+ static void ReRequestAnim(int32 col) { ReRequestModel(col + STREAM_OFFSET_ANIM); }
static void RequestBigBuildings(eLevelName level);
+ static void RequestBigBuildings(eLevelName level, const CVector &pos);
+ static void InstanceBigBuildings(eLevelName level, const CVector &pos);
+ static void InstanceLoadedModelsInSectorList(CPtrList &list);
+ static void InstanceLoadedModels(const CVector &pos);
static void RequestIslands(eLevelName level);
static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags);
static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags);
@@ -131,29 +145,32 @@ public:
static void DecrementRef(int32 id);
static void RemoveModel(int32 id);
static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }
+ static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); }
+ static void RemoveAnim(int32 id) { RemoveModel(id + STREAM_OFFSET_ANIM); }
static void RemoveUnusedBuildings(eLevelName level);
static void RemoveBuildings(eLevelName level);
static void RemoveUnusedBigBuildings(eLevelName level);
static void RemoveIslandsNotUsed(eLevelName level);
static void RemoveBigBuildings(eLevelName level);
static bool RemoveLoadedVehicle(void);
- static bool RemoveLeastUsedModel(void);
+ static bool RemoveLeastUsedModel(uint32 excludeMask);
static void RemoveAllUnusedModels(void);
static void RemoveUnusedModelsInLoadedList(void);
- static bool RemoveReferencedTxds(int32 mem);
static int32 GetAvailableVehicleSlot(void);
static bool IsTxdUsedByRequestedModels(int32 txdId);
+ static bool AreAnimsUsedByRequestedModels(int32 animId);
static bool AddToLoadedVehiclesList(int32 modelId);
static bool IsObjectInCdImage(int32 id);
- static void HaveAllBigBuildingsLoaded(eLevelName level);
static void SetModelIsDeletable(int32 id);
static void SetModelTxdIsDeletable(int32 id);
static void SetMissionDoesntRequireModel(int32 id);
static void LoadInitialPeds(void);
+ static void LoadInitialWeapons(void);
static void LoadInitialVehicles(void);
static void StreamVehiclesAndPeds(void);
static void StreamZoneModels(const CVector &pos);
static void RemoveCurrentZonesModels(void);
+ static void LoadBigBuildingsWhenNeeded(void);
static int32 GetCdImageOffset(int32 lastPosn);
static int32 GetNextFileOnCd(int32 position, bool priority);
@@ -183,6 +200,7 @@ public:
static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem);
static void LoadScene(const CVector &pos);
+ static void LoadSceneCollision(const CVector &pos);
static void MemoryCardSave(uint8 *buffer, uint32 *length);
static void MemoryCardLoad(uint8 *buffer, uint32 length);
diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp
index 79d6252b..f20923f2 100644
--- a/src/core/TempColModels.cpp
+++ b/src/core/TempColModels.cpp
@@ -16,6 +16,7 @@ CColModel CTempColModels::ms_colModelPedGroundHit;
CColModel CTempColModels::ms_colModelBoot1;
CColModel CTempColModels::ms_colModelDoor1;
CColModel CTempColModels::ms_colModelBonnet1;
+CColModel CTempColModels::ms_colModelWeapon;
CColSphere s_aPedSpheres[3];
@@ -41,13 +42,13 @@ CTempColModels::Initialise(void)
int i;
- ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0);
+ ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));
ms_colModelBBox.level = LEVEL_NONE;
for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) {
- ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0);
+ ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));
ms_colModelCutObj[i].level = LEVEL_NONE;
}
@@ -69,8 +70,8 @@ CTempColModels::Initialise(void)
s_aPedSpheres[i].piece = 0;
}
- ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f), SURFACE_DEFAULT, 0);
+ ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f));
SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres);
// Ped 2 Spheres
@@ -88,8 +89,8 @@ CTempColModels::Initialise(void)
s_aPed2Spheres[i].piece = 0;
}
- ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f), SURFACE_DEFAULT, 0);
+ ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f));
SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres);
@@ -114,8 +115,8 @@ CTempColModels::Initialise(void)
s_aPedGSpheres[2].piece = 0;
s_aPedGSpheres[3].piece = 6;
- ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f), SURFACE_DEFAULT, 0);
+ ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f));
SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres);
@@ -134,8 +135,8 @@ CTempColModels::Initialise(void)
s_aDoorSpheres[i].piece = 0;
}
- ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f), SURFACE_DEFAULT, 0);
+ ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f));
+ ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f));
SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres);
@@ -154,8 +155,8 @@ CTempColModels::Initialise(void)
s_aBumperSpheres[i].piece = 0;
}
- ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, -0.2f), SURFACE_DEFAULT, 0);
+ ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f));
+ ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, -0.2f));
SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres);
@@ -174,8 +175,8 @@ CTempColModels::Initialise(void)
s_aPanelSpheres[i].piece = 0;
}
- ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f), SURFACE_DEFAULT, 0);
+ ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f));
SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres);
@@ -194,8 +195,8 @@ CTempColModels::Initialise(void)
s_aBonnetSpheres[i].piece = 0;
}
- ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f), SURFACE_DEFAULT, 0);
+ ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f));
+ ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f));
SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres);
@@ -214,8 +215,8 @@ CTempColModels::Initialise(void)
s_aBootSpheres[i].piece = 0;
}
- ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f), SURFACE_DEFAULT, 0);
+ ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f));
+ ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f));
SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres);
@@ -236,8 +237,8 @@ CTempColModels::Initialise(void)
s_aWheelSpheres[i].piece = 0;
}
- ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f), SURFACE_DEFAULT, 0);
+ ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f));
SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres);
@@ -258,8 +259,8 @@ CTempColModels::Initialise(void)
s_aBodyPartSpheres1[i].piece = 0;
}
- ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f), SURFACE_DEFAULT, 0);
+ ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f));
+ ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f));
SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1);
@@ -280,10 +281,14 @@ CTempColModels::Initialise(void)
s_aBodyPartSpheres2[i].piece = 0;
}
- ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f), SURFACE_DEFAULT, 0);
+ ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f));
+ ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f));
SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2);
+
+ ms_colModelWeapon.boundingSphere.Set(0.25f, CVector(0.0f, 0.0f, 0.0f));
+ ms_colModelWeapon.boundingBox.Set(CVector(-0.25f, -0.25, -0.25f), CVector(0.25f, 0.25, 0.25f));
+
#undef SET_COLMODEL_SPHERES
}
diff --git a/src/core/TempColModels.h b/src/core/TempColModels.h
index 3e1dd5e1..0c936d6f 100644
--- a/src/core/TempColModels.h
+++ b/src/core/TempColModels.h
@@ -18,6 +18,7 @@ public:
static CColModel ms_colModelBoot1;
static CColModel ms_colModelDoor1;
static CColModel ms_colModelBonnet1;
+ static CColModel ms_colModelWeapon;
static void Initialise(void);
};
diff --git a/src/core/User.cpp b/src/core/User.cpp
index f906ae44..716d6393 100644
--- a/src/core/User.cpp
+++ b/src/core/User.cpp
@@ -32,8 +32,8 @@ void
CPlaceName::Process()
{
CVector pos = CWorld::Players[CWorld::PlayerInFocus].GetPos();
- CZone *navigZone = CTheZones::FindSmallestZonePositionType(&pos, ZONE_NAVIG);
- CZone *defaultZone = CTheZones::FindSmallestZonePositionType(&pos, ZONE_DEFAULT);
+ CZone *navigZone = CTheZones::FindSmallestNavigationZoneForPosition(&pos, false, true);
+ CZone *defaultZone = CTheZones::FindSmallestNavigationZoneForPosition(&pos, true, false);
if (navigZone == nil) m_pZone = nil;
if (defaultZone == nil) m_pZone2 = nil;
diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp
index 7508c9f4..d2623431 100644
--- a/src/core/Wanted.cpp
+++ b/src/core/Wanted.cpp
@@ -40,6 +40,12 @@ CWanted::Initialise()
}
bool
+CWanted::AreMiamiViceRequired()
+{
+ return m_nWantedLevel >= 3;
+}
+
+bool
CWanted::AreSwatRequired()
{
return m_nWantedLevel == 4 || m_bSwatRequired;
@@ -456,3 +462,10 @@ CWanted::UpdateCrimesQ(void)
}
}
}
+
+void
+CWanted::Suspend(void)
+{
+ // TODO(MIAMI)!
+ Reset(); // <- temporary
+}
diff --git a/src/core/Wanted.h b/src/core/Wanted.h
index de36c442..ee72aa47 100644
--- a/src/core/Wanted.h
+++ b/src/core/Wanted.h
@@ -31,6 +31,7 @@ public:
public:
void Initialise();
+ bool AreMiamiViceRequired();
bool AreSwatRequired();
bool AreFbiRequired();
bool AreArmyRequired();
@@ -48,6 +49,8 @@ public:
void UpdateCrimesQ();
void Update();
+ void Suspend();
+
bool IsIgnored(void) { return m_bIgnoredByCops || m_bIgnoredByEveryone; }
static int32 WorkOutPolicePresence(CVector posn, float radius);
diff --git a/src/core/World.cpp b/src/core/World.cpp
index edcfd865..16e5e80d 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -339,26 +339,10 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
if(e->IsPed()) {
if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) {
-#ifdef PED_SKIN
- if(IsClumpSkinned(e->GetClump()))
- colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump());
- else
-#endif
- if(((CPed *)e)->UseGroundColModel())
- colmodel = &CTempColModels::ms_colModelPedGroundHit;
- else
-#ifdef ANIMATE_PED_COL_MODEL
- colmodel = CPedModelInfo::AnimatePedColModel(
- ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))
- ->GetHitColModel(),
- RpClumpGetFrame(e->GetClump()));
-#else
- colmodel =
- ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))
- ->GetHitColModel();
-#endif
+ colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump());
} else
colmodel = nil;
+
} else if(e->bUsesCollision)
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
@@ -382,7 +366,11 @@ CWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, C
{
AdvanceCurrentScanCode();
CVector point2(point1.x, point1.y, z2);
- return ProcessVerticalLineSector(*GetSector(GetSectorIndexX(point1.x), GetSectorIndexY(point1.y)),
+ int secX = GetSectorIndexX(point1.x);
+ int secY = GetSectorIndexY(point1.y);
+ secX = clamp(secX, 0, NUMSECTORS_X-1);
+ secY = clamp(secY, 0, NUMSECTORS_Y-1);
+ return ProcessVerticalLineSector(*GetSector(secX, secY),
CColLine(point1, point2), point, entity, checkBuildings, checkVehicles,
checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly);
}
@@ -920,6 +908,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
bool ignoreSomeObjects)
{
static CColModel sphereCol;
+ CColSphere sphere;
sphereCol.boundingSphere.center.x = 0.0f;
sphereCol.boundingSphere.center.y = 0.0f;
@@ -932,7 +921,8 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
sphereCol.boundingBox.max.y = radius;
sphereCol.boundingBox.max.z = radius;
sphereCol.numSpheres = 1;
- sphereCol.spheres = &sphereCol.boundingSphere;
+ sphere.Set(radius, CVector(0.0f, 0.0f, 0.0f));
+ sphereCol.spheres = &sphere;
sphereCol.numLines = 0;
sphereCol.numBoxes = 0;
sphereCol.numTriangles = 0;
@@ -1201,7 +1191,7 @@ CWorld::FindObjectsIntersectingCubeSectorList(CPtrList &list, const CVector &vec
}
void
-CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, const CMatrix &matrix,
+CWorld::FindObjectsIntersectingAngledCollisionBox(const CBox &boundingBox, const CMatrix &matrix,
const CVector &position, float fStartX, float fStartY, float fEndX,
float fEndY, int16 *nEntitiesFound, int16 maxEntitiesToFind,
CEntity **aEntities, bool bBuildings, bool bVehicles, bool bPeds,
@@ -1261,7 +1251,7 @@ CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, co
}
void
-CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CColBox &boundingBox,
+CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CBox &boundingBox,
const CMatrix &matrix, const CVector &position,
int16 *nEntitiesFound, int16 maxEntitiesToFind,
CEntity **aEntities)
@@ -1823,18 +1813,22 @@ void
CWorld::RepositionOneObject(CEntity *pEntity)
{
int16 modelId = pEntity->GetModelIndex();
- if (IsStreetLight(modelId) || IsTreeModel(modelId) || modelId == MI_PARKINGMETER ||
- modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || modelId == MI_BIN || modelId == MI_POSTBOX1 ||
- modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || modelId == MI_DUMP1 ||
- modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 ||
- modelId == MI_PHONESIGN || modelId == MI_TAXISIGN || modelId == MI_FISHSTALL01 ||
- modelId == MI_FISHSTALL02 || modelId == MI_FISHSTALL03 || modelId == MI_FISHSTALL04 ||
- modelId == MI_BAGELSTAND2 || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT ||
- modelId == MI_PARKTABLE) {
+ if (modelId == MI_PARKINGMETER || modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN ||
+ modelId == MI_BIN || modelId == MI_POSTBOX1 || modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE ||
+ modelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 ||
+ modelId == MI_PHONESIGN || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT ||
+ modelId == MI_PARKTABLE || modelId == MI_PARKINGMETER2 || modelId == MI_TELPOLE02 ||
+ modelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId)
+// TODO(MIAMI): this is actually a different case
+|| IsStreetLight(modelId)
+ ) {
CVector &position = pEntity->GetMatrix().GetPosition();
- float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z;
+ CColModel *pColModel = pEntity->GetColModel();
+ float fBoundingBoxMinZ = pColModel->boundingBox.min.z;
+ float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z;
+ if(fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z;
position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y,
- position.z + OBJECT_REPOSITION_OFFSET_Z, nil) -
+ position.z + fHeight, nil) -
fBoundingBoxMinZ;
pEntity->m_matrix.UpdateRW();
pEntity->UpdateRwFrame();
@@ -1921,6 +1915,7 @@ CWorld::Process(void)
if(csObj && csObj->m_entryInfoList.first) {
if(csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP &&
RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) {
+// TODO(MIAMI): doRender argument
RpAnimBlendClumpUpdateAnimations(csObj->GetClump(),
0.02f * (csObj->IsObject()
? CTimer::GetTimeStepNonClipped()
@@ -1939,6 +1934,7 @@ CWorld::Process(void)
CEntity *movingEnt = (CEntity *)node->item;
if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP &&
RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) {
+// TODO(MIAMI): doRender argument
RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(),
0.02f * (movingEnt->IsObject()
? CTimer::GetTimeStepNonClipped()
@@ -2041,9 +2037,12 @@ CWorld::Process(void)
movingPed->EnteringCar()) {
CVehicle *movingCar = movingPed->m_pMyVehicle;
if(movingCar) {
+#ifdef GTA_TRAIN
if(movingCar->IsTrain()) {
movingPed->SetPedPositionInTrain();
- } else {
+ } else
+#endif
+ {
switch(movingPed->m_nPedState) {
case PED_ENTER_CAR:
case PED_CARJACK: movingPed->EnterCar(); break;
@@ -2228,4 +2227,60 @@ CWorld::UseDetonator(CEntity *pEntity)
pVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity);
}
}
+ CProjectileInfo::RemoveDetonatorProjectiles();
+}
+
+bool
+CWorld::IsWanderPathClear(CVector const& point1, CVector const& point2, float distance, int maxSteps)
+{
+ if (Abs(point1.z - point2.z) > distance)
+ return false;
+ if (!GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false))
+ return false;
+ CVector vecBetween = point2 - point1;
+ uint32 nSteps = Max(vecBetween.Magnitude(), maxSteps);
+ if (nSteps == 0)
+ return true;
+ vecBetween.Normalise();
+ uint32 step = 1;
+ for (step = 1; step < nSteps; step++) {
+ CVector posThisStep = point1 + vecBetween * step;
+ float level;
+ if (!CWaterLevel::GetWaterLevel(posThisStep, &level, false))
+ continue;
+ posThisStep.z = level;
+ AdvanceCurrentScanCode();
+
+ CVector vecCheckedPos(posThisStep.x, posThisStep.y, Max(point1.z, point2.z));
+ CColPoint colpoint;
+ CEntity* entity;
+ if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
+ CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
+ return false;
+ }
+
+ CVector posThisStep = point1;
+ AdvanceCurrentScanCode();
+ CVector vecCheckedPos(posThisStep.x, posThisStep.y, point1.z - 5.0f);
+
+ CColPoint colpoint;
+ CEntity* entity;
+ if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
+ CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
+ return false;
+
+ float heightNextStep = colpoint.point.z + 0.5f;
+ for (step = 1; step < nSteps; step++) {
+ CVector posThisStep = point1 + vecBetween * step;
+ posThisStep.z = heightNextStep;
+ AdvanceCurrentScanCode();
+ CVector vecCheckedPos(posThisStep.x, posThisStep.y, heightNextStep - 2.0f);
+ if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
+ CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
+ return false;
+ if (Abs(colpoint.point.z - heightNextStep) > 1.0f)
+ return false;
+ heightNextStep = colpoint.point.z + 0.5f;
+ }
+ return true;
}
diff --git a/src/core/World.h b/src/core/World.h
index 2bcc4e43..89f05cfd 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -4,19 +4,19 @@
#include "Lists.h"
#include "PlayerInfo.h"
-/* Sectors span from -2000 to 2000 in x and y.
- * With 100x100 sectors, each is 40x40 units. */
+/* Sectors span from -2400 to 1600 in x and -2000 to 2000 y.
+ * With 80x80 sectors, each is 50x50 units. */
-#define SECTOR_SIZE_X (40.0f)
-#define SECTOR_SIZE_Y (40.0f)
+#define SECTOR_SIZE_X (50.0f)
+#define SECTOR_SIZE_Y (50.0f)
-#define NUMSECTORS_X (100)
-#define NUMSECTORS_Y (100)
+#define NUMSECTORS_X (80)
+#define NUMSECTORS_Y (80)
#define WORLD_SIZE_X (NUMSECTORS_X * SECTOR_SIZE_X)
#define WORLD_SIZE_Y (NUMSECTORS_Y * SECTOR_SIZE_Y)
-#define WORLD_MIN_X (-2000.0f)
+#define WORLD_MIN_X (-2400.0f)
#define WORLD_MIN_Y (-2000.0f)
#define WORLD_MAX_X (WORLD_MIN_X + WORLD_SIZE_X)
@@ -114,8 +114,8 @@ public:
static void FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities);
static void FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies);
static void FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities);
- static void FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool);
- static void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities);
+ static void FindObjectsIntersectingAngledCollisionBox(const CBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool);
+ static void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities);
static void FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects);
static void FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList);
@@ -125,6 +125,8 @@ public:
static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY);
static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2);
+ static bool IsWanderPathClear(CVector const&, CVector const&, float, int);
+
static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); }
static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); }
static int GetSectorIndexX(float f) { return (int)GetSectorX(f); }
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index c376e11f..729cc35d 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -11,207 +11,22 @@
#include "ZoneCull.h"
#include "Zones.h"
-int32 CCullZones::NumCullZones;
-CCullZone CCullZones::aZones[NUMCULLZONES];
int32 CCullZones::NumAttributeZones;
CAttributeZone CCullZones::aAttributeZones[NUMATTRIBZONES];
-uint16 CCullZones::aIndices[NUMZONEINDICES];
-int16 CCullZones::aPointersToBigBuildingsForBuildings[NUMBUILDINGS];
-int16 CCullZones::aPointersToBigBuildingsForTreadables[NUMTREADABLES];
int32 CCullZones::CurrentWantedLevelDrop_Player;
int32 CCullZones::CurrentFlags_Camera;
int32 CCullZones::CurrentFlags_Player;
-int32 CCullZones::OldCullZone;
-int32 CCullZones::EntityIndicesUsed;
bool CCullZones::bCurrentSubwayIsInvisible;
-bool CCullZones::bCullZonesDisabled;
-
void
CCullZones::Init(void)
{
- int i;
-
NumAttributeZones = 0;
CurrentWantedLevelDrop_Player = 0;
CurrentFlags_Camera = 0;
CurrentFlags_Player = 0;
bCurrentSubwayIsInvisible = false;
- NumCullZones = 0;
- OldCullZone = -1;
- EntityIndicesUsed = 0;
-
- for(i = 0; i < NUMBUILDINGS; i++)
- aPointersToBigBuildingsForBuildings[i] = -1;
- for(i = 0; i < NUMTREADABLES; i++)
- aPointersToBigBuildingsForTreadables[i] = -1;
-}
-
-bool CCullZone::TestLine(CVector vec1, CVector vec2)
-{
- CColPoint colPoint;
- CEntity *entity;
-
- if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false);
-}
-
-
-uint16* pTempArrayIndices;
-int TempEntityIndicesUsed;
-
-void
-CCullZones::ResolveVisibilities(void)
-{
- int fd;
-
- CFileMgr::SetDir("");
- fd = CFileMgr::OpenFile("DATA\\cullzone.dat", "rb");
- if(fd > 0){
- CFileMgr::Read(fd, (char*)&NumCullZones, sizeof(NumCullZones));
- CFileMgr::Read(fd, (char*)aZones, sizeof(aZones));
- CFileMgr::Read(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones));
- CFileMgr::Read(fd, (char*)aAttributeZones, sizeof(aAttributeZones));
- CFileMgr::Read(fd, (char*)aIndices, sizeof(aIndices));
- CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
- CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
- CFileMgr::CloseFile(fd);
- }else{
-#if 0
- // TODO: implement code from mobile to generate data here
- EntityIndicesUsed = 0;
- BuildListForBigBuildings();
- pTempArrayIndices = new uint16[140000];
- TempEntityIndicesUsed = 0;
-
- for (int i = 0; i < NumCullZones; i++) {
- DoVisibilityTestCullZone(i, true);
- }
-
- CompressIndicesArray();
- delete[] pTempArrayIndices;
-
- fd = CFileMgr::OpenFileForWriting("data\\cullzone.dat");
- if (fd != 0) {
- CFileMgr::Write(fd, (char*)&NumCullZones, sizeof(NumCullZones));
- CFileMgr::Write(fd, (char*)aZones, sizeof(aZones));
- CFileMgr::Write(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones));
- CFileMgr::Write(fd, (char*)&aAttributeZones, sizeof(aAttributeZones));
- CFileMgr::Write(fd, (char*)&aIndices, sizeof(aIndices));
- CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
- CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
- CFileMgr::CloseFile(fd);
- }
-#endif
- }
-}
-
-void
-CCullZones::BuildListForBigBuildings()
-{
- for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) {
- CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
- if (building == nil || !building->bIsBIGBuilding) continue;
- CSimpleModelInfo *nonlod = (CSimpleModelInfo*)((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->m_atomics[2];
- if (nonlod == nil) continue;
-
- for (int j = i; j >= 0; j--) {
- CBuilding *building2 = CPools::GetBuildingPool()->GetSlot(j);
- if (building2 == nil || building2->bIsBIGBuilding) continue;
- if (CModelInfo::GetModelInfo(building2->GetModelIndex()) == nonlod) {
- if ((building2->GetPosition() - building->GetPosition()).Magnitude() < 5.0f) {
- aPointersToBigBuildingsForBuildings[j] = i;
- }
- }
- }
-
- for (int j = CPools::GetTreadablePool()->GetSize()-1; j >= 0; j--) {
- CTreadable *treadable = CPools::GetTreadablePool()->GetSlot(j);
- if (treadable == nil || treadable->bIsBIGBuilding) continue;
- if (CModelInfo::GetModelInfo(treadable->GetModelIndex()) == nonlod) {
- if ((treadable->GetPosition() - building->GetPosition()).Magnitude() < 5.0f) {
- aPointersToBigBuildingsForTreadables[j] = i;
- }
- }
- }
- }
-}
-
-void
-CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
-{
- aZones[zoneId].m_groupIndexCount[0] = 0;
- aZones[zoneId].m_groupIndexCount[1] = 0;
- aZones[zoneId].m_groupIndexCount[2] = 0;
- aZones[zoneId].m_indexStart = TempEntityIndicesUsed;
- aZones[zoneId].FindTestPoints();
-
- if (!doIt) return;
-
- for (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) {
- CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
- if (building != nil && !building->bIsBIGBuilding && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForBuildings[i] != -1)) {
- CBuilding *building2 = nil;
- if (aPointersToBigBuildingsForBuildings[i] != -1)
- building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
-
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
- pTempArrayIndices[TempEntityIndicesUsed++] = i;
- aZones[zoneId].m_groupIndexCount[0]++;
- }
- }
- }
-
- for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CTreadable* building = CPools::GetTreadablePool()->GetSlot(i);
- if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) {
- CTreadable* building2 = nil;
- if (aPointersToBigBuildingsForTreadables[i] != -1)
- building2 = CPools::GetTreadablePool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
-
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, building2)) {
- pTempArrayIndices[TempEntityIndicesUsed++] = i;
- aZones[zoneId].m_groupIndexCount[1]++;
- }
- }
- }
-
- for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CTreadable *building = CPools::GetTreadablePool()->GetSlot(i);
- if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < 40000.0f) {
- int start = aZones[zoneId].m_groupIndexCount[0] + aZones[zoneId].m_indexStart;
- int end = aZones[zoneId].m_groupIndexCount[1] + start;
-
- bool alreadyAdded = false;
-
- for (int k = start; k < end; k++) {
- if (aIndices[k] == i)
- alreadyAdded = true;
- }
-
- if (!alreadyAdded) {
- CBuilding *building2 = nil;
- if (aPointersToBigBuildingsForTreadables[i] != -1)
- building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
- pTempArrayIndices[TempEntityIndicesUsed++] = i;
- aZones[zoneId].m_groupIndexCount[2]++;
- }
- }
- }
- }
}
void
@@ -219,14 +34,9 @@ CCullZones::Update(void)
{
bool invisible;
- if(bCullZonesDisabled)
- return;
-
switch(CTimer::GetFrameCounter() & 7){
case 0:
case 4:
- /* Update Cull zone */
- ForceCullZoneCoors(TheCamera.GetGameCamPosition());
break;
case 2:
@@ -250,28 +60,6 @@ CCullZones::Update(void)
void
CCullZones::ForceCullZoneCoors(CVector coors)
{
- int32 z;
- z = FindCullZoneForCoors(coors);
- if(z != OldCullZone){
- if(OldCullZone >= 0)
- aZones[OldCullZone].DoStuffLeavingZone();
- if(z >= 0)
- aZones[z].DoStuffEnteringZone();
- OldCullZone = z;
- }
-}
-
-int32
-CCullZones::FindCullZoneForCoors(CVector coors)
-{
- int i;
-
- for(i = 0; i < NumCullZones; i++)
- if(coors.x >= aZones[i].minx && coors.x <= aZones[i].maxx &&
- coors.y >= aZones[i].miny && coors.y <= aZones[i].maxy &&
- coors.z >= aZones[i].minz && coors.z <= aZones[i].maxz)
- return i;
- return -1;
}
int32
@@ -346,219 +134,16 @@ CCullZones::AddCullZone(CVector const &position,
float minz, float maxz,
uint16 flag, int16 wantedLevel)
{
- CCullZone *cull;
CAttributeZone *attrib;
- CVector v;
- if((flag & ATTRZONE_NOTCULLZONE) == 0){
- cull = &aZones[NumCullZones++];
- v = position;
- // WTF is this?
- if((v-CVector(1032.14f, -624.255f, 24.93f)).Magnitude() < 1.0f)
- v = CVector(1061.7f, -613.0f, 19.0f);
- if((v-CVector(1029.48f, -495.757f, 21.98f)).Magnitude() < 1.0f)
- v = CVector(1061.4f, -506.0f, 18.5f);
- cull->position.x = clamp(v.x, minx, maxx);
- cull->position.y = clamp(v.y, miny, maxy);
- cull->position.z = clamp(v.z, minz, maxz);
- cull->minx = minx;
- cull->maxx = maxx;
- cull->miny = miny;
- cull->maxy = maxy;
- cull->minz = minz;
- cull->maxz = maxz;
- cull->m_groupIndexCount[0] = 0;
- cull->m_groupIndexCount[1] = 0;
- cull->m_groupIndexCount[2] = 0;
- cull->m_indexStart = 0;
- }
- if(flag & ~ATTRZONE_NOTCULLZONE){
- attrib = &aAttributeZones[NumAttributeZones++];
- attrib->minx = minx;
- attrib->maxx = maxx;
- attrib->miny = miny;
- attrib->maxy = maxy;
- attrib->minz = minz;
- attrib->maxz = maxz;
- attrib->attributes = flag;
- attrib->wantedLevel = wantedLevel;
- }
-}
-
-
-void
-CCullZone::DoStuffLeavingZone(void)
-{
- int i;
-
- for(i = 0; i < m_numBuildings; i++)
- DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
- for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables ; i++)
- DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[m_indexStart + i]);
-}
-
-void
-CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < 6000){
- CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false;
- bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
- }else{
- i -= 6000;
- for(j = 0; j < 3; j++)
- DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < 6000){
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false;
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false;
- bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
- }else{
- i -= 6000;
- for(j = 0; j < 3; j++)
- DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffEnteringZone(void)
-{
- int i;
-
- for(i = 0; i < m_numBuildings; i++)
- DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
- for(; i < m_numBuildings + m_numTreadablesPlus10m; i++)
- DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[m_indexStart + i]);
- for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables; i++)
- DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[m_indexStart + i]);
-}
-
-void
-CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < 6000){
- CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true;
- bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
- }else{
- i -= 6000;
- for(j = 0; j < 3; j++)
- DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < 6000){
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true;
- bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
- }else{
- i -= 6000;
- for(j = 0; j < 3; j++)
- DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < 6000){
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
- bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
- }else{
- i -= 6000;
- for(j = 0; j < 3; j++)
- DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[i+j]);
- }
-}
-
-float
-CCullZone::CalcDistToCullZoneSquared(float x, float y)
-{
- float rx, ry;
-
- if (x < minx) rx = sq(x - minx);
- else if (x > maxx) rx = sq(x - maxx);
- else rx = 0.0f;
-
- if (y < miny) ry = sq(y - miny);
- else if (y > maxy) ry = sq(y - maxy);
- else ry = 0.0f;
-
- return rx + ry;
-}
-
-bool
-CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
-{
- const CVector &pos = entity->GetPosition();
-
- CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex());
- float distToZone = CalcDistToCullZone(pos.x, pos.y);
- float lodDist;
- if (minfo->m_isSubway)
- lodDist = minfo->GetLargestLodDistance() + 30.0f;
- else
- lodDist = minfo->GetLargestLodDistance() + 50.0f;
-
- if (lodDist > distToZone) return true;
- if (!checkLevel) return false;
- CVector tempPos(minx, miny, minz);
- return CTheZones::GetLevelFromPosition(&pos) == CTheZones::GetLevelFromPosition(&tempPos);
-}
-
-bool
-CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
-{
- int32 curCount;
- int32 start;
- int32 size;
-
- for (int i = 0; i < NumCullZones; i++) {
- curCount = 0;
- for (int group = 0; group < 3; group++) {
- aZones[i].GetGroupStartAndSize(group, start, size);
-
- int unk = 0; // TODO: figure out
- for (int j = 0; j < size; j++) {
- for (int k = 0; k < 3; k++) {
- if (set[k] == pTempArrayIndices[start+j])
- unk++;
- }
- }
- if (unk == 3 && ++curCount >= count)
- return true;
- }
- }
- return false;
+ assert(NumAttributeZones < NUMATTRIBZONES);
+ attrib = &aAttributeZones[NumAttributeZones++];
+ attrib->minx = minx;
+ attrib->maxx = maxx;
+ attrib->miny = miny;
+ attrib->maxy = maxy;
+ attrib->minz = minz;
+ attrib->maxz = maxz;
+ attrib->attributes = flag;
+ attrib->wantedLevel = wantedLevel;
}
diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h
index 9bc07b8c..e76b7a44 100644
--- a/src/core/ZoneCull.h
+++ b/src/core/ZoneCull.h
@@ -1,57 +1,5 @@
class CEntity;
-class CCullZone
-{
-public:
- CVector position;
- float minx;
- float maxx;
- float miny;
- float maxy;
- float minz;
- float maxz;
-
- int32 m_indexStart;
- int16 m_groupIndexCount[3];
- int16 m_numBuildings;
- int16 m_numTreadablesPlus10m;
- int16 m_numTreadables;
-
- void DoStuffLeavingZone(void);
- static void DoStuffLeavingZone_OneBuilding(uint16 i);
- static void DoStuffLeavingZone_OneTreadableBoth(uint16 i);
- void DoStuffEnteringZone(void);
- static void DoStuffEnteringZone_OneBuilding(uint16 i);
- static void DoStuffEnteringZone_OneTreadablePlus10m(uint16 i);
- static void DoStuffEnteringZone_OneTreadable(uint16 i);
-
-
- static bool TestLine(CVector a1, CVector a2);
- float CalcDistToCullZoneSquared(float x, float y);
- float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); };
- bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel);
-
- void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) {
- switch (groupid) {
- case 1:
- start = m_groupIndexCount[0] + m_indexStart;
- size = m_groupIndexCount[1];
- break;
- case 2:
- start = m_groupIndexCount[0] + m_groupIndexCount[1] + m_indexStart;
- size = m_groupIndexCount[2];
- break;
- default:
- start = m_indexStart;
- size = m_groupIndexCount[0];
- break;
- }
- }
-
- void FindTestPoints() {}; // todo
- bool TestEntityVisibilityFromCullZone(CEntity*, float, CEntity*) { return false; }; // todo
-};
-
enum eZoneAttribs
{
ATTRZONE_CAMCLOSEIN = 1,
@@ -79,27 +27,17 @@ struct CAttributeZone
class CCullZones
{
public:
- static int32 NumCullZones;
- static CCullZone aZones[NUMCULLZONES];
static int32 NumAttributeZones;
static CAttributeZone aAttributeZones[NUMATTRIBZONES];
- static uint16 aIndices[NUMZONEINDICES];
- static int16 aPointersToBigBuildingsForBuildings[NUMBUILDINGS];
- static int16 aPointersToBigBuildingsForTreadables[NUMTREADABLES];
static int32 CurrentWantedLevelDrop_Player;
static int32 CurrentFlags_Camera;
static int32 CurrentFlags_Player;
- static int32 OldCullZone;
- static int32 EntityIndicesUsed;
static bool bCurrentSubwayIsInvisible;
- static bool bCullZonesDisabled;
static void Init(void);
- static void ResolveVisibilities(void);
static void Update(void);
static void ForceCullZoneCoors(CVector coors);
- static int32 FindCullZoneForCoors(CVector coors);
static int32 FindAttributesForCoors(CVector coors, int32 *wantedLevel);
static CAttributeZone *FindZoneWithStairsAttributeForPlayer(void);
static void MarkSubwayAsInvisible(bool visible);
@@ -117,9 +55,6 @@ public:
static bool CamNoRain(void) { return (CurrentFlags_Camera & ATTRZONE_NORAIN) != 0; }
static int32 GetWantedLevelDrop(void) { return CurrentWantedLevelDrop_Player; }
- static void BuildListForBigBuildings();
- static void DoVisibilityTestCullZone(int zoneId, bool doIt);
- static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set);
-
- static void CompressIndicesArray() {};// todo
+ //--MIAMI: TODO
+ static bool PoliceAbandonCars(void) { return false; }
};
diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp
index 4f491a49..0e8606f3 100644
--- a/src/core/Zones.cpp
+++ b/src/core/Zones.cpp
@@ -9,133 +9,138 @@
#include "World.h"
eLevelName CTheZones::m_CurrLevel;
-CZone *CTheZones::m_pPlayersZone;
int16 CTheZones::FindIndex;
uint16 CTheZones::NumberOfAudioZones;
int16 CTheZones::AudioZoneArray[NUMAUDIOZONES];
uint16 CTheZones::TotalNumberOfMapZones;
-uint16 CTheZones::TotalNumberOfZones;
-CZone CTheZones::ZoneArray[NUMZONES];
+uint16 CTheZones::TotalNumberOfInfoZones;
+uint16 CTheZones::TotalNumberOfNavigationZones;
+CZone CTheZones::InfoZoneArray[NUMINFOZONES];
CZone CTheZones::MapZoneArray[NUMMAPZONES];
+CZone CTheZones::NavigationZoneArray[NUMNAVIGZONES];
uint16 CTheZones::TotalNumberOfZoneInfos;
-CZoneInfo CTheZones::ZoneInfoArray[2*NUMZONES];
+CZoneInfo CTheZones::ZoneInfoArray[2*NUMINFOZONES];
-#define SWAPF(a, b) { float t; t = a; a = b; b = t; }
-
-inline bool IsNormalZone(int type) { return type == ZONE_DEFAULT || type == ZONE_NAVIG || type == ZONE_INFO; }
-static void
-CheckZoneInfo(CZoneInfo *info)
-{
- assert(info->carThreshold[0] >= 0);
- assert(info->carThreshold[0] <= info->carThreshold[1]);
- assert(info->carThreshold[1] <= info->carThreshold[2]);
- assert(info->carThreshold[2] <= info->carThreshold[3]);
- assert(info->carThreshold[3] <= info->carThreshold[4]);
- assert(info->carThreshold[4] <= info->carThreshold[5]);
- assert(info->carThreshold[5] <= info->copThreshold);
- assert(info->copThreshold <= info->gangThreshold[0]);
- assert(info->gangThreshold[0] <= info->gangThreshold[1]);
- assert(info->gangThreshold[1] <= info->gangThreshold[2]);
- assert(info->gangThreshold[2] <= info->gangThreshold[3]);
- assert(info->gangThreshold[3] <= info->gangThreshold[4]);
- assert(info->gangThreshold[4] <= info->gangThreshold[5]);
- assert(info->gangThreshold[5] <= info->gangThreshold[6]);
- assert(info->gangThreshold[6] <= info->gangThreshold[7]);
- assert(info->gangThreshold[7] <= info->gangThreshold[8]);
-}
+#define SWAPF(a, b) { float t; t = a; a = b; b = t; }
+//--MIAMI: done
wchar*
CZone::GetTranslatedName(void)
{
return TheText.Get(name);
}
+//--MIAMI: done
void
CTheZones::Init(void)
{
- int i;
+ int i, j;
for(i = 0; i < NUMAUDIOZONES; i++)
AudioZoneArray[i] = -1;
NumberOfAudioZones = 0;
- for(i = 0; i < NUMZONES; i++)
- memset(&ZoneArray[i], 0, sizeof(CZone));
-
- CZoneInfo *zonei;
- int x = 1000/6;
- for(i = 0; i < 2*NUMZONES; i++){
- zonei = &ZoneInfoArray[i];
- zonei->carDensity = 10;
- zonei->carThreshold[0] = x;
- zonei->carThreshold[1] = zonei->carThreshold[0] + x;
- zonei->carThreshold[2] = zonei->carThreshold[1] + x;
- zonei->carThreshold[3] = zonei->carThreshold[2] + x;
- zonei->carThreshold[4] = zonei->carThreshold[3];
- zonei->carThreshold[5] = zonei->carThreshold[4];
- zonei->copThreshold = zonei->carThreshold[5] + x;
- zonei->gangThreshold[0] = zonei->copThreshold;
- zonei->gangThreshold[1] = zonei->gangThreshold[0];
- zonei->gangThreshold[2] = zonei->gangThreshold[1];
- zonei->gangThreshold[3] = zonei->gangThreshold[2];
- zonei->gangThreshold[4] = zonei->gangThreshold[3];
- zonei->gangThreshold[5] = zonei->gangThreshold[4];
- zonei->gangThreshold[6] = zonei->gangThreshold[5];
- zonei->gangThreshold[7] = zonei->gangThreshold[6];
- zonei->gangThreshold[8] = zonei->gangThreshold[7];
- CheckZoneInfo(zonei);
+ for(i = 0; i < NUMNAVIGZONES; i++)
+ memset(&NavigationZoneArray[i], 0, sizeof(CZone));
+
+ for(i = 0; i < NUMINFOZONES; i++)
+ memset(&InfoZoneArray[i], 0, sizeof(CZone));
+
+ int x = 1000/9;
+ for(i = 0; i < 2*NUMINFOZONES; i++){
+ // Cars
+
+ ZoneInfoArray[i].carDensity = 10;
+ ZoneInfoArray[i].carThreshold[0] = x;
+ ZoneInfoArray[i].carThreshold[1] = ZoneInfoArray[i].carThreshold[0] + x;
+ ZoneInfoArray[i].carThreshold[2] = ZoneInfoArray[i].carThreshold[1] + x;
+ ZoneInfoArray[i].carThreshold[3] = ZoneInfoArray[i].carThreshold[2] + x;
+ ZoneInfoArray[i].carThreshold[4] = ZoneInfoArray[i].carThreshold[3] + x;
+ ZoneInfoArray[i].carThreshold[5] = ZoneInfoArray[i].carThreshold[4] + x;
+ ZoneInfoArray[i].carThreshold[6] = ZoneInfoArray[i].carThreshold[5] + x;
+ ZoneInfoArray[i].carThreshold[7] = ZoneInfoArray[i].carThreshold[6] + x;
+ ZoneInfoArray[i].carThreshold[8] = 1000;
+
+ ZoneInfoArray[i].boatThreshold[0] = 500;
+ ZoneInfoArray[i].boatThreshold[1] = 1000;
+
+ // What's going on here? this looks more like density
+ ZoneInfoArray[i].copThreshold = 50;
+ for(j = 0; j < NUM_GANGS; j++)
+ ZoneInfoArray[i].gangThreshold[j] = ZoneInfoArray[i].copThreshold;
+
+ // Peds
+
+ ZoneInfoArray[i].pedDensity = 12;
+
+ // What's going on here? this looks more like density
+ ZoneInfoArray[i].copPedThreshold = 50;
+ for(j = 0; j < NUM_GANGS; j++)
+ ZoneInfoArray[i].gangPedThreshold[j] = ZoneInfoArray[i].copPedThreshold;
+
+ ZoneInfoArray[i].pedGroup = 0;
}
TotalNumberOfZoneInfos = 1; // why 1?
- TotalNumberOfZones = 1;
+ TotalNumberOfNavigationZones = 1;
+ TotalNumberOfInfoZones = 1;
+
+ strcpy(InfoZoneArray[0].name, "CITYINF");
+ InfoZoneArray[0].minx = -2400.0f;
+ InfoZoneArray[0].miny = -2000.0f;
+ InfoZoneArray[0].minz = -500.0f;
+ InfoZoneArray[0].maxx = 1600.0f;
+ InfoZoneArray[0].maxy = 2000.0f;
+ InfoZoneArray[0].maxz = 500.0f;
+ InfoZoneArray[0].level = LEVEL_NONE;
+ InfoZoneArray[0].type = ZONE_INFO;
+
+ strcpy(NavigationZoneArray[0].name, "VICE_C");
+ NavigationZoneArray[0].minx = -2400.0f;
+ NavigationZoneArray[0].miny = -2000.0f;
+ NavigationZoneArray[0].minz = -500.0f;
+ NavigationZoneArray[0].maxx = 1600.0f;
+ NavigationZoneArray[0].maxy = 2000.0f;
+ NavigationZoneArray[0].maxz = 500.0f;
+ NavigationZoneArray[0].level = LEVEL_NONE;
+ NavigationZoneArray[0].type = ZONE_NAVIG;
m_CurrLevel = LEVEL_NONE;
- m_pPlayersZone = &ZoneArray[0];
-
- strcpy(ZoneArray[0].name, "CITYZON");
- ZoneArray[0].minx = -4000.0f;
- ZoneArray[0].miny = -4000.0f;
- ZoneArray[0].minz = -500.0f;
- ZoneArray[0].maxx = 4000.0f;
- ZoneArray[0].maxy = 4000.0f;
- ZoneArray[0].maxz = 500.0f;
- ZoneArray[0].level = LEVEL_NONE;
for(i = 0; i < NUMMAPZONES; i++){
memset(&MapZoneArray[i], 0, sizeof(CZone));
MapZoneArray[i].type = ZONE_MAPZONE;
}
-
TotalNumberOfMapZones = 1;
-
strcpy(MapZoneArray[0].name, "THEMAP");
- MapZoneArray[0].minx = -4000.0f;
- MapZoneArray[0].miny = -4000.0f;
+ MapZoneArray[0].minx = -2400.0f;
+ MapZoneArray[0].miny = -2000.0f;
MapZoneArray[0].minz = -500.0f;
- MapZoneArray[0].maxx = 4000.0f;
- MapZoneArray[0].maxy = 4000.0f;
+ MapZoneArray[0].maxx = 1600.0f;
+ MapZoneArray[0].maxy = 2000.0f;
MapZoneArray[0].maxz = 500.0f;
MapZoneArray[0].level = LEVEL_NONE;
}
+//--MIAMI: done
void
CTheZones::Update(void)
{
CVector pos;
pos = FindPlayerCoors();
- m_pPlayersZone = FindSmallestZonePosition(&pos);
m_CurrLevel = GetLevelFromPosition(&pos);
}
+//--MIAMI: done
void
CTheZones::CreateZone(char *name, eZoneType type,
float minx, float miny, float minz,
float maxx, float maxy, float maxz,
eLevelName level)
{
+ char tmpname[24];
char *p;
- char tmpname[8];
if(minx > maxx) SWAPF(minx, maxx);
if(miny > maxy) SWAPF(miny, maxy);
@@ -144,73 +149,94 @@ CTheZones::CreateZone(char *name, eZoneType type,
// make upper case
for(p = name; *p; p++) if(islower(*p)) *p = toupper(*p);
- // add zone
strncpy(tmpname, name, 7);
tmpname[7] = '\0';
- strcpy(ZoneArray[TotalNumberOfZones].name, tmpname);
- ZoneArray[TotalNumberOfZones].type = type;
- ZoneArray[TotalNumberOfZones].minx = minx;
- ZoneArray[TotalNumberOfZones].miny = miny;
- ZoneArray[TotalNumberOfZones].minz = minz;
- ZoneArray[TotalNumberOfZones].maxx = maxx;
- ZoneArray[TotalNumberOfZones].maxy = maxy;
- ZoneArray[TotalNumberOfZones].maxz = maxz;
- ZoneArray[TotalNumberOfZones].level = level;
- if(IsNormalZone(type)){
- ZoneArray[TotalNumberOfZones].zoneinfoDay = TotalNumberOfZoneInfos++;
- ZoneArray[TotalNumberOfZones].zoneinfoNight = TotalNumberOfZoneInfos++;
- }
- TotalNumberOfZones++;
-}
-
-void
-CTheZones::CreateMapZone(char *name, eZoneType type,
- float minx, float miny, float minz,
- float maxx, float maxy, float maxz,
- eLevelName level)
-{
- CZone *zone;
- char *p;
-
- if(minx > maxx) SWAPF(minx, maxx);
- if(miny > maxy) SWAPF(miny, maxy);
- if(minz > maxz) SWAPF(minz, maxz);
-
- // make upper case
- for(p = name; *p; p++) if(islower(*p)) *p = toupper(*p);
// add zone
- zone = &MapZoneArray[TotalNumberOfMapZones++];
- strncpy(zone->name, name, 7);
- zone->name[7] = '\0';
- zone->type = type;
- zone->minx = minx;
- zone->miny = miny;
- zone->minz = minz;
- zone->maxx = maxx;
- zone->maxy = maxy;
- zone->maxz = maxz;
- zone->level = level;
+ switch(type){
+ case ZONE_DEFAULT:
+ case ZONE_NAVIG:
+ assert(TotalNumberOfNavigationZones < NUMNAVIGZONES);
+ strcpy(NavigationZoneArray[TotalNumberOfNavigationZones].name, tmpname);
+ NavigationZoneArray[TotalNumberOfNavigationZones].type = type;
+ NavigationZoneArray[TotalNumberOfNavigationZones].minx = minx;
+ NavigationZoneArray[TotalNumberOfNavigationZones].miny = miny;
+ NavigationZoneArray[TotalNumberOfNavigationZones].minz = minz;
+ NavigationZoneArray[TotalNumberOfNavigationZones].maxx = maxx;
+ NavigationZoneArray[TotalNumberOfNavigationZones].maxy = maxy;
+ NavigationZoneArray[TotalNumberOfNavigationZones].maxz = maxz;
+ NavigationZoneArray[TotalNumberOfNavigationZones].level = level;
+ TotalNumberOfNavigationZones++;
+ break;
+ case ZONE_INFO:
+ assert(TotalNumberOfInfoZones < NUMINFOZONES);
+ strcpy(InfoZoneArray[TotalNumberOfInfoZones].name, tmpname);
+ InfoZoneArray[TotalNumberOfInfoZones].type = type;
+ InfoZoneArray[TotalNumberOfInfoZones].minx = minx;
+ InfoZoneArray[TotalNumberOfInfoZones].miny = miny;
+ InfoZoneArray[TotalNumberOfInfoZones].minz = minz;
+ InfoZoneArray[TotalNumberOfInfoZones].maxx = maxx;
+ InfoZoneArray[TotalNumberOfInfoZones].maxy = maxy;
+ InfoZoneArray[TotalNumberOfInfoZones].maxz = maxz;
+ InfoZoneArray[TotalNumberOfInfoZones].level = level;
+ InfoZoneArray[TotalNumberOfInfoZones].zoneinfoDay = TotalNumberOfZoneInfos++;
+ InfoZoneArray[TotalNumberOfInfoZones].zoneinfoNight = TotalNumberOfZoneInfos++;
+ TotalNumberOfInfoZones++;
+ break;
+ case ZONE_MAPZONE:
+ assert(TotalNumberOfMapZones < NUMMAPZONES);
+ strcpy(MapZoneArray[TotalNumberOfMapZones].name, tmpname);
+ MapZoneArray[TotalNumberOfMapZones].type = type;
+ MapZoneArray[TotalNumberOfMapZones].minx = minx;
+ MapZoneArray[TotalNumberOfMapZones].miny = miny;
+ MapZoneArray[TotalNumberOfMapZones].minz = minz;
+ MapZoneArray[TotalNumberOfMapZones].maxx = maxx;
+ MapZoneArray[TotalNumberOfMapZones].maxy = maxy;
+ MapZoneArray[TotalNumberOfMapZones].maxz = maxz;
+ MapZoneArray[TotalNumberOfMapZones].level = level;
+ TotalNumberOfMapZones++;
+ break;
+ }
}
+//--MIAMI: done
void
CTheZones::PostZoneCreation(void)
{
int i;
- for(i = 1; i < TotalNumberOfZones; i++)
- InsertZoneIntoZoneHierarchy(&ZoneArray[i]);
+ for(i = 1; i < TotalNumberOfNavigationZones; i++)
+ InsertZoneIntoZoneHierarchy(&NavigationZoneArray[i]);
InitialiseAudioZoneArray();
}
+//--MIAMI: done, but does nothing
+void
+CTheZones::CheckZonesForOverlap(void)
+{
+ int i, j;
+ char str[116];
+
+ for(i = 1; i < TotalNumberOfInfoZones; i++){
+ ZoneIsEntirelyContainedWithinOtherZone(&InfoZoneArray[i], &InfoZoneArray[0]);
+
+ for(j = 1; j < TotalNumberOfInfoZones; j++)
+ if(i != j && ZoneIsEntirelyContainedWithinOtherZone(&InfoZoneArray[i], &InfoZoneArray[j]))
+ sprintf(str, "Info zone %s contains %s\n",
+ &InfoZoneArray[j].name, &InfoZoneArray[i].name);
+ }
+}
+
+//--MIAMI: done
void
CTheZones::InsertZoneIntoZoneHierarchy(CZone *zone)
{
zone->child = nil;
zone->parent = nil;
zone->next = nil;
- InsertZoneIntoZoneHierRecursive(zone, &ZoneArray[0]);
+ InsertZoneIntoZoneHierRecursive(zone, &NavigationZoneArray[0]);
}
+//--MIAMI: done
bool
CTheZones::InsertZoneIntoZoneHierRecursive(CZone *inner, CZone *outer)
{
@@ -254,6 +280,7 @@ CTheZones::InsertZoneIntoZoneHierRecursive(CZone *inner, CZone *outer)
return true;
}
+//--MIAMI: done
bool
CTheZones::ZoneIsEntirelyContainedWithinOtherZone(CZone *inner, CZone *outer)
{
@@ -278,6 +305,7 @@ CTheZones::ZoneIsEntirelyContainedWithinOtherZone(CZone *inner, CZone *outer)
return true;
}
+//--MIAMI: done
bool
CTheZones::PointLiesWithinZone(const CVector *v, CZone *zone)
{
@@ -286,6 +314,7 @@ CTheZones::PointLiesWithinZone(const CVector *v, CZone *zone)
zone->minz <= v->z && v->z <= zone->maxz;
}
+//--MIAMI: done
eLevelName
CTheZones::GetLevelFromPosition(CVector const *v)
{
@@ -299,35 +328,35 @@ CTheZones::GetLevelFromPosition(CVector const *v)
return MapZoneArray[0].level;
}
+//--MIAMI: done
CZone*
-CTheZones::FindSmallestZonePosition(const CVector *v)
+CTheZones::FindInformationZoneForPosition(const CVector *v)
{
- CZone *best = &ZoneArray[0];
- // zone to test next
- CZone *zone = ZoneArray[0].child;
- while(zone)
- // if in zone, descent into children
- if(PointLiesWithinZone(v, zone)){
- best = zone;
- zone = zone->child;
- // otherwise try next zone
- }else
- zone = zone->next;
- return best;
+ int i;
+// char tmp[116];
+// if(!PointLiesWithinZone(v, &InfoZoneArray[0]))
+// sprintf(tmp, "x = %.3f y= %.3f z = %.3f\n", v.x, v.y, v.z);
+ for(i = 1; i < TotalNumberOfInfoZones; i++)
+ if(PointLiesWithinZone(v, &InfoZoneArray[i]))
+ return &InfoZoneArray[i];
+ return &InfoZoneArray[0];
}
+//--MIAMI: done
CZone*
-CTheZones::FindSmallestZonePositionType(const CVector *v, eZoneType type)
+CTheZones::FindSmallestNavigationZoneForPosition(const CVector *v, bool findDefault, bool findNavig)
{
CZone *best = nil;
- if(ZoneArray[0].type == type)
- best = &ZoneArray[0];
+ if(findDefault && NavigationZoneArray[0].type == ZONE_DEFAULT ||
+ findNavig && NavigationZoneArray[0].type == ZONE_NAVIG)
+ best = &NavigationZoneArray[0];
// zone to test next
- CZone *zone = ZoneArray[0].child;
+ CZone *zone = NavigationZoneArray[0].child;
while(zone)
// if in zone, descent into children
if(PointLiesWithinZone(v, zone)){
- if(zone->type == type)
+ if(findDefault && zone->type == ZONE_DEFAULT ||
+ findNavig && zone->type == ZONE_NAVIG)
best = zone;
zone = zone->child;
// otherwise try next zone
@@ -336,43 +365,73 @@ CTheZones::FindSmallestZonePositionType(const CVector *v, eZoneType type)
return best;
}
-CZone*
-CTheZones::FindSmallestZonePositionILN(const CVector *v)
+//--MIAMI: done
+int16
+CTheZones::FindZoneByLabelAndReturnIndex(char *name, eZoneType type)
{
- CZone *best = nil;
- if(IsNormalZone(ZoneArray[0].type))
- best = &ZoneArray[0];
- // zone to test next
- CZone *zone = ZoneArray[0].child;
- while(zone)
- // if in zone, descent into children
- if(PointLiesWithinZone(v, zone)){
- if(IsNormalZone(zone->type))
- best = zone;
- zone = zone->child;
- // otherwise try next zone
- }else
- zone = zone->next;
- return best;
+ char str[8];
+ memset(str, 0, 8);
+ strncpy(str, name, 8);
+ switch(type){
+ case ZONE_DEFAULT:
+ case ZONE_NAVIG:
+ for(FindIndex = 0; FindIndex < TotalNumberOfNavigationZones; FindIndex++)
+ if(strcmp(GetNavigationZone(FindIndex)->name, name) == 0)
+ return FindIndex;
+ break;
+
+ case ZONE_INFO:
+ for(FindIndex = 0; FindIndex < TotalNumberOfInfoZones; FindIndex++)
+ if(strcmp(GetInfoZone(FindIndex)->name, name) == 0)
+ return FindIndex;
+ break;
+
+ case ZONE_MAPZONE:
+ for(FindIndex = 0; FindIndex < TotalNumberOfMapZones; FindIndex++)
+ if(strcmp(GetMapZone(FindIndex)->name, name) == 0)
+ return FindIndex;
+ break;
+ }
+ return -1;
}
+//--MIAMI: done
int16
-CTheZones::FindZoneByLabelAndReturnIndex(Const char *name)
+CTheZones::FindNextZoneByLabelAndReturnIndex(char *name, eZoneType type)
{
char str[8];
+ ++FindIndex;
memset(str, 0, 8);
strncpy(str, name, 8);
- for(FindIndex = 0; FindIndex < TotalNumberOfZones; FindIndex++)
- if(strcmp(GetZone(FindIndex)->name, name) == 0)
- return FindIndex;
+ switch(type){
+ case ZONE_DEFAULT:
+ case ZONE_NAVIG:
+ for(; FindIndex < TotalNumberOfNavigationZones; FindIndex++)
+ if(strcmp(GetNavigationZone(FindIndex)->name, name) == 0)
+ return FindIndex;
+ break;
+
+ case ZONE_INFO:
+ for(; FindIndex < TotalNumberOfInfoZones; FindIndex++)
+ if(strcmp(GetInfoZone(FindIndex)->name, name) == 0)
+ return FindIndex;
+ break;
+
+ case ZONE_MAPZONE:
+ for(; FindIndex < TotalNumberOfMapZones; FindIndex++)
+ if(strcmp(GetMapZone(FindIndex)->name, name) == 0)
+ return FindIndex;
+ break;
+ }
return -1;
}
+//--MIAMI: done
CZoneInfo*
CTheZones::GetZoneInfo(const CVector *v, uint8 day)
{
CZone *zone;
- zone = FindSmallestZonePositionILN(v);
+ zone = FindInformationZoneForPosition(v);
if(zone == nil)
return &ZoneInfoArray[0];
return &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
@@ -383,6 +442,7 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info)
{
CZoneInfo *day, *night;
float d, n;
+ int i;
day = GetZoneInfo(pos, 1);
night = GetZoneInfo(pos, 0);
@@ -402,109 +462,60 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info)
n = 1.0f - d;
}
info->carDensity = day->carDensity * d + night->carDensity * n;
- info->carThreshold[0] = day->carThreshold[0] * d + night->carThreshold[0] * n;
- info->carThreshold[1] = day->carThreshold[1] * d + night->carThreshold[1] * n;
- info->carThreshold[2] = day->carThreshold[2] * d + night->carThreshold[2] * n;
- info->carThreshold[3] = day->carThreshold[3] * d + night->carThreshold[3] * n;
- info->carThreshold[4] = day->carThreshold[4] * d + night->carThreshold[4] * n;
- info->carThreshold[5] = day->carThreshold[5] * d + night->carThreshold[5] * n;
- info->copThreshold = day->copThreshold * d + night->copThreshold * n;
- info->gangThreshold[0] = day->gangThreshold[0] * d + night->gangThreshold[0] * n;
- info->gangThreshold[1] = day->gangThreshold[1] * d + night->gangThreshold[1] * n;
- info->gangThreshold[2] = day->gangThreshold[2] * d + night->gangThreshold[2] * n;
- info->gangThreshold[3] = day->gangThreshold[3] * d + night->gangThreshold[3] * n;
- info->gangThreshold[4] = day->gangThreshold[4] * d + night->gangThreshold[4] * n;
- info->gangThreshold[5] = day->gangThreshold[5] * d + night->gangThreshold[5] * n;
- info->gangThreshold[6] = day->gangThreshold[6] * d + night->gangThreshold[6] * n;
- info->gangThreshold[7] = day->gangThreshold[7] * d + night->gangThreshold[7] * n;
- info->gangThreshold[8] = day->gangThreshold[8] * d + night->gangThreshold[8] * n;
+ for(i = 0; i < ARRAY_SIZE(info->carThreshold); i++)
+ info->carThreshold[i] = day->carThreshold[i] * d + night->carThreshold[i] * n;
+ for(i = 0; i < ARRAY_SIZE(info->boatThreshold); i++)
+ info->boatThreshold[i] = day->boatThreshold[i] * d + night->boatThreshold[i] * n;
+ for(i = 0; i < ARRAY_SIZE(info->gangThreshold); i++)
+ info->gangThreshold[i] = day->gangThreshold[i] * d + night->gangThreshold[i] * n;
+ info->copThreshold = day->copThreshold * d + night->copThreshold * n;
info->pedDensity = day->pedDensity * d + night->pedDensity * n;
- info->copDensity = day->copDensity * d + night->copDensity * n;
- info->gangDensity[0] = day->gangDensity[0] * d + night->gangDensity[0] * n;
- info->gangDensity[1] = day->gangDensity[1] * d + night->gangDensity[1] * n;
- info->gangDensity[2] = day->gangDensity[2] * d + night->gangDensity[2] * n;
- info->gangDensity[3] = day->gangDensity[3] * d + night->gangDensity[3] * n;
- info->gangDensity[4] = day->gangDensity[4] * d + night->gangDensity[4] * n;
- info->gangDensity[5] = day->gangDensity[5] * d + night->gangDensity[5] * n;
- info->gangDensity[6] = day->gangDensity[6] * d + night->gangDensity[6] * n;
- info->gangDensity[7] = day->gangDensity[7] * d + night->gangDensity[7] * n;
- info->gangDensity[8] = day->gangDensity[8] * d + night->gangDensity[8] * n;
+ info->copPedThreshold = day->copPedThreshold * d + night->copPedThreshold * n;
+ for(i = 0; i < ARRAY_SIZE(info->gangPedThreshold); i++)
+ info->gangPedThreshold[i] = day->gangPedThreshold[i] * d + night->gangPedThreshold[i] * n;
}
if(CClock::GetIsTimeInRange(5, 19))
info->pedGroup = day->pedGroup;
else
info->pedGroup = night->pedGroup;
-
- CheckZoneInfo(info);
}
void
CTheZones::SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity,
- int16 gang0Num, int16 gang1Num, int16 gang2Num,
- int16 gang3Num, int16 gang4Num, int16 gang5Num,
- int16 gang6Num, int16 gang7Num, int16 gang8Num,
- int16 copNum,
- int16 car0Num, int16 car1Num, int16 car2Num,
- int16 car3Num, int16 car4Num, int16 car5Num)
+ int16 copCarDensity, const int16 *gangCarDensities)
{
CZone *zone;
CZoneInfo *info;
- zone = GetZone(zoneid);
+ zone = GetInfoZone(zoneid);
info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
- CheckZoneInfo(info);
-
- if(carDensity != -1) info->carDensity = carDensity;
- int16 oldCar1Num = info->carThreshold[1] - info->carThreshold[0];
- int16 oldCar2Num = info->carThreshold[2] - info->carThreshold[1];
- int16 oldCar3Num = info->carThreshold[3] - info->carThreshold[2];
- int16 oldCar4Num = info->carThreshold[4] - info->carThreshold[3];
- int16 oldCar5Num = info->carThreshold[5] - info->carThreshold[4];
- int16 oldCopNum = info->copThreshold - info->carThreshold[5];
- int16 oldGang0Num = info->gangThreshold[0] - info->copThreshold;
- int16 oldGang1Num = info->gangThreshold[1] - info->gangThreshold[0];
- int16 oldGang2Num = info->gangThreshold[2] - info->gangThreshold[1];
- int16 oldGang3Num = info->gangThreshold[3] - info->gangThreshold[2];
- int16 oldGang4Num = info->gangThreshold[4] - info->gangThreshold[3];
- int16 oldGang5Num = info->gangThreshold[5] - info->gangThreshold[4];
- int16 oldGang6Num = info->gangThreshold[6] - info->gangThreshold[5];
- int16 oldGang7Num = info->gangThreshold[7] - info->gangThreshold[6];
- int16 oldGang8Num = info->gangThreshold[8] - info->gangThreshold[7];
-
- if(car0Num != -1) info->carThreshold[0] = car0Num;
- if(car1Num != -1) info->carThreshold[1] = info->carThreshold[0] + car1Num;
- else info->carThreshold[1] = info->carThreshold[0] + oldCar1Num;
- if(car2Num != -1) info->carThreshold[2] = info->carThreshold[1] + car2Num;
- else info->carThreshold[2] = info->carThreshold[1] + oldCar2Num;
- if(car3Num != -1) info->carThreshold[3] = info->carThreshold[2] + car3Num;
- else info->carThreshold[3] = info->carThreshold[2] + oldCar3Num;
- if(car4Num != -1) info->carThreshold[4] = info->carThreshold[3] + car4Num;
- else info->carThreshold[4] = info->carThreshold[3] + oldCar4Num;
- if(car5Num != -1) info->carThreshold[5] = info->carThreshold[4] + car5Num;
- else info->carThreshold[5] = info->carThreshold[4] + oldCar5Num;
- if(copNum != -1) info->copThreshold = info->carThreshold[5] + copNum;
- else info->copThreshold = info->carThreshold[5] + oldCopNum;
- if(gang0Num != -1) info->gangThreshold[0] = info->copThreshold + gang0Num;
- else info->gangThreshold[0] = info->copThreshold + oldGang0Num;
- if(gang1Num != -1) info->gangThreshold[1] = info->gangThreshold[0] + gang1Num;
- else info->gangThreshold[1] = info->gangThreshold[0] + oldGang1Num;
- if(gang2Num != -1) info->gangThreshold[2] = info->gangThreshold[1] + gang2Num;
- else info->gangThreshold[2] = info->gangThreshold[1] + oldGang2Num;
- if(gang3Num != -1) info->gangThreshold[3] = info->gangThreshold[2] + gang3Num;
- else info->gangThreshold[3] = info->gangThreshold[2] + oldGang3Num;
- if(gang4Num != -1) info->gangThreshold[4] = info->gangThreshold[3] + gang4Num;
- else info->gangThreshold[4] = info->gangThreshold[3] + oldGang4Num;
- if(gang5Num != -1) info->gangThreshold[5] = info->gangThreshold[4] + gang5Num;
- else info->gangThreshold[5] = info->gangThreshold[4] + oldGang5Num;
- if(gang6Num != -1) info->gangThreshold[6] = info->gangThreshold[5] + gang6Num;
- else info->gangThreshold[6] = info->gangThreshold[5] + oldGang6Num;
- if(gang7Num != -1) info->gangThreshold[7] = info->gangThreshold[6] + gang7Num;
- else info->gangThreshold[7] = info->gangThreshold[6] + oldGang7Num;
- if(gang8Num != -1) info->gangThreshold[8] = info->gangThreshold[7] + gang8Num;
- else info->gangThreshold[8] = info->gangThreshold[7] + oldGang8Num;
-
- CheckZoneInfo(info);
+ info->carDensity = carDensity;
+ info->copThreshold = copCarDensity;
+ info->gangThreshold[0] = gangCarDensities[0] + copCarDensity;
+ info->gangThreshold[1] = gangCarDensities[1] + info->gangThreshold[0];
+ info->gangThreshold[2] = gangCarDensities[2] + info->gangThreshold[1];
+ info->gangThreshold[3] = gangCarDensities[3] + info->gangThreshold[2];
+ info->gangThreshold[4] = gangCarDensities[4] + info->gangThreshold[3];
+ info->gangThreshold[5] = gangCarDensities[5] + info->gangThreshold[4];
+ info->gangThreshold[6] = gangCarDensities[6] + info->gangThreshold[5];
+ info->gangThreshold[7] = gangCarDensities[7] + info->gangThreshold[6];
+ info->gangThreshold[8] = gangCarDensities[8] + info->gangThreshold[7];
+}
+
+void CTheZones::SetZoneCivilianCarInfo(uint16 zoneid, uint8 day,
+ const int16* carDensities, const int16* boatDensities)
+{
+ CZone* zone;
+ CZoneInfo* info;
+ zone = GetInfoZone(zoneid);
+ info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
+ info->carThreshold[0] = carDensities[0];
+ for (int i = 1; i < CCarCtrl::NUM_CAR_CLASSES; i++)
+ info->carThreshold[i] = carDensities[i] + info->carThreshold[i-1];
+ info->boatThreshold[0] = boatDensities[0];
+ for (int i = 1; i < CCarCtrl::NUM_BOAT_CLASSES; i++)
+ info->boatThreshold[i] = boatDensities[i] + info->boatThreshold[i - 1];
}
void
@@ -515,48 +526,59 @@ CTheZones::SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity,
{
CZone *zone;
CZoneInfo *info;
- zone = GetZone(zoneid);
+ zone = GetInfoZone(zoneid);
info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
- if(pedDensity != -1) info->pedDensity = pedDensity;
- if(copDensity != -1) info->copDensity = copDensity;
- if(gang0Density != -1) info->gangDensity[0] = gang0Density;
- if(gang1Density != -1) info->gangDensity[1] = gang1Density;
- if(gang2Density != -1) info->gangDensity[2] = gang2Density;
- if(gang3Density != -1) info->gangDensity[3] = gang3Density;
- if(gang4Density != -1) info->gangDensity[4] = gang4Density;
- if(gang5Density != -1) info->gangDensity[5] = gang5Density;
- if(gang6Density != -1) info->gangDensity[6] = gang6Density;
- if(gang7Density != -1) info->gangDensity[7] = gang7Density;
- if(gang8Density != -1) info->gangDensity[8] = gang8Density;
+ info->pedDensity = pedDensity;
+ info->copPedThreshold = copDensity;
+ info->gangPedThreshold[0] = gang0Density;
+ info->gangPedThreshold[1] = gang1Density;
+ info->gangPedThreshold[2] = gang2Density;
+ info->gangPedThreshold[3] = gang3Density;
+ info->gangPedThreshold[4] = gang4Density;
+ info->gangPedThreshold[5] = gang5Density;
+ info->gangPedThreshold[6] = gang6Density;
+ info->gangPedThreshold[7] = gang7Density;
+ info->gangPedThreshold[8] = gang8Density;
+
+ info->gangPedThreshold[0] += info->copPedThreshold;
+ info->gangPedThreshold[1] = info->gangPedThreshold[0];
+ info->gangPedThreshold[2] = info->gangPedThreshold[1];
+ info->gangPedThreshold[3] = info->gangPedThreshold[2];
+ info->gangPedThreshold[4] = info->gangPedThreshold[3];
+ info->gangPedThreshold[5] = info->gangPedThreshold[4];
+ info->gangPedThreshold[6] = info->gangPedThreshold[5];
+ info->gangPedThreshold[7] = info->gangPedThreshold[6];
+ info->gangPedThreshold[8] = info->gangPedThreshold[7];
}
+//--MIAMI: done, unused
void
CTheZones::SetCarDensity(uint16 zoneid, uint8 day, uint16 cardensity)
{
CZone *zone;
- zone = GetZone(zoneid);
- if(IsNormalZone(zone->type))
- ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].carDensity = cardensity;
+ zone = GetInfoZone(zoneid);
+ ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].carDensity = cardensity;
}
+//--MIAMI: done, unused
void
CTheZones::SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity)
{
CZone *zone;
- zone = GetZone(zoneid);
- if(IsNormalZone(zone->type))
- ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedDensity = peddensity;
+ zone = GetInfoZone(zoneid);
+ ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedDensity = peddensity;
}
+//--MIAMI: done
void
CTheZones::SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup)
{
CZone *zone;
- zone = GetZone(zoneid);
- if(IsNormalZone(zone->type))
- ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedGroup = pedgroup;
+ zone = GetInfoZone(zoneid);
+ ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedGroup = pedgroup;
}
+//--MIAMI: done
int16
CTheZones::FindAudioZone(CVector *pos)
{
@@ -568,18 +590,7 @@ CTheZones::FindAudioZone(CVector *pos)
return -1;
}
-eLevelName
-CTheZones::FindZoneForPoint(const CVector &pos)
-{
- if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("IND_ZON"))))
- return LEVEL_INDUSTRIAL;
- if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("COM_ZON"))))
- return LEVEL_COMMERCIAL;
- if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("SUB_ZON"))))
- return LEVEL_SUBURBAN;
- return LEVEL_NONE;
-}
-
+//--MIAMI: done
void
CTheZones::AddZoneToAudioZoneArray(CZone *zone)
{
@@ -590,12 +601,14 @@ CTheZones::AddZoneToAudioZoneArray(CZone *zone)
/* This is a bit stupid */
z = -1;
- for(i = 0; i < NUMZONES; i++)
- if(&ZoneArray[i] == zone)
+ for(i = 0; i < NUMNAVIGZONES; i++)
+ if(&NavigationZoneArray[i] == zone)
z = i;
+ assert(NumberOfAudioZones < NUMAUDIOZONES);
AudioZoneArray[NumberOfAudioZones++] = z;
}
+//--MIAMI: done
void
CTheZones::InitialiseAudioZoneArray(void)
{
@@ -603,7 +616,7 @@ CTheZones::InitialiseAudioZoneArray(void)
CZone *zone;
gonext = false;
- zone = &ZoneArray[0];
+ zone = &NavigationZoneArray[0];
// Go deep first,
// set gonext when backing up a level to visit the next child
while(zone)
@@ -627,6 +640,7 @@ CTheZones::InitialiseAudioZoneArray(void)
}
}
+//--MIAMI: TODO
void
CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
{
@@ -634,32 +648,39 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
int i;
*size = SAVE_HEADER_SIZE
- + sizeof(int32) // GetIndexForZonePointer
+ sizeof(m_CurrLevel) + sizeof(FindIndex)
+ sizeof(int16) // padding
- + sizeof(ZoneArray) + sizeof(ZoneInfoArray)
- + sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos)
+ + sizeof(NavigationZoneArray) + sizeof(InfoZoneArray) + sizeof(ZoneInfoArray)
+ + sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos)
+ sizeof(MapZoneArray) + sizeof(AudioZoneArray)
+ sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones);
WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE);
- WriteSaveBuf(buffer, GetIndexForZonePointer(m_pPlayersZone));
WriteSaveBuf(buffer, m_CurrLevel);
WriteSaveBuf(buffer, FindIndex);
WriteSaveBuf(buffer, (int16)0); // padding
- for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){
- CZone *zone = WriteSaveBuf(buffer, ZoneArray[i]);
- zone->child = (CZone*)GetIndexForZonePointer(ZoneArray[i].child);
- zone->parent = (CZone*)GetIndexForZonePointer(ZoneArray[i].parent);
- zone->next = (CZone*)GetIndexForZonePointer(ZoneArray[i].next);
+// TODO(MIAMI): implement SaveOneZone
+ for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){
+ CZone *zone = WriteSaveBuf(buffer, NavigationZoneArray[i]);
+ zone->child = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].child);
+ zone->parent = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].parent);
+ zone->next = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].next);
+ }
+
+ for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){
+ CZone *zone = WriteSaveBuf(buffer, InfoZoneArray[i]);
+ zone->child = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].child);
+ zone->parent = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].parent);
+ zone->next = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].next);
}
for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)
WriteSaveBuf(buffer, ZoneInfoArray[i]);
- WriteSaveBuf(buffer, TotalNumberOfZones);
+ WriteSaveBuf(buffer, TotalNumberOfNavigationZones);
+ WriteSaveBuf(buffer, TotalNumberOfInfoZones);
WriteSaveBuf(buffer, TotalNumberOfZoneInfos);
for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) {
@@ -687,6 +708,7 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
VALIDATESAVEBUF(*size)
}
+//--MIAMI: TODO
void
CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
{
@@ -695,23 +717,32 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE);
- m_pPlayersZone = GetPointerForZoneIndex(ReadSaveBuf<int32>(buffer));
m_CurrLevel = ReadSaveBuf<eLevelName>(buffer);
FindIndex = ReadSaveBuf<int16>(buffer);
ReadSaveBuf<int16>(buffer);
- for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){
- ZoneArray[i] = ReadSaveBuf<CZone>(buffer);
+// TODO(MIAMI): implement LoadOneZone
+ for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){
+ NavigationZoneArray[i] = ReadSaveBuf<CZone>(buffer);
+
+ NavigationZoneArray[i].child = GetPointerForZoneIndex((int32)NavigationZoneArray[i].child);
+ NavigationZoneArray[i].parent = GetPointerForZoneIndex((int32)NavigationZoneArray[i].parent);
+ NavigationZoneArray[i].next = GetPointerForZoneIndex((int32)NavigationZoneArray[i].next);
+ }
+
+ for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){
+ InfoZoneArray[i] = ReadSaveBuf<CZone>(buffer);
- ZoneArray[i].child = GetPointerForZoneIndex((uintptr)ZoneArray[i].child);
- ZoneArray[i].parent = GetPointerForZoneIndex((uintptr)ZoneArray[i].parent);
- ZoneArray[i].next = GetPointerForZoneIndex((uintptr)ZoneArray[i].next);
+ InfoZoneArray[i].child = GetPointerForZoneIndex((int32)InfoZoneArray[i].child);
+ InfoZoneArray[i].parent = GetPointerForZoneIndex((int32)InfoZoneArray[i].parent);
+ InfoZoneArray[i].next = GetPointerForZoneIndex((int32)InfoZoneArray[i].next);
}
for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)
ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer);
- TotalNumberOfZones = ReadSaveBuf<int16>(buffer);
+ TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer);
+ TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer);
TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer);
for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){
diff --git a/src/core/Zones.h b/src/core/Zones.h
index 6549dad5..8d5af182 100644
--- a/src/core/Zones.h
+++ b/src/core/Zones.h
@@ -2,6 +2,7 @@
#include "Game.h"
#include "Gangs.h"
+#include "CarCtrl.h"
enum eZoneType
{
@@ -37,31 +38,33 @@ class CZoneInfo
public:
// Car data
int16 carDensity;
- int16 carThreshold[6];
- int16 copThreshold;
+ int16 carThreshold[CCarCtrl::NUM_CAR_CLASSES];
+ int16 boatThreshold[CCarCtrl::NUM_BOAT_CLASSES];
int16 gangThreshold[NUM_GANGS];
+ int16 copThreshold;
// Ped data
uint16 pedDensity;
- uint16 copDensity;
- uint16 gangDensity[NUM_GANGS];
+ uint16 gangPedThreshold[NUM_GANGS];
+ uint16 copPedThreshold;
uint16 pedGroup;
};
class CTheZones
{
- static CZone *m_pPlayersZone;
static int16 FindIndex;
static uint16 NumberOfAudioZones;
static int16 AudioZoneArray[NUMAUDIOZONES];
static uint16 TotalNumberOfMapZones;
- static uint16 TotalNumberOfZones;
- static CZone ZoneArray[NUMZONES];
+ static uint16 TotalNumberOfInfoZones;
+ static uint16 TotalNumberOfNavigationZones;
+ static CZone InfoZoneArray[NUMINFOZONES];
static CZone MapZoneArray[NUMMAPZONES];
+ static CZone NavigationZoneArray[NUMNAVIGZONES];
static uint16 TotalNumberOfZoneInfos;
- static CZoneInfo ZoneInfoArray[2*NUMZONES];
+ static CZoneInfo ZoneInfoArray[2*NUMINFOZONES];
public:
static eLevelName m_CurrLevel;
@@ -71,31 +74,27 @@ public:
float minx, float miny, float minz,
float maxx, float maxy, float maxz,
eLevelName level);
- static void CreateMapZone(char *name, eZoneType type,
- float minx, float miny, float minz,
- float maxx, float maxy, float maxz,
- eLevelName level);
- static CZone *GetZone(uint16 i) { return &ZoneArray[i]; }
- static CZone *GetAudioZone(uint16 i) { return &ZoneArray[AudioZoneArray[i]]; }
+ static CZone *GetInfoZone(uint16 i) { return &InfoZoneArray[i]; }
+ static CZone *GetNavigationZone(uint16 i) { return &NavigationZoneArray[i]; }
+ static CZone *GetMapZone(uint16 i) { return &MapZoneArray[i]; }
+ static CZone *GetAudioZone(uint16 i) { return &InfoZoneArray[AudioZoneArray[i]]; }
static void PostZoneCreation(void);
+ static void CheckZonesForOverlap(void);
static void InsertZoneIntoZoneHierarchy(CZone *zone);
static bool InsertZoneIntoZoneHierRecursive(CZone *z1, CZone *z2);
static bool ZoneIsEntirelyContainedWithinOtherZone(CZone *z1, CZone *z2);
static bool PointLiesWithinZone(const CVector *v, CZone *zone);
static eLevelName GetLevelFromPosition(const CVector *v);
- static CZone *FindSmallestZonePosition(const CVector *v);
- static CZone *FindSmallestZonePositionType(const CVector *v, eZoneType type);
- static CZone *FindSmallestZonePositionILN(const CVector *v);
- static int16 FindZoneByLabelAndReturnIndex(Const char *name);
+ static CZone *FindInformationZoneForPosition(const CVector *v);
+ static CZone *FindSmallestNavigationZoneForPosition(const CVector *v, bool findDefault, bool findNavig);
+ static int16 FindZoneByLabelAndReturnIndex(char *name, eZoneType type);
+ static int16 FindNextZoneByLabelAndReturnIndex(char *name, eZoneType type);
static CZoneInfo *GetZoneInfo(const CVector *v, uint8 day);
static void GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info);
static void SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity,
- int16 gang0Num, int16 gang1Num, int16 gang2Num,
- int16 gang3Num, int16 gang4Num, int16 gang5Num,
- int16 gang6Num, int16 gang7Num, int16 gang8Num,
- int16 copNum,
- int16 car0Num, int16 car1Num, int16 car2Num,
- int16 car3Num, int16 car4Num, int16 car5Num);
+ int16 copCarDensity, const int16 *gangCarDensities /*[NUMGANGS]*/);
+ static void SetZoneCivilianCarInfo(uint16 zoneid, uint8 day,
+ const int16* carDensities, const int16* boatDensities);
static void SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity,
int16 gang0Density, int16 gang1Density, int16 gang2Density, int16 gang3Density,
int16 gang4Density, int16 gang5Density, int16 gang6Density, int16 gang7Density,
@@ -104,9 +103,8 @@ public:
static void SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity);
static void SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup);
static int16 FindAudioZone(CVector *pos);
- static eLevelName FindZoneForPoint(const CVector &pos);
- static CZone *GetPointerForZoneIndex(int32 i) { return i == -1 ? nil : &ZoneArray[i]; }
- static int32 GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - ZoneArray; }
+ static CZone *GetPointerForZoneIndex(int32 i) { return i == -1 ? nil : &InfoZoneArray[i]; }
+ static int32 GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - InfoZoneArray; }
static void AddZoneToAudioZoneArray(CZone *zone);
static void InitialiseAudioZoneArray(void);
static void SaveAllZones(uint8 *buffer, uint32 *length);
diff --git a/src/core/common.h b/src/core/common.h
index f79b199b..ed331bbb 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -187,6 +187,7 @@ public:
#if (defined(_MSC_VER))
extern int strcasecmp(const char *str1, const char *str2);
+extern int strncasecmp(const char *str1, const char *str2, size_t len);
#endif
#define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v))
diff --git a/src/core/config.h b/src/core/config.h
index 40882128..548092f7 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -3,71 +3,74 @@
enum Config {
NUMPLAYERS = 1,
- NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC)
+ NUMCDIMAGES = 6, // gta3.img duplicates (not used on PC)
MAX_CDIMAGES = 8, // additional cdimages
MAX_CDCHANNELS = 5,
- MODELINFOSIZE = 5500,
- TXDSTORESIZE = 850,
- EXTRADIRSIZE = 128,
+ MODELINFOSIZE = 6500,
+ TXDSTORESIZE = 1385,
+ COLSTORESIZE = 31,
+ EXTRADIRSIZE = 256,
CUTSCENEDIRSIZE = 512,
- SIMPLEMODELSIZE = 5000,
- MLOMODELSIZE = 1,
- MLOINSTANCESIZE = 1,
- TIMEMODELSIZE = 30,
+ SIMPLEMODELSIZE = 3885,
+ TIMEMODELSIZE = 385,
CLUMPMODELSIZE = 5,
- PEDMODELSIZE = 90,
- VEHICLEMODELSIZE = 120,
- XTRACOMPSMODELSIZE = 2,
- TWODFXSIZE = 2000,
+ WEAPONMODELSIZE = 37,
+ PEDMODELSIZE = 130,
+ VEHICLEMODELSIZE = 110,
+ TWODFXSIZE = 1210,
MAXVEHICLESLOADED = 50, // 70 on mobile
- NUMOBJECTINFO = 168, // object.dat
+ NUMOBJECTINFO = 400, // TODO(MIAMI): fantasy // object.dat
// Pool sizes
- NUMPTRNODES = 30000, // 26000 on PS2
- NUMENTRYINFOS = 5400, // 3200 on PS2
- NUMPEDS = 140, // 90 on PS2
- NUMVEHICLES = 110, // 70 on PS2
- NUMBUILDINGS = 5500, // 4915 on PS2
- NUMTREADABLES = 1214,
- NUMOBJECTS = 450,
- NUMDUMMIES = 2802, // 2368 on PS2
- NUMAUDIOSCRIPTOBJECTS = 256,
- NUMCUTSCENEOBJECTS = 50,
-
- NUMANIMBLOCKS = 2,
- NUMANIMATIONS = 250,
+ NUMPTRNODES = 50000,
+ NUMENTRYINFOS = 5400, // only 3200 in VC???
+ NUMPEDS = 140,
+ NUMVEHICLES = 110,
+ NUMBUILDINGS = 7000,
+ NUMTREADABLES = 1214, // 1 in VC
+ NUMOBJECTS = 460,
+ NUMDUMMIES = 2802, // 2340 in VC
+ NUMAUDIOSCRIPTOBJECTS = 256, // 192 in VC
+ NUMCUTSCENEOBJECTS = 50, // does not exist in VC
+ // TODO(MIAMI): colmodel pool
+
+ NUMANIMBLOCKS = 35,
+ NUMANIMATIONS = 450,
NUMTEMPOBJECTS = 30,
// Path data
- NUM_PATHNODES = 4930,
- NUM_CARPATHLINKS = 2076,
+ NUM_PATHNODES = 9650,
+ NUM_CARPATHLINKS = 3500,
NUM_MAPOBJECTS = 1250,
- NUM_PATHCONNECTIONS = 10260,
+ NUM_PATHCONNECTIONS = 20400,
// Link list lengths
NUMALPHALIST = 20,
- NUMALPHAENTITYLIST = 150,
+ NUMBOATALPHALIST = 20,
+ NUMALPHAENTITYLIST = 200,
+ NUMALPHAUNTERWATERENTITYLIST = 30,
NUMCOLCACHELINKS = 200,
NUMREFERENCES = 800,
// Zones
- NUMAUDIOZONES = 36,
- NUMZONES = 50,
- NUMMAPZONES = 25,
+ NUMAUDIOZONES = 14,
+ NUMINFOZONES = 169,
+ NUMMAPZONES = 39,
+ NUMNAVIGZONES = 20,
// Cull zones
- NUMCULLZONES = 512,
- NUMATTRIBZONES = 288,
- NUMZONEINDICES = 55000,
+ NUMATTRIBZONES = 704,
+
+ NUMOCCLUSIONVOLUMES = 350,
PATHNODESIZE = 4500,
- NUMWEATHERS = 4,
+ NUMWEATHERS = 7,
NUMHOURS = 24,
NUMEXTRADIRECTIONALS = 4,
@@ -107,11 +110,11 @@ enum Config {
NUMPEDROUTES = 200,
NUMPHONES = 50,
- NUMPEDGROUPS = 31,
- NUMMODELSPERPEDGROUP = 8,
+ NUMPEDGROUPS = 67,
+ NUMMODELSPERPEDGROUP = 16,
NUMSHOTINFOS = 100,
- NUMROADBLOCKS = 600,
+ NUMROADBLOCKS = 300,
NUMVISIBLEENTITIES = 2000,
NUMINVISIBLEENTITIES = 150,
@@ -127,7 +130,7 @@ enum Config {
NUM_AUDIO_REFLECTIONS = 5,
NUM_SCRIPT_MAX_ENTITIES = 40,
- NUM_GARAGE_STORED_CARS = 6,
+ NUM_GARAGE_STORED_CARS = 4,
NUM_CRANES = 8,
@@ -191,7 +194,7 @@ enum Config {
#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more
#define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things
-#define MORE_LANGUAGES // Add more translations to the game
+//#define MORE_LANGUAGES // Add more translations to the game
#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch)
#define USE_TXD_CDIMAGE // generate and load textures from txd.img
#define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 1ea8dc7f..9b40b81d 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -81,7 +81,7 @@ RwRGBA gColourTop;
bool gameAlreadyInitialised;
float NumberOfChunksLoaded;
-#define TOTALNUMCHUNKS 73.0f
+#define TOTALNUMCHUNKS 95.0f
bool g_SlowMode = false;
char version_name[64];
@@ -356,6 +356,7 @@ Terminate3D(void)
CSprite2d splash;
int splashTxdId = -1;
+//--MIAMI: done
CSprite2d*
LoadSplash(const char *name)
{
@@ -401,22 +402,23 @@ DestroySplashScreen(void)
splashTxdId = -1;
}
+//--MIAMI: done
Const char*
GetRandomSplashScreen(void)
{
int index;
static int index2 = 0;
static char splashName[128];
- static int splashIndex[24] = {
- 25, 22, 4, 13,
- 1, 21, 14, 16,
- 10, 12, 5, 9,
- 11, 18, 3, 2,
- 19, 23, 7, 17,
- 15, 6, 8, 20
+ static int splashIndex[12] = {
+ 1, 2,
+ 3, 4,
+ 5, 11,
+ 6, 8,
+ 9, 10,
+ 7, 12
};
- index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)];
+ index = splashIndex[2*index2 + CGeneral::GetRandomNumberInRange(0, 2)];
index2++;
if(index2 == 6)
index2 = 0;
@@ -443,17 +445,14 @@ ResetLoadingScreenBar()
NumberOfChunksLoaded = 0.0f;
}
-// TODO: compare with PS2
+//--MIAMI: done
void
LoadingScreen(const char *str1, const char *str2, const char *splashscreen)
{
CSprite2d *splash;
#ifndef RANDOMSPLASH
- if(CGame::frenchGame || CGame::germanGame || !CGame::nastyGame)
- splashscreen = "mainsc2";
- else
- splashscreen = "mainsc1";
+ splashscreen = "LOADSC0";
#endif
splash = LoadSplash(splashscreen);
@@ -474,36 +473,50 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen)
if(str1){
NumberOfChunksLoaded += 1;
+#ifndef RANDOMSPLASH
float hpos = SCREEN_SCALE_X(40);
- float length = SCREEN_WIDTH - SCREEN_SCALE_X(100);
- float vpos = SCREEN_HEIGHT - SCREEN_SCALE_Y(13);
- float height = SCREEN_SCALE_Y(7);
- CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(40, 53, 68, 255));
+ float length = SCREEN_WIDTH - SCREEN_SCALE_X(80);
+ float top = SCREEN_HEIGHT - SCREEN_SCALE_Y(14);
+ float bottom = top + SCREEN_SCALE_Y(5);
+#else
+ float hpos = SCREEN_STRETCH_X(40);
+ float length = SCREEN_STRETCH_X(440);
+ // this is rather weird
+ float top = SCREEN_STRETCH_Y(407.4f - 7.0f/3.0f);
+ float bottom = SCREEN_STRETCH_Y(407.4f + 7.0f/3.0f);
+#endif
+
+ CSprite2d::DrawRect(CRect(hpos-1.0f, top-1.0f, hpos+length+1.0f, bottom+1.0f), CRGBA(40, 53, 68, 255));
+
+ CSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(155, 50, 125, 255));
length *= NumberOfChunksLoaded/TOTALNUMCHUNKS;
- CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(81, 106, 137, 255));
+ CSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(255, 150, 225, 255));
// this is done by the game but is unused
+ CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(2), SCREEN_SCALE_Y(2));
CFont::SetPropOn();
CFont::SetRightJustifyOn();
+ CFont::SetDropShadowPosition(1);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetFontStyle(FONT_HEADING);
#ifdef CHATTYSPLASH
// my attempt
static wchar tmpstr[80];
float yscale = SCREEN_SCALE_Y(0.9f);
- vpos -= 45*yscale;
+ top -= 45*yscale;
CFont::SetScale(SCREEN_SCALE_X(0.75f), yscale);
CFont::SetPropOn();
CFont::SetRightJustifyOff();
CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(255, 255, 255, 255));
AsciiToUnicode(str1, tmpstr);
- CFont::PrintString(hpos, vpos, tmpstr);
- vpos += 22*yscale;
+ CFont::PrintString(hpos, top, tmpstr);
+ top += 22*yscale;
AsciiToUnicode(str2, tmpstr);
- CFont::PrintString(hpos, vpos, tmpstr);
+ CFont::PrintString(hpos, top, tmpstr);
#endif
}
@@ -778,14 +791,17 @@ RenderScene(void)
DoRWRenderHorizon();
CRenderer::RenderRoads();
CCoronas::RenderReflections();
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
CRenderer::RenderEverythingBarRoads();
- CRenderer::RenderBoats();
- DefinedState();
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
CWaterLevel::RenderWater();
+ CRenderer::RenderBoats();
+ CRenderer::RenderFadingInUnderwaterEntities();
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
+ // CWaterLevel::RenderTransparentWater();
CRenderer::RenderFadingInEntities();
- CRenderer::RenderVehiclesButNotBoats();
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
CWeather::RenderRainStreaks();
+ // CCoronas::RenderSunReflection
}
void
@@ -1138,7 +1154,7 @@ void
InitialiseGame(void)
{
LoadingScreen(nil, nil, "loadsc0");
- CGame::Initialise("DATA\\GTA3.DAT");
+ CGame::Initialise("DATA\\GTA_VC.DAT");
}
RsEventStatus
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 9bc6400c..0e62f3a5 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -199,11 +199,17 @@ ResetCamStatics(void)
}
static const char *carnames[] = {
- "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony",
- "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer",
- "securica", "banshee", "predator", "bus", "rhino", "barracks", "train", "chopper", "dodo", "coach", "cabbie", "stallion", "rumpo", "rcbandit",
- "bellyup", "mrwongs", "mafia", "yardie", "yakuza", "diablos", "columb", "hoods", "airtrain", "deaddodo", "speeder", "reefer", "panlant", "flatbed",
- "yankee", "escape", "borgnine", "toyz", "ghost",
+ "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "rio", "firetruk", "trash", "stretch", "manana",
+ "infernus", "voodoo", "pony", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "washing",
+ "bobcat", "mrwhoop", "bfinject", "hunter", "police", "enforcer", "securica", "banshee", "predator", "bus",
+ "rhino", "barracks", "cuban", "chopper", "angel", "coach", "cabbie", "stallion", "rumpo", "rcbandit", "romero",
+ "packer", "sentxs", "admiral", "squalo", "seaspar", "pizzaboy", "gangbur", "airtrain", "deaddodo", "speeder",
+ "reefer", "tropic", "flatbed", "yankee", "caddy", "zebra", "topfun", "skimmer", "pcj600", "faggio", "freeway",
+ "rcbaron", "rcraider", "glendale", "oceanic", "sanchez", "sparrow", "patriot", "lovefist", "coastg", "dinghy",
+ "hermes", "sabre", "sabretur", "pheonix", "walton", "regina", "comet", "deluxo", "burrito", "spand", "marquis",
+ "baggage", "kaufman", "maverick", "vcnmav", "rancher", "fbiranch", "virgo", "greenwoo", "jetmax", "hotring",
+ "sandking", "blistac", "polmav", "boxville", "benson", "mesa", "rcgoblin", "hotrina", "hotrinb",
+ "bloodra", "bloodrb", "vicechee"
};
static CTweakVar** TweakVarsList;
@@ -307,14 +313,12 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Cheats", "Nasty limbs", NastyLimbsCheat);
static int spawnCarId = MI_LANDSTAL;
- e = DebugMenuAddVar("Spawn", "Spawn Car ID", &spawnCarId, nil, 1, MI_LANDSTAL, MI_GHOST, carnames);
+ e = DebugMenuAddVar("Spawn", "Spawn Car ID", &spawnCarId, nil, 1, MI_LANDSTAL, MI_VICECHEE, carnames);
DebugMenuEntrySetWrap(e, true);
DebugMenuAddCmd("Spawn", "Spawn Car", [](){
- if(spawnCarId == MI_TRAIN ||
- spawnCarId == MI_CHOPPER ||
+ if(spawnCarId == MI_CHOPPER ||
spawnCarId == MI_AIRTRAIN ||
- spawnCarId == MI_DEADDODO ||
- spawnCarId == MI_ESCAPE)
+ spawnCarId == MI_DEADDODO)
return;
SpawnCar(spawnCarId);
});
@@ -326,19 +330,20 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Spawn", "Spawn Cheetah", [](){ SpawnCar(MI_CHEETAH); });
DebugMenuAddCmd("Spawn", "Spawn Esperanto", [](){ SpawnCar(MI_ESPERANT); });
DebugMenuAddCmd("Spawn", "Spawn Stallion", [](){ SpawnCar(MI_STALLION); });
- DebugMenuAddCmd("Spawn", "Spawn Kuruma", [](){ SpawnCar(MI_KURUMA); });
+ DebugMenuAddCmd("Spawn", "Spawn Washington", [](){ SpawnCar(MI_WASHING); });
DebugMenuAddCmd("Spawn", "Spawn Taxi", [](){ SpawnCar(MI_TAXI); });
DebugMenuAddCmd("Spawn", "Spawn Police", [](){ SpawnCar(MI_POLICE); });
DebugMenuAddCmd("Spawn", "Spawn Enforcer", [](){ SpawnCar(MI_ENFORCER); });
DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); });
- DebugMenuAddCmd("Spawn", "Spawn Yakuza", [](){ SpawnCar(MI_YAKUZA); });
- DebugMenuAddCmd("Spawn", "Spawn Yardie", [](){ SpawnCar(MI_YARDIE); });
- DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); });
+ DebugMenuAddCmd("Spawn", "Spawn Cuban", [](){ SpawnCar(MI_CUBAN); });
+ DebugMenuAddCmd("Spawn", "Spawn Voodoo", [](){ SpawnCar(MI_VOODOO); });
+ DebugMenuAddCmd("Spawn", "Spawn Sparrow", [](){ SpawnCar(MI_SPARROW); });
DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); });
DebugMenuAddVarBool8("Render", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil);
+ DebugMenuAddVarBool8("Render", "Backface Culling", &gBackfaceCulling, nil);
#ifdef LIBRW
DebugMenuAddVarBool8("Render", "PS2 Alpha test Emu", &gPS2alphaTest, nil);
#endif
@@ -348,8 +353,6 @@ DebugMenuPopulate(void)
DebugMenuAddVarBool8("Render", "Show Ped Paths", &gbShowPedPaths, nil);
DebugMenuAddVarBool8("Render", "Show Car Paths", &gbShowCarPaths, nil);
DebugMenuAddVarBool8("Render", "Show Car Path Links", &gbShowCarPathsLinks, nil);
- DebugMenuAddVarBool8("Render", "Show Ped Road Groups", &gbShowPedRoadGroups, nil);
- DebugMenuAddVarBool8("Render", "Show Car Road Groups", &gbShowCarRoadGroups, nil);
DebugMenuAddVarBool8("Render", "Show Collision Lines", &gbShowCollisionLines, nil);
DebugMenuAddVarBool8("Render", "Show Collision Polys", &gbShowCollisionPolys, nil);
DebugMenuAddVarBool8("Render", "Don't render Buildings", &gbDontRenderBuildings, nil);
diff --git a/src/core/templates.h b/src/core/templates.h
index 4f7b8490..465e3bef 100644
--- a/src/core/templates.h
+++ b/src/core/templates.h
@@ -44,18 +44,20 @@ class CPool
int m_allocPtr;
public:
+ // TODO(MIAMI): remove ctor without name argument
CPool(int size){
// TODO: use new here
m_entries = (U*)malloc(sizeof(U)*size);
m_flags = (Flags*)malloc(sizeof(Flags)*size);
m_size = size;
- m_allocPtr = 0;
+ m_allocPtr = -1;
for(int i = 0; i < size; i++){
m_flags[i].id = 0;
m_flags[i].free = 1;
}
}
-
+ CPool(int size, const char *name)
+ : CPool(size) {}
~CPool() {
Flush();
}
@@ -131,7 +133,7 @@ public:
// TODO: the cast is unsafe
return (int)((U*)entry - m_entries);
}
- int GetNoOfUsedSpaces(void) const{
+ int GetNoOfUsedSpaces(void) const {
int i;
int n = 0;
for(i = 0; i < m_size; i++)
@@ -162,6 +164,7 @@ public:
memcpy(entries, m_entries, sizeof(U)*m_size);
debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
}
+ int32 GetNoOfFreeSpaces() const { return GetSize() - GetNoOfUsedSpaces(); }
};
template<typename T>
diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp
index 3c096636..3217e684 100644
--- a/src/entities/Building.cpp
+++ b/src/entities/Building.cpp
@@ -20,3 +20,25 @@ CBuilding::ReplaceWithNewModel(int32 id)
if(m_level == LEVEL_NONE || m_level == CGame::currLevel)
CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE);
}
+
+bool
+IsBuildingPointerValid(CBuilding* pBuilding)
+{
+ if (!pBuilding)
+ return false;
+ if (pBuilding->GetIsATreadable()) {
+ int index = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding);
+#ifdef FIX_BUGS
+ return index >= 0 && index < CPools::GetTreadablePool()->GetSize();
+#else
+ return index >= 0 && index <= CPools::GetTreadablePool()->GetSize();
+#endif
+ } else {
+ int index = CPools::GetBuildingPool()->GetJustIndex(pBuilding);
+#ifdef FIX_BUGS
+ return index >= 0 && index < CPools::GetBuildingPool()->GetSize();
+#else
+ return index >= 0 && index <= CPools::GetBuildingPool()->GetSize();
+#endif
+ }
+}
diff --git a/src/entities/Building.h b/src/entities/Building.h
index 3586a8dc..2c2dfb1f 100644
--- a/src/entities/Building.h
+++ b/src/entities/Building.h
@@ -17,5 +17,4 @@ public:
virtual bool GetIsATreadable(void) { return false; }
};
-VALIDATE_SIZE(CBuilding, 0x64);
-
+bool IsBuildingPointerValid(CBuilding*);
diff --git a/src/entities/Dummy.cpp b/src/entities/Dummy.cpp
index 8a4bfd5f..92b69761 100644
--- a/src/entities/Dummy.cpp
+++ b/src/entities/Dummy.cpp
@@ -50,3 +50,18 @@ CDummy::Remove(void)
m_entryInfoList.DeleteNode(node);
}
}
+
+bool
+IsDummyPointerValid(CDummy* pDummy)
+{
+ if (!pDummy)
+ return false;
+ int index = CPools::GetDummyPool()->GetJustIndex(pDummy);
+#ifdef FIX_BUGS
+ if (index < 0 || index >= CPools::GetDummyPool()->GetSize())
+#else
+ if (index < 0 || index > CPools::GetDummyPool()->GetSize())
+#endif
+ return false;
+ return pDummy->m_entryInfoList.first;
+}
diff --git a/src/entities/Dummy.h b/src/entities/Dummy.h
index 3717a01c..84b1ce1a 100644
--- a/src/entities/Dummy.h
+++ b/src/entities/Dummy.h
@@ -16,5 +16,4 @@ public:
static void operator delete(void*, size_t);
};
-VALIDATE_SIZE(CDummy, 0x68);
-
+bool IsDummyPointerValid(CDummy* pDummy);
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index a9b6b2b8..efa67f36 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -28,6 +28,11 @@
#include "Bones.h"
#include "Debug.h"
#include "Renderer.h"
+#include "Ped.h"
+#include "Dummy.h"
+#include "WindModifiers.h"
+
+//--MIAMI: file almost done (see TODO)
int gBuildings;
@@ -52,18 +57,17 @@ CEntity::CEntity(void)
bRenderScorched = false;
bHasBlip = false;
bIsBIGBuilding = false;
- bRenderDamaged = false;
+ bStreamBIGBuilding = false;
+ bRenderDamaged = false;
bBulletProof = false;
bFireProof = false;
bCollisionProof = false;
bMeleeProof = false;
bOnlyDamagedByPlayer = false;
bStreamingDontDelete = false;
- bZoneCulled = false;
- bZoneCulled2 = false;
-
bRemoveFromWorld = false;
+
bHasHitWall = false;
bImBeingRendered = false;
bTouchingWater = false;
@@ -71,13 +75,20 @@ CEntity::CEntity(void)
bDrawLast = false;
bNoBrightHeadLights = false;
bDoNotRender = false;
-
bDistanceFade = false;
+
+ m_flagE1 = false;
m_flagE2 = false;
+ bOffscreen = false;
+ bIsStaticWaitingForCollision = false;
+ m_flagE10 = false;
+ bUnderwater = false;
+ bHasPreRenderEffects = false;
m_scanCode = 0;
m_modelIndex = -1;
m_rwObject = nil;
+ m_area = AREA_MAIN_MAP;
m_randomSeed = CGeneral::GetRandomNumber();
m_pFirstReference = nil;
}
@@ -269,6 +280,21 @@ CEntity::Remove(void)
}
void
+CEntity::SetModelIndex(uint32 id)
+{
+ m_modelIndex = id;
+ bHasPreRenderEffects = HasPreRenderEffects();
+ CreateRwObject();
+}
+
+void
+CEntity::SetModelIndexNoCreate(uint32 id)
+{
+ m_modelIndex = id;
+ bHasPreRenderEffects = HasPreRenderEffects();
+}
+
+void
CEntity::CreateRwObject(void)
{
CBaseModelInfo *mi;
@@ -298,10 +324,8 @@ CEntity::DeleteRwObject(void)
RpAtomicDestroy((RpAtomic*)m_rwObject);
RwFrameDestroy(f);
}else if(RwObjectGetType(m_rwObject) == rpCLUMP){
-#ifdef PED_SKIN
if(IsClumpSkinned((RpClump*)m_rwObject))
RpClumpForAllAtomics((RpClump*)m_rwObject, AtomicRemoveAnimFromSkinCB, nil);
-#endif
RpClumpDestroy((RpClump*)m_rwObject);
}
m_rwObject = nil;
@@ -332,14 +356,12 @@ CEntity::SetupBigBuilding(void)
bStreamingDontDelete = true;
bUsesCollision = false;
m_level = CTheZones::GetLevelFromPosition(&GetPosition());
- if(m_level == LEVEL_NONE){
- if(mi->GetTxdSlot() != CTxdStore::FindTxdSlot("generic")){
- mi->SetTexDictionary("generic");
- printf("%d:%s txd has been set to generic\n", m_modelIndex, mi->GetName());
- }
- }
- if(mi->m_lodDistances[0] > 2000.0f)
+ if(mi->m_lodDistances[0] <= 2000.0f)
+ bStreamBIGBuilding = true;
+ if(mi->m_lodDistances[0] > 2500.0f || mi->m_ignoreDrawDist)
m_level = LEVEL_NONE;
+ else if(m_level == LEVEL_NONE)
+ printf("%s isn't in a level\n", mi->GetName());
}
CRect
@@ -363,19 +385,39 @@ CEntity::GetBoundRect(void)
return rect;
}
+bool
+CEntity::HasPreRenderEffects(void)
+{
+ return IsTreeModel(GetModelIndex()) ||
+ GetModelIndex() == MI_COLLECTABLE1 ||
+ GetModelIndex() == MI_MONEY ||
+ GetModelIndex() == MI_CARMINE ||
+ GetModelIndex() == MI_NAUTICALMINE ||
+ GetModelIndex() == MI_BRIEFCASE ||
+ GetModelIndex() == MI_GRENADE ||
+ GetModelIndex() == MI_MOLOTOV ||
+ GetModelIndex() == MI_MISSILE ||
+ GetModelIndex() == MI_BEACHBALL ||
+ IsGlass(GetModelIndex()) ||
+ IsObject() && ((CObject*)this)->bIsPickup;
+ IsStreetLight(GetModelIndex());
+}
+
void
CEntity::PreRender(void)
{
+ if (CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects() != 0)
+ ProcessLightsForEntity();
+
+ if(!bHasPreRenderEffects)
+ return;
+
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);
+ if(IsTreeModel(GetModelIndex())){
+ float dist = (TheCamera.GetPosition() - GetPosition()).Magnitude2D();
+ CObject::fDistToNearestTree = Min(CObject::fDistToNearestTree, dist);
ModifyMatrixForTreeInWind();
- }else if(IsBannerModel(GetModelIndex())){
- ModifyMatrixForBannerInWind();
}
break;
case ENTITY_TYPE_OBJECT:
@@ -395,22 +437,6 @@ CEntity::PreRender(void)
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,
- GetPosition() - 0.07f*TheCamera.GetRight(),
- GetPosition() + 0.07f*TheCamera.GetRight());
- }else if(GetModelIndex() == MI_MOLOTOV){
- CMotionBlurStreaks::RegisterStreak((uintptr)this,
- 0, 100, 0,
- GetPosition() - 0.07f*TheCamera.GetRight(),
- GetPosition() + 0.07f*TheCamera.GetRight());
- }
}else if(GetModelIndex() == MI_MISSILE){
CVector pos = GetPosition();
float flicker = (CGeneral::GetRandomNumber() & 0xF)/(float)0x10;
@@ -433,12 +459,44 @@ CEntity::PreRender(void)
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
}else if(IsGlass(GetModelIndex())){
PreRenderForGlassWindow();
+ }else if (((CObject*)this)->bIsPickup) {
+ CPickups::DoPickUpEffects(this);
+ GetMatrix().UpdateRW();
+ UpdateRwFrame();
+ } else if (GetModelIndex() == MI_GRENADE) {
+ CMotionBlurStreaks::RegisterStreak((uintptr)this,
+ 100, 100, 100,
+ GetPosition() - 0.07f * TheCamera.GetRight(),
+ GetPosition() + 0.07f * TheCamera.GetRight());
+ } else if (GetModelIndex() == MI_MOLOTOV) {
+ CMotionBlurStreaks::RegisterStreak((uintptr)this,
+ 0, 100, 0,
+ GetPosition() - 0.07f * TheCamera.GetRight(),
+ GetPosition() + 0.07f * TheCamera.GetRight());
+ }else if(GetModelIndex() == MI_BEACHBALL){
+ CVector pos = GetPosition();
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_DARK,
+ gpShadowPedTex, &pos,
+ 0.4f, 0.0f, 0.0f, -0.4f,
+ CTimeCycle::GetShadowStrength(),
+ CTimeCycle::GetShadowStrength(),
+ CTimeCycle::GetShadowStrength(),
+ CTimeCycle::GetShadowStrength(),
+ 20.0f, false, 1.0f);
}
// 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_TRAFFICLIGHTS_VERTICAL){
+ CTrafficLights::DisplayActualLight(this);
+ }else if(GetModelIndex() == MI_TRAFFICLIGHTS_MIAMI){
+ CTrafficLights::DisplayActualLight(this);
+ CShadows::StoreShadowForPole(this, 4.819f, 1.315f, 0.0f, 16.0f, 0.4f, 0);
+ }else if(GetModelIndex() == MI_TRAFFICLIGHTS_TWOVERTICAL){
+ CTrafficLights::DisplayActualLight(this);
+ CShadows::StoreShadowForPole(this, 7.503f, 0.0f, 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)
@@ -447,19 +505,15 @@ CEntity::PreRender(void)
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())->GetNum2dEffects() != 0)
- ProcessLightsForEntity();
}
void
CEntity::PreRenderForGlassWindow(void)
{
+ if(((CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_isArtistGlass)
+ return;
CGlass::AskForObjectToBeRenderedInGlass(this);
bIsVisible = false;
}
@@ -480,8 +534,6 @@ CEntity::Render(void)
bool
CEntity::SetupLighting(void)
{
- DeActivateDirectional();
- SetAmbientColours();
return false;
}
@@ -567,13 +619,12 @@ CEntity::PruneReferences(void)
}
}
-#ifdef PED_SKIN
void
CEntity::UpdateRpHAnim(void)
{
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- RpHAnimHierarchyUpdateMatrices(hier);
-
+ if(IsClumpSkinned(GetClump())){
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ RpHAnimHierarchyUpdateMatrices(hier);
#if 0
int i;
char buf[256];
@@ -602,8 +653,8 @@ CEntity::UpdateRpHAnim(void)
void RenderSkeleton(RpHAnimHierarchy *hier);
RenderSkeleton(hier);
#endif
+ }
}
-#endif
void
CEntity::AddSteamsFromGround(CVector *unused)
@@ -635,6 +686,15 @@ CEntity::AddSteamsFromGround(CVector *unused)
case 4:
CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false);
break;
+// TODO(MIAMI): enable this once we have the particle objects
+/*
+ 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;
+*/
}
}
}
@@ -659,80 +719,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;
-
- pos = GetMatrix() * effect->pos;
+ switch(effect->type){
+ case EFFECT_LIGHT:
+ 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{
@@ -743,85 +789,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.shadowRange != 0.0f){
- if(lightOn){
- CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
- 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_ADDITIVE,
- 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);
+ // Light shadow
+ if(effect->light.shadowRange != 0.0f){
+ if(lightOn){
+ CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
+ 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_ADDITIVE,
+ 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);
+ }
+ }
+ 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::GetSunPosition());
+ 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;
}
}
}
@@ -844,27 +948,31 @@ CEntity::ModifyMatrixForTreeInWind(void)
CMatrix mat(GetMatrix().m_attachment);
if(CWeather::Wind >= 0.5){
- t = m_randomSeed + 16*CTimer::GetTimeInMilliseconds();
+ t = m_randomSeed + 8*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;
+ strength = -0.015f*CWeather::Wind;
}else if(CWeather::Wind >= 0.2){
t = (uintptr)this + CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = Sin(f * 6.28f);
- strength = 0.008f;
+ strength = -0.008f;
}else{
t = (uintptr)this + CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = Sin(f * 6.28f);
- strength = 0.005f;
+ strength = -0.005f;
}
mat.GetUp().x = strength * flutter;
+ if(IsPalmTreeModel(GetModelIndex()))
+ mat.GetUp().x += -0.07f*CWeather::Wind;
mat.GetUp().y = mat.GetUp().x;
+ CWindModifiers::FindWindModifier(GetPosition(), &mat.GetUp().x, &mat.GetUp().y);
+
mat.UpdateRW();
UpdateRwFrame();
}
@@ -876,6 +984,7 @@ float BannerWindTabel[] = {
0.28f, 0.28f, 0.22f, 0.1f, 0.0f, -0.1f, -0.17f, -0.12f
};
+//--MIAMI: unused
void
CEntity::ModifyMatrixForBannerInWind(void)
{
@@ -946,32 +1055,37 @@ CEntity::SaveEntityFlags(uint8*& buf)
if (bRenderScorched) tmp |= BIT(20);
if (bHasBlip) tmp |= BIT(21);
if (bIsBIGBuilding) tmp |= BIT(22);
- if (bRenderDamaged) tmp |= BIT(23);
+ if (bStreamBIGBuilding) tmp |= BIT(23);
- if (bBulletProof) tmp |= BIT(24);
- if (bFireProof) tmp |= BIT(25);
- if (bCollisionProof) tmp |= BIT(26);
- if (bMeleeProof) tmp |= BIT(27);
- if (bOnlyDamagedByPlayer) tmp |= BIT(28);
- if (bStreamingDontDelete) tmp |= BIT(29);
- if (bZoneCulled) tmp |= BIT(30);
- if (bZoneCulled2) tmp |= BIT(31);
+ if (bRenderDamaged) tmp |= BIT(24);
+ if (bBulletProof) tmp |= BIT(25);
+ if (bFireProof) tmp |= BIT(26);
+ if (bCollisionProof) tmp |= BIT(27);
+ if (bMeleeProof) tmp |= BIT(28);
+ if (bOnlyDamagedByPlayer) tmp |= BIT(29);
+ if (bStreamingDontDelete) tmp |= BIT(30);
+ if (bRemoveFromWorld) tmp |= BIT(31);
WriteSaveBuf<uint32>(buf, tmp);
tmp = 0;
- if (bRemoveFromWorld) tmp |= BIT(0);
- if (bHasHitWall) tmp |= BIT(1);
- if (bImBeingRendered) tmp |= BIT(2);
- if (bTouchingWater) tmp |= BIT(3);
- if (bIsSubway) tmp |= BIT(4);
- if (bDrawLast) tmp |= BIT(5);
- if (bNoBrightHeadLights) tmp |= BIT(6);
- if (bDoNotRender) tmp |= BIT(7);
+ if (bHasHitWall) tmp |= BIT(0);
+ if (bImBeingRendered) tmp |= BIT(1);
+ if (bTouchingWater) tmp |= BIT(2);
+ if (bIsSubway) tmp |= BIT(3);
+ if (bDrawLast) tmp |= BIT(4);
+ if (bNoBrightHeadLights) tmp |= BIT(5);
+ if (bDoNotRender) tmp |= BIT(6);
+ if (bDistanceFade) tmp |= BIT(7);
- if (bDistanceFade) tmp |= BIT(8);
+ if (m_flagE1) tmp |= BIT(8);
if (m_flagE2) tmp |= BIT(9);
+ if (bOffscreen) tmp |= BIT(10);
+ if (bIsStaticWaitingForCollision) tmp |= BIT(11);
+ if (m_flagE10) tmp |= BIT(12);
+ if (bUnderwater) tmp |= BIT(13);
+ if (bHasPreRenderEffects) tmp |= BIT(14);
WriteSaveBuf<uint32>(buf, tmp);
}
@@ -999,30 +1113,50 @@ CEntity::LoadEntityFlags(uint8*& buf)
bRenderScorched = !!(tmp & BIT(20));
bHasBlip = !!(tmp & BIT(21));
bIsBIGBuilding = !!(tmp & BIT(22));
- bRenderDamaged = !!(tmp & BIT(23));
+ bStreamBIGBuilding = !!(tmp & BIT(23));
- bBulletProof = !!(tmp & BIT(24));
- bFireProof = !!(tmp & BIT(25));
- bCollisionProof = !!(tmp & BIT(26));
- bMeleeProof = !!(tmp & BIT(27));
- bOnlyDamagedByPlayer = !!(tmp & BIT(28));
- bStreamingDontDelete = !!(tmp & BIT(29));
- bZoneCulled = !!(tmp & BIT(30));
- bZoneCulled2 = !!(tmp & BIT(31));
+ bRenderDamaged = !!(tmp & BIT(24));
+ bBulletProof = !!(tmp & BIT(25));
+ bFireProof = !!(tmp & BIT(26));
+ bCollisionProof = !!(tmp & BIT(27));
+ bMeleeProof = !!(tmp & BIT(28));
+ bOnlyDamagedByPlayer = !!(tmp & BIT(29));
+ bStreamingDontDelete = !!(tmp & BIT(30));
+ bRemoveFromWorld = !!(tmp & BIT(31));
tmp = ReadSaveBuf<uint32>(buf);
- bRemoveFromWorld = !!(tmp & BIT(0));
- bHasHitWall = !!(tmp & BIT(1));
- bImBeingRendered = !!(tmp & BIT(2));
- bTouchingWater = !!(tmp & BIT(3));
- bIsSubway = !!(tmp & BIT(4));
- bDrawLast = !!(tmp & BIT(5));
- bNoBrightHeadLights = !!(tmp & BIT(6));
- bDoNotRender = !!(tmp & BIT(7));
+ bHasHitWall = !!(tmp & BIT(0));
+ bImBeingRendered = !!(tmp & BIT(1));
+ bTouchingWater = !!(tmp & BIT(2));
+ bIsSubway = !!(tmp & BIT(3));
+ bDrawLast = !!(tmp & BIT(4));
+ bNoBrightHeadLights = !!(tmp & BIT(5));
+ bDoNotRender = !!(tmp & BIT(6));
+ bDistanceFade = !!(tmp & BIT(7));
- bDistanceFade = !!(tmp & BIT(8));
+ m_flagE1 = !!(tmp & BIT(8));
m_flagE2 = !!(tmp & BIT(9));
+ bOffscreen = !!(tmp & BIT(10));
+ bIsStaticWaitingForCollision = !!(tmp & BIT(11));
+ m_flagE10 = !!(tmp & BIT(12));
+ bUnderwater = !!(tmp & BIT(13));
+ bHasPreRenderEffects = !!(tmp & BIT(14));
}
#endif
+
+bool IsEntityPointerValid(CEntity* pEntity)
+{
+ if (!pEntity)
+ return false;
+ switch (pEntity->GetType()) {
+ case ENTITY_TYPE_NOTHING: return false;
+ case ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity);
+ case ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity);
+ case ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity);
+ case ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity);
+ case ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity);
+ }
+ return false;
+}
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index eca462cd..ab7b6203 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -59,36 +59,42 @@ public:
uint32 bRenderScorched : 1;
uint32 bHasBlip : 1;
uint32 bIsBIGBuilding : 1; // Set if this entity is a big building
- uint32 bRenderDamaged : 1; // use damaged LOD models for objects with applicable damage
+ uint32 bStreamBIGBuilding : 1; // set when draw dist <= 2000
// flagsC
+ uint32 bRenderDamaged : 1; // use damaged LOD models for objects with applicable damage
uint32 bBulletProof : 1;
uint32 bFireProof : 1;
uint32 bCollisionProof : 1;
uint32 bMeleeProof : 1;
uint32 bOnlyDamagedByPlayer : 1;
uint32 bStreamingDontDelete : 1; // Dont let the streaming remove this
- uint32 bZoneCulled : 1;
- uint32 bZoneCulled2 : 1; // only treadables+10m
+ uint32 bRemoveFromWorld : 1; // remove this entity next time it should be processed
// flagsD
- uint32 bRemoveFromWorld : 1; // remove this entity next time it should be processed
uint32 bHasHitWall : 1; // has collided with a building (changes subsequent collisions)
uint32 bImBeingRendered : 1; // don't delete me because I'm being rendered
uint32 bTouchingWater : 1; // used by cBuoyancy::ProcessBuoyancy
uint32 bIsSubway : 1; // set when subway, but maybe different meaning?
uint32 bDrawLast : 1; // draw object last
uint32 bNoBrightHeadLights : 1;
- uint32 bDoNotRender : 1;
+ uint32 bDoNotRender : 1; //-- only applies to CObjects apparently
+ uint32 bDistanceFade : 1; // Fade entity because it is far away
// flagsE
- uint32 bDistanceFade : 1; // Fade entity because it is far away
+ uint32 m_flagE1 : 1;
uint32 m_flagE2 : 1;
+ uint32 bOffscreen : 1; // offscreen flag. This can only be trusted when it is set to true
+ uint32 bIsStaticWaitingForCollision : 1; // this is used by script created entities - they are static until the collision is loaded below them
+ uint32 m_flagE10 : 1; // probably bDontStream
+ uint32 bUnderwater : 1; // this object is underwater change drawing order
+ uint32 bHasPreRenderEffects : 1; // Object has a prerender effects attached to it
uint16 m_scanCode;
uint16 m_randomSeed;
int16 m_modelIndex;
- uint16 m_level; // int16
+ int8 m_level;
+ int8 m_area;
CReference *m_pFirstReference;
public:
@@ -97,7 +103,7 @@ public:
eEntityStatus GetStatus() const { return (eEntityStatus)m_status; }
void SetStatus(eEntityStatus status) { m_status = status; }
CColModel *GetColModel(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); }
- bool IsStatic(void) { return bIsStatic; }
+ bool IsStatic(void) { return bIsStatic || bIsStaticWaitingForCollision; }
#ifdef COMPATIBLE_SAVES
void SaveEntityFlags(uint8*& buf);
void LoadEntityFlags(uint8*& buf);
@@ -106,12 +112,12 @@ public:
#endif
CEntity(void);
- ~CEntity(void);
+ virtual ~CEntity(void);
virtual void Add(void);
virtual void Remove(void);
- virtual void SetModelIndex(uint32 id) { m_modelIndex = id; CreateRwObject(); }
- virtual void SetModelIndexNoCreate(uint32 id) { m_modelIndex = id; }
+ virtual void SetModelIndex(uint32 id);
+ virtual void SetModelIndexNoCreate(uint32 id);
virtual void CreateRwObject(void);
virtual void DeleteRwObject(void);
virtual CRect GetBoundRect(void);
@@ -149,9 +155,12 @@ public:
bool GetIsOnScreenComplex(void);
bool IsVisible(void) { return m_rwObject && bIsVisible && GetIsOnScreen(); }
bool IsVisibleComplex(void) { return m_rwObject && bIsVisible && GetIsOnScreenComplex(); }
+// TODO(MIAMI):
+ bool IsEntityOccluded(void) { return false; }
int16 GetModelIndex(void) const { return m_modelIndex; }
void UpdateRwFrame(void);
void SetupBigBuilding(void);
+ bool HasPreRenderEffects(void);
void AttachToRwObject(RwObject *obj);
void DetachFromRwObject(void);
@@ -173,4 +182,4 @@ public:
static void AddSteamsFromGround(CPtrList& list);
};
-VALIDATE_SIZE(CEntity, 0x64);
+bool IsEntityPointerValid(CEntity*);
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index 31f8fcbc..423662f7 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -218,7 +218,8 @@ CPhysical::GetBoundRect(void)
void
CPhysical::AddToMovingList(void)
{
- m_movingListNode = CWorld::GetMovingEntityList().InsertItem(this);
+ if (!bIsStaticWaitingForCollision)
+ m_movingListNode = CWorld::GetMovingEntityList().InsertItem(this);
}
void
@@ -263,21 +264,11 @@ CPhysical::AddCollisionRecord(CEntity *ent)
}
}
+//--MIAMI: done
void
CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
{
if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
- CTreadable *t = (CTreadable*)ent;
- if(t->m_nodeIndices[PATH_PED][0] >= 0 ||
- t->m_nodeIndices[PATH_PED][1] >= 0 ||
- t->m_nodeIndices[PATH_PED][2] >= 0 ||
- t->m_nodeIndices[PATH_PED][3] >= 0)
- m_treadable[PATH_PED] = t;
- if(t->m_nodeIndices[PATH_CAR][0] >= 0 ||
- t->m_nodeIndices[PATH_CAR][1] >= 0 ||
- t->m_nodeIndices[PATH_CAR][2] >= 0 ||
- t->m_nodeIndices[PATH_CAR][3] >= 0)
- m_treadable[PATH_CAR] = t;
}
}
@@ -1420,7 +1411,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
A->bSkipLineCol = true;
Bobj->m_pCollidingEntity = A;
}else if(A->IsObject() && B->IsVehicle()){
- if(A->GetModelIndex() == MI_CAR_BUMPER || A->GetModelIndex() == MI_FILES)
+ if(A->GetModelIndex() == MI_CAR_BUMPER)// || A->GetModelIndex() == MI_FILES)
skipCollision = true;
else if(Aobj->ObjectCreatedBy == TEMP_OBJECT ||
Aobj->bHasBeenDamaged ||
@@ -1439,7 +1430,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
}
}
}else if(B->IsObject() && A->IsVehicle()){
- if(B->GetModelIndex() == MI_CAR_BUMPER || B->GetModelIndex() == MI_FILES)
+ if(B->GetModelIndex() == MI_CAR_BUMPER)// || B->GetModelIndex() == MI_FILES)
skipCollision = true;
else if(Bobj->ObjectCreatedBy == TEMP_OBJECT ||
Bobj->bHasBeenDamaged ||
@@ -1537,7 +1528,8 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
if(A->GetModelIndex() == MI_RCBANDIT)
adhesion *= 0.2f;
- else if(IsBoatModel(A->GetModelIndex())){
+// TODO(MIAMI): check this
+ else if(A->IsVehicle() && ((CVehicle*)A)->IsBoat()){
if(aColPoints[i].normal.z > 0.6f){
if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_LOOSE)
adhesion *= 3.0f;
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index c84686ed..b6e28275 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -46,7 +46,7 @@ public:
float m_fDistanceTravelled;
// damaged piece
- float m_fDamageImpulse;
+ float m_fDamageImpulse; // fCollisionPower
CEntity *m_pDamageEntity;
CVector m_vecDamageNormal;
int16 m_nDamagePieceType;
@@ -117,6 +117,17 @@ public:
void SetMoveSpeed(const CVector& speed) {
m_vecMoveSpeed = speed;
}
+ void AddToMoveSpeed(float x, float y, float z) {
+ m_vecMoveSpeed.x += x;
+ m_vecMoveSpeed.y += y;
+ m_vecMoveSpeed.z += z;
+ }
+ void AddToMoveSpeed(const CVector& addition) {
+ m_vecMoveSpeed += addition;
+ }
+ void AddToMoveSpeed(const CVector2D& addition) {
+ m_vecMoveSpeed += CVector(addition.x, addition.y, 0.0f);
+ }
const CVector &GetTurnSpeed() { return m_vecTurnSpeed; }
void SetTurnSpeed(float x, float y, float z) {
m_vecTurnSpeed.x = x;
@@ -160,5 +171,3 @@ public:
bool CheckCollision(void);
bool CheckCollision_SimpleCar(void);
};
-
-VALIDATE_SIZE(CPhysical, 0x128);
diff --git a/src/entities/Treadable.h b/src/entities/Treadable.h
index c3160f47..c3ab755e 100644
--- a/src/entities/Treadable.h
+++ b/src/entities/Treadable.h
@@ -8,10 +8,5 @@ public:
static void *operator new(size_t);
static void operator delete(void*, size_t);
- int16 m_nodeIndices[2][12]; // first car, then ped
-
bool GetIsATreadable(void) { return true; }
};
-
-VALIDATE_SIZE(CTreadable, 0x94);
-
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index b7e055c5..1d26cc20 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -78,7 +78,8 @@ public:
return *this;
}
- CVector &GetPosition(void){ return *(CVector*)&m_matrix.pos; }
+ const CVector &GetPosition(void) const { return *(CVector*)&m_matrix.pos; }
+ CVector& GetPosition(void) { return *(CVector*)&m_matrix.pos; }
CVector &GetRight(void) { return *(CVector*)&m_matrix.right; }
CVector &GetForward(void) { return *(CVector*)&m_matrix.up; }
CVector &GetUp(void) { return *(CVector*)&m_matrix.at; }
diff --git a/src/modelinfo/BaseModelInfo.cpp b/src/modelinfo/BaseModelInfo.cpp
index a2779107..31bb2500 100644
--- a/src/modelinfo/BaseModelInfo.cpp
+++ b/src/modelinfo/BaseModelInfo.cpp
@@ -4,12 +4,14 @@
#include "TxdStore.h"
#include "2dEffect.h"
#include "BaseModelInfo.h"
+#include "ModelInfo.h"
+//--MIAMI: file done
CBaseModelInfo::CBaseModelInfo(ModelInfoType type)
{
m_colModel = nil;
- m_twodEffects = nil;
+ m_2dEffectsID = -1;
m_objectId = -1;
m_refCount = 0;
m_txdSlot = -1;
@@ -23,7 +25,7 @@ CBaseModelInfo::Shutdown(void)
{
DeleteCollisionModel();
DeleteRwObject();
- m_twodEffects = nil;
+ m_2dEffectsID = -1;
m_num2dEffects = 0;
m_txdSlot = -1;
}
@@ -76,17 +78,17 @@ CBaseModelInfo::RemoveTexDictionaryRef(void)
void
CBaseModelInfo::Init2dEffects(void)
{
- m_twodEffects = nil;
+ m_2dEffectsID = -1;
m_num2dEffects = 0;
}
void
CBaseModelInfo::Add2dEffect(C2dEffect *fx)
{
- if(m_twodEffects)
+ if(m_2dEffectsID >= 0)
m_num2dEffects++;
else{
- m_twodEffects = fx;
+ m_2dEffectsID = CModelInfo::Get2dEffectStore().getIndex(fx);
m_num2dEffects = 1;
}
}
@@ -94,8 +96,8 @@ CBaseModelInfo::Add2dEffect(C2dEffect *fx)
C2dEffect*
CBaseModelInfo::Get2dEffect(int n)
{
- if(m_twodEffects)
- return &m_twodEffects[n];
+ if(m_2dEffectsID >= 0)
+ return CModelInfo::Get2dEffectStore().getItem(m_2dEffectsID+n);
else
return nil;
}
diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h
index 783f871f..e7dd9e4b 100644
--- a/src/modelinfo/BaseModelInfo.h
+++ b/src/modelinfo/BaseModelInfo.h
@@ -2,18 +2,20 @@
#include "Collision.h"
-#define MAX_MODEL_NAME (24)
+#define MAX_MODEL_NAME (21)
enum ModelInfoType : uint8
{
- MITYPE_NA = 0,
- MITYPE_SIMPLE = 1,
- MITYPE_MLO = 2,
- MITYPE_TIME = 3,
- MITYPE_CLUMP = 4,
- MITYPE_VEHICLE = 5,
- MITYPE_PED = 6,
- MITYPE_XTRACOMPS = 7,
+ MITYPE_NA,
+ MITYPE_SIMPLE,
+ MITYPE_MLO, // unused but still in enum
+ MITYPE_TIME,
+ MITYPE_WEAPON,
+ MITYPE_CLUMP,
+ MITYPE_VEHICLE,
+ MITYPE_PED,
+ MITYPE_XTRACOMPS, // unused but still in enum
+ MITYPE_HAND // xbox and mobile
};
VALIDATE_SIZE(ModelInfoType, 1);
@@ -23,14 +25,14 @@ class CBaseModelInfo
{
protected:
char m_name[MAX_MODEL_NAME];
+ ModelInfoType m_type;
+ uint8 m_num2dEffects;
+ bool m_bOwnsColModel;
CColModel *m_colModel;
- C2dEffect *m_twodEffects;
+ int16 m_2dEffectsID;
int16 m_objectId;
uint16 m_refCount;
int16 m_txdSlot;
- ModelInfoType m_type;
- uint8 m_num2dEffects;
- bool m_bOwnsColModel;
public:
CBaseModelInfo(ModelInfoType type);
@@ -40,13 +42,15 @@ public:
virtual RwObject *CreateInstance(RwMatrix *) = 0;
virtual RwObject *CreateInstance(void) = 0;
virtual RwObject *GetRwObject(void) = 0;
+ virtual void SetAnimFile(const char *file) {}
+ virtual void ConvertAnimFileIndex(void) {}
+ virtual int GetAnimFileIndex(void) { return -1; }
// one day it becomes virtual
ModelInfoType GetModelType() const { return m_type; }
- bool IsSimple(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME; }
- bool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE ||
- m_type == MITYPE_MLO || m_type == MITYPE_XTRACOMPS; // unused but what the heck
- }
+ bool IsBuilding(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME; }
+ bool IsSimple(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME || m_type == MITYPE_WEAPON; }
+ bool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE; }
char *GetName(void) { return m_name; }
void SetName(const char *name) { strncpy(m_name, name, MAX_MODEL_NAME); }
void SetColModel(CColModel *col, bool owns = false){
@@ -69,5 +73,3 @@ public:
uint8 GetNum2dEffects() const { return m_num2dEffects; }
uint16 GetNumRefs() const { return m_refCount; }
};
-
-VALIDATE_SIZE(CBaseModelInfo, 0x30);
diff --git a/src/modelinfo/ClumpModelInfo.cpp b/src/modelinfo/ClumpModelInfo.cpp
index 49198437..3fa9a36f 100644
--- a/src/modelinfo/ClumpModelInfo.cpp
+++ b/src/modelinfo/ClumpModelInfo.cpp
@@ -5,6 +5,9 @@
#include "NodeName.h"
#include "VisibilityPlugins.h"
#include "ModelInfo.h"
+#include "AnimManager.h"
+
+//--MIAMI: file done
void
CClumpModelInfo::DeleteRwObject(void)
@@ -13,17 +16,17 @@ CClumpModelInfo::DeleteRwObject(void)
RpClumpDestroy(m_clump);
m_clump = nil;
RemoveTexDictionaryRef();
+ if(GetAnimFileIndex() != -1)
+ CAnimManager::RemoveAnimBlockRef(GetAnimFileIndex());
}
}
-#ifdef PED_SKIN
static RpAtomic*
SetHierarchyForSkinAtomic(RpAtomic *atomic, void *data)
{
RpSkinAtomicSetHAnimHierarchy(atomic, (RpHAnimHierarchy*)data);
return nil;
}
-#endif
RwObject*
CClumpModelInfo::CreateInstance(void)
@@ -31,24 +34,17 @@ CClumpModelInfo::CreateInstance(void)
if(m_clump == nil)
return nil;
RpClump *clone = RpClumpClone(m_clump);
-#ifdef PED_SKIN
if(IsClumpSkinned(clone)){
RpHAnimHierarchy *hier;
RpHAnimAnimation *anim;
hier = GetAnimHierarchyFromClump(clone);
assert(hier);
- // This seems dangerous as only the first atomic will get a hierarchy
- // can we guarantee this if hands and head are also in the clump?
RpClumpForAllAtomics(clone, SetHierarchyForSkinAtomic, hier);
anim = HAnimAnimationCreateForHierarchy(hier);
RpHAnimHierarchySetCurrentAnim(hier, anim);
RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS));
- // the rest is xbox only:
- // RpSkinGetNumBones(RpSkinGeometryGetSkin(RpAtomicGetGeometry(IsClumpSkinned(clone))));
- RpHAnimHierarchyUpdateMatrices(hier);
}
-#endif
return (RwObject*)clone;
}
@@ -76,27 +72,18 @@ CClumpModelInfo::SetClump(RpClump *clump)
m_clump = clump;
CVisibilityPlugins::SetClumpModelInfo(m_clump, this);
AddTexDictionaryRef();
- RpClumpForAllAtomics(clump, SetAtomicRendererCB, nil);
-
-#ifdef PED_SKIN
+ if(GetAnimFileIndex() != -1)
+ CAnimManager::AddAnimBlockRef(GetAnimFileIndex());
if(IsClumpSkinned(clump)){
int i;
RpHAnimHierarchy *hier;
RpAtomic *skinAtomic;
RpSkin *skin;
- // mobile:
-// hier = nil;
-// RwFrameForAllChildren(RpClumpGetFrame(clump), GetHierarchyFromChildNodesCB, &hier);
-// assert(hier);
-// RpClumpForAllAtomics(clump, SetHierarchyForSkinAtomic, hier);
-// skinAtomic = GetFirstAtomic(clump);
-
- // xbox:
hier = GetAnimHierarchyFromClump(clump);
assert(hier);
- RpSkinAtomicSetHAnimHierarchy(IsClumpSkinned(clump), hier);
- skinAtomic = IsClumpSkinned(clump);
+ RpClumpForAllAtomics(clump, SetHierarchyForSkinAtomic, hier);
+ skinAtomic = GetFirstAtomic(clump);
assert(skinAtomic);
skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(skinAtomic));
@@ -110,12 +97,28 @@ CClumpModelInfo::SetClump(RpClump *clump)
weights->w3 /= sum;
}
RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS));
- }else
-#endif
- // do not set on skinned clip because cutscene head is not compatible with player head
- if(strncmp(GetName(), "playerh", 8) == 0)
- RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
+ }
+}
+void
+CClumpModelInfo::SetAnimFile(const char *file)
+{
+ if(strcasecmp(file, "null") == 0)
+ return;
+
+ m_animFileName = new char[strlen(file)+1];
+ strcpy(m_animFileName, file);
+}
+
+void
+CClumpModelInfo::ConvertAnimFileIndex(void)
+{
+ if(m_animFileIndex != -1){
+ // we have a string pointer in that union
+ int32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName);
+ delete[] m_animFileName;
+ m_animFileIndex = index;
+ }
}
void
@@ -147,6 +150,7 @@ CClumpModelInfo::FindFrameFromIdCB(RwFrame *frame, void *data)
return assoc->frame ? nil : frame;
}
+//--MIAMI: unused
RwFrame*
CClumpModelInfo::FindFrameFromNameCB(RwFrame *frame, void *data)
{
diff --git a/src/modelinfo/ClumpModelInfo.h b/src/modelinfo/ClumpModelInfo.h
index 58b6de11..0113d340 100644
--- a/src/modelinfo/ClumpModelInfo.h
+++ b/src/modelinfo/ClumpModelInfo.h
@@ -30,9 +30,13 @@ class CClumpModelInfo : public CBaseModelInfo
{
public:
RpClump *m_clump;
+ union {
+ int32 m_animFileIndex;
+ char *m_animFileName;
+ };
- CClumpModelInfo(void) : CBaseModelInfo(MITYPE_CLUMP) {}
- CClumpModelInfo(ModelInfoType id) : CBaseModelInfo(id) {}
+ CClumpModelInfo(void) : CBaseModelInfo(MITYPE_CLUMP) { m_animFileIndex = -1; }
+ CClumpModelInfo(ModelInfoType id) : CBaseModelInfo(id) { m_animFileIndex = -1; }
~CClumpModelInfo() {}
void DeleteRwObject(void);
RwObject *CreateInstance(void);
@@ -40,6 +44,9 @@ public:
RwObject *GetRwObject(void) { return (RwObject*)m_clump; }
virtual void SetClump(RpClump *);
+ virtual void SetAnimFile(const char *file);
+ virtual void ConvertAnimFileIndex(void);
+ virtual int GetAnimFileIndex(void) { return m_animFileIndex; }
static RpAtomic *SetAtomicRendererCB(RpAtomic *atomic, void *data);
void SetFrameIds(RwObjectNameIdAssocation *assocs);
@@ -50,5 +57,4 @@ public:
static RwFrame *FillFrameArrayCB(RwFrame *frame, void *data);
static RwFrame *GetFrameFromId(RpClump *clump, int32 id);
};
-
-VALIDATE_SIZE(CClumpModelInfo, 0x34);
+//static_assert(sizeof(CClumpModelInfo) == 0x34, "CClumpModelInfo: error");
diff --git a/src/modelinfo/MloModelInfo.cpp b/src/modelinfo/MloModelInfo.cpp
deleted file mode 100644
index 7535e6c5..00000000
--- a/src/modelinfo/MloModelInfo.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "common.h"
-
-#include "VisibilityPlugins.h"
-#include "ModelInfo.h"
-
-void
-CMloModelInfo::ConstructClump()
-{
- m_clump = RpClumpCreate();
- RwFrame *mainFrame = RwFrameCreate();
- RwFrameSetIdentity(mainFrame);
- RpClumpSetFrame(m_clump, mainFrame);
-
- for (int i = firstInstance; i < lastInstance; i++) {
- int modelId = CModelInfo::GetMloInstanceStore().store[i].m_modelIndex;
- RwMatrix *attMat = CModelInfo::GetMloInstanceStore().store[i].GetMatrix().m_attachment;
- CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(modelId);
-
- if (minfo->m_atomics[0] != nil) {
- RpAtomic *newAtomic = RpAtomicClone(minfo->m_atomics[0]);
- RwFrame *newFrame = RwFrameCreate();
- if (newAtomic != nil && newFrame != nil) {
- *RwFrameGetMatrix(newFrame) = *attMat;
- RpAtomicSetFrame(newAtomic, newFrame);
- RwFrameAddChild(mainFrame, newFrame);
- RpClumpAddAtomic(m_clump, newAtomic);
- } else {
- debug("Failed to allocate memory while creating template MLO.\n");
- }
- }
- }
-
- if (RpClumpGetNumAtomics(m_clump) != 0) {
- CVisibilityPlugins::SetClumpModelInfo(m_clump, this);
- } else {
- RpClumpDestroy(m_clump);
- m_clump = nil;
- }
-} \ No newline at end of file
diff --git a/src/modelinfo/MloModelInfo.h b/src/modelinfo/MloModelInfo.h
deleted file mode 100644
index d4344706..00000000
--- a/src/modelinfo/MloModelInfo.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-#include "ClumpModelInfo.h"
-
-class CMloModelInfo : public CClumpModelInfo
-{
-public:
- float field_34; // draw distance?
- int firstInstance;
- int lastInstance;
-public:
- CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
- void ConstructClump();
-}; \ No newline at end of file
diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h
index c0f01929..1d70be3d 100644
--- a/src/modelinfo/ModelIndices.h
+++ b/src/modelinfo/ModelIndices.h
@@ -1,13 +1,9 @@
#pragma once
+#include "ModelInfo.h"
+
#define MODELINDICES \
X("fire_hydrant", MI_FIRE_HYDRANT) \
- X("bagelstnd02", MI_BAGELSTAND2) \
- X("fish01", MI_FISHSTALL01) \
- X("fishstall02", MI_FISHSTALL02) \
- X("fishstall03", MI_FISHSTALL03) \
- X("fishstall04", MI_FISHSTALL04) \
- X("taxisign", MI_TAXISIGN) \
X("phonesign", MI_PHONESIGN) \
X("noparkingsign1", MI_NOPARKINGSIGN1) \
X("bussign1", MI_BUSSIGN1) \
@@ -20,97 +16,62 @@
X("wastebin", MI_WASTEBIN) \
X("phonebooth1", MI_PHONEBOOTH1) \
X("parkingmeter", MI_PARKINGMETER) \
+ X("parkingmeterg", MI_PARKINGMETER2) \
+ X("mall_fans", MI_MALLFAN) \
+ X("htl_fan_rotate_nt", MI_HOTELFAN_NIGHT) \
+ X("htl_fan_rotate_dy", MI_HOTELFAN_DAY) \
+ X("hotroomfan", MI_HOTROOMFAN) \
X("trafficlight1", MI_TRAFFICLIGHTS) \
+ X("MTraffic4", MI_TRAFFICLIGHTS_VERTICAL) \
+ X("MTraffic1", MI_TRAFFICLIGHTS_MIAMI) \
+ X("MTraffic2", MI_TRAFFICLIGHTS_TWOVERTICAL) \
X("lamppost1", MI_SINGLESTREETLIGHTS1) \
X("lamppost2", MI_SINGLESTREETLIGHTS2) \
X("lamppost3", MI_SINGLESTREETLIGHTS3) \
X("doublestreetlght1", MI_DOUBLESTREETLIGHTS) \
- X("rd_Road2A10", MI_ROADSFORROADBLOCKSSTART) \
- X("rd_Road1A30", MI_ROADSFORROADBLOCKSEND) \
- X("veg_tree1", MI_TREE1) \
+ X("Streetlamp1", MI_STREETLAMP1) \
+ X("Streetlamp2", MI_STREETLAMP2) \
X("veg_tree3", MI_TREE2) \
X("veg_treea1", MI_TREE3) \
- X("veg_treenew01", MI_TREE4) \
- X("veg_treenew05", MI_TREE5) \
X("veg_treeb1", MI_TREE6) \
- X("veg_treenew10", MI_TREE7) \
X("veg_treea3", MI_TREE8) \
- X("veg_treenew09", MI_TREE9) \
- X("veg_treenew08", MI_TREE10) \
- X("veg_treenew03", MI_TREE11) \
- X("veg_treenew16", MI_TREE12) \
- X("veg_treenew17", MI_TREE13) \
- X("veg_treenew06", MI_TREE14) \
X("doc_crane_cab", MODELID_CRANE_1) \
- X("cranetopb", MODELID_CRANE_2) \
- X("cranetopa", MODELID_CRANE_3) \
+ X("doc_crane_cab01", MODELID_CRANE_2) \
+ X("doc_crane_cab02", MODELID_CRANE_3) \
+ X("doc_crane_cab03", MODELID_CRANE_4) \
+ X("boatcranelg0", MODELID_CRANE_5) \
+ X("LODnetopa0", MODELID_CRANE_6) \
X("package1", MI_COLLECTABLE1) \
X("Money", MI_MONEY) \
X("barrel1", MI_CARMINE) \
- X("oddjgaragdoor", MI_GARAGEDOOR1) \
- X("bombdoor", MI_GARAGEDOOR2) \
- X("door_bombshop", MI_GARAGEDOOR3) \
- X("vheistlocdoor", MI_GARAGEDOOR4) \
- X("door2_garage", MI_GARAGEDOOR5) \
- X("ind_slidedoor", MI_GARAGEDOOR6) \
- X("bankjobdoor", MI_GARAGEDOOR7) \
- X("door_jmsgrage", MI_GARAGEDOOR9) \
- X("jamesgrge_kb", MI_GARAGEDOOR10) \
- X("door_sfehousegrge", MI_GARAGEDOOR11) \
- X("shedgaragedoor", MI_GARAGEDOOR12) \
- X("door4_garage", MI_GARAGEDOOR13) \
- X("door_col_compnd_01", MI_GARAGEDOOR14) \
- X("door_col_compnd_02", MI_GARAGEDOOR15) \
- X("door_col_compnd_03", MI_GARAGEDOOR16) \
- X("door_col_compnd_04", MI_GARAGEDOOR17) \
- X("door_col_compnd_05", MI_GARAGEDOOR18) \
- X("impex_door", MI_GARAGEDOOR19) \
- X("SalvGarage", MI_GARAGEDOOR20) \
- X("door3_garage", MI_GARAGEDOOR21) \
- X("leveldoor2", MI_GARAGEDOOR22) \
- X("double_garage_dr", MI_GARAGEDOOR23) \
- X("amcogaragedoor", MI_GARAGEDOOR24) \
- X("towergaragedoor1", MI_GARAGEDOOR25) \
- X("towergaragedoor2", MI_GARAGEDOOR26) \
- X("towergaragedoor3", MI_GARAGEDOOR27) \
- X("plysve_gragedoor", MI_GARAGEDOOR28) \
- X("impexpsubgrgdoor", MI_GARAGEDOOR29) \
- X("Sub_sprayshopdoor", MI_GARAGEDOOR30) \
- X("ind_plyrwoor", MI_GARAGEDOOR31) \
- X("8ballsuburbandoor", MI_GARAGEDOOR32) \
+ X("dk_paynspraydoor", MI_GARAGEDOOR2) \
+ X("dk_waretankdoor1", MI_GARAGEDOOR3) \
+ X("hav_garagedoor1", MI_GARAGEDOOR4) \
+ X("hav_garagedoor02", MI_GARAGEDOOR5) \
+ X("hav_garagedoor03", MI_GARAGEDOOR6) \
+ X("hav_garagedoor04", MI_GARAGEDOOR7) \
+ X("lh_showdoor03", MI_GARAGEDOOR9) \
+ X("lh_showdoor1", MI_GARAGEDOOR10) \
+ X("lhtankdoor", MI_GARAGEDOOR11) \
+ X("nbtgardoor", MI_GARAGEDOOR12) \
+ X("dk_camjonesdoor", MI_GARAGEDOOR13) \
+ X("nbtgardoor02", MI_GARAGEDOOR14) \
+ X("dt_savedra", MI_GARAGEDOOR15) \
+ X("dt_savedrb", MI_GARAGEDOOR16) \
+ X("dk_bombdoor", MI_GARAGEDOOR18) \
+ X("haiwshpnsdoor", MI_GARAGEDOOR19) \
+ X("wshpnsdoor", MI_GARAGEDOOR20) \
+ X("nbecpnsdoor", MI_GARAGEDOOR21) \
+ X("nbtgardoor03", MI_GARAGEDOOR22) \
+ X("dt_savedrc", MI_GARAGEDOOR23) \
+ X("dt_savedrd", MI_GARAGEDOOR24) \
+ X("man_frntstepGD", MI_GARAGEDOOR25) \
+ X("svegrgedoor", MI_GARAGEDOOR26) \
X("barrel2", MI_NAUTICALMINE) \
- X("crushercrush", MI_CRUSHERBODY) \
- X("crushertop", MI_CRUSHERLID) \
- X("donkeymag", MI_DONKEYMAG) \
- X("bullion", MI_BULLION) \
- X("floatpackge1", MI_FLOATPACKAGE1) \
X("briefcase", MI_BRIEFCASE) \
- X("chinabanner1", MI_CHINABANNER1) \
- X("chinabanner2", MI_CHINABANNER2) \
- X("chinabanner3", MI_CHINABANNER3) \
- X("chinabanner4", MI_CHINABANNER4) \
- X("iten_chinatown5", MI_CHINABANNER5) \
- X("iten_chinatown7", MI_CHINABANNER6) \
- X("iten_chinatown3", MI_CHINABANNER7) \
- X("iten_chinatown2", MI_CHINABANNER8) \
- X("iten_chinatown4", MI_CHINABANNER9) \
- X("iten_washline01", MI_CHINABANNER10) \
- X("iten_washline02", MI_CHINABANNER11) \
- X("iten_washline03", MI_CHINABANNER12) \
- X("chinalanterns", MI_CHINALANTERN) \
- X("glassfx1", MI_GLASS1) \
- X("glassfx2", MI_GLASS2) \
- X("glassfx3", MI_GLASS3) \
- X("glassfx4", MI_GLASS4) \
- X("glassfx55", MI_GLASS5) \
- X("glassfxsub1", MI_GLASS6) \
- X("glassfxsub2", MI_GLASS7) \
+ X("wglasssmash", MI_GLASS1) \
X("glassfx_composh", MI_GLASS8) \
- X("bridge_liftsec", MI_BRIDGELIFT) \
- X("bridge_liftweight", MI_BRIDGEWEIGHT) \
- X("subbridge_lift", MI_BRIDGEROADSEGMENT) \
X("barrel4", MI_EXPLODINGBARREL) \
- X("flagsitaly", MI_ITALYBANNER1) \
X("adrenaline", MI_PICKUP_ADRENALINE) \
X("bodyarmour", MI_PICKUP_BODYARMOUR) \
X("info", MI_PICKUP_INFO) \
@@ -119,44 +80,65 @@
X("bribe", MI_PICKUP_BRIBE) \
X("killfrenzy", MI_PICKUP_KILLFRENZY) \
X("camerapickup", MI_PICKUP_CAMERA) \
+ X("bigdollar", MI_PICKUP_REVENUE) \
+ X("pickupsave", MI_PICKUP_SAVEGAME) \
+ X("property_locked", MI_PICKUP_PROPERTY) \
+ X("property_fsale", MI_PICKUP_PROPERTY_FORSALE) \
+ X("clothesp", MI_PICKUP_CLOTHES) \
X("bollardlight", MI_BOLLARDLIGHT) \
- X("magnet", MI_MAGNET) \
- X("streetlamp1", MI_STREETLAMP1) \
- X("streetlamp2", MI_STREETLAMP2) \
- X("railtrax_lo4b", MI_RAILTRACKS) \
X("bar_barrier10", MI_FENCE) \
X("bar_barrier12", MI_FENCE2) \
X("petrolpump", MI_PETROLPUMP) \
- X("bodycast", MI_BODYCAST) \
- X("backdoor", MI_BACKDOOR) \
- X("coffee", MI_COFFEE) \
+ X("washgaspump", MI_PETROLPUMP2) \
X("bouy", MI_BUOY) \
X("parktable1", MI_PARKTABLE) \
- X("sbwy_tunl_start", MI_SUBWAY1) \
- X("sbwy_tunl_bit", MI_SUBWAY2) \
- X("sbwy_tunl_bend", MI_SUBWAY3) \
- X("sbwy_tunl_cstm6", MI_SUBWAY4) \
- X("sbwy_tunl_cstm7", MI_SUBWAY5) \
- X("sbwy_tunl_cstm8", MI_SUBWAY6) \
- X("sbwy_tunl_cstm10", MI_SUBWAY7) \
- X("sbwy_tunl_cstm9", MI_SUBWAY8) \
- X("sbwy_tunl_cstm11", MI_SUBWAY9) \
- X("sbwy_tunl_cstm1", MI_SUBWAY10) \
- X("sbwy_tunl_cstm2", MI_SUBWAY11) \
- X("sbwy_tunl_cstm4", MI_SUBWAY12) \
- X("sbwy_tunl_cstm3", MI_SUBWAY13) \
- X("sbwy_tunl_cstm5", MI_SUBWAY14) \
- X("subplatform_n2", MI_SUBWAY15) \
- X("suby_tunl_start", MI_SUBWAY16) \
- X("sbwy_tunl_start2", MI_SUBWAY17) \
- X("indy_tunl_start", MI_SUBWAY18) \
- X("indsubway03", MI_SUBPLATFORM_IND) \
- X("comerside_subway", MI_SUBPLATFORM_COMS) \
- X("subplatform", MI_SUBPLATFORM_COMS2) \
- X("subplatform_n", MI_SUBPLATFORM_COMN) \
- X("Otherside_subway", MI_SUBPLATFORM_SUB) \
- X("subplatform_sub", MI_SUBPLATFORM_SUB2) \
- X("files", MI_FILES)
+ X("lamppost1", MI_LAMPPOST1) \
+ X("veg_palm04", MI_VEG_PALM01) \
+ X("veg_palwee02", MI_VEG_PALM02) \
+ X("veg_palmkbb11", MI_VEG_PALM03) \
+ X("veg_palmkb4", MI_VEG_PALM04) \
+ X("veg_palm02", MI_VEG_PALM05) \
+ X("veg_palmkb3", MI_VEG_PALM06) \
+ X("veg_palmbig14", MI_VEG_PALM07) \
+ X("veg_palm01", MI_VEG_PALM08) \
+ X("mlamppost", MI_MLAMPPOST) \
+ X("roadworkbarrier1", MI_BARRIER1) \
+ X("littleha_police", MI_LITTLEHA_POLICE) \
+ X("telgrphpole02", MI_TELPOLE02) \
+ X("trafficlight1", MI_TRAFFICLIGHT01) \
+ X("parkbench1", MI_PARKBENCH) \
+ X("plc_stinger", MI_PLC_STINGER) \
+ X("od_lightbeam", MI_LIGHTBEAM) \
+ X("ap_radar1_01", MI_AIRPORTRADAR) \
+ X("rcbomb", MI_RCBOMB) \
+ X("beachball", MI_BEACHBALL) \
+ X("sandcastle1", MI_SANDCASTLE1) \
+ X("sandcastle2", MI_SANDCASTLE2) \
+ X("jellyfish", MI_JELLYFISH) \
+ X("jellyfish01", MI_JELLYFISH01) \
+ X("fish1single", MI_FISH1SINGLE) \
+ X("fish1s", MI_FISH1S) \
+ X("fish2single", MI_FISH2SINGLE) \
+ X("fish2s", MI_FISH2S) \
+ X("fish3single", MI_FISH3SINGLE) \
+ X("fish3s", MI_FISH3S) \
+ X("turtle", MI_TURTLE) \
+ X("dolphin", MI_DOLPHIN) \
+ X("shark", MI_SHARK) \
+ X("submarine", MI_SUBMARINE) \
+ X("Esc_step", MI_ESCALATORSTEP) \
+ X("lounge_wood_up", MI_LOUNGE_WOOD_UP) \
+ X("lounge_towel_up", MI_LOUNGE_TOWEL_UP) \
+ X("lounge_wood_dn", MI_LOUNGE_WOOD_DN) \
+ X("lotion", MI_LOTION) \
+ X("beachtowel01", MI_BEACHTOWEL01) \
+ X("beachtowel02", MI_BEACHTOWEL02) \
+ X("beachtowel03", MI_BEACHTOWEL03) \
+ X("beachtowel04", MI_BEACHTOWEL04) \
+ X("blimp_night", MI_BLIMP_NIGHT) \
+ X("blimp_day", MI_BLIMP_DAY) \
+ X("yt_main_body", MI_YT_MAIN_BODY) \
+ X("yt_main_body2", MI_YT_MAIN_BODY2)
#define X(name, var) extern int16 var;
MODELINDICES
@@ -174,88 +156,39 @@ enum
MI_MEDIC,
MI_FIREMAN,
MI_MALE01,
- MI_TAXI_D,
- MI_PIMP,
- MI_GANG01,
- MI_GANG02,
- MI_GANG03,
- MI_GANG04,
- MI_GANG05,
- MI_GANG06,
- MI_GANG07,
- MI_GANG08,
- MI_GANG09,
- MI_GANG10,
- MI_GANG11,
- MI_GANG12,
- MI_GANG13,
- MI_GANG14,
- MI_CRIMINAL01,
- MI_CRIMINAL02,
- MI_SPECIAL01,
- MI_SPECIAL02,
- MI_SPECIAL03,
- MI_SPECIAL04,
- MI_MALE02,
- MI_MALE03,
- MI_FATMALE01,
- MI_FATMALE02,
- MI_FEMALE01,
- MI_FEMALE02,
- MI_FEMALE03,
- MI_FATFEMALE01,
- MI_FATFEMALE02,
- MI_PROSTITUTE,
- MI_PROSTITUTE2,
- MI_P_MAN1,
- MI_P_MAN2,
- MI_P_WOM1,
- MI_P_WOM2,
- MI_CT_MAN1,
- MI_CT_MAN2,
- MI_CT_WOM1,
- MI_CT_WOM2,
- MI_LI_MAN1,
- MI_LI_MAN2,
- MI_LI_WOM1,
- MI_LI_WOM2,
- MI_DOCKER1,
- MI_DOCKER2,
- MI_SCUM_MAN,
- MI_SCUM_WOM,
- MI_WORKER1,
- MI_WORKER2,
- MI_B_MAN1,
- MI_B_MAN2,
- MI_B_MAN3,
- MI_B_WOM1,
- MI_B_WOM2,
- MI_B_WOM3,
- MI_MOD_MAN,
- MI_MOD_WOM,
- MI_ST_MAN,
- MI_ST_WOM,
- MI_FAN_MAN1,
- MI_FAN_MAN2,
- MI_FAN_WOM,
- MI_HOS_MAN,
- MI_HOS_WOM,
- MI_CONST1,
- MI_CONST2,
- MI_SHOPPER1,
- MI_SHOPPER2,
- MI_SHOPPER3,
- MI_STUD_MAN,
- MI_STUD_WOM,
- MI_CAS_MAN,
- MI_CAS_WOM,
- MI_BUSKER1,
- MI_BUSKER2,
- MI_BUSKER3,
- MI_BUSKER4,
- // three more peds possible
- MI_LAST_PED = 89,
+ MI_TAXI_D = 28, // HMOCA
+
+ MI_WFOGO = 63,
+ MI_WMOGO = 64,
+
+ MI_CBA = 83,
+ MI_CBB,
+ MI_HNA,
+ MI_HNB,
+ MI_SGA,
+ MI_SGB,
+ MI_CLA,
+ MI_CLB,
+ MI_GDA,
+ MI_GDB,
+ MI_BKA,
+ MI_BKB,
+ MI_PGA,
+ MI_PGB,
+ MI_VICE1,
+ MI_VICE2,
+ MI_VICE3,
+ MI_VICE4,
+ MI_VICE5,
+ MI_VICE6,
+ MI_VICE7,
+ MI_VICE8,
+ MI_WFYG2 = 106, // last regular ped
+ MI_SPECIAL01 = 109,
+ MI_SPECIAL21 = 129,
+
+ MI_LAST_PED = MI_SPECIAL21,
MI_FIRST_VEHICLE,
MI_LANDSTAL = MI_FIRST_VEHICLE,
@@ -264,13 +197,13 @@ enum
MI_LINERUN,
MI_PEREN,
MI_SENTINEL,
- MI_PATRIOT,
+ MI_RIO,
MI_FIRETRUCK,
MI_TRASH,
MI_STRETCH,
MI_MANANA,
MI_INFERNUS,
- MI_BLISTA,
+ MI_VOODOO,
MI_PONY,
MI_MULE,
MI_CHEETAH,
@@ -279,11 +212,11 @@ enum
MI_MOONBEAM,
MI_ESPERANT,
MI_TAXI,
- MI_KURUMA,
+ MI_WASHING,
MI_BOBCAT,
MI_MRWHOOP,
MI_BFINJECT,
- MI_CORPSE,
+ MI_HUNTER,
MI_POLICE,
MI_ENFORCER,
MI_SECURICA,
@@ -292,61 +225,109 @@ enum
MI_BUS,
MI_RHINO,
MI_BARRACKS,
- MI_TRAIN,
+ MI_CUBAN,
MI_CHOPPER,
- MI_DODO,
+ MI_ANGEL,
MI_COACH,
MI_CABBIE,
MI_STALLION,
MI_RUMPO,
MI_RCBANDIT,
- MI_BELLYUP,
- MI_MRWONGS,
- MI_MAFIA,
- MI_YARDIE,
- MI_YAKUZA,
- MI_DIABLOS,
- MI_COLUMB ,
- MI_HOODS,
+ MI_ROMERO,
+ MI_PACKER,
+ MI_SENTXS,
+ MI_ADMIRAL,
+ MI_SQUALO,
+ MI_SEASPAR,
+ MI_PIZZABOY,
+ MI_GANGBUR,
MI_AIRTRAIN,
MI_DEADDODO,
MI_SPEEDER,
MI_REEFER,
- MI_PANLANT,
+ MI_TROPIC,
MI_FLATBED,
MI_YANKEE,
- MI_ESCAPE,
- MI_BORGNINE,
- MI_TOYZ,
- MI_GHOST,
-
- // leftovers on PC
- MI_MIAMI_RCBARON = 154,
- MI_MIAMI_RCRAIDER = 155,
- MI_MIAMI_SPARROW = 159,
+ MI_CADDY,
+ MI_ZEBRA,
+ MI_TOPFUN,
+ MI_SKIMMER,
+ MI_PCJ600,
+ MI_FAGGIO,
+ MI_FREEWAY,
+ MI_RCBARON,
+ MI_RCRAIDER,
+ MI_GLENDALE,
+ MI_OCEANIC,
+ MI_SANCHEZ,
+ MI_SPARROW,
+ MI_PATRIOT,
+ MI_LOVEFIST,
+ MI_COASTG,
+ MI_DINGHY,
+ MI_HERMES,
+ MI_SABRE,
+ MI_SABRETUR,
+ MI_PHEONIX,
+ MI_WALTON,
+ MI_REGINA,
+ MI_COMET,
+ MI_DELUXO,
+ MI_BURRITO,
+ MI_SPAND,
+ MI_MARQUIS,
+ MI_BAGGAGE,
+ MI_KAUFMAN,
+ MI_MAVERICK,
+ MI_VCNMAV,
+ MI_RANCHER,
+ MI_FBIRANCH,
+ MI_VIRGO,
+ MI_GREENWOO,
+ MI_JETMAX,
+ MI_HOTRING,
+ MI_SANDKING,
+ MI_BLISTAC,
+ MI_POLMAV,
+ MI_BOXVILLE,
+ MI_BENSON,
+ MI_MESA,
+ MI_RCGOBLIN,
+ MI_HOTRINA,
+ MI_HOTRINB,
+ MI_BLOODRA,
+ MI_BLOODRB,
+ MI_VICECHEE,
+ // HACK
+ MI_TRAIN = -1,
+ MI_DODO = -2,
- MI_GRENADE = 170,
- MI_AK47,
- MI_BASEBALL_BAT,
- MI_COLT,
- MI_MOLOTOV,
- MI_ROCKETLAUNCHER,
- MI_SHOTGUN,
- MI_SNIPER,
- MI_UZI,
- MI_MISSILE,
- MI_M16,
- MI_FLAMETHROWER,
- MI_BOMB,
- MI_FINGERS,
+ MI_NIGHTSTICK = 262,
+ MI_BASEBALL_BAT = 264,
+ MI_GRENADE = 270,
+ MI_MOLOTOV = 272,
+ MI_MISSILE = 273,
+ MI_COLT = 274,
+ MI_AK47 = 276,
+ MI_SHOTGUN = 279,
+ MI_M16 = 280,
+ MI_TEC9 = 281,
+ MI_UZI = 282,
+ MI_SILENCEDINGRAM = 283,
+ MI_MP5 = 284,
+ MI_SNIPER = 285,
+ MI_ROCKETLAUNCHER = 287,
+ MI_FLAMETHROWER = 288,
+ MI_BOMB = 291,
+ MI_FINGERS = 293,
- MI_CUTOBJ01 = 185,
+ MI_CUTOBJ01 = 295,
MI_CUTOBJ02,
MI_CUTOBJ03,
MI_CUTOBJ04,
MI_CUTOBJ05,
- MI_CAR_DOOR = 190,
+ MI_CAR_DOOR = 240,
MI_CAR_BUMPER,
MI_CAR_PANEL,
MI_CAR_BONNET,
@@ -355,10 +336,9 @@ enum
MI_BODYPARTA,
MI_BODYPARTB,
- MI_AIRTRAIN_VLO = 198,
- MI_LOPOLYGUY,
+ MI_AIRTRAIN_VLO = 257,
- NUM_DEFAULT_MODELS
+ NUM_DEFAULT_MODELS = 300
};
enum{
@@ -373,24 +353,21 @@ void TestModelIndices(void);
inline bool
IsGlass(int16 id)
{
- return id == MI_GLASS1 ||
- id == MI_GLASS2 ||
- id == MI_GLASS3 ||
- id == MI_GLASS4 ||
- id == MI_GLASS5 ||
- id == MI_GLASS6 ||
- id == MI_GLASS7 ||
- id == MI_GLASS8;
+ CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
+ return mi->IsBuilding() && (mi->m_isCodeGlass || mi->m_isArtistGlass);
}
inline bool
IsStreetLight(int16 id)
{
- return id == MI_TRAFFICLIGHTS ||
- id == MI_SINGLESTREETLIGHTS1 ||
+ return id == MI_SINGLESTREETLIGHTS1 ||
id == MI_SINGLESTREETLIGHTS2 ||
id == MI_SINGLESTREETLIGHTS3 ||
- id == MI_DOUBLESTREETLIGHTS;
+ id == MI_TRAFFICLIGHTS_MIAMI ||
+ id == MI_TRAFFICLIGHTS_TWOVERTICAL ||
+ id == MI_MLAMPPOST ||
+ id == MI_STREETLAMP1 ||
+ id == MI_STREETLAMP2;
}
inline bool
@@ -399,81 +376,32 @@ IsBodyPart(int16 id)
return id == MI_BODYPARTA || id == MI_BODYPARTB;
}
-// This is bad and should perhaps not be used
inline bool
-IsBoatModel(int16 id)
+IsPedModel(int16 id)
{
- return id == MI_PREDATOR ||
- id == MI_REEFER ||
- id == MI_SPEEDER ||
- id == MI_GHOST;
+ return id >= MI_PLAYER && id <= MI_LAST_PED;
}
-
inline bool
-IsPedModel(int16 id)
+IsPalmTreeModel(int16 id)
{
- return id >= MI_PLAYER && id <= MI_LAST_PED;
+ return id == MI_VEG_PALM01 ||
+ id == MI_VEG_PALM02 ||
+ id == MI_VEG_PALM03 ||
+ id == MI_VEG_PALM04 ||
+ id == MI_VEG_PALM05 ||
+ id == MI_VEG_PALM06 ||
+ id == MI_VEG_PALM07 ||
+ id == MI_VEG_PALM08;
}
inline bool
IsTreeModel(int16 id)
{
- return id == MI_TREE1 ||
- id == MI_TREE2 ||
+ return id == MI_TREE2 ||
id == MI_TREE3 ||
- id == MI_TREE4 ||
- id == MI_TREE5 ||
id == MI_TREE6 ||
- id == MI_TREE7 ||
id == MI_TREE8 ||
- id == MI_TREE9 ||
- id == MI_TREE10 ||
- id == MI_TREE11 ||
- id == MI_TREE12 ||
- id == MI_TREE13 ||
- id == MI_TREE14;
-}
-
-inline bool
-IsBannerModel(int16 id)
-{
- return id == MI_CHINABANNER1 ||
- id == MI_CHINABANNER2 ||
- id == MI_CHINABANNER3 ||
- id == MI_CHINABANNER4 ||
- id == MI_CHINABANNER5 ||
- id == MI_CHINABANNER6 ||
- id == MI_CHINABANNER7 ||
- id == MI_CHINABANNER8 ||
- id == MI_CHINABANNER9 ||
- id == MI_CHINABANNER10 ||
- id == MI_CHINABANNER11 ||
- id == MI_CHINABANNER12 ||
- id == MI_ITALYBANNER1 ||
- id == MI_CHINALANTERN;
-}
-inline bool
-IsPickupModel(int16 id)
-{
- return id == MI_GRENADE ||
- id == MI_AK47 ||
- id == MI_BASEBALL_BAT ||
- id == MI_COLT ||
- id == MI_MOLOTOV ||
- id == MI_ROCKETLAUNCHER ||
- id == MI_SHOTGUN ||
- id == MI_SNIPER ||
- id == MI_UZI ||
- id == MI_M16 ||
- id == MI_FLAMETHROWER ||
- id == MI_PICKUP_ADRENALINE ||
- id == MI_PICKUP_BODYARMOUR ||
- id == MI_PICKUP_INFO ||
- id == MI_PICKUP_HEALTH ||
- id == MI_PICKUP_BONUS ||
- id == MI_PICKUP_BRIBE ||
- id == MI_PICKUP_KILLFRENZY ||
- id == MI_PICKUP_CAMERA;
+ IsPalmTreeModel(id);
}
inline bool
diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp
index da09bdfa..3dc048c9 100644
--- a/src/modelinfo/ModelInfo.cpp
+++ b/src/modelinfo/ModelInfo.cpp
@@ -8,13 +8,11 @@
CBaseModelInfo *CModelInfo::ms_modelInfoPtrs[MODELINFOSIZE];
CStore<CSimpleModelInfo, SIMPLEMODELSIZE> CModelInfo::ms_simpleModelStore;
-CStore<CMloModelInfo, MLOMODELSIZE> CModelInfo::ms_mloModelStore;
-CStore<CInstance, MLOINSTANCESIZE> CModelInfo::ms_mloInstanceStore;
CStore<CTimeModelInfo, TIMEMODELSIZE> CModelInfo::ms_timeModelStore;
+CStore<CWeaponModelInfo, WEAPONMODELSIZE> CModelInfo::ms_weaponModelStore;
CStore<CClumpModelInfo, CLUMPMODELSIZE> CModelInfo::ms_clumpModelStore;
CStore<CPedModelInfo, PEDMODELSIZE> CModelInfo::ms_pedModelStore;
CStore<CVehicleModelInfo, VEHICLEMODELSIZE> CModelInfo::ms_vehicleModelStore;
-CStore<CXtraCompsModelInfo, XTRACOMPSMODELSIZE> CModelInfo::ms_xtraCompsModelStore;
CStore<C2dEffect, TWODFXSIZE> CModelInfo::ms_2dEffectStore;
void
@@ -26,11 +24,9 @@ CModelInfo::Initialise(void)
for(i = 0; i < MODELINFOSIZE; i++)
ms_modelInfoPtrs[i] = nil;
ms_2dEffectStore.clear();
- ms_mloInstanceStore.clear();
- ms_xtraCompsModelStore.clear();
ms_simpleModelStore.clear();
ms_timeModelStore.clear();
- ms_mloModelStore.clear();
+ ms_weaponModelStore.clear();
ms_clumpModelStore.clear();
ms_pedModelStore.clear();
ms_vehicleModelStore.clear();
@@ -90,29 +86,23 @@ CModelInfo::ShutDown(void)
int i;
for(i = 0; i < ms_simpleModelStore.allocPtr; i++)
ms_simpleModelStore.store[i].Shutdown();
- for(i = 0; i < ms_mloInstanceStore.allocPtr; i++)
- ms_mloInstanceStore.store[i].Shutdown();
for(i = 0; i < ms_timeModelStore.allocPtr; i++)
ms_timeModelStore.store[i].Shutdown();
+ for(i = 0; i < ms_weaponModelStore.allocPtr; i++)
+ ms_weaponModelStore.store[i].Shutdown();
for(i = 0; i < ms_clumpModelStore.allocPtr; i++)
ms_clumpModelStore.store[i].Shutdown();
for(i = 0; i < ms_vehicleModelStore.allocPtr; i++)
ms_vehicleModelStore.store[i].Shutdown();
for(i = 0; i < ms_pedModelStore.allocPtr; i++)
ms_pedModelStore.store[i].Shutdown();
- for(i = 0; i < ms_xtraCompsModelStore.allocPtr; i++)
- ms_xtraCompsModelStore.store[i].Shutdown();
- for(i = 0; i < ms_mloInstanceStore.allocPtr; i++)
- ms_mloInstanceStore.store[i].Shutdown();
for(i = 0; i < ms_2dEffectStore.allocPtr; i++)
ms_2dEffectStore.store[i].Shutdown();
ms_2dEffectStore.clear();
ms_simpleModelStore.clear();
- ms_mloInstanceStore.clear();
- ms_mloModelStore.clear();
- ms_xtraCompsModelStore.clear();
ms_timeModelStore.clear();
+ ms_weaponModelStore.clear();
ms_pedModelStore.clear();
ms_clumpModelStore.clear();
ms_vehicleModelStore.clear();
@@ -128,23 +118,21 @@ CModelInfo::AddSimpleModel(int id)
return modelinfo;
}
-CMloModelInfo *
-CModelInfo::AddMloModel(int id)
+CTimeModelInfo*
+CModelInfo::AddTimeModel(int id)
{
- CMloModelInfo *modelinfo;
- modelinfo = CModelInfo::ms_mloModelStore.alloc();
+ CTimeModelInfo *modelinfo;
+ modelinfo = CModelInfo::ms_timeModelStore.alloc();
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
- modelinfo->m_clump = nil;
- modelinfo->firstInstance = 0;
- modelinfo->lastInstance = 0;
+ modelinfo->Init();
return modelinfo;
}
-CTimeModelInfo*
-CModelInfo::AddTimeModel(int id)
+CWeaponModelInfo*
+CModelInfo::AddWeaponModel(int id)
{
- CTimeModelInfo *modelinfo;
- modelinfo = CModelInfo::ms_timeModelStore.alloc();
+ CWeaponModelInfo *modelinfo;
+ modelinfo = CModelInfo::ms_weaponModelStore.alloc();
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
modelinfo->Init();
return modelinfo;
@@ -200,6 +188,18 @@ CModelInfo::GetModelInfo(const char *name, int *id)
return nil;
}
+CBaseModelInfo*
+CModelInfo::GetModelInfo(const char *name, int minIndex, int maxIndex)
+{
+ CBaseModelInfo *modelinfo;
+ for(int i = minIndex; i <= maxIndex; i++){
+ modelinfo = CModelInfo::ms_modelInfoPtrs[i];
+ if(modelinfo && !CGeneral::faststricmp(modelinfo->GetName(), name))
+ return modelinfo;
+ }
+ return nil;
+}
+
bool
CModelInfo::IsBoatModel(int32 id)
{
@@ -214,28 +214,11 @@ CModelInfo::IsBikeModel(int32 id)
((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BIKE;
}
-void
-CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
-{
- int i;
- CBaseModelInfo *mi;
- CColModel *colmodel;
-
- for(i = 0; i < MODELINFOSIZE; i++){
- mi = GetModelInfo(i);
- if(mi){
- colmodel = mi->GetColModel();
- if(colmodel && colmodel->level != LEVEL_NONE && colmodel->level != level)
- colmodel->RemoveCollisionVolumes();
- }
- }
-}
-
-void
-CModelInfo::ConstructMloClumps()
+bool
+CModelInfo::IsCarModel(int32 id)
{
- for (int i = 0; i < ms_mloModelStore.allocPtr; i++)
- ms_mloModelStore.store[i].ConstructClump();
+ return GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&
+ ((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_CAR;
}
void
diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h
index 65cfa4e7..a24ba797 100644
--- a/src/modelinfo/ModelInfo.h
+++ b/src/modelinfo/ModelInfo.h
@@ -3,49 +3,45 @@
#include "2dEffect.h"
#include "BaseModelInfo.h"
#include "SimpleModelInfo.h"
-#include "MloModelInfo.h"
#include "TimeModelInfo.h"
+#include "WeaponModelInfo.h"
#include "ClumpModelInfo.h"
#include "PedModelInfo.h"
#include "VehicleModelInfo.h"
-#include "XtraCompsModelInfo.h"
#include "Instance.h"
class CModelInfo
{
static CBaseModelInfo *ms_modelInfoPtrs[MODELINFOSIZE];
static CStore<CSimpleModelInfo, SIMPLEMODELSIZE> ms_simpleModelStore;
- static CStore<CMloModelInfo, MLOMODELSIZE> ms_mloModelStore;
- static CStore<CInstance, MLOINSTANCESIZE> ms_mloInstanceStore;
static CStore<CTimeModelInfo, TIMEMODELSIZE> ms_timeModelStore;
+ static CStore<CWeaponModelInfo, WEAPONMODELSIZE> ms_weaponModelStore;
static CStore<CClumpModelInfo, CLUMPMODELSIZE> ms_clumpModelStore;
static CStore<CPedModelInfo, PEDMODELSIZE> ms_pedModelStore;
static CStore<CVehicleModelInfo, VEHICLEMODELSIZE> ms_vehicleModelStore;
static CStore<C2dEffect, TWODFXSIZE> ms_2dEffectStore;
- static CStore<CXtraCompsModelInfo, XTRACOMPSMODELSIZE> ms_xtraCompsModelStore;
public:
static void Initialise(void);
static void ShutDown(void);
static CSimpleModelInfo *AddSimpleModel(int id);
- static CMloModelInfo *AddMloModel(int id);
static CTimeModelInfo *AddTimeModel(int id);
+ static CWeaponModelInfo *AddWeaponModel(int id);
static CClumpModelInfo *AddClumpModel(int id);
static CPedModelInfo *AddPedModel(int id);
static CVehicleModelInfo *AddVehicleModel(int id);
static CStore<C2dEffect, TWODFXSIZE> &Get2dEffectStore(void) { return ms_2dEffectStore; }
- static CStore<CInstance, MLOINSTANCESIZE> &GetMloInstanceStore(void) { return ms_mloInstanceStore; }
static CBaseModelInfo *GetModelInfo(const char *name, int *id);
static CBaseModelInfo *GetModelInfo(int id){
return ms_modelInfoPtrs[id];
}
+ static CBaseModelInfo *GetModelInfo(const char *name, int minIndex, int maxIndex);
static bool IsBoatModel(int32 id);
static bool IsBikeModel(int32 id);
- static void RemoveColModelsFromOtherLevels(eLevelName level);
- static void ConstructMloClumps();
+ static bool IsCarModel(int32 id);
static void ReInit2dEffects();
};
diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp
index 473e8b63..bf81bd8a 100644
--- a/src/modelinfo/PedModelInfo.cpp
+++ b/src/modelinfo/PedModelInfo.cpp
@@ -9,36 +9,18 @@
#include "VisibilityPlugins.h"
#include "ModelInfo.h"
+//--MIAMI: file done
+
void
CPedModelInfo::DeleteRwObject(void)
{
+ CClumpModelInfo::DeleteRwObject();
if(m_hitColModel)
delete m_hitColModel;
m_hitColModel = nil;
-#ifdef PED_SKIN
- RwFrame *frame;
- if(m_head){
- frame = RpAtomicGetFrame(m_head);
- RpAtomicDestroy(m_head);
- RwFrameDestroy(frame);
- m_head = nil;
- }
- if(m_lhand){
- frame = RpAtomicGetFrame(m_lhand);
- RpAtomicDestroy(m_lhand);
- RwFrameDestroy(frame);
- m_lhand = nil;
- }
- if(m_rhand){
- frame = RpAtomicGetFrame(m_rhand);
- RpAtomicDestroy(m_rhand);
- RwFrameDestroy(frame);
- m_rhand = nil;
- }
-#endif
- CClumpModelInfo::DeleteRwObject(); // PC calls this first
}
+// leftover...
RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = {
{ "Smid", PED_MID, 0, }, // that is strange...
{ "Shead", PED_HEAD, 0, },
@@ -54,131 +36,16 @@ RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = {
{ nil, 0, 0, },
};
-#ifdef PED_SKIN
-struct LimbCBarg
-{
- CPedModelInfo *mi;
- RpClump *clump;
- int32 frameIDs[3];
-};
-
-RpAtomic*
-CPedModelInfo::findLimbsCb(RpAtomic *atomic, void *data)
-{
- LimbCBarg *limbs = (LimbCBarg*)data;
- RwFrame *frame = RpAtomicGetFrame(atomic);
- const char *name = GetFrameNodeName(frame);
- if(CGeneral::faststricmp(name, "Shead01") == 0){
- limbs->frameIDs[0] = RpHAnimFrameGetID(frame);
- limbs->mi->m_head = atomic;
- RpClumpRemoveAtomic(limbs->clump, atomic);
- RwFrameRemoveChild(frame);
- }else if(CGeneral::faststricmp(name, "SLhand01") == 0){
- limbs->frameIDs[1] = RpHAnimFrameGetID(frame);
- limbs->mi->m_lhand = atomic;
- RpClumpRemoveAtomic(limbs->clump, atomic);
- RwFrameRemoveChild(frame);
- }else if(CGeneral::faststricmp(name, "SRhand01") == 0){
- limbs->frameIDs[2] = RpHAnimFrameGetID(frame);
- limbs->mi->m_rhand = atomic;
- RpClumpRemoveAtomic(limbs->clump, atomic);
- RwFrameRemoveChild(frame);
- }
- return atomic;
-}
-#endif
-
void
CPedModelInfo::SetClump(RpClump *clump)
{
-#ifdef PED_SKIN
-
- // CB has to be set here before atomics are detached from clump
- if(strncmp(GetName(), "player", 7) == 0)
- RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
- if(IsClumpSkinned(clump)){
- LimbCBarg limbs = { this, clump, { 0, 0, 0 } };
- RpClumpForAllAtomics(clump, findLimbsCb, &limbs);
- }
- CClumpModelInfo::SetClump(clump);
- SetFrameIds(m_pPedIds);
- if(m_hitColModel == nil && !IsClumpSkinned(clump))
- CreateHitColModel();
- // And again because CClumpModelInfo resets it
- if(strncmp(GetName(), "player", 7) == 0)
- RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
- else if(IsClumpSkinned(clump))
- // skinned peds have no low detail version, so they don't have the right render Cb
- RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB);
-#else
CClumpModelInfo::SetClump(clump);
- SetFrameIds(m_pPedIds);
+ SetFrameIds(m_pPedIds); // not needed in VC actually
if(m_hitColModel == nil)
- CreateHitColModel();
- if(strncmp(GetName(), "player", 7) == 0)
+ CreateHitColModelSkinned(clump);
+ RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB);
+ if(strcmp(GetName(), "player") == 0)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
-#endif
-}
-
-RpAtomic*
-CountAtomicsCB(RpAtomic *atomic, void *data)
-{
- (*(int32*)data)++;
- return atomic;
-}
-
-RpAtomic*
-GetAtomicListCB(RpAtomic *atomic, void *data)
-{
- **(RpAtomic***)data = atomic;
- (*(RpAtomic***)data)++;
- return atomic;
-}
-
-RwFrame*
-FindPedFrameFromNameCB(RwFrame *frame, void *data)
-{
- RwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;
-
- if(CGeneral::faststricmp(GetFrameNodeName(frame)+1, assoc->name+1)){
- RwFrameForAllChildren(frame, FindPedFrameFromNameCB, assoc);
- return assoc->frame ? nil : frame;
- }else{
- assoc->frame = frame;
- return nil;
- }
-}
-
-void
-CPedModelInfo::SetLowDetailClump(RpClump *lodclump)
-{
- RpAtomic *atomics[16];
- RpAtomic **pAtm;
- int32 numAtm, numLodAtm;
- int i;
- RwObjectNameAssociation assoc;
-
- numAtm = 0;
- numLodAtm = 0;
- RpClumpForAllAtomics(m_clump, CountAtomicsCB, &numAtm); // actually unused
- RpClumpForAllAtomics(lodclump, CountAtomicsCB, &numLodAtm);
-
- RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedHiDetailCB);
- RpClumpForAllAtomics(lodclump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedLowDetailCB);
-
- pAtm = atomics;
- RpClumpForAllAtomics(lodclump, GetAtomicListCB, &pAtm);
-
- for(i = 0; i < numLodAtm; i++){
- assoc.name = GetFrameNodeName(RpAtomicGetFrame(atomics[i]));
- assoc.frame = nil;
- RwFrameForAllChildren(RpClumpGetFrame(m_clump), FindPedFrameFromNameCB, &assoc);
- if(assoc.frame){
- RpAtomicSetFrame(atomics[i], assoc.frame);
- RpClumpRemoveAtomic(lodclump, atomics[i]);
- RpClumpAddAtomic(m_clump, atomics[i]);
- }
- }
}
struct ColNodeInfo
@@ -190,126 +57,20 @@ struct ColNodeInfo
float radius;
};
-#define NUMPEDINFONODES 8
+#define NUMPEDINFONODES 10
ColNodeInfo m_pColNodeInfos[NUMPEDINFONODES] = {
- { nil, PED_HEAD, PEDPIECE_HEAD, 0.0f, 0.05f, 0.2f },
- { "Storso", 0, PEDPIECE_TORSO, 0.0f, 0.15f, 0.2f },
- { "Storso", 0, PEDPIECE_TORSO, 0.0f, -0.05f, 0.3f },
- { nil, PED_MID, PEDPIECE_MID, 0.0f, -0.07f, 0.3f },
- { nil, PED_UPPERARML, PEDPIECE_LEFTARM, 0.07f, -0.1f, 0.2f },
- { nil, PED_UPPERARMR, PEDPIECE_RIGHTARM, -0.07f, -0.1f, 0.2f },
- { "Slowerlegl", 0, PEDPIECE_LEFTLEG, 0.0f, 0.07f, 0.25f },
- { nil, PED_LOWERLEGR, PEDPIECE_RIGHTLEG, 0.0f, 0.07f, 0.25f },
+ { nil, PED_HEAD, PEDPIECE_HEAD, 0.0f, 0.05f, 0.15f },
+ { nil, PED_MID, PEDPIECE_TORSO, 0.0f, 0.15f, 0.2f },
+ { nil, PED_MID, PEDPIECE_TORSO, 0.0f, -0.05f, 0.25f },
+ { nil, PED_MID, PEDPIECE_MID, 0.0f, -0.25f, 0.25f },
+ { nil, PED_UPPERARML, PEDPIECE_LEFTARM, 0.03f, -0.05f, 0.16f },
+ { nil, PED_UPPERARMR, PEDPIECE_RIGHTARM, -0.03f, -0.05f, 0.16f },
+ { nil, PED_LOWERLEGL, PEDPIECE_LEFTLEG, 0.0f, 0.15f, 0.2f },
+ { nil, PED_LOWERLEGR, PEDPIECE_RIGHTLEG, 0.0f, 0.15f, 0.2f },
+ { nil, PED_FOOTL, PEDPIECE_LEFTLEG, 0.0f, 0.15f, 0.15f },
+ { nil, PED_FOOTR, PEDPIECE_RIGHTLEG, 0.0f, 0.15f, 0.15f },
};
-RwObject*
-FindHeadRadiusCB(RwObject *object, void *data)
-{
- RpAtomic *atomic = (RpAtomic*)object;
- *(float*)data = RpAtomicGetBoundingSphere(atomic)->radius;
- return nil;
-}
-
-void
-CPedModelInfo::CreateHitColModel(void)
-{
- RwObjectNameAssociation nameAssoc;
- RwObjectIdAssociation idAssoc;
- CVector center;
- RwFrame *nodeFrame;
- CColModel *colmodel = new CColModel;
- CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere));
- RwFrame *root = RpClumpGetFrame(m_clump);
- RwMatrix *mat = RwMatrixCreate();
- for(int i = 0; i < NUMPEDINFONODES; i++){
- nodeFrame = nil;
- if(m_pColNodeInfos[i].name){
- nameAssoc.name = m_pColNodeInfos[i].name;
- nameAssoc.frame = nil;
- RwFrameForAllChildren(root, FindFrameFromNameCB, &nameAssoc);
- nodeFrame = nameAssoc.frame;
- }else{
- idAssoc.id = m_pColNodeInfos[i].pedNode;
- idAssoc.frame = nil;
- RwFrameForAllChildren(root, FindFrameFromIdCB, &idAssoc);
- nodeFrame = idAssoc.frame;
- }
- if(nodeFrame){
- float radius = m_pColNodeInfos[i].radius;
- if(m_pColNodeInfos[i].pieceType == PEDPIECE_HEAD)
- RwFrameForAllObjects(nodeFrame, FindHeadRadiusCB, &radius);
- RwMatrixTransform(mat, RwFrameGetMatrix(nodeFrame), rwCOMBINEREPLACE);
- const char *name = GetFrameNodeName(nodeFrame);
- for(nodeFrame = RwFrameGetParent(nodeFrame);
- nodeFrame;
- nodeFrame = RwFrameGetParent(nodeFrame)){
- name = GetFrameNodeName(nodeFrame);
- RwMatrixTransform(mat, RwFrameGetMatrix(nodeFrame), rwCOMBINEPOSTCONCAT);
- if(RwFrameGetParent(nodeFrame) == root)
- break;
- }
- center.x = mat->pos.x + m_pColNodeInfos[i].x;
- center.y = mat->pos.y + 0.0f;
- center.z = mat->pos.z + m_pColNodeInfos[i].z;
- spheres[i].Set(radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType);
- }
- }
- RwMatrixDestroy(mat);
- colmodel->spheres = spheres;
- colmodel->numSpheres = NUMPEDINFONODES;
- center.x = center.y = center.z = 0.0f;
- colmodel->boundingSphere.Set(2.0f, center, 0, 0);
- CVector min, max;
- min.x = min.y = -0.5f;
- min.z = -1.2f;
- max.x = max.y = 0.5f;
- max.z = 1.2f;
- colmodel->boundingBox.Set(min, max, 0, 0);
- colmodel->level = LEVEL_NONE;
- m_hitColModel = colmodel;
-}
-
-CColModel*
-CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame)
-{
- RwObjectNameAssociation nameAssoc;
- RwObjectIdAssociation idAssoc;
- RwMatrix* mat = RwMatrixCreate();
- CColSphere* spheres = colmodel->spheres;
-
- for (int i = 0; i < NUMPEDINFONODES; i++) {
- RwFrame* f = nil;
- if (m_pColNodeInfos[i].name) {
- nameAssoc.name = m_pColNodeInfos[i].name;
- nameAssoc.frame = nil;
- RwFrameForAllChildren(frame, FindFrameFromNameCB, &nameAssoc);
- f = nameAssoc.frame;
- }
- else {
- idAssoc.id = m_pColNodeInfos[i].pedNode;
- idAssoc.frame = nil;
- RwFrameForAllChildren(frame, FindFrameFromIdCB, &idAssoc);
- f = idAssoc.frame;
- }
- if (f) {
- RwMatrixCopy(mat, RwFrameGetMatrix(f));
-
- for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) {
- RwMatrixTransform(mat, RwFrameGetMatrix(f), rwCOMBINEPOSTCONCAT);
- if (RwFrameGetParent(f) == frame)
- break;
- }
-
- spheres[i].center.x = mat->pos.x + m_pColNodeInfos[i].x;
- spheres[i].center.y = mat->pos.y + 0.0f;
- spheres[i].center.z = mat->pos.z + m_pColNodeInfos[i].z;
- }
- }
-
- return colmodel;
-}
-
-#ifdef PED_SKIN
void
CPedModelInfo::CreateHitColModelSkinned(RpClump *clump)
{
@@ -342,13 +103,13 @@ CPedModelInfo::CreateHitColModelSkinned(RpClump *clump)
colmodel->spheres = spheres;
colmodel->numSpheres = NUMPEDINFONODES;
center.x = center.y = center.z = 0.0f;
- colmodel->boundingSphere.Set(2.0f, center, 0, 0);
+ colmodel->boundingSphere.Set(2.0f, center);
CVector min, max;
min.x = min.y = -0.5f;
min.z = -1.2f;
max.x = max.y = 0.5f;
max.z = 1.2f;
- colmodel->boundingBox.Set(min, max, 0, 0);
+ colmodel->boundingBox.Set(min, max);
colmodel->level = LEVEL_NONE;
m_hitColModel = colmodel;
}
@@ -385,4 +146,26 @@ CPedModelInfo::AnimatePedColModelSkinned(RpClump *clump)
return m_hitColModel;
}
-#endif
+CColModel*
+CPedModelInfo::AnimatePedColModelSkinnedWorld(RpClump *clump)
+{
+ if(m_hitColModel == nil)
+ CreateHitColModelSkinned(clump);
+ CColSphere *spheres = m_hitColModel->spheres;
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);
+ RwMatrix *mat;
+
+ for(int i = 0; i < NUMPEDINFONODES; i++){
+ int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode);
+ int idx = RpHAnimIDGetIndex(hier, id);
+
+ mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+ RwV3dTransformPoints(&pos, &pos, 1, mat);
+
+ spheres[i].center.x = pos.x + m_pColNodeInfos[i].x;
+ spheres[i].center.y = pos.y + 0.0f;
+ spheres[i].center.z = pos.z + m_pColNodeInfos[i].z;
+ }
+ return m_hitColModel;
+}
diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h
index d73d3646..e878a59b 100644
--- a/src/modelinfo/PedModelInfo.h
+++ b/src/modelinfo/PedModelInfo.h
@@ -5,8 +5,8 @@
#include "PedStats.h"
enum PedNode {
- PED_TORSO,
- PED_MID, // Smid on PS2/PC, Storso on mobile/xbox
+ PED_TORSO = 0, // has no bone!
+ PED_MID,
PED_HEAD,
PED_UPPERARML,
PED_UPPERARMR,
@@ -17,7 +17,15 @@ enum PedNode {
PED_FOOTL,
PED_FOOTR,
PED_LOWERLEGR,
- PED_NODE_MAX// Not valid: PED_LOWERLEGL
+ PED_LOWERLEGL,
+
+ PED_FOREARML,
+ PED_FOREARMR,
+ PED_CLAVICLEL,
+ PED_CLAVICLER,
+ PED_NECK,
+
+ PED_NODE_MAX
};
class CPedModelInfo : public CClumpModelInfo
@@ -28,40 +36,17 @@ public:
ePedStats m_pedStatType;
uint32 m_carsCanDrive;
CColModel *m_hitColModel;
-#ifdef PED_SKIN
- RpAtomic *m_head;
- RpAtomic *m_lhand;
- RpAtomic *m_rhand;
-#endif
+ int8 radio1, radio2;
static RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX];
- CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) {
- m_hitColModel = nil;
-#ifdef PED_SKIN
- m_head = nil;
- m_lhand = nil;
- m_rhand = nil;
-#endif
- }
+ CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { m_hitColModel = nil; }
~CPedModelInfo(void) { delete m_hitColModel; }
void DeleteRwObject(void);
void SetClump(RpClump *);
- void SetLowDetailClump(RpClump*);
- void CreateHitColModel(void);
void CreateHitColModelSkinned(RpClump *clump);
CColModel *GetHitColModel(void) { return m_hitColModel; }
- static CColModel *AnimatePedColModel(CColModel* colmodel, RwFrame* frame);
CColModel *AnimatePedColModelSkinned(RpClump *clump);
-
-#ifdef PED_SKIN
- static RpAtomic *findLimbsCb(RpAtomic *atomic, void *data);
- RpAtomic *getHead(void) { return m_head; }
- RpAtomic *getLeftHand(void) { return m_lhand; }
- RpAtomic *getRightHand(void) { return m_rhand; }
-#endif
+ CColModel *AnimatePedColModelSkinnedWorld(RpClump *clump);
};
-#ifndef PED_SKIN
-VALIDATE_SIZE(CPedModelInfo, 0x48);
-#endif \ No newline at end of file
diff --git a/src/modelinfo/SimpleModelInfo.cpp b/src/modelinfo/SimpleModelInfo.cpp
index a781cf58..a7e6d56c 100644
--- a/src/modelinfo/SimpleModelInfo.cpp
+++ b/src/modelinfo/SimpleModelInfo.cpp
@@ -3,6 +3,9 @@
#include "General.h"
#include "Camera.h"
#include "ModelInfo.h"
+#include "AnimManager.h"
+
+//--MIAMI: file done
#define LOD_DISTANCE (300.0f)
@@ -18,6 +21,8 @@ CSimpleModelInfo::DeleteRwObject(void)
RwFrameDestroy(f);
m_atomics[i] = nil;
RemoveTexDictionaryRef();
+ if(GetAnimFileIndex() != -1)
+ CAnimManager::RemoveAnimBlockRef(GetAnimFileIndex());
}
}
@@ -55,7 +60,7 @@ CSimpleModelInfo::Init(void)
m_atomics[2] = nil;
m_numAtomics = 0;
m_firstDamaged = 0;
- m_normalCull = 0;
+ m_wetRoadReflection = 0;
m_isDamaged = 0;
m_isBigBuilding = 0;
m_noFade = 0;
@@ -64,6 +69,10 @@ CSimpleModelInfo::Init(void)
m_isSubway = 0;
m_ignoreLight = 0;
m_noZwrite = 0;
+ m_noShadows = 0;
+ m_ignoreDrawDist = 0;
+ m_isCodeGlass = 0;
+ m_isArtistGlass = 0;
}
void
@@ -71,10 +80,14 @@ CSimpleModelInfo::SetAtomic(int n, RpAtomic *atomic)
{
AddTexDictionaryRef();
m_atomics[n] = atomic;
- if(m_ignoreLight){
- RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ if(GetAnimFileIndex() != -1)
+ CAnimManager::AddAnimBlockRef(GetAnimFileIndex());
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ if(m_ignoreLight)
RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) & ~rpGEOMETRYLIGHT);
- }
+ if(RpGeometryGetFlags(geo) & rpGEOMETRYNORMALS &&
+ RpGeometryGetNumTriangles(geo) > 200)
+ debug("%s has %d polys\n", m_name, RpGeometryGetNumTriangles(geo));
}
void
@@ -130,12 +143,20 @@ CSimpleModelInfo::GetAtomicFromDistance(float dist)
return nil;
}
+RpAtomic*
+CSimpleModelInfo::GetFirstAtomicFromDistance(float dist)
+{
+ if(dist < m_lodDistances[0] * TheCamera.LODDistMultiplier)
+ return m_atomics[0];
+ return nil;
+}
+
void
-CSimpleModelInfo::FindRelatedModel(void)
+CSimpleModelInfo::FindRelatedModel(int32 minID, int32 maxID)
{
int i;
CBaseModelInfo *mi;
- for(i = 0; i < MODELINFOSIZE; i++){
+ for(i = minID; i <= maxID; i++){
mi = CModelInfo::GetModelInfo(i);
if(mi && mi != this &&
!CGeneral::faststrcmp(GetName()+3, mi->GetName()+3)){
@@ -146,17 +167,23 @@ CSimpleModelInfo::FindRelatedModel(void)
}
}
+#define NEAR_DRAW_DIST 0.0f // 100.0f in liberty city
+
void
-CSimpleModelInfo::SetupBigBuilding(void)
+CSimpleModelInfo::SetupBigBuilding(int32 minID, int32 maxID)
{
CSimpleModelInfo *related;
if(m_lodDistances[0] > LOD_DISTANCE && GetRelatedModel() == nil){
m_isBigBuilding = 1;
- FindRelatedModel();
+ FindRelatedModel(minID, maxID);
related = GetRelatedModel();
- if(related)
+ if(related){
m_lodDistances[2] = related->GetLargestLodDistance()/TheCamera.LODDistMultiplier;
- else
- m_lodDistances[2] = 100.0f;
+ if(m_drawLast){
+ m_drawLast = false;
+ debug("%s was draw last\n", GetName());
+ }
+ }else
+ m_lodDistances[2] = NEAR_DRAW_DIST;
}
}
diff --git a/src/modelinfo/SimpleModelInfo.h b/src/modelinfo/SimpleModelInfo.h
index ee63f24b..986cb886 100644
--- a/src/modelinfo/SimpleModelInfo.h
+++ b/src/modelinfo/SimpleModelInfo.h
@@ -14,15 +14,22 @@ public:
uint16 m_firstDamaged : 2; // 0: no damage model
// 1: 1 and 2 are damage models
// 2: 2 is damage model
- uint16 m_normalCull : 1;
+ uint16 m_wetRoadReflection : 1;
uint16 m_isDamaged : 1;
+
uint16 m_isBigBuilding : 1;
uint16 m_noFade : 1;
uint16 m_drawLast : 1;
uint16 m_additive : 1;
+
uint16 m_isSubway : 1;
uint16 m_ignoreLight : 1;
uint16 m_noZwrite : 1;
+ uint16 m_noShadows : 1;
+
+ uint16 m_ignoreDrawDist : 1;
+ uint16 m_isCodeGlass : 1;
+ uint16 m_isArtistGlass : 1;
CSimpleModelInfo(void) : CBaseModelInfo(MITYPE_SIMPLE) {}
CSimpleModelInfo(ModelInfoType id) : CBaseModelInfo(id) {}
@@ -32,16 +39,18 @@ public:
RwObject *CreateInstance(RwMatrix *);
RwObject *GetRwObject(void) { return (RwObject*)m_atomics[0]; }
+ virtual void SetAtomic(int n, RpAtomic *atomic);
+
void Init(void);
void IncreaseAlpha(void);
- void SetAtomic(int n, RpAtomic *atomic);
void SetLodDistances(float *dist);
float GetLodDistance(int i);
float GetNearDistance(void);
float GetLargestLodDistance(void);
RpAtomic *GetAtomicFromDistance(float dist);
- void FindRelatedModel(void);
- void SetupBigBuilding(void);
+ RpAtomic *GetFirstAtomicFromDistance(float dist);
+ void FindRelatedModel(int32 minID, int32 maxID);
+ void SetupBigBuilding(int32 minID, int32 maxID);
void SetNumAtomics(int n) { m_numAtomics = n; }
CSimpleModelInfo *GetRelatedModel(void){
@@ -49,5 +58,4 @@ public:
void SetRelatedModel(CSimpleModelInfo *m){
m_atomics[2] = (RpAtomic*)m; }
};
-
-VALIDATE_SIZE(CSimpleModelInfo, 0x4C);
+//static_assert(sizeof(CSimpleModelInfo) == 0x4C, "CSimpleModelInfo: error");
diff --git a/src/modelinfo/TimeModelInfo.h b/src/modelinfo/TimeModelInfo.h
index 73b6ab26..6e3c64fb 100644
--- a/src/modelinfo/TimeModelInfo.h
+++ b/src/modelinfo/TimeModelInfo.h
@@ -17,5 +17,4 @@ public:
void SetOtherTimeModel(int32 other) { m_otherTimeModelID = other; }
CTimeModelInfo *FindOtherTimeModel(void);
};
-
-VALIDATE_SIZE(CTimeModelInfo, 0x58);
+//static_assert(sizeof(CTimeModelInfo) == 0x58, "CTimeModelInfo: error");
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index 74285c19..d80fc4cf 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -16,12 +16,14 @@
#include "Train.h"
#include "Plane.h"
#include "Heli.h"
+#include "Bike.h"
#include "ModelIndices.h"
#include "ModelInfo.h"
+//--MIAMI: done
+
int8 CVehicleModelInfo::ms_compsToUse[2] = { -2, -2 };
int8 CVehicleModelInfo::ms_compsUsed[2];
-RwTexture *CVehicleModelInfo::ms_pEnvironmentMaps[NUM_VEHICLE_ENVMAPS];
RwRGBA CVehicleModelInfo::ms_vehicleColourTable[256];
RwTexture *CVehicleModelInfo::ms_colourTextureTable[256];
@@ -81,9 +83,13 @@ RwObjectNameIdAssocation carIds[] = {
};
RwObjectNameIdAssocation boatIds[] = {
- { "boat_moving_hi", BOAT_MOVING, VEHICLE_FLAG_COLLAPSE },
- { "boat_rudder_hi", BOAT_RUDDER, VEHICLE_FLAG_COLLAPSE },
- { "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE },
+ { "boat_moving_hi", BOAT_MOVING, 0 },
+ { "boat_rudder_hi", BOAT_RUDDER, 0 },
+ { "boat_flap_left", BOAT_FLAP_LEFT, 0 },
+ { "boat_flap_right", BOAT_FLAP_RIGHT, 0 },
+ { "boat_rearflap_left", BOAT_REARFLAP_LEFT, 0 },
+ { "boat_rearflap_right", BOAT_REARFLAP_RIGHT, 0 },
+ { "windscreen_hi_ok", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST },
{ "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
{ nil, 0, 0 }
};
@@ -120,16 +126,18 @@ RwObjectNameIdAssocation planeIds[] = {
};
RwObjectNameIdAssocation bikeIds[] = {
- { "chassis_dummy", 1, 0 },
- { "forks_front", 2, 0 },
- { "forks_rear", 3, 0 },
- { "wheel_front", 4, 0 },
- { "wheel_rear", 5, 0 },
- { "mudguard", 6, 0 },
- { "ped_frontseat", 2, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
- { "headlights", 0, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
- { "taillights", 1, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
- { "exhaust", 9, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
+ { "chassis_dummy", BIKE_CHASSIS, 0 },
+ { "forks_front", BIKE_FORKS_FRONT, 0 },
+ { "forks_rear", BIKE_FORKS_REAR, 0 },
+ { "wheel_front", BIKE_WHEEL_FRONT, 0 },
+ { "wheel_rear", BIKE_WHEEL_REAR, 0 },
+ { "mudguard", BIKE_MUDGUARD, 0 },
+ { "handlebars", BIKE_HANDLEBARS, 0 },
+ { "ped_frontseat", BIKE_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
+ { "ped_backseat", BIKE_POS_BACKSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
+ { "headlights", BIKE_POS_HEADLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
+ { "taillights", BIKE_POS_TAILLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
+ { "exhaust", BIKE_POS_EXHAUST, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
{ "extra1", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
{ "extra2", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
{ "extra3", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
@@ -148,6 +156,8 @@ RwObjectNameIdAssocation *CVehicleModelInfo::ms_vehicleDescs[] = {
bikeIds
};
+bool gbBlackCars;
+bool gbPinkCars;
CVehicleModelInfo::CVehicleModelInfo(void)
: CClumpModelInfo(MITYPE_VEHICLE)
@@ -159,6 +169,7 @@ CVehicleModelInfo::CVehicleModelInfo(void)
m_positions[i].z = 0.0f;
}
m_numColours = 0;
+ m_animFileIndex = -1;
}
void
@@ -228,10 +239,30 @@ CVehicleModelInfo::SetClump(RpClump *clump)
SetFrameIds(ms_vehicleDescs[m_vehicleType]);
PreprocessHierarchy();
FindEditableMaterialList();
- m_envMap = nil;
SetEnvironmentMap();
}
+void
+CVehicleModelInfo::SetAnimFile(const char *file)
+{
+ if(strcasecmp(file, "null") == 0)
+ return;
+
+ m_animFileName = new char[strlen(file)+1];
+ strcpy(m_animFileName, file);
+}
+
+void
+CVehicleModelInfo::ConvertAnimFileIndex(void)
+{
+ if(m_animFileIndex != -1){
+ // we have a string pointer in that union
+ int32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName);
+ delete[] m_animFileName;
+ m_animFileIndex = index;
+ }
+}
+
RwFrame*
CVehicleModelInfo::CollapseFramesCB(RwFrame *frame, void *data)
{
@@ -384,30 +415,68 @@ CVehicleModelInfo::SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data)
RpAtomic*
CVehicleModelInfo::SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data)
{
- CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
+ char *name;
+
+ name = GetFrameNodeName(RpAtomicGetFrame(atomic));
+ if(strncmp(name, "toprotor", 8) == 0)
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleRotorAlphaCB);
+ else if(strncmp(name, "rearrotor", 9) == 0)
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleTailRotorAlphaCB);
+ else
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
+ return atomic;
+}
+
+RpAtomic*
+CVehicleModelInfo::SetAtomicRendererCB_RealHeli(RpAtomic *atomic, void *data)
+{
+ RpClump *clump;
+ char *name;
+ bool alpha;
+
+ clump = (RpClump*)data;
+ name = GetFrameNodeName(RpAtomicGetFrame(atomic));
+ alpha = false;
+ RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);
+ if(strncmp(name, "toprotor", 8) == 0)
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleRotorAlphaCB);
+ else if(strncmp(name, "rearrotor", 9) == 0)
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleTailRotorAlphaCB);
+ else if(strstr(name, "_hi") || strncmp(name, "extra", 5) == 0){
+ if(alpha || strncmp(name, "windscreen", 10) == 0)
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB);
+ else
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB);
+ }else if(strstr(name, "_lo")){
+ RpClumpRemoveAtomic(clump, atomic);
+ RpAtomicDestroy(atomic);
+ return atomic; // BUG: not done by gta
+ }else if(strstr(name, "_vlo"))
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB);
+ else
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
+ HideDamagedAtomicCB(atomic, nil);
return atomic;
}
void
CVehicleModelInfo::SetAtomicRenderCallbacks(void)
{
- switch(m_vehicleType){
- case VEHICLE_TYPE_TRAIN:
+#ifdef GTA_TRAIN
+ if(m_vehicleType == VEHICLE_TYPE_TRAIN)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Train, nil);
- break;
- case VEHICLE_TYPE_HELI:
+ else
+#endif
+ if(m_vehicleType == VEHICLE_TYPE_HELI)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Heli, nil);
- break;
- case VEHICLE_TYPE_PLANE:
+ else if(m_vehicleType == VEHICLE_TYPE_PLANE)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_BigVehicle, nil);
- break;
- case VEHICLE_TYPE_BOAT:
+ else if(m_vehicleType == VEHICLE_TYPE_BOAT)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Boat, m_clump);
- break;
- default:
+ else if(mod_HandlingManager.GetHandlingData((eHandlingId)m_handlingId)->Flags & HANDLING_IS_HELI)
+ RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_RealHeli, m_clump);
+ else
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, m_clump);
- break;
- }
}
RwObject*
@@ -604,6 +673,13 @@ ChooseComponent(int32 rule, int32 comps)
// only valid in rain
n = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps));
return COMPRULE_COMPN(comps, n);
+ case 3:
+ n = CGeneral::GetRandomNumberInRange(0, 1+CountCompsInRule(comps));
+ if(n != 0)
+ return COMPRULE_COMPN(comps, n-1);
+ return -1;
+ case 4:
+ return CGeneral::GetRandomNumberInRange(0, 5);
}
return -1;
}
@@ -730,6 +806,9 @@ CVehicleModelInfo::GetEditableMaterialListCB(RpAtomic *atomic, void *data)
return atomic;
}
+static int maxFirstMaterials;
+static int maxSecondMaterials;
+
void
CVehicleModelInfo::FindEditableMaterialList(void)
{
@@ -744,6 +823,8 @@ CVehicleModelInfo::FindEditableMaterialList(void)
GetEditableMaterialListCB(m_comps[i], &cbdata);
m_materials1[cbdata.numMats1] = nil;
m_materials2[cbdata.numMats2] = nil;
+ maxFirstMaterials = Max(maxFirstMaterials, cbdata.numMats1);
+ maxSecondMaterials = Max(maxSecondMaterials, cbdata.numMats2);
m_currentColour1 = -1;
m_currentColour2 = -1;
}
@@ -752,35 +833,26 @@ void
CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
{
RwRGBA col, *colp;
- RwTexture *coltex;
RpMaterial **matp;
if(c1 != m_currentColour1){
col = ms_vehicleColourTable[c1];
- coltex = ms_colourTextureTable[c1];
for(matp = m_materials1; *matp; matp++){
- if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
- colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
- colp->red = col.red;
- colp->green = col.green;
- colp->blue = col.blue;
- }else
- RpMaterialSetTexture(*matp, coltex);
+ colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
+ colp->red = col.red;
+ colp->green = col.green;
+ colp->blue = col.blue;
}
m_currentColour1 = c1;
}
if(c2 != m_currentColour2){
col = ms_vehicleColourTable[c2];
- coltex = ms_colourTextureTable[c2];
for(matp = m_materials2; *matp; matp++){
- if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
- colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
- colp->red = col.red;
- colp->green = col.green;
- colp->blue = col.blue;
- }else
- RpMaterialSetTexture(*matp, coltex);
+ colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
+ colp->red = col.red;
+ colp->green = col.green;
+ colp->blue = col.blue;
}
m_currentColour2 = c2;
}
@@ -789,9 +861,12 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
void
CVehicleModelInfo::ChooseVehicleColour(uint8 &col1, uint8 &col2)
{
- if(m_numColours == 0){
+ if(m_numColours == 0 || gbBlackCars){
col1 = 0;
col2 = 0;
+ }else if(gbPinkCars){
+ col1 = 68;
+ col2 = 68;
}else{
m_lastColorVariation = (m_lastColorVariation+1) % m_numColours;
col1 = m_colours1[m_lastColorVariation];
@@ -814,18 +889,27 @@ CVehicleModelInfo::AvoidSameVehicleColour(uint8 *col1, uint8 *col2)
{
int i, n;
- if(m_numColours > 1)
- for(i = 0; i < 8; i++){
- if(*col1 != m_lastColour1 || *col2 != m_lastColour2)
- break;
- n = CGeneral::GetRandomNumberInRange(0, m_numColours);
- *col1 = m_colours1[n];
- *col2 = m_colours2[n];
- }
- m_lastColour1 = *col1;
- m_lastColour2 = *col2;
+ if(gbBlackCars){
+ *col1 = 0;
+ *col2 = 0;
+ }else if(gbPinkCars){
+ *col1 = 68;
+ *col2 = 68;
+ }else{
+ if(m_numColours > 1)
+ for(i = 0; i < 8; i++){
+ if(*col1 != m_lastColour1 || *col2 != m_lastColour2)
+ break;
+ n = CGeneral::GetRandomNumberInRange(0, m_numColours);
+ *col1 = m_colours1[n];
+ *col2 = m_colours2[n];
+ }
+ m_lastColour1 = *col1;
+ m_lastColour2 = *col2;
+ }
}
+//--MIAMI: unused
RwTexture*
CreateCarColourTexture(uint8 r, uint8 g, uint8 b)
{
@@ -925,7 +1009,6 @@ CVehicleModelInfo::LoadVehicleColours(void)
ms_vehicleColourTable[numCols].green = g;
ms_vehicleColourTable[numCols].blue = b;
ms_vehicleColourTable[numCols].alpha = 0xFF;
- ms_colourTextureTable[numCols] = CreateCarColourTexture(r, g, b);
numCols++;
}else if(section == CARS){
n = sscanf(&line[start], // BUG: games doesn't add start
@@ -960,38 +1043,33 @@ CVehicleModelInfo::DeleteVehicleColourTextures(void)
for(i = 0; i < 256; i++){
if(ms_colourTextureTable[i]){
RwTextureDestroy(ms_colourTextureTable[i]);
-#ifdef GTA3_1_1_PATCH
ms_colourTextureTable[i] = nil;
-#endif
}
}
}
RpMaterial*
-CVehicleModelInfo::HasSpecularMaterialCB(RpMaterial *material, void *data)
+CVehicleModelInfo::GetMatFXEffectMaterialCB(RpMaterial *material, void *data)
{
- if(RpMaterialGetSurfaceProperties(material)->specular <= 0.0f)
+ if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTNULL)
return material;
- *(bool*)data = true;
+ *(int*)data = RpMatFXMaterialGetEffects(material);
return nil;
}
RpMaterial*
-CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial *material, void *data)
+CVehicleModelInfo::SetDefaultEnvironmentMapCB(RpMaterial *material, void *data)
{
- float spec;
-
- spec = RpMaterialGetSurfaceProperties(material)->specular;
- if(spec <= 0.0f)
- RpMatFXMaterialSetEffects(material, rpMATFXEFFECTNULL);
- else{
+ if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTENVMAP){
+ RpMatFXMaterialSetEnvMapFrame(material, pMatFxIdentityFrame);
if(RpMaterialGetTexture(material) == nil)
RpMaterialSetTexture(material, gpWhiteTexture);
RpMatFXMaterialSetEffects(material, rpMATFXEFFECTENVMAP);
#ifndef PS2_MATFX
- spec *= 0.5f; // Tone down a bit for PC
+ float coef = RpMatFXMaterialGetEnvMapCoefficient(material);
+ coef *= 0.25f; // Tone down a bit for PC
+ RpMatFXMaterialSetEnvMapCoefficient(material, coef);
#endif
- RpMatFXMaterialSetupEnvMap(material, (RwTexture*)data, pMatFxIdentityFrame, false, spec);
}
return material;
}
@@ -999,17 +1077,15 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial *material, void *data)
RpAtomic*
CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data)
{
- bool hasSpec;
+ int fx;
RpGeometry *geo;
geo = RpAtomicGetGeometry(atomic);
- hasSpec = 0;
- RpGeometryForAllMaterials(geo, HasSpecularMaterialCB, &hasSpec);
- if(hasSpec){
- RpGeometryForAllMaterials(geo, SetEnvironmentMapCB, data);
- RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR);
+ fx = 0;
+ RpGeometryForAllMaterials(geo, GetMatFXEffectMaterialCB, &fx);
+ if(fx != rpMATFXEFFECTNULL){
RpMatFXAtomicEnableEffects(atomic);
- // PS2 sets of PS2Manager lighting CB here
+ RpGeometryForAllMaterials(geo, SetDefaultEnvironmentMapCB, data);
}
return atomic;
}
@@ -1021,44 +1097,29 @@ CVehicleModelInfo::SetEnvironmentMap(void)
int32 i;
if(pMatFxIdentityFrame == nil){
+ RwV3d axis = { 1.0f, 0.0f, 0.0f };
pMatFxIdentityFrame = RwFrameCreate();
- RwMatrixSetIdentity(RwFrameGetMatrix(pMatFxIdentityFrame));
+ RwMatrixRotate(RwFrameGetMatrix(pMatFxIdentityFrame), &axis, 60.0f, rwCOMBINEREPLACE);
RwFrameUpdateObjects(pMatFxIdentityFrame);
RwFrameGetLTM(pMatFxIdentityFrame);
}
- if(m_envMap != ms_pEnvironmentMaps[0]){
- m_envMap = ms_pEnvironmentMaps[0];
- RpClumpForAllAtomics(m_clump, SetEnvironmentMapCB, m_envMap);
- if(m_wheelId != -1){
- wheelmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_wheelId);
- for(i = 0; i < wheelmi->m_numAtomics; i++)
- SetEnvironmentMapCB(wheelmi->m_atomics[i], m_envMap);
- }
+ RpClumpForAllAtomics(m_clump, SetEnvironmentMapCB, nil);
+ if(m_wheelId != -1){
+ wheelmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_wheelId);
+ for(i = 0; i < wheelmi->m_numAtomics; i++)
+ SetEnvironmentMapCB(wheelmi->m_atomics[i], nil);
}
}
void
CVehicleModelInfo::LoadEnvironmentMaps(void)
{
- const char *texnames[] = {
- "reflection01", // only one used
- "reflection02",
- "reflection03",
- "reflection04",
- "reflection05",
- "reflection06",
- };
int32 txdslot;
- int32 i;
txdslot = CTxdStore::FindTxdSlot("particle");
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(txdslot);
- for(i = 0; i < NUM_VEHICLE_ENVMAPS; i++){
- ms_pEnvironmentMaps[i] = RwTextureRead(texnames[i], nil);
- RwTextureSetFilterMode(ms_pEnvironmentMaps[i], rwFILTERLINEAR);
- }
if(gpWhiteTexture == nil){
gpWhiteTexture = RwTextureRead("white", nil);
RwTextureGetName(gpWhiteTexture)[0] = '@';
@@ -1070,14 +1131,8 @@ CVehicleModelInfo::LoadEnvironmentMaps(void)
void
CVehicleModelInfo::ShutdownEnvironmentMaps(void)
{
- int32 i;
-
- // ignoring "initialised" as that's a PS2 thing only
RwTextureDestroy(gpWhiteTexture);
gpWhiteTexture = nil;
- for(i = 0; i < NUM_VEHICLE_ENVMAPS; i++)
- if(ms_pEnvironmentMaps[i])
- RwTextureDestroy(ms_pEnvironmentMaps[i]);
RwFrameDestroy(pMatFxIdentityFrame);
pMatFxIdentityFrame = nil;
}
@@ -1094,12 +1149,15 @@ CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(int id)
case MI_FIRETRUCK:
n = 2;
break;
+ case MI_HUNTER:
+ n = 1;
+ break;
default:
n = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(id))->m_numDoors;
}
if(n == 0)
- return id == MI_RCBANDIT ? 0 : 1;
+ return id == MI_RCBANDIT || id == MI_PIZZABOY || id == MI_BAGGAGE ? 0 : 1;
if(id == MI_COACH)
return 8;
diff --git a/src/modelinfo/VehicleModelInfo.h b/src/modelinfo/VehicleModelInfo.h
index ba25d3cd..5ee6d263 100644
--- a/src/modelinfo/VehicleModelInfo.h
+++ b/src/modelinfo/VehicleModelInfo.h
@@ -3,10 +3,9 @@
#include "ClumpModelInfo.h"
enum {
- NUM_FIRST_MATERIALS = 26,
- NUM_SECOND_MATERIALS = 26,
+ NUM_FIRST_MATERIALS = 24,
+ NUM_SECOND_MATERIALS = 20,
NUM_VEHICLE_COLOURS = 8,
- NUM_VEHICLE_ENVMAPS = 1
};
enum {
@@ -36,7 +35,7 @@ enum eVehicleType {
};
enum {
- NUM_VEHICLE_POSITIONS = 10
+ NUM_VEHICLE_POSITIONS = 5
};
class CVehicleModelInfo : public CClumpModelInfo
@@ -44,17 +43,19 @@ class CVehicleModelInfo : public CClumpModelInfo
public:
uint8 m_lastColour1;
uint8 m_lastColour2;
- char m_gameName[32];
+ char m_gameName[10];
int32 m_vehicleType;
+ float m_wheelScale;
union {
- int32 m_wheelId;
- int32 m_planeLodId;
+ int16 m_wheelId;
+ int16 m_planeLodId;
};
- float m_wheelScale;
- int32 m_numDoors;
- int32 m_handlingId;
- int32 m_vehicleClass;
- int32 m_level;
+ int16 m_handlingId;
+ int8 m_numDoors;
+ int8 m_vehicleClass;
+ int8 m_level;
+ int8 m_numComps;
+ int16 m_frequency;
CVector m_positions[NUM_VEHICLE_POSITIONS];
uint32 m_compRules;
float m_bikeSteerAngle;
@@ -66,13 +67,15 @@ public:
uint8 m_lastColorVariation;
uint8 m_currentColour1;
uint8 m_currentColour2;
- RwTexture *m_envMap;
RpAtomic *m_comps[6];
- int32 m_numComps;
+ // This is stupid, CClumpModelInfo already has it!
+ union {
+ int32 m_animFileIndex;
+ char *m_animFileName;
+ };
static int8 ms_compsToUse[2];
static int8 ms_compsUsed[2];
- static RwTexture *ms_pEnvironmentMaps[NUM_VEHICLE_ENVMAPS];
static RwRGBA ms_vehicleColourTable[256];
static RwTexture *ms_colourTextureTable[256];
static RwObjectNameIdAssocation *ms_vehicleDescs[NUM_VEHICLE_TYPES];
@@ -81,6 +84,9 @@ public:
void DeleteRwObject(void);
RwObject *CreateInstance(void);
void SetClump(RpClump *);
+ void SetAnimFile(const char *file);
+ void ConvertAnimFileIndex(void);
+ int GetAnimFileIndex(void) { return m_animFileIndex; }
static RwFrame *CollapseFramesCB(RwFrame *frame, void *data);
static RwObject *MoveObjectsCB(RwObject *object, void *data);
@@ -93,6 +99,7 @@ public:
static RpAtomic *SetAtomicRendererCB_Train(RpAtomic *atomic, void *data);
static RpAtomic *SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data);
static RpAtomic *SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data);
+ static RpAtomic *SetAtomicRendererCB_RealHeli(RpAtomic *atomic, void *data);
void SetAtomicRenderCallbacks(void);
static RwObject *SetAtomicFlagCB(RwObject *object, void *data);
@@ -114,8 +121,8 @@ public:
static void DeleteVehicleColourTextures(void);
static RpAtomic *SetEnvironmentMapCB(RpAtomic *atomic, void *data);
- static RpMaterial *SetEnvironmentMapCB(RpMaterial *material, void *data);
- static RpMaterial *HasSpecularMaterialCB(RpMaterial *material, void *data);
+ static RpMaterial *SetDefaultEnvironmentMapCB(RpMaterial *material, void *data);
+ static RpMaterial *GetMatFXEffectMaterialCB(RpMaterial *material, void *data);
void SetEnvironmentMap(void);
static void LoadEnvironmentMaps(void);
static void ShutdownEnvironmentMaps(void);
@@ -124,4 +131,5 @@ public:
static void SetComponentsToUse(int8 c1, int8 c2) { ms_compsToUse[0] = c1; ms_compsToUse[1] = c2; }
};
-VALIDATE_SIZE(CVehicleModelInfo, 0x1F8);
+extern bool gbBlackCars;
+extern bool gbPinkCars;
diff --git a/src/modelinfo/WeaponModelInfo.cpp b/src/modelinfo/WeaponModelInfo.cpp
new file mode 100644
index 00000000..2a79fada
--- /dev/null
+++ b/src/modelinfo/WeaponModelInfo.cpp
@@ -0,0 +1,55 @@
+#include "common.h"
+
+#include "ModelInfo.h"
+#include "AnimManager.h"
+#include "VisibilityPlugins.h"
+
+//--MIAMI: file done
+
+void
+CWeaponModelInfo::SetAnimFile(const char *file)
+{
+ if(strcasecmp(file, "null") == 0)
+ return;
+
+ m_animFileName = new char[strlen(file)+1];
+ strcpy(m_animFileName, file);
+}
+
+void
+CWeaponModelInfo::ConvertAnimFileIndex(void)
+{
+ if(m_animFileIndex != -1){
+ // we have a string pointer in that union
+ int32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName);
+ delete[] m_animFileName;
+ m_animFileIndex = index;
+ }
+}
+
+void
+CWeaponModelInfo::Init(void)
+{
+ CSimpleModelInfo::Init();
+ SetWeaponInfo(0);
+}
+
+void
+CWeaponModelInfo::SetWeaponInfo(int32 weaponId)
+{
+ m_atomics[2] = (RpAtomic*)weaponId;
+}
+
+int32
+CWeaponModelInfo::GetWeaponInfo(void)
+{
+ return (int32)(uintptr)m_atomics[2];
+}
+
+void
+CWeaponModelInfo::SetAtomic(int n, RpAtomic *atomic)
+{
+ CSimpleModelInfo::SetAtomic(n, atomic);
+ CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderWeaponCB);
+}
+
diff --git a/src/modelinfo/WeaponModelInfo.h b/src/modelinfo/WeaponModelInfo.h
new file mode 100644
index 00000000..5c690c29
--- /dev/null
+++ b/src/modelinfo/WeaponModelInfo.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "SimpleModelInfo.h"
+
+class CWeaponModelInfo : public CSimpleModelInfo
+{
+ union {
+ int32 m_animFileIndex;
+ char *m_animFileName;
+ };
+public:
+ CWeaponModelInfo(void) : CSimpleModelInfo(MITYPE_WEAPON) { m_animFileIndex = -1; }
+
+ virtual void SetAnimFile(const char *file);
+ virtual void ConvertAnimFileIndex(void);
+ virtual int GetAnimFileIndex(void) { return m_animFileIndex; }
+ virtual void SetAtomic(int n, RpAtomic *atomic);
+
+ void Init(void);
+ void SetWeaponInfo(int32 weaponId);
+ int32 GetWeaponInfo(void);
+};
diff --git a/src/modelinfo/XtraCompsModelInfo.h b/src/modelinfo/XtraCompsModelInfo.h
deleted file mode 100644
index 9832399c..00000000
--- a/src/modelinfo/XtraCompsModelInfo.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-#include "ClumpModelInfo.h"
-
-class CXtraCompsModelInfo : public CClumpModelInfo
-{
- int field_34;
-public:
- CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
- void SetClump(RpClump*) {};
- void Shutdown(void) {};
-}; \ No newline at end of file
diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp
deleted file mode 100644
index 55e75807..00000000
--- a/src/objects/CutsceneHead.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-#include "common.h"
-#include <rpskin.h>
-
-#include "main.h"
-#include "RwHelper.h"
-#include "RpAnimBlend.h"
-#include "AnimBlendClumpData.h"
-#include "Bones.h"
-#include "Directory.h"
-#include "CutsceneMgr.h"
-#include "Streaming.h"
-#include "CutsceneHead.h"
-#include "CdStream.h"
-
-
-CCutsceneHead::CCutsceneHead(CObject *obj)
-{
- RpAtomic *atm;
-
- assert(RwObjectGetType(obj->m_rwObject) == rpCLUMP);
-#ifdef PED_SKIN
- unk1 = 0;
- bIsSkinned = false;
- m_parentObject = (CCutsceneObject*)obj;
- // Hide original head
- if(IsClumpSkinned(obj->GetClump())){
- m_parentObject->SetRenderHead(false);
- bIsSkinned = true;
- }else
-#endif
- {
- m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame;
- atm = (RpAtomic*)GetFirstObject(m_pHeadNode);
- if(atm){
- assert(RwObjectGetType((RwObject*)atm) == rpATOMIC);
- RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER);
- }
- }
-}
-
-void
-CCutsceneHead::CreateRwObject(void)
-{
- RpAtomic *atm;
-
- CEntity::CreateRwObject();
- assert(RwObjectGetType(m_rwObject) == rpCLUMP);
- atm = GetFirstAtomic((RpClump*)m_rwObject);
- RpSkinAtomicSetHAnimHierarchy(atm, RpHAnimFrameGetHierarchy(GetFirstChild(RpClumpGetFrame((RpClump*)m_rwObject))));
-}
-
-void
-CCutsceneHead::DeleteRwObject(void)
-{
- CEntity::DeleteRwObject();
-}
-
-void
-CCutsceneHead::ProcessControl(void)
-{
- RpAtomic *atm;
- RpHAnimHierarchy *hier;
-
- // android/xbox calls is at the end
- CPhysical::ProcessControl();
-
-#ifdef PED_SKIN
- if(bIsSkinned){
- UpdateRpHAnim();
- UpdateRwFrame();
-
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump());
- int idx = RpHAnimIDGetIndex(hier, BONE_head);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- if(RwV3dLength(&mat->pos) > 100.0f){
- m_matrix.SetRotateY(PI/2);
- m_matrix = CMatrix(mat) * m_matrix;
- }
- }else
-#endif
- {
- m_matrix.SetRotateY(PI/2);
- m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix;
- UpdateRwFrame(); // android/xbox don't call this
- }
-
- assert(RwObjectGetType(m_rwObject) == rpCLUMP);
- atm = GetFirstAtomic((RpClump*)m_rwObject);
- hier = RpSkinAtomicGetHAnimHierarchy(atm);
- RpHAnimHierarchyAddAnimTime(hier, CTimer::GetTimeStepNonClipped()/50.0f);
-}
-
-void
-CCutsceneHead::Render(void)
-{
- RpAtomic *atm;
-
-#ifdef PED_SKIN
- if(bIsSkinned){
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump());
- RpHAnimHierarchyUpdateMatrices(hier);
- int idx = RpHAnimIDGetIndex(hier, BONE_head);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- if(RwV3dLength(&mat->pos) > 100.0f){
- m_matrix.SetRotateY(PI/2);
- m_matrix = CMatrix(mat) * m_matrix;
- }
- // This is head...it has no limbs
-#ifndef FIX_BUGS
- RenderLimb(BONE_Lhand);
- RenderLimb(BONE_Rhand);
-#endif
- }else
-#endif
- {
- m_matrix.SetRotateY(PI/2);
- m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix;
- }
-
- UpdateRwFrame();
-
- assert(RwObjectGetType(m_rwObject) == rpCLUMP);
- atm = GetFirstAtomic((RpClump*)m_rwObject);
- RpHAnimHierarchyUpdateMatrices(RpSkinAtomicGetHAnimHierarchy(atm));
-
- CObject::Render();
-}
-
-#ifdef PED_SKIN
-void
-CCutsceneHead::RenderLimb(int32 bone)
-{
- // It's not clear what this is...
- // modelinfo for this object is not a ped so it also doesn't have any limbs
-#ifndef FIX_BUGS
- RpAtomic *atomic;
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump());
- int idx = RpHAnimIDGetIndex(hier, bone);
- RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
- CPedModelInfo *mi = (CPedModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
- assert(mi->GetModelType() == MITYPE_PED);
- switch(bone){
- case BONE_Lhand:
- atomic = mi->getLeftHand();
- break;
- case BONE_Rhand:
- atomic = mi->getRightHand();
- break;
- default:
- return;
- }
- if(atomic){
- RwFrame *frame = RpAtomicGetFrame(atomic);
- RwMatrixTransform(RwFrameGetMatrix(frame), &mats[idx], rwCOMBINEREPLACE);
- RwFrameUpdateObjects(frame);
- RpAtomicRender(atomic);
- }
-#endif
-}
-#endif
-
-void
-CCutsceneHead::PlayAnimation(const char *animName)
-{
- RpAtomic *atm;
- RpHAnimHierarchy *hier;
- RpHAnimAnimation *anim;
- uint32 offset, size;
- RwStream *stream;
-
- assert(RwObjectGetType(m_rwObject) == rpCLUMP);
- atm = GetFirstAtomic((RpClump*)m_rwObject);
- hier = RpSkinAtomicGetHAnimHierarchy(atm);
-
- sprintf(gString, "%s.anm", animName);
-
- if(CCutsceneMgr::ms_pCutsceneDir->FindItem(gString, offset, size)){
- stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
- assert(stream);
-
- CStreaming::MakeSpaceFor(size * CDSTREAM_SECTOR_SIZE);
- CStreaming::ImGonnaUseStreamingMemory();
-
- RwStreamSkip(stream, offset*2048);
- if(RwStreamFindChunk(stream, rwID_HANIMANIMATION, nil, nil)){
- anim = RpHAnimAnimationStreamRead(stream);
- RpHAnimHierarchySetCurrentAnim(hier, anim);
- }
-
- CStreaming::IHaveUsedStreamingMemory();
-
- RwStreamClose(stream, nil);
- }
-}
diff --git a/src/objects/CutsceneHead.h b/src/objects/CutsceneHead.h
deleted file mode 100644
index c931eb01..00000000
--- a/src/objects/CutsceneHead.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include "CutsceneObject.h"
-
-class CCutsceneHead : public CCutsceneObject
-{
-public:
- RwFrame *m_pHeadNode;
-#ifdef PED_SKIN
- int32 unk1;
- CCutsceneObject *m_parentObject;
- int32 unk2;
- int32 bIsSkinned;
-#endif
-
- CCutsceneHead(CObject *obj);
-
- void CreateRwObject(void);
- void DeleteRwObject(void);
- void ProcessControl(void);
- void Render(void);
- void RenderLimb(int32 bone);
-
- void PlayAnimation(const char *animName);
-};
-#ifndef PED_SKIN
-VALIDATE_SIZE(CCutsceneHead, 0x19C);
-#endif
diff --git a/src/objects/CutsceneObject.cpp b/src/objects/CutsceneObject.cpp
index 5c10d37d..bf39bd03 100644
--- a/src/objects/CutsceneObject.cpp
+++ b/src/objects/CutsceneObject.cpp
@@ -21,12 +21,6 @@ CCutsceneObject::CCutsceneObject(void)
ObjectCreatedBy = CUTSCENE_OBJECT;
m_fMass = 1.0f;
m_fTurnMass = 1.0f;
-
-#ifdef PED_SKIN
- bRenderHead = true;
- bRenderRightHand = true;
- bRenderLeftHand = true;
-#endif
}
void
@@ -85,47 +79,9 @@ CCutsceneObject::PreRender(void)
void
CCutsceneObject::Render(void)
{
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- if(bRenderLeftHand) RenderLimb(BONE_Lhand);
- if(bRenderRightHand) RenderLimb(BONE_Rhand);
- if(bRenderHead) RenderLimb(BONE_head);
- }
-#endif
CObject::Render();
}
-#ifdef PED_SKIN
-void
-CCutsceneObject::RenderLimb(int32 bone)
-{
- RpAtomic *atomic;
- CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
- switch(bone){
- case BONE_head:
- atomic = mi->getHead();
- break;
- case BONE_Lhand:
- atomic = mi->getLeftHand();
- break;
- case BONE_Rhand:
- atomic = mi->getRightHand();
- break;
- default:
- return;
- }
- if(atomic){
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int idx = RpHAnimIDGetIndex(hier, bone);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- RwFrame *frame = RpAtomicGetFrame(atomic);
- *RwFrameGetMatrix(frame) = *mat;
- RwFrameUpdateObjects(frame);
- RpAtomicRender(atomic);
- }
-}
-#endif
-
bool
CCutsceneObject::SetupLighting(void)
{
diff --git a/src/objects/CutsceneObject.h b/src/objects/CutsceneObject.h
index 407adcc7..bb642f3e 100644
--- a/src/objects/CutsceneObject.h
+++ b/src/objects/CutsceneObject.h
@@ -5,29 +5,12 @@
class CCutsceneObject : public CObject
{
public:
-#ifdef PED_SKIN
- bool bRenderHead;
- bool bRenderRightHand;
- bool bRenderLeftHand;
-
- bool GetRenderHead(void) { return bRenderHead; }
- bool GetRenderRightHand(void) { return bRenderRightHand; }
- bool GetRenderLeftHand(void) { return bRenderLeftHand; }
- void SetRenderHead(bool render) { bRenderHead = render; }
- void SetRenderRightHand(bool render) { bRenderRightHand = render; }
- void SetRenderLeftHand(bool render) { bRenderLeftHand = render; }
-#endif
-
CCutsceneObject(void);
void SetModelIndex(uint32 id);
void ProcessControl(void);
void PreRender(void);
void Render(void);
- void RenderLimb(int32 bone);
bool SetupLighting(void);
void RemoveLighting(bool reset);
};
-#ifndef PED_SKIN
-VALIDATE_SIZE(CCutsceneObject, 0x198);
-#endif
diff --git a/src/objects/DummyObject.cpp b/src/objects/DummyObject.cpp
index d5805073..8dd1643d 100644
--- a/src/objects/DummyObject.cpp
+++ b/src/objects/DummyObject.cpp
@@ -10,4 +10,5 @@ CDummyObject::CDummyObject(CObject *obj)
AttachToRwObject(obj->m_rwObject);
obj->DetachFromRwObject();
m_level = obj->m_level;
+ m_area = obj->m_area;
}
diff --git a/src/objects/DummyObject.h b/src/objects/DummyObject.h
index d6f88335..680df685 100644
--- a/src/objects/DummyObject.h
+++ b/src/objects/DummyObject.h
@@ -10,5 +10,3 @@ public:
CDummyObject(void) {}
CDummyObject(CObject *obj);
};
-
-VALIDATE_SIZE(CDummyObject, 0x68);
diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp
index c5f73987..e6bb7aee 100644
--- a/src/objects/Object.cpp
+++ b/src/objects/Object.cpp
@@ -14,7 +14,8 @@
#include "soundlist.h"
int16 CObject::nNoTempObjects;
-int16 CObject::nBodyCastHealth = 1000;
+//int16 CObject::nBodyCastHealth = 1000;
+float CObject::fDistToNearestTree;
void *CObject::operator new(size_t sz) { return CPools::GetObjectPool()->New(); }
void *CObject::operator new(size_t sz, int handle) { return CPools::GetObjectPool()->New(handle);};
@@ -69,6 +70,7 @@ CObject::CObject(CDummyObject *dummy)
dummy->DetachFromRwObject();
Init();
m_level = dummy->m_level;
+ m_area = dummy->m_area;
}
CObject::~CObject(void)
@@ -160,6 +162,7 @@ CObject::ObjectDamage(float amount)
return;
static int8 nFrameGen = 0;
bool bBodyCastDamageEffect = false;
+#if 0
if (GetModelIndex() == MI_BODYCAST) {
if (amount > 50.0f)
nBodyCastHealth = (int16)(nBodyCastHealth - 0.5f * amount);
@@ -169,6 +172,7 @@ CObject::ObjectDamage(float amount)
bBodyCastDamageEffect = true;
amount = 0.0f;
}
+#endif
if ((amount * m_fCollisionDamageMultiplier > 150.0f || bBodyCastDamageEffect) && m_nCollisionDamageEffect) {
const CVector& vecPos = m_matrix.GetPosition();
const float fDirectionZ = 0.0002f * amount;
@@ -334,9 +338,12 @@ CObject::Init(void)
m_pCurSurface = outEntity;
else
m_pCurSurface = nil;
+#if 0
if (GetModelIndex() == MI_BODYCAST)
nBodyCastHealth = 1000;
- else if (GetModelIndex() == MI_BUOY)
+ else
+#endif
+ if (GetModelIndex() == MI_BUOY)
bTouchingWater = true;
}
@@ -395,3 +402,18 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius)
}
}
}
+
+bool
+IsObjectPointerValid(CObject* pObject)
+{
+ if (!pObject)
+ return false;
+ int index = CPools::GetObjectPool()->GetJustIndex(pObject);
+#ifdef FIX_BUGS
+ if (index < 0 || index >= CPools::GetObjectPool()->GetSize())
+#else
+ if (index < 0 || index > CPools::GetObjectPool()->GetSize())
+#endif
+ return false;
+ return pObject->bIsBIGBuilding || pObject->m_entryInfoList.first;
+}
diff --git a/src/objects/Object.h b/src/objects/Object.h
index 79589dc9..9ceffb2f 100644
--- a/src/objects/Object.h
+++ b/src/objects/Object.h
@@ -25,13 +25,29 @@ enum CollisionDamageEffect
DAMAGE_EFFECT_NONE,
DAMAGE_EFFECT_CHANGE_MODEL,
DAMAGE_EFFECT_SPLIT_MODEL,
- DAMAGE_EFFECT_SMASH_COMPLETELY,
+ DAMAGE_EFFECT_SMASH_AND_DAMAGE_TRAFFICLIGHTS,
+
+ DAMAGE_EFFECT_SMASH_COMPLETELY = 20,
DAMAGE_EFFECT_CHANGE_THEN_SMASH,
DAMAGE_EFFECT_SMASH_CARDBOARD_COMPLETELY = 50,
+ DAMAGE_EFFECT_SMASH_YELLOW_TARGET_COMPLETELY,
+
DAMAGE_EFFECT_SMASH_WOODENBOX_COMPLETELY = 60,
DAMAGE_EFFECT_SMASH_TRAFFICCONE_COMPLETELY = 70,
- DAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY = 80
+ DAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY = 80,
+
+ DAMAGE_EFFECT_SMASH_NEWSTANDNEW1 = 91,
+ DAMAGE_EFFECT_SMASH_NEWSTANDNEW21,
+ DAMAGE_EFFECT_SMASH_NEWSTANDNEW31,
+ DAMAGE_EFFECT_SMASH_NEWSTANDNEW41,
+ DAMAGE_EFFECT_SMASH_NEWSTANDNEW51,
+
+ DAMAGE_EFFECT_SMASH_BLACKBAG = 100,
+ DAMAGE_EFFECT_SMASH_VEGPALM = 110,
+ DAMAGE_EFFECT_BURST_BEACHBALL = 120,
+ DAMAGE_EFFECT_SMASH_BEACHLOUNGE_WOOD = 131,
+ DAMAGE_EFFECT_SMASH_BEACHLOUNGE_TOWEL,
};
class CVehicle;
@@ -70,7 +86,9 @@ public:
int8 m_colour1, m_colour2;
static int16 nNoTempObjects;
- static int16 nBodyCastHealth;
+// static int16 nBodyCastHealth;
+
+ static float fDistToNearestTree;
static void *operator new(size_t);
static void *operator new(size_t, int);
@@ -98,4 +116,4 @@ public:
static void DeleteAllTempObjectsInArea(CVector point, float fRadius);
};
-VALIDATE_SIZE(CObject, 0x198);
+bool IsObjectPointerValid(CObject* pObject);
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp
index 2dee0397..48b1f6cd 100644
--- a/src/peds/CivilianPed.cpp
+++ b/src/peds/CivilianPed.cpp
@@ -9,6 +9,9 @@
#include "World.h"
#include "Vehicle.h"
#include "SurfaceTable.h"
+#include "Weather.h"
+#include "PedAttractor.h"
+#include "Object.h"
CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
{
@@ -16,6 +19,8 @@ CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {
m_nearPeds[i] = nil;
}
+ m_nAttractorCycleState = 0;
+ m_bAttractorUnk = (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 1.25f);
}
void
@@ -187,9 +192,6 @@ CCivilianPed::CivilianAI(void)
void
CCivilianPed::ProcessControl(void)
{
- if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
- return;
-
CPed::ProcessControl();
if (bWasPostponed)
@@ -198,7 +200,7 @@ CCivilianPed::ProcessControl(void)
if (DyingOrDead())
return;
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, nil);
switch (m_nPedState) {
case PED_WANDER_RANGE:
case PED_WANDER_PATH:
@@ -215,7 +217,7 @@ CCivilianPed::ProcessControl(void)
// fall through
case PED_SEEK_POS:
if (Seek()) {
- if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && m_pNextPathNode) {
+ if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) && m_pNextPathNode) {
m_pNextPathNode = nil;
#ifdef TOGGLEABLE_BETA_FEATURES
} else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) {
@@ -247,7 +249,7 @@ CCivilianPed::ProcessControl(void)
} else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT
&& m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) {
SetMoveState(m_pedInObjective->m_nMoveState);
- } else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) {
+ } else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) {
SetIdle();
} else {
RestorePreviousState();
@@ -323,7 +325,7 @@ CCivilianPed::ProcessControl(void)
CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10);
}
- m_pMyVehicle->pDriver->m_fHealth = Min(125.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth);
+ m_pMyVehicle->pDriver->m_fHealth = Min(CWorld::Players[0].m_nMaxHealth + 25.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth);
if (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250)
CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
} else {
@@ -334,7 +336,7 @@ CCivilianPed::ProcessControl(void)
} else {
bWanderPathAfterExitingCar = true;
CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
- m_pMyVehicle->pDriver->m_fHealth = 125.0f;
+ m_pMyVehicle->pDriver->m_fHealth = CWorld::Players[0].m_nMaxHealth + 25.0f;
SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
}
} else {
@@ -368,6 +370,10 @@ CCivilianPed::ProcessControl(void)
if (IsPedInControl())
CivilianAI();
+ if (CharCreatedBy == RANDOM_CHAR) {
+ UseNearbyAttractors();
+ }
+
if (CTimer::GetTimeInMilliseconds() > m_timerUnused) {
m_stateUnused = 0;
m_timerUnused = 0;
@@ -376,3 +382,90 @@ CCivilianPed::ProcessControl(void)
if (m_moved.Magnitude() > 0.0f)
Avoid();
}
+
+const int32 gFrequencyOfAttractorAttempt = 11;
+const float gDistanceToSeekAttractors = 50.0f;
+const float gMaxDistanceToAttract = 10.0f;
+
+/* Probably this was inlined */
+void CCivilianPed::FindNearbyAttractorsSectorList(CPtrList& list, float& minDistance, C2dEffect*& pClosestAttractor, CEntity*& pAttractorEntity)
+{
+ for (CPtrNode* pNode = list.first; pNode != nil; pNode = pNode->next) {
+ CEntity* pEntity = (CEntity*)pNode->item;
+ if (pEntity->IsObject() && (!pEntity->IsStatic() || ((CObject*)pEntity)->bHasBeenDamaged))
+ continue;
+ CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex());
+ for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) {
+ C2dEffect* pEffect = pModelInfo->Get2dEffect(i);
+ if (pEffect->type != EFFECT_PED_ATTRACTOR)
+ continue;
+ if (!IsAttractedTo(pEffect->pedattr.type))
+ continue;
+ CVector pos;
+ CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos);
+ if ((pos - GetPosition()).MagnitudeSqr() < minDistance) {
+ CPedAttractorManager* pManager = GetPedAttractorManager();
+ if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) {
+ pClosestAttractor = pEffect;
+ pAttractorEntity = pEntity;
+ minDistance = (pos - GetPosition()).MagnitudeSqr();
+ }
+ }
+ }
+ }
+}
+
+void CCivilianPed::UseNearbyAttractors()
+{
+ if (CWeather::Rain < 0.2f && !m_bAttractorUnk)
+ return;
+ if (HasAttractor())
+ return;
+ if (m_nAttractorCycleState != gFrequencyOfAttractorAttempt) {
+ m_nAttractorCycleState++;
+ return;
+ }
+ m_nAttractorCycleState = 0;
+ if (!IsPedInControl())
+ return;
+ if (m_nPedState == PED_FLEE_ENTITY)
+ return;
+
+ float left = GetPosition().x - gDistanceToSeekAttractors;
+ float right = GetPosition().x + gDistanceToSeekAttractors;
+ float top = GetPosition().y - gDistanceToSeekAttractors;
+ float bottom = GetPosition().y + gDistanceToSeekAttractors;
+ int xstart = Max(0, CWorld::GetSectorIndexX(left));
+ int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
+ int ystart = Max(0, CWorld::GetSectorIndexY(top));
+ int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
+ assert(xstart <= xend);
+ assert(ystart <= yend);
+
+ float minDistance = SQR(gMaxDistanceToAttract);
+ C2dEffect* pClosestAttractor = nil;
+ CEntity* pAttractorEntity = nil;
+
+ for (int y = ystart; y <= yend; y++) {
+ for (int x = xstart; x <= xend; x++) {
+ CSector* s = CWorld::GetSector(x, y);
+ FindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_BUILDINGS], minDistance, pClosestAttractor, pAttractorEntity);
+ FindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_OBJECTS], minDistance, pClosestAttractor, pAttractorEntity);
+ }
+ }
+ if (pClosestAttractor)
+ GetPedAttractorManager()->RegisterPedWithAttractor(this, pClosestAttractor, pAttractorEntity->GetMatrix());
+}
+
+bool CCivilianPed::IsAttractedTo(int8 type)
+{
+ switch (type) {
+ case ATTRACTOR_ATM: return true;
+ case ATTRACTOR_SEAT: return true;
+ case ATTRACTOR_STOP: return true;
+ case ATTRACTOR_PIZZA: return true;
+ case ATTRACTOR_SHELTER: return CWeather::Rain >= 0.2f;
+ case ATTRACTOR_ICECREAM: return false;
+ }
+ return false;
+}
diff --git a/src/peds/CivilianPed.h b/src/peds/CivilianPed.h
index 8418a99f..27d458f7 100644
--- a/src/peds/CivilianPed.h
+++ b/src/peds/CivilianPed.h
@@ -4,12 +4,17 @@
class CCivilianPed : public CPed
{
+ bool m_bAttractorUnk;
+ int32 m_nAttractorCycleState;
public:
CCivilianPed(ePedType, uint32);
~CCivilianPed(void) { }
void CivilianAI(void);
void ProcessControl(void);
+ void UseNearbyAttractors(void);
+ void FindNearbyAttractorsSectorList(CPtrList&, float&, C2dEffect*&, CEntity*&);
+ bool IsAttractedTo(int8);
};
#ifndef PED_SKIN
VALIDATE_SIZE(CCivilianPed, 0x53C);
diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp
index 99e8c1ae..b84dcf14 100644
--- a/src/peds/CopPed.cpp
+++ b/src/peds/CopPed.cpp
@@ -17,13 +17,14 @@
#include "Renderer.h"
#include "Camera.h"
-CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
+CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP)
{
m_nCopType = copType;
switch (copType) {
case COP_STREET:
SetModelIndex(MI_COP);
- GiveWeapon(WEAPONTYPE_COLT45, 1000);
+ GiveWeapon(WEAPONTYPE_NIGHTSTICK, 1000, true);
+ GiveDelayedWeapon(WEAPONTYPE_COLT45, 1000);
m_currentWeapon = WEAPONTYPE_UNARMED;
m_fArmour = 0.0f;
m_wepSkills = 208; /* TODO: what is this? seems unused */
@@ -31,17 +32,15 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
break;
case COP_FBI:
SetModelIndex(MI_FBI);
- GiveWeapon(WEAPONTYPE_COLT45, 1000);
- GiveWeapon(WEAPONTYPE_AK47, 1000);
- SetCurrentWeapon(WEAPONTYPE_AK47);
+ GiveDelayedWeapon(WEAPONTYPE_MP5, 1000);
+ SetCurrentWeapon(WEAPONTYPE_MP5);
m_fArmour = 100.0f;
m_wepSkills = 176; /* TODO: what is this? seems unused */
m_wepAccuracy = 76;
break;
case COP_SWAT:
SetModelIndex(MI_SWAT);
- GiveWeapon(WEAPONTYPE_COLT45, 1000);
- GiveWeapon(WEAPONTYPE_UZI, 1000);
+ GiveDelayedWeapon(WEAPONTYPE_UZI, 1000);
SetCurrentWeapon(WEAPONTYPE_UZI);
m_fArmour = 50.0f;
m_wepSkills = 32; /* TODO: what is this? seems unused */
@@ -49,15 +48,29 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
break;
case COP_ARMY:
SetModelIndex(MI_ARMY);
- GiveWeapon(WEAPONTYPE_COLT45, 1000);
- GiveWeapon(WEAPONTYPE_M16, 1000);
- GiveWeapon(WEAPONTYPE_GRENADE, 10);
- SetCurrentWeapon(WEAPONTYPE_M16);
+ GiveDelayedWeapon(WEAPONTYPE_MP5, 1000);
+ SetCurrentWeapon(WEAPONTYPE_MP5);
m_fArmour = 100.0f;
m_wepSkills = 32; /* TODO: what is this? seems unused */
m_wepAccuracy = 84;
break;
- default:
+ case COP_MIAMIVICE:
+ switch (modifier) {
+ case 0: SetModelIndex(MI_VICE1); break;
+ case 1: SetModelIndex(MI_VICE2); break;
+ case 2: SetModelIndex(MI_VICE3); break;
+ case 3: SetModelIndex(MI_VICE4); break;
+ case 4: SetModelIndex(MI_VICE5); break;
+ case 5: SetModelIndex(MI_VICE6); break;
+ case 6: SetModelIndex(MI_VICE7); break;
+ case 7: SetModelIndex(MI_VICE8); break;
+ default: assert(0); break;
+ }
+ GiveDelayedWeapon(WEAPONTYPE_UZI, 1000);
+ SetCurrentWeapon(WEAPONTYPE_UZI);
+ m_fArmour = 100.0f;
+ m_wepSkills = 176;
+ m_wepAccuracy = 76;
break;
}
m_bIsInPursuit = false;
@@ -425,8 +438,9 @@ CCopPed::CopAI(void)
#ifdef VC_PED_PORTS
float dotProd;
if (m_nRoadblockNode != -1) {
- CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]];
- dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition());
+ // TODO(MIAMI): check this, i'm only getting this compile here....
+ CPathNode *roadBlockNode = &ThePaths.m_pathNodes[CRoadBlocks::RoadBlockNodes[m_nRoadblockNode]];
+ dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockNode->GetPosition(), GetPosition() - roadBlockNode->GetPosition());
} else
dotProd = -1.0f;
@@ -559,9 +573,6 @@ CCopPed::CopAI(void)
void
CCopPed::ProcessControl(void)
{
- if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
- return;
-
CPed::ProcessControl();
if (bWasPostponed)
return;
@@ -578,7 +589,7 @@ CCopPed::ProcessControl(void)
ArrestPlayer();
return;
}
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, nil);
if (m_moved.Magnitude() > 0.0f)
Avoid();
@@ -709,7 +720,7 @@ CCopPed::ProcessControl(void)
return;
bool dontShoot = false;
- if (GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(this)) {
+ if (GetIsOnScreen()) {
if (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) {
CEntity *foundBuilding = nil;
CColPoint foundCol;
diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h
index 5346d9a1..945f78b8 100644
--- a/src/peds/CopPed.h
+++ b/src/peds/CopPed.h
@@ -7,6 +7,7 @@ enum eCopType
COP_FBI = 1,
COP_SWAT = 2,
COP_ARMY = 3,
+ COP_MIAMIVICE = 5
};
class CCopPed : public CPed
@@ -24,7 +25,7 @@ public:
eCopType m_nCopType;
int8 field_1364;
- CCopPed(eCopType);
+ CCopPed(eCopType, int32 modifier = 0);
~CCopPed();
void ClearPursuit(void);
diff --git a/src/peds/DummyPed.h b/src/peds/DummyPed.h
index ea617c76..cace4ead 100644
--- a/src/peds/DummyPed.h
+++ b/src/peds/DummyPed.h
@@ -8,5 +8,3 @@ class CDummyPed : CDummy
int32 pedType;
int32 unknown;
};
-
-VALIDATE_SIZE(CDummyPed, 0x70);
diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp
index cdaee657..a62ac76d 100644
--- a/src/peds/EmergencyPed.cpp
+++ b/src/peds/EmergencyPed.cpp
@@ -44,15 +44,12 @@ CEmergencyPed::InRange(CPed *victim)
void
CEmergencyPed::ProcessControl(void)
{
- if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
- return;
-
CPed::ProcessControl();
if (bWasPostponed)
return;
if(!DyingOrDead()) {
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, nil);
if (IsPedInControl() && m_moved.Magnitude() > 0.0f)
Avoid();
@@ -317,7 +314,7 @@ CEmergencyPed::MedicAI(void)
m_nEmergencyPedState = EMERGENCY_PED_STAND_STILL;
} else {
m_nEmergencyPedState = EMERGENCY_PED_FACE_TO_PATIENT;
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CPR, 4.0f);
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_MEDIC, ANIM_CPR, 4.0f);
bIsDucking = true;
}
SetLookTimer(2000);
diff --git a/src/peds/Gangs.cpp b/src/peds/Gangs.cpp
index 8859e61e..2d6d1137 100644
--- a/src/peds/Gangs.cpp
+++ b/src/peds/Gangs.cpp
@@ -2,12 +2,17 @@
#include "ModelIndices.h"
#include "Gangs.h"
+#include "General.h"
+#include "Streaming.h"
#include "Weapon.h"
CGangInfo CGangs::Gang[NUM_GANGS];
+bool CGangs::GangAttackWithCops[NUM_GANGS];
CGangInfo::CGangInfo() :
- m_nVehicleMI(MI_BUS),
+ m_nVehicleMI(-1),
+ m_nPedModel1MI(-1),
+ m_nPedModel2MI(-1),
m_nPedModelOverride(-1),
m_Weapon1(WEAPONTYPE_UNARMED),
m_Weapon2(WEAPONTYPE_UNARMED)
@@ -15,21 +20,63 @@ CGangInfo::CGangInfo() :
void CGangs::Initialise(void)
{
- Gang[GANG_MAFIA].m_nVehicleMI = MI_MAFIA;
- Gang[GANG_TRIAD].m_nVehicleMI = MI_BELLYUP;
- Gang[GANG_DIABLOS].m_nVehicleMI = MI_DIABLOS;
- Gang[GANG_YAKUZA].m_nVehicleMI = MI_YAKUZA;
- Gang[GANG_YARDIE].m_nVehicleMI = MI_YARDIE;
- Gang[GANG_COLUMB].m_nVehicleMI = MI_COLUMB;
- Gang[GANG_HOODS].m_nVehicleMI = MI_HOODS;
- Gang[GANG_7].m_nVehicleMI = -1;
- Gang[GANG_8].m_nVehicleMI = -1;
+ SetGangPedModels(GANG_CUBAN, MI_CBA, MI_CBB);
+ SetGangPedModels(GANG_HAITIAN, MI_HNA, MI_HNB);
+ SetGangPedModels(GANG_STREET, MI_SGA, MI_SGB);
+ SetGangPedModels(GANG_DIAZ, MI_CLA, MI_CLB);
+ SetGangPedModels(GANG_SECURITY, MI_GDA, MI_GDB);
+ SetGangPedModels(GANG_BIKER, MI_BKA, MI_BKB);
+ SetGangPedModels(GANG_PLAYER, MI_PGA, MI_PGB);
+ SetGangPedModels(GANG_GOLFER, MI_WFOGO, MI_WMOGO);
+ SetGangVehicleModel(GANG_CUBAN, MI_CUBAN);
+ SetGangVehicleModel(GANG_HAITIAN, MI_VOODOO);
+ SetGangVehicleModel(GANG_STREET, MI_GANGBUR);
+ SetGangVehicleModel(GANG_DIAZ, -1);
+ SetGangVehicleModel(GANG_SECURITY, -1);
+ SetGangVehicleModel(GANG_BIKER, MI_ANGEL);
+ SetGangVehicleModel(GANG_PLAYER, -1);
+ SetGangVehicleModel(GANG_GOLFER, MI_CADDY);
+ SetGangWeapons(GANG_GOLFER, WEAPONTYPE_GOLFCLUB, WEAPONTYPE_GOLFCLUB);
#ifdef FIX_BUGS
for (int i = 0; i < NUM_GANGS; i++)
- Gang[i].m_nPedModelOverride = -1;
+ SetGangPedModelOverride(i, -1);
#endif
}
+bool CGangs::HaveGangModelsLoaded(int16 gang)
+{
+ CGangInfo* pGangInfo = GetGangInfo(gang);
+ return CStreaming::HasModelLoaded(pGangInfo->m_nPedModel1MI) && CStreaming::HasModelLoaded(pGangInfo->m_nPedModel2MI);
+}
+
+void CGangs::SetGangPedModels(int16 gang, int32 mi1, int32 mi2)
+{
+ GetGangInfo(gang)->m_nPedModel1MI = mi1;
+ GetGangInfo(gang)->m_nPedModel2MI = mi2;
+}
+
+void CGangs::SetWillAttackPlayerWithCops(ePedType type, bool will)
+{
+ if (type >= PEDTYPE_GANG1 && type <= PEDTYPE_GANG9)
+ GangAttackWithCops[type - PEDTYPE_GANG1] = will;
+}
+
+bool CGangs::GetWillAttackPlayerWithCops(ePedType type)
+{
+ if (type >= PEDTYPE_GANG1 && type <= PEDTYPE_GANG9)
+ return GangAttackWithCops[type - PEDTYPE_GANG1];
+ return false;
+}
+
+int32 CGangs::ChooseGangPedModel(int16 gang)
+{
+ CGangInfo* pGangInfo = GetGangInfo(gang);
+ if (pGangInfo->m_nPedModelOverride != -1 || CGeneral::GetRandomTrueFalse())
+ return pGangInfo->m_nPedModel1MI;
+ else
+ return pGangInfo->m_nPedModel2MI;
+}
+
void CGangs::SetGangVehicleModel(int16 gang, int32 model)
{
GetGangInfo(gang)->m_nVehicleMI = model;
diff --git a/src/peds/Gangs.h b/src/peds/Gangs.h
index c8ea2916..c6381343 100644
--- a/src/peds/Gangs.h
+++ b/src/peds/Gangs.h
@@ -1,8 +1,12 @@
#pragma once
+#include "PedType.h"
+
struct CGangInfo
{
int32 m_nVehicleMI;
+ int32 m_nPedModel1MI;
+ int32 m_nPedModel2MI;
int8 m_nPedModelOverride;
int32 m_Weapon1;
int32 m_Weapon2;
@@ -13,15 +17,15 @@ struct CGangInfo
VALIDATE_SIZE(CGangInfo, 0x10);
enum {
- GANG_MAFIA = 0,
- GANG_TRIAD,
- GANG_DIABLOS,
- GANG_YAKUZA,
- GANG_YARDIE,
- GANG_COLUMB,
- GANG_HOODS,
- GANG_7,
- GANG_8,
+ GANG_CUBAN = 0,
+ GANG_HAITIAN,
+ GANG_STREET,
+ GANG_DIAZ,
+ GANG_SECURITY,
+ GANG_BIKER,
+ GANG_PLAYER,
+ GANG_GOLFER,
+ GANG_9,
NUM_GANGS
};
@@ -36,9 +40,18 @@ public:
static void SaveAllGangData(uint8 *, uint32 *);
static void LoadAllGangData(uint8 *, uint32);
+ static void SetGangPedModels(int16, int32, int32);
+ static void SetWillAttackPlayerWithCops(ePedType type, bool will);
+ static bool GetWillAttackPlayerWithCops(ePedType type);
+ static int32 ChooseGangPedModel(int16);
+
+ static bool HaveGangModelsLoaded(int16 gang);
+ static int32 GetGangPedModel1(int16 gang) { return Gang[gang].m_nPedModel1MI; }
+ static int32 GetGangPedModel2(int16 gang) { return Gang[gang].m_nPedModel2MI; }
static int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; }
static CGangInfo *GetGangInfo(int16 gang) { return &Gang[gang]; }
private:
static CGangInfo Gang[NUM_GANGS];
+ static bool GangAttackWithCops[NUM_GANGS];
};
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index d48a6a2f..12870236 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -57,6 +57,8 @@
#include "Timecycle.h"
#include "ParticleObject.h"
#include "Floater.h"
+#include "Streaming.h"
+#include "PedAttractor.h"
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
@@ -65,6 +67,9 @@ uint16 gnNumTempPedList;
CColPoint aTempPedColPts[MAX_COLLISION_POINTS];
+// TODO(Miami)
+#define AUDIO_NOT_READY
+
// Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL)
PedAudioData CommentWaitTime[39] = {
{500, 800, 500, 2},
@@ -111,32 +116,8 @@ uint16 nPlayerInComboMove;
RpClump *flyingClumpTemp;
-// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat.
FightMove tFightMoves[NUM_FIGHTMOVES] = {
- {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0},
- {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0},
- {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0},
- {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0},
- {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0},
- {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0},
- {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0},
- {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0},
- {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0},
- {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0},
- {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ // TODO(Miami)
};
uint16 CPed::nThreatReactionRangeMultiplier = 1;
@@ -384,6 +365,8 @@ CPed::DebugRenderOnePedText(void)
CPed::~CPed(void)
{
CWorld::Remove(this);
+ if (m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
if (InVehicle()){
uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
@@ -402,6 +385,10 @@ CPed::~CPed(void)
}
if (m_pFire)
m_pFire->Extinguish();
+ if (bCarPassenger)
+ CPopulation::ms_nTotalCarPassengerPeds--;
+ if (bMiamiViceCop)
+ CPopulation::NumMiamiViceCops--;
CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
DMAudio.DestroyEntity(m_audioEntityId);
}
@@ -448,13 +435,17 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
CharCreatedBy = RANDOM_CHAR;
m_leader = nil;
m_pedInObjective = nil;
+ m_attractorHeading = 0.0f;
m_carInObjective = nil;
+ m_attractorHeading = 0.0f;
bInVehicle = false;
m_pMyVehicle = nil;
m_pVehicleAnim = nil;
m_vecOffsetSeek.x = 0.0f;
m_vecOffsetSeek.y = 0.0f;
m_vecOffsetSeek.z = 0.0f;
+ m_attractor = nil;
+ m_positionInQueue = -1;
m_pedFormation = FORMATION_UNDEFINED;
m_collidingThingTimer = 0;
m_nPedStateTimer = 0;
@@ -483,6 +474,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
m_wepSkills = 0;
m_distanceToCountSeekDone = 1.0f;
+ m_acceptableHeadingOffset = 0.1f;
bRunningToPhone = false;
m_phoneId = -1;
m_lastAccident = 0;
@@ -521,6 +513,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_fAirResistance = 0.4f / m_fMass;
m_fElasticity = 0.05f;
+ m_ceaseAttackTimer = 0;
+
bIsStanding = false;
bWasStanding = false;
bIsAttacking = false;
@@ -601,9 +595,18 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
#ifdef KANGAROO_CHEAT
m_ped_flagI80 = false;
#endif
+
+ m_gangFlags = 0xFF;
+
+ bReachedAttractorHeadingTarget = false;
+ bTurnedAroundOnAttractor = false;
+ bCarPassenger = false;
+ bMiamiViceCop = false;
#ifdef VC_PED_PORTS
- bSomeVCflag1 = false;
+ bHeadStuckInCollision = false;
#endif
+ bIsPlayerFriend = true;
+ bDeadPedInFrontOfCar = false;
if ((CGeneral::GetRandomNumber() & 3) == 0)
bHasACamera = true;
@@ -626,8 +629,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED;
m_currentWeapon = WEAPONTYPE_UNARMED;
m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
+ m_delayedWeapon = WEAPONTYPE_UNIDENTIFIED;
- for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
+ for(int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
CWeapon &weapon = GetWeapon(i);
weapon.m_eWeaponType = WEAPONTYPE_UNARMED;
weapon.m_eWeaponState = WEAPONSTATE_READY;
@@ -637,39 +641,62 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
}
m_lastFightMove = FIGHTMOVE_NULL;
- GiveWeapon(WEAPONTYPE_UNARMED, 0);
+ GiveWeapon(WEAPONTYPE_UNARMED, 0, true);
m_wepAccuracy = 60;
m_lastWepDam = -1;
+ m_lastDamEntity = nil;
+ m_attachedTo = nil;
+ m_attachWepAmmo = 0;
m_collPoly.valid = false;
m_fCollisionSpeed = 0.0f;
m_wepModelID = -1;
+ uint16 random = CGeneral::GetRandomNumber();
+ m_nPedMoney = random % 25;
+ if (m_nPedMoney == 23)
+ m_nPedMoney = 400;
#ifdef PED_SKIN
m_pWeaponModel = nil;
#endif
CPopulation::UpdatePedCount((ePedType)m_nPedType, false);
}
-uint32
-CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo)
+// --MIAMI: Done
+int32
+CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo, bool unused)
{
- CWeapon &weapon = GetWeapon(weaponType);
+ int slot = GetWeaponSlot(weaponType);
- if (HasWeapon(weaponType)) {
- if (weapon.m_nAmmoTotal + ammo > 99999)
- weapon.m_nAmmoTotal = 99999;
- else
- weapon.m_nAmmoTotal += ammo;
+ if (m_weapons[slot].m_eWeaponType == weaponType) {
+ GetWeapon(slot).m_nAmmoTotal += ammo;
+ if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) {
- weapon.Reload();
+ // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1.
+ GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal);
+ } else {
+ GetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal);
+ }
+ GetWeapon(slot).Reload();
+ if (GetWeapon(slot).m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO && GetWeapon(slot).m_nAmmoTotal > 0)
+ GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;
} else {
- weapon.Initialise(weaponType, ammo);
- // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous.
- m_maxWeaponTypeAllowed++;
+ if (HasWeaponSlot(slot)) {
+
+ // TODO(Miami): Make an enum for that
+ if (slot == 4 || slot == 5 || slot == 6)
+ ammo += GetWeapon(slot).m_nAmmoTotal;
+
+ RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon(slot).m_eWeaponType)->m_nModelId);
+ GetWeapon(slot).Shutdown();
+ }
+ GetWeapon(slot).Initialise(weaponType, ammo);
+ if (slot == m_currentWeapon && !bInVehicle) {
+ AddWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nModelId);
+ }
}
- if (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO)
- weapon.m_eWeaponState = WEAPONSTATE_READY;
+ if (GetWeapon(slot).m_eWeaponState != WEAPONSTATE_OUT_OF_AMMO)
+ GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;
- return weaponType;
+ return slot;
}
static RwObject*
@@ -823,8 +850,12 @@ CPed::AddWeaponModel(int id)
if (id != -1) {
#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump()))
+ if (IsClumpSkinned(GetClump())) {
+ if (m_pWeaponModel)
+ RemoveWeaponModel(-1);
+
m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
+ }
else
#endif
{
@@ -833,7 +864,12 @@ CPed::AddWeaponModel(int id)
RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame);
RpClumpAddAtomic(GetClump(), atm);
}
+ CModelInfo::GetModelInfo(id)->AddRef();
m_wepModelID = id;
+
+ // TODO(Miami)
+ // if (IsPlayer() && id == MI_MINIGUN)
+ // ((CPlayerPed*)this)->m_pMinigunTopAtomic = (RpAtomic*)CModelInfo::GetModelInfo(MI_MINIGUN2)->CreateInstance();
}
}
@@ -1119,56 +1155,142 @@ CPed::IsPedHeadAbovePos(float zOffset)
return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z;
}
+// --MIAMI: Done
+void
+CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
+
+ if (ped->DyingOrDead())
+ return;
+
+ if (ped->bIsDucking && ped->bCrouchWhenShooting) {
+ CAnimBlendAssociation *crouchFireAssoc = nil;
+ if (!!weapon->m_bCrouchFire) {
+ crouchFireAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchFireAnim(weapon));
+ }
+ if (!!weapon->m_bReload && reloadAssoc) {
+ if (reloadAssoc->animId == GetCrouchReloadAnim(weapon) && !crouchFireAssoc) {
+ CAnimBlendAssociation *crouchAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 8.0f);
+ crouchAssoc->SetCurrentTime(crouchAssoc->hierarchy->totalLength);
+ crouchAssoc->flags &= ~ASSOC_RUNNING;
+ }
+ }
+ } else if (weapon->m_bReloadLoop2Start && ped->bIsAttacking) {
+ CAnimBlendAssociation *fireAssoc =
+ CAnimManager::BlendAnimation(ped->GetClump(), weapon->m_AnimToPlay, GetPrimaryFireAnim(weapon), 8.0f);
+ fireAssoc->SetFinishCallback(FinishedAttackCB, ped);
+ fireAssoc->SetRun();
+ if (fireAssoc->currentTime != reloadAssoc->hierarchy->totalLength) {
+ if (fireAssoc->currentTime >= weapon->m_fAnimLoopStart)
+ return;
+
+ fireAssoc->SetCurrentTime(Max(weapon->m_fAnimLoopStart - 0.04f, 0.0f));
+ } else {
+ fireAssoc->SetCurrentTime(Max(weapon->m_fAnimLoopStart - 0.04f, 0.0f));
+ }
+ }
+}
+
+// --MIAMI: Done
void
CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
{
- CWeaponInfo *currentWeapon;
- CAnimBlendAssociation *newAnim;
+ CAnimBlendAssociation *newAnim, *reloadAnimAssoc;
CPed *ped = (CPed*)arg;
+ CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
- if (attackAssoc) {
- switch (attackAssoc->animId) {
- case ANIM_WEAPON_START_THROW:
- // what?!
- if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {
- attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU);
- } else {
- attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW);
+ if (ped->m_nPedState != PED_ATTACK) {
+ if (ped->bIsDucking && ped->IsPedInControl()) {
+ if (currentWeapon->m_bReload) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon));
+ }
+ if (currentWeapon->m_bCrouchFire && attackAssoc) {
+ if (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) {
+ newAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 8.0f);
+ newAnim->SetCurrentTime(newAnim->hierarchy->totalLength);
+ newAnim->flags &= ~ASSOC_RUNNING;
}
+ }
+ }
+ return;
+ }
+ if (attackAssoc && attackAssoc->animId == ANIM_THROWABLE_START_THROW && currentWeapon->m_AnimToPlay == ASSOCGRP_THROW) {
+ if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {
+ attackAssoc->blendDelta = -1000.0f;
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_THROWABLE_THROWU);
+ } else {
+ attackAssoc->blendDelta = -1000.0;
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_THROWABLE_THROW);
+ }
+ newAnim->SetFinishCallback(FinishedAttackCB, ped);
+ return;
+ }
- newAnim->SetFinishCallback(FinishedAttackCB, ped);
- return;
+ if (ped->bIsDucking && ped->bCrouchWhenShooting) {
+ if (currentWeapon->m_bReload) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon));
+ }
+ if (currentWeapon->m_bCrouchFire && attackAssoc) {
+ if (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) {
+ newAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 8.0f);
+ newAnim->SetCurrentTime(newAnim->hierarchy->totalLength);
+ newAnim->flags &= ~ASSOC_RUNNING;
+ }
+ }
- case ANIM_FIGHT_PPUNCH:
- attackAssoc->blendDelta = -8.0f;
- attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
- ped->ClearAttack();
- return;
+ if (!ped->bIsAttacking)
+ ped->ClearAttack();
- case ANIM_WEAPON_THROW:
- case ANIM_WEAPON_THROWU:
- if (ped->GetWeapon()->m_nAmmoTotal > 0) {
- currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
+ return;
+ }
+
+ // Not for unarmed, it's for weapons using unarmed anims
+ if (currentWeapon->m_bUse2nd && ped->bIsAttacking && currentWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) {
+ AnimationId groundAnim = GetFireAnimGround(currentWeapon);
+ CAnimBlendAssociation *groundAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), groundAnim);
+ if (!groundAnimAssoc || groundAnimAssoc->blendAmount <= 0.95f && groundAnimAssoc->blendDelta <= 0.0f) {
+ if (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK) {
+ newAnim = CAnimManager::BlendAnimation(
+ ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_2ND, 8.0f);
+ } else {
+ newAnim = CAnimManager::BlendAnimation(
+ ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK, 8.0f);
+ }
+ newAnim->SetFinishCallback(FinishedAttackCB, ped);
+ }
+ } else {
+ if (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK && currentWeapon->m_AnimToPlay == ASSOCGRP_UNARMED)
+ {
+ attackAssoc->blendDelta = -8.0f;
+ attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ped->ClearAttack();
+ return;
+ }
+ if (attackAssoc)
+ {
+ if (currentWeapon->m_AnimToPlay == ASSOCGRP_THROW)
+ {
+ if ((attackAssoc->animId == ANIM_THROWABLE_THROW || attackAssoc->animId == ANIM_THROWABLE_THROWU) && ped->GetWeapon()->m_nAmmoTotal > 0)
+ {
+ ped->RemoveWeaponModel(currentWeapon->m_nModelId);
ped->AddWeaponModel(currentWeapon->m_nModelId);
}
- break;
- default:
- break;
+ }
}
+
+ if (!ped->bIsAttacking)
+ ped->ClearAttack();
}
-
- if (!ped->bIsAttacking)
- ped->ClearAttack();
}
+// --MIAMI: Done except melee weapons
void
CPed::Attack(void)
{
CAnimBlendAssociation *weaponAnimAssoc;
int32 weaponAnim;
- float animStart;
eWeaponType ourWeaponType;
float weaponAnimTime;
eWeaponFire ourWeaponFire;
@@ -1177,58 +1299,131 @@ CPed::Attack(void)
bool attackShouldContinue;
AnimationId reloadAnim;
CAnimBlendAssociation *reloadAnimAssoc;
+ CAnimBlendAssociation *throwAssoc;
float delayBetweenAnimAndFire;
+ float animLoopStart;
CVector firePos;
ourWeaponType = GetWeapon()->m_eWeaponType;
ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
ourWeaponFire = ourWeapon->m_eWeaponFire;
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
+ weaponAnimAssoc = nil;
attackShouldContinue = bIsAttacking;
reloadAnimAssoc = nil;
+ throwAssoc = nil;
reloadAnim = NUM_ANIMS;
+ animLoopStart = ourWeapon->m_fAnimLoopStart;
+ animLoopEnd = ourWeapon->m_fAnimLoopEnd;
delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire;
weaponAnim = ourWeapon->m_AnimToPlay;
- if (weaponAnim == ANIM_WEAPON_HGUN_BODY)
- reloadAnim = ANIM_HGUN_RELOAD;
- else if (weaponAnim == ANIM_WEAPON_AK_BODY)
- reloadAnim = ANIM_AK_RELOAD;
+ if (bIsDucking) {
+ if (!!ourWeapon->m_bCrouchFire && bCrouchWhenShooting) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(ourWeapon));
+ if (weaponAnimAssoc) {
+ animLoopStart = ourWeapon->m_fAnim2LoopStart;
+ animLoopEnd = ourWeapon->m_fAnim2LoopEnd;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
+ }
+ }
+ } else {
+ AnimationId anim = GetFireAnimNotDucking(ourWeapon);
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), anim);
+ if (anim == ANIM_WEAPON_FIRE_3RD && weaponAnimAssoc) {
+ animLoopStart = 11.f/30.f;
+ animLoopEnd = 19.f/30.f;
+ delayBetweenAnimAndFire = 14.f/30.f;
+ }
+ }
- if (reloadAnim != NUM_ANIMS)
- reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
+ if (ourWeapon->m_bReload) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(ourWeapon));
+ }
- if (bIsDucking)
- return;
+ if (!!ourWeapon->m_bReload && !reloadAnimAssoc) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(ourWeapon));
+ }
- if (reloadAnimAssoc) {
+ if ( reloadAnimAssoc && reloadAnimAssoc->IsRunning() ) {
if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)
ClearAttack();
-
return;
}
- if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ if ( reloadAnimAssoc ) {
+ reloadAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if ( reloadAnimAssoc->blendDelta >= 0.0f )
+ reloadAnimAssoc->blendDelta = -8.0f;
+ }
+
+ if (!!ourWeapon->m_bThrow) {
+ throwAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_THROWABLE_START_THROW);
+ }
+
+ if ( CTimer::GetTimeInMilliseconds() < m_shootTimer )
attackShouldContinue = true;
+ bool meleeAttackStarted = false;
+ if ( !weaponAnimAssoc ) {
+ if (!!ourWeapon->m_bPartialAttack) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_ATTACK_START);
+ if ( weaponAnimAssoc ) {
+ if ( IsPlayer() )
+ meleeAttackStarted = true;
+
+ switch ( ourWeapon->m_AnimToPlay ) {
+ case ASSOCGRP_UNARMED:
+ case ASSOCGRP_SCREWDRIVER:
+ case ASSOCGRP_KNIFE:
+ case ASSOCGRP_BASEBALLBAT:
+ case ASSOCGRP_GOLFCLUB:
+ case ASSOCGRP_CHAINSAW:
+ delayBetweenAnimAndFire = 0.2f;
+ animLoopStart = 0.1f;
+ break;
+ default:
+ break;
+ }
+ animLoopEnd = 99.9f;
+ }
+ }
+ }
if (!weaponAnimAssoc) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay);
- delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
-
- // Long throw granade, molotov
- if (!weaponAnimAssoc && ourWeapon->m_bThrow) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
- delayBetweenAnimAndFire = 0.2f;
+ if (!!ourWeapon->m_bUse2nd) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE_2ND);
+ if (weaponAnimAssoc) {
+ animLoopStart = ourWeapon->m_fAnim2LoopStart;
+ animLoopEnd = ourWeapon->m_fAnim2LoopEnd;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
+ }
+ }
+ }
+ if (!weaponAnimAssoc) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(ourWeapon));
+ if (weaponAnimAssoc) {
+ animLoopStart = ourWeapon->m_fAnim2LoopStart;
+ animLoopEnd = ourWeapon->m_fAnim2LoopEnd;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
}
+ }
- if (!weaponAnimAssoc) {
+ if (!weaponAnimAssoc) {
+ if (!throwAssoc) {
if (attackShouldContinue) {
if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
- if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
- }
- else {
- weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ if (bCrouchWhenShooting && bIsDucking && !!ourWeapon->m_bCrouchFire) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f);
+
+ } else if(!!ourWeapon->m_bUse2nd && CGeneral::GetRandomNumber() & 1){
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE_2ND, 8.0f);
+
+ } else if (!CGame::nastyGame || (!ourWeapon->m_bGround2nd && !ourWeapon->m_bGround3rd) ||
+ ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
+
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimNotDucking(ourWeapon), 8.0f);
+
+ } else {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimGround(ourWeapon, false), 8.0f);
}
weaponAnimAssoc->SetFinishCallback(CPed::FinishedAttackCB, this);
@@ -1245,66 +1440,83 @@ CPed::Attack(void)
} else
FinishedAttackCB(nil, this);
- return;
}
+ return;
}
- animStart = ourWeapon->m_fAnimLoopStart;
+ if (meleeAttackStarted && IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bHaveTargetSelected || ((CPlayerPed*)this)->m_fMoveSpeed < 0.5f) {
+ weaponAnimAssoc->SetRun();
+ } else {
+ if (weaponAnimAssoc->currentTime > animLoopStart && weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= animLoopStart)
+ weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
+ }
+ }
+
+ float animStart = ourWeapon->m_fAnimLoopStart * 0.4f;
weaponAnimTime = weaponAnimAssoc->currentTime;
if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
- if (ourWeapon->m_bCanAimWithArm)
+ if (!bIsDucking && !(m_nPedType == PEDTYPE_COP && ourWeapon->m_bCop3rd && weaponAnimAssoc->animId == ANIM_WEAPON_FIRE_3RD) && ourWeapon->m_bCanAimWithArm)
m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
else
m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
+ // TODO(Miami): Chainsaw
if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
if (weaponAnimAssoc->speed < 1.0f)
weaponAnimAssoc->speed = 1.0f;
} else {
firePos = ourWeapon->m_vecFireOffset;
- if (ourWeaponType == WEAPONTYPE_BASEBALLBAT) {
- if (weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;
+ // TODO(Miami): Katana & Chainsaw
+ if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) {
firePos = GetMatrix() * firePos;
- } else if (ourWeaponType != WEAPONTYPE_UNARMED) {
- TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR);
} else {
- firePos = GetMatrix() * firePos;
+ TransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR);
}
GetWeapon()->Fire(this, &firePos);
- if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) {
+ // TODO(Miami)
+ if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE
+ /* ourWeaponType == WEAPONTYPE_TEARGAS*/) {
RemoveWeaponModel(ourWeapon->m_nModelId);
}
if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
SelectGunIfArmed();
}
- if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) {
- // If reloading just began, start the animation
- // Last condition will always return true, even IDA hides it
- if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS /* && !reloadAnimAssoc*/) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f);
- ClearLookFlag();
- ClearAimFlag();
- bIsAttacking = false;
- bIsPointingGunAt = false;
- m_shootTimer = CTimer::GetTimeInMilliseconds();
- return;
+ if (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) {
+ int damagerType = 0;
+ if (m_pDamageEntity && (m_fDamageImpulse == 0.0f || !m_pDamageEntity->IsBuilding())) {
+ damagerType = m_pDamageEntity->GetType();
}
- } else {
- if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
- } else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ switch (ourWeapon->m_AnimToPlay) {
+ case ASSOCGRP_UNARMED:
+ if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) {
+#ifdef AUDIO_NOT_READY
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+#else
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, (damagerType | (ourWeaponType << 8)));
+#endif
+ }
+ break;
+ case ASSOCGRP_KNIFE:
+ case ASSOCGRP_BASEBALLBAT:
+ case ASSOCGRP_GOLFCLUB:
+ case ASSOCGRP_CHAINSAW:
+#ifdef AUDIO_NOT_READY
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
+#else
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (ourWeaponType << 8)));
+#endif
+ break;
+ default:
+ break;
}
- weaponAnimAssoc->speed = 0.5f;
-
if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
weaponAnimAssoc->callbackType = 0;
}
@@ -1313,10 +1525,11 @@ CPed::Attack(void)
attackShouldContinue = false;
}
- if (ourWeaponType == WEAPONTYPE_SHOTGUN) {
+ if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && ourWeapon->m_AnimToPlay == ASSOCGRP_SHOTGUN) {
weaponAnimTime = weaponAnimAssoc->currentTime;
firePos = ourWeapon->m_vecFireOffset;
+ //TODO(Miami): Check
if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {
TransformToNode(firePos, PED_HANDR);
@@ -1335,58 +1548,52 @@ CPed::Attack(void)
GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);
}
}
-#ifdef VC_PED_PORTS
+
+ // TODO(Miami): CSpecialFX::AddWeaponStreak
+
+ // Anim breakout on running
if (IsPlayer()) {
if (CPad::GetPad(0)->GetSprint()) {
- // animBreakout is a member of WeaponInfo in VC, so it's me that added the below line.
- float animBreakOut = ((ourWeaponType == WEAPONTYPE_FLAMETHROWER || ourWeaponType == WEAPONTYPE_UZI || ourWeaponType == WEAPONTYPE_SHOTGUN) ? 25 / 30.0f : 99 / 30.0f);
- if (!attackShouldContinue && weaponAnimAssoc->currentTime > animBreakOut) {
+ if (!attackShouldContinue && weaponAnimAssoc->currentTime > ourWeapon->m_fAnimBreakout) {
weaponAnimAssoc->blendDelta = -4.0f;
FinishedAttackCB(nil, this);
return;
}
}
}
-#endif
- animLoopEnd = ourWeapon->m_fAnimLoopEnd;
- if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- animLoopEnd = 3.4f/6.0f;
weaponAnimTime = weaponAnimAssoc->currentTime;
// Anim loop end, either start the loop again or finish the attack
if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) {
-
- if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd
- && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)
- && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
-
- weaponAnim = weaponAnimAssoc->animId;
- if (ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) {
- weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart);
- } else {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
+ if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING) {
+ if (ourWeapon->m_bReload && !reloadAnimAssoc) {
+ if (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) {
+ CAnimBlendAssociation *newReloadAssoc;
+ if (bIsDucking) {
+ newReloadAssoc = CAnimManager::BlendAnimation(
+ GetClump(), ourWeapon->m_AnimToPlay,
+ GetCrouchReloadAnim(ourWeapon),
+ 8.0f);
+ } else {
+ newReloadAssoc = CAnimManager::BlendAnimation(
+ GetClump(), ourWeapon->m_AnimToPlay,
+ GetReloadAnim(ourWeapon),
+ 8.0f);
+ }
+ newReloadAssoc->SetFinishCallback(FinishedReloadCB, this);
}
- } else {
- if (weaponAnim == ourWeapon->m_Anim2ToPlay)
- weaponAnimAssoc->SetCurrentTime(0.1f);
- else
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
- }
-#ifdef VC_PED_PORTS
- } else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
- weaponAnimAssoc->SetCurrentTime(ourWeapon->m_fAnimLoopEnd);
- weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
- SetPointGunAt(m_pPointGunAt);
-#endif
- } else {
- ClearAimFlag();
-
- // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
- if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) {
+ ClearLookFlag();
+ ClearAimFlag();
+ bIsAttacking = false;
+ bIsPointingGunAt = false;
+ m_shootTimer = CTimer::GetTimeInMilliseconds();
+#ifdef AUDIO_NOT_READY
switch (ourWeaponType) {
case WEAPONTYPE_UZI:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
break;
case WEAPONTYPE_AK47:
@@ -1398,22 +1605,92 @@ CPed::Attack(void)
default:
break;
}
+#else
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);
+#endif
+ return;
}
+ }
+ if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd
+ && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ && (GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING
+ /* || GetWeapon()->m_nWeaponType == WEAPONTYPE_MINIGUN */)) {
- // Fun fact: removing this part leds to reloading flamethrower
- if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
- weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
- weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
- weaponAnimAssoc->blendDelta = -4.0f;
+ PedOnGroundState pedOnGroundState;
+ if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE &&
+ (CGame::nastyGame && ((pedOnGroundState = CheckForPedsOnGroundToAttack(this, nil)) > PED_IN_FRONT_OF_ATTACKER)
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {
+
+ AnimationId fireAnim = GetFireAnimGround(ourWeapon, false);
+ if (weaponAnimAssoc->animId == fireAnim)
+ weaponAnimAssoc->SetCurrentTime(0.1f);
+ else {
+ if (fireAnim) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, fireAnim, 8.0f);
+ } else {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_KICK_FLOOR, 8.0f);
+ }
+ }
+ weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
+ } else if (!!ourWeapon->m_bUse2nd) {
+ if (weaponAnimAssoc->animId == ANIM_WEAPON_FIRE_2ND) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE, 8.0f);
+ } else {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE_2ND, 8.0f);
+ }
+ weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
+ } else {
+ weaponAnimAssoc->SetCurrentTime(animLoopStart);
+ weaponAnimAssoc->SetRun();
+ }
+ }
+ } else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
+ weaponAnimAssoc->SetCurrentTime(animLoopEnd);
+ weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
+ SetPointGunAt(m_pPointGunAt);
+ } else {
+ ClearAimFlag();
+
+ // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
+ if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < animLoopEnd) {
+
+#ifdef AUDIO_NOT_READY
+ switch (ourWeaponType) {
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
+ break;
+ case WEAPONTYPE_AK47:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f);
+ break;
+ case WEAPONTYPE_M16:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f);
+ break;
+ default:
+ break;
}
+#else
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);
+#endif
+ }
+
+ // Fun fact: removing this part leds to reloading flamethrower
+ if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
+ weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
+ weaponAnimAssoc->blendDelta = -4.0f;
}
}
+
if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire)
attackShouldContinue = false;
bIsAttacking = attackShouldContinue;
}
+// --MIAMI: Done
void
CPed::RemoveWeaponModel(int modelId)
{
@@ -1421,40 +1698,75 @@ CPed::RemoveWeaponModel(int modelId)
#ifdef PED_SKIN
if(IsClumpSkinned(GetClump())){
if(m_pWeaponModel){
- RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel);
- RpAtomicDestroy(m_pWeaponModel);
- RwFrameDestroy(frm);
- m_pWeaponModel = nil;
+ if (modelId == -1
+ || CVisibilityPlugins::GetAtomicModelInfo(m_pWeaponModel) == CModelInfo::GetModelInfo(modelId)) {
+ CVisibilityPlugins::GetAtomicModelInfo(m_pWeaponModel)->RemoveRef();
+ RwFrame* frm = RpAtomicGetFrame(m_pWeaponModel);
+ RpAtomicDestroy(m_pWeaponModel);
+ RwFrameDestroy(frm);
+ m_pWeaponModel = nil;
+ }
}
}else
#endif
RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil);
+
+ // TODO(Miami): Minigun
+ if (IsPlayer() && (modelId == -1 /* || modelId == MI_MINIGUN)*/)) {
+ RpAtomic* &atm = ((CPlayerPed*)this)->m_pMinigunTopAtomic;
+ if (atm) {
+ RwFrame *frm = RpAtomicGetFrame(atm);
+ RpAtomicDestroy(atm);
+ RwFrameDestroy(frm);
+ atm = nil;
+ }
+ }
m_wepModelID = -1;
}
+// --MIAMI: Done
void
-CPed::SetCurrentWeapon(uint32 weaponType)
+CPed::SetCurrentWeapon(eWeaponType weaponType)
{
- CWeaponInfo *weaponInfo;
- if (HasWeapon(weaponType)) {
+ SetCurrentWeapon(CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot);
+}
+
+// --MIAMI: Done
+void
+CPed::SetCurrentWeapon(int slot)
+{
+ if (slot == -1)
+ return;
+
+ CWeaponInfo* weaponInfo;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(weaponInfo->m_nModelId);
+ }
+ m_currentWeapon = slot;
- m_currentWeapon = weaponType;
+ if (FindPlayerPed() && IsPlayer())
+ ((CPlayerPed*)this)->m_nSelectedWepSlot = m_currentWeapon;
+ if (HasWeaponSlot(slot)) {
weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
AddWeaponModel(weaponInfo->m_nModelId);
}
}
+// --MIAMI: Done
// Only used while deciding which gun ped should switch to, if no ammo left.
bool
CPed::SelectGunIfArmed(void)
{
- for (int i = 0; i < m_maxWeaponTypeAllowed; i++) {
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
if (GetWeapon(i).m_nAmmoTotal > 0) {
eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
- if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) {
+
+ // First condition checks for Pistol, Python and Shotguns
+ if ((weaponType >= WEAPONTYPE_COLT45 && weaponType < WEAPONTYPE_TEC9) ||
+ weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M16 || weaponType == WEAPONTYPE_MP5 ||
+ weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_SNIPERRIFLE) {
SetCurrentWeapon(i);
return true;
}
@@ -1464,38 +1776,54 @@ CPed::SelectGunIfArmed(void)
return false;
}
+// --MIAMI: Done
void
CPed::Duck(void)
{
if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
ClearDuck();
+ else if (bIsDucking && bCrouchWhenShooting) {
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CAnimBlendAssociation *attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH);
+ if (!attackAssoc) {
+ if(!!weapon->m_bCrouchFire)
+ attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));
+ }
+ if (!attackAssoc) {
+ if(!!weapon->m_bReload)
+ attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(weapon));
+ }
+ if (!attackAssoc) {
+ bIsDucking = false;
+ }
+ }
}
+// --MIAMI: Done
void
-CPed::ClearDuck(void)
+CPed::ClearDuck(bool clearTimer)
{
CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
if (!animAssoc) {
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
-
- if (!animAssoc) {
- bIsDucking = false;
- return;
- }
}
- if (!bCrouchWhenShooting)
- return;
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH);
+ }
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN)
- return;
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -4.0f;
+ }
+ bIsDucking = false;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
- if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ if (clearTimer) {
+ m_duckTimer = 0;
}
}
+// --MIAMI: Done
void
CPed::ClearPointGunAt(void)
{
@@ -1505,27 +1833,24 @@ CPed::ClearPointGunAt(void)
ClearLookFlag();
ClearAimFlag();
bIsPointingGunAt = false;
-#ifndef VC_PED_PORTS
- if (m_nPedState == PED_AIM_GUN) {
- RestorePreviousState();
-#else
if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {
+
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
m_nPedState = PED_IDLE;
RestorePreviousState();
}
-#endif
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
- if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
- }
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -4.0f;
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ if (!animAssoc || animAssoc->blendDelta < 0.0f) {
+ if (!!weaponInfo->m_bCrouchFire) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo));
}
-#ifndef VC_PED_PORTS
}
-#endif
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -4.0f;
+ }
}
void
@@ -1850,7 +2175,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
case ANIM_VAN_GETIN:
#ifdef VC_PED_PORTS
multExtractedFromAnim = true;
- zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f);
+ zBlend = Max(m_pVehicleAnim->GetProgress() - 0.3f, 0.0f) / (1.0f - 0.3f);
// fall through
#endif
case ANIM_CAR_QJACKED:
@@ -1861,7 +2186,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
#ifdef VC_PED_PORTS
if (!multExtractedFromAnim) {
multExtractedFromAnim = true;
- zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f);
+ zBlend = Max(m_pVehicleAnim->GetProgress() - 0.5f, 0.0f) / (1.0f - 0.5f);
}
// fall through
#endif
@@ -1869,14 +2194,14 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
case ANIM_CAR_CRAWLOUT_RHS2:
case ANIM_VAN_GETOUT_L:
case ANIM_VAN_GETOUT:
- seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength;
+ seatPosMult = m_pVehicleAnim->GetProgress();
break;
case ANIM_CAR_GETIN_RHS:
case ANIM_CAR_GETIN_LHS:
#ifdef VC_PED_PORTS
if (veh && veh->IsCar() && veh->bIsBus) {
multExtractedFromAnimBus = true;
- zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f;
+ zBlend = Min(m_pVehicleAnim->GetProgress(), 0.5f) / 0.5f;
}
// fall through
#endif
@@ -2345,6 +2670,7 @@ CPed::SetPedStats(ePedStats pedStat)
m_pedStats = CPedStats::ms_apPedStats[pedStat];
}
+// --MIAMI: Done
void
CPed::SetModelIndex(uint32 mi)
{
@@ -2357,19 +2683,37 @@ CPed::SetModelIndex(uint32 mi)
m_animGroup = (AssocGroupId) modelInfo->m_animGroup;
CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE);
+ // TODO(Miami): This is inlined CanUseTorsoWhenLooking
+ bool canUseMyBody = false;
+ if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) {
+ if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN)
+ canUseMyBody = true;
+ }
+ if (!canUseMyBody)
+ m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;
+
// This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
(*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
#ifdef PED_SKIN
if(modelInfo->GetHitColModel() == nil)
modelInfo->CreateHitColModelSkinned(GetClump());
+
+ if (IsClumpSkinned(GetClump())) // condition isn't there in VC
+ UpdateRpHAnim();
#endif
}
void
CPed::RemoveLighting(bool reset)
{
- CRenderer::RemoveVehiclePedLights(this, reset);
+ if (!bRenderScorched) {
+ CRenderer::RemoveVehiclePedLights(this, reset);
+ if (reset)
+ ReSetAmbientAndDirectionalColours();
+ }
+ SetAmbientColours();
+ DeActivateDirectional();
}
bool
@@ -2434,14 +2778,15 @@ CPed::WorkOutHeadingForMovingFirstPerson(float offset)
angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
} else {
if (leftRight < 0.0f)
- angle = 0.5f * PI;
+ angle = HALFPI;
else if (leftRight > 0.0f)
- angle = -0.5f * PI;
+ angle = -HALFPI;
}
return CGeneral::LimitRadianAngle(offset + angle);
}
+// --MIAMI: Done
void
CPed::CalculateNewVelocity(void)
{
@@ -2456,9 +2801,6 @@ CPed::CalculateNewVelocity(void)
limitedRotDest -= 2 * PI;
}
- if (IsPlayer() && m_nPedState == PED_ATTACK)
- headAmount /= 4.0f;
-
float neededTurn = limitedRotDest - m_fRotationCur;
if (neededTurn <= headAmount) {
if (neededTurn > (-headAmount))
@@ -2482,8 +2824,12 @@ CPed::CalculateNewVelocity(void)
}
if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam())
- || FindPlayerPed() != this || !CanStrafeOrMouseControl())
+ || FindPlayerPed() != this || !CanStrafeOrMouseControl()) {
+
+ if (FindPlayerPed() == this)
+ FindPlayerPed()->m_fWalkAngle = 0.0f;
return;
+ }
float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur);
float pedSpeed = m_moved.Magnitude();
@@ -2503,16 +2849,13 @@ CPed::CalculateNewVelocity(void)
CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
-#ifdef VC_PED_PORTS
if(!fightAssoc)
fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- // There is one more anim in VC.
+ if(!fightAssoc)
+ fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHRELOAD);
if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) {
-#else
- if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
-#endif
LimbOrientation newUpperLegs;
newUpperLegs.yaw = localWalkAngle;
@@ -2523,31 +2866,14 @@ CPed::CalculateNewVelocity(void)
}
if (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) {
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
-/*
- // this looks shit
- newUpperLegs.pitch = 0.0f;
- RwV3d axis = { -1.0f, 0.0f, 0.0f };
- RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT);
-*/
- newUpperLegs.pitch = 0.1f;
- RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
- RwV3d Zaxis = { 0.0f, 0.0f, 1.0f };
- RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
-
- bDontAcceptIKLookAts = true;
- }else
-#endif
- {
- newUpperLegs.pitch = 0.0f;
- m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false);
- m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false);
- }
+ newUpperLegs.pitch = 0.1f;
+ RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+ RwV3d Zaxis = { 0.0f, 0.0f, 1.0f };
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
+ bDontAcceptIKLookAts = true;
}
}
}
@@ -3601,29 +3927,40 @@ CPed::ClearAttack(void)
}
}
+// --MIAMI: Done
void
CPed::ClearAttackByRemovingAnim(void)
{
- if (m_nPedState != PED_ATTACK || bIsDucking)
+ if (m_nPedState != PED_ATTACK)
return;
CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay);
- if (!weaponAssoc) {
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay);
-
- if (!weaponAssoc && weapon->m_bThrow)
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(weapon));
- if (!weaponAssoc) {
- ClearAttack();
- return;
- }
+ if (!weaponAssoc) {
+ if (!!weapon->m_bCrouchFire)
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));
+ }
+ if (!weaponAssoc) {
+ if(!!weapon->m_bFinish3rd)
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_SPECIAL);
+ }
+ if (!weaponAssoc) {
+ if(!!weapon->m_bUse2nd)
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE);
+ }
+ if (!weaponAssoc) {
+ if(!!weapon->m_bCop3rd)
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_SPECIAL);
+ }
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = -8.0f;
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
+ } else {
+ ClearAttack();
}
- weaponAssoc->blendDelta = -8.0f;
- weaponAssoc->flags &= ~ASSOC_RUNNING;
- weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
- weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
}
void
@@ -3656,6 +3993,8 @@ CPed::SetStoredState(void)
void
CPed::SetDie(AnimationId animId, float delta, float speed)
{
+ if (m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
CPlayerPed *player = FindPlayerPed();
if (player == this) {
if (!player->m_bCanBeDamaged)
@@ -3877,6 +4216,9 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
break;
case WEAPONTYPE_COLT45:
case WEAPONTYPE_UZI:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
case WEAPONTYPE_SHOTGUN:
case WEAPONTYPE_AK47:
case WEAPONTYPE_M16:
@@ -4238,6 +4580,9 @@ CPed::SetGetUp(void)
}
if (m_nPedState != PED_GETUP) {
SetStoredState();
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
m_nPedState = PED_GETUP;
}
@@ -4246,7 +4591,7 @@ CPed::SetGetUp(void)
if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE ||
collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE
&& ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 ||
- CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(),
+ CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(),
aTempPedColPts, nil, nil) > 0)) {
bGetUpAnimStarted = false;
@@ -4425,25 +4770,15 @@ CPed::SetWanderPath(int8 pathStateDest)
}
}
+// --MIAMI: Done
void
CPed::ClearWeapons(void)
{
- CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(currentWeapon->m_nModelId);
-
- m_maxWeaponTypeAllowed = WEAPONTYPE_BASEBALLBAT;
- m_currentWeapon = WEAPONTYPE_UNARMED;
-
- currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- AddWeaponModel(currentWeapon->m_nModelId);
- for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
- CWeapon &weapon = GetWeapon(i);
- weapon.m_eWeaponType = WEAPONTYPE_UNARMED;
- weapon.m_eWeaponState = WEAPONSTATE_READY;
- weapon.m_nAmmoInClip = 0;
- weapon.m_nAmmoTotal = 0;
- weapon.m_nTimer = 0;
+ RemoveWeaponModel(-1);
+ for (int i = 0; i < ARRAY_SIZE(m_weapons); i++) {
+ GetWeapon(i).Shutdown();
}
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
}
void
@@ -4548,68 +4883,100 @@ CPed::SetAimFlag(float angle)
m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
+// --MIAMI: Done
void
CPed::SetPointGunAt(CEntity *to)
{
if (to) {
SetLookFlag(to, true);
SetAimFlag(to);
-#ifdef VC_PED_PORTS
SetLookTimer(INT32_MAX);
-#endif
}
- if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
+ CWeaponInfo* curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (m_nPedState == PED_AIM_GUN || (bIsDucking && !IsPlayer()) || m_nWaitState == WAITSTATE_PLAYANIM_DUCK || curWeapon->m_AnimToPlay == ASSOCGRP_STD)
return;
if (m_nPedState != PED_ATTACK)
SetStoredState();
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
m_nPedState = PED_AIM_GUN;
bIsPointingGunAt = true;
- CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
SetMoveState(PEDMOVE_NONE);
CAnimBlendAssociation *aimAssoc;
- if (bCrouchWhenShooting)
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay);
- else
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay);
+ if (bCrouchWhenShooting && bIsDucking) {
+ if (!!curWeapon->m_bCrouchFire) {
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
+ }
+ } else {
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ }
if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
- if (bCrouchWhenShooting)
- aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f);
- else
- aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay);
+ if (bCrouchWhenShooting && bIsDucking) {
+ if (!!curWeapon->m_bCrouchFire) {
+ aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f);
+ }
+ } else {
+ aimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE);
+ }
aimAssoc->blendAmount = 0.0f;
aimAssoc->blendDelta = 8.0f;
}
- if (to)
+ if (to && !IsPlayer())
Say(SOUND_PED_ATTACK);
}
+// --MIAMI: Done
void
CPed::SetAmmo(eWeaponType weaponType, uint32 ammo)
{
- if (HasWeapon(weaponType)) {
- GetWeapon(weaponType).m_nAmmoTotal = ammo;
+ int slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;
+ if (slot == -1)
+ return;
+
+ GetWeapon(slot).m_nAmmoTotal = ammo;
+ if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) {
+
+ // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1.
+ GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal);
} else {
- GetWeapon(weaponType).Initialise(weaponType, ammo);
- m_maxWeaponTypeAllowed++;
+ GetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal);
}
+ int32 newClip = GetWeapon(slot).m_nAmmoTotal;
+ if (newClip >= GetWeapon(slot).m_nAmmoInClip)
+ newClip = GetWeapon(slot).m_nAmmoInClip;
+ GetWeapon(slot).m_nAmmoInClip = newClip;
+
+ if (GetWeapon(slot).m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO && GetWeapon(slot).m_nAmmoTotal > 0)
+ GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;
}
+// --MIAMI: Done
void
CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo)
{
- if (HasWeapon(weaponType)) {
- GetWeapon(weaponType).m_nAmmoTotal += ammo;
+ int slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;
+ if (slot == -1)
+ return;
+
+ GetWeapon(slot).m_nAmmoTotal += ammo;
+ if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) {
+
+ // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1.
+ GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal);
} else {
- GetWeapon(weaponType).Initialise(weaponType, ammo);
- m_maxWeaponTypeAllowed++;
+ GetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal);
}
+
+ if (GetWeapon(slot).m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO && GetWeapon(slot).m_nAmmoTotal > 0)
+ GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;
}
void
@@ -4800,28 +5167,22 @@ CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)
}
}
+// --MIAMI: Done
void
CPed::SetAttack(CEntity *victim)
{
CPed *victimPed = nil;
+ CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CAnimBlendAssociation *animAssoc;
+
if (victim && victim->IsPed())
victimPed = (CPed*)victim;
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
- if (animAssoc) {
- animAssoc->blendDelta = -1000.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE)
- return;
-
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) {
- bIsAttacking = false;
+ if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE || (bIsDucking && !bCrouchWhenShooting))
return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) {
+ if (curWeapon->m_bReload &&
+ (RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(curWeapon)) || RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(curWeapon)))) {
if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)
bIsAttacking = false;
else
@@ -4830,20 +5191,20 @@ CPed::SetAttack(CEntity *victim)
return;
}
- CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) {
- if (GetWeapon()->HitsGround(this, nil, victim))
- return;
- }
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
+ // TODO(Miami): Brass knuckles
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || curWeapon->m_bFightMode || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) {
if (IsPlayer() ||
- (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
+ (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL
+ && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS) && curWeapon->m_bPartialAttack)) {
if (m_nPedState != PED_ATTACK) {
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
m_nPedState = PED_ATTACK;
bIsAttacking = false;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
+
+ CAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f);
animAssoc->SetRun();
if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
animAssoc->SetCurrentTime(0.0f);
@@ -4851,33 +5212,66 @@ CPed::SetAttack(CEntity *victim)
animAssoc->SetFinishCallback(FinishedAttackCB, this);
}
} else {
- StartFightAttack(CGeneral::GetRandomNumber() % 256);
+ StartFightAttack(CGeneral::GetRandomNumber());
+ }
+ return;
+ }
+
+ if (curWeapon->m_bPartialAttack &&
+ (IsPlayer() && ((CPlayerPed*)this)->m_fMoveSpeed >= 1.0f ||
+ m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN)) {
+
+ if (m_nPedState != PED_ATTACK) {
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
+ m_nPedState = PED_ATTACK;
+ bIsAttacking = false;
+ CAnimBlendAssociation* animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f);
+ animAssoc->SetRun();
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
}
return;
}
+ // TODO(Miami): Clean up old referene
m_pSeekTarget = victim;
if (m_pSeekTarget)
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
if (curWeapon->m_bCanAim) {
CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition();
+ aimPos += GetUp() * 0.35f;
CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
- if (obstacle)
- return;
+ if (obstacle) {
+ if(gaTempSphereColPoints[0].surfaceB != SURFACE_SCAFFOLD && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_FENCE &&
+ gaTempSphereColPoints[0].surfaceB != SURFACE_WOOD_BOX && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_POLE) {
+ if (!IsPlayer()) {
+ bObstacleShowedUpDuringKillObjective = true;
+ m_shootTimer = 0;
+ SetAttackTimer(1500);
+ m_shotTime = CTimer::GetTimeInMilliseconds();
+ }
+ return;
+ }
+ }
m_pLookTarget = victim;
if (victim) {
m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
}
+
if (m_pLookTarget) {
SetAimFlag(m_pLookTarget);
- } else {
+ } else if (this == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam()) {
+ SetAimFlag(m_fRotationCur);
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
+ } else if (curWeapon->m_bCanAimWithArm) {
SetAimFlag(m_fRotationCur);
-
- if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
}
}
if (m_nPedState == PED_ATTACK) {
@@ -4885,7 +5279,7 @@ CPed::SetAttack(CEntity *victim)
return;
}
- if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
+ if (IsPlayer() || (!victimPed || victimPed->IsPedInControl())) {
if (IsPlayer())
CPad::GetPad(0)->ResetAverageWeapon();
@@ -4899,7 +5293,7 @@ CPed::SetAttack(CEntity *victim)
ClearAimFlag();
// This condition is pointless
- if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed)
+ if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed && (IsPlayer() || !m_carInObjective))
StartFightAttack(200);
} else {
if (!curWeapon->m_bCanAim)
@@ -4908,21 +5302,45 @@ CPed::SetAttack(CEntity *victim)
if (m_nPedState != PED_AIM_GUN)
SetStoredState();
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
m_nPedState = PED_ATTACK;
SetMoveState(PEDMOVE_NONE);
- if (bCrouchWhenShooting) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ if (bCrouchWhenShooting && bIsDucking && !!curWeapon->m_bCrouchFire) {
+ CAnimBlendAssociation* curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
+ if (curMoveAssoc) {
+ if (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon))->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) {
+ delete curMoveAssoc;
+ }
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 8.0f);
} else {
float animDelta = 8.0f;
if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE)
animDelta = 1000.0f;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT
- || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta);
+ AnimationId fireAnim;
+ if (curWeapon->m_bThrow)
+ fireAnim = ANIM_THROWABLE_START_THROW;
+ else if (CGame::nastyGame && (curWeapon->m_bGround2nd || curWeapon->m_bGround3rd)) {
+ PedOnGroundState pedOnGround = CheckForPedsOnGroundToAttack(this, nil);
+ if (pedOnGround > PED_IN_FRONT_OF_ATTACKER || pedOnGround == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle()) {
+ fireAnim = GetFireAnimGround(curWeapon, false);
+ } else {
+ fireAnim = GetFireAnimNotDucking(curWeapon);
+ }
} else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
+ fireAnim = GetFireAnimNotDucking(curWeapon);
}
+
+ CAnimBlendAssociation* curFireAssoc = RpAnimBlendClumpGetAssociation(GetClump(), fireAnim);
+ if (curFireAssoc) {
+ if (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, fireAnim)->hierarchy->name, curFireAssoc->hierarchy->name) != 0) {
+ delete curFireAssoc;
+ }
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, fireAnim, animDelta);
}
animAssoc->SetRun();
@@ -4937,7 +5355,8 @@ CPed::SetAttack(CEntity *victim)
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
SetWaitState(WAITSTATE_SURPRISE, nil);
- SetLookFlag(victim, false);
+ // TODO(Miami): New parameter
+ SetLookFlag(victim, true); //true);
SetLookTimer(100);
}
@@ -5015,10 +5434,11 @@ CPed::StartFightAttack(uint8 buttonPressure)
nPlayerInComboMove = 0;
}
+// --MIAMI: Done
void
CPed::LoadFightData(void)
{
- float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
+ float startFireTime, endFireTime, comboFollowOnTime, strikeRadius, extendReachMultiplier;
int damage, flags;
char line[256], moveName[32], animName[32], hitLevel;
int moveId = 0;
@@ -5047,12 +5467,13 @@ CPed::LoadFightData(void)
sscanf(
&line[lp],
- "%s %f %f %f %f %c %s %d %d",
+ "%s %f %f %f %f %f %c %s %d %d",
moveName,
&startFireTime,
&endFireTime,
&comboFollowOnTime,
&strikeRadius,
+ &extendReachMultiplier,
&hitLevel,
animName,
&damage,
@@ -5065,6 +5486,7 @@ CPed::LoadFightData(void)
tFightMoves[moveId].endFireTime = endFireTime / 30.0f;
tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
tFightMoves[moveId].strikeRadius = strikeRadius;
+ tFightMoves[moveId].extendReachMultiplier = extendReachMultiplier;
tFightMoves[moveId].damage = damage;
tFightMoves[moveId].flags = flags;
@@ -5088,11 +5510,14 @@ CPed::LoadFightData(void)
break;
}
- if (strncmp(animName, "null", 4) != 0) {
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
- tFightMoves[moveId].animId = (AnimationId)animAssoc->animId;
- } else {
- tFightMoves[moveId].animId = ANIM_WALK;
+ if (strncmp(animName, "default", 8) != 0) {
+ if (strncmp(animName, "null", 5) != 0) {
+ animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
+ tFightMoves[moveId].animId = (AnimationId)animAssoc->animId;
+ }
+ else {
+ tFightMoves[moveId].animId = ANIM_WALK;
+ }
}
moveId++;
}
@@ -5115,7 +5540,7 @@ CPed::GetLocalDirection(const CVector2D &posOffset)
bool
CPed::FightStrike(CVector &touchedNodePos)
{
- CColModel *ourCol;
+ CColModel *hisCol;
CVector attackDistance;
ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
float maxDistanceToBeBeaten;
@@ -5139,41 +5564,26 @@ CPed::FightStrike(CVector &touchedNodePos)
if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
CVector nearPedCentre;
+
+ // Have to animate a skinned clump because the initial col model is useless
+ hisCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(nearPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(nearPed->GetClump());
+
nearPed->GetBoundCentre(nearPedCentre);
CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
// He can beat us
if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
-#ifdef PED_SKIN
- // Have to animate a skinned clump because the initial col model is useless
- if(IsClumpSkinned(GetClump()))
- ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump());
- else
-#endif
- if (nearPed->m_nPedState == PED_FALL
- || nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE
- || !nearPed->IsPedHeadAbovePos(-0.3f)) {
- ourCol = &CTempColModels::ms_colModelPedGroundHit;
- } else {
-#ifdef ANIMATE_PED_COL_MODEL
- ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(),
- RpClumpGetFrame(GetClump()));
-#else
- ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
-#endif
- }
-
- for (int j = 0; j < ourCol->numSpheres; j++) {
- attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
+ for (int j = 0; j < hisCol->numSpheres; j++) {
+ attackDistance = hisCol->spheres[j].center;
attackDistance -= touchedNodePos;
- CColSphere *ourPieces = ourCol->spheres;
- float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius;
+ CColSphere *hisPieces = hisCol->spheres;
+ float maxDistanceToBeat = hisPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius;
// We can beat him too
if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
pedFound = true;
- closestPedPiece = (ePedPieceTypes) ourPieces[j].piece;
+ closestPedPiece = (ePedPieceTypes) hisPieces[j].piece;
break;
}
}
@@ -5200,6 +5610,7 @@ CPed::FightStrike(CVector &touchedNodePos)
damageMult *= m_pedStats->m_attackStrength;
}
+ /*
// Change direction if we used kick.
if (m_lastFightMove == FIGHTMOVE_KICK) {
if (CGeneral::GetRandomNumber() & 1) {
@@ -5207,7 +5618,7 @@ CPed::FightStrike(CVector &touchedNodePos)
if (direction > 3)
direction -= 4;
}
- }
+ } */
nearPed->ReactToAttack(this);
// Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
@@ -5510,8 +5921,45 @@ CPed::SetWaitState(eWaitState state, void *time)
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
break;
+ case WAITSTATE_SIT_DOWN:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_DOWN, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ break;
+ case WAITSTATE_SIT_UP:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_UP, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;
+ break;
+ case WAITSTATE_SIT_IDLE:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_IDLE, 5000.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000);
+ break;
+ case WAITSTATE_USE_ATM:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ATM, 5000.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;
+ break;
+ case WAITSTATE_SUN_BATHE_PRE:
+ case WAITSTATE_SUN_BATHE_DOWN:
+ case WAITSTATE_SUN_BATHE_IDLE:
+ case WAITSTATE_RIOT:
+ case WAITSTATE_FAST_FALL:
+ case WAITSTATE_BOMBER:
+ case WAITSTATE_STRIPPER:
+ case WAITSTATE_GROUND_ATTACK:
+ case WAITSTATE_LANCESITTING:
+ case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:
+ assert(0);
default:
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
RestoreHeadingRate();
return;
}
@@ -5910,6 +6358,7 @@ CPed::CollideWithPed(CPed *collideWith)
}
}
+// --MIAMI: Done except commented thing
void
CPed::CreateDeadPedMoney(void)
{
@@ -5917,54 +6366,50 @@ CPed::CreateDeadPedMoney(void)
return;
int skin = GetModelIndex();
+
+ // TODO(Miami): New flag
if ((skin >= MI_COP && skin <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle)
return;
- int money = CGeneral::GetRandomNumber() % 60;
+ int money = m_nPedMoney;
if (money < 10)
return;
- if (money == 43)
- money = 700;
+ CVector pickupPos = GetPosition();
+ bool found;
- int pickupCount = money / 40 + 1;
+ int pickupCount = Min(money / 20 + 1, 7);
int moneyPerPickup = money / pickupCount;
for(int i = 0; i < pickupCount; i++) {
// (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish.
- float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x;
- float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y;
- bool found = false;
- float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f;
+ pickupPos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128);
+ pickupPos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128);
+ pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
if (found) {
- CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
+ CPickups::GenerateNewOne(CVector(pickupPos.x, pickupPos.y, pickupPos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3));
}
}
+ m_nPedMoney = 0;
}
void
-CPed::CreateDeadPedWeaponPickups(void)
+CPed::CreateDeadPedPickupCoors(float *x, float *y, float *z)
{
bool found = false;
- float angleToPed;
CVector pickupPos;
- if (bInVehicle)
- return;
+#define NUMBER_OF_ATTEMPTS 32
+ for (int i = 0; i < NUMBER_OF_ATTEMPTS; i++) {
- for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
-
- eWeaponType weapon = GetWeapon(i).m_eWeaponType;
- int weaponAmmo = GetWeapon(i).m_nAmmoTotal;
- if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0)
- continue;
-
- angleToPed = i * 1.75f;
pickupPos = GetPosition();
- pickupPos.x += 1.5f * Sin(angleToPed);
- pickupPos.y += 1.5f * Cos(angleToPed);
+ pickupPos.x = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x;
+ pickupPos.y = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y;
pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+ if (!found)
+ continue;
+
CVector pedPos = GetPosition();
pedPos.z += 0.3f;
@@ -5972,21 +6417,53 @@ CPed::CreateDeadPedWeaponPickups(void)
float distance = pedToPickup.Magnitude();
// outer edge of pickup
- distance = (distance + 0.3f) / distance;
+ distance = (distance + 0.4f) / distance;
CVector pickupPos2 = pedPos;
pickupPos2 += distance * pedToPickup;
- // pickup must be on ground and line to its edge must be clear
- if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) {
- // otherwise try another position (but disregard second check apparently)
- angleToPed += 3.14f;
- pickupPos = GetPosition();
- pickupPos.x += 1.5f * Sin(angleToPed);
- pickupPos.y += 1.5f * Cos(angleToPed);
- pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+ if ((pickupPos - FindPlayerCoors()).Magnitude2D() > 2.0f || i > NUMBER_OF_ATTEMPTS / 2) {
+
+ if (i > NUMBER_OF_ATTEMPTS / 2 || !CPickups::TestForPickupsInBubble(pickupPos, 1.3f)) {
+
+ if (CWorld::GetIsLineOfSightClear(pickupPos2, pedPos,
+ true, i < NUMBER_OF_ATTEMPTS / 2, false, i < NUMBER_OF_ATTEMPTS / 2, false, false, false)) {
+
+ if (i > NUMBER_OF_ATTEMPTS / 2 || !CWorld::TestSphereAgainstWorld(pickupPos, 1.2f, nil, false, true, false, false, false, false)) {
+ *x = pickupPos.x;
+ *y = pickupPos.y;
+ *z = pickupPos.z;
+ return;
+ }
+ }
+ }
+ }
+ }
+ *x = GetPosition().x;
+ *y = GetPosition().y;
+ *z = GetPosition().z + 0.4f;
+#undef NUMBER_OF_ATTEMPTS
+}
+
+void
+CPed::CreateDeadPedWeaponPickups(void)
+{
+ CVector pickupPos;
+
+ if (bInVehicle)
+ return;
+
+ for(int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
+
+ eWeaponType weapon = GetWeapon(i).m_eWeaponType;
+ int weaponAmmo = GetWeapon(i).m_nAmmoTotal;
+ if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || (weaponAmmo == 0 && !GetWeapon(i).IsTypeMelee()))
+ continue;
+
+ int quantity = Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon] / 2);
+ CreateDeadPedPickupCoors(&pickupPos.x, &pickupPos.y, &pickupPos.z);
+ if (!CPickups::TryToMerge_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, quantity, false)) {
+ CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, quantity));
}
- if (found)
- CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon]));
}
ClearWeapons();
}
@@ -6077,18 +6554,57 @@ CPed::SetChat(CEntity *chatWith, uint32 time)
m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
}
+// --MIAMI: Done
+void
+CPed::RemoveWeaponAnims(int unused, float animDelta)
+{
+ CAnimBlendAssociation *weaponAssoc;
+ //CWeaponInfo::GetWeaponInfo(unused);
+
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_RELOAD);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHRELOAD);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_SPECIAL);
+ if (weaponAssoc) {
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (weaponAssoc->flags & ASSOC_PARTIAL)
+ weaponAssoc->blendDelta = animDelta;
+ else
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, -animDelta);
+ }
+}
+
+// --MIAMI: Done
void
CPed::SetDead(void)
{
-#ifdef VC_PED_PORTS
if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DROWN))
-#endif
bUsesCollision = false;
m_fHealth = 0.0f;
if (m_nPedState == PED_DRIVING)
bIsVisible = false;
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
m_nPedState = PED_DEAD;
m_pVehicleAnim = nil;
m_pCollidingEntity = nil;
@@ -6099,6 +6615,7 @@ CPed::SetDead(void)
m_currentWeapon = WEAPONTYPE_UNARMED;
CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250);
if (this != FindPlayerPed()) {
+ RemoveWeaponAnims(0, -1000.0f);
CreateDeadPedWeaponPickups();
CreateDeadPedMoney();
}
@@ -6204,6 +6721,7 @@ CPed::DoesLOSBulletHitPed(CColPoint &colPoint)
return retVal;
}
+// TODO(Miami): Ducking doesn't work, fix this
bool
CPed::DuckAndCover(void)
{
@@ -6221,9 +6739,11 @@ CPed::DuckAndCover(void)
SetAimFlag(m_pedInObjective);
} else {
- bCrouchWhenShooting = false;
bKindaStayInSamePlace = false;
- bIsDucking = false;
+ if (bIsDucking)
+ ClearDuck(true);
+
+ bCrouchWhenShooting = false;
bDuckAndCover = false;
m_headingRate = 10.0f;
m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000);
@@ -6236,8 +6756,11 @@ CPed::DuckAndCover(void)
bool justDucked = false;
CVehicle *foundVeh = nil;
float maxDist = 225.0f;
- bIsDucking = false;
+ if (bIsDucking)
+ ClearDuck(true);
+
bCrouchWhenShooting = false;
+
if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
CVector pos = GetPosition();
int16 lastVehicle;
@@ -6468,6 +6991,7 @@ CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos)
return 1;
}
+#ifdef GTA_TRAIN
void
CPed::LineUpPedWithTrain(void)
{
@@ -6519,6 +7043,7 @@ CPed::ExitTrain(void)
{
LineUpPedWithTrain();
}
+#endif
void
CPed::ExitCar(void)
@@ -6624,13 +7149,9 @@ CPed::Fight(void)
case FIGHTMOVE_KNEE:
TransformToNode(touchingNodePos, PED_LOWERLEGR);
break;
- case FIGHTMOVE_HEADBUTT:
- TransformToNode(touchingNodePos, PED_HEAD);
- break;
case FIGHTMOVE_PUNCHJAB:
TransformToNode(touchingNodePos, PED_HANDL);
break;
- case FIGHTMOVE_KICK:
case FIGHTMOVE_LONGKICK:
case FIGHTMOVE_ROUNDHOUSE:
case FIGHTMOVE_GROUNDKICK:
@@ -6691,12 +7212,12 @@ CPed::Fight(void)
canRoundhouse = false;
punchOnly = false;
canKick = true;
- nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
+ nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_BODYBLOW : FIGHTMOVE_KNEE);
hasShoppingBags = false;
canKneeHead = true;
nPlayerInComboMove = 0;
} else {
- nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
+ nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_BODYBLOW : FIGHTMOVE_KNEE);
uint16 pedFeatures = m_pedStats->m_flags;
punchOnly = pedFeatures & STAT_PUNCH_ONLY;
canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE;
@@ -6735,7 +7256,7 @@ CPed::Fight(void)
&& neededTurn < DEGTORAD(35.0f)
&& (canKick || hasShoppingBags)) {
- nextFightMove = FIGHTMOVE_KICK;
+ nextFightMove = FIGHTMOVE_LONGKICK;
if (hasShoppingBags) {
nextFightMove = FIGHTMOVE_ROUNDHOUSE;
} else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) {
@@ -6828,7 +7349,7 @@ CPed::Fight(void)
if (fightingPedDist >= 1.3f) {
if (fightingPedDist < 1.7f && canKick) {
- nextFightMove = FIGHTMOVE_KICK;
+ nextFightMove = FIGHTMOVE_LONGKICK;
if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
nextFightMove = FIGHTMOVE_ROUNDHOUSE;
@@ -7055,9 +7576,7 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
if (obstacle) {
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
-
- // ANIM_HIT_WALL in VC (which makes more sense)
- CAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 8.0f);
+ CAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 8.0f);
handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped);
ped->bIsLanding = true;
@@ -7169,7 +7688,7 @@ CPed::Wait(void)
CPed *pedWeLook;
if (DyingOrDead()) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
RestoreHeadingRate();
return;
}
@@ -7179,7 +7698,7 @@ CPed::Wait(void)
case WAITSTATE_TRAFFIC_LIGHTS:
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
SetMoveState(PEDMOVE_WALK);
}
}
@@ -7188,7 +7707,7 @@ CPed::Wait(void)
case WAITSTATE_CROSS_ROAD:
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
else
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
@@ -7202,7 +7721,7 @@ CPed::Wait(void)
case WAITSTATE_CROSS_ROAD_LOOK:
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
if (animAssoc) {
animAssoc->blendDelta = -8.0f;
@@ -7219,7 +7738,7 @@ CPed::Wait(void)
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
}
} else {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
SetMoveState(PEDMOVE_WALK);
}
break;
@@ -7230,13 +7749,13 @@ CPed::Wait(void)
m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
}
} else {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
}
break;
case WAITSTATE_TURN180:
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
SetMoveState(PEDMOVE_WALK);
m_fRotationCur = m_fRotationCur + PI;
if (m_nPedState == PED_INVESTIGATE)
@@ -7255,7 +7774,7 @@ CPed::Wait(void)
animAssoc->SetFinishCallback(FinishedWaitCB, this);
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
} else {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
}
}
break;
@@ -7284,7 +7803,7 @@ CPed::Wait(void)
if (animAssoc->animId == ANIM_TURN_180) {
m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
SetMoveState(PEDMOVE_WALK);
m_nStoredMoveState = PEDMOVE_NONE;
m_panicCounter = 0;
@@ -7321,7 +7840,7 @@ CPed::Wait(void)
case WAITSTATE_LOOK_ABOUT:
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
if (animAssoc) {
animAssoc->blendDelta = -8.0f;
@@ -7348,7 +7867,7 @@ CPed::Wait(void)
TurnBody();
} else {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
m_nWaitTimer = 0;
if (m_pLookTarget && m_pLookTarget->IsPed()) {
@@ -7423,7 +7942,7 @@ CPed::Wait(void)
animAssoc->blendDelta = -4.0f;
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
}
#ifdef VC_PED_PORTS
else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
@@ -7447,13 +7966,59 @@ CPed::Wait(void)
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
int timer = 2000;
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
}
} else {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
+ }
+ break;
+ case WAITSTATE_SIT_DOWN:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ ClearWaitState();
+ SetWaitState(WAITSTATE_SIT_IDLE, 0);
}
break;
+ //case WAITSTATE_SIT_DOWN_RVRS:
+ case WAITSTATE_SIT_UP:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (m_attractor)
+ GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
+ ClearWaitState();
+ //TODO(MIAMI): scan for threats!
+ }
+ break;
+ case WAITSTATE_SIT_IDLE:
+ if (bTurnedAroundOnAttractor) {
+ m_fRotationCur += PI;
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ m_fRotationDest = m_fRotationCur;
+ bTurnedAroundOnAttractor = false;
+ }
+ // TODO(MIAMI): scan for threats!
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ ClearWaitState();
+ SetWaitState(WAITSTATE_SIT_UP, 0);
+ }
+ break;
+ case WAITSTATE_USE_ATM:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (m_attractor)
+ GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
+ ClearWaitState();
+ }
+ break;
+ case WAITSTATE_SUN_BATHE_PRE:
+ case WAITSTATE_SUN_BATHE_DOWN:
+ case WAITSTATE_SUN_BATHE_IDLE:
+ case WAITSTATE_RIOT:
+ case WAITSTATE_FAST_FALL:
+ case WAITSTATE_BOMBER:
+ case WAITSTATE_STRIPPER:
+ case WAITSTATE_GROUND_ATTACK:
+ case WAITSTATE_LANCESITTING:
+ case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:
+ assert(0);
default:
break;
}
@@ -8028,93 +8593,18 @@ CPed::GetNextPointOnRoute(void)
return nextPoint;
}
-// These categories are purely random, most of ped models have no correlation. So I don't think making an enum.
uint8
CPed::GetPedRadioCategory(uint32 modelIndex)
{
- switch (modelIndex) {
- case MI_MALE01:
- case MI_FEMALE03:
- case MI_PROSTITUTE2:
- case MI_WORKER1:
- case MI_MOD_MAN:
- case MI_MOD_WOM:
- case MI_ST_WOM:
- case MI_FAN_WOM:
- return 3;
- case MI_TAXI_D:
- case MI_PIMP:
- case MI_MALE02:
- case MI_FEMALE02:
- case MI_FATFEMALE01:
- case MI_FATFEMALE02:
- case MI_DOCKER1:
- case MI_WORKER2:
- case MI_FAN_MAN2:
- return 9;
- case MI_GANG01:
- case MI_GANG02:
- case MI_SCUM_MAN:
- case MI_SCUM_WOM:
- case MI_HOS_WOM:
- case MI_CONST1:
- return 1;
- case MI_GANG03:
- case MI_GANG04:
- case MI_GANG07:
- case MI_GANG08:
- case MI_CT_MAN2:
- case MI_CT_WOM2:
- case MI_B_MAN3:
- case MI_SHOPPER3:
- return 4;
- case MI_GANG05:
- case MI_GANG06:
- case MI_GANG11:
- case MI_GANG12:
- case MI_CRIMINAL02:
- case MI_B_WOM2:
- case MI_ST_MAN:
- case MI_HOS_MAN:
- return 5;
- case MI_FATMALE01:
- case MI_LI_MAN2:
- case MI_SHOPPER1:
- case MI_CAS_MAN:
- return 6;
- case MI_PROSTITUTE:
- case MI_P_WOM2:
- case MI_LI_WOM2:
- case MI_B_WOM3:
- case MI_CAS_WOM:
- return 2;
- case MI_P_WOM1:
- case MI_DOCKER2:
- case MI_STUD_MAN:
- return 7;
- case MI_CT_MAN1:
- case MI_CT_WOM1:
- case MI_LI_MAN1:
- case MI_LI_WOM1:
- case MI_B_MAN1:
- case MI_B_MAN2:
- case MI_B_WOM1:
- case MI_SHOPPER2:
- case MI_STUD_WOM:
- return 8;
- default:
- return 0;
- }
+ // TODO(MIAMI): remove this function and use modelinfo for radio
+ return 1;
}
-// Some kind of VC leftover I think
+// --MIAMI: Done
int
CPed::GetWeaponSlot(eWeaponType weaponType)
{
- if (HasWeapon(weaponType))
- return weaponType;
- else
- return -1;
+ return CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;
}
void
@@ -8264,6 +8754,11 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
{
// FIX: If there were no translations on enter anims, there were overflows all over this function.
+ int vanBlock = CAnimManager::GetAnimationBlockIndex("van");
+ CStreaming::RequestAnim(vanBlock, STREAMFLAGS_DEPENDENCY);
+ CStreaming::LoadAllRequestedModels(false);
+ CAnimManager::AddAnimBlockRef(vanBlock);
+
CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy;
CAnimBlendSequence *seq = enterAssoc->sequences;
CAnimManager::UncompressAnimation(enterAssoc);
@@ -8312,7 +8807,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
}
}
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy;
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_VAN, ANIM_VAN_GETIN_L)->hierarchy;
seq = enterAssoc->sequences;
CAnimManager::UncompressAnimation(enterAssoc);
if (seq->numFrames > 0) {
@@ -8323,7 +8818,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
vecPedVanRearDoorAnimOffset = lastFrame->translation;
}
}
-
+#ifdef GTA_TRAIN
enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_TRAIN_GETOUT)->hierarchy;
seq = enterAssoc->sequences;
CAnimManager::UncompressAnimation(enterAssoc);
@@ -8335,6 +8830,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
vecPedTrainDoorAnimOffset = lastFrame->translation;
}
}
+#endif
}
void
@@ -8540,7 +9036,11 @@ CPed::InvestigateEvent(void)
bool
CPed::IsPedDoingDriveByShooting(void)
{
+#ifdef FIX_BUGS
+ if (FindPlayerPed() == this && CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nWeaponSlot == 5) {
+#else
if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
+#endif
if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
return true;
}
@@ -8790,7 +9290,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
if ((m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
&& !m_pCollidingEntity &&
- (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
+ (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
m_pCollidingEntity = car;
}
@@ -8826,7 +9326,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
void
CPed::Look(void)
{
- // UNUSED: This is a perfectly empty function.
+ TurnBody();
}
bool
@@ -9290,7 +9790,6 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
bool itsLow = !!veh->bLowVehicle;
#endif
eDoors enterDoor;
- AnimationId enterAnim;
switch (ped->m_vehEnterType) {
case CAR_DOOR_RF:
@@ -9320,28 +9819,27 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
}
if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
if (itsVan) {
- enterAnim = ANIM_VAN_GETIN;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN);
} else if (itsBus) {
- enterAnim = ANIM_COACH_IN_R;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_R);
#ifdef FIX_BUGS
} else if (itsLow) {
- enterAnim = ANIM_CAR_GETIN_LOW_RHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_RHS);
#endif
} else {
- enterAnim = ANIM_CAR_GETIN_RHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_RHS);
}
} else if (itsVan) {
- enterAnim = ANIM_VAN_GETIN_L;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN_L);
} else if (itsBus) {
- enterAnim = ANIM_COACH_IN_L;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_L);
#ifdef FIX_BUGS
} else if (itsLow) {
- enterAnim = ANIM_CAR_GETIN_LOW_LHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
#endif
} else {
- enterAnim = ANIM_CAR_GETIN_LHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
}
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterAnim);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
} else if (veh->CanPedOpenLocks(ped)) {
@@ -9349,16 +9847,16 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
veh->AutoPilot.m_nCruiseSpeed = 0;
if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
if (itsVan) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN);
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_OPEN);
} else if (itsBus) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_R);
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_OPEN_R);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_RHS);
}
} else if (itsVan) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN_L);
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_OPEN_L);
} else if (itsBus) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L);
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_OPEN_L);
} else {
if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {
@@ -9397,9 +9895,6 @@ CPed::ProcessControl(void)
CColPoint foundCol;
CEntity *foundEnt = nil;
- if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
- return;
-
int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
if (!bFadeOut) {
if (alpha < 255) {
@@ -9528,7 +10023,7 @@ CPed::ProcessControl(void)
} else if (m_nPedStateTimer < 1001) {
m_nPedStateTimer = 0;
}
- } else {
+ } else if (!GetPedAttractorManager()->IsInQueue(this, m_attractor)) {
if (m_panicCounter == 50 && IsPedInControl()) {
SetWaitState(WAITSTATE_STUCK, nil);
// Leftover
@@ -9582,11 +10077,8 @@ CPed::ProcessControl(void)
if (m_nPedState == PED_FOLLOW_PATH) {
if (DotProduct(m_vecDamageNormal, GetForward()) < -0.866f && CanPedJumpThis(collidingEnt, &m_vecDamageNormal)) {
SetJump();
-
- // Moved break into here, for compatibility with III
- break;
}
- // break;
+ break;
}
#endif
if (m_pedInObjective &&
@@ -10168,7 +10660,7 @@ CPed::ProcessControl(void)
flyDir = 1;
}
- if (flyDir != 0 && !bSomeVCflag1) {
+ if (flyDir != 0 && !bHeadStuckInCollision) {
SetPosition((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point));
GetMatrix().GetPosition().z += FEET_OFFSET;
GetMatrix().UpdateRW();
@@ -10275,11 +10767,11 @@ CPed::ProcessControl(void)
if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, nil)) {
#ifdef VC_PED_PORTS
- if (!bSomeVCflag1 || FEET_OFFSET + foundCol.point.z < GetPosition().z) {
+ if (!bHeadStuckInCollision || FEET_OFFSET + foundCol.point.z < GetPosition().z) {
GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z;
GetMatrix().UpdateRW();
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
+ if (bHeadStuckInCollision)
+ bHeadStuckInCollision = false;
}
#else
GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z;
@@ -10339,24 +10831,25 @@ CPed::ProcessControl(void)
CPhysical::ProcessControl();
#endif
if (m_nPedState != PED_DIE || bIsPedDieAnimPlaying) {
+ RequestDelayedWeapon();
+ PlayFootSteps();
if (m_nPedState != PED_DEAD) {
CalculateNewVelocity();
CalculateNewOrientation();
}
UpdatePosition();
- PlayFootSteps();
if (IsPedInControl() && !bIsStanding && !m_pDamageEntity && CheckIfInTheAir()) {
SetInTheAir();
#ifdef VC_PED_PORTS
- bSomeVCflag1 = false;
+ bHeadStuckInCollision = false;
#endif
}
#ifdef VC_PED_PORTS
- if (bSomeVCflag1) {
+ if (bHeadStuckInCollision) {
CVector posToCheck = GetPosition();
posToCheck.z += 0.9f;
if (!CWorld::TestSphereAgainstWorld(posToCheck, 0.2f, this, true, true, false, true, false, false))
- bSomeVCflag1 = false;
+ bHeadStuckInCollision = false;
}
#endif
ProcessObjective();
@@ -10540,12 +11033,14 @@ CPed::ProcessControl(void)
case PED_GETUP:
SetGetUp();
break;
+#ifdef GTA_TRAIN
case PED_ENTER_TRAIN:
EnterTrain();
break;
case PED_EXIT_TRAIN:
ExitTrain();
break;
+#endif
case PED_DRIVING:
{
if (!m_pMyVehicle) {
@@ -10554,15 +11049,13 @@ CPed::ProcessControl(void)
return;
}
- if (m_pMyVehicle->pDriver != this || m_pMyVehicle->IsBoat()) {
+ if (m_pMyVehicle->pDriver != this) {
LookForSexyPeds();
LookForSexyCars();
break;
}
- if (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE || !m_pMyVehicle->pDriver->IsPlayer()) {
- break;
- }
+ // TODO(Miami): Start KILL_CHAR_ON_BOAT objective
CPad* pad = CPad::GetPad(0);
@@ -10592,12 +11085,24 @@ CPed::ProcessControl(void)
}
}
#endif
+
+ // TODO(Miami): This part moved to DriveVehicle in VC
float steerAngle = m_pMyVehicle->m_fSteerAngle;
CAnimBlendAssociation *lDriveAssoc;
CAnimBlendAssociation *rDriveAssoc;
CAnimBlendAssociation *lbAssoc;
CAnimBlendAssociation *sitAssoc;
- if (m_pMyVehicle->bLowVehicle) {
+ if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) {
+ sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT);
+
+ if (!sitAssoc || sitAssoc->blendAmount < 1.0f) {
+ break;
+ }
+
+ lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT_L);
+ rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT_R);
+ lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BOAT_LB);
+ } else if (m_pMyVehicle->bLowVehicle) {
sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
if (!sitAssoc || sitAssoc->blendAmount < 1.0f) {
@@ -10617,18 +11122,21 @@ CPed::ProcessControl(void)
lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L);
rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R);
lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB);
+ }
- if (lbAssoc &&
- TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON
- && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) {
- lbAssoc->blendDelta = -1000.0f;
- }
+ if (lbAssoc &&
+ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON
+ && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) {
+ lbAssoc->blendDelta = -1000.0f;
}
CAnimBlendAssociation *driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
-
if (!driveByAssoc)
driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
+ if (!driveByAssoc)
+ driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_LOW_L);
+ if (!driveByAssoc)
+ driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_LOW_R);
if (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc) {
if (steerAngle == 0.0f || driveByAssoc) {
@@ -10643,6 +11151,8 @@ CPed::ProcessControl(void)
if (rDriveAssoc)
rDriveAssoc->blendAmount = clamp(steerAngle * -100.0f / 61.0f, 0.0f, 1.0f);
+ else if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT_R);
else if (m_pMyVehicle->bLowVehicle)
CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_R);
else
@@ -10654,6 +11164,8 @@ CPed::ProcessControl(void)
if (lDriveAssoc)
lDriveAssoc->blendAmount = clamp(steerAngle * 100.0f / 61.0f, 0.0f, 1.0f);
+ else if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT_L);
else if (m_pMyVehicle->bLowVehicle)
CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_L);
else
@@ -10666,10 +11178,18 @@ CPed::ProcessControl(void)
if ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON
|| TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT)
- && (!lbAssoc || lbAssoc->blendAmount < 1.0f)) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f);
+ && (!lbAssoc || lbAssoc->blendAmount < 1.0f && lbAssoc->blendDelta <= 0.0f)) {
+
+ if(m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_BOAT_LB, 4.0f);
+ else
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f);
}
}
+
+ // TODO(Miami): This part belongs to DriveVehicle
+ if (!m_pMyVehicle)
+ return;
break;
}
case PED_DIE:
@@ -10721,7 +11241,8 @@ CPed::ProcessControl(void)
}
m_pCurrentPhysSurface = nil;
}
- }
+ } else
+ ServiceTalking();
}
void
@@ -10742,26 +11263,52 @@ CPed::SetInTheAir(void)
}
+// --MIAMI: Done
void
CPed::RestoreHeadPosition(void)
{
+ // TODO(Miami): This is inlined CanUseTorsoWhenLooking
+ bool canUseMyBody = false;
+ if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) {
+ if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN)
+ canUseMyBody = true;
+ }
+ if (!canUseMyBody)
+ m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;
+
if (m_pedIK.RestoreLookAt()) {
bIsRestoringLook = false;
+ canUseMyBody = false;
+ if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) {
+ if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN)
+ canUseMyBody = true;
+ }
+ if(canUseMyBody)
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
}
}
+// --MIAMI: Done
void
CPed::PointGunAt(void)
{
CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
- if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f)
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
+ float animLoopStart = weaponInfo->m_fAnimLoopStart;
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f) {
+ if (!!weaponInfo->m_bCrouchFire) {
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo));
+ animLoopStart = weaponInfo->m_fAnim2LoopStart;
+ }
+ }
- if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
- weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
+ if (weaponAssoc && weaponAssoc->currentTime > animLoopStart * 0.4f) {
+ weaponAssoc->SetCurrentTime(animLoopStart);
weaponAssoc->flags &= ~ASSOC_RUNNING;
+ if (bIsDucking)
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+
if (weaponInfo->m_bCanAimWithArm)
m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
else
@@ -10940,28 +11487,26 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
isVan = false;
if (ped->m_nPedState != PED_CARJACK || isBus) {
- AnimationId animToPlay;
if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
if (isVan) {
- animToPlay = ANIM_VAN_GETIN;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN);
} else if (isBus) {
- animToPlay = ANIM_COACH_IN_R;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_R);
} else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_RHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_RHS);
} else {
- animToPlay = ANIM_CAR_GETIN_RHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_RHS);
}
} else if (isVan) {
- animToPlay = ANIM_VAN_GETIN_L;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN_L);
} else if (isBus) {
- animToPlay = ANIM_COACH_IN_L;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_L);
} else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_LHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
} else {
- animToPlay = ANIM_CAR_GETIN_LHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
}
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
} else {
CPed *pedToDragOut = nil;
@@ -11070,51 +11615,17 @@ CPed::ServiceTalkingWhenDead(void)
return m_queuedSound == SOUND_PED_DEATH;
}
+// --MIAMI: Done
void
CPed::RemoveInCarAnims(void)
{
- if (!IsPlayer())
- return;
+ CAnimBlendAssociation* assoc;
- CAnimBlendAssociation *animAssoc;
-
- if (m_pMyVehicle && m_pMyVehicle->bLowVehicle) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- } else {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
+ for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_DRIVING); assoc;
+ assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_DRIVING)) {
+ assoc->flags |= ASSOC_DELETEFADEDOUT;
+ assoc->blendDelta = -1000.0f;
}
-
-#ifdef VC_PED_PORTS
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-#endif
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
}
void
@@ -11236,32 +11747,32 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
if (veh->IsDoorMissing(enterDoor) || isBus) {
PedAnimDoorCloseCB(nil, ped);
} else {
- AnimationId animToPlay;
if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
if (isVan) {
- animToPlay = ANIM_VAN_CLOSE;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_CLOSE);
} else if (isLow) {
- animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_LOW_RHS);
} else {
- animToPlay = ANIM_CAR_CLOSEDOOR_RHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_RHS);
}
} else if (isVan) {
- animToPlay = ANIM_VAN_CLOSE_L;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_CLOSE_L);
} else if (isLow) {
- animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_LOW_LHS);
} else {
- animToPlay = ANIM_CAR_CLOSEDOOR_LHS;
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_LHS);
}
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
}
}
+#ifdef GTA_TRAIN
void
CPed::SetPedPositionInTrain(void)
{
LineUpPedWithTrain();
}
+#endif
void
CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg)
@@ -11858,19 +12369,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)
ped->SetObjective(OBJECTIVE_NONE);
}
- if (veh->pDriver == ped) {
- if (veh->bLowVehicle) {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
- } else {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
- }
- } else if (veh->bLowVehicle) {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f);
- } else {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f);
- }
-
- ped->StopNonPartialAnims();
+ ped->AddInCarAnims(veh, veh->pDriver == ped);
if (veh->bIsBus)
ped->bRenderPedInCar = false;
@@ -11982,7 +12481,7 @@ CPed::RegisterThreatWithGangPeds(CEntity *attacker)
}
if (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) {
- if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOYZ) {
+ if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOPFUN) {
int16 lastVehicle;
CEntity *vehicles[8];
CWorld::FindObjectsInRange(GetPosition(), 30.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
@@ -12258,14 +12757,14 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg)
}
}
-// It was inlined in III but not in VC.
+// --MIAMI: Done, but enumarate weapon slots
inline void
CPed::ReplaceWeaponWhenExitingVehicle(void)
{
eWeaponType weaponType = GetWeapon()->m_eWeaponType;
// If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car.
- if (IsPlayer() && weaponType == WEAPONTYPE_UZI) {
+ if (IsPlayer() && GetWeaponSlot(weaponType) == 5) {
if (m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {
SetCurrentWeapon(m_storedWeapon);
m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
@@ -12275,14 +12774,14 @@ CPed::ReplaceWeaponWhenExitingVehicle(void)
}
}
-// Same, it's inlined in III.
+// --MIAMI: Done
inline void
CPed::RemoveWeaponWhenEnteringVehicle(void)
{
- if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
+ if (IsPlayer() && HasWeaponSlot(5) && GetWeapon(5).m_nAmmoTotal > 0 && ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed()->m_bDriveByAllowed) {
if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
m_storedWeapon = GetWeapon()->m_eWeaponType;
- SetCurrentWeapon(WEAPONTYPE_UZI);
+ SetCurrentWeapon(GetWeapon(5).m_eWeaponType);
} else {
CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(ourWeapon->m_nModelId);
@@ -12676,13 +13175,7 @@ CPed::Render(void)
bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) {
CEntity::Render();
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- renderLimb(PED_HEAD);
- renderLimb(PED_HANDL);
- renderLimb(PED_HANDR);
- }
- if(m_pWeaponModel && IsClumpSkinned(GetClump())){
+ if(m_pWeaponModel){
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);
RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
@@ -12691,51 +13184,9 @@ CPed::Render(void)
RwFrameUpdateObjects(frame);
RpAtomicRender(m_pWeaponModel);
}
-#endif
}
}
-#ifdef PED_SKIN
-static RpMaterial*
-SetLimbAlphaCB(RpMaterial *material, void *data)
-{
- ((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data;
- return material;
-}
-
-void
-CPed::renderLimb(int node)
-{
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
- RpAtomic *atomic;
- switch(node){
- case PED_HEAD:
- atomic = mi->getHead();
- break;
- case PED_HANDL:
- atomic = mi->getLeftHand();
- break;
- case PED_HANDR:
- atomic = mi->getRightHand();
- break;
- default:
- return;
- }
- if(atomic == nil)
- return;
-
- RwFrame *frame = RpAtomicGetFrame(atomic);
- *RwFrameGetMatrix(frame) = *mat;
- RwFrameUpdateObjects(frame);
- int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
- RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha);
- RpAtomicRender(atomic);
-}
-#endif
-
void
CPed::ProcessObjective(void)
{
@@ -12778,14 +13229,26 @@ CPed::ProcessObjective(void)
case OBJECTIVE_FOLLOW_CAR_IN_CAR:
case OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE:
case OBJECTIVE_DESTROY_OBJ:
- case OBJECTIVE_23:
- case OBJECTIVE_24:
+ case OBJECTIVE_26:
+ case OBJECTIVE_27:
case OBJECTIVE_SET_LEADER:
break;
case OBJECTIVE_IDLE:
- SetIdle();
- m_objective = OBJECTIVE_NONE;
- SetMoveState(PEDMOVE_STILL);
+ if (GetPedState() == PED_DRIVING)
+ m_objective = OBJECTIVE_NONE;
+ else {
+ SetIdle();
+ if (m_attractor) {
+ if (m_objectiveTimer && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
+ m_objectiveTimer = 0;
+ }
+ }
+ else {
+ m_objective = OBJECTIVE_NONE;
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
break;
case OBJECTIVE_FLEE_TILL_SAFE:
if (InVehicle()) {
@@ -12915,8 +13378,8 @@ CPed::ProcessObjective(void)
int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &ourPos, &chosenCarClass);
CAutomobile *newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE);
if (newVeh) {
- newVeh->GetMatrix().GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition();
- newVeh->GetMatrix().GetPosition().z += 4.0f;
+ newVeh->GetMatrix().GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition();
+ newVeh->GetMatrix().GetPosition().z += 4.0f;
newVeh->SetHeading(DEGTORAD(200.0f));
newVeh->SetStatus(STATUS_ABANDONED);
newVeh->m_nDoorLock = CARLOCK_UNLOCKED;
@@ -13843,14 +14306,14 @@ CPed::ProcessObjective(void)
float distWithTargetScSqr = distWithTarget.MagnitudeSqr();
if (distWithTargetScSqr <= sq(10.0f)) {
if (distWithTargetScSqr <= sq(1.4f)) {
- CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD);
+ CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,
GetPosition().x, GetPosition().y);
if (reloadAssoc || !m_pedInObjective->IsPedShootable()) {
if (reloadAssoc &&
- (!reloadAssoc->IsRunning() || reloadAssoc->currentTime / reloadAssoc->hierarchy->totalLength > 0.8f)) {
+ (!reloadAssoc->IsRunning() || reloadAssoc->GetProgress() > 0.8f)) {
CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
punchAssoc->flags |= ASSOC_DELETEFADEDOUT;
punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
@@ -13880,7 +14343,7 @@ CPed::ProcessObjective(void)
if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)
SetCurrentWeapon(WEAPONTYPE_UNARMED);
- CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f);
+ CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FUCKU, 8.0f);
newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
}
@@ -13913,23 +14376,21 @@ CPed::ProcessObjective(void)
case OBJECTIVE_LEAVE_VEHICLE:
if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
if (InVehicle()
-#ifdef VC_PED_PORTS
&& (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate()
|| bBusJacked)
-#endif
) {
if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN
&& (m_nPedType != PEDTYPE_COP
-#ifdef VC_PED_PORTS
|| m_pMyVehicle->IsBoat()
-#endif
|| m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) {
+#ifdef GTA_TRAIN
if (m_pMyVehicle->IsTrain())
SetExitTrain(m_pMyVehicle);
-#ifdef VC_PED_PORTS
- else if (m_pMyVehicle->IsBoat())
- SetExitBoat(m_pMyVehicle);
+ else
#endif
+ if (m_pMyVehicle->IsBoat())
+ SetExitBoat(m_pMyVehicle);
+
else
SetExitCar(m_pMyVehicle, 0);
}
@@ -13966,6 +14427,187 @@ CPed::ProcessObjective(void)
}
break;
}
+ case OBJECTIVE_USE_SEAT_ATTRACTOR:
+ case OBJECTIVE_USE_ATM_ATTRACTOR:
+ case OBJECTIVE_USE_STOP_ATTRACTOR:
+ case OBJECTIVE_USE_PIZZA_ATTRACTOR:
+ case OBJECTIVE_USE_SHELTER_ATTRACTOR:
+ case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
+ if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
+ m_objectiveTimer = 0;
+ if (m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ }
+ else {
+ CVector distance = m_nextRoutePointPos - GetPosition();
+ distance.z = 0.0f;
+ if (m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR) {
+ if (m_nMoveState == PEDMOVE_SPRINT && distance.Magnitude() < SQR(2.0f)) {
+ SetMoveState(PEDMOVE_WALK);
+ bIsRunning = false;
+ }
+ else if (CWeather::Rain < 0.2f && m_attractor) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ }
+ else if (m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR) {
+ if (m_nMoveState == PEDMOVE_SPRINT && distance.Magnitude() < SQR(4.0f)) {
+ SetMoveState(PEDMOVE_WALK);
+ bIsRunning = false;
+ }
+ CVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());
+ if (0.01f * CTimer::GetTimeStep() * 5.0f < pIceCreamVan->m_fDistanceTravelled) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ if (!pIceCreamVan->pDriver ||
+ !pIceCreamVan->pDriver->IsPlayer() ||
+ pIceCreamVan->pDriver->GetPedState() == PED_ARRESTED ||
+ pIceCreamVan->pDriver->GetPedState() == PED_DEAD) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ if (!pIceCreamVan->m_bSirenOrAlarm) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ if (pIceCreamVan->GetStatus() == STATUS_WRECKED) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ }
+ if (sq(m_distanceToCountSeekDone) < distance.MagnitudeSqr()) {
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || GetPedState() != PED_SEEK_POS)
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ }
+ else {
+ if (!bReachedAttractorHeadingTarget) {
+ float fHeadingDistance = m_fRotationCur - m_attractorHeading;
+ float fSinHeading = Sin(fHeadingDistance);
+ float fCosHeading = Cos(fHeadingDistance);
+ if (fSinHeading > 0.0f) {
+ if (fCosHeading > 0.0f)
+ m_attractorHeading = m_fRotationCur - Asin(fSinHeading);
+ else
+ m_attractorHeading = m_fRotationCur - Acos(fCosHeading);
+ }
+ else {
+ if (fCosHeading > 0.0f)
+ m_attractorHeading = m_fRotationCur - Asin(fSinHeading);
+ else
+ m_attractorHeading = m_fRotationCur + Acos(fCosHeading);
+ }
+ m_fRotationDest = m_attractorHeading;
+ m_headingRate = 3.5f;
+ bReachedAttractorHeadingTarget = true;
+ bTurnedAroundOnAttractor = false;
+ }
+ if (Abs(m_fRotationCur - m_attractorHeading) >= m_acceptableHeadingOffset &&
+ Abs(m_fRotationCur - m_attractorHeading + TWOPI) >= m_acceptableHeadingOffset &&
+ Abs(m_fRotationCur - m_attractorHeading - TWOPI) >= m_acceptableHeadingOffset)
+ SetMoveState(PEDMOVE_STILL);
+ else {
+ m_fRotationDest = m_fRotationCur;
+ bReachedAttractorHeadingTarget = false;
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ RestoreHeadingRate();
+ GetPedAttractorManager()->BroadcastArrival(this, m_attractor);
+ if (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) {
+ switch (m_objective) {
+ case OBJECTIVE_USE_SEAT_ATTRACTOR:
+ if (!bTurnedAroundOnAttractor) {
+ ClearObjective();
+ SetWaitState(WAITSTATE_SIT_DOWN, 0);
+ }
+ else {
+ ClearObjective();
+ SetWaitState(WAITSTATE_SIT_DOWN_RVRS, 0);
+ }
+ break;
+ case OBJECTIVE_USE_ATM_ATTRACTOR:
+ ClearObjective();
+ SetWaitState(WAITSTATE_USE_ATM, 0);
+ break;
+ case OBJECTIVE_USE_STOP_ATTRACTOR:
+ ClearObjective();
+ SetObjective(OBJECTIVE_WAIT_FOR_BUS);
+ break;
+ case OBJECTIVE_USE_PIZZA_ATTRACTOR:
+ ClearObjective();
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_IDLE);
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + m_attractor->GetHeadOfQueueWaitTime();
+ break;
+ case OBJECTIVE_USE_SHELTER_ATTRACTOR:
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_WAIT_FOR_RAIN_TO_END);
+ break;
+ case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_PURCHASE_ICECREAM);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return;
+ case OBJECTIVE_WAIT_FOR_RAIN_TO_END:
+ SetIdle();
+ if (m_attractor && CWeather::Rain < 0.2f)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ break;
+ case OBJECTIVE_WAIT_FOR_BUS:
+ SetIdle();
+ if (m_attractor) {
+ float left = GetPosition().x - 10.0f;
+ float right = GetPosition().x + 10.0f;
+ float top = GetPosition().y - 10.0f;
+ float bottom = GetPosition().y + 10.0f;
+ int xstart = Max(0, CWorld::GetSectorIndexX(left));
+ int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
+ int ystart = Max(0, CWorld::GetSectorIndexY(top));
+ int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
+ assert(xstart <= xend);
+ assert(ystart <= yend);
+
+ float minDistance = SQR(10.0f);
+ CVehicle* pBus = nil;
+
+ for (int y = ystart; y <= yend; y++) {
+ for (int x = xstart; x <= xend; x++) {
+ CSector* s = CWorld::GetSector(x, y);
+ for (CPtrNode* pNode = s->m_lists[ENTITYLIST_VEHICLES].first; pNode != nil; pNode = pNode->next) {
+ CEntity* pEntity = (CEntity*)pNode->item;
+ if (!pEntity->IsVehicle())
+ continue;
+ CVehicle* pVehicle = (CVehicle*)pEntity;
+ if (!pVehicle->bIsBus)
+ continue;
+ if (pVehicle->GetMoveSpeed().MagnitudeSqr() >= SQR(0.005f))
+ continue;
+ float distanceSq = (GetPosition() - pVehicle->GetPosition()).MagnitudeSqr();
+ if (distanceSq < minDistance) {
+ minDistance = distanceSq;
+ pBus = pVehicle;
+ }
+ }
+ }
+ }
+
+ if (pBus) {
+ if (pBus->m_nNumPassengers >= pBus->m_nNumMaxPassengers - 1)
+ SetObjective(OBJECTIVE_IDLE);
+ else {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus);
+ bDontDragMeOutCar = true; // TODO(MIAMI): check, add more flags
+ }
+ }
+ }
+ break;
#endif
}
if (bObjectiveCompleted
@@ -14033,6 +14675,7 @@ CPed::SetSeekBoatPosition(CVehicle *boat)
m_nPedState = PED_SEEK_IN_BOAT;
}
+#ifdef GTA_TRAIN
void
CPed::SetExitTrain(CVehicle* train)
{
@@ -14050,6 +14693,7 @@ CPed::SetExitTrain(CVehicle* train)
bUsesCollision = false;
LineUpPedWithTrain();
}
+#endif
#ifdef NEW_WALK_AROUND_ALGORITHM
CVector
@@ -14694,10 +15338,10 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) {
bStillOnValidPoly = true;
#ifdef VC_PED_PORTS
- if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
+ if(!bHeadStuckInCollision || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
+ if (bHeadStuckInCollision)
+ bHeadStuckInCollision = false;
}
#else
GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
@@ -14772,13 +15416,13 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
}
}
#ifdef VC_PED_PORTS
- if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
+ if (!bHeadStuckInCollision || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
+ if (bHeadStuckInCollision)
+ bHeadStuckInCollision = false;
}
#else
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
#endif
m_nSurfaceTouched = intersectionPoint.surfaceB;
if (m_nSurfaceTouched == SURFACE_STONE) {
@@ -14786,8 +15430,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
m_vecDamageNormal = intersectionPoint.normal;
}
}
- // VC code is working perfectly, but we don't want mega jumps to damage us significantly :shrug:
-#if 0 // #ifdef VC_PED_PORTS
+
float upperSpeedLimit = 0.33f;
float lowerSpeedLimit = -0.25f;
float speed = m_vecMoveSpeed.Magnitude2D();
@@ -14795,7 +15438,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
upperSpeedLimit *= 2.0f;
lowerSpeedLimit *= 1.5f;
}
- if (!m_ped_flagA2) {
+ if (!bWasStanding) {
if ((speed <= upperSpeedLimit /* || (bfFlagsL >> 5) & 1 */) && m_vecMoveSpeed.z >= lowerSpeedLimit
|| m_pCollidingEntity == collidingEnt) {
@@ -14818,27 +15461,6 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
Say(SOUND_PED_LAND);
}
}
-#else
- float speedSqr = 0.0f;
- if (!bWasStanding) {
- if (m_vecMoveSpeed.z >= -0.25f && (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) <= sq(0.5f)) {
-
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL) && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
- }
- } else {
- if (speedSqr == 0.0f)
- speedSqr = sq(m_vecMoveSpeed.z);
-
- uint8 dir = 2; // from backward
- if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
- CVector2D offset = -m_vecMoveSpeed;
- dir = GetLocalDirection(offset);
- }
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir);
- }
- }
-#endif
m_vecMoveSpeed.z = 0.0f;
bIsStanding = true;
#ifndef VC_PED_PORTS
@@ -14884,7 +15506,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed);
sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed);
GetMatrix().GetPosition().z -= 0.05f;
- bSomeVCflag1 = true;
+ bHeadStuckInCollision = true;
}
#endif
sphereNormal.Normalise();
@@ -14975,6 +15597,7 @@ CPed::WillChat(CPed *stranger)
return true;
}
+#ifdef GTA_TRAIN
void
CPed::SetEnterTrain(CVehicle *train, uint32 unused)
{
@@ -15000,20 +15623,24 @@ CPed::SetEnterTrain(CVehicle *train, uint32 unused)
((CPlayerPed*)this)->ClearAdrenaline();
}
}
+#endif
+// --MIAMI: Done, but what is this parameter for?
void
-CPed::SetDuck(uint32 time)
+CPed::SetDuck(uint32 time, bool sth)
{
- if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer)
+ if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer && !sth) {
+ if (sth && CTimer::GetTimeInMilliseconds() + time > m_duckTimer)
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
return;
+ }
- if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) {
- CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
- if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f);
- bIsDucking = true;
- m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
- }
+ CAnimBlendAssociation *duckAssoc;
+ if (bCrouchWhenShooting) {
+ duckAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 4.0f);
+ duckAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ bIsDucking = true;
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
} else {
CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
@@ -15413,8 +16040,9 @@ CPed::SetSolicit(uint32 time)
}
bool
-CPed::SetFollowPath(CVector dest)
+CPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* pFollowedPed, CEntity*, int time)
{
+ // TODO(MIAMI): new follow
if (m_nPedState == PED_FOLLOW_PATH)
return false;
@@ -15676,13 +16304,13 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
} else {
if (veh->GetUp().z > -0.8f) {
bool addDoorSmoke = false;
- if (veh->GetModelIndex() == MI_YARDIE)
+ if (veh->GetModelIndex() == MI_VOODOO)
addDoorSmoke = true;
switch (m_vehEnterType) {
case CAR_DOOR_RF:
if (veh->bIsBus) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_COACH_OUT_L);
} else {
if (isLow)
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
@@ -15695,7 +16323,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
break;
case CAR_DOOR_RR:
if (veh->bIsVan) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT);
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETOUT);
} else if (isLow) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
} else {
@@ -15704,7 +16332,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
break;
case CAR_DOOR_LF:
if (veh->bIsBus) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_COACH_OUT_L);
} else {
if (isLow)
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
@@ -15717,7 +16345,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
break;
case CAR_DOOR_LR:
if (veh->bIsVan) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L);
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETOUT_L);
} else if (isLow) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
} else {
@@ -16216,9 +16844,12 @@ CPed::SeekCar(void)
if (Seek()) {
if (!foundBetterPosToSeek) {
if (1.5f + GetPosition().z > dest.z && GetPosition().z - 0.5f < dest.z) {
+#ifdef GTA_TRAIN
if (vehToSeek->IsTrain()) {
SetEnterTrain(vehToSeek, m_vehEnterType);
- } else {
+ } else
+#endif
+ {
m_fRotationCur = m_fRotationDest;
if (!bVehEnterDoorIsBlocked) {
vehToSeek->bIsStatic = false;
@@ -17025,33 +17656,11 @@ CPed::WarpPedIntoCar(CVehicle *car)
DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
}
-#ifdef VC_PED_PORTS
RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
- // VC uses AddInCarAnims but we don't have that
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+ AddInCarAnims(car, car->pDriver == this);
RemoveWeaponWhenEnteringVehicle();
-#else
- if (car->IsBoat()) {
-#ifndef FIX_BUGS
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
-#else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
-#endif
- CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(ourWeapon->m_nModelId);
- } else {
- // Because we can use Uzi for drive by
- RemoveWeaponWhenEnteringVehicle();
- if (car->bLowVehicle)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
- }
-#endif
-
- StopNonPartialAnims();
if (car->bIsBus)
bRenderPedInCar = false;
@@ -17059,6 +17668,22 @@ CPed::WarpPedIntoCar(CVehicle *car)
}
void
+CPed::SetObjective(eObjective newObj, float heading, const CVector& pos)
+{
+ switch (newObj) {
+ case OBJECTIVE_USE_SEAT_ATTRACTOR:
+ case OBJECTIVE_USE_ATM_ATTRACTOR:
+ case OBJECTIVE_USE_STOP_ATTRACTOR:
+ case OBJECTIVE_USE_PIZZA_ATTRACTOR:
+ case OBJECTIVE_USE_SHELTER_ATTRACTOR:
+ case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
+ ClearPointGunAt();
+ SetObjective(newObj, pos);
+ m_attractorHeading = heading;
+ }
+}
+
+void
CPed::SetObjective(eObjective newObj, CVector dest)
{
if (DyingOrDead())
@@ -17107,14 +17732,50 @@ CPed::SetObjective(eObjective newObj, CVector dest)
break;
case OBJECTIVE_GOTO_AREA_ANY_MEANS:
case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_USE_SEAT_ATTRACTOR:
+ case OBJECTIVE_USE_ATM_ATTRACTOR:
+ case OBJECTIVE_USE_STOP_ATTRACTOR:
+ case OBJECTIVE_USE_PIZZA_ATTRACTOR:
+ case OBJECTIVE_USE_SHELTER_ATTRACTOR:
+ case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
bIsRunning = false;
m_pNextPathNode = nil;
m_nextRoutePointPos = dest;
m_vecSeekPos = m_nextRoutePointPos;
m_distanceToCountSeekDone = 0.5f;
- bUsePedNodeSeek = true;
- if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D())
- return;
+ if (m_objective == OBJECTIVE_USE_ATM_ATTRACTOR) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (m_objective == OBJECTIVE_USE_SEAT_ATTRACTOR) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (m_objective == OBJECTIVE_USE_STOP_ATTRACTOR) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (m_objective == OBJECTIVE_USE_PIZZA_ATTRACTOR) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR) {
+ bIsRunning = true;
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR) {
+ bIsRunning = true;
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ bUsePedNodeSeek = false;
+ if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) {
+ if (!IsUseAttractorObjective(m_objective))
+ return;
+ if (Abs(m_fRotationCur - m_attractorHeading) < m_acceptableHeadingOffset)
+ return;
+ }
break;
case OBJECTIVE_RUN_TO_AREA:
bIsRunning = true;
@@ -17281,25 +17942,13 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
m_vecOffsetSeek = doorOpenPos - GetPosition();
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
if (car->IsBoat()) {
-#ifdef VC_PED_PORTS
- // VC checks for handling flag, but we can't do that
- if(car->GetModelIndex() == MI_SPEEDER)
+ if(car->pHandling->Flags & HANDLING_SIT_IN_BOAT)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
PedSetInCarCB(nil, this);
bVehExitWillBeInstant = true;
-#else
-
-#ifndef FIX_BUGS
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
-#else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
-#endif
-
- m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
-#endif
if (IsPlayer())
CWaterLevel::AllocateBoatWakeArray();
} else {
@@ -17339,7 +17988,7 @@ CPed::WanderPath(void)
if (!Seek())
return;
- CPathNode *previousLastNode = m_pLastPathNode;
+ CPathNode *previousLastNode = m_pLastPathNode;
uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;
// We don't prefer 180-degree turns in normal situations
@@ -17610,7 +18259,7 @@ CPed::SetCarJack(CVehicle* car)
pedInSeat = car->pDriver;
if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS ||
- (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO)))
+ (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO)))
if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
@@ -17741,6 +18390,65 @@ CPed::SetExitBoat(CVehicle *boat)
CWaterLevel::FreeBoatWakeArray();
}
+void
+CPed::SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float heading, float time, int32 qid)
+{
+ if (!m_attractor)
+ m_attractor = pAttractor;
+ if (m_attractor != pAttractor)
+ return;
+ switch (pAttractor->GetEffect()->pedattr.type) {
+ case ATTRACTOR_ATM: SetObjective(OBJECTIVE_USE_ATM_ATTRACTOR, heading, pos); break;
+ case ATTRACTOR_SEAT: SetObjective(OBJECTIVE_USE_SEAT_ATTRACTOR, heading, pos); break;
+ case ATTRACTOR_STOP: SetObjective(OBJECTIVE_USE_STOP_ATTRACTOR, heading, pos); break;
+ case ATTRACTOR_PIZZA: SetObjective(OBJECTIVE_USE_PIZZA_ATTRACTOR, heading, pos); break;
+ case ATTRACTOR_SHELTER: SetObjective(OBJECTIVE_USE_SHELTER_ATTRACTOR, heading, pos); break;
+ case ATTRACTOR_ICECREAM: SetObjective(OBJECTIVE_USE_ICECREAM_ATTRACTOR, heading, pos); break;
+ default: return;
+ }
+ SetObjectiveTimer(time);
+ m_positionInQueue = qid;
+}
+
+void
+CPed::ClearWaitState(void)
+{
+ switch (m_nWaitState) {
+ case WAITSTATE_PLAYANIM_CHAT:
+ case WAITSTATE_SIT_DOWN:
+ case WAITSTATE_SIT_DOWN_RVRS:
+ case WAITSTATE_SIT_UP:
+ case WAITSTATE_SIT_IDLE:
+ case WAITSTATE_USE_ATM:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ AnimationId id;
+ switch (m_nWaitState) { // TODO(MIAMI): actual!
+ case WAITSTATE_PLAYANIM_CHAT: id = ANIM_IDLE_CHAT; break;
+ case WAITSTATE_SIT_DOWN: id = ANIM_SEAT_DOWN; break;
+ case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_SEAT_DOWN2; break;
+ case WAITSTATE_SIT_UP: id = ANIM_SEAT_UP; break;
+ case WAITSTATE_SIT_IDLE: id = ANIM_SEAT_IDLE; break;
+ case WAITSTATE_USE_ATM: id = ANIM_ATM; break;
+ }
+ CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetAssociation(GetClump(), id);
+ if (pAssoc)
+ pAssoc->blendDelta = -8.0f;
+ if (m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ }
+ break;
+ case WAITSTATE_RIOT:
+ case WAITSTATE_FAST_FALL:
+ case WAITSTATE_BOMBER:
+ case WAITSTATE_STRIPPER:
+ case WAITSTATE_GROUND_ATTACK:
+ case WAITSTATE_LANCESITTING:
+ case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:
+ assert(0);
+ }
+ m_nWaitState = WAITSTATE_FALSE;
+}
+
#ifdef COMPATIBLE_SAVES
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
@@ -17757,7 +18465,7 @@ CPed::Save(uint8*& buf)
CopyToBuf(buf, m_fHealth);
CopyToBuf(buf, m_fArmour);
SkipSaveBuf(buf, 148);
- for (int i = 0; i < 13; i++) // has to be hardcoded
+ for (int i = 0; i < 10; i++) // has to be hardcoded
m_weapons[i].Save(buf);
SkipSaveBuf(buf, 5);
CopyToBuf(buf, m_maxWeaponTypeAllowed);
@@ -17777,8 +18485,24 @@ CPed::Load(uint8*& buf)
CopyFromBuf(buf, m_fHealth);
CopyFromBuf(buf, m_fArmour);
SkipSaveBuf(buf, 148);
- for (int i = 0; i < 13; i++) // has to be hardcoded
- m_weapons[i].Load(buf);
+
+ CWeapon bufWeapon;
+ for (int i = 0; i < 10; i++) { // has to be hardcoded
+ bufWeapon.Load(buf);
+
+ if (bufWeapon.m_eWeaponType != WEAPONTYPE_UNARMED) {
+ int modelId = CWeaponInfo::GetWeaponInfo(bufWeapon.m_eWeaponType)->m_nModelId;
+ if (modelId != -1) {
+ CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY);
+ int modelId2 = CWeaponInfo::GetWeaponInfo(bufWeapon.m_eWeaponType)->m_nModel2Id;
+ if (modelId2 != -1)
+ CStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);
+
+ CStreaming::LoadAllRequestedModels(false);
+ }
+ GiveWeapon(bufWeapon.m_eWeaponType, bufWeapon.m_nAmmoTotal);
+ }
+ }
SkipSaveBuf(buf, 5);
CopyFromBuf(buf, m_maxWeaponTypeAllowed);
SkipSaveBuf(buf, 162);
@@ -17786,3 +18510,127 @@ CPed::Load(uint8*& buf)
#undef CopyFromBuf
#undef CopyToBuf
#endif
+
+// --MIAMI: Done
+void
+CPed::GiveDelayedWeapon(eWeaponType weapon, uint32 ammo)
+{
+ m_delayedWeapon = weapon;
+ m_delayedWeaponAmmo = ammo;
+ if (m_delayedWeapon != WEAPONTYPE_UNIDENTIFIED) {
+ int modelId1 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModelId;
+ int modelId2 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModel2Id;
+ if (modelId1 != -1)
+ CStreaming::RequestModel(modelId1, STREAMFLAGS_DEPENDENCY);
+ if (modelId2 != -1)
+ CStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);
+
+ if ((modelId1 == -1 || CStreaming::HasModelLoaded(modelId1))
+ && (modelId2 == -1 || CStreaming::HasModelLoaded(modelId2))) {
+ GiveWeapon(m_delayedWeapon, m_delayedWeaponAmmo, true);
+ m_delayedWeapon = WEAPONTYPE_UNIDENTIFIED;
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::RequestDelayedWeapon()
+{
+ if (m_delayedWeapon != WEAPONTYPE_UNIDENTIFIED) {
+ int modelId1 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModelId;
+ int modelId2 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModel2Id;
+ if (modelId1 != -1)
+ CStreaming::RequestModel(modelId1, STREAMFLAGS_DEPENDENCY);
+ if (modelId2 != -1)
+ CStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);
+
+ if ((modelId1 == -1 || CStreaming::HasModelLoaded(modelId1))
+ && (modelId2 == -1 || CStreaming::HasModelLoaded(modelId2))) {
+ GiveWeapon(m_delayedWeapon, m_delayedWeaponAmmo, 1);
+ m_delayedWeapon = WEAPONTYPE_UNIDENTIFIED;
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ClearFollowPath()
+{
+ for (int i = 0; i < ARRAY_SIZE(m_pPathNodesStates); i++) {
+ m_pPathNodesStates[i] = nil;
+ }
+ m_nPathNodes = 0;
+ m_nCurPathNode = 0;
+}
+
+// --MIAMI: Done except bikes
+void
+CPed::AddInCarAnims(CVehicle* car, bool isDriver)
+{
+ AnimationId anim;
+ AssocGroupId group;
+ if (car->IsBoat()) {
+ if (car->pHandling->Flags & HANDLING_SIT_IN_BOAT) {
+ anim = ANIM_CAR_SIT;
+ } else {
+ anim = ANIM_DRIVE_BOAT;
+ }
+ group = ASSOCGRP_STD;
+ } else if (car->IsBike()) {
+ if (isDriver) {
+ // TODO(Miami): Bikes
+ } else {
+ // TODO(Miami): Bikes
+ }
+ } else {
+ if (isDriver) {
+ if (car->bLowVehicle) {
+ anim = ANIM_CAR_LSIT;
+ } else {
+ anim = ANIM_CAR_SIT;
+ }
+ } else {
+ if (car->bLowVehicle) {
+ anim = ANIM_CAR_SITPLO;
+ } else {
+ anim = ANIM_CAR_SITP;
+ }
+ }
+ group = ASSOCGRP_STD;
+ }
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), group, anim, 100.0f);
+
+ StopNonPartialAnims();
+}
+
+bool
+CPed::CanBeDamagedByThisGangMember(CPed* who)
+{
+ return m_gangFlags & (1 << (uint8)(who->m_nPedType - PEDTYPE_GANG1));
+}
+
+bool
+IsPedPointerValid_NotInWorld(CPed* pPed)
+{
+ if (!pPed)
+ return false;
+ int index = CPools::GetPedPool()->GetJustIndex(pPed);
+#ifdef FIX_BUGS
+ if (index < 0 || index >= NUMPEDS)
+#else
+ if (index < 0 || index > NUMPEDS)
+#endif
+ return false;
+ return true;
+}
+
+bool
+IsPedPointerValid(CPed* pPed)
+{
+ if (!IsPedPointerValid_NotInWorld(pPed))
+ return false;
+ if (pPed->bInVehicle && pPed->m_pMyVehicle)
+ return IsEntityPointerValid(pPed->m_pMyVehicle);
+ return pPed->m_entryInfoList.first || pPed == FindPlayerPed();
+} \ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 56e527c5..f5e6d95a 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -19,6 +19,7 @@ class CObject;
class CFire;
struct AnimBlendFrameData;
class CAnimBlendAssociation;
+class CPedAttractor;
struct PedAudioData
{
@@ -78,11 +79,11 @@ struct FightMove
float endFireTime;
float comboFollowOnTime;
float strikeRadius;
+ float extendReachMultiplier;
uint8 hitLevel; // FightMoveHitLevel
uint8 damage;
uint8 flags;
};
-VALIDATE_SIZE(FightMove, 0x18);
// TODO: This is eFightState on mobile.
enum PedFightMoves
@@ -93,13 +94,21 @@ enum PedFightMoves
FIGHTMOVE_IDLE,
FIGHTMOVE_SHUFFLE_F,
FIGHTMOVE_KNEE,
- FIGHTMOVE_HEADBUTT,
- FIGHTMOVE_PUNCHJAB,
FIGHTMOVE_PUNCHHOOK,
- FIGHTMOVE_KICK,
+ FIGHTMOVE_PUNCHJAB,
+ FIGHTMOVE_PUNCH,
+ FIGHTMOVE_BODYBLOW = FIGHTMOVE_PUNCH,
FIGHTMOVE_LONGKICK,
FIGHTMOVE_ROUNDHOUSE,
- FIGHTMOVE_BODYBLOW,
+ // Directionals
+ FIGHTMOVE_FWDLEFT,
+ FIGHTMOVE_FWDRIGHT,
+ FIGHTMOVE_BACKKICK,
+ FIGHTMOVE_BACKFLIP,
+ FIGHTMOVE_BACKLEFT,
+ FIGHTMOVE_BACKRIGHT,
+ FIGHTMOVE_RIGHTSWEEP,
+ // Special
FIGHTMOVE_GROUNDKICK,
// Opponent
FIGHTMOVE_HITFRONT,
@@ -112,6 +121,9 @@ enum PedFightMoves
FIGHTMOVE_HITBIGSTEP,
FIGHTMOVE_HITONFLOOR,
FIGHTMOVE_HITBEHIND,
+ FIGHTMOVE_MELEE1,
+ FIGHTMOVE_MELEE2,
+ FIGHTMOVE_MELEE3,
FIGHTMOVE_IDLE2NORM,
NUM_FIGHTMOVES
};
@@ -148,12 +160,28 @@ enum eWaitState {
WAITSTATE_PLAYANIM_HANDSUP,
WAITSTATE_PLAYANIM_HANDSCOWER,
WAITSTATE_PLAYANIM_CHAT,
- WAITSTATE_FINISH_FLEE
+ WAITSTATE_FINISH_FLEE,
+ WAITSTATE_SIT_DOWN,
+ WAITSTATE_SIT_DOWN_RVRS,
+ WAITSTATE_SIT_UP,
+ WAITSTATE_SIT_IDLE,
+ WAITSTATE_USE_ATM,
+ WAITSTATE_SUN_BATHE_PRE,
+ WAITSTATE_SUN_BATHE_DOWN,
+ WAITSTATE_SUN_BATHE_IDLE,
+ WAITSTATE_RIOT,
+ WAITSTATE_FAST_FALL,
+ WAITSTATE_BOMBER,
+ WAITSTATE_STRIPPER,
+ WAITSTATE_GROUND_ATTACK,
+ WAITSTATE_LANCESITTING,
+ WAITSTATE_PLAYANIM_HANDSUP_SIMPLE,
};
enum eObjective : uint32 {
OBJECTIVE_NONE,
OBJECTIVE_IDLE,
+ OBJ_2,
OBJECTIVE_FLEE_TILL_SAFE,
OBJECTIVE_GUARD_SPOT,
OBJECTIVE_GUARD_AREA, // not implemented
@@ -165,6 +193,8 @@ enum eObjective : uint32 {
OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS,
OBJECTIVE_GOTO_CHAR_ON_FOOT,
OBJECTIVE_FOLLOW_PED_IN_FORMATION,
+ OBJ_14,
+ OBJ_15,
OBJECTIVE_LEAVE_VEHICLE,
OBJECTIVE_ENTER_CAR_AS_PASSENGER,
OBJECTIVE_ENTER_CAR_AS_DRIVER,
@@ -175,8 +205,8 @@ enum eObjective : uint32 {
OBJECTIVE_GOTO_AREA_ANY_MEANS,
OBJECTIVE_GOTO_AREA_ON_FOOT,
OBJECTIVE_RUN_TO_AREA,
- OBJECTIVE_23, // not implemented
- OBJECTIVE_24, // not implemented
+ OBJECTIVE_26, // not implemented
+ OBJECTIVE_27, // not implemented
OBJECTIVE_FIGHT_CHAR,
OBJECTIVE_SET_LEADER,
OBJECTIVE_FOLLOW_ROUTE,
@@ -185,11 +215,31 @@ enum eObjective : uint32 {
OBJECTIVE_CATCH_TRAIN,
OBJECTIVE_BUY_ICE_CREAM,
OBJECTIVE_STEAL_ANY_CAR,
+ OBJ_36,
OBJECTIVE_MUG_CHAR,
+ OBJECTIVE_LEAVE_CAR_AND_DIE,
+ OBJECTIVE_USE_SEAT_ATTRACTOR,
+ OBJECTIVE_USE_ATM_ATTRACTOR,
OBJECTIVE_FLEE_CAR,
-#ifdef VC_PED_PORTS
- OBJECTIVE_LEAVE_CAR_AND_DIE
-#endif
+ OBJ_42,
+ OBJECTIVE_USE_STOP_ATTRACTOR,
+ OBJECTIVE_USE_PIZZA_ATTRACTOR,
+ OBJECTIVE_USE_SHELTER_ATTRACTOR,
+ OBJ_46,
+ OBJ_47,
+ OBJECTIVE_WAIT_FOR_RAIN_TO_END,
+ OBJ_49,
+ OBJ_50,
+ OBJ_51,
+ OBJECTIVE_WAIT_FOR_BUS,
+ OBJECTIVE_USE_ICECREAM_ATTRACTOR,
+ OBJECTIVE_PURCHASE_ICECREAM,
+ OBJ_55,
+ OBJ_56,
+ OBJ_57,
+ OBJ_58,
+ OBJ_59
+
};
enum {
@@ -379,22 +429,62 @@ public:
uint32 bVehExitWillBeInstant : 1;
uint32 bHasAlreadyBeenRecorded : 1;
uint32 bFallenDown : 1;
-#ifdef VC_PED_PORTS
- uint32 bSomeVCflag1 : 1;
-#endif
#ifdef PED_SKIN
uint32 bDontAcceptIKLookAts : 1; // TODO: find uses of this
#endif
+ uint32 bReachedAttractorHeadingTarget : 1;
+ uint32 bTurnedAroundOnAttractor : 1;
+
+ uint32 bHasAlreadyUsedAttractor : 1;
+ //uint32 b155_2
+ uint32 bCarPassenger : 1;
+ //uint32 b155_8
+ //uint32 b155_10
+ uint32 bMiamiViceCop : 1;
+ //uint32 b155_40
+ //uint32 b155_80
+
+ //uint32 b156_1
+ //uint32 b156_2
+ //uint32 b156_4
+ //uint32 b156_8
+ uint32 bIsPlayerFriend : 1;
+#ifdef VC_PED_PORTS
+ uint32 bHeadStuckInCollision : 1;
+#endif
+ uint32 bDeadPedInFrontOfCar : 1;
+ //uint32 b156_80
+
+ //uint32 b157_1
+ //uint32 b157_2
+ //uint32 b157_4
+ //uint32 b157_8
+ //uint32 b157_10
+ //uint32 b157_20
+ //uint32 b157_40
+ //uint32 b157_80
+
+ //uint32 b158_1
+ //uint32 b158_2
+ //uint32 b158_4
+ //uint32 b158_8
+ //uint32 b158_10
+ //uint32 b158_20
+ //uint32 b158_40
+ //uint32 b158_80
+
// our own flags
uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator
uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle
+ uint8 m_gangFlags;
uint8 CharCreatedBy;
eObjective m_objective;
eObjective m_prevObjective;
CPed *m_pedInObjective;
CVehicle *m_carInObjective;
CVector m_nextRoutePointPos;
+ float m_attractorHeading;
CPed *m_leader;
eFormation m_pedFormation;
uint32 m_fearFlags;
@@ -452,6 +542,11 @@ public:
CVehicle *m_pMyVehicle;
bool bInVehicle;
float m_distanceToCountSeekDone;
+ float m_acceptableHeadingOffset;
+ CPedAttractor* m_attractor;
+ int32 m_positionInQueue;
+ CVehicle* m_vehicleInAccident;
+
bool bRunningToPhone;
int16 m_phoneId;
eCrimeType m_crimeToReportOnPhone;
@@ -469,8 +564,10 @@ public:
uint8 m_stateUnused;
uint32 m_timerUnused;
CVector2D *m_wanderRangeBounds; // array with 2 CVector2D (actually unused CRange2D class) - unused
- CWeapon m_weapons[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS];
+ CWeapon m_weapons[TOTAL_WEAPON_SLOTS];
eWeaponType m_storedWeapon;
+ eWeaponType m_delayedWeapon;
+ uint32 m_delayedWeaponAmmo;
uint8 m_currentWeapon; // eWeaponType
uint8 m_maxWeaponTypeAllowed; // eWeaponType
uint8 m_wepSkills;
@@ -496,12 +593,26 @@ public:
uint32 m_duckTimer;
uint32 m_duckAndCoverTimer;
uint32 m_bloodyFootprintCountOrDeathTime; // Death time when bDoBloodyFootprints is false. Weird decision
+ uint32 m_shotTime;
+ uint32 m_ceaseAttackTimer;
uint8 m_panicCounter;
bool m_deadBleeding;
int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't
CPed *m_nearPeds[10];
uint16 m_numNearPeds;
- int8 m_lastWepDam;
+ uint16 m_nPedMoney;
+ int8 m_lastWepDam;
+ CEntity *m_lastDamEntity;
+ CEntity *m_attachedTo;
+ CVector m_vecAttachOffset;
+ uint16 m_attachType;
+ float m_attachRot;
+ uint32 m_attachWepAmmo;
+ uint32 m_threatFlags;
+ uint32 m_threatCheck;
+ uint32 m_lastThreatCheck;
+ uint32 m_sayType;
+ uint32 m_sayTimer;
uint32 m_lastSoundStart;
uint32 m_soundStart;
uint16 m_lastQueuedSound;
@@ -549,9 +660,10 @@ public:
void ClearAttack(void);
bool IsPedHeadAbovePos(float zOffset);
void RemoveWeaponModel(int modelId);
- void SetCurrentWeapon(uint32 weaponType);
+ void SetCurrentWeapon(eWeaponType weaponType);
+ void SetCurrentWeapon(int weapon);
void Duck(void);
- void ClearDuck(void);
+ void ClearDuck(bool = false);
void ClearPointGunAt(void);
void BeingDraggedFromCar(void);
void RestartNonPartialAnims(void);
@@ -560,7 +672,7 @@ public:
void PlayFootSteps(void);
void QuitEnteringCar(void);
void BuildPedLists(void);
- uint32 GiveWeapon(eWeaponType weaponType, uint32 ammo);
+ int32 GiveWeapon(eWeaponType weaponType, uint32 ammo, bool unused = false);
void CalculateNewOrientation(void);
float WorkOutHeadingForMovingFirstPerson(float);
void CalculateNewVelocity(void);
@@ -575,10 +687,11 @@ public:
void SetObjective(eObjective, int16, int16);
void SetObjective(eObjective, CVector);
void SetObjective(eObjective, CVector, float);
+ void SetObjective(eObjective, float, const CVector&);
void ClearChat(void);
void InformMyGangOfAttack(CEntity*);
void ReactToAttack(CEntity*);
- void SetDuck(uint32);
+ void SetDuck(uint32, bool = false);
void RegisterThreatWithGangPeds(CEntity*);
bool TurnBody(void);
void Chat(void);
@@ -596,7 +709,9 @@ public:
void SetPointGunAt(CEntity*);
bool Seek(void);
bool SetWanderPath(int8);
- bool SetFollowPath(CVector);
+ bool SetFollowPath(CVector dest, float radius, eMoveState state, CEntity*, CEntity*, int);
+ bool SetFollowPathStatic(void);
+ bool SetFollowPathDynamic(void);
void ClearAttackByRemovingAnim(void);
void SetStoredState(void);
void StopNonPartialAnims(void);
@@ -632,8 +747,10 @@ public:
void RemoveInCarAnims(void);
void CollideWithPed(CPed*);
void SetDirectionToWalkAroundObject(CEntity*);
+ void RemoveWeaponAnims(int, float);
void CreateDeadPedMoney(void);
void CreateDeadPedWeaponPickups(void);
+ void CreateDeadPedPickupCoors(float *x, float *y, float *z);
void SetAttackTimer(uint32);
void SetBeingDraggedFromCar(CVehicle*, uint32, bool);
void SetRadioStation(void);
@@ -647,7 +764,6 @@ public:
void EnterCar(void);
uint8 GetNearestTrainPedPosition(CVehicle*, CVector&);
uint8 GetNearestTrainDoor(CVehicle*, CVector&);
- void LineUpPedWithTrain(void);
void ExitCar(void);
void Fight(void);
bool FindBestCoordsFromNodes(CVector, CVector*);
@@ -694,7 +810,6 @@ public:
void SetExitCar(CVehicle*, uint32);
void SetFormation(eFormation);
bool WillChat(CPed*);
- void SetEnterTrain(CVehicle*, uint32);
void SetEnterCar_AllClear(CVehicle*, uint32, uint32);
void SetSolicit(uint32 time);
void ScanForInterestingStuff(void);
@@ -703,6 +818,11 @@ public:
bool WarpPedToNearLeaderOffScreen(void);
void Solicit(void);
void SetExitBoat(CVehicle*);
+ void ClearFollowPath();
+ void GiveDelayedWeapon(eWeaponType weapon, uint32 ammo);
+ void RequestDelayedWeapon();
+ void AddInCarAnims(CVehicle* car, bool isDriver);
+ bool CanBeDamagedByThisGangMember(CPed*);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
@@ -730,8 +850,9 @@ public:
static void PedSetDraggedOutCarCB(CAnimBlendAssociation *assoc, void *arg);
static void PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg);
static void PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg);
- static void PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg); // TODO(Miami): Should be under GTA_TRAIN
static void FinishedAttackCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishedReloadCB(CAnimBlendAssociation *assoc, void *arg);
static void FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg);
static void PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg);
static void FinishJumpCB(CAnimBlendAssociation *assoc, void *arg);
@@ -760,8 +881,14 @@ public:
void SetPedStats(ePedStats);
bool IsGangMember(void);
void Die(void);
+#ifdef GTA_TRAIN
void EnterTrain(void);
void ExitTrain(void);
+ void SetExitTrain(CVehicle*);
+ void SetPedPositionInTrain(void);
+ void LineUpPedWithTrain(void);
+ void SetEnterTrain(CVehicle*, uint32);
+#endif
void Fall(void);
bool IsPedShootable(void);
void Look(void);
@@ -769,11 +896,9 @@ public:
void RestoreHeadPosition(void);
void PointGunAt(void);
bool ServiceTalkingWhenDead(void);
- void SetPedPositionInTrain(void);
void SetShootTimer(uint32);
void SetSeekCar(CVehicle*, uint32);
void SetSeekBoatPosition(CVehicle*);
- void SetExitTrain(CVehicle*);
void WanderRange(void);
void SetFollowRoute(int16, int16);
void SeekBoatPosition(void);
@@ -786,12 +911,20 @@ public:
bool CanPedJumpThis(CEntity*);
#endif
- bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
- CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
+ void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int);
+ void ClearWaitState(void);
+
+ bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; }
+ CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; }
CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
PedState GetPedState(void) { return m_nPedState; }
- void SetPedState(PedState state) { m_nPedState = state; }
+ void SetPedState(PedState state)
+ {
+ if (GetPedState() == PED_FOLLOW_PATH)
+ ClearFollowPath();
+ m_nPedState = state;
+ }
bool Dead(void) { return m_nPedState == PED_DEAD; }
bool Dying(void) { return m_nPedState == PED_DIE; }
bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; }
@@ -800,10 +933,65 @@ public:
bool Driving(void) { return m_nPedState == PED_DRIVING; }
bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state.
bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; }
+ bool HasAttractor(void) { return m_attractor != nil; }
+ bool IsUseAttractorObjective(eObjective obj) {
+ return obj == OBJECTIVE_USE_ATM_ATTRACTOR || obj == OBJECTIVE_USE_ICECREAM_ATTRACTOR ||
+ obj == OBJECTIVE_USE_PIZZA_ATTRACTOR || obj == OBJECTIVE_USE_SEAT_ATTRACTOR ||
+ obj == OBJECTIVE_USE_SHELTER_ATTRACTOR || obj == OBJECTIVE_USE_STOP_ATTRACTOR;
+ }
void ReplaceWeaponWhenExitingVehicle(void);
void RemoveWeaponWhenEnteringVehicle(void);
bool IsNotInWreckedVehicle();
+
+ // My names. Inlined in VC
+ AnimationId GetFireAnimNotDucking(CWeaponInfo* weapon) {
+ if (m_nPedType == PEDTYPE_COP && !!weapon->m_bCop3rd)
+ return ANIM_WEAPON_FIRE_3RD;
+ else
+ return GetPrimaryFireAnim(weapon);
+ }
+
+ static AnimationId GetFireAnimGround(CWeaponInfo* weapon, bool kickFloorIfNone = true) {
+ if (!!weapon->m_bGround2nd)
+ return ANIM_WEAPON_CROUCHFIRE;
+ else if (!!weapon->m_bGround3rd)
+ return ANIM_WEAPON_FIRE_3RD;
+ else if (kickFloorIfNone)
+ return ANIM_KICK_FLOOR;
+ else
+ return (AnimationId)0;
+ }
+
+ static AnimationId GetPrimaryFireAnim(CWeaponInfo* weapon) {
+ if (weapon->m_bAnimDetonate)
+ return ANIM_BOMBER;
+ else
+ return ANIM_WEAPON_FIRE;
+ }
+
+ static AnimationId GetCrouchReloadAnim(CWeaponInfo* weapon) {
+ if (!!weapon->m_bReload)
+ return ANIM_WEAPON_CROUCHRELOAD;
+ else
+ return (AnimationId)0;
+ }
+
+ static AnimationId GetCrouchFireAnim(CWeaponInfo* weapon) {
+ if (!!weapon->m_bCrouchFire)
+ return ANIM_WEAPON_CROUCHFIRE;
+ else
+ return (AnimationId)0;
+ }
+
+ static AnimationId GetReloadAnim(CWeaponInfo* weapon) {
+ if (!!weapon->m_bReload)
+ return ANIM_WEAPON_RELOAD;
+ else
+ return (AnimationId)0;
+ }
+ // --
+
// My additions, because there were many, many instances of that.
inline void SetFindPathAndFlee(CEntity *fleeFrom, int time, bool walk = false)
{
@@ -822,43 +1010,24 @@ public:
if (walk)
SetMoveState(PEDMOVE_WALK);
}
+ // --
// Using this to abstract nodes of skinned and non-skinned meshes
CVector GetNodePosition(int32 node)
{
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- RwV3d pos = { 0.0f, 0.0f, 0.0f };
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
- RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
- // this is just stupid
- //RwV3dTransformPoints(&pos, &pos, 1, &mats[idx]);
- pos = mats[idx].pos;
- return pos;
- }else
-#endif
- {
- RwMatrix mat;
- CPedIK::GetWorldMatrix(m_pFrames[node]->frame, &mat);
- return mat.pos;
- }
+ RwV3d pos = { 0.0f, 0.0f, 0.0f };
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
+ RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
+ pos = mats[idx].pos;
+ return pos;
}
void TransformToNode(CVector &pos, int32 node)
{
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
- RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
- RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, &mats[idx]);
- }else
-#endif
- {
- RwFrame *frame;
- for (frame = m_pFrames[node]->frame; frame; frame = RwFrameGetParent(frame))
- RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, RwFrameGetMatrix(frame));
- }
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
+ RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
+ RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, &mats[idx]);
}
// set by 0482:set_threat_reaction_range_multiplier opcode
@@ -883,10 +1052,6 @@ public:
void DebugRenderOnePedText(void);
#endif
-#ifdef PED_SKIN
- void renderLimb(int node);
-#endif
-
#ifdef COMPATIBLE_SAVES
virtual void Save(uint8*& buf);
virtual void Load(uint8*& buf);
@@ -895,6 +1060,10 @@ public:
void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg);
+// TODO(Miami): Change those when Ped struct is done
#ifndef PED_SKIN
VALIDATE_SIZE(CPed, 0x53C);
#endif
+
+bool IsPedPointerValid(CPed*);
+bool IsPedPointerValid_NotInWorld(CPed*);
diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp
new file mode 100644
index 00000000..782d2770
--- /dev/null
+++ b/src/peds/PedAttactor.cpp
@@ -0,0 +1,775 @@
+#include "common.h"
+#include "PedAttractor.h"
+
+#include "General.h"
+#include "Vehicle.h"
+#include "World.h"
+
+const int gcMaxSizeOfAtmQueue = 1;
+const int gcMaxSizeOfSeatQueue = 1;
+const int gcMaxSizeOfStopQueue = 5;
+const int gcMaxSizeOfPizzaQueue = 5;
+const int gcMaxSizeOfShelterQueue = 5;
+const int gcMaxSizeOfIceCreamQueue = 1;
+
+//--MIAMI: file done
+
+std::vector<CVector> CPedShelterAttractor::ms_displacements;
+
+CPedAttractorManager* GetPedAttractorManager()
+{
+ static CPedAttractorManager manager;
+ return &manager;
+}
+
+CVehicleToEffect::CVehicleToEffect(CVehicle* pVehicle) : m_pVehicle(pVehicle)
+{
+ m_effects[1].col = CRGBA(0, 0, 0, 0);
+ m_effects[1].type = EFFECT_PED_ATTRACTOR;
+ m_effects[1].pos = CVector(2.0f, 1.0f, 0.0f);
+ m_effects[1].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f);
+ m_effects[1].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f);
+ m_effects[1].pedattr.type = ATTRACTOR_ICECREAM;
+
+ m_effects[3].col = CRGBA(0, 0, 0, 0);
+ m_effects[3].type = EFFECT_PED_ATTRACTOR;
+ m_effects[3].pos = CVector(2.0f, -0.5f, 0.0f);
+ m_effects[3].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f);
+ m_effects[3].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f);
+ m_effects[3].pedattr.type = ATTRACTOR_ICECREAM;
+
+ m_effects[0].col = CRGBA(0, 0, 0, 0);
+ m_effects[0].type = EFFECT_PED_ATTRACTOR;
+ m_effects[0].pos = CVector(-2.0f, 1.0f, 0.0f);
+ m_effects[0].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f);
+ m_effects[0].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f);
+ m_effects[0].pedattr.type = ATTRACTOR_ICECREAM;
+
+ m_effects[2].col = CRGBA(0, 0, 0, 0);
+ m_effects[2].type = EFFECT_PED_ATTRACTOR;
+ m_effects[2].pos = CVector(-2.0f, -0.5f, 0.0f);
+ m_effects[2].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f);
+ m_effects[2].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f);
+ m_effects[2].pedattr.type = ATTRACTOR_ICECREAM;
+}
+
+CVehicleToEffect& CVehicleToEffect::From(const CVehicleToEffect& other)
+{
+ m_pVehicle = other.m_pVehicle;
+ for (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) {
+ m_effects[i].col = other.m_effects[i].col;
+ m_effects[i].type = other.m_effects[i].type;
+ m_effects[i].pos = other.m_effects[i].pos;
+ m_effects[i].pedattr = other.m_effects[i].pedattr;
+ }
+ return *this;
+}
+
+const C2dEffect* CVehicleToEffect::ChooseEffect(const CVector& pos) const
+{
+ if (!m_pVehicle)
+ return nil;
+ if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetRight()) > 0.0f) {
+ if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f)
+ return &m_effects[0];
+ else
+ return &m_effects[2];
+ }
+ else {
+ if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f)
+ return &m_effects[1];
+ else
+ return &m_effects[3];
+ }
+}
+
+bool CVehicleToEffect::HasThisEffect(C2dEffect* pEffect) const
+{
+ for (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) {
+ if (pEffect == &m_effects[i])
+ return true;
+ }
+ return false;
+}
+
+const C2dEffect* CPedAttractorManager::GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos)
+{
+ if (!vVehicleToEffect.empty()) {
+ for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) {
+ if (assoc->GetVehicle() == pVehicle)
+ return assoc->ChooseEffect(pos);
+ }
+ }
+ CVehicleToEffect effect(pVehicle);
+ vVehicleToEffect.push_back(effect);
+ return effect.ChooseEffect(pos);
+}
+
+CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect)
+{
+ if (vVehicleToEffect.empty())
+ return false;
+ for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) {
+ if (assoc->HasThisEffect(pEffect))
+ return assoc->GetVehicle();
+ }
+ return nil;
+}
+
+const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors)
+{
+ if (vecAttractors.empty())
+ return nil;
+ for (std::vector<CPedAttractor*>::const_iterator attractor = vecAttractors.cbegin(); attractor != vecAttractors.cend(); ++attractor) {
+ if ((*attractor)->GetEffect() == pEffect)
+ return *attractor;
+ }
+ return nil;
+}
+
+void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect)
+{
+ CVehicle* pVehicle = GetIceCreamVanForEffect(pEffect);
+ if (!pVehicle)
+ return;
+ if (vVehicleToEffect.empty())
+ return;
+ for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend();) {
+ if (assoc->GetVehicle() != pVehicle)
+ return;
+ size_t total = 0;
+ for (size_t j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) {
+ if (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors))
+ total++;
+ }
+ if (total > 0)
+ assoc++;
+ else
+ assoc = vVehicleToEffect.erase(assoc);
+ }
+}
+
+CPedAttractor::CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ p2dEffect(pEffect),
+ m_nMaxPedsInAttractor(maxpeds),
+ m_fQueueDistance(qdist),
+ m_fTimeInWaitQueue(waitTime),
+ m_fTimeInApproachingQueue(approachTime),
+ m_fDistanceToUseAttractor(distance),
+ m_fAcceptableHeading(headingdiff),
+ m_fMaxPositionDisplacement(posdisp),
+ m_fMaxHeadingDisplacement(headdisp)
+{
+ CPedAttractorManager::ComputeEffectPos(pEffect, matrix, vecEffectPos);
+ CPedAttractorManager::ComputeEffectQueueDir(pEffect, matrix, vecQueueDir);
+ CPedAttractorManager::ComputeEffectUseDir(pEffect, matrix, vecUseDir);
+}
+
+void CPedPizzaAttractor::UpdatePedStateOnDeparture(CPed* pPed) const
+{
+ if (pPed->m_nPedMoney > 10)
+ pPed->m_nPedMoney -= 10;
+ else
+ pPed->m_nPedMoney = 0;
+}
+
+void CPedAtmAttractor::UpdatePedStateOnDeparture(CPed* pPed) const
+{
+ pPed->m_nPedMoney += 20 * CGeneral::GetRandomNumberInRange(1, 51);
+};
+
+float CPedAttractor::ComputeDeltaHeading() const
+{
+ return CGeneral::GetRandomNumberInRange(-m_fMaxHeadingDisplacement, m_fMaxHeadingDisplacement);
+}
+
+float CPedAttractor::ComputeDeltaPos() const
+{
+ return CGeneral::GetRandomNumberInRange(-m_fMaxPositionDisplacement, m_fMaxPositionDisplacement);
+}
+
+void CPedAttractor::ComputeAttractTime(int32 id, bool approacher, float& time) const
+{
+ if (approacher)
+ time = m_fTimeInApproachingQueue;
+ else
+ time = m_fTimeInWaitQueue;
+}
+
+void CPedAttractor::ComputeAttractPos(int32 qid, CVector& pos) const
+{
+ if (!p2dEffect)
+ return;
+ pos = vecEffectPos - qid * vecQueueDir * m_fQueueDistance;
+ if (qid != 0) {
+ pos.x += ComputeDeltaPos();
+ pos.y += ComputeDeltaPos();
+ }
+}
+
+CVector CPedShelterAttractor::GetDisplacement(int32 qid) const
+{
+ if (ms_displacements.empty()) {
+ int i = 0;
+ while (i < gcMaxSizeOfShelterQueue) {
+ float fRandomAngle = CGeneral::GetRandomNumberInRange(0.0f, TWOPI);
+ float fRandomOffset = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);
+ CVector vecDisplacement(fRandomOffset * Sin(fRandomAngle), fRandomOffset * Cos(fRandomAngle), 0.0f);
+ bool close = false;
+ for (std::vector<CVector>::const_iterator v = ms_displacements.cbegin(); v != ms_displacements.cend(); ++v) {
+ if ((*v - vecDisplacement).Magnitude() < 1.0f) {
+ close = true;
+ break;
+ }
+ }
+ if (!close) {
+ ms_displacements.push_back(vecDisplacement);
+ i++;
+ }
+ }
+ }
+ return ms_displacements[qid];
+}
+
+void CPedShelterAttractor::ComputeAttractPos(int32 qid, CVector& pos) const
+{
+ if (!p2dEffect)
+ return;
+ pos = vecEffectPos + GetDisplacement(qid);
+}
+
+void CPedAttractor::ComputeAttractHeading(int32 qid, float& heading) const
+{
+ heading = CGeneral::GetRadianAngleBetweenPoints(qid != 0 ? vecQueueDir.x : vecUseDir.x, qid != 0 ? vecQueueDir.y : vecUseDir.y, 0.0f, 0.0f);
+ if (qid != 0)
+ heading += ComputeDeltaHeading();
+}
+
+void CPedShelterAttractor::ComputeAttractHeading(int32 qid, float& heading) const
+{
+ heading = CGeneral::GetRandomNumberInRange(0.0f, TWOPI);
+}
+
+bool CPedAttractor::RegisterPed(CPed* pPed)
+{
+ for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
+ if (*pPedIt == pPed) {
+ vApproachingQueue.erase(pPedIt);
+ return false;
+ }
+ }
+ if (GetNoOfRegisteredPeds() >= m_nMaxPedsInAttractor)
+ return 0;
+ vApproachingQueue.push_back(pPed);
+ CVector pos;
+ float heading;
+ float time;
+ int32 slot = ComputeFreeSlot();
+ ComputeAttractPos(slot, pos);
+ ComputeAttractHeading(slot, heading);
+ ComputeAttractTime(slot, false, time);
+ pPed->SetNewAttraction(this, pos, heading, time, slot);
+ return true;
+}
+
+static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed)
+{
+ switch (type) {
+ case ATTRACTOR_ATM:
+ if (pPed->m_objective == OBJECTIVE_USE_ATM_ATTRACTOR)
+ return true;
+ break;
+ case ATTRACTOR_SEAT:
+ if (pPed->m_objective == OBJECTIVE_USE_SEAT_ATTRACTOR)
+ return true;
+ break;
+ case ATTRACTOR_STOP:
+ if (pPed->m_objective == OBJECTIVE_USE_STOP_ATTRACTOR || pPed->m_objective == OBJECTIVE_WAIT_FOR_BUS || pPed->m_objective == OBJECTIVE_IDLE)
+ return true;
+ break;
+ case ATTRACTOR_PIZZA:
+ if (pPed->m_objective == OBJECTIVE_USE_PIZZA_ATTRACTOR || pPed->m_objective == OBJECTIVE_IDLE)
+ return true;
+ break;
+ case ATTRACTOR_SHELTER:
+ if (pPed->m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR || pPed->m_objective == OBJECTIVE_WAIT_FOR_RAIN_TO_END)
+ return true;
+ break;
+ case ATTRACTOR_ICECREAM:
+ if (pPed->m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR || pPed->m_objective == OBJECTIVE_PURCHASE_ICECREAM)
+ return true;
+ break;
+ }
+ return false;
+}
+
+bool CPedAttractor::DeRegisterPed(CPed* pPed)
+{
+ for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
+ if (*pPedIt != pPed)
+ continue;
+ pPed->m_attractor = nil;
+ pPed->m_positionInQueue = -1;
+ pPed->bHasAlreadyUsedAttractor = true;
+
+ if (IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed))
+ pPed->SetObjective(OBJECTIVE_NONE);
+ else if (pPed->GetPedState() != PED_IDLE && pPed->GetPedState() != PED_NONE) {
+ vApproachingQueue.erase(pPedIt);
+ return true;
+ }
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
+ vApproachingQueue.erase(pPedIt);
+ return true;
+ }
+ return BroadcastDeparture(pPed);
+}
+
+bool CPedAttractor::BroadcastArrival(CPed* pPed)
+{
+ for (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) {
+ if (*pPedIt == pPed)
+ return false;
+ }
+ vWaitingQueue.push_back(pPed);
+ for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
+ if (*pPedIt == pPed) {
+ vApproachingQueue.erase(pPedIt);
+ break;
+ }
+ }
+ for (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {
+ CPed* pPed = *pPedIt;
+ CVector pos;
+ float heading;
+ float time;
+ int32 slot = ComputeFreeSlot();
+ ComputeAttractPos(slot, pos);
+ ComputeAttractHeading(slot, heading);
+ ComputeAttractTime(slot, false, time);
+ pPed->SetNewAttraction(this, pos, heading, time, slot);
+ }
+ return true;
+}
+
+bool CPedAttractor::BroadcastDeparture(CPed* pPed)
+{
+ int qid = -1;
+ for (size_t i = 0; i < vWaitingQueue.size(); i++){
+ if (vWaitingQueue[i] == pPed)
+ qid = i;
+ }
+ if (qid < 0)
+ return false;
+ for (size_t i = qid + 1; i < vWaitingQueue.size(); i++) {
+ CVector pos;
+ float heading;
+ float time;
+ ComputeAttractPos(i - 1, pos);
+ ComputeAttractHeading(i - 1, heading);
+ ComputeAttractTime(i - 1, true, time);
+ pPed->SetNewAttraction(this, pos, heading, time, i - 1);
+ }
+ pPed->m_attractor = nil;
+ pPed->m_positionInQueue = -1;
+ pPed->bHasAlreadyUsedAttractor = true;
+ if (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) {
+ if (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE)
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
+ }
+ else if (qid == 0)
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y));
+ else if (qid == vWaitingQueue.size() - 1)
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
+ else
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.z));
+ vWaitingQueue.erase(vWaitingQueue.cbegin() + qid);
+ for (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {
+ CPed* pPed = *pPedIt;
+ CVector pos;
+ float heading;
+ float time;
+ int32 slot = ComputeFreeSlot();
+ ComputeAttractPos(slot, pos);
+ ComputeAttractHeading(slot, heading);
+ ComputeAttractTime(slot, false, time);
+ pPed->SetNewAttraction(this, pos, heading, time, slot);
+ }
+ return true;
+}
+
+bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed)
+{
+ int qid = -1;
+ for (size_t i = 0; i < vWaitingQueue.size(); i++) {
+ if (vWaitingQueue[i] == pPed)
+ qid = i;
+ }
+ if (qid < 0)
+ return false;
+ pPed->m_attractor = nil;
+ pPed->m_positionInQueue = -1;
+ pPed->bHasAlreadyUsedAttractor = true;
+ if (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) {
+ if (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE)
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
+ }
+ else if (qid == 0)
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y));
+ else if (qid == vWaitingQueue.size() - 1)
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
+ else
+ pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.z));
+ vWaitingQueue.erase(vWaitingQueue.cbegin() + qid);
+ for (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {
+ CPed* pPed = *pPedIt;
+ CVector pos;
+ float heading;
+ float time;
+ int32 slot = ComputeFreeSlot();
+ ComputeAttractPos(slot, pos);
+ ComputeAttractHeading(slot, heading);
+ ComputeAttractTime(slot, false, time);
+ pPed->SetNewAttraction(this, pos, heading, time, slot);
+ }
+ return true;
+}
+
+bool CPedAttractor::IsRegisteredWithPed(CPed* pPed) const
+{
+ for (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) {
+ if (*pPedIt == pPed)
+ return true;
+ }
+ for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
+ if (*pPedIt == pPed) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CPedAttractor::IsInQueue(CPed* pPed) const
+{
+ for (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) {
+ if (*pPedIt == pPed)
+ return true;
+ }
+ return false;
+}
+
+CPedAttractor* CPedAttractorManager::RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix)
+{
+ if (pEffect->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ if (IsPedRegisteredWithEffect(pPed))
+ return nil;
+ switch (pEffect->pedattr.type) {
+ case ATTRACTOR_ATM: return RegisterPed(pPed, pEffect, matrix, vAtmAttractors);
+ case ATTRACTOR_SEAT: return RegisterPed(pPed, pEffect, matrix, vSeatAttractors);
+ case ATTRACTOR_STOP: return RegisterPed(pPed, pEffect, matrix, vStopAttractors);
+ case ATTRACTOR_PIZZA: return RegisterPed(pPed, pEffect, matrix, vPizzaAttractors);
+ case ATTRACTOR_SHELTER: return RegisterPed(pPed, pEffect, matrix, vShelterAttractors);
+ case ATTRACTOR_ICECREAM: return RegisterPed(pPed, pEffect, matrix, vIceCreamAttractors);
+ }
+ return nil;
+}
+
+bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor)
+{
+ if (!pAttractor)
+ return false;
+ if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ if (!IsPedRegisteredWithEffect(pPed))
+ return nil;
+ switch (pAttractor->GetEffect()->pedattr.type) {
+ case ATTRACTOR_ATM: return DeRegisterPed(pPed, pAttractor, vAtmAttractors);
+ case ATTRACTOR_SEAT: return DeRegisterPed(pPed, pAttractor, vSeatAttractors);
+ case ATTRACTOR_STOP: return DeRegisterPed(pPed, pAttractor, vStopAttractors);
+ case ATTRACTOR_PIZZA: return DeRegisterPed(pPed, pAttractor, vPizzaAttractors);
+ case ATTRACTOR_SHELTER: return DeRegisterPed(pPed, pAttractor, vShelterAttractors);
+ case ATTRACTOR_ICECREAM: return DeRegisterPed(pPed, pAttractor, vIceCreamAttractors);
+ }
+ return nil;
+}
+
+bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor)
+{
+ if (!pAttractor)
+ return false;
+ if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ if (!IsPedRegisteredWithEffect(pPed))
+ return nil;
+ switch (pAttractor->GetEffect()->pedattr.type) {
+ case ATTRACTOR_ATM: return BroadcastArrival(pPed, pAttractor, vAtmAttractors);
+ case ATTRACTOR_SEAT: return BroadcastArrival(pPed, pAttractor, vSeatAttractors);
+ case ATTRACTOR_STOP: return BroadcastArrival(pPed, pAttractor, vStopAttractors);
+ case ATTRACTOR_PIZZA: return BroadcastArrival(pPed, pAttractor, vPizzaAttractors);
+ case ATTRACTOR_SHELTER: return BroadcastArrival(pPed, pAttractor, vShelterAttractors);
+ case ATTRACTOR_ICECREAM: return BroadcastArrival(pPed, pAttractor, vIceCreamAttractors);
+ }
+ return nil;
+}
+
+bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor)
+{
+ if (!pAttractor)
+ return false;
+ if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ if (!IsPedRegisteredWithEffect(pPed))
+ return nil;
+ switch (pAttractor->GetEffect()->pedattr.type) {
+ case ATTRACTOR_ATM: return BroadcastDeparture(pPed, pAttractor, vAtmAttractors);
+ case ATTRACTOR_SEAT: return BroadcastDeparture(pPed, pAttractor, vSeatAttractors);
+ case ATTRACTOR_STOP: return BroadcastDeparture(pPed, pAttractor, vStopAttractors);
+ case ATTRACTOR_PIZZA: return BroadcastDeparture(pPed, pAttractor, vPizzaAttractors);
+ case ATTRACTOR_SHELTER: return BroadcastDeparture(pPed, pAttractor, vShelterAttractors);
+ case ATTRACTOR_ICECREAM: return BroadcastDeparture(pPed, pAttractor, vIceCreamAttractors);
+ }
+ return nil;
+}
+
+bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor)
+{
+ if (!pAttractor)
+ return false;
+ if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ if (!IsPedRegisteredWithEffect(pPed))
+ return nil;
+ switch (pAttractor->GetEffect()->pedattr.type) {
+ case ATTRACTOR_ATM: return IsAtHeadOfQueue(pPed, pAttractor, vAtmAttractors);
+ case ATTRACTOR_SEAT: return IsAtHeadOfQueue(pPed, pAttractor, vSeatAttractors);
+ case ATTRACTOR_STOP: return IsAtHeadOfQueue(pPed, pAttractor, vStopAttractors);
+ case ATTRACTOR_PIZZA: return IsAtHeadOfQueue(pPed, pAttractor, vPizzaAttractors);
+ case ATTRACTOR_SHELTER: return IsAtHeadOfQueue(pPed, pAttractor, vShelterAttractors);
+ case ATTRACTOR_ICECREAM: return IsAtHeadOfQueue(pPed, pAttractor, vIceCreamAttractors);
+ }
+ return nil;
+}
+
+bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor)
+{
+ if (!pAttractor)
+ return false;
+ if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ if (!IsPedRegisteredWithEffect(pPed))
+ return nil;
+ switch (pAttractor->GetEffect()->pedattr.type) {
+ case ATTRACTOR_ATM: return IsInQueue(pPed, pAttractor, vAtmAttractors);
+ case ATTRACTOR_SEAT: return IsInQueue(pPed, pAttractor, vSeatAttractors);
+ case ATTRACTOR_STOP: return IsInQueue(pPed, pAttractor, vStopAttractors);
+ case ATTRACTOR_PIZZA: return IsInQueue(pPed, pAttractor, vPizzaAttractors);
+ case ATTRACTOR_SHELTER: return IsInQueue(pPed, pAttractor, vShelterAttractors);
+ case ATTRACTOR_ICECREAM: return IsInQueue(pPed, pAttractor, vIceCreamAttractors);
+ }
+ return nil;
+}
+
+bool CPedAttractorManager::HasEmptySlot(const C2dEffect* pEffect)
+{
+ if (!pEffect)
+ return false;
+ if (pEffect->type != EFFECT_PED_ATTRACTOR)
+ return nil;
+ const CPedAttractor* pAttractor;
+ switch (pEffect->pedattr.type) {
+ case ATTRACTOR_ATM: pAttractor = FindAssociatedAttractor(pEffect, vAtmAttractors); break;
+ case ATTRACTOR_SEAT: pAttractor = FindAssociatedAttractor(pEffect, vSeatAttractors); break;
+ case ATTRACTOR_STOP: pAttractor = FindAssociatedAttractor(pEffect, vStopAttractors); break;
+ case ATTRACTOR_PIZZA: pAttractor = FindAssociatedAttractor(pEffect, vPizzaAttractors); break;
+ case ATTRACTOR_SHELTER: pAttractor = FindAssociatedAttractor(pEffect, vShelterAttractors); break;
+ case ATTRACTOR_ICECREAM: pAttractor = FindAssociatedAttractor(pEffect, vIceCreamAttractors); break;
+ default: return true;
+ }
+ if (!pAttractor)
+ return true;
+ return pAttractor->GetNoOfRegisteredPeds() < pAttractor->GetMaxPedsInAttractor();
+}
+
+bool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed)
+{
+ return IsPedRegistered(pPed, vAtmAttractors) ||
+ IsPedRegistered(pPed, vSeatAttractors) ||
+ IsPedRegistered(pPed, vStopAttractors) ||
+ IsPedRegistered(pPed, vPizzaAttractors) ||
+ IsPedRegistered(pPed, vShelterAttractors) ||
+ IsPedRegistered(pPed, vIceCreamAttractors);
+}
+
+void CPedAttractorManager::ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
+{
+ pos = matrix.GetPosition() + Multiply3x3(matrix, pEffect->pos);
+}
+
+void CPedAttractorManager::ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
+{
+ pos = Multiply3x3(matrix, pEffect->pedattr.queueDir);
+}
+
+void CPedAttractorManager::ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
+{
+ pos = Multiply3x3(matrix, pEffect->pedattr.useDir);
+}
+
+CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector<CPedAttractor*>& vecAttractors)
+{
+ CPedAttractor* pRegisteredAttractor = nil;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ CPedAttractor* pAttractor = *pAttractorIt;
+ CVector vEffectPos;
+ ComputeEffectPos(pAttractor->GetEffect(), matrix, vEffectPos);
+ if (pAttractor->GetEffect() == pEffect && vEffectPos == pAttractor->GetEffectPos()) {
+ if (!IsApproachable(pEffect, matrix, pAttractor->ComputeFreeSlot(), pPed))
+ return false;
+ pRegisteredAttractor = pAttractor;
+ break;
+ }
+ }
+ if (pRegisteredAttractor || !IsApproachable(pEffect, matrix, 0, pPed)) {
+ if (pRegisteredAttractor)
+ pRegisteredAttractor->RegisterPed(pPed);
+ return pRegisteredAttractor;
+ }
+ switch (pEffect->pedattr.type) {
+ case ATTRACTOR_ATM: vecAttractors.push_back(new CPedAtmAttractor(pEffect, matrix, gcMaxSizeOfAtmQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.15f, 0.1f, 0.1f)); break;
+ case ATTRACTOR_SEAT: vecAttractors.push_back(new CPedSeatAttractor(pEffect, matrix, gcMaxSizeOfSeatQueue, 1.0f, 30000.0f, 3000.0f, 0.125f, 0.1f, 0.1f, 0.1f)); break;
+ case ATTRACTOR_STOP: vecAttractors.push_back(new CPedStopAttractor(pEffect, matrix, gcMaxSizeOfStopQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f)); break;
+ case ATTRACTOR_PIZZA: vecAttractors.push_back(new CPedPizzaAttractor(pEffect, matrix, gcMaxSizeOfPizzaQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f)); break;
+ case ATTRACTOR_SHELTER: vecAttractors.push_back(new CPedShelterAttractor(pEffect, matrix, gcMaxSizeOfShelterQueue, 1.0f, 30000.0f, 3000.0f, 0.5f, 6.28f, 0.1f, 0.1f)); break;
+ case ATTRACTOR_ICECREAM: vecAttractors.push_back(new CPedIceCreamAttractor(pEffect, matrix, gcMaxSizeOfIceCreamQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.3f, 0.1f, 0.1f)); break;
+ }
+ if (pRegisteredAttractor)
+ pRegisteredAttractor->RegisterPed(pPed);
+ return pRegisteredAttractor;
+}
+
+bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
+{
+ if (!pAttractor)
+ return false;
+ CPedAttractor* pFound = nil;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ pFound = *pAttractorIt;
+ break;
+ }
+ }
+ if (!pFound)
+ return false;
+ pFound->DeRegisterPed(pPed);
+ if (pFound->GetNoOfRegisteredPeds() != 0)
+ return true;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ vecAttractors.erase(pAttractorIt);
+ break;
+ }
+ }
+ delete pAttractor;
+ return true;
+}
+
+bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
+{
+ if (!pAttractor)
+ return false;
+ CPedAttractor* pFound = nil;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ pFound = *pAttractorIt;
+ break;
+ }
+ }
+ if (!pFound)
+ return false;
+ pFound->BroadcastArrival(pPed);
+ return true;
+}
+
+bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
+{
+ if (!pAttractor)
+ return false;
+ CPedAttractor* pFound = nil;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ pFound = *pAttractorIt;
+ break;
+ }
+ }
+ if (!pFound)
+ return false;
+ pFound->DeRegisterPed(pPed);
+ if (pFound->GetNoOfRegisteredPeds() != 0)
+ return true;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ vecAttractors.erase(pAttractorIt);
+ break;
+ }
+ }
+ delete pAttractor;
+ return true;
+}
+
+bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
+{
+ if (!pAttractor)
+ return false;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ return (*pAttractorIt)->IsInQueue(pPed);
+ }
+ }
+ return false;
+}
+
+bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
+{
+ if (!pAttractor)
+ return false;
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if (*pAttractorIt == pAttractor) {
+ return (*pAttractorIt)->IsAtHeadOfQueue(pPed);
+ }
+ }
+ return false;
+}
+
+bool CPedAttractorManager::IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*>& vecAttractors)
+{
+ for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
+ if ((*pAttractorIt)->IsRegisteredWithPed(pPed))
+ return true;
+ }
+ return false;
+}
+
+bool CPedAttractorManager::IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed)
+{
+ if (pEffect->pedattr.type == ATTRACTOR_SHELTER) {
+ CVector pos;
+ ComputeEffectPos(pEffect, matrix, pos);
+ return CWorld::GetIsLineOfSightClear(pPed->GetPosition(), pos, true, false, false, false, false, false);
+ }
+ CVector vecUseDir, vecEffectPos;
+ ComputeEffectUseDir(pEffect, matrix, vecUseDir);
+ ComputeEffectPos(pEffect, matrix, vecEffectPos);
+ float dp = -DotProduct(vecUseDir, vecEffectPos);
+ if (pEffect->pedattr.type == ATTRACTOR_ATM || pEffect->pedattr.type == ATTRACTOR_PIZZA || pEffect->pedattr.type == ATTRACTOR_ICECREAM) {
+ vecUseDir = -vecUseDir;
+ dp = -dp;
+ }
+ if (dp + DotProduct(vecEffectPos, pPed->GetPosition()) > 0.0f) {
+ CVector vecPedToAttractor = pPed->GetPosition() - vecEffectPos;
+ vecPedToAttractor.Normalise();
+ if (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f && CWorld::IsWanderPathClear(pPed->GetPosition(), vecEffectPos, 2.0f, 0))
+ return true;
+ }
+ return false;
+}
diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h
new file mode 100644
index 00000000..563efd3a
--- /dev/null
+++ b/src/peds/PedAttractor.h
@@ -0,0 +1,196 @@
+#pragma once
+#include "common.h"
+#include <vector>
+
+#include "2dEffect.h"
+#include "Ped.h"
+
+#define NUM_ATTRACTORS_FOR_ICECREAM_VAN 4
+
+class CPedAttractor;
+
+class CVehicleToEffect
+{
+ CVehicle* m_pVehicle;
+ C2dEffect m_effects[NUM_ATTRACTORS_FOR_ICECREAM_VAN];
+
+public:
+ CVehicleToEffect(CVehicle* pVehicle);
+ const C2dEffect* ChooseEffect(const CVector& pos) const;
+ CVehicleToEffect& From(const CVehicleToEffect& other);
+ CVehicleToEffect& operator=(const CVehicleToEffect& other) { return From(other); }
+ ~CVehicleToEffect() { m_pVehicle = nil; }
+ CVehicle* GetVehicle() const { return m_pVehicle; }
+ bool HasThisEffect(C2dEffect* pEffect) const;
+ const C2dEffect* GetEffect(int32 i) const { return &m_effects[i]; }
+};
+
+class CPedAttractorManager
+{
+ std::vector<CPedAttractor*> vAtmAttractors;
+ std::vector<CPedAttractor*> vSeatAttractors;
+ std::vector<CPedAttractor*> vStopAttractors;
+ std::vector<CPedAttractor*> vPizzaAttractors;
+ std::vector<CPedAttractor*> vShelterAttractors;
+ std::vector<CPedAttractor*> vIceCreamAttractors;
+ std::vector<CVehicleToEffect> vVehicleToEffect;
+
+public:
+ CPedAttractor* RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix);
+ CPedAttractor* RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector<CPedAttractor*>& vecAttractors);
+ bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor);
+ bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
+ const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos);
+ bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed);
+ void RemoveIceCreamVanEffects(C2dEffect* pEffect);
+ bool HasEmptySlot(const C2dEffect* pEffect);
+ const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors);
+ bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor);
+ bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
+ bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor);
+ bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
+ bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor);
+ bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
+ bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor);
+ bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
+ bool IsPedRegisteredWithEffect(CPed* pPed);
+ bool IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*>& vecAttractors);
+ CVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect);
+
+ static void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
+ static void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
+ static void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
+
+};
+
+CPedAttractorManager* GetPedAttractorManager();
+
+enum ePedAttractorType
+{
+ ATTRACTOR_ATM = 0,
+ ATTRACTOR_SEAT,
+ ATTRACTOR_STOP,
+ ATTRACTOR_PIZZA,
+ ATTRACTOR_SHELTER,
+ ATTRACTOR_ICECREAM
+};
+
+class CPedAttractor
+{
+protected:
+ C2dEffect* p2dEffect;
+ std::vector<CPed*> vApproachingQueue;
+ std::vector<CPed*> vWaitingQueue;
+ int32 m_nMaxPedsInAttractor;
+ float m_fQueueDistance;
+ float m_fTimeInWaitQueue;
+ float m_fTimeInApproachingQueue;
+ float m_fDistanceToUseAttractor;
+ float m_fAcceptableHeading;
+ float m_fMaxPositionDisplacement;
+ float m_fMaxHeadingDisplacement;
+ CVector vecEffectPos;
+ CVector vecQueueDir;
+ CVector vecUseDir;
+
+public:
+ virtual float GetHeadOfQueueWaitTime() { return 0.0f; }
+ virtual ~CPedAttractor() {};
+ virtual ePedAttractorType GetType() const = 0;
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const = 0;
+ virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; }
+ virtual void ComputeAttractPos(int32 id, CVector& pos) const;
+ virtual void ComputeAttractHeading(int32 id, float& pHeading) const;
+ virtual bool BroadcastDeparture(CPed* pPed);
+
+ bool IsRegisteredWithPed(CPed* pPed) const;
+ bool DeRegisterPed(CPed* pPed);
+ float ComputeDeltaHeading() const;
+ float ComputeDeltaPos() const;
+ void ComputeAttractTime(int32 id, bool, float& time) const;
+ int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); }
+ int32 ComputeFreeSlot() const { return vWaitingQueue.size(); }
+ bool IsInQueue(CPed*) const;
+ bool RegisterPed(CPed*);
+ bool BroadcastArrival(CPed*);
+
+ CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp);
+
+ C2dEffect* GetEffect() const { return p2dEffect; }
+ const CVector& GetEffectPos() const { return vecEffectPos; }
+ int32 GetMaxPedsInAttractor() const { return m_nMaxPedsInAttractor; }
+ float GetDistanceToCountSeekDone() const { return m_fDistanceToUseAttractor; }
+ float GetAcceptableHeading() const { return m_fAcceptableHeading; }
+};
+
+class CPedAtmAttractor : public CPedAttractor
+{
+public:
+ virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; };
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const override;
+ CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
+ {};
+};
+
+class CPedIceCreamAttractor : public CPedAttractor
+{
+public:
+ virtual ~CPedIceCreamAttractor() override { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); }
+ virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; }
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
+ CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
+ {};
+};
+
+class CPedPizzaAttractor : public CPedAttractor
+{
+public:
+ virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; }
+ virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; }
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const override;
+ CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
+ {};
+};
+
+class CPedSeatAttractor : public CPedAttractor
+{
+public:
+ virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; }
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
+ CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
+ {};
+};
+
+class CPedShelterAttractor : public CPedAttractor
+{
+ static std::vector<CVector> ms_displacements;
+public:
+ virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; }
+ virtual bool BroadcastDeparture(CPed*) override;
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
+ virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; }
+ virtual void ComputeAttractPos(int qid, CVector& pos) const override;
+ virtual void ComputeAttractHeading(int qid, float& heading) const override;
+
+ CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
+ {};
+
+
+ CVector GetDisplacement(int32 qid) const;
+};
+
+class CPedStopAttractor : public CPedAttractor
+{
+public:
+ virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; }
+ virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
+
+ CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
+ CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
+ {};
+}; \ No newline at end of file
diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp
index ebd41296..6543e9a3 100644
--- a/src/peds/PedIK.cpp
+++ b/src/peds/PedIK.cpp
@@ -7,11 +7,13 @@
#include "General.h"
#include "RwHelper.h"
-LimbMovementInfo CPedIK::ms_torsoInfo = { DEGTORAD(50.0f), DEGTORAD(-50.0f), DEGTORAD(15.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(7.0f) };
-LimbMovementInfo CPedIK::ms_headInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(10.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(5.0f) };
+//--MIAMI: file almost done (only some special weapon cases left)
+
+LimbMovementInfo CPedIK::ms_torsoInfo = { DEGTORAD(50.0f), DEGTORAD(-50.0f), DEGTORAD(8.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(5.0f) };
+LimbMovementInfo CPedIK::ms_headInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(15.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(8.0f) };
LimbMovementInfo CPedIK::ms_headRestoreInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(10.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(5.0f) };
-LimbMovementInfo CPedIK::ms_upperArmInfo = { DEGTORAD(20.0f), DEGTORAD(-100.0f), DEGTORAD(20.0f), DEGTORAD(70.0f), DEGTORAD(-70.0f), DEGTORAD(10.0f) };
-LimbMovementInfo CPedIK::ms_lowerArmInfo = { DEGTORAD(80.0f), DEGTORAD(0.0f), DEGTORAD(20.0f), DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(5.0f) };
+LimbMovementInfo CPedIK::ms_upperArmInfo = { DEGTORAD(5.0f), DEGTORAD(-120.0f), DEGTORAD(20.0f), DEGTORAD(70.0f), DEGTORAD(-70.0f), DEGTORAD(20.0f) };
+LimbMovementInfo CPedIK::ms_lowerArmInfo = { DEGTORAD(60.0f), DEGTORAD(0.0f), DEGTORAD(15.0f), DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(10.0f) };
const RwV3d XaxisIK = { 1.0f, 0.0f, 0.0f};
const RwV3d YaxisIK = { 0.0f, 1.0f, 0.0f};
@@ -31,7 +33,6 @@ CPedIK::CPedIK(CPed *ped)
m_lowerArmOrient.pitch = 0.0f;
}
-#ifdef PED_SKIN
inline RwMatrix*
GetBoneMatrix(CPed *ped, int32 bone)
{
@@ -45,134 +46,20 @@ GetComponentMatrix(CPed *ped, int32 node)
{
return GetBoneMatrix(ped, ped->m_pFrames[node]->nodeID);
}
-#endif
void
CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool changeRoll)
{
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- RtQuat *q = &node->hanimFrame->q;
-#ifndef FIX_BUGS
- // this is what the game does (also VC), but it does not look great
- RtQuatRotate(q, &XaxisIK, RADTODEG(limb->yaw), rwCOMBINEPRECONCAT);
- RtQuatRotate(q, &ZaxisIK, RADTODEG(limb->pitch), rwCOMBINEPRECONCAT); // pitch
-#else
- // copied the code from the non-skinned case
- // this seems to work ok
-
- // We can't get the parent matrix of an hanim frame but
- // this function is always called with PED_MID, so we know the parent frame.
- // Trouble is that PED_MID is "Smid" on PS2/PC but BONE_torso on mobile/xbox...
- // Assuming BONE_torso, the parent is BONE_mid, so let's use that:
- RwMatrix *mat = GetBoneMatrix(m_ped, BONE_mid);
-
- RwV3d vec1, vec2;
- vec1.x = mat->right.z;
- vec1.y = mat->up.z;
- vec1.z = mat->at.z;
- float c = Cos(m_ped->m_fRotationCur);
- float s = Sin(m_ped->m_fRotationCur);
- vec2.x = -(c*mat->right.x + s*mat->right.y);
- vec2.y = -(c*mat->up.x + s*mat->up.y);
- vec2.z = -(c*mat->at.x + s*mat->at.y);
-
- // Not sure what exactly to do here
- RtQuatRotate(q, &vec1, RADTODEG(limb->yaw), rwCOMBINEPRECONCAT);
- RtQuatRotate(q, &vec2, RADTODEG(limb->pitch), rwCOMBINEPRECONCAT);
-#endif
- m_ped->bDontAcceptIKLookAts = true;
- }else
-#endif
- {
- RwFrame *f = node->frame;
- RwMatrix *mat = GetWorldMatrix(RwFrameGetParent(f), RwMatrixCreate());
-
- RwV3d upVector = { mat->right.z, mat->up.z, mat->at.z };
- RwV3d rightVector;
- RwV3d pos = RwFrameGetMatrix(f)->pos;
-
- // rotation == 0 -> looking in y direction
- // left? vector
- float c = Cos(m_ped->m_fRotationCur);
- float s = Sin(m_ped->m_fRotationCur);
- rightVector.x = -(c*mat->right.x + s*mat->right.y);
- rightVector.y = -(c*mat->up.x + s*mat->up.y);
- rightVector.z = -(c*mat->at.x + s*mat->at.y);
-
- if(changeRoll){
- // Used when aiming only involves over the legs.(canAimWithArm)
- // Automatically changes roll(forward rotation) axis of the parts above upper legs while moving, based on position of upper legs.
- // Not noticeable in normal conditions...
-
- RwV3d forwardVector;
- CVector inversedForward = CrossProduct(CVector(0.0f, 0.0f, 1.0f), mat->up);
- inversedForward.Normalise();
- float dotProduct = DotProduct(mat->at, inversedForward);
- if(dotProduct > 1.0f) dotProduct = 1.0f;
- if(dotProduct < -1.0f) dotProduct = -1.0f;
- float alpha = Acos(dotProduct);
-
- if(mat->at.z < 0.0f)
- alpha = -alpha;
-
- forwardVector.x = s * mat->right.x - c * mat->right.y;
- forwardVector.y = s * mat->up.x - c * mat->up.y;
- forwardVector.z = s * mat->at.x - c * mat->at.y;
-
- float curYaw, curPitch;
- ExtractYawAndPitchWorld(mat, &curYaw, &curPitch);
- RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->pitch), rwCOMBINEPOSTCONCAT);
- RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->yaw - (curYaw - m_ped->m_fRotationCur)), rwCOMBINEPOSTCONCAT);
- RwMatrixRotate(RwFrameGetMatrix(f), &forwardVector, RADTODEG(alpha), rwCOMBINEPOSTCONCAT);
- }else{
- // pitch
- RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->pitch), rwCOMBINEPOSTCONCAT);
- // yaw
- RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->yaw), rwCOMBINEPOSTCONCAT);
- }
- RwFrameGetMatrix(f)->pos = pos;
- RwMatrixDestroy(mat);
- }
+ RtQuat *q = &node->hanimFrame->q;
+ RtQuatRotate(q, &XaxisIK, RADTODEG(limb->yaw), rwCOMBINEREPLACE);
+ RtQuatRotate(q, &ZaxisIK, RADTODEG(limb->pitch), rwCOMBINEPRECONCAT);
+ m_ped->bDontAcceptIKLookAts = true;
}
void
CPedIK::GetComponentPosition(RwV3d *pos, uint32 node)
{
- RwFrame *f;
- RwMatrix *mat;
-
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- pos->x = 0.0f;
- pos->y = 0.0f;
- pos->z = 0.0f;
- mat = GetComponentMatrix(m_ped, node);
- // could just copy the position out of the matrix...
- RwV3dTransformPoints(pos, pos, 1, mat);
- }else
-#endif
- {
- f = m_ped->m_pFrames[node]->frame;
- mat = RwFrameGetMatrix(f);
- *pos = mat->pos;
-
- for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f))
- RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(f));
- }
-}
-
-RwMatrix*
-CPedIK::GetWorldMatrix(RwFrame *source, RwMatrix *destination)
-{
- RwFrame *i;
-
- *destination = *RwFrameGetMatrix(source);
-
- for (i = RwFrameGetParent(source); i; i = RwFrameGetParent(i))
- RwMatrixTransform(destination, RwFrameGetMatrix(i), rwCOMBINEPOSTCONCAT);
-
- return destination;
+ *pos = GetComponentMatrix(m_ped, node)->pos;
}
LimbMoveStatus
@@ -182,15 +69,15 @@ CPedIK::MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, Limb
// yaw
- if (limb.yaw > targetYaw) {
- limb.yaw -= moveInfo.yawD;
- } else if (limb.yaw < targetYaw) {
- limb.yaw += moveInfo.yawD;
- }
-
- if (Abs(limb.yaw - targetYaw) < moveInfo.yawD) {
+ if(Abs(limb.yaw-targetYaw) < moveInfo.yawD){
limb.yaw = targetYaw;
result = ANGLES_SET_EXACTLY;
+ }else{
+ if (limb.yaw > targetYaw) {
+ limb.yaw -= moveInfo.yawD;
+ } else if (limb.yaw < targetYaw) {
+ limb.yaw += moveInfo.yawD;
+ }
}
if (limb.yaw > moveInfo.maxYaw || limb.yaw < moveInfo.minYaw) {
@@ -200,16 +87,16 @@ CPedIK::MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, Limb
// pitch
- if (limb.pitch > targetPitch) {
- limb.pitch -= moveInfo.pitchD;
- } else if (limb.pitch < targetPitch) {
- limb.pitch += moveInfo.pitchD;
- }
-
- if (Abs(limb.pitch - targetPitch) < moveInfo.pitchD)
+ if (Abs(limb.pitch - targetPitch) < moveInfo.pitchD){
limb.pitch = targetPitch;
- else
+ }else{
+ if (limb.pitch > targetPitch) {
+ limb.pitch -= moveInfo.pitchD;
+ } else if (limb.pitch < targetPitch) {
+ limb.pitch += moveInfo.pitchD;
+ }
result = ONE_ANGLE_COULDNT_BE_SET_EXACTLY;
+ }
if (limb.pitch > moveInfo.maxPitch || limb.pitch < moveInfo.minPitch) {
limb.pitch = clamp(limb.pitch, moveInfo.minPitch, moveInfo.maxPitch);
@@ -226,107 +113,60 @@ CPedIK::RestoreGunPosn(void)
return limbStatus == ANGLES_SET_EXACTLY;
}
-#ifdef PED_SKIN
-void
-CPedIK::RotateHead(void)
-{
- RtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q;
- RtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.yaw), rwCOMBINEREPLACE);
- RtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.pitch), rwCOMBINEPOSTCONCAT);
- m_ped->bDontAcceptIKLookAts = true;
-}
-#endif
-
bool
CPedIK::LookInDirection(float targetYaw, float targetPitch)
{
bool success = true;
float yaw, pitch;
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) {
- m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION;
- ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &m_headOrient.yaw, &m_headOrient.pitch);
- }
-
- // parent of head is torso
- RwMatrix worldMat = *GetBoneMatrix(m_ped, BONE_torso);
- ExtractYawAndPitchWorld(&worldMat, &yaw, &pitch);
-
- LimbMoveStatus headStatus = MoveLimb(m_headOrient, CGeneral::LimitRadianAngle(targetYaw - yaw),
- CGeneral::LimitRadianAngle(DEGTORAD(10.0f)), ms_headInfo);
- if (headStatus == ANGLES_SET_TO_MAX)
- success = false;
-
- if (headStatus != ANGLES_SET_EXACTLY){
- if (!(m_flags & LOOKAROUND_HEAD_ONLY)){
- if (MoveLimb(m_torsoOrient, CGeneral::LimitRadianAngle(targetYaw), targetPitch, ms_torsoInfo))
- success = true;
- }else{
- RotateHead();
- return success;
- }
- }
-
- if (!(m_flags & LOOKAROUND_HEAD_ONLY))
- RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
- RotateHead();
- }else
-#endif
- {
- RwFrame *frame = m_ped->m_pFrames[PED_HEAD]->frame;
- RwMatrix *frameMat = RwFrameGetMatrix(frame);
-
- if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) {
- m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION;
- ExtractYawAndPitchLocal(frameMat, &m_headOrient.yaw, &m_headOrient.pitch);
- }
-
- RwMatrix *worldMat = RwMatrixCreate();
- worldMat = GetWorldMatrix(RwFrameGetParent(frame), worldMat);
-
- ExtractYawAndPitchWorld(worldMat, &yaw, &pitch);
- RwMatrixDestroy(worldMat);
-
- yaw += m_torsoOrient.yaw;
- float neededYawTurn = CGeneral::LimitRadianAngle(targetYaw - yaw);
- pitch *= Cos(neededYawTurn);
+ if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) {
+ m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION;
+ RwMatrix *m = GetComponentMatrix(m_ped, PED_NECK);
+ m_headOrient.yaw = Atan2(-m->at.y, -m->at.x);
+ m_headOrient.yaw -= m_ped->m_fRotationCur;
+ m_headOrient.yaw = CGeneral::LimitRadianAngle(m_headOrient.yaw);
+ float up = clamp(m->up.z, -1.0f, 1.0f);
+ m_headOrient.pitch = Atan2(-up, Sqrt(1.0f - SQR(-up)));
+ }
- float neededPitchTurn = CGeneral::LimitRadianAngle(targetPitch - pitch);
- LimbMoveStatus headStatus = MoveLimb(m_headOrient, neededYawTurn, neededPitchTurn, ms_headInfo);
- if (headStatus == ANGLES_SET_TO_MAX)
- success = false;
+ // parent of head is neck
+ RwMatrix *m = GetComponentMatrix(m_ped, PED_NECK);
+ yaw = CGeneral::LimitRadianAngle(Atan2(-m->at.y, -m->at.x));
+ float up = clamp(m->up.z, -1.0f, 1.0f);
+ pitch = Atan2(-up, Sqrt(1.0f - SQR(-up)));
+ float headYaw = CGeneral::LimitRadianAngle(targetYaw - (yaw + m_torsoOrient.yaw));
+ float headPitch = CGeneral::LimitRadianAngle(targetPitch - pitch) * Cos(Min(Abs(headYaw), HALFPI));
- if (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKAROUND_HEAD_ONLY)) {
- float remainingTurn = CGeneral::LimitRadianAngle(targetYaw - m_ped->m_fRotationCur);
- if (MoveLimb(m_torsoOrient, remainingTurn, targetPitch, ms_torsoInfo))
- success = true;
- }
- CMatrix nextFrame = CMatrix(frameMat);
- CVector framePos = nextFrame.GetPosition();
+ LimbMoveStatus headStatus = MoveLimb(m_headOrient, headYaw, headPitch, ms_headInfo);
+ if (headStatus == ANGLES_SET_TO_MAX)
+ success = false;
- nextFrame.SetRotateZ(m_headOrient.pitch);
- nextFrame.RotateX(m_headOrient.yaw);
- nextFrame.GetPosition() += framePos;
- nextFrame.UpdateRW();
+ if (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKAROUND_HEAD_ONLY))
+ if (MoveLimb(m_torsoOrient, CGeneral::LimitRadianAngle(targetYaw-m_ped->m_fRotationCur), targetPitch, ms_torsoInfo))
+ success = true;
- if (!(m_flags & LOOKAROUND_HEAD_ONLY))
- RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
+ // This was RotateHead
+ RtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q;
+ RtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.pitch), rwCOMBINEREPLACE);
+ RtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.yaw), rwCOMBINEPRECONCAT);
+ m_ped->bDontAcceptIKLookAts = true;
- }
+ if (!(m_flags & LOOKAROUND_HEAD_ONLY))
+ RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
return success;
}
bool
CPedIK::LookAtPosition(CVector const &pos)
{
+ RwV3d *pedpos = &GetComponentMatrix(m_ped, PED_MID)->pos;
float yawToFace = CGeneral::GetRadianAngleBetweenPoints(
pos.x, pos.y,
- m_ped->GetPosition().x, m_ped->GetPosition().y);
+ pedpos->x, pedpos->y);
float pitchToFace = CGeneral::GetRadianAngleBetweenPoints(
+ // BUG? not using pedpos here
pos.z, (m_ped->GetPosition() - pos).Magnitude2D(),
- m_ped->GetPosition().z, 0.0f);
+ pedpos->z, 0.0f);
return LookInDirection(yawToFace, pitchToFace);
}
@@ -336,12 +176,12 @@ CPedIK::PointGunInDirection(float targetYaw, float targetPitch)
{
bool result = true;
bool armPointedToGun = false;
- float angle = CGeneral::LimitRadianAngle(targetYaw - m_ped->m_fRotationCur);
- m_flags &= (~GUN_POINTED_SUCCESSFULLY);
+ targetYaw = CGeneral::LimitRadianAngle(targetYaw - m_ped->GetForward().Heading());
+ m_flags &= ~GUN_POINTED_SUCCESSFULLY;
m_flags |= LOOKAROUND_HEAD_ONLY;
if (m_flags & AIMS_WITH_ARM) {
- armPointedToGun = PointGunInDirectionUsingArm(angle, targetPitch);
- angle = CGeneral::LimitRadianAngle(angle - m_upperArmOrient.yaw);
+ armPointedToGun = PointGunInDirectionUsingArm(targetYaw, targetPitch);
+ targetYaw = CGeneral::LimitRadianAngle(targetYaw - (m_upperArmOrient.yaw + m_lowerArmOrient.yaw));
}
if (armPointedToGun) {
if (m_flags & AIMS_WITH_ARM && m_torsoOrient.yaw * m_upperArmOrient.yaw < 0.0f)
@@ -350,31 +190,35 @@ CPedIK::PointGunInDirection(float targetYaw, float targetPitch)
// Unused code
RwMatrix *matrix;
float yaw, pitch;
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- matrix = RwMatrixCreate();
- *matrix = *GetComponentMatrix(m_ped, PED_UPPERARMR);
- ExtractYawAndPitchWorld(matrix, &yaw, &pitch);
- RwMatrixDestroy(matrix);
- }else
-#endif
- {
- matrix = GetWorldMatrix(RwFrameGetParent(m_ped->m_pFrames[PED_UPPERARMR]->frame), RwMatrixCreate());
- ExtractYawAndPitchWorld(matrix, &yaw, &pitch);
- RwMatrixDestroy(matrix);
- }
- //
+ matrix = RwMatrixCreate();
+ *matrix = *GetComponentMatrix(m_ped, PED_CLAVICLER);
+ ExtractYawAndPitchWorld(matrix, &yaw, &pitch);
+ RwMatrixDestroy(matrix);
- LimbMoveStatus status = MoveLimb(m_torsoOrient, angle, targetPitch, ms_torsoInfo);
+ if(m_flags & AIMS_WITH_ARM){
+ if(targetPitch > 0.0f)
+ targetPitch = Max(targetPitch - Abs(targetYaw), 0.0f);
+ else
+ targetPitch = Min(targetPitch + Abs(targetYaw), 0.0f);
+ }
+ LimbMoveStatus status = MoveLimb(m_torsoOrient, targetYaw, targetPitch, ms_torsoInfo);
if (status == ANGLES_SET_TO_MAX)
result = false;
else if (status == ANGLES_SET_EXACTLY)
m_flags |= GUN_POINTED_SUCCESSFULLY;
}
- if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && m_flags & AIMS_WITH_ARM)
- RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, true);
- else
- RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
+ RwMatrix *m = GetBoneMatrix(m_ped, BONE_spine); // BUG: game uses index 2 directly, which happens to be identical to BONE_spine
+ RwV3d axis = { 0.0f, 0.0f, 0.0f };
+ float axisangle = -CGeneral::LimitRadianAngle(Atan2(-m->at.y, -m->at.x) - m_ped->m_fRotationCur);
+ axis.y = -Sin(axisangle);
+ axis.z = Cos(axisangle);
+
+ // this was RotateTorso
+ RtQuat *q = &m_ped->m_pFrames[PED_MID]->hanimFrame->q;
+ RtQuatRotate(q, &axis, RADTODEG(m_torsoOrient.pitch), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(q, &XaxisIK, RADTODEG(m_torsoOrient.yaw), rwCOMBINEPOSTCONCAT);
+ m_ped->bDontAcceptIKLookAts = true;
+
return result;
}
@@ -382,103 +226,79 @@ bool
CPedIK::PointGunInDirectionUsingArm(float targetYaw, float targetPitch)
{
bool result = false;
-
- RwV3d upVector; // only for non-skinned
RwMatrix *matrix;
float yaw, pitch;
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- matrix = RwMatrixCreate();
- *matrix = *GetComponentMatrix(m_ped, PED_UPPERARMR);
- ExtractYawAndPitchWorld(matrix, &yaw, &pitch);
- RwMatrixDestroy(matrix);
- }else
-#endif
- {
- RwFrame *frame = m_ped->m_pFrames[PED_UPPERARMR]->frame;
- matrix = GetWorldMatrix(RwFrameGetParent(frame), RwMatrixCreate());
- // with PED_SKIN this is actually done below (with a memory leak)
- upVector.x = matrix->right.z;
- upVector.y = matrix->up.z;
- upVector.z = matrix->at.z;
-
- ExtractYawAndPitchWorld(matrix, &yaw, &pitch);
- RwMatrixDestroy(matrix);
- }
+ float uaRoll = 45.0f;
+ float handRoll = 30.0f;
- RwV3d rightVector = { 0.0f, 0.0f, 1.0f };
- RwV3d forwardVector = { 1.0f, 0.0f, 0.0f };
+ matrix = GetComponentMatrix(m_ped, PED_CLAVICLER);
+ yaw = CGeneral::LimitRadianAngle(Atan2(matrix->right.y, matrix->right.x) - m_ped->m_fRotationCur);
+ pitch = Atan2(matrix->up.z, Sqrt(1.0f - SQR(matrix->up.z)));
float uaYaw, uaPitch;
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- uaYaw = targetYaw;
- uaPitch = targetPitch + DEGTORAD(10.0f);
- }else
-#endif
- {
- uaYaw = targetYaw - m_torsoOrient.yaw - DEGTORAD(15.0f);
- uaPitch = CGeneral::LimitRadianAngle(targetPitch - pitch);
- }
+ uaYaw = CGeneral::LimitRadianAngle(targetYaw - yaw - DEGTORAD(15.0f));
+ uaPitch = CGeneral::LimitRadianAngle(targetPitch - pitch + DEGTORAD(10.0f));
LimbMoveStatus uaStatus = MoveLimb(m_upperArmOrient, uaYaw, uaPitch, ms_upperArmInfo);
if (uaStatus == ANGLES_SET_EXACTLY) {
m_flags |= GUN_POINTED_SUCCESSFULLY;
result = true;
}
-#ifdef PED_SKIN
- // this code is completely missing on xbox & android, but we can keep it with the check
- // TODO? implement it for skinned geometry?
- if(!IsClumpSkinned(m_ped->GetClump()))
-#endif
if (uaStatus == ANGLES_SET_TO_MAX) {
float laYaw = uaYaw - m_upperArmOrient.yaw;
LimbMoveStatus laStatus;
- if (laYaw > 0.0f)
- laStatus = MoveLimb(m_lowerArmOrient, laYaw, -DEGTORAD(45.0f), ms_lowerArmInfo);
- else
+ if (laYaw > 0.0f){
+ float rollReduce = laYaw/DEGTORAD(30.0f);
+ uaRoll *= 1.0f - Min(rollReduce, 1.0f);
+ handRoll *= 1.0f - Min(rollReduce, 1.0f);
+
+ laYaw *= 1.9f;
+ laStatus = MoveLimb(m_lowerArmOrient, laYaw, 0.0f, ms_lowerArmInfo);
+
+ // some unused statics here
+ float uaPitchAmount = 1.0f - (m_lowerArmOrient.yaw + m_upperArmOrient.yaw) * 0.34f;
+ float f1 = ms_upperArmInfo.maxPitch * Max(uaPitchAmount, 0.0f);
+ float f2 = 0.2f*m_lowerArmOrient.yaw + m_upperArmOrient.pitch;
+ m_upperArmOrient.pitch = Min(f1, f2);
+ }else
laStatus = MoveLimb(m_lowerArmOrient, laYaw, 0.0f, ms_lowerArmInfo);
if (laStatus == ANGLES_SET_EXACTLY) {
m_flags |= GUN_POINTED_SUCCESSFULLY;
result = true;
}
- RwFrame *child = GetFirstChild(m_ped->m_pFrames[PED_UPPERARMR]->frame);
- RwV3d pos = RwFrameGetMatrix(child)->pos;
- RwMatrixRotate(RwFrameGetMatrix(child), &forwardVector, RADTODEG(m_lowerArmOrient.pitch), rwCOMBINEPOSTCONCAT);
- RwMatrixRotate(RwFrameGetMatrix(child), &rightVector, RADTODEG(-m_lowerArmOrient.yaw), rwCOMBINEPOSTCONCAT);
- RwFrameGetMatrix(child)->pos = pos;
- }
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- RtQuat *q = &m_ped->m_pFrames[PED_UPPERARMR]->hanimFrame->q;
- RtQuatRotate(q, &XaxisIK, RADTODEG(m_upperArmOrient.yaw), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(q, &ZaxisIK, RADTODEG(m_upperArmOrient.pitch), rwCOMBINEPOSTCONCAT);
+ // game does this stupidly by going through the clump extension...
+ RtQuat *q = &m_ped->m_pFrames[PED_FOREARMR]->hanimFrame->q;
+ RtQuatRotate(q, &ZaxisIK, -RADTODEG(m_lowerArmOrient.yaw), rwCOMBINEREPLACE);
+ RtQuatRotate(q, &XaxisIK, -RADTODEG(m_lowerArmOrient.pitch), rwCOMBINEPOSTCONCAT);
m_ped->bDontAcceptIKLookAts = true;
- }else
-#endif
- {
- RwFrame *frame = m_ped->m_pFrames[PED_UPPERARMR]->frame;
- // with PED_SKIN we're also getting upVector here
- RwV3d pos = RwFrameGetMatrix(frame)->pos;
- RwMatrixRotate(RwFrameGetMatrix(frame), &rightVector, RADTODEG(m_upperArmOrient.pitch), rwCOMBINEPOSTCONCAT);
- RwMatrixRotate(RwFrameGetMatrix(frame), &upVector, RADTODEG(m_upperArmOrient.yaw), rwCOMBINEPOSTCONCAT);
- RwFrameGetMatrix(frame)->pos = pos;
}
+
+ RtQuat *q = &m_ped->m_pFrames[PED_UPPERARMR]->hanimFrame->q;
+ RtQuatRotate(q, &XaxisIK, uaRoll, rwCOMBINEREPLACE);
+ RtQuatRotate(q, &YaxisIK, -RADTODEG(m_upperArmOrient.pitch), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(q, &ZaxisIK, -RADTODEG(m_upperArmOrient.yaw+HALFPI), rwCOMBINEPOSTCONCAT);
+ m_ped->bDontAcceptIKLookAts = true;
+
+ q = &m_ped->m_pFrames[PED_HANDR]->hanimFrame->q;
+ RtQuatRotate(q, &XaxisIK, handRoll, rwCOMBINEPRECONCAT);
+
return result;
}
bool
CPedIK::PointGunAtPosition(CVector const& position)
{
+ // TODO(MIAMI): special cases for some weapons
+
+ RwV3d armPos;
+ GetComponentPosition(&armPos, PED_UPPERARMR);
return PointGunInDirection(
CGeneral::GetRadianAngleBetweenPoints(position.x, position.y, m_ped->GetPosition().x, m_ped->GetPosition().y),
- CGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y),
- m_ped->GetPosition().z,
- 0.0f));
+ CGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y), armPos.z, 0.0f));
}
bool
@@ -487,40 +307,24 @@ CPedIK::RestoreLookAt(void)
bool result = false;
float yaw, pitch;
-#ifdef PED_SKIN
- if(IsClumpSkinned(m_ped->GetClump())){
- if (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) {
- m_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION);
- } else {
- ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &yaw, &pitch);
- if (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY)
- result = true;
- }
- RotateHead();
- }else
-#endif
- {
- RwMatrix *mat = RwFrameGetMatrix(m_ped->m_pFrames[PED_HEAD]->frame);
- if (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) {
- m_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION);
- } else {
- ExtractYawAndPitchLocal(mat, &yaw, &pitch);
- if (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY)
- result = true;
- }
-
- CMatrix matrix(mat);
- CVector pos = matrix.GetPosition();
- matrix.SetRotateZ(m_headOrient.pitch);
- matrix.RotateX(m_headOrient.yaw);
- matrix.Translate(pos);
- matrix.UpdateRW();
+ if (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) {
+ m_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION);
+ } else {
+ ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &yaw, &pitch);
+ if (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY)
+ result = true;
}
- if (!(m_flags & LOOKAROUND_HEAD_ONLY)){
+
+ // This was RotateHead
+ RtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q;
+ RtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.yaw), rwCOMBINEREPLACE);
+ RtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.pitch), rwCOMBINEPRECONCAT);
+ m_ped->bDontAcceptIKLookAts = true;
+
+ if (!(m_flags & LOOKAROUND_HEAD_ONLY))
MoveLimb(m_torsoOrient, 0.0f, 0.0f, ms_torsoInfo);
- if (!(m_flags & LOOKAROUND_HEAD_ONLY))
- RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
- }
+ if (!(m_flags & LOOKAROUND_HEAD_ONLY))
+ RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
return result;
}
@@ -548,7 +352,6 @@ CPedIK::ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch)
if (mat->up.x > 0.0f) *pitch = -*pitch;
}
-#ifdef PED_SKIN
void
CPedIK::ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch)
{
@@ -557,4 +360,3 @@ CPedIK::ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, flo
ExtractYawAndPitchLocal(mat, yaw, pitch);
RwMatrixDestroy(mat);
}
-#endif
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index e91d7c06..b5f895cd 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -52,14 +52,12 @@ public:
bool PointGunInDirectionUsingArm(float targetYaw, float targetPitch);
bool PointGunAtPosition(CVector const& position);
void GetComponentPosition(RwV3d *pos, uint32 node);
- static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination);
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch);
void ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch);
void ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch);
LimbMoveStatus MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, LimbMovementInfo &moveInfo);
bool RestoreGunPosn(void);
- void RotateHead(void);
bool LookInDirection(float targetYaw, float targetPitch);
bool LookAtPosition(CVector const& pos);
bool RestoreLookAt(void);
diff --git a/src/peds/PedPlacement.cpp b/src/peds/PedPlacement.cpp
index 2d4a92fa..6011ce44 100644
--- a/src/peds/PedPlacement.cpp
+++ b/src/peds/PedPlacement.cpp
@@ -43,9 +43,13 @@ CPedPlacement::IsPositionClearOfCars(Const CVector *pos)
}
bool
-CPedPlacement::IsPositionClearForPed(CVector* pos)
+CPedPlacement::IsPositionClearForPed(const CVector& pos, float radius, int total, CEntity** entities)
{
int16 count;
- CWorld::FindObjectsKindaColliding(*pos, 0.75f, true, &count, 2, nil, false, true, true, false, false);
+ if (radius == -1.0f)
+ radius = 0.75f;
+ if (total == -1)
+ total = 2;
+ CWorld::FindObjectsKindaColliding(pos, radius, true, &count, total, entities, false, true, true, false, false);
return count == 0;
}
diff --git a/src/peds/PedPlacement.h b/src/peds/PedPlacement.h
index b51e2aad..5b8354d4 100644
--- a/src/peds/PedPlacement.h
+++ b/src/peds/PedPlacement.h
@@ -4,5 +4,5 @@ class CPedPlacement {
public:
static void FindZCoorForPed(CVector* pos);
static CEntity* IsPositionClearOfCars(Const CVector*);
- static bool IsPositionClearForPed(CVector*);
+ static bool IsPositionClearForPed(const CVector& pos, float radius = -1.0f, int total = -1, CEntity** entities = nil);
}; \ No newline at end of file
diff --git a/src/peds/PedStats.h b/src/peds/PedStats.h
index df97bdb8..7fc8cdbf 100644
--- a/src/peds/PedStats.h
+++ b/src/peds/PedStats.h
@@ -37,6 +37,11 @@ enum ePedStats
PEDSTAT_SPORTSFAN,
PEDSTAT_SHOPPER,
PEDSTAT_OLDSHOPPER,
+ PEDSTAT_BEACH_GUY,
+ PEDSTAT_BEACH_GIRL,
+ PEDSTAT_SKATER,
+ PEDSTAT_STD_MISSION,
+ PEDSTAT_COWARD,
NUM_PEDSTATS
};
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 3c6fad57..9f972882 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -16,6 +16,7 @@
#include "Pools.h"
#include "Darkel.h"
#include "CarCtrl.h"
+#include "MBlur.h"
#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f
@@ -31,6 +32,7 @@ CPlayerPed::~CPlayerPed()
delete m_pWanted;
}
+// --MIAMI: Done except commented out things
CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
{
m_fMoveSpeed = 0.0f;
@@ -44,31 +46,57 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
m_nSpeedTimer = 0;
m_bSpeedTimerFlag = false;
+
+ // This should be something inlined
+ // TODO(Miami)
+
+ // if (pPointGunAt)
+ // m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);
m_pPointGunAt = nil;
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
+ // TODO(Miami)
+ // This should be something inlined
+
m_nPedState = PED_IDLE;
m_fMaxStamina = 150.0f;
m_fCurrentStamina = m_fMaxStamina;
m_fStaminaProgress = 0.0f;
m_nEvadeAmount = 0;
- field_1367 = 0;
+ m_pEvadingFrom = nil;
m_nHitAnimDelayTimer = 0;
m_fAttackButtonCounter = 0.0f;
m_bHaveTargetSelected = false;
m_bHasLockOnTarget = false;
+ m_bDrunkVisualsWearOff = true;
m_bCanBeDamaged = true;
m_fWalkAngle = 0.0f;
m_fFPSMoveHeading = 0.0f;
+ m_pMinigunTopAtomic = nil;
+ m_fGunSpinSpeed = 0.0;
+ m_fGunSpinAngle = 0.0;
m_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1;
- field_1413 = 0;
+ unused1 = false;
for (int i = 0; i < 6; i++) {
m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f);
m_pPedAtSafePos[i] = nil;
+ m_pCheckPlayers[i] = nil;
}
+ m_nCheckPlayersIndex = 0;
+ m_nPadUpPressedInMilliseconds = 0;
+ m_nPadDownPressedInMilliseconds = 0;
+ // TODO(Miami): Idle anim block index
}
void CPlayerPed::ClearWeaponTarget()
{
if (m_nPedType == PEDTYPE_PLAYER1) {
+
+ // TODO(Miami)
+ // if (m_pPointGunAt)
+ // m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);
+
m_pPointGunAt = nil;
TheCamera.ClearPlayerWeaponMode();
CWeaponEffects::ClearCrossHair();
@@ -181,21 +209,24 @@ CPlayerPed::UseSprintEnergy(void)
}
}
+// --MIAMI: Use that on everywhere except ProcessPlayerWeapon
void
-CPlayerPed::MakeChangesForNewWeapon(int8 weapon)
+CPlayerPed::MakeChangesForNewWeapon(eWeaponType weapon)
{
if (m_nPedState == PED_SNIPER_MODE) {
RestorePreviousState();
TheCamera.ClearPlayerWeaponMode();
}
SetCurrentWeapon(weapon);
+ m_nSelectedWepSlot = m_currentWeapon;
GetWeapon()->m_nAmmoInClip = Min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition);
if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAim))
ClearWeaponTarget();
- CAnimBlendAssociation *weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)->m_AnimToPlay);
+ // WEAPONTYPE_SNIPERRIFLE? Wut?
+ CAnimBlendAssociation* weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)));
if (weaponAnim) {
weaponAnim->SetRun();
weaponAnim->flags |= ASSOC_FADEOUTWHENDONE;
@@ -203,6 +234,14 @@ CPlayerPed::MakeChangesForNewWeapon(int8 weapon)
TheCamera.ClearPlayerWeaponMode();
}
+// --MIAMI: Done, but this should be only called from ProcessPlayerWeapon
+void
+CPlayerPed::MakeChangesForNewWeapon(int32 slot)
+{
+ if(slot != -1)
+ MakeChangesForNewWeapon(m_weapons[slot].m_eWeaponType);
+}
+
void
CPlayerPed::ReApplyMoveAnims(void)
{
@@ -222,14 +261,19 @@ CPlayerPed::ReApplyMoveAnims(void)
}
}
+// --MIAMI: Done
void
CPlayerPed::SetInitialState(void)
{
+ m_nDrunkenness = 0;
+ m_nFadeDrunkenness = 0;
+ CMBlur::ClearDrunkBlur();
+ m_nDrunkCountdown = 0;
m_bAdrenalineActive = false;
m_nAdrenalineTime = 0;
- CTimer::SetTimeStep(1.0f);
+ CTimer::SetTimeScale(1.0f);
m_pSeekTarget = nil;
- m_vecSeekPos = { 0.0f, 0.0f, 0.0f };
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
m_fleeFromPosX = 0.0f;
m_fleeFromPosY = 0.0f;
m_fleeFrom = nil;
@@ -241,9 +285,14 @@ CPlayerPed::SetInitialState(void)
ClearLookFlag();
bIsPointingGunAt = false;
bRenderPedInCar = true;
+
if (m_pFire)
m_pFire->Extinguish();
+
RpAnimBlendClumpRemoveAllAssociations(GetClump());
+ if (m_nPedState == PED_FOLLOW_PATH)
+ ClearFollowPath();
+
m_nPedState = PED_IDLE;
SetMoveState(PEDMOVE_STILL);
m_nLastPedState = PED_NONE;
@@ -257,6 +306,11 @@ CPlayerPed::SetInitialState(void)
m_bCanBeDamaged = true;
m_pedStats->m_temper = 50;
m_fWalkAngle = 0.0f;
+ if (m_attachedTo && !bUsesCollision)
+ bUsesCollision = true;
+
+ m_attachedTo = nil;
+ m_attachWepAmmo = 0;
}
void
@@ -397,7 +451,7 @@ CPlayerPed::SetRealMoveAnim(void)
} else if (curSprintAssoc->blendDelta >= 0.0f || curSprintAssoc->blendAmount >= 0.8f) {
if (m_fMoveSpeed < 0.4f) {
AnimationId runStopAnim;
- if (curSprintAssoc->currentTime / curSprintAssoc->hierarchy->totalLength < 0.5) // double
+ if (curSprintAssoc->GetProgress() < 0.5) // double
runStopAnim = ANIM_RUN_STOP;
else
runStopAnim = ANIM_RUN_STOP_R;
@@ -497,8 +551,9 @@ CPlayerPed::DoWeaponSmoothSpray(void)
{
if (m_nPedState == PED_ATTACK && !m_pPointGunAt) {
eWeaponType weapon = GetWeapon()->m_eWeaponType;
- if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI || weapon == WEAPONTYPE_SHOTGUN ||
- weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON)
+ if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI ||
+ weapon == WEAPONTYPE_TEC9 || weapon == WEAPONTYPE_SILENCED_INGRAM || weapon == WEAPONTYPE_MP5 ||
+ weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON)
return true;
}
return false;
@@ -583,59 +638,82 @@ CPlayerPed::PlayerControlSniper(CPad *padUsed)
firePos = GetMatrix() * firePos;
GetWeapon()->Fire(this, &firePos);
}
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, nil);
}
+// --MIAMI: Made compatible with slots, but still TODO
// I think R* also used goto in here.
void
CPlayerPed::ProcessWeaponSwitch(CPad *padUsed)
{
- if (CDarkel::FrenzyOnGoing())
+ if (CDarkel::FrenzyOnGoing() || m_attachedTo)
goto switchDetectDone;
- if (padUsed->CycleWeaponRightJustDown() && !m_pPointGunAt) {
+ if (!m_pPointGunAt && /* !byte_A10B57 && */ GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR) {
+ if (padUsed->CycleWeaponRightJustDown()) {
- if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
+ if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
- for (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; ++m_nSelectedWepSlot) {
- if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
- goto switchDetectDone;
+ for (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < TOTAL_WEAPON_SLOTS; ++m_nSelectedWepSlot) {
+ if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
+ goto spentAmmoCheck;
+ }
}
+ m_nSelectedWepSlot = 0;
}
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
- }
- } else if (padUsed->CycleWeaponLeftJustDown() && !m_pPointGunAt) {
- if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
+ } else if (padUsed->CycleWeaponLeftJustDown()) {
+ if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
- for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) {
- if (m_nSelectedWepSlot < WEAPONTYPE_UNARMED)
- m_nSelectedWepSlot = WEAPONTYPE_DETONATOR;
+ for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) {
+ if (m_nSelectedWepSlot < 0)
+ m_nSelectedWepSlot = TOTAL_WEAPON_SLOTS - 1;
- if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
- goto switchDetectDone;
+ if (m_nSelectedWepSlot == 0)
+ break;
+
+ if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
+ break;
+ }
}
}
}
- } else if (CWeaponInfo::GetWeaponInfo((eWeaponType)m_currentWeapon)->m_eWeaponFire != WEAPON_FIRE_MELEE) {
- if (GetWeapon(m_currentWeapon).m_nAmmoTotal <= 0) {
+ }
+
+spentAmmoCheck:
+ if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_eWeaponFire != WEAPON_FIRE_MELEE
+ /*&& (!padUsed->GetWeapon() || GetWeapon()->m_eWeaponType != WEAPONTYPE_MINIGUN) */) {
+ if (GetWeapon()->m_nAmmoTotal <= 0) {
if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
- for (m_nSelectedWepSlot = m_currentWeapon - 1; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) {
- if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && HasWeapon(WEAPONTYPE_BASEBALLBAT)
- || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE) {
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR
+ || GetWeapon(2).m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE)
+ m_nSelectedWepSlot = m_currentWeapon - 1;
+ else
+ m_nSelectedWepSlot = 2;
+
+ for (; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) {
+
+ // BUG: m_nSelectedWepSlot and GetWeapon(..) takes slot in VC but they compared them against weapon types in whole condition! jeez
+#ifdef FIX_BUGS
+ if (m_nSelectedWepSlot == 1 || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != 2) {
+#else
+ if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(WEAPONTYPE_BASEBALLBAT).m_eWeaponType == WEAPONTYPE_BASEBALLBAT
+ || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0
+ && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE && m_nSelectedWepSlot != WEAPONTYPE_TEARGAS) {
+#endif
goto switchDetectDone;
}
}
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
+ m_nSelectedWepSlot = 0;
}
}
}
@@ -643,6 +721,7 @@ CPlayerPed::ProcessWeaponSwitch(CPad *padUsed)
switchDetectDone:
if (m_nSelectedWepSlot != m_currentWeapon) {
if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT)
+ RemoveWeaponAnims(m_currentWeapon, -1000.0f);
MakeChangesForNewWeapon(m_nSelectedWepSlot);
}
}
@@ -663,7 +742,7 @@ CPlayerPed::PlayerControlM16(CPad *padUsed)
firePos = GetMatrix() * firePos;
GetWeapon()->Fire(this, &firePos);
}
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, nil);
}
void
@@ -934,6 +1013,7 @@ CPlayerPed::FindWeaponLockOnTarget(void)
return true;
}
+// --MIAMI: Done, but uncomment new weapon types when weapons got ported
void
CPlayerPed::ProcessAnimGroups(void)
{
@@ -946,17 +1026,29 @@ CPlayerPed::ProcessAnimGroups(void)
if (m_fWalkAngle > 0.0f) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
groupToSet = ASSOCGRP_ROCKETLEFT;
+ else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER
+ /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/ )
+ groupToSet = ASSOCGRP_CHAINSAWLEFT;
else
groupToSet = ASSOCGRP_PLAYERLEFT;
} else {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
groupToSet = ASSOCGRP_ROCKETRIGHT;
+ else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER
+ /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/)
+ groupToSet = ASSOCGRP_CHAINSAWRIGHT;
else
groupToSet = ASSOCGRP_PLAYERRIGHT;
}
} else {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
groupToSet = ASSOCGRP_ROCKETBACK;
+ else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER
+ /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/)
+ groupToSet = ASSOCGRP_CHAINSAWBACK;
else
groupToSet = ASSOCGRP_PLAYERBACK;
}
@@ -964,9 +1056,21 @@ CPlayerPed::ProcessAnimGroups(void)
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
groupToSet = ASSOCGRP_PLAYERROCKET;
} else {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT
+ /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MACHETE */)
groupToSet = ASSOCGRP_PLAYERBBBAT;
- } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) {
+ else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER
+ /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/)
+ groupToSet = ASSOCGRP_PLAYERCHAINSAW;
+ else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI
+ // I hope this was inlined...
+ /*
+ && GetWeapon()->m_eWeaponType != WEAPONTYPE_PYTHON*/ && GetWeapon()->m_eWeaponType != WEAPONTYPE_TEC9
+ && GetWeapon()->m_eWeaponType != WEAPONTYPE_SILENCED_INGRAM && GetWeapon()->m_eWeaponType != WEAPONTYPE_MP5 /*
+ && GetWeapon()->m_eWeaponType != WEAPONTYPE_GOLFCLUB && GetWeapon()->m_eWeaponType != WEAPONTYPE_KATANA
+ && GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA
+ */) {
if (!GetWeapon()->IsType2Handed()) {
groupToSet = ASSOCGRP_PLAYER;
} else {
@@ -984,6 +1088,7 @@ CPlayerPed::ProcessAnimGroups(void)
}
}
+// TODO(Miami): Hella TODO
void
CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
{
@@ -995,8 +1100,9 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
}
if (!m_pFire) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ||
- GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) {
- if (padUsed->TargetJustDown()) {
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 ||
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47) {
+ if (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) {
SetStoredState();
m_nPedState = PED_SNIPER_MODE;
#ifdef FREE_CAM
@@ -1030,7 +1136,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
else
#endif
SetAttack(m_pPointGunAt);
- } else if (m_currentWeapon != WEAPONTYPE_UNARMED) {
+ } else {
if (m_nPedState == PED_ATTACK) {
if (padUsed->WeaponJustDown()) {
m_bHaveTargetSelected = true;
@@ -1041,12 +1147,19 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
m_fAttackButtonCounter = 0.0f;
m_bHaveTargetSelected = false;
}
- SetAttack(nil);
- } else if (padUsed->WeaponJustDown()) {
- if (m_fMoveSpeed < 1.0f)
- StartFightAttack(padUsed->GetWeapon());
- else
- SetAttack(nil);
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&
+ !weaponInfo->m_bFightMode) {
+
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR && GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE ||
+ padUsed->WeaponJustDown())
+
+ SetAttack(nil);
+ } else if (padUsed->WeaponJustDown()) {
+ if (m_fMoveSpeed < 1.0f || m_nPedState == PED_FIGHT)
+ StartFightAttack(padUsed->GetWeapon());
+ else
+ SetAttack(nil);
+ }
}
}
} else {
@@ -1063,7 +1176,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
// Weapons except throwable and melee ones
- if (weaponInfo->m_bCanAim || weaponInfo->m_b1stPerson || weaponInfo->m_bExpands) {
+ if (weaponInfo->m_nWeaponSlot > 2) {
if ((padUsed->GetTarget() && weaponInfo->m_bCanAimWithArm) || padUsed->GetWeapon()) {
float limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
@@ -1081,7 +1194,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
#endif
} else {
m_fRotationDest = limitedCam;
- m_headingRate = 50.0f;
+ m_headingRate = 12.5f;
// Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly)
if (weaponInfo->m_bCanAim && padUsed->WeaponJustDown()) {
@@ -1185,7 +1298,7 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed)
float neededTurn = CGeneral::LimitRadianAngle(padHeading - camOrientation);
if (doSmoothSpray) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || GetWeapon()->m_eWeaponType == WEAPONTYPE_COLT45
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI)
+ || CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nWeaponSlot == 5)
m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 80.0f) * CTimer::GetTimeStep();
else
m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 128.0f) * CTimer::GetTimeStep();
@@ -1457,7 +1570,7 @@ CPlayerPed::ProcessControl(void)
}
if (padUsed && IsPedShootable()) {
ProcessWeaponSwitch(padUsed);
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, this);
}
ProcessAnimGroups();
if (padUsed) {
diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h
index e8173c8c..354140df 100644
--- a/src/peds/PlayerPed.h
+++ b/src/peds/PlayerPed.h
@@ -18,22 +18,32 @@ public:
int8 m_nSelectedWepSlot; // eWeaponType
bool m_bSpeedTimerFlag;
uint8 m_nEvadeAmount;
- int8 field_1367;
- uint32 m_nSpeedTimer;
- uint32 m_nHitAnimDelayTimer;
+ uint32 m_nSpeedTimer; // m_nStandStillTimer?
+ uint32 m_nHitAnimDelayTimer; // m_nShotDelay?
float m_fAttackButtonCounter;
bool m_bHaveTargetSelected; // may have better name
CEntity *m_pEvadingFrom; // is this CPhysical?
int32 m_nTargettableObjects[4];
+ uint32 m_nAdrenalineTime;
+ uint8 m_nDrunkenness; // Needed to work out whether we lost target this frame
+ uint8 m_nFadeDrunkenness;
+ uint8 m_nDrunkCountdown; //countdown in frames when the drunk effect ends
bool m_bAdrenalineActive;
bool m_bHasLockOnTarget;
- uint32 m_nAdrenalineTime;
bool m_bCanBeDamaged;
- int8 field_1413;
+ bool m_bDrunkVisualsWearOff; // TODO(Miami): That may be something else
CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree
CPed *m_pPedAtSafePos[6];
- float m_fWalkAngle;
+ CPlayerPed* m_pCheckPlayers[6]; //checks something with players, could be a leftover from original multiplayer
+ char unused1;
+ int16 m_nCheckPlayersIndex;
+ float m_fWalkAngle; //angle between heading and walking direction
float m_fFPSMoveHeading;
+ RpAtomic* m_pMinigunTopAtomic; //atomic for the spinning part of the minigun model
+ float m_fGunSpinSpeed; // for minigun
+ float m_fGunSpinAngle;
+ unsigned int m_nPadDownPressedInMilliseconds;
+ unsigned int m_nPadUpPressedInMilliseconds;
CPlayerPed();
~CPlayerPed();
@@ -45,7 +55,8 @@ public:
void SetWantedLevelNoDrop(int32 level);
void KeepAreaAroundPlayerClear(void);
void AnnoyPlayerPed(bool);
- void MakeChangesForNewWeapon(int8);
+ void MakeChangesForNewWeapon(int32);
+ void MakeChangesForNewWeapon(eWeaponType);
void SetInitialState(void);
void ProcessControl(void);
void ClearAdrenaline(void);
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index e2257a28..40ceb6c3 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -31,6 +31,10 @@
// Transition areas between zones
const RegenerationPoint aSafeZones[] = {
+// TODO(MIAMI): this is totally bogus
+ { LEVEL_BEACH, LEVEL_MAINLAND, 400.0f, 814.0f, -954.0f, -903.0f, 30.0f, 100.0f,
+ CVector(790.0f, -917.0f, 39.0f), CVector(775.0f, -921.0f, 39.0f), CVector(424.0f, -942.0f, 38.0f), CVector(439.0f, -938.0f, 38.0f) },
+#ifndef MIAMI
{ LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 400.0f, 814.0f, -954.0f, -903.0f, 30.0f, 100.0f,
CVector(790.0f, -917.0f, 39.0f), CVector(775.0f, -921.0f, 39.0f), CVector(424.0f, -942.0f, 38.0f), CVector(439.0f, -938.0f, 38.0f) },
{ LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 555.0f, 711.0f, 118.0f, 186.0f, -30.0f, -10.0f,
@@ -47,6 +51,7 @@ const RegenerationPoint aSafeZones[] = {
CVector(-321.0f, -1043.0f, -13.2f), CVector(-328.0f, -1045.0f, -13.2f), CVector(-398.0f, -1044.0f, -13.5f), CVector(-390.0f, -1040.5f, -13.5f) },
{ LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -425.0f, -280.0f, -471.0f, -447.0f, -20.0f, -5.0f,
CVector(-292.0f, -457.0f, -11.6f), CVector(-310.0f, -461.0f, -11.6f), CVector(-413.0f, -461.0f, -11.5f), CVector(-399.0f, -457.0f, -11.3f) }
+#endif
};
PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS];
@@ -78,6 +83,9 @@ CVector CPopulation::RegenerationPoint_a;
CVector CPopulation::RegenerationPoint_b;
CVector CPopulation::RegenerationForward;
+uint32 CPopulation::ms_nTotalCarPassengerPeds;
+uint32 CPopulation::NumMiamiViceCops;
+
void
CPopulation::Initialise()
{
@@ -98,6 +106,8 @@ CPopulation::Initialise()
ms_nNumGang9 = 0;
ms_nNumDummy = 0;
+ ms_nTotalCarPassengerPeds = 0;
+
m_AllRandomPedsThisType = -1;
PedDensityMultiplier = 1.0f;
bZoneChangeHasHappened = false;
@@ -109,7 +119,6 @@ CPopulation::Initialise()
ms_nTotalCivPeds = 0;
LoadPedGroups();
- DealWithZoneChange(LEVEL_COMMERCIAL, LEVEL_INDUSTRIAL, true);
debug("CPopulation ready\n");
}
@@ -320,64 +329,13 @@ CPopulation::UpdatePedCount(ePedType pedType, bool decrease)
int
CPopulation::ChooseGangOccupation(int gangId)
{
- int8 modelOverride = CGangs::GetGangPedModelOverride(gangId);
-
- // All gangs have 2 models
- int firstGangModel = 2 * gangId + MI_GANG01;
-
- // GetRandomNumberInRange never returns max. value
- if (modelOverride == -1)
- return CGeneral::GetRandomNumberInRange(firstGangModel, firstGangModel + 2);
-
- if (modelOverride != 0)
- return firstGangModel + 1;
- else
- return firstGangModel;
+ return CGangs::ChooseGangPedModel(gangId);
}
+//--MIAMI: done
void
CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool forceIndustrialZone)
{
- bZoneChangeHasHappened = true;
-
- CVector findSafeZoneAround;
- int safeZone;
-
- if (forceIndustrialZone) {
- // Commercial to industrial transition area on Callahan Bridge
- findSafeZoneAround.x = 690.0f;
- findSafeZoneAround.y = -920.0f;
- findSafeZoneAround.z = 42.0f;
- } else {
- findSafeZoneAround = FindPlayerCoors();
- }
- eLevelName level;
- FindCollisionZoneForCoors(&findSafeZoneAround, &safeZone, &level);
-
- // We aren't in a "safe zone", find closest one
- if (safeZone < 0)
- FindClosestZoneForCoors(&findSafeZoneAround, &safeZone, oldLevel, newLevel);
-
- // No, there should be one!
- if (safeZone < 0) {
- if (newLevel == LEVEL_INDUSTRIAL) {
- safeZone = 0;
- } else if (newLevel == LEVEL_SUBURBAN) {
- safeZone = 4;
- }
- }
-
- if (aSafeZones[safeZone].srcLevel == newLevel) {
- CPopulation::RegenerationPoint_a = aSafeZones[safeZone].srcPosA;
- CPopulation::RegenerationPoint_b = aSafeZones[safeZone].srcPosB;
- CPopulation::RegenerationForward = aSafeZones[safeZone].destPosA - aSafeZones[safeZone].srcPosA;
- RegenerationForward.Normalise();
- } else if (aSafeZones[safeZone].destLevel == newLevel) {
- CPopulation::RegenerationPoint_a = aSafeZones[safeZone].destPosA;
- CPopulation::RegenerationPoint_b = aSafeZones[safeZone].destPosB;
- CPopulation::RegenerationForward = aSafeZones[safeZone].srcPosA - aSafeZones[safeZone].destPosA;
- RegenerationForward.Normalise();
- }
}
void
@@ -433,6 +391,7 @@ CPopulation::Update()
+ ms_nNumGang2 + ms_nNumGang1;
ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
+ ms_nTotalPeds -= ms_nTotalCarPassengerPeds;
if (!CCutsceneMgr::IsRunning()) {
float pcdm = PedCreationDistMultiplier();
AddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier),
@@ -454,6 +413,7 @@ CPopulation::GeneratePedsAtStartOfGame()
+ ms_nNumGang3 + ms_nNumGang2 + ms_nNumGang1;
ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
+ ms_nTotalPeds -= ms_nTotalCarPassengerPeds;
// Min dist is 10.0f only for start of the game (naturally)
AddToPopulation(10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE),
@@ -488,7 +448,7 @@ CPopulation::PedCreationDistMultiplier()
}
CPed*
-CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors)
+CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors, int32 modifier)
{
switch (pedType) {
case PEDTYPE_CIVMALE:
@@ -499,16 +459,34 @@ CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors)
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CWorld::Add(ped);
if (ms_bGivePedsWeapons) {
- eWeaponType weapon = (eWeaponType)CGeneral::GetRandomNumberInRange(WEAPONTYPE_UNARMED, WEAPONTYPE_DETONATOR);
+ eWeaponType weapon;
+
+ switch (CGeneral::GetRandomNumber() & 3) {
+ case 0:
+ weapon = WEAPONTYPE_COLT45;
+ break;
+ case 1:
+ weapon = WEAPONTYPE_NIGHTSTICK;
+ break;
+ case 2:
+ weapon = WEAPONTYPE_GOLFCLUB;
+ break;
+ case 3:
+ weapon = WEAPONTYPE_TEC9;
+ break;
+ default:
+ break;
+ }
if (weapon != WEAPONTYPE_UNARMED) {
- ped->SetCurrentWeapon(ped->GiveWeapon(weapon, 25001));
+ ped->GiveDelayedWeapon(weapon, 25001);
+ ped->SetCurrentWeapon(CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot);
}
}
return ped;
}
case PEDTYPE_COP:
{
- CCopPed *ped = new CCopPed((eCopType)miOrCopType);
+ CCopPed *ped = new CCopPed((eCopType)miOrCopType, modifier);
ped->SetPosition(coors);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CWorld::Add(ped);
@@ -529,12 +507,14 @@ CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors)
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CWorld::Add(ped);
- uint32 weapon;
+ eWeaponType weapon;
if (CGeneral::GetRandomNumberInRange(0, 100) >= 50)
- weapon = ped->GiveWeapon((eWeaponType)CGangs::GetGangInfo(pedType - PEDTYPE_GANG1)->m_Weapon2, 25001);
+ weapon = (eWeaponType)CGangs::GetGangInfo(pedType - PEDTYPE_GANG1)->m_Weapon2;
else
- weapon = ped->GiveWeapon((eWeaponType)CGangs::GetGangInfo(pedType - PEDTYPE_GANG1)->m_Weapon1, 25001);
- ped->SetCurrentWeapon(weapon);
+ weapon = (eWeaponType)CGangs::GetGangInfo(pedType - PEDTYPE_GANG1)->m_Weapon1;
+
+ ped->GiveDelayedWeapon(weapon, 25001);
+ ped->SetCurrentWeapon(CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot);
return ped;
}
case PEDTYPE_EMERGENCY:
@@ -599,14 +579,12 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);
- if (decisionThreshold < zoneInfo.copDensity || addCop) {
+ if (decisionThreshold < zoneInfo.copPedThreshold || addCop) {
pedTypeToAdd = PEDTYPE_COP;
modelToAdd = ChoosePolicePedOccupation();
} else {
- int16 density = zoneInfo.copDensity;
for (int i = 0; i < NUM_GANGS; i++) {
- density += zoneInfo.gangDensity[i];
- if (decisionThreshold < density) {
+ if (decisionThreshold < zoneInfo.gangPedThreshold[i]) {
pedTypeToAdd = PEDTYPE_GANG1 + i;
break;
}
@@ -693,7 +671,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
generatedCoors.y = yOffset + gangLeader->GetPosition().y;
}
}
- if (!CPedPlacement::IsPositionClearForPed(&generatedCoors))
+ if (!CPedPlacement::IsPositionClearForPed(generatedCoors))
break;
// Why no love for last gang member?!
@@ -743,9 +721,10 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
}
CPed*
-CPopulation::AddPedInCar(CVehicle* car)
+CPopulation::AddPedInCar(CVehicle* car, bool isDriver)
{
int defaultModel = MI_MALE01;
+ int miamiViceIndex = 0;
bool imSureThatModelIsLoaded = true;
CVector coors = FindPlayerCoors();
CZoneInfo zoneInfo;
@@ -769,6 +748,7 @@ CPopulation::AddPedInCar(CVehicle* car)
pedType = PEDTYPE_COP;
break;
case MI_POLICE:
+ case MI_PREDATOR:
preferredModel = COP_STREET;
pedType = PEDTYPE_COP;
break;
@@ -781,9 +761,15 @@ CPopulation::AddPedInCar(CVehicle* car)
preferredModel = COP_ARMY;
pedType = PEDTYPE_COP;
break;
+ case MI_VICECHEE: // TODO(MIAMI): figure out new structure of the function
+ preferredModel = COP_MIAMIVICE;
+ pedType = PEDTYPE_COP;
+ miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1);
+ break;
case MI_TAXI:
case MI_CABBIE:
- case MI_BORGNINE:
+ case MI_ZEBRA:
+ case MI_KAUFMAN:
if (CGeneral::GetRandomTrueFalse()) {
pedType = PEDTYPE_CIVMALE;
preferredModel = MI_TAXI_D;
@@ -826,120 +812,20 @@ CPopulation::AddPedInCar(CVehicle* car)
pedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(defaultModel))->m_pedType;
}
- CPed *newPed = CPopulation::AddPed((ePedType)pedType, preferredModel, car->GetPosition());
+ CPed *newPed = CPopulation::AddPed((ePedType)pedType, preferredModel, car->GetPosition(), miamiViceIndex);
newPed->bUsesCollision = false;
- // what??
- if (pedType != PEDTYPE_COP) {
- newPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
+ if (newPed->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
newPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(newPed->GetWeapon()->m_eWeaponType)->m_nModelId);
}
- /*
- // Miami leftover
- if (car->m_vehType == VEHICLE_TYPE_BIKE) {
- newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, *((CBike*)car + 308h), 100.0f);
- } else */
- // FIX: Make peds comfortable while driving car/boat
-#ifdef FIX_BUGS
- {
- newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
- }
-#else
- {
- newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
- }
-#endif
-
- newPed->StopNonPartialAnims();
+ newPed->AddInCarAnims(car, isDriver);
return newPed;
}
void
CPopulation::MoveCarsAndPedsOutOfAbandonedZones()
{
- eLevelName level;
- int zone;
- int frame = CTimer::GetFrameCounter() & 7;
- if (frame == 1) {
- int movedVehicleCount = 0;
- int poolSize = CPools::GetVehiclePool()->GetSize();
- for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
-
- CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
- if (veh && veh->m_nZoneLevel == LEVEL_NONE && veh->IsCar()) {
-
- if(veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_PLAYER &&
- veh->GetStatus() != STATUS_PLAYER_REMOTE) {
-
- CVector vehPos(veh->GetPosition());
- CPopulation::FindCollisionZoneForCoors(&vehPos, &zone, &level);
-
- // Level 0 is transition zones, and we don't wanna touch cars on transition zones.
- if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && vehPos.z > -4.0f) {
- if (veh->bIsLocked || !veh->CanBeDeleted()) {
- switch (movedVehicleCount & 3) {
- case 0:
- veh->SetPosition(RegenerationPoint_a);
- break;
- case 1:
- veh->SetPosition(RegenerationPoint_b);
- break;
- case 2:
- veh->SetPosition(RegenerationPoint_a.x, RegenerationPoint_b.y, RegenerationPoint_a.z);
- break;
- case 3:
- veh->SetPosition(RegenerationPoint_b.x, RegenerationPoint_a.y, RegenerationPoint_a.z);
- break;
- default:
- break;
- }
- veh->GetMatrix().GetPosition().z += (movedVehicleCount / 4) * 7.0f;
- veh->GetMatrix().GetForward() = RegenerationForward;
- ((CAutomobile*)veh)->PlaceOnRoadProperly();
- CCarCtrl::JoinCarWithRoadSystem(veh);
- CTheScripts::ClearSpaceForMissionEntity(veh->GetPosition(), veh);
- ++movedVehicleCount;
- } else {
- CWorld::Remove(veh);
- delete veh;
- }
- }
- }
- }
- }
- } else if (frame == 5) {
- int poolSize = CPools::GetPedPool()->GetSize();
- for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
-
- CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);
- if (ped && ped->m_nZoneLevel == LEVEL_NONE && !ped->bInVehicle) {
-
- CVector pedPos(ped->GetPosition());
- CPopulation::FindCollisionZoneForCoors(&pedPos, &zone, &level);
-
- // Level 0 is transition zones, and we don't wanna touch peds on transition zones.
- if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && pedPos.z > -4.0f) {
- if (ped->CanBeDeleted()) {
- CWorld::Remove(ped);
- delete ped;
- } else if (ped->m_nPedType != PEDTYPE_PLAYER1 && ped->m_nPedType != PEDTYPE_PLAYER2) {
- ped->SetPosition(RegenerationPoint_a);
-
- bool foundGround;
- float groundZ = CWorld::FindGroundZFor3DCoord(ped->GetPosition().x, ped->GetPosition().y,
- ped->GetPosition().z + 2.0f, &foundGround);
-
- if (foundGround) {
- ped->GetMatrix().GetPosition().z = 1.0f + groundZ;
- //ped->GetPosition().z += 0.0f;
- CTheScripts::ClearSpaceForMissionEntity(ped->GetPosition(), ped);
- }
- }
- }
- }
- }
- }
}
void
@@ -970,7 +856,8 @@ CPopulation::ConvertToRealObject(CDummyObject *dummy)
delete dummy;
CWorld::Add(obj);
- if (IsGlass(obj->GetModelIndex())) {
+ CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(obj->GetModelIndex());
+ if (IsGlass(obj->GetModelIndex()) && !mi->m_isArtistGlass) {
obj->bIsVisible = false;
} else if (obj->GetModelIndex() == MI_BUOY) {
obj->bIsStatic = false;
@@ -989,7 +876,8 @@ CPopulation::ConvertToDummyObject(CObject *obj)
dummy->GetMatrix().UpdateRW();
dummy->UpdateRwFrame();
- if (IsGlass(obj->GetModelIndex()))
+ CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(obj->GetModelIndex());
+ if (IsGlass(obj->GetModelIndex()) && !mi->m_isArtistGlass)
dummy->bIsVisible = false;
CWorld::Remove(obj);
@@ -1117,6 +1005,10 @@ CPopulation::ManagePopulation(void)
}
float dist = (ped->GetPosition() - playerPos).Magnitude2D();
+
+ if (ped->IsGangMember() || (ped->bDeadPedInFrontOfCar && ped->m_vehicleInAccident))
+ dist -= 30.0f;
+
bool pedIsFarAway = false;
if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist
|| (!ped->bCullExtraFarAway && PedCreationDistMultiplier() * PED_REMOVE_DIST * TheCamera.GenerationDistMultiplier < dist)
@@ -1163,3 +1055,49 @@ CPopulation::ManagePopulation(void)
}
}
}
+
+CPed*
+CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit)
+{
+ if (TheCamera.IsSphereVisible(pos, 2.0f)) {
+ float fDistanceToPlayer = (pos - FindPlayerPed()->GetPosition()).Magnitude2D();
+ float fDistanceMultiplier;
+ if (FindPlayerVehicle())
+ fDistanceMultiplier = clamp(FindPlayerVehicle()->GetMoveSpeed().Magnitude2D() - 0.1f + 1.0f, 1.0f, 1.5f);
+ else
+ fDistanceMultiplier = 1.0f;
+ if (40.0f * fDistanceMultiplier > fDistanceToPlayer)
+ return nil;
+ }
+ bool found;
+ float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 1.0f;
+ if (!found)
+ return nil;
+ z = Max(z, pos.z);
+ if (!CModelInfo::GetModelInfo(MI_MALE01)->GetRwObject()) // strange way to check it
+ return nil;
+ CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter
+ pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ pPed->m_nPedMoney = 0;
+ pPed->bDeadPedInFrontOfCar = true;
+ pPed->m_vehicleInAccident = pCulprit;
+ pCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident);
+ CEntity* pEntities[3] = { 0 };
+ if (!CPedPlacement::IsPositionClearForPed(pos, 2.0f, 3, pEntities)) {
+ for (int i = 0; i < 3; i++) {
+ if (pEntities[i] && pEntities[i] != pCulprit && pEntities[i] != pPed) {
+ CWorld::Remove(pPed);
+ delete pPed;
+ return nil;
+ }
+ }
+ }
+ CColPoint colpts[MAX_COLLISION_POINTS];
+ if (CCollision::ProcessColModels(pCulprit->GetMatrix(), *pCulprit->GetColModel(), pPed->GetMatrix(), *pPed->GetColModel(), colpts, nil, nil)) {
+ CWorld::Remove(pPed);
+ delete pPed;
+ return nil;
+ }
+ CVisibilityPlugins::SetClumpAlpha(pPed->GetClump(), 0);
+ return pPed;
+}
diff --git a/src/peds/Population.h b/src/peds/Population.h
index aa8129c0..ae4aa44c 100644
--- a/src/peds/Population.h
+++ b/src/peds/Population.h
@@ -62,12 +62,15 @@ public:
static CVector RegenerationPoint_b;
static CVector RegenerationForward;
+ static uint32 ms_nTotalCarPassengerPeds;
+ static uint32 NumMiamiViceCops;
+
static void Initialise();
static void Update(void);
static void LoadPedGroups();
static void UpdatePedCount(ePedType, bool);
static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);
- static CPed *AddPedInCar(CVehicle *car);
+ static CPed *AddPedInCar(CVehicle *car, bool isDriver);
static bool IsPointInSafeZone(CVector *coors);
static void RemovePed(CPed *ent);
static int32 ChooseCivilianOccupation(int32);
@@ -77,7 +80,7 @@ public:
static void FindClosestZoneForCoors(CVector*, int*, eLevelName, eLevelName);
static void GeneratePedsAtStartOfGame();
static float PedCreationDistMultiplier();
- static CPed *AddPed(ePedType pedType, uint32 mi, CVector const &coors);
+ static CPed *AddPed(ePedType pedType, uint32 mi, CVector const &coors, int32 modifier = 0);
static void AddToPopulation(float, float, float, float);
static void ManagePopulation(void);
static void MoveCarsAndPedsOutOfAbandonedZones(void);
@@ -86,4 +89,6 @@ public:
static void ConvertAllObjectsToDummyObjects(void);
static bool TestRoomForDummyObject(CObject*);
static bool TestSafeForRealObject(CDummyObject*);
+
+ static CPed* AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit);
};
diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h
index 2a71a8d5..504824c5 100644
--- a/src/render/2dEffect.h
+++ b/src/render/2dEffect.h
@@ -3,7 +3,9 @@
enum {
EFFECT_LIGHT,
EFFECT_PARTICLE,
- EFFECT_ATTRACTOR
+ EFFECT_ATTRACTOR,
+ EFFECT_PED_ATTRACTOR,
+ EFFECT_SUNGLARE
};
enum {
@@ -34,6 +36,8 @@ enum {
// same order as CPointLights flags, must start at 2
LIGHTFLAG_FOG_NORMAL = 2, // can have light and fog
LIGHTFLAG_FOG_ALWAYS = 4, // fog only
+ LIGHTFLAG_HIDE_OBJECT = 8, // hide the object instead of rendering light (???)
+ LIGHTFLAG_LONG_DIST = 16,
LIGHTFLAG_FOG = (LIGHTFLAG_FOG_NORMAL|LIGHTFLAG_FOG_ALWAYS)
};
@@ -63,6 +67,11 @@ public:
uint8 flags;
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) {}
diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp
index 60450213..c6ba0f10 100644
--- a/src/render/Clouds.cpp
+++ b/src/render/Clouds.cpp
@@ -3,6 +3,7 @@
#include "Sprite.h"
#include "Sprite2d.h"
#include "General.h"
+#include "Game.h"
#include "Coronas.h"
#include "Camera.h"
#include "TxdStore.h"
@@ -23,8 +24,10 @@ uint32 CClouds::IndividualRotation;
float CClouds::ms_cameraRoll;
float CClouds::ms_horizonZ;
+float CClouds::ms_HorizonTilt;
CRGBA CClouds::ms_colourTop;
CRGBA CClouds::ms_colourBottom;
+CRGBA CClouds::ms_colourBkGrd;
void
CClouds::Init(void)
@@ -44,25 +47,15 @@ void
CClouds::Shutdown(void)
{
RwTextureDestroy(gpCloudTex[0]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[0] = nil;
-#endif
RwTextureDestroy(gpCloudTex[1]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[1] = nil;
-#endif
RwTextureDestroy(gpCloudTex[2]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[2] = nil;
-#endif
RwTextureDestroy(gpCloudTex[3]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[3] = nil;
-#endif
RwTextureDestroy(gpCloudTex[4]);
-#ifdef GTA3_1_1_PATCH
gpCloudTex[4] = nil;
-#endif
}
void
@@ -70,11 +63,11 @@ 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
}
@@ -86,6 +79,9 @@ CClouds::Render(void)
RwV3d screenpos;
RwV3d worldpos;
+ if(!CGame::CanSeeOutSideFromCurrArea())
+ return;
+
CCoronas::SunBlockedByClouds = false;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
@@ -95,26 +91,21 @@ CClouds::Render(void)
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
CSprite::InitSpriteBuffer();
- int minute = CClock::GetHours()*60 + CClock::GetMinutes();
+ float minute = CClock::GetHours()*60 + CClock::GetMinutes() + CClock::GetSeconds()/60.0f;
RwV3d campos = *(RwV3d*)&TheCamera.GetPosition();
float coverage = Max(CWeather::Foggyness, CWeather::Foggyness);
// Moon
- int moonfadeout = Abs(minute - 180); // fully visible at 3AM
- if(moonfadeout < 180){ // fade in/out 3 hours
- int brightness = (1.0f - coverage) * (180 - moonfadeout);
+ float moonfadeout = Abs(minute - 180.0f); // fully visible at 3AM
+ if((int)moonfadeout < 180){ // fade in/out 3 hours
+ 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);
}
@@ -132,7 +123,7 @@ CClouds::Render(void)
starintens = 255 * (60 - CClock::GetMinutes())/60.0f;
if(starintens != 0){
// R
- static float StarCoorsX[9] = { 0.0f, 0.05f, 0.12f, 0.5f, 0.8f, 0.6f, 0.27f, 0.55f, 0.75f };
+ static float StarCoorsX[9] = { 0.0f, 0.05f, 0.13f, 0.4f, 0.7f, 0.6f, 0.27f, 0.55f, 0.75f };
static float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f };
static float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f };
int brightness = (1.0f - coverage) * starintens;
@@ -170,7 +161,7 @@ CClouds::Render(void)
1.0f, 0.7f, 0.4f, 0.4f, -0.8f, -0.8f };
static float LowCloudsZ[12] = { 0.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.3f,
0.9f, 0.4f, 1.3f, 1.4f, 1.2f, 1.7f };
- float lowcloudintensity = 1.0f - coverage;
+ float lowcloudintensity = 1.0f - Max(coverage, CWeather::ExtraSunnyness);
int r = CTimeCycle::GetLowCloudsRed() * lowcloudintensity;
int g = CTimeCycle::GetLowCloudsGreen() * lowcloudintensity;
int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity;
@@ -191,7 +182,7 @@ 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 float CoorsOffsetX[37] = {
0.0f, 60.0f, 72.0f, 48.0f, 21.0f, 12.0f,
@@ -218,7 +209,7 @@ CClouds::Render(void)
2.0f, 2.0f, 1.5f, 1.2f, 1.7f, 1.5f, 2.1f
};
static bool bCloudOnScreen[37];
- float hilight;
+ float sundist, hilight;
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
@@ -230,15 +221,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 - coverage) * (1.0f - sundist/(SCREEN_WIDTH/2));
+ int distLimit = (3*SCREEN_WIDTH)/4;
+ if(sundist < distLimit){
+ hilight = (1.0f - coverage) * (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;
@@ -272,8 +264,7 @@ CClouds::Render(void)
worldpos.y = campos.x*rot_sin + campos.y*rot_cos + pos.y;
worldpos.z = pos.z;
if(bCloudOnScreen[i] && CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
- // BUG: this is stupid....would have to do this for each cloud individually
- if(hilight > 0.0f){
+ if(sundist < SCREEN_WIDTH/3){
CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(screenpos.x, screenpos.y, screenpos.z,
szx*30.0f, szy*30.0f,
200*hilight, 0, 0, 255, 1.0f/screenpos.z,
@@ -320,14 +311,17 @@ void
CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue,
int16 botred, int16 botgreen, int16 botblue, int16 alpha)
{
- CVector left = TheCamera.GetRight();
- float c = left.Magnitude2D();
+ CVector right = CrossProduct(TheCamera.GetUp(), TheCamera.GetForward());
+ right.Normalise();
+ float c = right.Magnitude2D();
if(c > 1.0f)
c = 1.0f;
ms_cameraRoll = Acos(c);
- if(left.z < 0.0f)
+ if(right.z < 0.0f)
ms_cameraRoll = -ms_cameraRoll;
+ ms_HorizonTilt = SCREEN_WIDTH/2.0f * Tan(ms_cameraRoll);
+
if(UseDarkBackground()){
ms_colourTop.r = 50;
ms_colourTop.g = 50;
@@ -350,75 +344,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;
}
}
@@ -431,21 +424,35 @@ CClouds::RenderHorizon(void)
ms_colourBottom.a = 230;
ms_colourTop.a = 80;
- if(ms_horizonZ > SCREEN_HEIGHT)
- return;
+ float topright = ms_horizonZ - ms_HorizonTilt;
+ float topleft = ms_horizonZ + ms_HorizonTilt;
+ float botright = topright + SMALLSTRIPHEIGHT;
+ float botleft = topleft + SMALLSTRIPHEIGHT;
+
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom);
+
+
+ ms_colourBkGrd.r = 128.0f*CTimeCycle::GetAmbientRed();
+ ms_colourBkGrd.g = 128.0f*CTimeCycle::GetAmbientGreen();
+ ms_colourBkGrd.b = 128.0f*CTimeCycle::GetAmbientBlue();
+ ms_colourBkGrd.a = 255;
+
+ float horzstrip = SCREEN_STRETCH_Y(HORIZSTRIPHEIGHT);
+ topright = botright;
+ topleft = botleft;
+ botright = topright + horzstrip;
+ botleft = topleft + horzstrip;
+
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourBottom, ms_colourBottom, ms_colourBkGrd, ms_colourBkGrd);
+
+
+ topright = botright;
+ topleft = botleft;
+ botright = Max(topright, SCREEN_HEIGHT);
+ botleft = Max(topleft, SCREEN_HEIGHT);
- float z1 = Min(ms_horizonZ + SMALLSTRIPHEIGHT, SCREEN_HEIGHT);
- CSprite2d::DrawRectXLU(CRect(0, ms_horizonZ, SCREEN_WIDTH, z1),
- ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
-
- // This is just weird
- float a = SCREEN_HEIGHT/400.0f * HORIZSTRIPHEIGHT +
- SCREEN_HEIGHT/300.0f * Max(TheCamera.GetPosition().z, 0.0f);
- float b = TheCamera.GetUp().z < 0.0f ?
- SCREEN_HEIGHT :
- SCREEN_HEIGHT * Abs(TheCamera.GetRight().z);
- float z2 = z1 + (a + b)*TheCamera.LODDistMultiplier;
- z2 = Min(z2, SCREEN_HEIGHT);
- CSprite2d::DrawRect(CRect(0, z1, SCREEN_WIDTH, z2),
- ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);
+ CSprite2d::DrawAnyRect(0.0f, topleft, SCREEN_WIDTH, topright, 0.0f, botleft, SCREEN_WIDTH, botright,
+ ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd);
}
diff --git a/src/render/Clouds.h b/src/render/Clouds.h
index 4d8cd2c8..ef33030b 100644
--- a/src/render/Clouds.h
+++ b/src/render/Clouds.h
@@ -8,8 +8,10 @@ public:
static float ms_cameraRoll;
static float ms_horizonZ;
+ static float ms_HorizonTilt;
static CRGBA ms_colourTop;
static CRGBA ms_colourBottom;
+ static CRGBA ms_colourBkGrd;
static void Init(void);
static void Shutdown(void);
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index de3b5c78..8e832ab1 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -53,7 +53,7 @@ RwTexture *gpCoronaTexture[9] = { nil, nil, nil, nil, nil, nil, nil, nil, nil };
float CCoronas::LightsMult = 1.0f;
float CCoronas::SunScreenX;
float CCoronas::SunScreenY;
-bool CCoronas::bSmallMoon;
+int CCoronas::MoonSize;
bool CCoronas::SunBlockedByClouds;
int CCoronas::bChangeBrightnessImmediately;
@@ -129,7 +129,8 @@ 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 longDist, float nearDist)
{
int i;
@@ -192,11 +193,13 @@ CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 al
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 longDist, 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,
+ longDist, nearDist);
}
void
diff --git a/src/render/Coronas.h b/src/render/Coronas.h
index 46eb4315..cb4e8583 100644
--- a/src/render/Coronas.h
+++ b/src/render/Coronas.h
@@ -81,7 +81,7 @@ public:
static float LightsMult;
static float SunScreenY;
static float SunScreenX;
- static bool bSmallMoon;
+ static int MoonSize;
static bool SunBlockedByClouds;
static int bChangeBrightnessImmediately;
@@ -90,10 +90,12 @@ 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 longDist = false, float nearClip = 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 longDist = false, float nearClip = 1.5f);
static void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle);
static void Render(void);
static void RenderReflections(void);
diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp
index 9f3f6929..59ac1652 100644
--- a/src/render/Fluff.cpp
+++ b/src/render/Fluff.cpp
@@ -104,7 +104,8 @@ void CMovingThings::Init()
EndCloseList.m_pNext = nil;
EndCloseList.m_pPrev = &CMovingThings::StartCloseList;
Num = 0;
-
+
+#ifndef MIAMI // something is still used here actually
// Initialize scroll bars
aScrollBars[0].Init(CVector( 228.3f, -669.0f, 39.0f ), SCROLL_BUSINESS, 0.0f, 0.5f, 0.5f, 255, 128, 0, 0.3f);
aScrollBars[1].Init(CVector( 772.0f, 164.0f, -9.5f ), SCROLL_TRAFFIC, 0.0f, 0.5f, 0.25f, 128, 255, 0, 0.3f);
@@ -137,6 +138,7 @@ void CMovingThings::Init()
CVector(58.145f - sz.y * 0.05f - sz.x * 0.3f, -1079.268f + sz.x * 0.05f - sz.y * 0.3f, 32.803f),
-sz.x, -sz.y, 0, 255, 0, 100.0f, 0.8f
);
+#endif
}
void CMovingThings::Shutdown()
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index 8c7904ef..7289d70c 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -23,18 +23,20 @@
// 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 RADARDISC_COLOR(255, 255, 255, 255);
CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255);
CRGBA WASTEDBUSTED_COLOR(170, 123, 87, 255);
CRGBA ODDJOB_COLOR(89, 115, 150, 255);
@@ -86,6 +88,21 @@ float CHud::PagerXOffset;
int16 CHud::PagerTimer;
int16 CHud::PagerOn;
+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;
+
CSprite2d CHud::Sprites[NUM_HUD_SPRITES];
struct
@@ -123,6 +140,10 @@ RwTexture *gpRocketSightTex;
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;
@@ -134,22 +155,29 @@ void CHud::Draw()
bool DrawCrossHair = 0;
bool DrawCrossHairPC = 0;
- int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType;
+ CPlayerPed *playerPed = FindPlayerPed();
+ eWeaponType WeaponType = playerPed->GetWeapon()->m_eWeaponType;
int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
- if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON)
- DrawCrossHair = 1;
- if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
- DrawCrossHairPC = 1;
+ // TODO(Miami): New cam mode
+ if ((Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON/* || Mode == 46*/)
+ && playerPed && !playerPed->GetWeapon()->IsTypeMelee())
+ DrawCrossHair = 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 = 1;
+ if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
+ 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) {
+
+ // TODO(Miami): Uncomment
+ if (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_AK47
+ /*|| WeaponType == WEAPONTYPE_M60 || || WeaponType == WEAPONTYPE_MINIGUN */
+ || WeaponType == WEAPONTYPE_FLAMETHROWER) {
+ DrawCrossHairPC = 1;
+ }
+ }
}
}
@@ -169,7 +197,8 @@ void CHud::Draw()
#ifdef ASPECT_RATIO_SCALE
f3rdY -= SCREEN_SCALE_Y(2.0f);
#endif
- if (FindPlayerPed() && WeaponType == WEAPONTYPE_M16) {
+ // TODO(Miami): M60
+ if (playerPed && (WeaponType == WEAPONTYPE_M16 || WeaponType == WEAPONTYPE_AK47/* || 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);
@@ -185,8 +214,7 @@ void CHud::Draw()
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255));
}
- }
- else {
+ } else {
if (Mode == CCam::MODE_M16_1STPERSON ||
Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
Mode == CCam::MODE_HELICANNON_1STPERSON) {
@@ -213,8 +241,11 @@ void CHud::Draw()
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex));
CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
}
else {
+
+ // TODO(Miami)
// Sniper
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(210.0f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(210.0f);
@@ -241,9 +272,9 @@ void CHud::Draw()
Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255));
}
}
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
else {
SpriteBrightness = 0;
@@ -252,35 +283,51 @@ void CHud::Draw()
/*
DrawMoneyCounter
*/
+
wchar sPrint[16];
wchar sPrintIcon[16];
char sTemp[16];
+ float alpha;
- sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
- AsciiToUnicode(sTemp, sPrint);
-
- CFont::SetPropOff();
- CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
- CFont::SetCentreOff();
- CFont::SetRightJustifyOn();
- CFont::SetRightJustifyWrap(0.0f);
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_HEADING);
- CFont::SetPropOff();
- CFont::SetColor(CRGBA(0, 0, 0, 255));
-
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(43.0f + 2.0f), sPrint);
+ if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) {
+ alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 0);
+ } else {
+ alpha = CHud::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::SetColor(MONEY_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), 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);
+
+ // TODO(Miami): m_nHudMode
+ //if (CMenuManager.m_nHudMode)
+ {
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint);
+ }
+ }
/*
DrawAmmo
*/
- uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition;
- uint32 AmmoInClip = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoInClip;
- uint32 TotalAmmo = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_nAmmoTotal;
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType);
+ CWeapon *weapon = playerPed->GetWeapon();
+ uint32 AmmoAmount = weaponInfo->m_nAmountofAmmunition;
+ uint32 AmmoInClip = weapon->m_nAmmoInClip;
+ uint32 TotalAmmo = weapon->m_nAmmoTotal;
uint32 Ammo, Clip;
if (AmmoAmount <= 1 || AmmoAmount >= 1000)
@@ -311,36 +358,59 @@ void CHud::Draw()
/*
DrawWeaponIcon
*/
- Sprites[WeaponType].Draw(
- CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)),
- CRGBA(255, 255, 255, 255),
- 0.015f,
- 0.015f,
- 1.0f,
- 0.0f,
- 0.015f,
- 1.0f,
- 1.0f,
- 1.0f);
+
+ if (weaponInfo->m_nModelId <= 0) {
+ Sprites[WeaponType].Draw(
+ CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)),
+ CRGBA(255, 255, 255, 255),
+ 0.015f,
+ 0.015f,
+ 1.0f,
+ 0.0f,
+ 0.015f,
+ 1.0f,
+ 1.0f,
+ 1.0f);
+ } else {
+ CBaseModelInfo *weaponModel = CModelInfo::GetModelInfo(weaponInfo->m_nModelId);
+ RwTexDictionary *weaponTxd = CTxdStore::GetSlot(weaponModel->GetTxdSlot())->texDict;
+ if (weaponTxd) {
+ RwTexture *weaponIcon = RwTexDictionaryFindNamedTexture(weaponTxd, weaponModel->GetName());
+ if (weaponIcon) {
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon));
+ const float xSize = SCREEN_SCALE_X(64.0f / 2.0f);
+ const float ySize = SCREEN_SCALE_X(64.0f / 2.0f);
+ CSprite::RenderOneXLUSprite(SCREEN_SCALE_FROM_RIGHT(99.0f) + xSize, SCREEN_SCALE_Y(25.0f) + ySize, 1.0f, xSize, ySize,
+ 255, 255, 255, 255, 1.0f, 255);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ }
+ }
+ }
CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f));
+ CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f));
CFont::SetJustifyOff();
CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_SCALE_X(640.0f));
CFont::SetPropOn();
+ CFont::SetDropShadowPosition(0);
CFont::SetFontStyle(FONT_BANK);
- if (!CDarkel::FrenzyOnGoing() && WeaponType != WEAPONTYPE_UNARMED && WeaponType != WEAPONTYPE_BASEBALLBAT) {
+ 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, 255));
CFont::SetColor(AMMO_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(73.0f), sPrint);
+ 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::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetJustifyOff();
CFont::SetCentreOff();
CFont::SetRightJustifyWrap(0.0f);
@@ -350,16 +420,16 @@ void CHud::Draw()
if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8
|| m_ItemToFlash != ITEM_HEALTH
- || FindPlayerPed()->m_fHealth < 10
+ || playerPed->m_fHealth < 10
&& CTimer::GetFrameCounter() & 8) {
- if (FindPlayerPed()->m_fHealth >= 10
- || FindPlayerPed()->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) {
+ if (playerPed->m_fHealth >= 10
+ || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 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);
@@ -383,13 +453,13 @@ void CHud::Draw()
DrawArmour
*/
if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) {
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
- if (FindPlayerPed()->m_fArmour > 1.0f) {
+ 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);
@@ -414,27 +484,33 @@ void CHud::Draw()
DrawWantedLevel
*/
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::SetJustifyOff();
CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
+ CFont::SetRightJustifyOn();
CFont::SetPropOn();
CFont::SetFontStyle(FONT_HEADING);
+ CFont::SetDropShadowPosition(2); // TODO(Miami): Remove that, VC keeps that open above
AsciiToUnicode("]", sPrintIcon);
for (int i = 0; i < 6; i++) {
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString(2.0f + SCREEN_SCALE_FROM_RIGHT(60.0f - 2.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f + 2.0f), sPrintIcon);
- if (FindPlayerPed()->m_pWanted->m_nWantedLevel > i
- && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange
+ if (playerPed->m_pWanted->m_nWantedLevel > i
+ && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange
+ 2000 || CTimer::GetFrameCounter() & 4)) {
CFont::SetColor(WANTED_COLOR);
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(60.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
+
+ // TODO(Miami): There is one more condition in here
+ }else if (playerPed->m_pWanted->m_nWantedLevel <= i) {
+ CFont::SetColor(NOTWANTED_COLOR);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);
}
}
+ CFont::SetDropShadowPosition(0); // TODO(Miami): Remove that, VC keeps that open
+
/*
DrawZoneName
*/
@@ -517,15 +593,20 @@ void CHud::Draw()
else
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
+ 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::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint);
CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint);
+
+ CFont::SetSlant(0.f);
}
}
}
@@ -611,15 +692,20 @@ void CHud::Draw()
else
CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f));
+ CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f));
+ CFont::SetSlant(0.15f);
+
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(105.f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint);
CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f), m_pVehicleNameToPrint);
+
+ CFont::SetSlant(0.f);
}
}
}
@@ -636,7 +722,7 @@ void CHud::Draw()
CFont::SetJustifyOff();
CFont::SetCentreOff();
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::SetBackGroundOnlyTextOff();
CFont::SetPropOff();
CFont::SetFontStyle(FONT_HEADING);
@@ -685,7 +771,7 @@ void CHud::Draw()
AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, 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));
@@ -693,7 +779,7 @@ void CHud::Draw()
CFont::SetBackGroundOnlyTextOn();
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer);
- CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
+ CFont::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);
@@ -725,7 +811,7 @@ void CHud::Draw()
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::SetCentreOff();
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
@@ -751,7 +837,7 @@ void CHud::Draw()
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) {
CFont::SetPropOn();
- 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::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText));
@@ -1417,6 +1503,21 @@ void CHud::Initialise()
PagerSoundPlayed = 0;
PagerXOffset = 150.0f;
+ m_WantedFadeTimer = 0;
+ m_WantedState = FADE_DISABLED;
+ m_WantedTimer = 0;
+ m_EnergyLostFadeTimer = 0;
+ m_EnergyLostState = FADE_DISABLED;
+ m_EnergyLostTimer = 0;
+ m_DisplayScoreFadeTimer = 0;
+ m_DisplayScoreState = FADE_DISABLED;
+ m_DisplayScoreTimer = 0;
+ m_WeaponFadeTimer = 0;
+ m_WeaponState = FADE_DISABLED;
+ m_WeaponTimer = 0;
+
+ m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
+
CTxdStore::PopCurrentTxd();
}
@@ -1440,6 +1541,21 @@ void CHud::ReInitialise() {
PagerTimer = 0;
PagerSoundPlayed = 0;
PagerXOffset = 150.0f;
+
+ m_WantedFadeTimer = 0;
+ m_WantedState = FADE_DISABLED;
+ m_WantedTimer = 0;
+ m_EnergyLostFadeTimer = 0;
+ m_EnergyLostState = FADE_DISABLED;
+ m_EnergyLostTimer = 0;
+ m_DisplayScoreFadeTimer = 0;
+ m_DisplayScoreState = FADE_DISABLED;
+ m_DisplayScoreTimer = 0;
+ m_WeaponFadeTimer = 0;
+ m_WeaponState = FADE_DISABLED;
+ m_WeaponTimer = 0;
+
+ m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
}
wchar LastBigMessage[6][128];
@@ -1536,3 +1652,106 @@ void CHud::Shutdown()
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);
+}
diff --git a/src/render/Hud.h b/src/render/Hud.h
index 701e47e2..bae19ee4 100644
--- a/src/render/Hud.h
+++ b/src/render/Hud.h
@@ -9,6 +9,25 @@ 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,
@@ -32,6 +51,10 @@ enum eSprites
NUM_HUD_SPRITES,
};
+// TODO(Miami): Make those 0.7f - 1.25f once fonts have been ported
+#define HUD_TEXT_SCALE_X 0.8f
+#define HUD_TEXT_SCALE_Y 1.35f
+
class CHud
{
public:
@@ -82,6 +105,21 @@ public:
static int16 PagerTimer;
static int16 PagerOn;
+ static uint32 m_WantedFadeTimer;
+ static uint32 m_WantedState;
+ static uint32 m_WantedTimer;
+ static uint32 m_EnergyLostFadeTimer;
+ static uint32 m_EnergyLostState;
+ static uint32 m_EnergyLostTimer;
+ static uint32 m_DisplayScoreFadeTimer;
+ static uint32 m_DisplayScoreState;
+ static uint32 m_DisplayScoreTimer;
+ static uint32 m_WeaponFadeTimer;
+ static uint32 m_WeaponState;
+ static uint32 m_WeaponTimer;
+
+ static uint32 m_LastDisplayScore;
+
public:
static void Draw();
static void DrawAfterFade();
@@ -95,4 +133,5 @@ public:
static void SetVehicleName(wchar *name);
static void SetZoneName(wchar *name);
static void Shutdown();
+ static float DrawFadeState(DRAW_FADE_STATE, int);
};
diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp
index 68ec1194..9934ae18 100644
--- a/src/render/MBlur.cpp
+++ b/src/render/MBlur.cpp
@@ -3,14 +3,17 @@
#include "RwHelper.h"
#include "Camera.h"
#include "MBlur.h"
+#include "Timer.h"
// Originally taken from RW example 'mblur'
RwRaster *CMBlur::pFrontBuffer;
bool CMBlur::ms_bJustInitialised;
bool CMBlur::BlurOn;
+float CMBlur::Drunkness;
static RwIm2DVertex Vertex[4];
+static RwIm2DVertex Vertex2[4];
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
void
@@ -103,29 +106,62 @@ CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect)
RwIm2DVertexSetV(&Vertex[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[0], zero);
+ RwIm2DVertexSetScreenY(&Vertex2[0], zero);
+ 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], zero);
+ RwIm2DVertexSetScreenY(&Vertex2[1], ymax);
+ 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);
+ RwIm2DVertexSetScreenY(&Vertex2[2], ymax);
+ 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);
+ RwIm2DVertexSetScreenY(&Vertex2[3], zero);
+ 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::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 addalpha)
+CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type)
{
RwRGBA color = { (RwUInt8)red, (RwUInt8)green, (RwUInt8)blue, (RwUInt8)blur };
+ if(ms_bJustInitialised)
+ ms_bJustInitialised = false;
+ else
+ OverlayRender(cam, pFrontBuffer, color, type);
if(BlurOn){
- if(pFrontBuffer){
- if(ms_bJustInitialised)
- ms_bJustInitialised = false;
- else
- OverlayRender(cam, pFrontBuffer, color, type, addalpha);
- }
RwRasterPushContext(pFrontBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext();
- }else{
- OverlayRender(cam, nil, color, type, addalpha);
}
}
void
-CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, uint32 addalpha)
+CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type)
{
int r, g, b, a;
@@ -170,41 +206,75 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type,
}
if(!BlurOn){
- r *= 0.6f;
- g *= 0.6f;
- b *= 0.6f;
- if(type != 1)
- a *= 0.6f;
- // 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 == MBLUR_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);
-
- a = addalpha/2;
- if(a < 30)
- a = 30;
-
- 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);
- RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
+ if(BlurOn){
+ if(type == MBLUR_SNIPER){
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, 80);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ // TODO(MIAMI): pBufVertCount = 0;
+ }else{
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r*2, g*2, b*2, 30);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6);
+
+ 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);
+ }
}
+ // TODO(MIAMI): drunkness
+
+ // TODO(MIAMI): OverlayRenderFx
+
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
@@ -213,3 +283,10 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type,
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}
+
+void
+CMBlur::ClearDrunkBlur()
+{
+ Drunkness = 0.0f;
+ CTimer::SetTimeScale(1.0f);
+} \ No newline at end of file
diff --git a/src/render/MBlur.h b/src/render/MBlur.h
index e8a5bef8..3129c070 100644
--- a/src/render/MBlur.h
+++ b/src/render/MBlur.h
@@ -6,11 +6,13 @@ public:
static RwRaster *pFrontBuffer;
static bool ms_bJustInitialised;
static bool BlurOn;
+ static float Drunkness;
public:
static void MotionBlurOpen(RwCamera *cam);
static void MotionBlurClose(void);
static void CreateImmediateModeData(RwCamera *cam, RwRect *rect);
- static void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 addalpha);
- static void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, uint32 bluralpha);
+ static void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type);
+ static void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type);
+ static void ClearDrunkBlur();
};
diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp
new file mode 100644
index 00000000..1c4e4266
--- /dev/null
+++ b/src/render/Occlusion.cpp
@@ -0,0 +1,44 @@
+#include "common.h"
+
+#include "Occlusion.h"
+
+int32 COcclusion::NumOccludersOnMap;
+int16 COcclusion::FarAwayList;
+int16 COcclusion::NearbyList;
+int16 COcclusion::ListWalkThroughFA;
+int16 COcclusion::PreviousListWalkThroughFA;
+COccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES];
+
+void
+COcclusion::Init(void)
+{
+ NumOccludersOnMap = 0;
+ 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 * UINT16_MAX/360.0f;
+ aOccluders[NumOccludersOnMap].listIndex = FarAwayList;
+ FarAwayList = NumOccludersOnMap++;
+}
+
+void
+COcclusion::ProcessBeforeRendering(void)
+{
+}
diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h
new file mode 100644
index 00000000..ac0ede5e
--- /dev/null
+++ b/src/render/Occlusion.h
@@ -0,0 +1,26 @@
+#pragma once
+
+class COccluder
+{
+public:
+ int16 width, length, height;
+ int16 x, y, z;
+ uint16 angle;
+ int16 listIndex;
+};
+
+class COcclusion
+{
+public:
+ static int32 NumOccludersOnMap;
+ static int16 FarAwayList;
+ static int16 NearbyList;
+ static int16 ListWalkThroughFA;
+ static int16 PreviousListWalkThroughFA;
+
+ static COccluder aOccluders[NUMOCCLUSIONVOLUMES];
+
+ 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);
+};
diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp
index a867ae13..5f37bdc6 100644
--- a/src/render/Particle.cpp
+++ b/src/render/Particle.cpp
@@ -1546,7 +1546,7 @@ void CParticle::Render()
particle->m_fSize * 63.0f,
particle->m_Color,
particle->m_nColorIntensity,
- (float)particle->m_nRotation, //DEGTORAD((float)particle->m_nRotation) ps2
+ DEGTORAD(particle->m_nRotation),
particle->m_nAlpha);
}
else
@@ -1586,7 +1586,7 @@ void CParticle::Render()
particle->m_Color.blue,
particle->m_nColorIntensity,
1.0f / coors.z,
- float(particle->m_nRotation), // DEGTORAD((float)particle->m_nRotation) ps2
+ DEGTORAD(particle->m_nRotation),
particle->m_nAlpha);
}
else if ( psystem->Flags & SCREEN_TRAIL )
@@ -1639,7 +1639,7 @@ void CParticle::Render()
particle->m_Color.blue,
particle->m_nColorIntensity,
1.0f / coors.z,
- fRotation,
+ DEGTORAD(fRotation),
particle->m_nAlpha);
particle->m_vecScreenPosition = coors;
@@ -1688,7 +1688,7 @@ void CParticle::Render()
particle->m_Color.blue,
particle->m_nColorIntensity,
1.0f / coors.z,
- fRotation,
+ DEGTORAD(fRotation),
particle->m_nAlpha);
}
else if ( psystem->Flags & VERT_TRAIL )
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 8a48eb11..f149c6fb 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -18,13 +18,13 @@
#include "Streaming.h"
#include "Shadows.h"
#include "PointLights.h"
+#include "Occlusion.h"
#include "Renderer.h"
-bool gbShowPedRoadGroups;
-bool gbShowCarRoadGroups;
+//--MIAMI: file almost done, just one bike flag left
+
bool gbShowCollisionPolys;
bool gbShowCollisionLines;
-bool gbShowCullZoneDebugStuff;
bool gbBigWhiteDebugLightSwitchedOn;
bool gbDontRenderBuildings;
@@ -142,8 +142,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()){
@@ -153,6 +156,7 @@ CRenderer::RenderOneNonRoad(CEntity *e)
for(i = 0; i < 8; i++)
if(veh->pPassengers[i] && veh->pPassengers[i]->m_nPedState == PED_DRIVING)
veh->pPassengers[i]->Render();
+ SetCullMode(rwCULLMODECULLNONE);
}
e->Render();
@@ -160,6 +164,7 @@ CRenderer::RenderOneNonRoad(CEntity *e)
e->bImBeingRendered = true;
CVisibilityPlugins::RenderAlphaAtomics();
e->bImBeingRendered = false;
+ SetCullMode(rwCULLMODECULLBACK);
}
e->RemoveLighting(resetLights);
@@ -180,38 +185,40 @@ CRenderer::RenderFirstPersonVehicle(void)
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
}
+inline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CSimpleModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->m_wetRoadReflection; }
+
void
CRenderer::RenderRoads(void)
{
int i;
- CTreadable *t;
+ CEntity *e;
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
DeActivateDirectional();
SetAmbientColours();
for(i = 0; i < ms_nNoOfVisibleEntities; i++){
- t = (CTreadable*)ms_aVisibleEntityPtrs[i];
- if(t->IsBuilding() && t->GetIsATreadable()){
-#ifndef MASTER
- if(gbShowCarRoadGroups || gbShowPedRoadGroups){
- int ind = 0;
- if(gbShowCarRoadGroups)
- ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_CAR][0]].group;
- if(gbShowPedRoadGroups)
- ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group;
- SetAmbientColoursToIndicateRoadGroup(ind);
- }
-#endif
- RenderOneRoad(t);
-#ifndef MASTER
- if(gbShowCarRoadGroups || gbShowPedRoadGroups)
- ReSetAmbientAndDirectionalColours();
-#endif
- }
+ e = ms_aVisibleEntityPtrs[i];
+ if(IsRoad(e))
+ RenderOneRoad(e);
}
}
+inline bool PutIntoSortedVehicleList(CVehicle *veh)
+{
+ if(veh->IsBoat()){
+ int mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
+ if(mode == CCam::MODE_WHEELCAM ||
+ mode == CCam::MODE_1STPERSON && TheCamera.GetLookDirection() != LOOKING_FORWARD && TheCamera.GetLookDirection() != LOOKING_BEHIND ||
+ CVisibilityPlugins::GetClumpAlpha(veh->GetClump()) != 255)
+ return false;
+ return true;
+ }else
+ return veh->bTouchingWater;
+}
+
void
CRenderer::RenderEverythingBarRoads(void)
{
@@ -220,17 +227,20 @@ CRenderer::RenderEverythingBarRoads(void)
CVector dist;
EntityInfo ei;
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
gSortedVehiclesAndPeds.Clear();
for(i = 0; i < ms_nNoOfVisibleEntities; i++){
e = ms_aVisibleEntityPtrs[i];
- if(e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable())
+ if(IsRoad(e))
continue;
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();
@@ -248,27 +258,14 @@ CRenderer::RenderEverythingBarRoads(void)
}
void
-CRenderer::RenderVehiclesButNotBoats(void)
-{
- // This function doesn't do anything
- // because only boats are inserted into the list
- CLink<EntityInfo> *node;
-
- for(node = gSortedVehiclesAndPeds.tail.prev;
- node != &gSortedVehiclesAndPeds.head;
- node = node->prev){
- // only boats in this list
- CVehicle *v = (CVehicle*)node->item.ent;
- if(!v->IsBoat())
- RenderOneNonRoad(v);
- }
-}
-
-void
CRenderer::RenderBoats(void)
{
CLink<EntityInfo> *node;
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
+
for(node = gSortedVehiclesAndPeds.tail.prev;
node != &gSortedVehiclesAndPeds.head;
node = node->prev){
@@ -283,12 +280,22 @@ void
CRenderer::RenderFadingInEntities(void)
{
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ SetCullMode(rwCULLMODECULLBACK);
DeActivateDirectional();
SetAmbientColours();
CVisibilityPlugins::RenderFadingEntities();
}
void
+CRenderer::RenderFadingInUnderwaterEntities(void)
+{
+ DeActivateDirectional();
+ SetAmbientColours();
+ CVisibilityPlugins::RenderFadingUnderwaterEntities();
+}
+
+void
CRenderer::RenderCollisionLines(void)
{
int i;
@@ -332,7 +339,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())){
@@ -348,25 +355,36 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
request = false;
}
}else{
- if (mi->GetModelType() != MITYPE_SIMPLE) {
+ if(mi->GetModelType() != MITYPE_SIMPLE && mi->GetModelType() != MITYPE_WEAPON){
if(FindPlayerVehicle() == ent &&
- TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){
+ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON &&
+//TODO(MIAMI): that bike flag
+ (!FindPlayerVehicle()->IsBike() || true)){
// 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();
@@ -376,22 +394,36 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
}
return VIS_VISIBLE;
}
- if(ent->IsObject() &&
- ((CObject*)ent)->ObjectCreatedBy == TEMP_OBJECT){
+ if(ent->m_flagE10){
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.
+ if(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE)
+ dist += mi->GetLargestLodDistance() - LOD_DISTANCE;
+#endif
if(ent->IsObject() && ent->bRenderDamaged)
mi->m_isDamaged = true;
@@ -411,7 +443,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;
}
@@ -423,9 +455,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;
}
@@ -461,7 +494,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{
@@ -474,19 +507,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();
@@ -495,7 +541,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)
@@ -503,7 +549,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())
@@ -511,7 +557,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
}
}
- RpAtomic *a = mi->GetAtomicFromDistance(dist);
+ RpAtomic *a = mi->GetFirstAtomicFromDistance(dist);
if(a){
if(ent->m_rwObject == nil)
ent->CreateRwObject();
@@ -522,8 +568,18 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
// that of an atomic for another draw distance.
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- if(!ent->IsVisibleComplex())
+ mi->IncreaseAlpha();
+ if(!ent->IsVisibleComplex() || ent->IsEntityOccluded()){
+ mi->m_alpha = 255;
return VIS_INVISIBLE;
+ }
+
+ if(mi->m_alpha != 255){
+ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ ent->bDistanceFade = true;
+ return VIS_INVISIBLE;
+ }
+
if(mi->m_drawLast){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = false;
@@ -539,10 +595,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...
@@ -552,14 +612,21 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- if(ent->IsVisibleComplex())
- CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ mi->IncreaseAlpha();
+ if(!ent->IsVisibleComplex() || ent->IsEntityOccluded()){
+ mi->m_alpha = 255;
+ return VIS_INVISIBLE;
+ }
+ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
+ ent->bDistanceFade = true;
return VIS_INVISIBLE;
}
void
CRenderer::ConstructRenderList(void)
{
+ COcclusion::ProcessBeforeRendering();
+
ms_nNoOfVisibleEntities = 0;
ms_nNoOfInVisibleEntities = 0;
ms_vecCameraPosition = TheCamera.GetPosition();
@@ -619,6 +686,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;
@@ -664,6 +740,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);
@@ -673,7 +750,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){
poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);
poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y);
@@ -701,7 +780,7 @@ CRenderer::ScanWorld(void)
}
ScanSectorPoly(poly, 3, ScanSectorList);
- ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory));
+ ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel));
ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_NONE));
}
}
@@ -733,6 +812,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
@@ -945,11 +1025,26 @@ CRenderer::ScanBigBuildingList(CPtrList &list)
{
CPtrNode *node;
CEntity *ent;
+ int vis;
+ int f = CTimer::GetFrameCounter() & 3;
for(node = list.first; node; node = node->next){
ent = (CEntity*)node->item;
- if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE)
+ if(ent->bOffscreen || (ent->m_randomSeed&3) != f){
+ ent->bOffscreen = true;
+ vis = SetupBigBuildingVisibility(ent);
+ }else
+ vis = VIS_VISIBLE;
+ switch(vis){
+ case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ ent->bOffscreen = false;
+ break;
+ case VIS_STREAMME:
+ if(!CStreaming::ms_disableStreaming)
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ break;
+ }
}
}
@@ -969,35 +1064,30 @@ CRenderer::ScanSectorList(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
+ ent->bOffscreen = false;
- if(IsEntityCullZoneVisible(ent))
- switch(SetupEntityVisibility(ent)){
- case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
- break;
- case VIS_INVISIBLE:
- if(!IsGlass(ent->GetModelIndex()))
- break;
- // fall through
- case VIS_OFFSCREEN:
- dx = ms_vecCameraPosition.x - ent->GetPosition().x;
- dy = ms_vecCameraPosition.y - ent->GetPosition().y;
- if(dx > -65.0f && dx < 65.0f &&
- dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
- ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
- break;
- case VIS_STREAMME:
- if(!CStreaming::ms_disableStreaming)
- if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ switch(SetupEntityVisibility(ent)){
+ case VIS_VISIBLE:
+ ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ break;
+ case VIS_INVISIBLE:
+ if(!IsGlass(ent->GetModelIndex()))
break;
- }
- else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
+ // fall through
+ case VIS_OFFSCREEN:
+ ent->bOffscreen = true;
+ dx = ms_vecCameraPosition.x - ent->GetPosition().x;
+ dy = ms_vecCameraPosition.y - ent->GetPosition().y;
+ if(dx > -30.0f && dx < 30.0f &&
+ dy > -30.0f && dy < 30.0f &&
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
+ ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
+ break;
+ case VIS_STREAMME:
if(!CStreaming::ms_disableStreaming)
- if(SetupEntityVisibility(ent) == VIS_STREAMME)
- if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ break;
}
}
}
@@ -1019,41 +1109,38 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
+ ent->bOffscreen = false;
- if(IsEntityCullZoneVisible(ent))
- switch(SetupEntityVisibility(ent)){
- case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
- break;
- case VIS_INVISIBLE:
- if(!IsGlass(ent->GetModelIndex()))
- break;
- // fall through
- case VIS_OFFSCREEN:
- dx = ms_vecCameraPosition.x - ent->GetPosition().x;
- dy = ms_vecCameraPosition.y - ent->GetPosition().y;
- if(dx > -65.0f && dx < 65.0f &&
- dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
- ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
- break;
- case VIS_STREAMME:
- if(!CStreaming::ms_disableStreaming){
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
- if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)
- m_loadingPriority = true;
- }
+ switch(SetupEntityVisibility(ent)){
+ case VIS_VISIBLE:
+ ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ break;
+ case VIS_INVISIBLE:
+ if(!IsGlass(ent->GetModelIndex()))
break;
+ // fall through
+ case VIS_OFFSCREEN:
+ ent->bOffscreen = true;
+ dx = ms_vecCameraPosition.x - ent->GetPosition().x;
+ dy = ms_vecCameraPosition.y - ent->GetPosition().y;
+ if(dx > -30.0f && dx < 30.0f &&
+ dy > -30.0f && dy < 30.0f &&
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
+ ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
+ break;
+ case VIS_STREAMME:
+ if(!CStreaming::ms_disableStreaming){
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ if(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)
+ m_loadingPriority = true;
}
- else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
- if(!CStreaming::ms_disableStreaming)
- if(SetupEntityVisibility(ent) == VIS_STREAMME)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ break;
}
}
}
}
+#ifdef GTA_TRAIN
void
CRenderer::ScanSectorList_Subway(CPtrList *lists)
{
@@ -1070,15 +1157,17 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists)
if(ent->m_scanCode == CWorld::GetCurrentScanCode())
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
+ ent->bOffscreen = false;
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
break;
case VIS_OFFSCREEN:
+ ent->bOffscreen = true;
dx = ms_vecCameraPosition.x - ent->GetPosition().x;
dy = ms_vecCameraPosition.y - ent->GetPosition().y;
- if(dx > -65.0f && dx < 65.0f &&
- dy > -65.0f && dy < 65.0f &&
+ if(dx > -30.0f && dx < 30.0f &&
+ dy > -30.0f && dy < 30.0f &&
ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
break;
@@ -1086,6 +1175,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists)
}
}
}
+#endif
void
CRenderer::ScanSectorList_RequestModels(CPtrList *lists)
@@ -1102,8 +1192,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);
}
}
@@ -1138,70 +1227,29 @@ CRenderer::SortBIGBuildingsForSectorList(CPtrList *list)
}
bool
-CRenderer::ShouldModelBeStreamed(CEntity *ent)
+CRenderer::ShouldModelBeStreamed(CEntity *ent, const CVector &campos)
{
- CSimpleModelInfo *mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());
- float dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
+ if(!IsAreaVisible(ent->m_area))
+ return false;
+ CTimeModelInfo *mi = (CTimeModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());
+ if(mi->GetModelType() == MITYPE_TIME)
+ if(!CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))
+ return false;
+ float dist = (ent->GetPosition() - campos).Magnitude();
if(mi->m_noFade)
return dist - STREAM_DISTANCE < mi->GetLargestLodDistance();
else
return dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance();
}
-bool
-CRenderer::IsEntityCullZoneVisible(CEntity *ent)
-{
- CPed *ped;
- CObject *obj;
-
- if(ent->bZoneCulled)
- return false;
-
- switch(ent->GetType()){
- case ENTITY_TYPE_VEHICLE:
- return IsVehicleCullZoneVisible(ent);
- case ENTITY_TYPE_PED:
- ped = (CPed*)ent;
- if (ped->bInVehicle) {
- if (ped->m_pMyVehicle)
- return IsVehicleCullZoneVisible(ped->m_pMyVehicle);
- else
- return true;
- }
- return !(ped->m_pCurSurface && ped->m_pCurSurface->bZoneCulled2);
- case ENTITY_TYPE_OBJECT:
- obj = (CObject*)ent;
- if(!obj->IsStatic())
- return true;
- return !(obj->m_pCurSurface && obj->m_pCurSurface->bZoneCulled2);
- default: break;
- }
- return true;
-}
-
-bool
-CRenderer::IsVehicleCullZoneVisible(CEntity *ent)
-{
- CVehicle *v = (CVehicle*)ent;
- switch(v->GetStatus()) {
- case STATUS_SIMPLE:
- case STATUS_PHYSICS:
- case STATUS_ABANDONED:
- case STATUS_WRECKED:
- return !(v->m_pCurGroundEntity && v->m_pCurGroundEntity->bZoneCulled2);
- default: break;
- }
- return true;
-}
-
void
CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset)
{
- if(ent->bRenderScorched){
- WorldReplaceScorchedLightsWithNormal(Scene.world);
- return;
+ if(!ent->bRenderScorched){
+ CPointLights::RemoveLightsAffectingObject();
+ if(reset)
+ ReSetAmbientAndDirectionalColours();
}
- CPointLights::RemoveLightsAffectingObject();
- if(reset)
- ReSetAmbientAndDirectionalColours();
+ SetAmbientColours();
+ DeActivateDirectional();
}
diff --git a/src/render/Renderer.h b/src/render/Renderer.h
index 362741e3..e9f82078 100644
--- a/src/render/Renderer.h
+++ b/src/render/Renderer.h
@@ -2,11 +2,8 @@
class CEntity;
-extern bool gbShowPedRoadGroups;
-extern bool gbShowCarRoadGroups;
extern bool gbShowCollisionPolys;
extern bool gbShowCollisionLines;
-extern bool gbShowCullZoneDebugStuff;
extern bool gbBigWhiteDebugLightSwitchedOn;
extern bool gbDontRenderBuildings;
@@ -38,8 +35,8 @@ public:
static void RenderRoads(void);
static void RenderFadingInEntities(void);
+ static void RenderFadingInUnderwaterEntities(void);
static void RenderEverythingBarRoads(void);
- static void RenderVehiclesButNotBoats(void);
static void RenderBoats(void);
static void RenderOneRoad(CEntity *);
static void RenderOneNonRoad(CEntity *);
@@ -63,9 +60,7 @@ public:
static void SortBIGBuildings(void);
static void SortBIGBuildingsForSectorList(CPtrList *list);
- static bool ShouldModelBeStreamed(CEntity *ent);
- static bool IsEntityCullZoneVisible(CEntity *ent);
- static bool IsVehicleCullZoneVisible(CEntity *ent);
+ static bool ShouldModelBeStreamed(CEntity *ent, const CVector &campos);
static void RemoveVehiclePedLights(CEntity *ent, bool reset);
};
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index 5d521041..7f057319 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/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++){
@@ -54,17 +50,7 @@ void
CSkidmarks::Shutdown(void)
{
RwTextureDestroy(gpSkidTex);
-#ifdef GTA3_1_1_PATCH
gpSkidTex = nil;
-#endif
- RwTextureDestroy(gpSkidBloodTex);
-#ifdef GTA3_1_1_PATCH
- gpSkidBloodTex = nil;
-#endif
- RwTextureDestroy(gpSkidMudTex);
-#ifdef GTA3_1_1_PATCH
- gpSkidMudTex = nil;
-#endif
}
void
@@ -116,33 +102,23 @@ void
CSkidmarks::Render(void)
{
int i, j;
- RwTexture *lastTex = nil;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));
for(i = 0; i < NUMSKIDMARKS; i++){
if(aSkidmarks[i].m_state == 0 || aSkidmarks[i].m_last < 1)
continue;
- if(aSkidmarks[i].m_isBloody){
- if(lastTex != gpSkidBloodTex){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidBloodTex));
- lastTex = gpSkidBloodTex;
- }
- }else if(aSkidmarks[i].m_isMuddy){
- if(lastTex != gpSkidMudTex){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidMudTex));
- lastTex = gpSkidMudTex;
- }
- }else{
- if(lastTex != gpSkidTex){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));
- lastTex = gpSkidTex;
- }
- }
+ CRGBA color(0, 0, 0, 255);
+ // TODO(MIAMI): we have a type field here actually (0-3)
+ if(aSkidmarks[i].m_isBloody) // TODO: type 3
+ color = CRGBA(132, 34, 11, 255);
+ else if(aSkidmarks[i].m_isMuddy) // TODO: type 1
+ color = CRGBA(90, 62, 9, 255);
uint32 fade, alpha;
if(aSkidmarks[i].m_state == 1 || CTimer::GetTimeInMilliseconds() < aSkidmarks[i].m_fadeStart)
@@ -158,9 +134,9 @@ CSkidmarks::Render(void)
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);
+ 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);
+ 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);
}
diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp
index 1dd1aaab..9631aced 100644
--- a/src/render/Sprite.cpp
+++ b/src/render/Sprite.cpp
@@ -267,8 +267,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];
@@ -580,8 +580,8 @@ CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w
{
m_bFlushSpriteBufferSwitchZTest = 1;
CRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha);
- float c = Cos(DEGTORAD(rotation));
- float s = Sin(DEGTORAD(rotation));
+ float c = Cos(rotation);
+ float s = Sin(rotation);
Set6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex],
x + c*w - s*h,
diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp
index 52b85018..189c9797 100644
--- a/src/render/Sprite2d.cpp
+++ b/src/render/Sprite2d.cpp
@@ -151,7 +151,6 @@ CSprite2d::Draw(float x1, float y1, float x2, float y2, float x3, float y3, floa
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
}
-
// Arguments:
// 2---3
// | |
@@ -461,6 +460,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);
diff --git a/src/render/Sprite2d.h b/src/render/Sprite2d.h
index 0e12d441..04b40591 100644
--- a/src/render/Sprite2d.h
+++ b/src/render/Sprite2d.h
@@ -46,6 +46,8 @@ 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);
diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp
index cf3426d7..c120c003 100644
--- a/src/render/Timecycle.cpp
+++ b/src/render/Timecycle.cpp
@@ -10,9 +10,20 @@
#include "FileMgr.h"
#include "Timecycle.h"
+// TODO(MIAMI): change some of the types here
+
int CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS];
int CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
int CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
+int CTimeCycle::m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
int CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
int CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
int CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
@@ -33,7 +44,7 @@ float CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS];
float CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
short CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS];
short CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
-short CTimeCycle::m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS];
+short CTimeCycle::m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
float CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS];
float CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS];
float CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
@@ -49,11 +60,24 @@ int 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];
+float CTimeCycle::m_fWaterRed[NUMHOURS][NUMWEATHERS];
+float CTimeCycle::m_fWaterGreen[NUMHOURS][NUMWEATHERS];
+float CTimeCycle::m_fWaterBlue[NUMHOURS][NUMWEATHERS];
+float CTimeCycle::m_fWaterAlpha[NUMHOURS][NUMWEATHERS];
+
float CTimeCycle::m_fCurrentAmbientRed;
float CTimeCycle::m_fCurrentAmbientGreen;
float CTimeCycle::m_fCurrentAmbientBlue;
+float CTimeCycle::m_fCurrentAmbientRed_Obj;
+float CTimeCycle::m_fCurrentAmbientGreen_Obj;
+float CTimeCycle::m_fCurrentAmbientBlue_Obj;
+float CTimeCycle::m_fCurrentAmbientRed_Bl;
+float CTimeCycle::m_fCurrentAmbientGreen_Bl;
+float CTimeCycle::m_fCurrentAmbientBlue_Bl;
+float CTimeCycle::m_fCurrentAmbientRed_Obj_Bl;
+float CTimeCycle::m_fCurrentAmbientGreen_Obj_Bl;
+float CTimeCycle::m_fCurrentAmbientBlue_Obj_Bl;
float CTimeCycle::m_fCurrentDirectionalRed;
float CTimeCycle::m_fCurrentDirectionalGreen;
float CTimeCycle::m_fCurrentDirectionalBlue;
@@ -74,7 +98,7 @@ float CTimeCycle::m_fCurrentSpriteSize;
float CTimeCycle::m_fCurrentSpriteBrightness;
int CTimeCycle::m_nCurrentShadowStrength;
int CTimeCycle::m_nCurrentLightShadowStrength;
-int CTimeCycle::m_nCurrentTreeShadowStrength;
+int CTimeCycle::m_nCurrentPoleShadowStrength;
float CTimeCycle::m_fCurrentFogStart;
float CTimeCycle::m_fCurrentFarClip;
float CTimeCycle::m_fCurrentLightsOnGroundBrightness;
@@ -90,7 +114,10 @@ int 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;
int CTimeCycle::m_nCurrentFogColourRed;
int CTimeCycle::m_nCurrentFogColourGreen;
int CTimeCycle::m_nCurrentFogColourBlue;
@@ -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");
@@ -150,25 +181,39 @@ CTimeCycle::Initialise(void)
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;
@@ -189,7 +234,7 @@ CTimeCycle::Initialise(void)
m_fSpriteBrightness[h][w] = sprBght;
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;
@@ -205,7 +250,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;
@@ -220,7 +268,7 @@ 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);
@@ -240,16 +288,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);
@@ -264,7 +318,7 @@ CTimeCycle::Update(void)
m_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness);
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);
@@ -284,26 +338,49 @@ 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 == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL)
- TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, m_fCurrentBlurAlpha, MBLUR_NORMAL);
+ m_fCurrentWaterRed = INTERP(m_fWaterRed);
+ m_fCurrentWaterGreen = INTERP(m_fWaterGreen);
+ m_fCurrentWaterBlue = INTERP(m_fWaterBlue);
+ m_fCurrentWaterAlpha = INTERP(m_fWaterAlpha);
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 = GetSunPosition();
sunPos.x = Sin(sunAngle);
sunPos.y = 1.0f;
sunPos.z = 0.2f - Cos(sunAngle);
sunPos.Normalise();
+ // TODO(MIAMI): extra colours
+
+ if(TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL)
+ TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, 5, MBLUR_NORMAL);
+
+ m_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3;
+ m_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3;
+ m_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3;
+
+ m_fCurrentAmbientRed /= 255.0f;
+ m_fCurrentAmbientGreen /= 255.0f;
+ m_fCurrentAmbientBlue /= 255.0f;
+ m_fCurrentAmbientRed_Obj /= 255.0f;
+ m_fCurrentAmbientGreen_Obj /= 255.0f;
+ m_fCurrentAmbientBlue_Obj /= 255.0f;
+ m_fCurrentAmbientRed_Bl /= 255.0f;
+ m_fCurrentAmbientGreen_Bl /= 255.0f;
+ m_fCurrentAmbientBlue_Bl /= 255.0f;
+ m_fCurrentAmbientRed_Obj_Bl /= 255.0f;
+ m_fCurrentAmbientGreen_Obj_Bl /= 255.0f;
+ m_fCurrentAmbientBlue_Obj_Bl /= 255.0f;
+ m_fCurrentDirectionalRed /= 255.0f;
+ m_fCurrentDirectionalGreen /= 255.0f;
+ m_fCurrentDirectionalBlue /= 255.0f;
+
CShadows::CalcPedShadowValues(sunPos,
&m_fShadowFrontX[m_CurrentStoredValue], &m_fShadowFrontY[m_CurrentStoredValue],
&m_fShadowSideX[m_CurrentStoredValue], &m_fShadowSideY[m_CurrentStoredValue],
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index 28a0b7dd..dc52d493 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -5,6 +5,15 @@ class CTimeCycle
static int m_nAmbientRed[NUMHOURS][NUMWEATHERS];
static int m_nAmbientGreen[NUMHOURS][NUMWEATHERS];
static int m_nAmbientBlue[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];
+ static int m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];
static int m_nDirectionalRed[NUMHOURS][NUMWEATHERS];
static int m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];
static int m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];
@@ -25,7 +34,7 @@ class CTimeCycle
static float m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];
static short m_nShadowStrength[NUMHOURS][NUMWEATHERS];
static short m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];
- static short m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS];
+ static short m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];
static float m_fFogStart[NUMHOURS][NUMWEATHERS];
static float m_fFarClip[NUMHOURS][NUMWEATHERS];
static float m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];
@@ -41,11 +50,23 @@ class CTimeCycle
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 float m_fWaterRed[NUMHOURS][NUMWEATHERS];
+ static float m_fWaterGreen[NUMHOURS][NUMWEATHERS];
+ static float m_fWaterBlue[NUMHOURS][NUMWEATHERS];
+ static float 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 int m_nCurrentShadowStrength;
static int m_nCurrentLightShadowStrength;
- static int m_nCurrentTreeShadowStrength;
+ static int 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 int m_nCurrentFogColourRed;
static int m_nCurrentFogColourGreen;
static int m_nCurrentFogColourBlue;
@@ -102,6 +126,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,6 +173,11 @@ public:
static int GetFogBlue(void) { return m_nCurrentFogColourBlue; }
static int GetFogReduction(void) { return m_FogReduction; }
+ static int GetWaterRed(void) { return m_fCurrentWaterRed; }
+ static int GetWaterGreen(void) { return m_fCurrentWaterGreen; }
+ static int GetWaterBlue(void) { return m_fCurrentWaterBlue; }
+ static int GetWaterAlpha(void) { return m_fCurrentWaterAlpha; }
+
static void Initialise(void);
static void Update(void);
static CVector &GetSunPosition(void) { return m_VectorToSun[m_CurrentStoredValue]; }
diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp
index 1a28ce83..f1ccccb3 100644
--- a/src/render/WaterLevel.cpp
+++ b/src/render/WaterLevel.cpp
@@ -36,9 +36,6 @@ RpAtomic *CWaterLevel::ms_pWavyAtomic;
RpGeometry *CWaterLevel::apGeomArray[8];
int16 CWaterLevel::nGeomUsed;
-//RwTexture *gpWaterTex;
-//RwRaster *gpWaterRaster;
-
RwTexture *gpWaterTex;
RwRaster *gpWaterRaster;
@@ -84,7 +81,7 @@ CWaterLevel::Initialise(Const char *pWaterDat)
CTxdStore::SetCurrentTxd(slot);
if ( gpWaterTex == NULL )
- gpWaterTex = RwTextureRead("water_old", NULL);
+ gpWaterTex = RwTextureRead("waterclear256", NULL);
gpWaterRaster = RwTextureGetRaster(gpWaterTex);
CTxdStore::PopCurrentTxd();
@@ -222,7 +219,7 @@ CWaterLevel::DestroyWavyAtomic()
bool
CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ)
{
- int32 x = WATER_HUGE_X(fX);
+ int32 x = WATER_HUGE_X(fX + WATER_X_OFFSET);
int32 y = WATER_HUGE_Y(fY);
ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE );
@@ -240,8 +237,9 @@ 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)) )
+ ( WATER_UNSIGN_Y(fY) - float(y) * MAX_HUGE_SECTORS
+ + WATER_UNSIGN_X(fX + WATER_X_OFFSET) - float(x) * MAX_HUGE_SECTORS )
+
* (TWOPI / MAX_HUGE_SECTORS ) + fAngle
);
@@ -261,7 +259,7 @@ 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 x = WATER_HUGE_X(fX + WATER_X_OFFSET);
int32 y = WATER_HUGE_Y(fY);
ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE );
@@ -368,10 +366,10 @@ CWaterLevel::RenderWater()
WavesCalculatedThisFrame = false;
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();
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
@@ -387,15 +385,15 @@ CWaterLevel::RenderWater()
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 )
@@ -415,7 +413,7 @@ CWaterLevel::RenderWater()
|| !(aWaterBlockList[2*x+0][2*y+1] & 128)
|| !(aWaterBlockList[2*x+1][2*y+1] & 128) )
{
- 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
@@ -457,7 +455,7 @@ CWaterLevel::RenderWater()
{
if ( !(aWaterBlockList[x2][y2] & 128) )
{
- 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
@@ -614,15 +612,15 @@ CWaterLevel::RenderWater()
bottom -> top && left -> right
*/
- if ( !bUseCamStartY )
+ for ( int32 x = 0; x < 26; x++ )
{
- for ( int32 x = 0; x < 26; x++ )
+ for ( int32 y = 0; y < 5; y++ )
{
- for ( int32 y = 0; y < 5; y++ )
+ float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - 400.0f;
+ float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
+
+ if ( !bUseCamStartY )
{
- 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,
@@ -633,8 +631,7 @@ CWaterLevel::RenderWater()
if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
{
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
{
RenderOneFlatExtraHugeWaterPoly(
vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
@@ -644,6 +641,30 @@ CWaterLevel::RenderWater()
}
}
}
+
+ if ( !bUseCamEndY )
+ {
+ CVector2D vecExtraHugeSectorCentre
+ (
+ fX + EXTRAHUGE_SECTOR_SIZE/2,
+ -(fY + EXTRAHUGE_SECTOR_SIZE/2)
+ );
+
+ float fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();
+
+ if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
+ {
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
+ {
+ RenderOneFlatExtraHugeWaterPoly(
+ vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
+ vecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,
+ 0.0f,
+ color);
+ }
+ }
+ }
+
}
}
@@ -651,8 +672,8 @@ CWaterLevel::RenderWater()
{
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 fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - 400.0f;
+ float fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f + 400.0f;
float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
if ( !bUseCamStartX )
@@ -667,8 +688,7 @@ CWaterLevel::RenderWater()
if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
{
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
{
RenderOneFlatExtraHugeWaterPoly(
vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
@@ -691,8 +711,7 @@ CWaterLevel::RenderWater()
if ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )
{
- if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE),
- &TheCamera.GetCameraMatrix()) )
+ if ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )
{
RenderOneFlatExtraHugeWaterPoly(
vecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,
@@ -1092,8 +1111,8 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY)
{
const float fSectorMaxRenderDist = 75.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;
@@ -1110,7 +1129,7 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY)
{
if ( !(aWaterFineBlockList[x][y] & 128) )
{
- 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
diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h
index 985c9744..435692c1 100644
--- a/src/render/WaterLevel.h
+++ b/src/render/WaterLevel.h
@@ -1,8 +1,10 @@
#pragma once
+#define WATER_X_OFFSET (400.0f)
+
#define WATER_BLOCK_SIZE LARGE_SECTOR_SIZE
#define WATER_FINEBLOCK_SIZE HUGE_SECTOR_SIZE
-#define WATER_Z_OFFSET (1.5f)
+#define WATER_Z_OFFSET (0.5f)
#define MAX_SMALL_SECTORS 128
#define MAX_LARGE_SECTORS 64
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index b4031705..fc3e0d61 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -8,6 +8,7 @@
#include "DMAudio.h"
#include "General.h"
#include "Pad.h"
+#include "PlayerPed.h"
#include "Particle.h"
#include "RenderBuffer.h"
#include "Stats.h"
@@ -32,6 +33,7 @@ uint32 CWeather::LightningFlashLastChange;
uint32 CWeather::WhenToPlayLightningSound;
uint32 CWeather::LightningDuration;
+float CWeather::ExtraSunnyness;
float CWeather::Foggyness;
float CWeather::CloudCoverage;
float CWeather::Wind;
@@ -39,41 +41,60 @@ float CWeather::Rain;
float CWeather::InterpolationValue;
float CWeather::WetRoads;
float CWeather::Rainbow;
+float CWeather::SunGlare;
+float CWeather::WindClipped;
+float CWeather::TrafficLightBrightness;
bool CWeather::bScriptsForceRain;
-bool CWeather::Stored_StateStored;
-
-float CWeather::Stored_InterpolationValue;
-int16 CWeather::Stored_OldWeatherType;
-int16 CWeather::Stored_NewWeatherType;
-float CWeather::Stored_Rain;
tRainStreak Streaks[NUM_RAIN_STREAKS];
const int16 WeatherTypesList[] = {
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY,
+ WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY,
WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_CLOUDY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_CLOUDY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, WEATHER_CLOUDY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
- WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY
+};
+
+const int16 WeatherTypesList_WithHurricanes[] = {
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_CLOUDY,
+ WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_CLOUDY, WEATHER_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_SUNNY,
- WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_RAINY, WEATHER_CLOUDY,
+ WEATHER_CLOUDY, WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_HURRICANE,
+ WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
+ WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY
};
const float Windiness[] = {
- 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 +125,9 @@ const float Windiness[] = {
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;
@@ -127,16 +147,8 @@ void CWeather::Update(void)
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;
+ NewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList];
}
-#endif
}
InterpolationValue = fNewInterpolation;
if (CPad::GetPad(1)->GetRightShockJustDown()) {
@@ -188,14 +200,14 @@ void CWeather::Update(void)
}
// Wet roads
- if (OldWeatherType == WEATHER_RAINY) {
- if (NewWeatherType == WEATHER_RAINY)
+ if (OldWeatherType == WEATHER_RAINY || OldWeatherType == WEATHER_HURRICANE) {
+ if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)
WetRoads = 1.0f;
else
WetRoads = 1.0f - InterpolationValue;
}
else {
- if (NewWeatherType == WEATHER_RAINY)
+ if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)
WetRoads = InterpolationValue;
else
WetRoads = 0.0f;
@@ -203,10 +215,10 @@ void CWeather::Update(void)
// Rain
float fNewRain;
- if (NewWeatherType == WEATHER_RAINY) {
+ if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {
// if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
- if (OldWeatherType != WEATHER_RAINY) {
+ if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {
if (InterpolationValue < 0.4f)
// if rain has just started (<24 minutes), always 0.5
fNewRain = 0.5f;
@@ -217,19 +229,14 @@ void CWeather::Update(void)
}
else
fNewRain = 0.0f;
- if (Rain != fNewRain) { // ok to use comparasion
- if (Rain < fNewRain)
- Rain = Min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
- else
- Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
- }
+ Rain = fNewRain;
// Clouds
- if (OldWeatherType != WEATHER_SUNNY)
+ if (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
CloudCoverage = 1.0f - InterpolationValue;
else
CloudCoverage = 0.0f;
- if (NewWeatherType != WEATHER_SUNNY)
+ if (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
CloudCoverage += InterpolationValue;
// Fog
@@ -239,12 +246,76 @@ 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_RAINY && (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::GetSunPosition().z);
+ SunGlare = clamp(SunGlare, 0.0f, 1.0f);
+ // TODO(MIAMI): if (CSpecialFX::bSnapShotActive)...
+ }
+
Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType];
+ WindClipped = Max(1.0f, Wind);
+
+ if (CClock::GetHours() == 20)
+ TrafficLightBrightness = CClock::GetMinutes() / 60.0f;
+ else if (CClock::GetHours() > 6 && CClock::GetHours() < 20)
+ TrafficLightBrightness = 0.0f;
+ else if (CClock::GetHours() == 6)
+ TrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f;
+ else
+ TrafficLightBrightness = 1.0f;
+ TrafficLightBrightness = Max(WetRoads, 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()
+{
+ /* TODO(MIAMI) */
+}
+
+void CWeather::AddBeastie()
+{
+ /* TODO(MIAMI) */
}
void CWeather::ForceWeather(int16 weather)
@@ -510,23 +581,3 @@ void CWeather::RenderRainStreaks(void)
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
}
-
-void CWeather::StoreWeatherState()
-{
- Stored_StateStored = true;
- Stored_InterpolationValue = InterpolationValue;
- Stored_Rain = Rain;
- Stored_NewWeatherType = NewWeatherType;
- Stored_OldWeatherType = OldWeatherType;
-}
-
-void CWeather::RestoreWeatherState()
-{
-#ifdef FIX_BUGS // it's not used anyway though
- Stored_StateStored = false;
-#endif
- InterpolationValue = Stored_InterpolationValue;
- Rain = Stored_Rain;
- NewWeatherType = Stored_NewWeatherType;
- OldWeatherType = Stored_OldWeatherType;
-}
diff --git a/src/render/Weather.h b/src/render/Weather.h
index 9c670317..bd9b9603 100644
--- a/src/render/Weather.h
+++ b/src/render/Weather.h
@@ -1,21 +1,17 @@
enum {
- WEATHER_SUNNY,
+ WEATHER_RANDOM = -1,
+ WEATHER_SUNNY = 0,
WEATHER_CLOUDY,
WEATHER_RAINY,
- WEATHER_FOGGY
+ WEATHER_FOGGY,
+ WEATHER_EXTRA_SUNNY,
+ WEATHER_HURRICANE,
+ WEATHER_TOTAL
};
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;
@@ -30,6 +26,7 @@ public:
static uint32 WhenToPlayLightningSound;
static uint32 LightningDuration;
+ static float ExtraSunnyness;
static float Foggyness;
static float CloudCoverage;
static float Wind;
@@ -37,13 +34,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 +47,9 @@ public:
static void ReleaseWeather();
static void ForceWeather(int16);
static void ForceWeatherNow(int16);
- static void StoreWeatherState();
- static void RestoreWeatherState();
static void AddRain();
+ static void AddHeatHaze();
+ static void AddBeastie();
};
enum {
diff --git a/src/render/WindModifiers.cpp b/src/render/WindModifiers.cpp
new file mode 100644
index 00000000..d7405c7a
--- /dev/null
+++ b/src/render/WindModifiers.cpp
@@ -0,0 +1,8 @@
+#include "common.h"
+#include "WindModifiers.h"
+
+int32
+CWindModifiers::FindWindModifier(CVector pos, float *x, float *y)
+{
+ return 0;
+}
diff --git a/src/render/WindModifiers.h b/src/render/WindModifiers.h
new file mode 100644
index 00000000..b4024343
--- /dev/null
+++ b/src/render/WindModifiers.h
@@ -0,0 +1,7 @@
+#pragma once
+
+class CWindModifiers
+{
+public:
+ static int32 FindWindModifier(CVector pos, float *x, float *y);
+};
diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp
index 5a253854..8f7f92b6 100644
--- a/src/rw/Lights.cpp
+++ b/src/rw/Lights.cpp
@@ -8,6 +8,7 @@
#include "Weather.h"
#include "ZoneCull.h"
#include "Frontend.h"
+#include "MBlur.h"
RpLight *pAmbient;
RpLight *pDirect;
@@ -22,6 +23,7 @@ RwRGBAReal DirectionalLightColourForFrame;
RwRGBAReal AmbientLightColour;
RwRGBAReal DirectionalLightColour;
+//--MIAMI: done
void
SetLightsWithTimeOfDayColour(RpWorld *)
{
@@ -29,17 +31,35 @@ SetLightsWithTimeOfDayColour(RpWorld *)
RwMatrix mat;
if(pAmbient){
- AmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed() * CCoronas::LightsMult;
- AmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen() * CCoronas::LightsMult;
- AmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue() * CCoronas::LightsMult;
+ if(CMBlur::BlurOn){
+ AmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed_Bl() * CCoronas::LightsMult;
+ AmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen_Bl() * CCoronas::LightsMult;
+ AmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue_Bl() * CCoronas::LightsMult;
+ }else{
+ AmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed() * CCoronas::LightsMult;
+ AmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen() * CCoronas::LightsMult;
+ AmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue() * CCoronas::LightsMult;
+ }
+
+ if(CMBlur::BlurOn){
+ AmbientLightColourForFrame_PedsCarsAndObjects.red = CTimeCycle::GetAmbientRed_Obj_Bl() * CCoronas::LightsMult;
+ AmbientLightColourForFrame_PedsCarsAndObjects.green = CTimeCycle::GetAmbientGreen_Obj_Bl() * CCoronas::LightsMult;
+ AmbientLightColourForFrame_PedsCarsAndObjects.blue = CTimeCycle::GetAmbientBlue_Obj_Bl() * CCoronas::LightsMult;
+ }else{
+ AmbientLightColourForFrame_PedsCarsAndObjects.red = CTimeCycle::GetAmbientRed_Obj() * CCoronas::LightsMult;
+ AmbientLightColourForFrame_PedsCarsAndObjects.green = CTimeCycle::GetAmbientGreen_Obj() * CCoronas::LightsMult;
+ AmbientLightColourForFrame_PedsCarsAndObjects.blue = CTimeCycle::GetAmbientBlue_Obj() * CCoronas::LightsMult;
+ }
+
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
AmbientLightColourForFrame.red = 1.0f;
AmbientLightColourForFrame.green = 1.0f;
AmbientLightColourForFrame.blue = 1.0f;
+
+ AmbientLightColourForFrame_PedsCarsAndObjects.red = 1.0f;
+ AmbientLightColourForFrame_PedsCarsAndObjects.green = 1.0f;
+ AmbientLightColourForFrame_PedsCarsAndObjects.blue = 1.0f;
}
- AmbientLightColourForFrame_PedsCarsAndObjects.red = Min(1.0f, AmbientLightColourForFrame.red*1.3f);
- AmbientLightColourForFrame_PedsCarsAndObjects.green = Min(1.0f, AmbientLightColourForFrame.green*1.3f);
- AmbientLightColourForFrame_PedsCarsAndObjects.blue = Min(1.0f, AmbientLightColourForFrame.blue*1.3f);
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
}
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 191fc7ab..a87874d7 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -12,6 +12,7 @@ RtCharset *debugCharset;
#endif
bool gPS2alphaTest = 1;
+bool gBackfaceCulling;
#ifndef FINAL
static bool charsetOpen;
@@ -127,6 +128,15 @@ DefinedState(void)
#endif
}
+void
+SetCullMode(uint32 mode)
+{
+ if(gBackfaceCulling)
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)mode);
+ else
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
+}
+
RwFrame*
GetFirstFrameCallback(RwFrame *child, void *data)
{
diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h
index a751ee39..993acd89 100644
--- a/src/rw/RwHelper.h
+++ b/src/rw/RwHelper.h
@@ -1,6 +1,7 @@
#pragma once
extern bool gPS2alphaTest;
+extern bool gBackfaceCulling;
void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
void RwFreeAlign(void *mem);
@@ -11,6 +12,7 @@ void DestroyDebugFont();
void ObrsPrintfString(const char *str, short x, short y);
void FlushObrsPrintfs();
void DefinedState(void);
+void SetCullMode(uint32 mode);
RwFrame *GetFirstChild(RwFrame *frame);
RwObject *GetFirstObject(RwFrame *frame);
RpAtomic *GetFirstAtomic(RpClump *clump);
diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp
index 22edcb68..cff1ff16 100644
--- a/src/rw/VisibilityPlugins.cpp
+++ b/src/rw/VisibilityPlugins.cpp
@@ -4,15 +4,20 @@
#include "Entity.h"
#include "ModelInfo.h"
#include "Lights.h"
+#include "RwHelper.h"
#include "Renderer.h"
#include "Camera.h"
#include "VisibilityPlugins.h"
#include "World.h"
+//--MIAMI: file done
+
#define FADE_DISTANCE 20.0f
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList;
+CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaBoatAtomicList;
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList;
+CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaUnderwaterEntityList;
int32 CVisibilityPlugins::ms_atomicPluginOffset = -1;
int32 CVisibilityPlugins::ms_framePluginOffset = -1;
@@ -26,7 +31,6 @@ float CVisibilityPlugins::ms_vehicleLod1Dist;
float CVisibilityPlugins::ms_vehicleFadeDist;
float CVisibilityPlugins::ms_bigVehicleLod0Dist;
float CVisibilityPlugins::ms_bigVehicleLod1Dist;
-float CVisibilityPlugins::ms_pedLod0Dist;
float CVisibilityPlugins::ms_pedLod1Dist;
float CVisibilityPlugins::ms_pedFadeDist;
@@ -36,6 +40,11 @@ CVisibilityPlugins::Initialise(void)
m_alphaList.Init(NUMALPHALIST);
m_alphaList.head.item.sort = 0.0f;
m_alphaList.tail.item.sort = 100000000.0f;
+
+ m_alphaBoatAtomicList.Init(NUMBOATALPHALIST);
+ m_alphaBoatAtomicList.head.item.sort = 0.0f;
+ m_alphaBoatAtomicList.tail.item.sort = 100000000.0f;
+
#ifdef ASPECT_RATIO_SCALE
// default 150 if not enough for bigger FOVs
m_alphaEntityList.Init(NUMALPHAENTITYLIST * 3);
@@ -44,19 +53,28 @@ CVisibilityPlugins::Initialise(void)
#endif // ASPECT_RATIO_SCALE
m_alphaEntityList.head.item.sort = 0.0f;
m_alphaEntityList.tail.item.sort = 100000000.0f;
+
+ m_alphaUnderwaterEntityList.Init(NUMALPHAUNTERWATERENTITYLIST);
+ m_alphaUnderwaterEntityList.head.item.sort = 0.0f;
+ m_alphaUnderwaterEntityList.tail.item.sort = 100000000.0f;
+
}
void
CVisibilityPlugins::Shutdown(void)
{
m_alphaList.Shutdown();
+ m_alphaBoatAtomicList.Shutdown();
m_alphaEntityList.Shutdown();
+ m_alphaUnderwaterEntityList.Shutdown();
}
void
CVisibilityPlugins::InitAlphaEntityList(void)
{
m_alphaEntityList.Clear();
+ m_alphaBoatAtomicList.Clear();
+ m_alphaUnderwaterEntityList.Clear();
}
bool
@@ -65,10 +83,9 @@ CVisibilityPlugins::InsertEntityIntoSortedList(CEntity *e, float dist)
AlphaObjectInfo item;
item.entity = e;
item.sort = dist;
- bool ret = !!m_alphaEntityList.InsertSorted(item);
-// if(!ret)
-// printf("list full %d\n", m_alphaEntityList.Count());
- return ret;
+ if(e->bUnderwater && m_alphaUnderwaterEntityList.InsertSorted(item))
+ return true;
+ return !!m_alphaEntityList.InsertSorted(item);
}
void
@@ -83,10 +100,16 @@ CVisibilityPlugins::InsertAtomicIntoSortedList(RpAtomic *a, float dist)
AlphaObjectInfo item;
item.atomic = a;
item.sort = dist;
- bool ret = !!m_alphaList.InsertSorted(item);
-// if(!ret)
-// printf("list full %d\n", m_alphaList.Count());
- return ret;
+ return !!m_alphaList.InsertSorted(item);
+}
+
+bool
+CVisibilityPlugins::InsertAtomicIntoBoatSortedList(RpAtomic *a, float dist)
+{
+ AlphaObjectInfo item;
+ item.atomic = a;
+ item.sort = dist;
+ return !!m_alphaBoatAtomicList.InsertSorted(item);
}
void
@@ -106,11 +129,25 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)
ms_vehicleFadeDist = sq(100.0f * TheCamera.GenerationDistMultiplier);
ms_bigVehicleLod0Dist = sq(60.0f * TheCamera.GenerationDistMultiplier);
ms_bigVehicleLod1Dist = sq(150.0f * TheCamera.GenerationDistMultiplier);
- ms_pedLod0Dist = sq(25.0f * TheCamera.LODDistMultiplier);
ms_pedLod1Dist = sq(60.0f * TheCamera.LODDistMultiplier);
ms_pedFadeDist = sq(70.0f * TheCamera.LODDistMultiplier);
}
+static float DistToCameraSq;
+static float PitchToCamera;
+
+void
+CVisibilityPlugins::SetupVehicleVariables(RpClump *vehicle)
+{
+ if (RwObjectGetType((RwObject*)vehicle) != rpCLUMP)
+ return;
+ DistToCameraSq = GetDistanceSquaredFromCamera(RpClumpGetFrame(vehicle));
+ RwV3d distToCam;
+ RwV3dSub(&distToCam, ms_pCameraPosn, &RwFrameGetMatrix(RpClumpGetFrame(vehicle))->pos);
+ float dist2d = Sqrt(SQR(distToCam.x) + SQR(distToCam.y));
+ PitchToCamera = Atan2(distToCam.z, dist2d);
+}
+
RpMaterial*
SetAlphaCB(RpMaterial *material, void *data)
{
@@ -126,32 +163,38 @@ SetTextureCB(RpMaterial *material, void *data)
}
void
-CVisibilityPlugins::RenderAlphaAtomics(void)
+CVisibilityPlugins::RenderAtomicList(CLinkList<AlphaObjectInfo> &list)
{
CLink<AlphaObjectInfo> *node;
- for(node = m_alphaList.tail.prev;
- node != &m_alphaList.head;
- node = node->prev)
+ for(node = list.tail.prev; node != &list.head; node = node->prev)
AtomicDefaultRenderCallBack(node->item.atomic);
}
void
-CVisibilityPlugins::RenderFadingEntities(void)
+CVisibilityPlugins::RenderAlphaAtomics(void)
+{
+ RenderAtomicList(m_alphaList);
+}
+
+void
+CVisibilityPlugins::RenderBoatAlphaAtomics(void)
+{
+ SetCullMode(rwCULLMODECULLNONE);
+ RenderAtomicList(m_alphaBoatAtomicList);
+ SetCullMode(rwCULLMODECULLBACK);
+}
+
+void
+CVisibilityPlugins::RenderFadingEntities(CLinkList<AlphaObjectInfo> &list)
{
CLink<AlphaObjectInfo> *node;
CSimpleModelInfo *mi;
- for(node = m_alphaEntityList.tail.prev;
- node != &m_alphaEntityList.head;
- node = node->prev){
+ for(node = list.tail.prev; node != &list.head; node = node->prev){
CEntity *e = node->item.entity;
if(e->m_rwObject == nil)
continue;
mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex());
-#ifdef FIX_BUGS
if(mi->GetModelType() == MITYPE_SIMPLE && mi->m_noZwrite)
-#else
- if(mi->m_noZwrite)
-#endif
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
if(e->bDistanceFade){
@@ -163,29 +206,34 @@ CVisibilityPlugins::RenderFadingEntities(void)
}else
CRenderer::RenderOneNonRoad(e);
-#ifdef FIX_BUGS
if(mi->GetModelType() == MITYPE_SIMPLE && mi->m_noZwrite)
-#else
- if(mi->m_noZwrite)
-#endif
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
}
+void
+CVisibilityPlugins::RenderFadingEntities(void)
+{
+ RenderFadingEntities(m_alphaEntityList);
+ RenderBoatAlphaAtomics();
+}
+
+void
+CVisibilityPlugins::RenderFadingUnderwaterEntities(void)
+{
+ RenderFadingEntities(m_alphaUnderwaterEntityList);
+}
+
RpAtomic*
CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic)
{
RpAtomic *lodatm;
- RwMatrix *m;
- RwV3d view;
float len;
CSimpleModelInfo *mi;
mi = GetAtomicModelInfo(atomic);
- m = RwFrameGetLTM(RpAtomicGetFrame(atomic));
- RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);
- len = RwV3dLength(&view);
- lodatm = mi->GetAtomicFromDistance(len);
+ len = Sqrt(DistToCameraSq);
+ lodatm = mi->GetAtomicFromDistance(len * TheCamera.LODDistMultiplier / TheCamera.GenerationDistMultiplier);
if(lodatm){
if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic))
RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE);
@@ -227,6 +275,24 @@ CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha)
}
RpAtomic*
+CVisibilityPlugins::RenderWeaponCB(RpAtomic *atomic)
+{
+ RwMatrix *m;
+ RwV3d view;
+ float maxdist, distsq;
+ CSimpleModelInfo *mi;
+
+ mi = GetAtomicModelInfo(atomic);
+ m = RwFrameGetLTM(RpAtomicGetFrame(atomic));
+ RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);
+ maxdist = mi->GetLodDistance(0);
+ distsq = RwV3dDotProduct(&view, &view);
+ if(distsq < maxdist*maxdist)
+ AtomicDefaultRenderCallBack(atomic);
+ return atomic;
+}
+
+RpAtomic*
CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
{
RpAtomic *lodatm;
@@ -236,29 +302,30 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
mi = GetAtomicModelInfo(atomic);
lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);
- if(mi->m_additive){
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ if(mi->m_additive)
AtomicDefaultRenderCallBack(atomic);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- }else{
- fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
- if(fadefactor > 1.0f)
- fadefactor = 1.0f;
- alpha = mi->m_alpha * fadefactor;
- if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
- else{
- RpGeometry *geo = RpAtomicGetGeometry(lodatm);
- uint32 flags = RpGeometryGetFlags(geo);
- RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
- RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
- if(geo != RpAtomicGetGeometry(atomic))
- RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- AtomicDefaultRenderCallBack(atomic);
- RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
- RpGeometrySetFlags(geo, flags);
- }
+
+ fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
+ if(fadefactor > 1.0f)
+ fadefactor = 1.0f;
+ alpha = mi->m_alpha * fadefactor;
+ if(alpha == 255)
+ AtomicDefaultRenderCallBack(atomic);
+ else{
+ RpGeometry *geo = RpAtomicGetGeometry(lodatm);
+ uint32 flags = RpGeometryGetFlags(geo);
+ RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
+ RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
+ if(geo != RpAtomicGetGeometry(atomic))
+ RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
+ AtomicDefaultRenderCallBack(atomic);
+ RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
+ RpGeometrySetFlags(geo, flags);
}
+
+ if(mi->m_additive)
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
return atomic;
}
@@ -268,17 +335,16 @@ RpAtomic*
CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_vehicleLod0Dist){
+ if(DistToCameraSq < ms_vehicleLod0Dist){
flags = GetAtomicId(atomic);
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
- if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
+ if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))
return atomic;
}
AtomicDefaultRenderCallBack(atomic);
@@ -290,25 +356,24 @@ RpAtomic*
CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_vehicleLod0Dist){
+ if(DistToCameraSq < ms_vehicleLod0Dist){
flags = GetAtomicId(atomic);
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
- if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)
+ if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))
return atomic;
if(flags & ATOMIC_FLAG_DRAWLAST){
// sort before clump
- if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq - 0.0001f))
AtomicDefaultRenderCallBack(atomic);
}else{
- if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))
AtomicDefaultRenderCallBack(atomic);
}
}
@@ -319,14 +384,13 @@ RpAtomic*
CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_bigVehicleLod0Dist){
+ if(DistToCameraSq < ms_bigVehicleLod0Dist){
flags = GetAtomicId(atomic);
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
if(dot > 0.0f)
@@ -341,20 +405,19 @@ RpAtomic*
CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_bigVehicleLod0Dist){
+ if(DistToCameraSq < ms_bigVehicleLod0Dist){
flags = GetAtomicId(atomic);
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
- if(dot > 0.0f)
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)
+ if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))
return atomic;
- if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))
AtomicDefaultRenderCallBack(atomic);
}
return atomic;
@@ -363,29 +426,36 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)
RpAtomic*
CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic)
{
- RwFrame *clumpframe;
- float distsq;
-
- clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_bigVehicleLod1Dist)
+ if(DistToCameraSq < ms_bigVehicleLod1Dist)
AtomicDefaultRenderCallBack(atomic);
return atomic;
}
RpAtomic*
+CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_Boat(RpAtomic *atomic)
+{
+ if(DistToCameraSq < ms_vehicleLod0Dist){
+ if(GetAtomicId(atomic) & ATOMIC_FLAG_DRAWLAST){
+ if(!InsertAtomicIntoBoatSortedList(atomic, DistToCameraSq))
+ AtomicDefaultRenderCallBack(atomic);
+ }else
+ AtomicDefaultRenderCallBack(atomic);
+ }
+ return atomic;
+}
+
+RpAtomic*
CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq >= ms_bigVehicleLod0Dist &&
- distsq < ms_bigVehicleLod1Dist){
+ if(DistToCameraSq >= ms_bigVehicleLod0Dist &&
+ DistToCameraSq < ms_bigVehicleLod1Dist){
flags = GetAtomicId(atomic);
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
if(dot > 0.0f)
@@ -400,21 +470,20 @@ RpAtomic*
CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq >= ms_bigVehicleLod0Dist &&
- distsq < ms_bigVehicleLod1Dist){
+ if(DistToCameraSq >= ms_bigVehicleLod0Dist &&
+ DistToCameraSq < ms_bigVehicleLod1Dist){
flags = GetAtomicId(atomic);
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
if(dot > 0.0f)
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)
return atomic;
- if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))
AtomicDefaultRenderCallBack(atomic);
}
return atomic;
@@ -424,12 +493,10 @@ RpAtomic*
CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)
{
RpClump *clump;
- float dist;
int32 alpha;
clump = RpAtomicGetClump(atomic);
- dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump));
- if(dist >= ms_vehicleLod0Dist){
+ if(DistToCameraSq >= ms_vehicleLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
AtomicDefaultRenderCallBack(atomic);
@@ -443,12 +510,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)
RpAtomic*
CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic)
{
- RwFrame *clumpframe;
- float distsq;
-
- clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq >= ms_bigVehicleLod1Dist)
+ if(DistToCameraSq >= ms_bigVehicleLod1Dist)
AtomicDefaultRenderCallBack(atomic);
return atomic;
}
@@ -457,17 +519,16 @@ RpAtomic*
CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_bigVehicleLod1Dist){
+ if(DistToCameraSq < ms_bigVehicleLod1Dist){
flags = GetAtomicId(atomic);
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0){
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
- if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
+ if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))
return atomic;
}
AtomicDefaultRenderCallBack(atomic);
@@ -479,25 +540,24 @@ RpAtomic*
CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)
{
RwFrame *clumpframe;
- float distsq, dot;
+ float dot;
uint32 flags;
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
- distsq = GetDistanceSquaredFromCamera(clumpframe);
- if(distsq < ms_bigVehicleLod1Dist){
+ if(DistToCameraSq < ms_bigVehicleLod1Dist){
flags = GetAtomicId(atomic);
dot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),
RwFrameGetLTM(clumpframe), flags);
- if(distsq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0)
- if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
+ if(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)
+ if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))
return atomic;
if(flags & ATOMIC_FLAG_DRAWLAST){
// sort before clump
- if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq - 0.0001f))
AtomicDefaultRenderCallBack(atomic);
}else{
- if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))
AtomicDefaultRenderCallBack(atomic);
}
}
@@ -505,54 +565,49 @@ CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)
}
RpAtomic*
-CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)
+CVisibilityPlugins::RenderVehicleRotorAlphaCB(RpAtomic *atomic)
{
- if(CWorld::Players[0].m_pSkinTexture)
- RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture);
- AtomicDefaultRenderCallBack(atomic);
+ RwFrame *clumpframe;
+ float dot;
+ RwV3d cam2atm;
+
+ clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
+ if(DistToCameraSq < ms_bigVehicleLod1Dist){
+ RwV3dSub(&cam2atm, &RwFrameGetLTM(RpAtomicGetFrame(atomic))->pos, ms_pCameraPosn);
+ dot = RwV3dDotProduct(&cam2atm, &RwFrameGetLTM(clumpframe)->at);
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot*20.0f))
+ AtomicDefaultRenderCallBack(atomic);
+ }
return atomic;
}
RpAtomic*
-CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic)
+CVisibilityPlugins::RenderVehicleTailRotorAlphaCB(RpAtomic *atomic)
{
- RpClump *clump;
- float dist;
- int32 alpha;
+ RwMatrix *clumpMat, *atmMat;
+ float dot;
+ RwV3d cam2atm;
- clump = RpAtomicGetClump(atomic);
- dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump));
- if(dist >= ms_pedLod0Dist){
- alpha = GetClumpAlpha(clump);
- if(alpha == 255)
+ if(DistToCameraSq < ms_bigVehicleLod0Dist){
+ atmMat = RwFrameGetLTM(RpAtomicGetFrame(atomic));
+ clumpMat = RwFrameGetLTM(RpClumpGetFrame(RpAtomicGetClump(atomic)));
+ RwV3dSub(&cam2atm, &atmMat->pos, ms_pCameraPosn);
+ dot = RwV3dDotProduct(&cam2atm, &clumpMat->up) + RwV3dDotProduct(&cam2atm, &clumpMat->right);
+ if(!InsertAtomicIntoSortedList(atomic, DistToCameraSq - dot))
AtomicDefaultRenderCallBack(atomic);
- else
- RenderAlphaAtomic(atomic, alpha);
}
return atomic;
}
RpAtomic*
-CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic)
+CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)
{
- RpClump *clump;
- float dist;
- int32 alpha;
-
- clump = RpAtomicGetClump(atomic);
- dist = GetDistanceSquaredFromCamera(RpClumpGetFrame(clump));
- if(dist < ms_pedLod0Dist){
- alpha = GetClumpAlpha(clump);
- if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
- else
- RenderAlphaAtomic(atomic, alpha);
- }
+ if(CWorld::Players[0].m_pSkinTexture)
+ RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture);
+ AtomicDefaultRenderCallBack(atomic);
return atomic;
}
-// This is needed for peds with only one clump, i.e. skinned models
-// strangely even the xbox version has no such thing
RpAtomic*
CVisibilityPlugins::RenderPedCB(RpAtomic *atomic)
{
@@ -627,16 +682,6 @@ CVisibilityPlugins::DefaultVisibilityCB(RpClump *clump)
}
bool
-CVisibilityPlugins::MloVisibilityCB(RpClump *clump)
-{
- RwFrame *frame = RpClumpGetFrame(clump);
- CMloModelInfo *modelInfo = (CMloModelInfo*)GetFrameHierarchyId(frame);
- if (sq(modelInfo->field_34) < GetDistanceSquaredFromCamera(frame))
- return false;
- return CVisibilityPlugins::FrustumSphereCB(clump);
-}
-
-bool
CVisibilityPlugins::FrustumSphereCB(RpClump *clump)
{
RwSphere sphere;
@@ -730,13 +775,6 @@ CVisibilityPlugins::SetAtomicModelInfo(RpAtomic *atomic,
{
AtomicExt *ext = ATOMICEXT(atomic);
ext->modelInfo = modelInfo;
- switch (modelInfo->GetModelType()) {
- case MITYPE_SIMPLE:
- case MITYPE_TIME:
- if(modelInfo->m_normalCull)
- SetAtomicRenderCallback(atomic, RenderObjNormalAtomic);
- default: break;
- }
}
CSimpleModelInfo*
diff --git a/src/rw/VisibilityPlugins.h b/src/rw/VisibilityPlugins.h
index b367d7ee..89583432 100644
--- a/src/rw/VisibilityPlugins.h
+++ b/src/rw/VisibilityPlugins.h
@@ -21,7 +21,9 @@ public:
};
static CLinkList<AlphaObjectInfo> m_alphaList;
+ static CLinkList<AlphaObjectInfo> m_alphaBoatAtomicList;
static CLinkList<AlphaObjectInfo> m_alphaEntityList;
+ static CLinkList<AlphaObjectInfo> m_alphaUnderwaterEntityList;
static RwCamera *ms_pCamera;
static RwV3d *ms_pCameraPosn;
static float ms_cullCompsDist;
@@ -30,7 +32,6 @@ public:
static float ms_vehicleFadeDist;
static float ms_bigVehicleLod0Dist;
static float ms_bigVehicleLod1Dist;
- static float ms_pedLod0Dist;
static float ms_pedLod1Dist;
static float ms_pedFadeDist;
@@ -40,12 +41,15 @@ public:
static bool InsertEntityIntoSortedList(CEntity *e, float dist);
static void InitAlphaAtomicList(void);
static bool InsertAtomicIntoSortedList(RpAtomic *a, float dist);
+ static bool InsertAtomicIntoBoatSortedList(RpAtomic *a, float dist);
static void SetRenderWareCamera(RwCamera *camera);
+ static void SetupVehicleVariables(RpClump *vehicle);
static RpAtomic *RenderWheelAtomicCB(RpAtomic *atomic);
static RpAtomic *RenderObjNormalAtomic(RpAtomic *atomic);
static RpAtomic *RenderAlphaAtomic(RpAtomic *atomic, int alpha);
+ static RpAtomic *RenderWeaponCB(RpAtomic *atomic);
static RpAtomic *RenderFadingAtomic(RpAtomic *atm, float dist);
static RpAtomic *RenderVehicleHiDetailCB(RpAtomic *atomic);
@@ -53,25 +57,29 @@ public:
static RpAtomic *RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic);
static RpAtomic *RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic);
static RpAtomic *RenderVehicleHiDetailCB_Boat(RpAtomic *atomic);
+ static RpAtomic *RenderVehicleHiDetailAlphaCB_Boat(RpAtomic *atomic);
static RpAtomic *RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic);
static RpAtomic *RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic);
static RpAtomic *RenderVehicleReallyLowDetailCB(RpAtomic *atomic);
static RpAtomic *RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic);
static RpAtomic *RenderTrainHiDetailCB(RpAtomic *atomic);
static RpAtomic *RenderTrainHiDetailAlphaCB(RpAtomic *atomic);
+ static RpAtomic *RenderVehicleRotorAlphaCB(RpAtomic *atomic);
+ static RpAtomic *RenderVehicleTailRotorAlphaCB(RpAtomic *atomic);
static RpAtomic *RenderPlayerCB(RpAtomic *atomic);
- static RpAtomic *RenderPedLowDetailCB(RpAtomic *atomic);
- static RpAtomic *RenderPedHiDetailCB(RpAtomic *atomic);
static RpAtomic *RenderPedCB(RpAtomic *atomic); // for skinned models with only one clump
+ static void RenderAtomicList(CLinkList<AlphaObjectInfo> &list);
static void RenderAlphaAtomics(void);
+ static void RenderBoatAlphaAtomics(void);
+ static void RenderFadingEntities(CLinkList<AlphaObjectInfo> &list);
static void RenderFadingEntities(void);
+ static void RenderFadingUnderwaterEntities(void);
// All actually unused
static bool DefaultVisibilityCB(RpClump *clump);
static bool FrustumSphereCB(RpClump *clump);
- static bool MloVisibilityCB(RpClump *clump);
static bool VehicleVisibilityCB(RpClump *clump);
static bool VehicleVisibilityCB_BigVehicle(RpClump *clump);
diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp
index 8aae4011..1afa8165 100644
--- a/src/save/GenericGameStorage.cpp
+++ b/src/save/GenericGameStorage.cpp
@@ -543,11 +543,6 @@ RestoreForStartLoad()
ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().z);
CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
CStreaming::RemoveUnusedBuildings(CGame::currLevel);
- CCollision::SortOutCollisionAfterLoad();
- CStreaming::RequestBigBuildings(CGame::currLevel);
- CStreaming::LoadAllRequestedModels(false);
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
- CGame::TidyUpMemory(true, false);
if (CloseFile(file)) {
return true;
diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp
index fc23e900..c60c5cd9 100644
--- a/src/skel/glfw/glfw.cpp
+++ b/src/skel/glfw/glfw.cpp
@@ -1768,5 +1768,9 @@ int strcasecmp(const char* str1, const char* str2)
{
return _strcmpi(str1, str2);
}
+int strncasecmp(const char *str1, const char *str2, size_t len)
+{
+ return _strnicmp(str1, str2, len);
+}
#endif
#endif
diff --git a/src/skel/win/gta3.ico b/src/skel/win/gta3.ico
deleted file mode 100644
index 2017c811..00000000
--- a/src/skel/win/gta3.ico
+++ /dev/null
Binary files differ
diff --git a/src/skel/win/gtavc.ico b/src/skel/win/gtavc.ico
new file mode 100644
index 00000000..d253ff2c
--- /dev/null
+++ b/src/skel/win/gtavc.ico
Binary files differ
diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp
index 9a885818..f41b9ef8 100644
--- a/src/skel/win/win.cpp
+++ b/src/skel/win/win.cpp
@@ -1884,13 +1884,11 @@ WinMain(HINSTANCE instance,
StaticPatcher::Apply();
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);
-/*
// TODO: make this an option somewhere
AllocConsole();
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
-*/
/*
* Initialize the platform independent data.
@@ -3152,5 +3150,9 @@ int strcasecmp(const char *str1, const char *str2)
{
return _strcmpi(str1, str2);
}
+int strncasecmp(const char *str1, const char *str2, size_t len)
+{
+ return _strnicmp(str1, str2, len);
+}
#endif
#endif \ No newline at end of file
diff --git a/src/skel/win/win.rc b/src/skel/win/win.rc
index 379c473d..9b5aa305 100644
--- a/src/skel/win/win.rc
+++ b/src/skel/win/win.rc
@@ -42,6 +42,6 @@ END
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
-IDI_MAIN_ICON ICON DISCARDABLE "gta3.ico"
+IDI_MAIN_ICON ICON DISCARDABLE "gtavc.ico"
///////////////////////////////////////////////////////////////////////////// \ No newline at end of file
diff --git a/src/text/Text.cpp b/src/text/Text.cpp
index 1e58fcd1..74f53f80 100644
--- a/src/text/Text.cpp
+++ b/src/text/Text.cpp
@@ -7,27 +7,36 @@
#include "Frontend.h"
#include "Messages.h"
#include "Text.h"
+#include "Timer.h"
static wchar WideErrorString[25];
CText TheText;
+//--MIAMI: DONE
CText::CText(void)
{
encoding = 'e';
+ bHasMissionTextOffsets = false;
+ bIsMissionTextLoaded = false;
+ memset(szMissionTableName, 0, sizeof(szMissionTableName));
memset(WideErrorString, 0, sizeof(WideErrorString));
}
+//--MIAMI: DONE
void
CText::Load(void)
{
- uint8 *filedata;
- char filename[32], type[4];
- int length;
- int offset, sectlen;
+ char filename[32];
+ uint32 offset;
+ int file;
+ bool tkey_loaded = false, tdat_loaded = false;
+ ChunkHeader m_ChunkHeader;
+
+ bIsMissionTextLoaded = false;
+ bHasMissionTextOffsets = false;
Unload();
- filedata = new uint8[0x40000];
CFileMgr::SetDir("TEXT");
switch(CMenuManager::m_PrefsLanguage){
@@ -59,49 +68,64 @@ CText::Load(void)
#endif
}
- length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
- CFileMgr::SetDir("");
+ file = CFileMgr::OpenFile(filename, "rb");
offset = 0;
- while(offset < length){
- type[0] = filedata[offset++];
- type[1] = filedata[offset++];
- type[2] = filedata[offset++];
- type[3] = filedata[offset++];
- sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
- (int)filedata[offset+1]<<8 | (int)filedata[offset+0];
- offset += 4;
- if(sectlen != 0){
- if(strncmp(type, "TKEY", 4) == 0)
- keyArray.Load(sectlen, filedata, &offset);
- else if(strncmp(type, "TDAT", 4) == 0)
- data.Load(sectlen, filedata, &offset);
- else
- offset += sectlen;
+ while (!tkey_loaded || !tdat_loaded) {
+ ReadChunkHeader(&m_ChunkHeader, file, &offset);
+ if (m_ChunkHeader.size != 0) {
+ if (strncmp(m_ChunkHeader.magic, "TABL", 4) == 0) {
+ MissionTextOffsets.Load(m_ChunkHeader.size, file, &offset, 0x58000);
+ bHasMissionTextOffsets = true;
+ } else if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) {
+ this->keyArray.Load(m_ChunkHeader.size, file, &offset);
+ tkey_loaded = true;
+ } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) {
+ this->data.Load(m_ChunkHeader.size, file, &offset);
+ tdat_loaded = true;
+ } else {
+ CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);
+ offset += m_ChunkHeader.size;
+ }
}
}
keyArray.Update(data.chars);
-
- delete[] filedata;
+ CFileMgr::CloseFile(file);
+ CFileMgr::SetDir("");
}
+//--MIAMI: DONE
void
CText::Unload(void)
{
CMessages::ClearAllMessagesDisplayedByGame();
- data.Unload();
keyArray.Unload();
+ data.Unload();
+ mission_keyArray.Unload();
+ mission_data.Unload();
+ bIsMissionTextLoaded = false;
+ memset(szMissionTableName, 0, sizeof(szMissionTableName));
}
+//--MIAMI: DONE
wchar*
CText::Get(const char *key)
{
+ uint8 result = false;
+#ifdef FIX_BUGS
+ wchar *outstr = keyArray.Search(key, data.chars, &result);
+#else
+ wchar *outstr = keyArray.Search(key, &result);
+#endif
+
+ if (!result && bHasMissionTextOffsets && bIsMissionTextLoaded)
#ifdef FIX_BUGS
- return keyArray.Search(key, data.chars);
+ outstr = mission_keyArray.Search(key, mission_data.chars, &result);
#else
- return keyArray.Search(key);
+ outstr = mission_keyArray.Search(key, &result);
#endif
+ return outstr;
}
wchar UpperCaseTable[128] = {
@@ -134,6 +158,7 @@ wchar FrenchUpperCaseTable[128] = {
253, 254, 255
};
+//--MIAMI: TODO (check tables)
wchar
CText::GetUpperCase(wchar c)
{
@@ -165,6 +190,7 @@ CText::GetUpperCase(wchar c)
return c;
}
+//--MIAMI: DONE
void
CText::UpperCase(wchar *s)
{
@@ -174,21 +200,131 @@ CText::UpperCase(wchar *s)
}
}
+//--MIAMI: DONE
+void
+CText::GetNameOfLoadedMissionText(char *outName)
+{
+ strcpy(outName, szMissionTableName);
+}
+
+//--MIAMI: DONE
+void
+CText::ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *offset)
+{
+ // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded
+ CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader));
+ *offset += sizeof(ChunkHeader);
+}
+
+//--MIAMI: DONE
+void
+CText::LoadMissionText(char *MissionTableName)
+{
+ char filename[32];
+
+ mission_keyArray.Unload();
+ mission_data.Unload();
+
+ bool search_result = false;
+ int missionTableId = 0;
+
+ for (missionTableId = 0; missionTableId < MissionTextOffsets.size; missionTableId++) {
+ if (strncmp(MissionTextOffsets.data[missionTableId].szMissionName, MissionTableName, strlen(MissionTextOffsets.data[missionTableId].szMissionName)) == 0) {
+ search_result = true;
+ break;
+ }
+ }
+
+ if (!search_result) {
+ printf("CText::LoadMissionText - couldn't find %s", MissionTableName);
+ return;
+ }
+
+ CFileMgr::SetDir("TEXT");
+ switch (CMenuManager::m_PrefsLanguage) {
+ case LANGUAGE_AMERICAN:
+ sprintf(filename, "AMERICAN.GXT");
+ break;
+ case LANGUAGE_FRENCH:
+ sprintf(filename, "FRENCH.GXT");
+ break;
+ case LANGUAGE_GERMAN:
+ sprintf(filename, "GERMAN.GXT");
+ break;
+ case LANGUAGE_ITALIAN:
+ sprintf(filename, "ITALIAN.GXT");
+ break;
+ case LANGUAGE_SPANISH:
+ sprintf(filename, "SPANISH.GXT");
+ break;
+#ifdef MORE_LANGUAGES
+ case LANGUAGE_POLISH:
+ sprintf(filename, "POLISH.GXT");
+ break;
+ case LANGUAGE_RUSSIAN:
+ sprintf(filename, "RUSSIAN.GXT");
+ break;
+ case LANGUAGE_JAPANESE:
+ sprintf(filename, "JAPANESE.GXT");
+ break;
+#endif
+ }
+ CTimer::Suspend();
+ int file = CFileMgr::OpenFile(filename, "rb");
+ CFileMgr::Seek(file, MissionTextOffsets.data[missionTableId].offset, SEEK_SET);
+
+ char TableCheck[8];
+ CFileMgr::Read(file, TableCheck, 8);
+ if (strncmp(TableCheck, MissionTableName, 8) != 0)
+ printf("CText::LoadMissionText - expected to find %s in the text file", MissionTableName);
+
+ bool tkey_loaded = false, tdat_loaded = false;
+ ChunkHeader m_ChunkHeader;
+ while (!tkey_loaded || !tdat_loaded) {
+ uint32 bytes_read = 0;
+ ReadChunkHeader(&m_ChunkHeader, file, &bytes_read);
+ if (m_ChunkHeader.size != 0) {
+ if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) {
+ uint32 bytes_read = 0;
+ mission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read);
+ tkey_loaded = true;
+ } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) {
+ uint32 bytes_read = 0;
+ mission_data.Load(m_ChunkHeader.size, file, &bytes_read);
+ tdat_loaded = true;
+ } else
+ CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);
+ }
+ }
+
+ mission_keyArray.Update(mission_data.chars);
+ CFileMgr::CloseFile(file);
+ CTimer::Resume();
+ CFileMgr::SetDir("");
+ strcpy(szMissionTableName, MissionTableName);
+ bIsMissionTextLoaded = true;
+}
+
+//--MIAMI: DONE
void
-CKeyArray::Load(uint32 length, uint8 *data, int *offset)
+CKeyArray::Load(uint32 length, int file, uint32 *offset)
{
- uint32 i;
- uint8 *rawbytes;
+ char *rawbytes;
numEntries = length / sizeof(CKeyEntry);
entries = new CKeyEntry[numEntries];
- rawbytes = (uint8*)entries;
+ rawbytes = (char*)entries;
- for(i = 0; i < length; i++)
- rawbytes[i] = data[(*offset)++];
+#if DUMB
+ for (uint32 i = 0; i < length; i++)
+ CFileMgr::Read(file, &rawbytes[i], 1);
+#else
+ CFileMgr::Read(file, rawbytes, length);
+#endif
}
+//--MIAMI: DONE
void
CKeyArray::Unload(void)
{
@@ -197,6 +333,7 @@ CKeyArray::Unload(void)
numEntries = 0;
}
+//--MIAMI: DONE
void
CKeyArray::Update(wchar *chars)
{
@@ -207,6 +344,7 @@ CKeyArray::Update(wchar *chars)
#endif
}
+//--MIAMI: DONE
CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
{
@@ -227,11 +365,12 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi
return nil;
}
+//--MIAMI: DONE
wchar*
#ifdef FIX_BUGS
-CKeyArray::Search(const char *key, wchar *data)
+CKeyArray::Search(const char *key, wchar *data, uint8 *result)
#else
-CKeyArray::Search(const char *key)
+CKeyArray::Search(const char *key, uint8 *result)
#endif
{
CKeyEntry *found;
@@ -240,34 +379,47 @@ CKeyArray::Search(const char *key)
#ifdef FIX_BUGS
found = BinarySearch(key, entries, 0, numEntries-1);
- if(found)
+ if (found) {
+ *result = true;
return (wchar*)((uint8*)data + found->valueOffset);
+ }
#else
found = BinarySearch(key, entries, 0, numEntries-1);
- if(found)
+ if (found) {
+ *result = true;
return found->value;
+ }
#endif
+ *result = false;
+#ifdef MASTER
+ sprintf(errstr, "%");
+#else
sprintf(errstr, "%s missing", key);
+#endif // MASTER
for(i = 0; i < 25; i++)
WideErrorString[i] = errstr[i];
return WideErrorString;
}
-
+//--MIAMI: DONE
void
-CData::Load(uint32 length, uint8 *data, int *offset)
+CData::Load(uint32 length, int file, uint32 *offset)
{
- uint32 i;
- uint8 *rawbytes;
+ char *rawbytes;
numChars = length / sizeof(wchar);
chars = new wchar[numChars];
- rawbytes = (uint8*)chars;
+ rawbytes = (char*)chars;
- for(i = 0; i < length; i++)
- rawbytes[i] = data[(*offset)++];
+#if DUMB
+ for(uint32 i = 0; i < length; i++)
+ CFileMgr::Read(file, &rawbytes[i], 1);
+#else
+ CFileMgr::Read(file, rawbytes, length);
+#endif
}
+//--MIAMI: DONE
void
CData::Unload(void)
{
@@ -276,6 +428,16 @@ CData::Unload(void)
numChars = 0;
}
+//--MIAMI: DONE
+void
+CMissionTextOffsets::Load(uint32 table_size, int file, uint32 *offset, int)
+{
+ // not exact VC code but smaller and better :P
+ size = table_size / sizeof(CMissionTextOffsets::Entry);
+ CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size);
+ *offset += sizeof(CMissionTextOffsets::Entry) * size;
+}
+
void
AsciiToUnicode(const char *src, wchar *dst)
{
diff --git a/src/text/Text.h b/src/text/Text.h
index 18a904bc..dcffccbf 100644
--- a/src/text/Text.h
+++ b/src/text/Text.h
@@ -28,14 +28,14 @@ public:
CKeyArray(void) : entries(nil), numEntries(0) {}
~CKeyArray(void) { Unload(); }
- void Load(uint32 length, uint8 *data, int *offset);
+ void Load(uint32 length, int file, uint32 *offset);
void Unload(void);
void Update(wchar *chars);
CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);
#ifdef FIX_BUGS
- wchar *Search(const char *key, wchar *data);
+ wchar *Search(const char *key, wchar *data, uint8 *result);
#else
- wchar *Search(const char *key);
+ wchar *Search(const char *key, uint8* result);
#endif
};
@@ -47,15 +47,45 @@ public:
CData(void) : chars(nil), numChars(0) {}
~CData(void) { Unload(); }
- void Load(uint32 length, uint8 *data, int *offset);
+ void Load(uint32 length, int file, uint32 *offset);
void Unload(void);
};
+class CMissionTextOffsets
+{
+public:
+ struct Entry
+ {
+ char szMissionName[8];
+ uint32 offset;
+ };
+
+ enum {MAX_MISSION_TEXTS = 90}; // beware that LCS has more
+
+ Entry data[MAX_MISSION_TEXTS];
+ uint16 size;
+
+ CMissionTextOffsets(void) : size(0) {}
+ void Load(uint32 table_size, int file, uint32* bytes_read, int);
+};
+
+struct ChunkHeader
+{
+ char magic[4];
+ int size;
+};
+
class CText
{
CKeyArray keyArray;
CData data;
+ CKeyArray mission_keyArray;
+ CData mission_data;
char encoding;
+ bool bHasMissionTextOffsets;
+ bool bIsMissionTextLoaded;
+ char szMissionTableName[8];
+ CMissionTextOffsets MissionTextOffsets;
public:
CText(void);
void Load(void);
@@ -63,6 +93,9 @@ public:
wchar *Get(const char *key);
wchar GetUpperCase(wchar c);
void UpperCase(wchar *s);
+ void GetNameOfLoadedMissionText(char *outName);
+ void ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *bytes_read);
+ void LoadMissionText(char *MissionTableName);
};
extern CText TheText;
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 2212ddff..ae78c93e 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -72,6 +72,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
bFixedColour = false;
bBigWheels = false;
bWaterTight = false;
+ bTankDetonateCars = true;
SetModelIndex(id);
@@ -195,7 +196,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
CMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
mat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z);
mat1.UpdateRW();
- }else if(GetModelIndex() == MI_MIAMI_SPARROW || GetModelIndex() == MI_MIAMI_RCRAIDER){
+ }else if(IsRealHeli()){
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
@@ -229,10 +230,6 @@ CAutomobile::ProcessControl(void)
colModel = GetColModel();
bWarnedPeds = false;
- // skip if the collision isn't for the current level
- if(colModel->level > LEVEL_NONE && colModel->level != CCollision::ms_collisionInMemory)
- return;
-
// Improve grip of vehicles in certain cases
bool strongGrip1 = false;
bool strongGrip2 = false;
@@ -336,7 +333,7 @@ CAutomobile::ProcessControl(void)
bool playerRemote = false;
switch(GetStatus()){
case STATUS_PLAYER_REMOTE:
- if(CPad::GetPad(0)->WeaponJustDown()){
+ if(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){
BlowUpCar(FindPlayerPed());
CRemote::TakeRemoteControlledCarFromPlayer();
}
@@ -496,8 +493,7 @@ CAutomobile::ProcessControl(void)
TankControl();
BlowUpCarsInPath();
break;
- case MI_YARDIE:
- // beta also had esperanto here it seems
+ case MI_VOODOO:
HydraulicControl();
break;
default:
@@ -679,9 +675,7 @@ CAutomobile::ProcessControl(void)
acceleration /= m_fForceMultiplier;
// unused
- if(GetModelIndex() == MI_MIAMI_RCBARON ||
- GetModelIndex() == MI_MIAMI_RCRAIDER ||
- GetModelIndex() == MI_MIAMI_SPARROW)
+ if(GetModelIndex() == MI_RCBARON || IsRealHeli())
acceleration = 0.0f;
brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
@@ -1013,7 +1007,7 @@ CAutomobile::ProcessControl(void)
m_bSirenOrAlarm = !m_bSirenOrAlarm;
}else
m_nCarHornTimer = 0;
- }else if(GetModelIndex() != MI_YARDIE && !CVehicle::bCheat3){
+ }else if(GetModelIndex() != MI_VOODOO && !CVehicle::bCheat3){
if(Pads[0].GetHorn())
m_nCarHornTimer = 1;
else
@@ -1024,7 +1018,7 @@ CAutomobile::ProcessControl(void)
// Flying
if(GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PHYSICS){
- if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW)
+ if(GetModelIndex() == MI_RCRAIDER || GetModelIndex() == MI_SPARROW)
m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.0005f, 0.0f);
}else if((GetModelIndex() == MI_DODO || CVehicle::bAllDodosCheat) &&
m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){
@@ -1034,20 +1028,20 @@ CAutomobile::ProcessControl(void)
else
#endif
FlyingControl(FLIGHT_MODEL_DODO);
- }else if(GetModelIndex() == MI_MIAMI_RCBARON){
+ }else if(GetModelIndex() == MI_RCBARON){
FlyingControl(FLIGHT_MODEL_RCPLANE);
- }else if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW || bAllCarCheat){
+ }else if(IsRealHeli() || bAllCarCheat){
#ifdef ALLCARSHELI_CHEAT
if (bAllCarCheat)
FlyingControl(FLIGHT_MODEL_HELI);
else
#endif
{
- if (CPad::GetPad(0)->GetCircleJustDown())
- m_aWheelSpeed[0] = Max(m_aWheelSpeed[0] - 0.03f, 0.0f);
- if (m_aWheelSpeed[0] < 0.22f)
- m_aWheelSpeed[0] += 0.0001f;
- if (m_aWheelSpeed[0] > 0.15f)
+ // if (CPad::GetPad(0)->GetCircleJustDown())
+ // m_aWheelSpeed[0] = Max(m_aWheelSpeed[0] - 0.03f, 0.0f);
+ // if (m_aWheelSpeed[0] < 0.22f)
+ // m_aWheelSpeed[0] += 0.0001f;
+ // if (m_aWheelSpeed[0] > 0.15f)
FlyingControl(FLIGHT_MODEL_HELI);
}
}
@@ -1606,7 +1600,8 @@ CAutomobile::PreRender(void)
case MI_TAXI:
case MI_CABBIE:
- case MI_BORGNINE:
+ case MI_ZEBRA:
+ case MI_KAUFMAN:
if(bTaxiLight){
CVector pos = GetPosition() + GetUp()*0.95f;
CCoronas::RegisterCorona((uintptr)this + 21,
@@ -2197,6 +2192,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
phys->RegisterReference((CEntity**)&m_aGroundPhysical[i]);
m_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition();
+#if 0
if(phys->GetModelIndex() == MI_BODYCAST && GetStatus() == STATUS_PLAYER){
// damage body cast
float speed = m_vecMoveSpeed.MagnitudeSqr();
@@ -2213,6 +2209,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
phys->AddToMovingList();
}
}
+#endif
}
m_nSurfaceTouched = m_aWheelColPoints[i].surfaceB;
@@ -2858,6 +2855,7 @@ CAutomobile::ProcessBuoyancy(void)
if(impulseRatio > 0.5f){
bIsInWater = true;
+ bIsDrowning = true;
if(m_vecMoveSpeed.z < -0.1f)
m_vecMoveSpeed.z = -0.1f;
@@ -2872,8 +2870,11 @@ CAutomobile::ProcessBuoyancy(void)
if(pPassengers[i]->IsPlayer() || !bWaterTight)
pPassengers[i]->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
}
- }else
+ }
+ else {
bIsInWater = false;
+ bIsDrowning = false;
+ }
static uint32 nGenerateRaindrops = 0;
static uint32 nGenerateWaterCircles = 0;
@@ -2955,6 +2956,7 @@ CAutomobile::ProcessBuoyancy(void)
}
}else{
bIsInWater = false;
+ bIsDrowning = false;
bTouchingWater = false;
static RwRGBA splashCol = {155, 155, 185, 196};
@@ -3029,11 +3031,15 @@ void
CAutomobile::DoDriveByShootings(void)
{
CAnimBlendAssociation *anim;
+ CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed();
+ if (playerInfo && !playerInfo->m_bDriveByAllowed)
+ return;
+
CWeapon *weapon = pDriver->GetWeapon();
- if(weapon->m_eWeaponType != WEAPONTYPE_UZI)
+ if(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != 5)
return;
- weapon->Update(pDriver->m_audioEntityId);
+ weapon->Update(pDriver->m_audioEntityId, nil);
bool lookingLeft = false;
bool lookingRight = false;
@@ -3049,37 +3055,42 @@ CAutomobile::DoDriveByShootings(void)
lookingRight = true;
}
+ AnimationId rightAnim = ANIM_DRIVEBY_R;
+ AnimationId leftAnim = ANIM_DRIVEBY_L;
+ if (pDriver->m_pMyVehicle->bLowVehicle) {
+ rightAnim = ANIM_DRIVEBY_LOW_R;
+ leftAnim = ANIM_DRIVEBY_LOW_L;
+ }
+
if(lookingLeft || lookingRight){
if(lookingLeft){
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim);
if(anim)
anim->blendDelta = -1000.0f;
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim);
if(anim == nil || anim->blendDelta < 0.0f)
- CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_L);
- else
- anim->SetRun();
+ anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, leftAnim);
}else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim);
if(anim)
anim->blendDelta = -1000.0f;
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim);
if(anim == nil || anim->blendDelta < 0.0f)
- CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_R);
- else
- anim->SetRun();
+ anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, rightAnim);
}
- if(CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer){
- weapon->FireFromCar(this, lookingLeft);
- weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;
+ if (!anim || !anim->IsRunning()) {
+ if (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) {
+ weapon->FireFromCar(this, lookingLeft);
+ weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;
+ }
}
}else{
weapon->Reload();
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim);
if(anim)
anim->blendDelta = -1000.0f;
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim);
if(anim)
anim->blendDelta = -1000.0f;
}
@@ -4036,10 +4047,22 @@ CAutomobile::PlayCarHorn(void)
{
int r;
+ if (m_nAlarmState && m_nAlarmState != -1)
+ return;
+
+ if (GetStatus() == STATUS_WRECKED)
+ return;
+
if(m_nCarHornTimer != 0)
return;
- r = CGeneral::GetRandomNumber() & 7;
+ if (m_nCarHornDelay) {
+ m_nCarHornDelay--;
+ return;
+ }
+
+ m_nCarHornDelay = (CGeneral::GetRandomNumber() & 0x7F) + 150;
+ r = m_nCarHornDelay & 7;
if(r < 2){
m_nCarHornTimer = 45;
}else if(r < 4){
@@ -4139,7 +4162,7 @@ CAutomobile::BlowUpCarsInPath(void)
{
int i;
- if(m_vecMoveSpeed.Magnitude() > 0.1f)
+ if(m_vecMoveSpeed.Magnitude() > 0.1f && bTankDetonateCars)
for(i = 0; i < m_nCollisionRecords; i++)
if(m_aCollisionRecords[i] &&
m_aCollisionRecords[i]->IsVehicle() &&
@@ -4601,6 +4624,18 @@ CAutomobile::SetAllTaxiLights(bool set)
m_sAllTaxiLights = set;
}
+void
+CAutomobile::TellHeliToGoToCoors(float x, float y, float z, uint8 speed)
+{
+ AutoPilot.m_nCarMission = MISSION_HELI_FLYTOCOORS;
+ AutoPilot.m_vecDestinationCoors.x = x;
+ AutoPilot.m_vecDestinationCoors.y = y;
+ AutoPilot.m_vecDestinationCoors.z = z;
+ AutoPilot.m_nCruiseSpeed = speed;
+ SetStatus(STATUS_PHYSICS);
+ //TODO(MIAMI)
+}
+
#ifdef COMPATIBLE_SAVES
void
CAutomobile::Save(uint8*& buf)
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index a3e8ac17..e096465e 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -36,7 +36,7 @@ enum eCarPositions
CAR_POS_TAILLIGHTS,
CAR_POS_FRONTSEAT,
CAR_POS_BACKSEAT,
- CAR_POS_EXHAUST = 9,
+ CAR_POS_EXHAUST
};
// These are used for all the wheel arrays
@@ -84,7 +84,6 @@ public:
float m_aWheelPosition[4];
float m_aWheelSpeed[4];
uint8 field_4D8;
- uint8 m_bombType : 3;
uint8 bTaxiLight : 1;
uint8 bHadDriver : 1; // for bombs
uint8 bFixedColour : 1;
@@ -92,7 +91,7 @@ public:
uint8 bWaterTight : 1; // no damage for non-player peds
uint8 bNotDamagedUpsideDown : 1;
uint8 bMoreResistantToDamage : 1;
- CEntity *m_pBombRigger;
+ uint8 bTankDetonateCars : 1;
int16 field_4E0;
uint16 m_hydraulicState;
uint32 m_nBusDoorTimerEnd;
@@ -180,6 +179,8 @@ public:
void SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents = false);
void SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents = false);
+ void TellHeliToGoToCoors(float x, float y, float z, uint8 speed);
+
void Fix(void);
void SetComponentVisibility(RwFrame *frame, uint32 flags);
void SetupModelNodes(void);
@@ -197,8 +198,6 @@ public:
static void SetAllTaxiLights(bool set);
};
-VALIDATE_SIZE(CAutomobile, 0x5A8);
-
inline uint8 GetCarDoorFlag(int32 carnode) {
switch (carnode) {
case CAR_DOOR_LF:
diff --git a/src/vehicles/Bike.h b/src/vehicles/Bike.h
index 4e7e5a0e..85cd3213 100644
--- a/src/vehicles/Bike.h
+++ b/src/vehicles/Bike.h
@@ -1,7 +1,5 @@
#pragma once
-// some miami bike leftovers
-
enum eBikeNodes {
BIKE_NODE_NONE,
BIKE_CHASSIS,
@@ -12,4 +10,13 @@ enum eBikeNodes {
BIKE_MUDGUARD,
BIKE_HANDLEBARS,
BIKE_NUM_NODES
-}; \ No newline at end of file
+};
+
+enum eBikePositions
+{
+ BIKE_POS_HEADLIGHTS,
+ BIKE_POS_TAILLIGHTS,
+ BIKE_POS_FRONTSEAT,
+ BIKE_POS_BACKSEAT,
+ BIKE_POS_EXHAUST
+};
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 72fca542..c4ac94a2 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -3,6 +3,7 @@
#include "General.h"
#include "Timecycle.h"
#include "HandlingMgr.h"
+#include "CarAI.h"
#include "CarCtrl.h"
#include "RwHelper.h"
#include "ModelIndices.h"
@@ -18,6 +19,9 @@
#include "Pools.h"
#include "Pad.h"
#include "Boat.h"
+#include "AnimBlendAssociation.h"
+#include "RpAnimBlend.h"
+#include "Record.h"
#define INVALID_ORIENTATION (-9999.99f)
@@ -96,7 +100,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)
void
CBoat::SetModelIndex(uint32 id)
{
- CEntity::SetModelIndex(id);
+ CVehicle::SetModelIndex(id);
SetupModelNodes();
}
@@ -109,9 +113,6 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos)
void
CBoat::ProcessControl(void)
{
- if(m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
- return;
-
bool onLand = m_fDamageImpulse > 0.0f && m_vecDamageNormal.z > 0.1f;
PruneWakeTrail();
@@ -151,10 +152,14 @@ CBoat::ProcessControl(void)
ProcessControlInputs(0);
if(GetModelIndex() == MI_PREDATOR)
DoFixedMachineGuns();
+
+ if (!CRecordDataForChase::IsRecording())
+ DoDriveByShootings();
break;
case STATUS_SIMPLE:
m_bIsAnchored = false;
m_fOrientation = INVALID_ORIENTATION;
+ CCarAI::UpdateCarAI(this);
CPhysical::ProcessControl();
bBoatInWater = true;
bPropellerInWater = true;
@@ -163,7 +168,8 @@ CBoat::ProcessControl(void)
case STATUS_PHYSICS:
m_bIsAnchored = false;
m_fOrientation = INVALID_ORIENTATION;
- CCarCtrl::SteerAIBoatWithPhysics(this);
+ CCarAI::UpdateCarAI(this);
+ CCarCtrl::SteerAICarWithPhysics(this);
break;
case STATUS_ABANDONED:
case STATUS_WRECKED:
@@ -267,9 +273,17 @@ CBoat::ProcessControl(void)
if(0.1f * m_fMass * GRAVITY*CTimer::GetTimeStep() < buoyanceImpulse.z){
bBoatInWater = true;
bIsInWater = true;
+ if (GetUp().z < -0.6f && Abs(GetMoveSpeed().x) < 0.05 && Abs(GetMoveSpeed().y) < 0.05) {
+ bIsDrowning = true;
+ if (pDriver)
+ pDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
+ }
+ else
+ bIsDrowning = false;
}else{
bBoatInWater = false;
bIsInWater = false;
+ bIsDrowning = false;
}
m_fVolumeUnderWater = mod_Buoyancy.m_volumeUnderWater;
@@ -295,8 +309,8 @@ CBoat::ProcessControl(void)
AddWakePoint(GetPosition());
float steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward());
- if (GetModelIndex() == MI_GHOST)
- steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward())*0.3f;
+// if (GetModelIndex() == MI_GHOST)
+// steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward())*0.3f;
if(steerFactor < 0.0f) steerFactor = 0.0f;
CVector propeller(0.0f, -pHandling->Dimension.y*m_fPropellerY, -pHandling->Dimension.z*m_fPropellerZ);
@@ -406,10 +420,10 @@ CBoat::ProcessControl(void)
}
// Slow down or push down boat as it approaches the world limits
- m_vecMoveSpeed.x = Min(m_vecMoveSpeed.x, -(GetPosition().x - 1900.0f)*0.01f); // east
- m_vecMoveSpeed.x = Max(m_vecMoveSpeed.x, -(GetPosition().x - -1515.0f)*0.01f); // west
- m_vecMoveSpeed.y = Min(m_vecMoveSpeed.y, -(GetPosition().y - 600.0f)*0.01f); // north
- m_vecMoveSpeed.y = Max(m_vecMoveSpeed.y, -(GetPosition().y - -1900.0f)*0.01f); // south
+ m_vecMoveSpeed.x = Min(m_vecMoveSpeed.x, -(GetPosition().x - (WORLD_MAX_X-100.0f))*0.01f); // east
+ m_vecMoveSpeed.x = Max(m_vecMoveSpeed.x, -(GetPosition().x - (WORLD_MIN_X+100.0f))*0.01f); // west
+ m_vecMoveSpeed.y = Min(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MAX_Y-100.0f))*0.01f); // north
+ m_vecMoveSpeed.y = Max(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MIN_Y+100.0f))*0.01f); // south
if(!onLand && bBoatInWater)
ApplyWaterResistance();
@@ -439,7 +453,7 @@ CBoat::ProcessControl(void)
speedUp = pHandling->fBrakeDeceleration - m_vecMoveSpeed.z;
if(speedUp < 0.0f) speedUp = 0.0f;
float speedFwd = DotProduct(m_vecMoveSpeed, GetForward());
- speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fTractionLoss;
+ speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fBrakeBias;
CVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp);
CVector splashImpulse = speed * m_fMass;
ApplyMoveForce(splashImpulse);
@@ -513,6 +527,7 @@ CBoat::ProcessControl(void)
}else{
bBoatInWater = false;
bIsInWater = false;
+ bIsDrowning = false;
}
if(m_bIsAnchored){
@@ -912,6 +927,68 @@ CBoat::AddWakePoint(CVector point)
}
}
+void
+CBoat::DoDriveByShootings(void)
+{
+ CAnimBlendAssociation *anim;
+ CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed();
+ if (playerInfo && !playerInfo->m_bDriveByAllowed)
+ return;
+
+ CWeapon *weapon = pDriver->GetWeapon();
+ if(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != 5)
+ return;
+
+ weapon->Update(pDriver->m_audioEntityId, nil);
+
+ bool lookingLeft = false;
+ bool lookingRight = false;
+ if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN){
+ if(CPad::GetPad(0)->GetLookLeft())
+ lookingLeft = true;
+ if(CPad::GetPad(0)->GetLookRight())
+ lookingRight = true;
+ }else{
+ if(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft)
+ lookingLeft = true;
+ if(TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
+ lookingRight = true;
+ }
+
+ if(lookingLeft || lookingRight){
+ if(lookingLeft){
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
+ if(anim)
+ anim->blendDelta = -1000.0f;
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
+ if(anim == nil || anim->blendDelta < 0.0f)
+ anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_L);
+ }else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
+ if(anim)
+ anim->blendDelta = -1000.0f;
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
+ if(anim == nil || anim->blendDelta < 0.0f)
+ anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_R);
+ }
+
+ if (!anim || !anim->IsRunning()) {
+ if (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) {
+ weapon->FireFromCar(this, lookingLeft);
+ weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;
+ }
+ }
+ }else{
+ weapon->Reload();
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
+ if(anim)
+ anim->blendDelta = -1000.0f;
+ anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
+ if(anim)
+ anim->blendDelta = -1000.0f;
+ }
+}
+
#ifdef COMPATIBLE_SAVES
void
CBoat::Save(uint8*& buf)
diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h
index 3cc3513d..c8168db0 100644
--- a/src/vehicles/Boat.h
+++ b/src/vehicles/Boat.h
@@ -5,8 +5,12 @@
enum eBoatNodes
{
BOAT_MOVING = 1,
+ BOAT_WINDSCREEN,
BOAT_RUDDER,
- BOAT_WINDSCREEN
+ BOAT_FLAP_LEFT,
+ BOAT_FLAP_RIGHT,
+ BOAT_REARFLAP_LEFT,
+ BOAT_REARFLAP_RIGHT
};
class CBoat : public CVehicle
@@ -57,6 +61,7 @@ public:
void SetupModelNodes();
void PruneWakeTrail(void);
void AddWakePoint(CVector point);
+ void DoDriveByShootings(void);
static CBoat *apFrameWakeGeneratingBoats[4];
@@ -72,8 +77,6 @@ public:
};
-VALIDATE_SIZE(CBoat, 0x484);
-
extern float MAX_WAKE_LENGTH;
extern float MIN_WAKE_INTERVAL;
extern float WAKE_LIFETIME; \ No newline at end of file
diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp
index 72b6c30c..7c02f3ee 100644
--- a/src/vehicles/CarGen.cpp
+++ b/src/vehicles/CarGen.cpp
@@ -12,7 +12,9 @@
#include "Streaming.h"
#include "Timer.h"
#include "Vehicle.h"
+#include "VisibilityPlugins.h"
#include "World.h"
+#include "Zones.h"
uint8 CTheCarGenerators::ProcessCounter;
uint32 CTheCarGenerators::NumOfCarGenerators;
@@ -38,21 +40,43 @@ uint32 CCarGenerator::CalcNextGen()
return CTimer::GetTimeInMilliseconds() + 4;
}
+//TODO(MIAMI): check for more changes - so far only -1 mi is accounted for
void CCarGenerator::DoInternalProcessing()
{
- if (CheckForBlockage()) {
- m_nTimer += 4;
- if (m_nUsesRemaining == 0)
- --CTheCarGenerators::CurrentActiveCount;
- return;
- }
+ int mi;
if (CCarCtrl::NumParkedCars >= 10)
return;
- CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY);
- if (!CStreaming::HasModelLoaded(m_nModelIndex))
+ if (m_nModelIndex >= 0) {
+ if (CheckForBlockage(m_nModelIndex)) {
+ m_nTimer += 4;
+ return;
+ }
+ mi = m_nModelIndex;
+ }
+ else {
+ mi = -m_nModelIndex;
+ if (m_nModelIndex == -1 || !CStreaming::HasModelLoaded(mi)) {
+ CZoneInfo pZone;
+ CTheZones::GetZoneInfoForTimeOfDay(&FindPlayerCoors(), &pZone);
+ mi = CCarCtrl::ChooseCarModel(CCarCtrl::ChooseCarRating(&pZone));
+ if (mi < 0)
+ return;
+ m_nModelIndex = -mi;
+ m_nColor1 = -1;
+ m_nColor2 = -1;
+ }
+ if (CheckForBlockage(mi)) {
+ m_nTimer += 4;
+ return;
+ }
+ }
+ CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
+ if (!CStreaming::HasModelLoaded(mi))
return;
- if (CModelInfo::IsBoatModel(m_nModelIndex)){
- CBoat* pBoat = new CBoat(m_nModelIndex, PARKED_VEHICLE);
+ CVehicle* pVehicle;
+ if (CModelInfo::IsBoatModel(mi)){
+ CBoat* pBoat = new CBoat(mi, PARKED_VEHICLE);
+ pVehicle = pBoat;
pBoat->bIsStatic = false;
pBoat->bEngineOn = false;
CVector pos = m_vecPos;
@@ -63,17 +87,7 @@ void CCarGenerator::DoInternalProcessing()
pBoat->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
pBoat->SetStatus(STATUS_ABANDONED);
pBoat->m_nDoorLock = CARLOCK_UNLOCKED;
- CWorld::Add(pBoat);
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
- pBoat->m_nAlarmState = -1;
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
- pBoat->m_nDoorLock = CARLOCK_LOCKED;
- if (m_nColor1 != -1 && m_nColor2){
- pBoat->m_currentColour1 = m_nColor1;
- pBoat->m_currentColour2 = m_nColor2;
- }
- m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat);
- }else{
+ }else{ // TODO(MIAMI): bikes
bool groundFound = false;
CVector pos = m_vecPos;
if (pos.z > -100.0f){
@@ -88,28 +102,35 @@ void CCarGenerator::DoInternalProcessing()
}
if (!groundFound) {
debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y);
- }else{
- CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE);
- pCar->bIsStatic = false;
- pCar->bEngineOn = false;
- pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel();
- pCar->SetPosition(pos);
- pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
- pCar->SetStatus(STATUS_ABANDONED);
- pCar->bLightsOn = false;
- pCar->m_nDoorLock = CARLOCK_UNLOCKED;
- CWorld::Add(pCar);
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
- pCar->m_nAlarmState = -1;
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
- pCar->m_nDoorLock = CARLOCK_LOCKED;
- if (m_nColor1 != -1 && m_nColor2) {
- pCar->m_currentColour1 = m_nColor1;
- pCar->m_currentColour2 = m_nColor2;
- }
- m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pCar);
+ return;
}
+ CAutomobile* pCar = new CAutomobile(mi, PARKED_VEHICLE);
+ pVehicle = pCar;
+ pCar->bIsStatic = false;
+ pCar->bEngineOn = false;
+ pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel();
+ pCar->SetPosition(pos);
+ pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
+ pCar->SetStatus(STATUS_ABANDONED);
+ pCar->bLightsOn = false;
+ pCar->m_nDoorLock = CARLOCK_UNLOCKED;
+
+ }
+ CWorld::Add(pVehicle);
+ if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
+ pVehicle->m_nAlarmState = -1;
+ if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
+ pVehicle->m_nDoorLock = CARLOCK_LOCKED;
+ if (m_nColor1 != -1 && m_nColor2 != -1) {
+ pVehicle->m_currentColour1 = m_nColor1;
+ pVehicle->m_currentColour2 = m_nColor2;
}
+ else if (m_nModelIndex < -1) {
+ m_nColor1 = pVehicle->m_currentColour1;
+ m_nColor2 = pVehicle->m_currentColour2;
+ }
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
+ m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pVehicle);
if (m_nUsesRemaining < -1) /* I don't think this is a correct comparasion */
--m_nUsesRemaining;
m_nTimer = CalcNextGen();
@@ -155,25 +176,33 @@ void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int1
m_nTimer = CTimer::GetTimeInMilliseconds() + 1;
m_nUsesRemaining = 0;
m_bIsBlocking = false;
- m_vecInf = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.min;
- m_vecSup = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.max;
- m_fSize = Max(m_vecInf.Magnitude(), m_vecSup.Magnitude());
}
-bool CCarGenerator::CheckForBlockage()
+bool CCarGenerator::CheckForBlockage(int32 mi)
{
int16 entities;
- CWorld::FindObjectsKindaColliding(CVector(m_vecPos), m_fSize, 1, &entities, 2, nil, false, true, true, false, false);
- return entities > 0;
+ CEntity* pEntities[8];
+ CColModel* pColModel = CModelInfo::GetModelInfo(mi)->GetColModel();
+ CWorld::FindObjectsKindaColliding(CVector(m_vecPos), pColModel->boundingSphere.radius, 1, &entities, 8, pEntities, false, true, true, false, false);
+ for (int i = 0; i < entities; i++) {
+ if (m_vecPos.z + pColModel->boundingBox.min.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.max.z + 1.0f &&
+ m_vecPos.z + pColModel->boundingBox.max.z > pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) {
+ m_bIsBlocking = true;
+ return true;
+ }
+ }
+ return false;
}
bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer()
{
CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos;
float distance = direction.Magnitude();
- float farclip = 120.0f * TheCamera.GenerationDistMultiplier;
+ float farclip = 110.0f * TheCamera.GenerationDistMultiplier;
float nearclip = farclip - 20.0f;
- if (distance >= farclip){
+ bool canBeRemoved = (m_nModelIndex > 0 && CModelInfo::IsBoatModel(m_nModelIndex) && 165.0f * TheCamera.GenerationDistMultiplier > distance &&
+ TheCamera.IsPointVisible(m_vecPos, &TheCamera.GetCameraMatrix())); // TODO(MIAMI) COcclision::IsPositionOccluded(m_vecPos, 0.0f)
+ if (distance >= farclip || canBeRemoved){
if (m_bIsBlocking)
m_bIsBlocking = false;
return false;
diff --git a/src/vehicles/CarGen.h b/src/vehicles/CarGen.h
index 9d645318..684f93ee 100644
--- a/src/vehicles/CarGen.h
+++ b/src/vehicles/CarGen.h
@@ -22,9 +22,6 @@ class CCarGenerator
int32 m_nVehicleHandle;
uint16 m_nUsesRemaining;
bool m_bIsBlocking;
- CVector m_vecInf;
- CVector m_vecSup;
- float m_fSize;
public:
void SwitchOff();
void SwitchOn();
@@ -32,7 +29,7 @@ public:
void DoInternalProcessing();
void Process();
void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
- bool CheckForBlockage();
+ bool CheckForBlockage(int32 mi);
bool CheckIfWithinRangeOfAnyPlayer();
void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; }
};
diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp
index 9c8f9fda..5a165c00 100644
--- a/src/vehicles/Cranes.cpp
+++ b/src/vehicles/Cranes.cpp
@@ -57,7 +57,8 @@ void CCranes::InitCranes(void)
}
}
}
- for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode = pNode->next) {
+ // TODO(MIAMI): LEVEL_MAINLAND just so it compiles
+ for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_MAINLAND).first; pNode; pNode = pNode->next) {
CEntity* pEntity = (CEntity*)pNode->item;
if (MODELID_CRANE_1 == pEntity->GetModelIndex() ||
MODELID_CRANE_2 == pEntity->GetModelIndex() ||
@@ -87,6 +88,7 @@ void CCranes::AddThisOneCrane(CEntity* pEntity)
if (pCrane->m_nAudioEntity >= 0)
DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1);
pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex());
+#if 0
// Is this used to avoid military crane?
if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) {
CObject* pHook = new CObject(MI_MAGNET, false);
@@ -99,6 +101,7 @@ void CCranes::AddThisOneCrane(CEntity* pEntity)
pCrane->SetHookMatrix();
}
else
+#endif
pCrane->m_pHook = nil;
NumCranes++;
}
diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp
index 5beed29e..3d5d4e77 100644
--- a/src/vehicles/HandlingMgr.cpp
+++ b/src/vehicles/HandlingMgr.cpp
@@ -4,6 +4,8 @@
#include "FileMgr.h"
#include "HandlingMgr.h"
+//--MIAMI: done
+
cHandlingDataMgr mod_HandlingManager;
const char *HandlingFilename = "HANDLING.CFG";
@@ -21,7 +23,6 @@ const char VehicleNames[NUMHANDLINGS][14] = {
"STRETCH",
"MANANA",
"INFERNUS",
- "BLISTA",
"PONY",
"MULE",
"CHEETAH",
@@ -38,7 +39,6 @@ const char VehicleNames[NUMHANDLINGS][14] = {
"ENFORCER",
"SECURICA",
"BANSHEE",
- "PREDATOR",
"BUS",
"RHINO",
"BARRACKS",
@@ -50,22 +50,73 @@ const char VehicleNames[NUMHANDLINGS][14] = {
"STALLION",
"RUMPO",
"RCBANDIT",
- "BELLYUP",
- "MRWONGS",
"MAFIA",
- "YARDIE",
- "YAKUZA",
- "DIABLOS",
- "COLUMB",
- "HOODS",
"AIRTRAIN",
"DEADDODO",
- "SPEEDER",
- "REEFER",
- "PANLANT",
"FLATBED",
"YANKEE",
- "BORGNINE"
+ "GOLFCART",
+ "VOODOO",
+ "WASHING",
+ "CUBAN",
+ "ROMERO",
+ "PACKER",
+ "ADMIRAL",
+ "GANGBUR",
+ "ZEBRA",
+ "TOPFUN",
+ "GLENDALE",
+ "OCEANIC",
+ "HERMES",
+ "SABRE1",
+ "SABRETUR",
+ "PHEONIX",
+ "WALTON",
+ "REGINA",
+ "COMET",
+ "DELUXO",
+ "BURRITO",
+ "SPAND",
+ "BAGGAGE",
+ "KAUFMAN",
+ "RANCHER",
+ "FBIRANCH",
+ "VIRGO",
+ "GREENWOO",
+ "HOTRING",
+ "SANDKING",
+ "BLISTAC",
+ "BOXVILLE",
+ "BENSON",
+ "DESPERAD",
+ "LOVEFIST",
+ "BLOODRA",
+ "BLOODRB",
+ "BIKE",
+ "MOPED",
+ "DIRTBIKE",
+ "ANGEL",
+ "FREEWAY",
+ "PREDATOR",
+ "SPEEDER",
+ "REEFER",
+ "RIO",
+ "SQUALO",
+ "TROPIC",
+ "COASTGRD",
+ "DINGHY",
+ "MARQUIS",
+ "CUPBOAT",
+ "SEAPLANE",
+ "SPARROW",
+ "SEASPAR",
+ "MAVERICK",
+ "COASTMAV",
+ "POLMAV",
+ "HUNTER",
+ "RCBARON",
+ "RCGOBLIN",
+ "RCCOPTER"
};
cHandlingDataMgr::cHandlingDataMgr(void)
@@ -94,6 +145,9 @@ cHandlingDataMgr::LoadHandlingData(void)
int field, handlingId;
int keepGoing;
tHandlingData *handling;
+ tFlyingHandlingData *flyingHandling;
+ tBoatHandlingData *boatHandling;
+ tBikeHandlingData *bikeHandling;
CFileMgr::SetDir("DATA");
CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r");
@@ -102,6 +156,9 @@ cHandlingDataMgr::LoadHandlingData(void)
start = (char*)work_buff;
end = start+1;
handling = nil;
+ flyingHandling = nil;
+ boatHandling = nil;
+ bikeHandling = nil;
keepGoing = 1;
while(keepGoing){
@@ -118,55 +175,157 @@ cHandlingDataMgr::LoadHandlingData(void)
if(strncmp(line, ";the end", 9) == 0)
keepGoing = 0;
else if(line[0] != ';'){
- field = 0;
- strcpy(delim, " \t");
- // FIX: game seems to use a do-while loop here
- for(word = strtok(line, delim); word; word = strtok(nil, delim)){
- switch(field){
- case 0:
- handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
- assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
- handling = &HandlingData[handlingId];
- handling->nIdentifier = (eHandlingId)handlingId;
- break;
- case 1: handling->fMass = strtod(word, nil); break;
- case 2: handling->Dimension.x = strtod(word, nil); break;
- case 3: handling->Dimension.y = strtod(word, nil); break;
- case 4: handling->Dimension.z = strtod(word, nil); break;
- case 5: handling->CentreOfMass.x = strtod(word, nil); break;
- case 6: handling->CentreOfMass.y = strtod(word, nil); break;
- case 7: handling->CentreOfMass.z = strtod(word, nil); break;
- case 8: handling->nPercentSubmerged = atoi(word); break;
- case 9: handling->fTractionMultiplier = strtod(word, nil); break;
- case 10: handling->fTractionLoss = strtod(word, nil); break;
- case 11: handling->fTractionBias = strtod(word, nil); break;
- case 12: handling->Transmission.nNumberOfGears = atoi(word); break;
- case 13: handling->Transmission.fMaxVelocity = strtod(word, nil); break;
- case 14: handling->Transmission.fEngineAcceleration = strtod(word, nil) * 0.4f; break;
- case 15: handling->Transmission.nDriveType = word[0]; break;
- case 16: handling->Transmission.nEngineType = word[0]; break;
- case 17: handling->fBrakeDeceleration = strtod(word, nil); break;
- case 18: handling->fBrakeBias = strtod(word, nil); break;
- case 19: handling->bABS = !!atoi(word); break;
- case 20: handling->fSteeringLock = strtod(word, nil); break;
- case 21: handling->fSuspensionForceLevel = strtod(word, nil); break;
- case 22: handling->fSuspensionDampingLevel = strtod(word, nil); break;
- case 23: handling->fSeatOffsetDistance = strtod(word, nil); break;
- case 24: handling->fCollisionDamageMultiplier = strtod(word, nil); break;
- case 25: handling->nMonetaryValue = atoi(word); break;
- case 26: handling->fSuspensionUpperLimit = strtod(word, nil); break;
- case 27: handling->fSuspensionLowerLimit = strtod(word, nil); break;
- case 28: handling->fSuspensionBias = strtod(word, nil); break;
- case 29:
- sscanf(word, "%x", &handling->Flags);
- handling->Transmission.Flags = handling->Flags;
- break;
- case 30: handling->FrontLights = atoi(word); break;
- case 31: handling->RearLights = atoi(word); break;
+ if(line[0] == '!'){
+ // Bike data
+ field = 0;
+ strcpy(delim, " \t");
+ // FIX: game seems to use a do-while loop here
+ for(word = strtok(line, delim); word; word = strtok(nil, delim)){
+ switch(field){
+ case 0: break;
+ case 1:
+ handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
+ assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
+ bikeHandling = GetBikePointer(handlingId);
+ bikeHandling->nIdentifier = (eHandlingId)handlingId;
+ break;
+ case 2: bikeHandling->fLeanFwdCOM = atof(word); break;
+ case 3: bikeHandling->fLeanFwdForce = atof(word); break;
+ case 4: bikeHandling->fLeanBakCOM = atof(word); break;
+ case 5: bikeHandling->fLeanBackForce = atof(word); break;
+ case 6: bikeHandling->fMaxLean = atof(word); break;
+ case 7: bikeHandling->fFullAnimLean = atof(word); break;
+ case 8: bikeHandling->fDesLean = atof(word); break;
+ case 9: bikeHandling->fSpeedSteer = atof(word); break;
+ case 10: bikeHandling->fSlipSteer = atof(word); break;
+ case 11: bikeHandling->fNoPlayerCOMz = atof(word); break;
+ case 12: bikeHandling->fWheelieAng = atof(word); break;
+ case 13: bikeHandling->fStoppieAng = atof(word); break;
+ case 14: bikeHandling->fWheelieSteer = atof(word); break;
+ case 15: bikeHandling->fWheelieStabMult = atof(word); break;
+ case 16: bikeHandling->fStoppieStabMult = atof(word); break;
+ }
+ field++;
+ }
+ ConvertBikeDataToGameUnits(bikeHandling);
+ }else if(line[0] == '$'){
+ // Flying data
+ field = 0;
+ strcpy(delim, " \t");
+ // FIX: game seems to use a do-while loop here
+ for(word = strtok(line, delim); word; word = strtok(nil, delim)){
+ switch(field){
+ case 0: break;
+ case 1:
+ handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
+ assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
+ flyingHandling = GetFlyingPointer(handlingId);
+ flyingHandling->nIdentifier = (eHandlingId)handlingId;
+ break;
+ case 2: flyingHandling->fThrust = atof(word); break;
+ case 3: flyingHandling->fThrustFallOff = atof(word); break;
+ case 4: flyingHandling->fYaw = atof(word); break;
+ case 5: flyingHandling->fYawStab = atof(word); break;
+ case 6: flyingHandling->fSideSlip = atof(word); break;
+ case 7: flyingHandling->fRoll = atof(word); break;
+ case 8: flyingHandling->fRollStab = atof(word); break;
+ case 9: flyingHandling->fPitch = atof(word); break;
+ case 10: flyingHandling->fPitchStab = atof(word); break;
+ case 11: flyingHandling->fFormLift = atof(word); break;
+ case 12: flyingHandling->fAttackLift = atof(word); break;
+ case 13: flyingHandling->fMoveRes = atof(word); break;
+ case 14: flyingHandling->vecTurnRes.x = atof(word); break;
+ case 15: flyingHandling->vecTurnRes.y = atof(word); break;
+ case 16: flyingHandling->vecTurnRes.z = atof(word); break;
+ case 17: flyingHandling->vecSpeedRes.x = atof(word); break;
+ case 18: flyingHandling->vecSpeedRes.y = atof(word); break;
+ case 19: flyingHandling->vecSpeedRes.z = atof(word); break;
+ }
+ field++;
+ }
+ }else if(line[0] == '%'){
+ // Boat data
+ field = 0;
+ strcpy(delim, " \t");
+ // FIX: game seems to use a do-while loop here
+ for(word = strtok(line, delim); word; word = strtok(nil, delim)){
+ switch(field){
+ case 0: break;
+ case 1:
+ handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
+ assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
+ boatHandling = GetBoatPointer(handlingId);
+ boatHandling->nIdentifier = (eHandlingId)handlingId;
+ break;
+ case 2: boatHandling->fThrustY = atof(word); break;
+ case 3: boatHandling->fThrustZ = atof(word); break;
+ case 4: boatHandling->fThrustAppZ = atof(word); break;
+ case 5: boatHandling->fAqPlaneForce = atof(word); break;
+ case 6: boatHandling->fAqPlaneLimit = atof(word); break;
+ case 7: boatHandling->fAqPlaneOffset = atof(word); break;
+ case 8: boatHandling->fWaveAudioMult = atof(word); break;
+ case 9: boatHandling->vecMoveRes.x = atof(word); break;
+ case 10: boatHandling->vecMoveRes.y = atof(word); break;
+ case 11: boatHandling->vecMoveRes.z = atof(word); break;
+ case 12: boatHandling->vecTurnRes.x = atof(word); break;
+ case 13: boatHandling->vecTurnRes.y = atof(word); break;
+ case 14: boatHandling->vecTurnRes.z = atof(word); break;
+ case 15: boatHandling->fLook_L_R_BehindCamHeight = atof(word); break;
+ }
+ field++;
}
- field++;
+ }else{
+ field = 0;
+ strcpy(delim, " \t");
+ // FIX: game seems to use a do-while loop here
+ for(word = strtok(line, delim); word; word = strtok(nil, delim)){
+ switch(field){
+ case 0:
+ handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
+ assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
+ handling = &HandlingData[handlingId];
+ handling->nIdentifier = (eHandlingId)handlingId;
+ break;
+ case 1: handling->fMass = atof(word); break;
+ case 2: handling->Dimension.x = atof(word); break;
+ case 3: handling->Dimension.y = atof(word); break;
+ case 4: handling->Dimension.z = atof(word); break;
+ case 5: handling->CentreOfMass.x = atof(word); break;
+ case 6: handling->CentreOfMass.y = atof(word); break;
+ case 7: handling->CentreOfMass.z = atof(word); break;
+ case 8: handling->nPercentSubmerged = atoi(word); break;
+ case 9: handling->fTractionMultiplier = atof(word); break;
+ case 10: handling->fTractionLoss = atof(word); break;
+ case 11: handling->fTractionBias = atof(word); break;
+ case 12: handling->Transmission.nNumberOfGears = atoi(word); break;
+ case 13: handling->Transmission.fMaxVelocity = atof(word); break;
+ case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4f; break;
+ case 15: handling->Transmission.nDriveType = word[0]; break;
+ case 16: handling->Transmission.nEngineType = word[0]; break;
+ case 17: handling->fBrakeDeceleration = atof(word); break;
+ case 18: handling->fBrakeBias = atof(word); break;
+ case 19: handling->bABS = !!atoi(word); break;
+ case 20: handling->fSteeringLock = atof(word); break;
+ case 21: handling->fSuspensionForceLevel = atof(word); break;
+ case 22: handling->fSuspensionDampingLevel = atof(word); break;
+ case 23: handling->fSeatOffsetDistance = atof(word); break;
+ case 24: handling->fCollisionDamageMultiplier = atof(word); break;
+ case 25: handling->nMonetaryValue = atoi(word); break;
+ case 26: handling->fSuspensionUpperLimit = atof(word); break;
+ case 27: handling->fSuspensionLowerLimit = atof(word); break;
+ case 28: handling->fSuspensionBias = atof(word); break;
+ case 29: handling->fSuspensionAntidiveMultiplier = atof(word); break;
+ case 30:
+ sscanf(word, "%x", &handling->Flags);
+ handling->Transmission.Flags = handling->Flags;
+ break;
+ case 31: handling->FrontLights = atoi(word); break;
+ case 32: handling->RearLights = atoi(word); break;
+ }
+ field++;
+ }
+ ConvertDataToGameUnits(handling);
}
- ConvertDataToGameUnits(handling);
}
}
}
@@ -199,6 +358,7 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
if(handling->fTurnMass < 10.0f)
handling->fTurnMass *= 5.0f;
handling->fInvMass = 1.0f/handling->fMass;
+ handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;
handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * 0.008f*handling->fMass;
// What the hell is going on here?
@@ -214,11 +374,16 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
if(handling->nIdentifier == HANDLING_RCBANDIT){
handling->Transmission.fUnkMaxVelocity = handling->Transmission.fMaxVelocity;
+ handling->Transmission.fMaxReverseVelocity = -handling->Transmission.fMaxVelocity;
+ }else if(handling->nIdentifier >= HANDLING_BIKE && handling->nIdentifier <= HANDLING_FREEWAY){
+ handling->Transmission.fUnkMaxVelocity = velocity;
+ handling->Transmission.fMaxVelocity = velocity * 1.2f;
+ handling->Transmission.fMaxReverseVelocity = -0.05f;
}else{
handling->Transmission.fUnkMaxVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
+ handling->Transmission.fMaxReverseVelocity = -0.2f;
}
- handling->Transmission.fMaxReverseVelocity = -0.2f;
if(handling->Transmission.nDriveType == '4')
handling->Transmission.fEngineAcceleration /= 4.0f;
@@ -228,6 +393,15 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
handling->Transmission.InitGearRatios();
}
+void
+cHandlingDataMgr::ConvertBikeDataToGameUnits(tBikeHandlingData *handling)
+{
+ handling->fMaxLean = Sin(DEGTORAD(handling->fMaxLean));
+ handling->fFullAnimLean = DEGTORAD(handling->fFullAnimLean);
+ handling->fWheelieAng = Sin(DEGTORAD(handling->fWheelieAng));
+ handling->fStoppieAng = Sin(DEGTORAD(handling->fStoppieAng));
+}
+
int32
cHandlingDataMgr::GetHandlingId(const char *name)
{
@@ -237,3 +411,19 @@ cHandlingDataMgr::GetHandlingId(const char *name)
break;
return i;
}
+
+tFlyingHandlingData*
+cHandlingDataMgr::GetFlyingPointer(uint8 id)
+{
+ if(id >= HANDLING_SEAPLANE && id <= HANDLING_RCCOPTER)
+ return &FlyingHandlingData[id-HANDLING_SEAPLANE];
+ return &FlyingHandlingData[0];
+}
+
+tBoatHandlingData*
+cHandlingDataMgr::GetBoatPointer(uint8 id)
+{
+ if(id >= HANDLING_PREDATOR && id <= HANDLING_SEAPLANE)
+ return &BoatHandlingData[id-HANDLING_PREDATOR];
+ return &BoatHandlingData[0];
+}
diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h
index 10e25573..e93f7879 100644
--- a/src/vehicles/HandlingMgr.h
+++ b/src/vehicles/HandlingMgr.h
@@ -16,7 +16,6 @@ enum eHandlingId
HANDLING_STRETCH,
HANDLING_MANANA,
HANDLING_INFERNUS,
- HANDLING_BLISTA,
HANDLING_PONY,
HANDLING_MULE,
HANDLING_CHEETAH,
@@ -33,7 +32,6 @@ enum eHandlingId
HANDLING_ENFORCER,
HANDLING_SECURICA,
HANDLING_BANSHEE,
- HANDLING_PREDATOR,
HANDLING_BUS,
HANDLING_RHINO,
HANDLING_BARRACKS,
@@ -45,24 +43,81 @@ enum eHandlingId
HANDLING_STALLION,
HANDLING_RUMPO,
HANDLING_RCBANDIT,
- HANDLING_BELLYUP,
- HANDLING_MRWONGS,
HANDLING_MAFIA,
- HANDLING_YARDIE,
- HANDLING_YAKUZA,
- HANDLING_DIABLOS,
- HANDLING_COLUMB,
- HANDLING_HOODS,
HANDLING_AIRTRAIN,
HANDLING_DEADDODO,
- HANDLING_SPEEDER,
- HANDLING_REEFER,
- HANDLING_PANLANT,
HANDLING_FLATBED,
HANDLING_YANKEE,
- HANDLING_BORGNINE,
+ HANDLING_GOLFCART,
+ HANDLING_VOODOO,
+ HANDLING_WASHING,
+ HANDLING_CUBAN,
+ HANDLING_ROMERO,
+ HANDLING_PACKER,
+ HANDLING_ADMIRAL,
+ HANDLING_GANGBUR,
+ HANDLING_ZEBRA,
+ HANDLING_TOPFUN,
+ HANDLING_GLENDALE,
+ HANDLING_OCEANIC,
+ HANDLING_HERMES,
+ HANDLING_SABRE1,
+ HANDLING_SABRETUR,
+ HANDLING_PHEONIX,
+ HANDLING_WALTON,
+ HANDLING_REGINA,
+ HANDLING_COMET,
+ HANDLING_DELUXO,
+ HANDLING_BURRITO,
+ HANDLING_SPAND,
+ HANDLING_BAGGAGE,
+ HANDLING_KAUFMAN,
+ HANDLING_RANCHER,
+ HANDLING_FBIRANCH,
+ HANDLING_VIRGO,
+ HANDLING_GREENWOO,
+ HANDLING_HOTRING,
+ HANDLING_SANDKING,
+ HANDLING_BLISTAC,
+ HANDLING_BOXVILLE,
+ HANDLING_BENSON,
+ HANDLING_DESPERAD,
+ HANDLING_LOVEFIST,
+ HANDLING_BLOODRA,
+ HANDLING_BLOODRB,
- NUMHANDLINGS
+ HANDLING_BIKE,
+ HANDLING_MOPED,
+ HANDLING_DIRTBIKE,
+ HANDLING_ANGEL,
+ HANDLING_FREEWAY,
+
+ HANDLING_PREDATOR,
+ HANDLING_SPEEDER,
+ HANDLING_REEFER,
+ HANDLING_RIO,
+ HANDLING_SQUALO,
+ HANDLING_TROPIC,
+ HANDLING_COASTGRD,
+ HANDLING_DINGHY,
+ HANDLING_MARQUIS,
+ HANDLING_CUPBOAT,
+ HANDLING_SEAPLANE, // both boat and plane!
+ HANDLING_SPARROW,
+ HANDLING_SEASPAR,
+ HANDLING_MAVERICK,
+ HANDLING_COASTMAV,
+ HANDLING_POLMAV,
+ HANDLING_HUNTER,
+ HANDLING_RCBARON,
+ HANDLING_RCGOBLIN,
+ HANDLING_RCCOPTER,
+
+ NUMHANDLINGS,
+
+ NUMBIKEHANDLINGS = HANDLING_FREEWAY+1 - HANDLING_BIKE,
+ NUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_SEAPLANE,
+ NUMBOATHANDLINGS = HANDLING_SEAPLANE+1 - HANDLING_PREDATOR,
};
enum
@@ -83,6 +138,18 @@ enum
HANDLING_HAS_NO_ROOF = 0x2000,
HANDLING_IS_BIG = 0x4000,
HANDLING_HALOGEN_LIGHTS = 0x8000,
+ HANDLING_IS_BIKE = 0x10000,
+ HANDLING_IS_HELI = 0x20000,
+ HANDLING_IS_PLANE = 0x40000,
+ HANDLING_IS_BOAT = 0x80000,
+ HANDLING_NO_EXHAUST = 0x100000,
+ HANDLING_REARWHEEL_1ST = 0x200000,
+ HANDLING_HANDBRAKE_TYRE = 0x400000,
+ HANDLING_SIT_IN_BOAT = 0x800000,
+ HANDLING_FAT_REARW = 0x1000000,
+ HANDLING_NARROW_FRONTW = 0x2000000,
+ HANDLING_GOOD_INSAND = 0x4000000,
+ HANDLING_UNKNOWN = 0x8000000, // something for helis and planes
};
struct tHandlingData
@@ -109,6 +176,7 @@ struct tHandlingData
float fSuspensionUpperLimit;
float fSuspensionLowerLimit;
float fSuspensionBias;
+ float fSuspensionAntidiveMultiplier;
float fCollisionDamageMultiplier;
uint32 Flags;
float fSeatOffsetDistance;
@@ -116,7 +184,60 @@ struct tHandlingData
int8 FrontLights;
int8 RearLights;
};
-VALIDATE_SIZE(tHandlingData, 0xD8);
+
+struct tBikeHandlingData
+{
+ eHandlingId nIdentifier;
+ float fLeanFwdCOM;
+ float fLeanFwdForce;
+ float fLeanBakCOM;
+ float fLeanBackForce;
+ float fMaxLean;
+ float fFullAnimLean;
+ float fDesLean;
+ float fSpeedSteer;
+ float fSlipSteer;
+ float fNoPlayerCOMz;
+ float fWheelieAng;
+ float fStoppieAng;
+ float fWheelieSteer;
+ float fWheelieStabMult;
+ float fStoppieStabMult;
+};
+
+struct tBoatHandlingData
+{
+ eHandlingId nIdentifier;
+ float fThrustY;
+ float fThrustZ;
+ float fThrustAppZ;
+ float fAqPlaneForce;
+ float fAqPlaneLimit;
+ float fAqPlaneOffset;
+ float fWaveAudioMult;
+ float fLook_L_R_BehindCamHeight;
+ CVector vecMoveRes;
+ CVector vecTurnRes;
+};
+
+struct tFlyingHandlingData
+{
+ eHandlingId nIdentifier;
+ float fThrust;
+ float fThrustFallOff;
+ float fYaw;
+ float fYawStab;
+ float fSideSlip;
+ float fRoll;
+ float fRollStab;
+ float fPitch;
+ float fPitchStab;
+ float fFormLift;
+ float fAttackLift;
+ float fMoveRes;
+ CVector vecTurnRes;
+ CVector vecSpeedRes;
+};
class cHandlingDataMgr
{
@@ -128,7 +249,9 @@ private:
float field_C; // unused it seems
float field_10; //
tHandlingData HandlingData[NUMHANDLINGS];
- uint32 field_302C; // unused it seems
+ tBikeHandlingData BikeHandlingData[NUMBIKEHANDLINGS];
+ tFlyingHandlingData FlyingHandlingData[NUMFLYINGHANDLINGS];
+ tBoatHandlingData BoatHandlingData[NUMBOATHANDLINGS];
public:
cHandlingDataMgr(void);
@@ -136,10 +259,13 @@ public:
void LoadHandlingData(void);
int FindExactWord(const char *word, const char *words, int wordLen, int numWords);
void ConvertDataToGameUnits(tHandlingData *handling);
+ void ConvertBikeDataToGameUnits(tBikeHandlingData *handling);
int32 GetHandlingId(const char *name);
tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; }
+ tBikeHandlingData *GetBikePointer(uint8 id) { return &BikeHandlingData[id-HANDLING_BIKE]; }
+ tFlyingHandlingData *GetFlyingPointer(uint8 id);
+ tBoatHandlingData *GetBoatPointer(uint8 id);
bool HasRearWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'R'; }
bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; }
};
-VALIDATE_SIZE(cHandlingDataMgr, 0x3030);
extern cHandlingDataMgr mod_HandlingManager;
diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp
index 7b62b461..5cd6488a 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -776,7 +776,6 @@ CHeli::InitHelis(void)
for(i = 0; i < NUM_HELIS; i++)
pHelis[i] = nil;
- ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1);
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);
}
@@ -787,10 +786,7 @@ GenerateHeli(bool catalina)
CVector heliPos;
int i;
- if(catalina)
- heli = new CHeli(MI_ESCAPE, PERMANENT_VEHICLE);
- else
- heli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE);
+ heli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE);
if(catalina)
heliPos = CVector(-224.0f, 201.0f, 83.0f);
@@ -867,18 +863,6 @@ CHeli::UpdateHelis(void)
pHelis[HELI_SCRIPT]->m_heliStatus = HELI_STATUS_FLY_AWAY;
}
- // Handle Catalina's heli
- if(CatalinaHeliOn){
- if(CStreaming::HasModelLoaded(MI_ESCAPE) && pHelis[HELI_CATALINA] == nil){
- pHelis[HELI_CATALINA] = GenerateHeli(true);
- pHelis[HELI_CATALINA]->m_heliType = HELI_TYPE_CATALINA;
- }else
- CStreaming::RequestModel(MI_ESCAPE, STREAMFLAGS_DONT_REMOVE);
- }else{
- if(pHelis[HELI_CATALINA])
- pHelis[HELI_CATALINA]->m_heliStatus = HELI_STATUS_FLY_AWAY;
- }
-
// Delete helis that we no longer need
for(i = 0; i < NUM_HELIS; i++)
if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_FLY_AWAY && pHelis[i]->GetPosition().z > 150.0f){
diff --git a/src/vehicles/Heli.h b/src/vehicles/Heli.h
index cf3f791f..a8f604aa 100644
--- a/src/vehicles/Heli.h
+++ b/src/vehicles/Heli.h
@@ -95,6 +95,3 @@ public:
static void ActivateHeli(bool activate);
};
-
-VALIDATE_SIZE(CHeli, 0x33C);
-
diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp
index 71189d84..8f32f12a 100644
--- a/src/vehicles/Plane.cpp
+++ b/src/vehicles/Plane.cpp
@@ -735,6 +735,7 @@ CPlane::InitPlanes(void)
TotalDurationOfFlightPath2 = TotalLengthOfFlightPath2/CRUISE_SPEED;
}
+/*
// Mission Cesna
if(pPath3Nodes == nil){
pPath3Nodes = LoadPath("data\\paths\\flight3.dat", NumPath3Nodes, TotalLengthOfFlightPath3, false);
@@ -746,6 +747,7 @@ CPlane::InitPlanes(void)
pPath4Nodes = LoadPath("data\\paths\\flight4.dat", NumPath4Nodes, TotalLengthOfFlightPath4, false);
TotalDurationOfFlightPath4 = TotalLengthOfFlightPath4/CRUISE_SPEED;
}
+*/
CStreaming::LoadAllRequestedModels(false);
CStreaming::RequestModel(MI_AIRTRAIN, 0);
@@ -806,7 +808,7 @@ CPlane::LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool
for(i = 0; i < numNodes; i++){
*gString = '\0';
- for(lp = 0; work_buff[bp] != '\n'; bp++, lp++)
+ for(lp = 0; work_buff[bp] != '\n' && work_buff[bp] != '\0'; bp++, lp++)
gString[lp] = work_buff[bp];
bp++;
// BUG: game doesn't terminate string
diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h
index a6f6e1d9..a9afa4bc 100644
--- a/src/vehicles/Plane.h
+++ b/src/vehicles/Plane.h
@@ -71,8 +71,6 @@ public:
static bool HasDropOffCesnaBeenShotDown(void);
};
-VALIDATE_SIZE(CPlane, 0x29C);
-
extern float LandingPoint;
extern float TakeOffPoint;
extern float PlanePathPosition[3];
diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp
index 1d47ca3a..5dab70c5 100644
--- a/src/vehicles/Train.cpp
+++ b/src/vehicles/Train.cpp
@@ -38,6 +38,7 @@ CVector CTrain::aStationCoors_S[4];
CTrain::CTrain(int32 id, uint8 CreatedBy)
: CVehicle(CreatedBy)
{
+#ifdef GTA_TRAIN
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
m_vehType = VEHICLE_TYPE_TRAIN;
pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
@@ -60,22 +61,28 @@ CTrain::CTrain(int32 id, uint8 CreatedBy)
bUsesCollision = true;
SetStatus(STATUS_TRAIN_MOVING);
+#else
+ assert(0 && "No trains in this game");
+#endif
}
void
CTrain::SetModelIndex(uint32 id)
{
+#ifdef GTA_TRAIN
int i;
CVehicle::SetModelIndex(id);
for(i = 0; i < NUM_TRAIN_NODES; i++)
m_aTrainNodes[i] = nil;
CClumpModelInfo::FillFrameArray(GetClump(), m_aTrainNodes);
+#endif
}
void
CTrain::ProcessControl(void)
{
+#ifdef GTA_TRAIN
if(gbModelViewer || m_isFarAway && (CTimer::GetFrameCounter() + m_nWagonId) & 0xF)
return;
@@ -278,11 +285,13 @@ CTrain::ProcessControl(void)
TrainHitStuff(s->m_lists[ENTITYLIST_PEDS_OVERLAP]);
}
}
+#endif GTA_TRAIN
}
void
CTrain::PreRender(void)
{
+#ifdef GTA_TRAIN
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
if(m_bIsFirstWagon){
@@ -342,17 +351,21 @@ CTrain::PreRender(void)
CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
}
+#endif
}
void
CTrain::Render(void)
{
+#ifdef GTA_TRAIN
CEntity::Render();
+#endif
}
void
CTrain::TrainHitStuff(CPtrList &list)
{
+#ifdef GTA_TRAIN
CPtrNode *node;
CPhysical *phys;
@@ -361,11 +374,13 @@ CTrain::TrainHitStuff(CPtrList &list)
if(phys != this && Abs(this->GetPosition().z - phys->GetPosition().z) < 1.5f)
phys->bHitByTrain = true;
}
+#endif
}
void
CTrain::AddPassenger(CPed *ped)
{
+#ifdef GTA_TRAIN
int i = ped->m_vehEnterType;
if((i == TRAIN_POS_LEFT_ENTRY || i == TRAIN_POS_MID_ENTRY || i == TRAIN_POS_RIGHT_ENTRY) && pPassengers[i] == nil){
pPassengers[i] = ped;
@@ -378,11 +393,13 @@ CTrain::AddPassenger(CPed *ped)
return;
}
}
+#endif
}
void
CTrain::OpenTrainDoor(float ratio)
{
+#ifdef GTA_TRAIN
if(m_rwObject == nil)
return;
@@ -407,6 +424,7 @@ CTrain::OpenTrainDoor(float ratio)
doorL.UpdateRW();
doorR.UpdateRW();
+#endif
}
@@ -414,6 +432,7 @@ CTrain::OpenTrainDoor(float ratio)
void
CTrain::InitTrains(void)
{
+#ifdef GTA_TRAIN
int i, j;
CTrain *train;
@@ -480,21 +499,25 @@ CTrain::InitTrains(void)
for(j = 0; pTrackNodes_S[j].t < StationDist_S[i]; j++);
aStationCoors_S[i] = pTrackNodes_S[j].p;
}
+#endif
}
void
CTrain::Shutdown(void)
{
+#ifdef GTA_TRAIN
delete[] pTrackNodes;
delete[] pTrackNodes_S;
pTrackNodes = nil;
pTrackNodes_S = nil;
+#endif
}
void
CTrain::ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int16 *numNodes, int32 numStations, float *stationDists,
float *totalLength, float *totalDuration, CTrainInterpolationLine *interpLines, bool rightRail)
{
+#ifdef GTA_TRAIN
bool readingFile = false;
int bp, lp;
int i, tmp;
@@ -616,6 +639,7 @@ CTrain::ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int1
// end
interpLines[j].time = *totalDuration;
+#endif
}
void
@@ -627,6 +651,7 @@ ProcessTrainAnnouncements(void)
void
CTrain::UpdateTrains(void)
{
+#ifdef GTA_TRAIN
int i, j;
uint32 time;
float t, deltaT;
@@ -690,4 +715,5 @@ CTrain::UpdateTrains(void)
// time offset for each train
time += 0x40000/4;
}
+#endif
}
diff --git a/src/vehicles/Train.h b/src/vehicles/Train.h
index c645ecaf..d8ee949d 100644
--- a/src/vehicles/Train.h
+++ b/src/vehicles/Train.h
@@ -91,5 +91,3 @@ public:
float *totalLength, float *totalDuration, CTrainInterpolationLine *interpLines, bool rightRail);
static void UpdateTrains(void);
};
-
-VALIDATE_SIZE(CTrain, 0x2E4);
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 0dd95faf..58c68a8d 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -18,6 +18,7 @@
#include "Radar.h"
#include "Fire.h"
#include "Darkel.h"
+#include "Streaming.h"
bool CVehicle::bWheelsOnlyCheat;
bool CVehicle::bAllDodosCheat;
@@ -28,6 +29,7 @@ bool CVehicle::bCheat5;
bool CVehicle::bAltDodoCheat;
#endif
bool CVehicle::m_bDisableMouseSteering = true;
+bool CVehicle::bDisableRemoteDetonation;
void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); }
void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); }
@@ -55,6 +57,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_fSteerRatio = 0.0f;
m_type = ENTITY_TYPE_VEHICLE;
VehicleCreatedBy = CreatedBy;
+ m_nRouteSeed = 0;
bIsLocked = false;
bIsLawEnforcer = false;
bIsAmbulanceOnDuty = false;
@@ -99,6 +102,11 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_bSirenOrAlarm = 0;
m_nCarHornTimer = 0;
m_nCarHornPattern = 0;
+ m_nCarHornDelay = 0;
+ bPartOfConvoy = false;
+ bIsDrowning = false;
+ bCreatedAsPoliceVehicle = false;
+ bParking = false;
m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED;
m_nLastWeaponDamage = -1;
@@ -118,6 +126,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
AutoPilot.m_bStayInCurrentLevel = false;
AutoPilot.m_bIgnorePathfinding = false;
+ AutoPilot.m_nSwitchDistance = 20;
}
CVehicle::~CVehicle()
@@ -383,7 +392,7 @@ CVehicle::FlyingControl(eFlightModel flightModel)
case FLIGHT_MODEL_HELI:
{
CVector vecMoveResistance;
- if (GetModelIndex() == MI_MIAMI_SPARROW)
+ if (GetModelIndex() == MI_SPARROW)
vecMoveResistance = vecHeliMoveRes;
else
vecMoveResistance = vecRCHeliMoveRes;
@@ -418,23 +427,22 @@ CVehicle::FlyingControl(eFlightModel flightModel)
}
else {
fPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;
- fRoll = CPad::GetPad(0)->GetLookLeft();
- if (CPad::GetPad(0)->GetLookRight())
- fRoll = -1.0f;
- fYaw = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
+ fYaw = CPad::GetPad(0)->GetLookRight();
+ if (CPad::GetPad(0)->GetLookLeft())
+ fYaw = -1.0f;
+ fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
}
if (CPad::GetPad(0)->GetHorn()) {
fYaw = 0.0f;
fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetUp()), -200.0f, 1.3f);
fRoll = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f);
}
- debug("fPitch: %f\n", fPitch);
ApplyTurnForce(fPitch * GetUp() * fPitchVar * m_fTurnMass * CTimer::GetTimeStep(), GetForward());
ApplyTurnForce(fRoll * GetUp() * fRollVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight());
ApplyTurnForce(fYaw * GetForward() * fYawVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight());
CVector vecResistance;
- if (GetModelIndex() == MI_MIAMI_SPARROW)
+ if (GetModelIndex() == MI_SPARROW)
vecResistance = vecHeliResistance;
else
vecResistance = vecRCHeliResistance;
@@ -605,11 +613,14 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage
break;
case WEAPONTYPE_COLT45:
case WEAPONTYPE_UZI:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
case WEAPONTYPE_SHOTGUN:
case WEAPONTYPE_AK47:
case WEAPONTYPE_M16:
case WEAPONTYPE_SNIPERRIFLE:
- case WEAPONTYPE_TOTAL_INVENTORY_WEAPONS:
+ case WEAPONTYPE_HELICANNON:
case WEAPONTYPE_UZI_DRIVEBY:
if (bBulletProof)
return;
@@ -706,45 +717,7 @@ void
CVehicle::DoFixedMachineGuns(void)
{
if(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){
- if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 150){
- CVector source, target;
- float dx, dy, len;
-
- dx = GetForward().x;
- dy = GetForward().y;
- len = Sqrt(SQR(dx) + SQR(dy));
- if(len < 0.1f) len = 0.1f;
- dx /= len;
- dy /= len;
-
- m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
-
- source = GetMatrix() * CVector(2.0f, 2.5f, 1.0f);
- target = source + CVector(dx, dy, 0.0f)*60.0f;
- target += CVector(
- ((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
- ((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
- ((CGeneral::GetRandomNumber()&0xFF)-128) * 0.02f);
- CWeapon::DoTankDoomAiming(this, pDriver, &source, &target);
- FireOneInstantHitRound(&source, &target, 15);
-
- source = GetMatrix() * CVector(-2.0f, 2.5f, 1.0f);
- target = source + CVector(dx, dy, 0.0f)*60.0f;
- target += CVector(
- ((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
- ((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
- ((CGeneral::GetRandomNumber()&0xFF)-128) * 0.02f);
- CWeapon::DoTankDoomAiming(this, pDriver, &source, &target);
- FireOneInstantHitRound(&source, &target, 15);
-
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
-
- m_nAmmoInClip--;
- if(m_nAmmoInClip == 0){
- m_nAmmoInClip = 20;
- m_nGunFiringTime = CTimer::GetTimeInMilliseconds() + 1400;
- }
- }
+ FireFixedMachineGuns();
}else{
if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400)
m_nAmmoInClip = 20;
@@ -752,6 +725,50 @@ CVehicle::DoFixedMachineGuns(void)
}
void
+CVehicle::FireFixedMachineGuns(void)
+{
+ if (CTimer::GetTimeInMilliseconds() <= m_nGunFiringTime + 150)
+ return;
+ CVector source, target;
+ float dx, dy, len;
+
+ dx = GetForward().x;
+ dy = GetForward().y;
+ len = Sqrt(SQR(dx) + SQR(dy));
+ if (len < 0.1f) len = 0.1f;
+ dx /= len;
+ dy /= len;
+
+ m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
+
+ source = GetMatrix() * CVector(2.0f, 2.5f, 1.0f);
+ target = source + CVector(dx, dy, 0.0f) * 60.0f;
+ target += CVector(
+ ((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,
+ ((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,
+ ((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.02f);
+ CWeapon::DoTankDoomAiming(this, pDriver, &source, &target);
+ FireOneInstantHitRound(&source, &target, 15);
+
+ source = GetMatrix() * CVector(-2.0f, 2.5f, 1.0f);
+ target = source + CVector(dx, dy, 0.0f) * 60.0f;
+ target += CVector(
+ ((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,
+ ((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,
+ ((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.02f);
+ CWeapon::DoTankDoomAiming(this, pDriver, &source, &target);
+ FireOneInstantHitRound(&source, &target, 15);
+
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
+
+ m_nAmmoInClip--;
+ if (m_nAmmoInClip == 0) {
+ m_nAmmoInClip = 20;
+ m_nGunFiringTime = CTimer::GetTimeInMilliseconds() + 1400;
+ }
+}
+
+void
CVehicle::ExtinguishCarFire(void)
{
m_fHealth = Max(m_fHealth, 300.0f);
@@ -886,24 +903,7 @@ CVehicle::IsVehicleNormal(void)
{
if (!pDriver || m_nNumPassengers != 0 || GetStatus() == STATUS_WRECKED)
return false;
- switch (GetModelIndex()){
- case MI_FIRETRUCK:
- case MI_AMBULAN:
- case MI_TAXI:
- case MI_POLICE:
- case MI_ENFORCER:
- case MI_BUS:
- case MI_RHINO:
- case MI_BARRACKS:
- case MI_DODO:
- case MI_COACH:
- case MI_CABBIE:
- case MI_RCBANDIT:
- case MI_BORGNINE:
- return false;
- default:
- return true;
- }
+ return GetModelInfo()->m_vehicleClass != -1;
}
bool
@@ -1060,7 +1060,7 @@ CVehicle::SetUpDriver(void)
if(VehicleCreatedBy != RANDOM_VEHICLE)
return nil;
- pDriver = CPopulation::AddPedInCar(this);
+ pDriver = CPopulation::AddPedInCar(this, true);
pDriver->m_pMyVehicle = this;
pDriver->m_pMyVehicle->RegisterReference((CEntity**)&pDriver->m_pMyVehicle);
pDriver->bInVehicle = true;
@@ -1076,7 +1076,7 @@ CVehicle::SetupPassenger(int n)
if(pPassengers[n])
return pPassengers[n];
- pPassengers[n] = CPopulation::AddPedInCar(this);
+ pPassengers[n] = CPopulation::AddPedInCar(this, false);
pPassengers[n]->m_pMyVehicle = this;
pPassengers[n]->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle);
pPassengers[n]->bInVehicle = true;
@@ -1095,14 +1095,15 @@ CVehicle::SetDriver(CPed *driver)
if(bFreebies && driver == FindPlayerPed()){
if(GetModelIndex() == MI_AMBULAN)
- FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f);
+ FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth);
else if(GetModelIndex() == MI_TAXI)
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
- else if(GetModelIndex() == MI_POLICE)
+ else if (GetModelIndex() == MI_POLICE) {
+ CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE);
driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5);
- else if(GetModelIndex() == MI_ENFORCER)
- driver->m_fArmour = Max(driver->m_fArmour, 100.0f);
- else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE)
+ } else if (GetModelIndex() == MI_ENFORCER)
+ driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour);
+ else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA) // TODO(MIAMI): check zebra
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
bFreebies = false;
}
@@ -1360,3 +1361,36 @@ CVehicle::Load(uint8*& buf)
SkipSaveBuf(buf, 99);
}
#endif
+
+eVehicleAppearance
+//--MIAMI: TODO, implement VC version, appearance != type
+// This would work for cars, boats and bikes but not for planes and helis
+CVehicle::GetVehicleAppearance(void)
+{
+ if (IsCar())
+ return VEHICLE_APPEARANCE_CAR;
+ if (IsBoat())
+ return VEHICLE_APPEARANCE_BOAT;
+ if (IsBike())
+ return VEHICLE_APPEARANCE_BIKE;
+ if (IsPlane())
+ return VEHICLE_APPEARANCE_PLANE;
+ if (IsHeli())
+ return VEHICLE_APPEARANCE_HELI;
+ return VEHICLE_APPEARANCE_NONE;
+}
+
+bool
+IsVehiclePointerValid(CVehicle* pVehicle)
+{
+ if (!pVehicle)
+ return false;
+ int index = CPools::GetVehiclePool()->GetJustIndex(pVehicle);
+#ifdef FIX_BUGS
+ if (index < 0 || index >= NUMVEHICLES)
+#else
+ if (index < 0 || index > NUMVEHICLES)
+#endif
+ return false;
+ return pVehicle->m_vehType == VEHICLE_TYPE_PLANE || pVehicle->m_entryInfoList.first;
+}
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index f7205c7d..0b7d3cba 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -5,6 +5,7 @@
#include "ModelIndices.h"
#include "AnimManager.h"
#include "Weapon.h"
+#include "HandlingMgr.h"
class CPed;
class CFire;
@@ -109,6 +110,16 @@ enum eFlightModel
FLIGHT_MODEL_SEAPLANE
};
+enum eVehicleAppearance
+{
+ VEHICLE_APPEARANCE_NONE,
+ VEHICLE_APPEARANCE_CAR,
+ VEHICLE_APPEARANCE_BIKE,
+ VEHICLE_APPEARANCE_HELI,
+ VEHICLE_APPEARANCE_BOAT,
+ VEHICLE_APPEARANCE_PLANE,
+};
+
// Or Weapon.h?
void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage);
@@ -122,7 +133,7 @@ public:
uint8 m_currentColour2;
uint8 m_aExtras[2];
int16 m_nAlarmState;
- int16 m_nMissionValue;
+ int16 m_nRouteSeed;
CPed *pDriver;
CPed *pPassengers[8];
uint8 m_nNumPassengers;
@@ -171,6 +182,18 @@ public:
uint8 bVehicleColProcessed : 1;// Has ProcessEntityCollision been processed for this car?
uint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command
uint8 bHasAlreadyBeenRecorded : 1; // Used for replays
+ uint8 bPartOfConvoy : 1;
+ //uint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really
+ //uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear
+
+ uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water)
+ //uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible
+ uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc)
+ //uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed
+ uint8 bParking : 1;
+ //uint8 bCanPark : 1;
+
+ uint8 m_bombType : 3;
int8 m_numPedsUseItAsCover;
uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default)
@@ -180,6 +203,7 @@ public:
float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode
uint8 m_nCurrentGear;
float m_fChangeGearTime;
+ CEntity* m_pBombRigger;
uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats)
uint32 m_nTimeOfDeath;
uint16 m_nTimeBlocked;
@@ -189,12 +213,14 @@ public:
float m_fMapObjectHeightBehind; // rear Z?
eCarLock m_nDoorLock;
int8 m_nLastWeaponDamage; // see eWeaponType, -1 if no damage
+ CEntity *m_pLastDamageEntity;
int8 m_nRadioStation;
uint8 m_bRainAudioCounter;
uint8 m_bRainSamplesCounter;
uint8 m_nCarHornTimer;
- uint8 m_nCarHornPattern; // last horn?
+ uint8 m_nCarHornPattern;
bool m_bSirenOrAlarm;
+ uint8 m_nCarHornDelay;
int8 m_comedyControlState;
CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car
float m_fSteerRatio;
@@ -236,6 +262,7 @@ public:
virtual void Load(uint8*& buf);
#endif
+ eVehicleAppearance GetVehicleAppearance(void);
bool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; }
bool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; }
bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }
@@ -273,12 +300,13 @@ public:
bool ShufflePassengersToMakeSpace(void);
void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage);
void DoFixedMachineGuns(void);
+ void FireFixedMachineGuns(void);
bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }
- bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; }
- AnimationId GetDriverAnim(void) { return IsCar() && bLowVehicle ? ANIM_CAR_LSIT : (IsBoat() && GetModelIndex() != MI_SPEEDER ? ANIM_DRIVE_BOAT : ANIM_CAR_SIT); }
+ bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA || GetModelIndex() == MI_KAUFMAN; }
+ bool IsRealHeli(void) { return !!(pHandling->Flags & HANDLING_IS_HELI); }
static bool bWheelsOnlyCheat;
static bool bAllDodosCheat;
@@ -289,8 +317,8 @@ public:
static bool bAltDodoCheat;
#endif
static bool m_bDisableMouseSteering;
+ static bool bDisableRemoteDetonation;
};
-VALIDATE_SIZE(CVehicle, 0x288);
-
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);
+bool IsVehiclePointerValid(CVehicle* pVehicle);
diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp
index 47bc65ac..35e55b36 100644
--- a/src/weapons/ProjectileInfo.cpp
+++ b/src/weapons/ProjectileInfo.cpp
@@ -45,6 +45,7 @@ CProjectileInfo::GetProjectileInfo(int32 id)
return &gaProjectileInfo[id];
}
+// --MIAMI: Mostly done
bool
CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos, float speed)
{
@@ -58,32 +59,36 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
switch (weapon)
{
- case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_ROCKET:
{
- float vy = 1.25f;
- time = CTimer::GetTimeInMilliseconds() + 1400;
- if (ped->IsPlayer()) {
- matrix.GetForward() = TheCamera.Cams[TheCamera.ActiveCam].Front;
- matrix.GetUp() = TheCamera.Cams[TheCamera.ActiveCam].Up;
- matrix.GetRight() = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Up, TheCamera.Cams[TheCamera.ActiveCam].Front);
+ float vy = 0.35f;
+ time = CTimer::GetTimeInMilliseconds() + 2000;
+ if (entity->GetModelIndex() == MI_SPARROW || entity->GetModelIndex() == MI_HUNTER || entity->GetModelIndex() == MI_SENTINEL) {
+ matrix = ped->GetMatrix();
matrix.GetPosition() = pos;
- } else if (ped->m_pSeekTarget != nil) {
+ CVector vecSpeed = ((CPhysical*)entity)->m_vecMoveSpeed;
+ vy += Max(0.0f, DotProduct(vecSpeed, entity->GetForward())) + Max(0.0f, DotProduct(vecSpeed, entity->GetUp()));
+ } else {
+ if (ped->IsPlayer()) {
+ matrix.GetForward() = TheCamera.Cams[TheCamera.ActiveCam].Front;
+ matrix.GetUp() = TheCamera.Cams[TheCamera.ActiveCam].Up;
+ matrix.GetRight() = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Up, TheCamera.Cams[TheCamera.ActiveCam].Front);
+ matrix.GetPosition() = pos;
+ } else if (ped->m_pSeekTarget != nil) {
float ry = CGeneral::GetRadianAngleBetweenPoints(1.0f, ped->m_pSeekTarget->GetPosition().z, 1.0f, pos.z);
float rz = Atan2(-ped->GetForward().x, ped->GetForward().y);
vy = 0.35f * speed + 0.15f;
matrix.SetTranslate(0.0f, 1.0f, 1.0f);
matrix.Rotate(0.0f, ry, rz);
matrix.GetPosition() += pos;
- } else {
- matrix = ped->GetMatrix();
+ } else {
+ matrix = ped->GetMatrix();
+ }
}
velocity = Multiply3x3(matrix, CVector(0.0f, vy, 0.0f));
gravity = false;
break;
}
- case WEAPONTYPE_FLAMETHROWER:
- Error("Undefined projectile type, AddProjectile, ProjectileInfo.cpp");
- break;
case WEAPONTYPE_MOLOTOV:
{
time = CTimer::GetTimeInMilliseconds() + 2000;
@@ -100,6 +105,7 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
break;
}
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
{
time = CTimer::GetTimeInMilliseconds() + 2000;
float scale = 0.0f;
@@ -116,7 +122,9 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
elasticity = 0.5f;
break;
}
- default: break;
+ default:
+ Error("Undefined projectile type, AddProjectile, ProjectileInfo.cpp");
+ break;
}
int i = 0;
@@ -127,7 +135,7 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
switch (weapon)
{
- case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_ROCKET:
ms_apProjectile[i] = new CProjectile(MI_MISSILE);
break;
case WEAPONTYPE_FLAMETHROWER:
@@ -136,6 +144,7 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
ms_apProjectile[i] = new CProjectile(MI_MOLOTOV);
break;
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
ms_apProjectile[i] = new CProjectile(MI_GRENADE);
break;
default: break;
@@ -158,6 +167,10 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
CWorld::Add(ms_apProjectile[i]);
gaProjectileInfo[i].m_vecPos = ms_apProjectile[i]->GetPosition();
+
+ if (entity && entity->IsPed() && !ped->m_pCollidingEntity) {
+ ped->m_pCollidingEntity = ms_apProjectile[i];
+ }
return true;
}
@@ -182,7 +195,7 @@ CProjectileInfo::RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector p
case WEAPONTYPE_MOLOTOV:
CExplosion::AddExplosion(nil, entity, EXPLOSION_MOLOTOV, pos, 0);
break;
- case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_ROCKET:
CExplosion::AddExplosion(nil, entity, EXPLOSION_ROCKET, pos, 0);
break;
default: break;
@@ -204,17 +217,17 @@ CProjectileInfo::Update()
continue;
}
- if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET) {
CParticle::AddParticle(PARTICLE_SMOKE, ms_apProjectile[i]->GetPosition(), CVector(0.0f, 0.0f, 0.0f));
}
if (CTimer::GetTimeInMilliseconds() <= gaProjectileInfo[i].m_nExplosionTime) {
- if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET) {
CVector pos = ms_apProjectile[i]->GetPosition();
CWorld::pIgnoreEntity = ms_apProjectile[i];
if (ms_apProjectile[i]->bHasCollided
|| !CWorld::GetIsLineOfSightClear(gaProjectileInfo[i].m_vecPos, pos, true, true, true, true, false, false)
- || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
+ || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
}
CWorld::pIgnoreEntity = nil;
@@ -227,14 +240,25 @@ CProjectileInfo::Update()
{
if (ms_apProjectile[i]->bHasCollided
|| !CWorld::GetIsLineOfSightClear(gaProjectileInfo[i].m_vecPos, pos, true, true, true, true, false, false)
- || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
+ || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
}
}
CWorld::pIgnoreEntity = nil;
}
} else {
- RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {
+ CEntity *ent = gaProjectileInfo[i].m_pSource;
+ if (ent->IsPed() && ((CPed*)ped)->IsPlayer()) {
+ CPed *ped = (CPed*)ent;
+ if (ped->GetWeapon(ped->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponType != WEAPONTYPE_DETONATOR
+ || ped->GetWeapon(ped->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_nAmmoTotal == 0) {
+ gaProjectileInfo[i].m_nExplosionTime = 0;
+ }
+ }
+ } else {
+ RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
+ }
}
gaProjectileInfo[i].m_vecPos = ms_apProjectile[i]->GetPosition();
@@ -247,7 +271,7 @@ CProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, flo
bool result = false;
for (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {
if (gaProjectileInfo[i].m_bInUse) {
- if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_MOLOTOV || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_GRENADE) {
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_MOLOTOV || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_GRENADE) {
const CVector &pos = ms_apProjectile[i]->GetPosition();
if (pos.x >= x1 && pos.x <= x2 && pos.y >= y1 && pos.y <= y2 && pos.z >= z1 && pos.z <= z2) {
result = true;
@@ -263,6 +287,20 @@ CProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, flo
return result;
}
+// --MIAMI: Done
+void
+CProjectileInfo::RemoveDetonatorProjectiles()
+{
+ for (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {
+ if (gaProjectileInfo[i].m_bInUse && gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {
+ CExplosion::AddExplosion(nil, gaProjectileInfo[i].m_pSource, EXPLOSION_GRENADE, gaProjectileInfo[i].m_vecPos, 0); // TODO(Miami): New parameter (1)
+ gaProjectileInfo[i].m_bInUse = false;
+ CWorld::Remove(ms_apProjectile[i]);
+ delete ms_apProjectile[i];
+ }
+ }
+}
+
void
CProjectileInfo::RemoveAllProjectiles()
{
diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h
index 3d8074c9..d1688948 100644
--- a/src/weapons/ProjectileInfo.h
+++ b/src/weapons/ProjectileInfo.h
@@ -26,6 +26,7 @@ public:
static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
static bool RemoveIfThisIsAProjectile(CObject *pObject);
static void RemoveAllProjectiles();
+ static void RemoveDetonatorProjectiles();
static void Update();
static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
};
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index 88c4788c..4c1f1c52 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -30,20 +30,38 @@
#include "WeaponInfo.h"
#include "World.h"
+// TODO(Miami)
+#define AUDIO_NOT_READY
+
uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] =
{
0, // UNARMED
- 0, // BASEBALLBAT
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, // GRENADE
+ 0, // DETONATEGRENADE
+ 0, // MOLOTOV
+ 0, // ROCKET
250, // COLT45
- 400, // UZI
650, // SHOTGUN
- 300, // AK47
+ 400, // TEC9
+ 400, // UZIhec
+ 400, // SILENCED_INGRAM
+ 400, // MP5
300, // M16
+ 300, // AK47
423, // SNIPERRIFLE
400, // ROCKETLAUNCHER
0, // FLAMETHROWER
- 0, // MOLOTOV
- 0, // GRENADE
0, // DETONATOR
0 // HELICANNON
};
@@ -85,18 +103,42 @@ CWeapon::UpdateWeapons(void)
CBulletInfo::Update();
}
+// --MIAMI: Done
void
CWeapon::Initialise(eWeaponType type, int32 ammo)
{
m_eWeaponType = type;
m_eWeaponState = WEAPONSTATE_READY;
- if (ammo > 99999)
- m_nAmmoTotal = 99999;
- else
- m_nAmmoTotal = ammo;
+ m_nAmmoTotal = Min(ammo, 99999);
m_nAmmoInClip = 0;
Reload();
m_nTimer = 0;
+ int modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId;
+ if (modelId != -1)
+ CModelInfo::GetModelInfo(modelId)->AddRef();
+
+ int model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id;
+ if (model2Id != -1)
+ CModelInfo::GetModelInfo(model2Id)->AddRef();
+}
+
+// --MIAMI: Done
+void
+CWeapon::Shutdown()
+{
+ int modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId;
+ if (modelId != -1)
+ CModelInfo::GetModelInfo(modelId)->RemoveRef();
+
+ int model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id;
+ if (model2Id != -1)
+ CModelInfo::GetModelInfo(model2Id)->RemoveRef();
+
+ m_eWeaponType = WEAPONTYPE_UNARMED;
+ m_eWeaponState = WEAPONSTATE_READY;
+ m_nAmmoInClip = 0;
+ m_nAmmoTotal = 0;
+ m_nTimer = 0;
}
bool
@@ -124,6 +166,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
return false;
bool fired;
+ bool addFireRateAsDelay = true;
if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE )
{
@@ -134,6 +177,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
{
case WEAPONTYPE_SHOTGUN:
{
+ addFireRateAsDelay = true;
fired = FireShotgun(shooter, source);
break;
@@ -141,10 +185,21 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
case WEAPONTYPE_COLT45:
case WEAPONTYPE_UZI:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
case WEAPONTYPE_AK47:
+ case WEAPONTYPE_M16:
+ case WEAPONTYPE_HELICANNON:
{
- fired = FireInstantHit(shooter, source);
-
+ if ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON)
+ && shooter == FindPlayerPed()) {
+ addFireRateAsDelay = false;
+ fired = FireM16_1stPerson(shooter);
+ } else {
+ addFireRateAsDelay = true;
+ fired = FireInstantHit(shooter, source);
+ }
break;
}
@@ -155,16 +210,6 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
break;
}
- case WEAPONTYPE_M16:
- {
- if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() )
- fired = FireM16_1stPerson(shooter);
- else
- fired = FireInstantHit(shooter, source);
-
- break;
- }
-
case WEAPONTYPE_ROCKETLAUNCHER:
{
if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil )
@@ -184,6 +229,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
case WEAPONTYPE_MOLOTOV:
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
{
if ( shooter == FindPlayerPed() )
{
@@ -201,6 +247,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
else
fired = FireProjectile(shooter, source, 0.3f);
+ if (m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {
+ ((CPed*)shooter)->GiveWeapon(WEAPONTYPE_DETONATOR, 1, true);
+ ((CPed*)shooter)->GetWeapon(((CPed*)shooter)->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponState = WEAPONSTATE_READY;
+ ((CPed*)shooter)->SetCurrentWeapon(WEAPONTYPE_DETONATOR);
+ }
break;
}
@@ -221,19 +272,6 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
break;
}
- case WEAPONTYPE_HELICANNON:
- {
- if ( (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON )
- && shooter == FindPlayerPed() )
- {
- fired = FireM16_1stPerson(shooter);
- }
- else
- fired = FireInstantHit(shooter, source);
-
- break;
- }
-
default:
{
debug("Unknown weapon type, Weapon.cpp");
@@ -241,51 +279,58 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
}
}
- if ( fired )
+ if (fired)
{
bool isPlayer = false;
- if ( shooter->IsPed() )
+ if (shooter->IsPed())
{
- CPed *shooterPed = (CPed*)shooter;
+ CPed* shooterPed = (CPed*)shooter;
shooterPed->bIsShooting = true;
- if ( shooterPed->IsPlayer() )
+ if (shooterPed->IsPlayer())
isPlayer = true;
DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
}
- if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--;
- if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--;
+ if (m_nAmmoInClip > 0)
+ m_nAmmoInClip--;
- if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER )
+ if (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) && (!isPlayer || CStats::GetPercentageProgress() < 100.0f || m_eWeaponType == WEAPONTYPE_DETONATOR))
+ m_nAmmoTotal--;
+
+ if (m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER)
DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f);
m_eWeaponState = WEAPONSTATE_FIRING;
- }
- if ( m_nAmmoInClip == 0 )
- {
- if ( m_nAmmoTotal == 0 )
- return true;
+ if (m_nAmmoInClip == 0)
+ {
+ if (m_nAmmoTotal == 0)
+ return true;
- m_eWeaponState = WEAPONSTATE_RELOADING;
- m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;
+ m_eWeaponState = WEAPONSTATE_RELOADING;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;
- if ( shooter == FindPlayerPed() )
- {
- if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload )
- m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4;
+ if (shooter == FindPlayerPed())
+ {
+ if (CWorld::Players[CWorld::PlayerInFocus].m_bFastReload)
+ m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4;
+ }
+
+ return true;
}
- return true;
- }
+ if (addFireRateAsDelay)
+ m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nFiringRate;
+ else
+ m_nTimer = CTimer::GetTimeInMilliseconds();
- m_nTimer = CTimer::GetTimeInMilliseconds() + 1000;
- if ( shooter == FindPlayerPed() )
- CStats::RoundsFiredByPlayer++;
+ if (shooter == FindPlayerPed())
+ CStats::RoundsFiredByPlayer++;
+ }
}
else
{
@@ -293,9 +338,15 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
{
m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;
m_eWeaponState = WEAPONSTATE_FIRING;
+#ifndef AUDIO_NOT_READY
+ if (shooter->IsPed() && m_eWeaponType != WEAPONTYPE_CHAINSAW)
+ {
+ DMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, 188, m_eWeaponType << 8);
+ }
+#endif
}
- FireMelee(shooter, *source);
+ fired = FireMelee(shooter, *source);
}
if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT )
@@ -305,7 +356,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
}
bool
-CWeapon::FireFromCar(CAutomobile *shooter, bool left)
+CWeapon::FireFromCar(CVehicle *shooter, bool left)
{
ASSERT(shooter!=nil);
@@ -343,6 +394,7 @@ CWeapon::FireFromCar(CAutomobile *shooter, bool left)
return true;
}
+// --MIAMI: Done, except commented things
bool
CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
{
@@ -350,28 +402,39 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
CWeaponInfo *info = GetInfo();
- bool anim2Playing = false;
- if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) )
- anim2Playing = true;
+ bool anim2Playing = RpAnimBlendClumpGetAssociation(shooter->GetClump(), CPed::GetFireAnimGround(info, false));
ASSERT(shooter->IsPed());
CPed *shooterPed = (CPed*)shooter;
+ if (shooterPed == FindPlayerPed()) {
+ if (m_eWeaponType == WEAPONTYPE_GOLFCLUB || m_eWeaponType == WEAPONTYPE_NIGHTSTICK ||
+ (m_eWeaponType >= WEAPONTYPE_BASEBALLBAT && m_eWeaponType <= WEAPONTYPE_CHAINSAW)) {
+
+ // TODO(Miami): BreakGlassPhysically
+ if (m_eWeaponType == WEAPONTYPE_CHAINSAW) {
+ CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000);
+ }
+ }
+ }
+
+ int damageEntityRegistered = 0;
+
for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ )
{
CPed *victimPed = shooterPed->m_nearPeds[i];
ASSERT(victimPed!=nil);
if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget)
- && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) )
+ && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31)
+ && (!shooterPed->IsGangMember() || victimPed->CanBeDamagedByThisGangMember(shooterPed)) )
{
bool collided = false;
- CColModel *victimPedCol = &CTempColModels::ms_colModelPed1;
- if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) )
- victimPedCol = &CTempColModels::ms_colModelPedGroundHit;
-
+ if (victimPed->m_nPedState == PED_DRIVING && (m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE
+ || info->m_bFightMode))
+ continue;
float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius;
if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() )
@@ -380,12 +443,29 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() )
{
CVector collisionDist;
+ CColModel* victimPedCol = &CTempColModels::ms_colModelPed1;
+ bool useLocalPos = false;
+ if (victimPed->m_nPedState == PED_FALL
+ || victimPed->m_nPedState == PED_DIE && victimPed->bIsPedDieAnimPlaying
+ || victimPed->m_nWaitState == WAITSTATE_SIT_IDLE
+ || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE)
+ {
+ useLocalPos = true;
+ victimPedCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(victimPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(victimPed->GetClump());
+ } else if (victimPed->DyingOrDead()) {
+ victimPedCol = &CTempColModels::ms_colModelPedGroundHit;
+ }
int32 s = 0;
while ( s < victimPedCol->numSpheres )
{
CColSphere *sphere = &victimPedCol->spheres[s];
- collisionDist = victimPedPos+sphere->center-(*fireSource);
+
+ if (useLocalPos) {
+ collisionDist = sphere->center - (*fireSource);
+ } else {
+ collisionDist = victimPedPos + sphere->center - (*fireSource);
+ }
if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() )
{
@@ -406,65 +486,115 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
int32 localDir = victimPed->GetLocalDirection(posOffset);
- bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT;
+ bool isHeavy = m_eWeaponType >= WEAPONTYPE_GOLFCLUB && m_eWeaponType <= WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_HAMMER;
+
+ if (shooterPed->m_fDamageImpulse == 0.0f) {
+ shooterPed->m_pDamageEntity = victimPed;
+ victimPed->RegisterReference(&shooterPed->m_pDamageEntity);
+ }
+
+ damageEntityRegistered = 3;
+ // TODO(Miami): Bike
if ( !victimPed->DyingOrDead() )
victimPed->ReactToAttack(shooterPed);
uint8 hitLevel = HITLEVEL_HIGH;
- if ( isBat && victimPed->OnGround() )
+ if ( isHeavy && (victimPed->OnGround() || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE))
hitLevel = HITLEVEL_GROUND;
victimPed->StartFightDefend(localDir, hitLevel, 10);
if ( !victimPed->DyingOrDead() )
{
- if ( shooterPed->IsPlayer() && isBat && anim2Playing )
+ if ( shooterPed->IsPlayer() && isHeavy && anim2Playing )
victimPed->InflictDamage(shooterPed, m_eWeaponType, 100.0f, PEDPIECE_TORSO, localDir);
else if ( shooterPed->IsPlayer() && ((CPlayerPed*)shooterPed)->m_bAdrenalineActive )
victimPed->InflictDamage(shooterPed, m_eWeaponType, 3.5f*info->m_nDamage, PEDPIECE_TORSO, localDir);
else
{
- if ( victimPed->IsPlayer() && isBat ) // wtf, it's not fair
+ if ( victimPed->IsPlayer() && isHeavy ) // wtf, it's not fair
victimPed->InflictDamage(shooterPed, m_eWeaponType, 2.0f*info->m_nDamage, PEDPIECE_TORSO, localDir);
else
victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir);
}
}
- if ( CGame::nastyGame )
+ if ( CGame::nastyGame && victimPed->GetIsOnScreen() )
{
- if ( victimPed->GetIsOnScreen() )
- {
- CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr());
+ CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr());
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
+
+ if ( isHeavy )
+ {
+ dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
+ dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
+
+ dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
+ dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
+ }
- if ( isBat )
+ if (m_eWeaponType == WEAPONTYPE_CHAINSAW)
+ {
+ if (victimPed->m_nPedState != PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 1)
+ || victimPed->m_nPedState == PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 3))
{
- dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
- dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
-
- dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
- dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);
+ CParticle::AddParticle(PARTICLE_TEST, bloodPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f);
}
+ CVector newDir(dir);
+ newDir.z += 0.2f;
+ CParticle::AddParticle(PARTICLE_BLOOD_SMALL, bloodPos, newDir);
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir);
+ newDir.z = dir.z + 0.1f;
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir);
+ newDir.x = 0.0f;
+ newDir.y = 0.0f;
+ newDir.z = 0.01f;
+ CParticle::AddParticle(PARTICLE_DEBRIS2, bloodPos, newDir);
+
+ // TODO(Miami): New particle
+ /*
+ v116.z = 0.0;
+ v116.x = CGeneral::GetRandomNumberInRange(-0.15f, 0.15f);
+ v116.y = CGeneral::GetRandomNumberInRange(0.1f, 0.35f);
+ v115.x = CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_X(50.0f), SCREEN_STRETCH_FROM_RIGHT(50.0f));
+ v115.z = 1.0;
+ v115.y = CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_Y(50.0f), SCREEN_STRETCH_FROM_BOTTOM(50.0f));
+ CParticle::AddParticle(41, v115, v116, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.15f),
+ CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 0);
+
+ */
+ }
+ if (info->m_AnimToPlay == ASSOCGRP_KNIFE)
+ {
+ dir.x += 0.1f * shooterPed->GetUp().x + 0.05f * shooterPed->GetRight().x;
+ dir.y += 0.1f * shooterPed->GetUp().y + 0.05f * shooterPed->GetRight().y;
+ dir.z += 0.1f * shooterPed->GetUp().z + 0.05f * shooterPed->GetRight().z;
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir);
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir);
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir);
}
}
if ( !victimPed->OnGround() )
{
if ( victimPed->m_fHealth > 0.0f
- && (victimPed->m_fHealth < 20.0f && victimPedHealth > 20.0f || isBat && !victimPed->IsPlayer()) )
+ && (victimPed->m_fHealth < 30.0f && victimPedHealth > 20.0f ||
+ (isHeavy || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) && !victimPed->IsPlayer()) )
{
posOffset.Normalise();
victimPed->bIsStanding = false;
- victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f);
+ if(m_eWeaponType == WEAPONTYPE_CHAINSAW)
+ victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 2.0f);
+ else
+ victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f);
- if ( isBat && victimPed->IsPlayer() )
+ if ( isHeavy && victimPed->IsPlayer() )
victimPed->SetFall(3000, AnimationId(ANIM_KO_SKID_FRONT + localDir), false);
else
victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false);
@@ -477,21 +607,152 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
{
posOffset.Normalise();
victimPed->bIsStanding = false;
- victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f);
+ if(m_eWeaponType == WEAPONTYPE_CHAINSAW)
+ victimPed->ApplyMoveForce(posOffset.x*-1.0f, posOffset.y*-1.0f, 1.0f);
+ else
+ victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f);
}
m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT;
- if ( victimPed->m_nPedType == PEDTYPE_COP )
- CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);
- else
- CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);
+ if (m_eWeaponType != WEAPONTYPE_KNIFE && m_eWeaponType != WEAPONTYPE_MACHETE
+ && m_eWeaponType != WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_CHAINSAW) {
+
+ if (victimPed->m_nPedType == PEDTYPE_COP)
+ CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);
+ else
+ CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);
+ } else {
+ if (victimPed->m_nPedType == PEDTYPE_COP)
+ CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);
+ else
+ CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);
+ }
}
}
}
}
}
}
+ CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, false, true, false, false, false, false);
+ if (nearVeh && nearVeh->IsCar())
+ {
+ CAutomobile *nearCar = (CAutomobile*)nearVeh;
+ m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT;
+ if (shooterPed == FindPlayerPed())
+ {
+ if (nearCar->IsLawEnforcementVehicle())
+ {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_VEHICLE, nearCar, shooterPed, 2000);
+ }
+ float oldHealth = nearCar->m_fHealth;
+ if (m_eWeaponType == WEAPONTYPE_CHAINSAW)
+ {
+ for(int i=0; i<4; i++) {
+ CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f));
+ CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, gaTempSphereColPoints[0].normal * 0.1f);
+ }
+ }
+ if (m_eWeaponType == WEAPONTYPE_CHAINSAW)
+ {
+ nearCar->VehicleDamage(info->m_nDamage * (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB);
+
+ // TODO(Miami): Particle not in III
+ // CParticle::AddParticle(81, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0);
+ }
+ else
+ {
+ nearCar->VehicleDamage(info->m_nDamage* (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB);
+ }
+ if (nearCar->m_fHealth < oldHealth)
+ {
+ nearCar->m_nLastWeaponDamage = m_eWeaponType;
+ nearCar->m_pLastDamageEntity = shooterPed;
+ }
+ if (shooterPed->m_fDamageImpulse == 0.0f)
+ {
+ shooterPed->m_pDamageEntity = nearCar;
+ nearCar->RegisterReference(&shooterPed->m_pDamageEntity);
+ }
+ damageEntityRegistered = 2;
+ if (FindPlayerPed()->GetWeapon() == this && nearCar->VehicleCreatedBy != MISSION_VEHICLE)
+ {
+ if (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH
+ && (CGeneral::GetRandomTrueFalse() || nearCar->AutoPilot.m_nCarMission != MISSION_CRUISE))
+ {
+ int leaveCarDelay = 200;
+ CPed *driver = nearCar->pDriver;
+ if (driver && driver->CharCreatedBy != MISSION_CHAR)
+ {
+ if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear)
+ {
+ driver->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ }
+ else
+ {
+ driver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, FindPlayerPed());
+ driver->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ driver->m_prevObjective = OBJECTIVE_KILL_CHAR_ON_FOOT;
+ }
+ driver->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 200;
+ leaveCarDelay = 400;
+ }
+ for (int j = 0; j < nearCar->m_nNumPassengers; ++j)
+ {
+ CPed *passenger = nearCar->pPassengers[j];
+ if (passenger && passenger->CharCreatedBy != MISSION_CHAR)
+ {
+ nearCar->pPassengers[j]->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + leaveCarDelay;
+ leaveCarDelay += 200;
+ }
+ }
+ }
+ else
+ {
+ CPed *driver = nearCar->pDriver;
+ if (driver)
+ {
+ if (driver->m_objective != OBJECTIVE_LEAVE_VEHICLE && driver->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT &&
+ driver->m_objective != OBJECTIVE_FLEE_TILL_SAFE)
+ {
+ if (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH)
+ nearCar->AutoPilot.m_nCruiseSpeed = nearCar->AutoPilot.m_nCruiseSpeed * 1.5f;
+
+ nearCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;
+ }
+ }
+ }
+ }
+ }
+ if (m_eWeaponType == WEAPONTYPE_CHAINSAW)
+ {
+ CEntity *nearStatic = (CObject*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, true, false, false, true, false, false);
+ if (nearStatic)
+ {
+ for(int i=0; i < 4; i++) {
+ CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f), 0, 0.0f, 0, 0, 0, 0);
+ CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, 0.1f * gaTempSphereColPoints[0].normal, 0, 0.0f, 0, 0, 0, 0);
+ }
+
+ // TODO(Miami): Particle not in III
+ //CParticle::AddParticle(81, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0);
+
+ if (!damageEntityRegistered)
+ {
+ m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT;
+ if (shooterPed->m_fDamageImpulse == 0.0f)
+ {
+ shooterPed->m_pDamageEntity = nearStatic;
+ nearStatic->RegisterReference(&shooterPed->m_pDamageEntity);
+ }
+ }
+ if (nearStatic->IsObject() && ((CObject*)nearStatic)->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY)
+ ((CObject*)nearStatic)->ObjectDamage(200.0f);
+ }
+ }
return true;
}
@@ -634,45 +895,15 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource)
switch ( m_eWeaponType )
{
- case WEAPONTYPE_AK47:
- {
- static uint8 counter = 0;
-
- if ( !(++counter & 1) )
- {
- CPointLights::AddLight(CPointLights::LIGHT_POINT,
- *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f,
- 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);
-
- CVector gunflashPos = *fireSource;
- gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f);
- CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.10f);
- gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f);
- CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f);
- gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f);
- CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f);
- gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f);
- CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);
-
- CVector gunsmokePos = *fireSource;
- float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f);
- CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f));
-
- CVector gunshellPos = *fireSource;
- gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f);
- CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f));
- dir.Normalise2D();
- AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f);
- }
-
- break;
- }
-
case WEAPONTYPE_M16:
+ case WEAPONTYPE_AK47:
+ // case WEAPONTYPE_M60:
+ // case WEAPONTYPE_MINIGUN:
+ case WEAPONTYPE_HELICANNON:
{
static uint8 counter = 0;
- if ( !(++counter & 1) )
+ if ( info->m_nFiringRate >= 50 && !(++counter & 1) )
{
CPointLights::AddLight(CPointLights::LIGHT_POINT,
*fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f,
@@ -739,6 +970,9 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource)
}
case WEAPONTYPE_UZI:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
{
CPointLights::AddLight(CPointLights::LIGHT_POINT,
*fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f,
@@ -1387,10 +1621,12 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power)
ASSERT(fireSource!=nil);
CVector source, target;
+ eWeaponType projectileType = m_eWeaponType;
if ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER )
{
source = *fireSource;
+ projectileType = WEAPONTYPE_ROCKET;
if ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() )
{
@@ -1432,7 +1668,7 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power)
if ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) )
{
if ( m_eWeaponType != WEAPONTYPE_GRENADE )
- CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource);
+ CProjectileInfo::RemoveNotAdd(shooter, projectileType, *fireSource);
else
{
if ( shooter->IsPed() )
@@ -1441,14 +1677,14 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power)
source.z -= 0.4f;
if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, nil, false, false, true, false, false, false) )
- CProjectileInfo::AddProjectile(shooter, m_eWeaponType, source, 0.0f);
+ CProjectileInfo::AddProjectile(shooter, WEAPONTYPE_GRENADE, source, 0.0f);
else
- CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource);
+ CProjectileInfo::RemoveNotAdd(shooter, WEAPONTYPE_GRENADE, *fireSource);
}
}
}
else
- CProjectileInfo::AddProjectile(shooter, m_eWeaponType, *fireSource, power);
+ CProjectileInfo::AddProjectile(shooter, projectileType, *fireSource, power);
return true;
}
@@ -1532,7 +1768,7 @@ CWeapon::FireSniper(CEntity *shooter)
CVector dir = cam->Front;
if ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f )
- CCoronas::bSmallMoon = !CCoronas::bSmallMoon;
+ CCoronas::MoonSize = (CCoronas::MoonSize+1) & 7;
dir.Normalise();
dir *= 16.0f;
@@ -1555,6 +1791,7 @@ CWeapon::FireSniper(CEntity *shooter)
return true;
}
+// --MIAMI: Heavily TODO
bool
CWeapon::FireM16_1stPerson(CEntity *shooter)
{
@@ -1599,7 +1836,9 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
DoBulletImpact(shooter, victim, &source, &target, &point, front);
CVector bulletPos;
- if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, 4) )
+
+ // TODO(Miami): M60
+ if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, (/*m_eWeaponType == WEAPONTYPE_M60 || */ m_eWeaponType == WEAPONTYPE_HELICANNON ? 20 : 4)) )
{
for ( int32 i = 0; i < 16; i++ )
CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f));
@@ -1609,23 +1848,34 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
{
CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z);
- if ( m_eWeaponType == WEAPONTYPE_M16 )
- {
- TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f;
- TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f;
- }
- else if ( m_eWeaponType == WEAPONTYPE_HELICANNON )
- {
- TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f;
- TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f;
+ // TODO(Miami)
+ float mult;
+ switch (m_eWeaponType) {
+ case WEAPONTYPE_M16: // case WEAPONTYPE_M4:
+ case WEAPONTYPE_HELICANNON:
+ // case WEAPONTYPE_M60:
+ mult = 0.0003f;
+ break;
+ case WEAPONTYPE_AK47: // case WEAPONTYPE_RUGER:
+ mult = 0.00015f;
+ break;
+ default:
+ mult = 0.0002f;
+ break;
}
+
+ if (FindPlayerPed()->bIsDucking || FindPlayerPed()->m_attachedTo)
+ mult *= 0.3f;
+
+ TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * mult;
+ TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * mult;
}
return true;
}
bool
-CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left)
+CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left)
{
CWeaponInfo *info = GetInfo();
@@ -1996,8 +2246,10 @@ CWeapon::Reload(void)
}
void
-CWeapon::Update(int32 audioEntity)
+CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound)
{
+ CWeaponInfo *info = GetInfo();
+
switch ( m_eWeaponState )
{
case WEAPONSTATE_MELEE_MADECONTACT:
@@ -2030,9 +2282,57 @@ CWeapon::Update(int32 audioEntity)
{
if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE )
{
- uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType];
- if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed )
- DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f);
+ CAnimBlendAssociation *reloadAssoc = nil;
+ if (pedToAdjustSound) {
+ if (CPed::GetReloadAnim(info) && (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload || !pedToAdjustSound->IsPlayer())) {
+ reloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetReloadAnim(info));
+ if (!reloadAssoc) {
+ reloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetCrouchReloadAnim(info));
+ }
+ }
+ }
+ if (reloadAssoc && reloadAssoc->IsRunning() && reloadAssoc->blendAmount > 0.2f) {
+ float soundStart = 0.75f;
+ switch (info->m_AnimToPlay) {
+ case ASSOCGRP_PYTHON:
+ soundStart = 0.5f;
+ break;
+ case ASSOCGRP_COLT:
+ case ASSOCGRP_TEC:
+ soundStart = 0.7f;
+ break;
+ case ASSOCGRP_UZI:
+ soundStart = 0.75f;
+ break;
+ case ASSOCGRP_RIFLE:
+ soundStart = 0.75f;
+ break;
+ case ASSOCGRP_M60:
+ soundStart = 0.7f;
+ break;
+ default:
+ break;
+ }
+ if (reloadAssoc->GetProgress() >= soundStart && (reloadAssoc->currentTime - reloadAssoc->timeStep) / reloadAssoc->hierarchy->totalLength < soundStart) {
+#ifdef AUDIO_NOT_READY
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f);
+#else
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType);
+#endif
+ }
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer && reloadAssoc->GetProgress() < 0.9f) {
+ m_nTimer = CTimer::GetTimeInMilliseconds();
+ }
+ } else {
+ uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType];
+ if (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed) {
+#ifdef AUDIO_NOT_READY
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f);
+#else
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType);
+#endif
+ }
+ }
}
if ( CTimer::GetTimeInMilliseconds() > m_nTimer )
@@ -2155,13 +2455,17 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage)
bool
CWeapon::IsTypeMelee(void)
{
- return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT;
+ return CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE;
}
bool
CWeapon::IsType2Handed(void)
{
- return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER;
+ // TODO(Miami): Uncomment
+ return m_eWeaponType == WEAPONTYPE_FLAMETHROWER || m_eWeaponType == WEAPONTYPE_HELICANNON || /* m_eWeaponType == WEAPONTYPE_M60 */
+ m_eWeaponType == WEAPONTYPE_M16 ||
+ (m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType < WEAPONTYPE_TEC9) || // Shotguns
+ m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_SNIPERRIFLE /*|| m_eWeaponType == WEAPONTYPE_LASERSCOPE*/;
}
void
@@ -2268,13 +2572,15 @@ CWeapon::BlowUpExplosiveThings(CEntity *thing)
bool
CWeapon::HasWeaponAmmoToBeUsed(void)
{
- switch (m_eWeaponType) {
- case WEAPONTYPE_UNARMED:
- case WEAPONTYPE_BASEBALLBAT:
- return true;
- default:
- return m_nAmmoTotal != 0;
- }
+ // FIX: This is better (not bug tho)
+#if 0
+ if (m_eWeaponType <= WEAPONTYPE_CHAINSAW)
+#else
+ if (CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE)
+#endif
+ return true;
+ else
+ return m_nAmmoTotal != 0;
}
bool
diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h
index 1b2c0320..f6228b32 100644
--- a/src/weapons/Weapon.h
+++ b/src/weapons/Weapon.h
@@ -7,7 +7,8 @@
class CEntity;
class CPhysical;
-class CAutomobile;
+class CVehicle;
+class CPed;
struct CColPoint;
class CWeaponInfo;
@@ -16,8 +17,8 @@ class CWeapon
public:
eWeaponType m_eWeaponType;
eWeaponState m_eWeaponState;
- uint32 m_nAmmoInClip;
- uint32 m_nAmmoTotal;
+ int32 m_nAmmoInClip;
+ int32 m_nAmmoTotal;
uint32 m_nTimer;
bool m_bAddRotOffset;
@@ -32,9 +33,10 @@ public:
static void UpdateWeapons (void);
void Initialise(eWeaponType type, int32 ammo);
+ void Shutdown();
bool Fire (CEntity *shooter, CVector *fireSource);
- bool FireFromCar (CAutomobile *shooter, bool left);
+ bool FireFromCar (CVehicle *shooter, bool left);
bool FireMelee (CEntity *shooter, CVector &fireSource);
bool FireInstantHit(CEntity *shooter, CVector *fireSource);
@@ -49,14 +51,14 @@ public:
bool FireAreaEffect (CEntity *shooter, CVector *fireSource);
bool FireSniper (CEntity *shooter);
bool FireM16_1stPerson (CEntity *shooter);
- bool FireInstantHitFromCar(CAutomobile *shooter, bool left);
+ bool FireInstantHitFromCar(CVehicle *shooter, bool left);
static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target);
static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target);
static void DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target);
void Reload(void);
- void Update(int32 audioEntity);
+ void Update(int32 audioEntity, CPed *pedToAdjustSound);
bool IsTypeMelee (void);
bool IsType2Handed(void);
diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp
index c4ab75d2..d5e759b9 100644
--- a/src/weapons/WeaponInfo.cpp
+++ b/src/weapons/WeaponInfo.cpp
@@ -6,24 +6,47 @@
#include "AnimManager.h"
#include "AnimBlendAssociation.h"
#include "Weapon.h"
+#include "ModelInfo.h"
+#include "ModelIndices.h"
+
+// Yeah...
+int32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS];
+// --MIAMI: Todo
static char ms_aWeaponNames[][32] = {
"Unarmed",
+ "BrassKnuckle",
+ "ScrewDriver",
+ "GolfClub",
+ "NightStick",
+ "Knife",
"BaseballBat",
+ "Hammer",
+ "Cleaver",
+ "Machete",
+ "Katana",
+ "Chainsaw",
+ "Grenade",
+ "DetonateGrenade",
+ "Molotov",
+ "Rocket",
"Colt45",
- "Uzi",
"Shotgun",
- "AK47",
+ "Tec9",
+ "Uzi",
+ "SilencedIngram",
+ "Mp5",
"M16",
+ "AK47",
"SniperRifle",
"RocketLauncher",
"FlameThrower",
- "Molotov",
- "Grenade",
"Detonator",
- "HeliCannon"
+ "HeliCannon",
};
CWeaponInfo*
@@ -31,45 +54,61 @@ CWeaponInfo::GetWeaponInfo(eWeaponType weaponType) {
return &CWeaponInfo::ms_apWeaponInfos[weaponType];
}
+// --MIAMI: done except WEAPONTYPE_TOTALWEAPONS value
void
CWeaponInfo::Initialise(void)
{
debug("Initialising CWeaponInfo...\n");
for (int i = 0; i < WEAPONTYPE_TOTALWEAPONS; i++) {
ms_apWeaponInfos[i].m_eWeaponFire = WEAPON_FIRE_INSTANT_HIT;
- ms_apWeaponInfos[i].m_AnimToPlay = ANIM_PUNCH_R;
- ms_apWeaponInfos[i].m_Anim2ToPlay = NUM_ANIMS;
+ ms_apWeaponInfos[i].m_fRange = 0.0f;
+ ms_apWeaponInfos[i].m_nFiringRate = 0;
+ ms_apWeaponInfos[i].m_nReload = 0;
+ ms_apWeaponInfos[i].m_nAmountofAmmunition = 0;
+ ms_apWeaponInfos[i].m_nDamage = 0;
+ ms_apWeaponInfos[i].m_fSpeed = 0.0f;
+ ms_apWeaponInfos[i].m_fRadius = 0.0f;
+ ms_apWeaponInfos[i].m_fLifespan = 0.0f;
+ ms_apWeaponInfos[i].m_fSpread = 0.0f;
+ ms_apWeaponInfos[i].m_vecFireOffset = CVector(0.0f, 0.0f, 0.0f);
+ ms_apWeaponInfos[i].m_AnimToPlay = ASSOCGRP_UNARMED;
+ ms_apWeaponInfos[i].m_fAnimLoopStart = 0.0f;
+ ms_apWeaponInfos[i].m_fAnimLoopEnd = 0.0f;
+ ms_apWeaponInfos[i].m_fAnimFrameFire = 0.0f;
+ ms_apWeaponInfos[i].m_fAnim2LoopStart = 0.0f;
+ ms_apWeaponInfos[i].m_fAnim2LoopEnd = 0.0f;
+ ms_apWeaponInfos[i].m_fAnim2FrameFire = 0.0f;
+ ms_apWeaponInfos[i].m_fAnimBreakout = 0.0f;
ms_apWeaponInfos[i].m_bUseGravity = 1;
ms_apWeaponInfos[i].m_bSlowsDown = 1;
ms_apWeaponInfos[i].m_bRandSpeed = 1;
ms_apWeaponInfos[i].m_bExpands = 1;
ms_apWeaponInfos[i].m_bExplodes = 1;
+ ms_apWeaponInfos[i].m_nWeaponSlot = 0;
}
debug("Loading weapon data...\n");
LoadWeaponData();
debug("CWeaponInfo ready\n");
}
+// --MIAMI: Done, commented parts wait for weapons port
void
CWeaponInfo::LoadWeaponData(void)
{
float spread, speed, lifeSpan, radius;
float range, fireOffsetX, fireOffsetY, fireOffsetZ;
- float delayBetweenAnimAndFire, delayBetweenAnim2AndFire, animLoopStart, animLoopEnd;
+ float anim2LoopStart, anim2LoopEnd, delayBetweenAnim2AndFire, animBreakout;
+ float delayBetweenAnimAndFire, animLoopStart, animLoopEnd;
int flags, ammoAmount, damage, reload, weaponType;
- int firingRate, modelId;
+ int firingRate, modelId, modelId2, weaponSlot;
char line[256], weaponName[32], fireType[32];
- char animToPlay[32], anim2ToPlay[32];
-
- CAnimBlendAssociation *animAssoc;
- AnimationId animId;
+ char animToPlay[32];
int bp, buflen;
int lp, linelen;
CFileMgr::SetDir("DATA");
buflen = CFileMgr::LoadFile("WEAPON.DAT", work_buff, sizeof(work_buff), "r");
- CFileMgr::SetDir("");
for (bp = 0; bp < buflen; ) {
// read file line by line
@@ -101,10 +140,9 @@ CWeaponInfo::LoadWeaponData(void)
fireType[0] = '\0';
fireOffsetY = 0.0f;
fireOffsetZ = 0.0f;
- animId = ANIM_WALK;
sscanf(
&line[lp],
- "%s %s %f %d %d %d %d %f %f %f %f %f %f %f %s %s %f %f %f %f %d %d",
+ "%s %s %f %d %d %d %d %f %f %f %f %f %f %f %s %f %f %f %f %f %f %f %d %d %x %d",
weaponName,
fireType,
&range,
@@ -120,27 +158,23 @@ CWeaponInfo::LoadWeaponData(void)
&fireOffsetY,
&fireOffsetZ,
animToPlay,
- anim2ToPlay,
&animLoopStart,
&animLoopEnd,
&delayBetweenAnimAndFire,
+ &anim2LoopStart,
+ &anim2LoopEnd,
&delayBetweenAnim2AndFire,
+ &animBreakout,
&modelId,
- &flags);
+ &modelId2,
+ &flags,
+ &weaponSlot);
if (strncmp(weaponName, "ENDWEAPONDATA", 13) == 0)
return;
weaponType = FindWeaponType(weaponName);
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animToPlay);
- animId = static_cast<AnimationId>(animAssoc->animId);
-
- if (strncmp(anim2ToPlay, "null", 4) != 0) {
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, anim2ToPlay);
- ms_apWeaponInfos[weaponType].m_Anim2ToPlay = (AnimationId) animAssoc->animId;
- }
-
CVector vecFireOffset(fireOffsetX, fireOffsetY, fireOffsetZ);
ms_apWeaponInfos[weaponType].m_eWeaponFire = FindWeaponFireType(fireType);
@@ -154,12 +188,16 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_fLifespan = lifeSpan;
ms_apWeaponInfos[weaponType].m_fSpread = spread;
ms_apWeaponInfos[weaponType].m_vecFireOffset = vecFireOffset;
- ms_apWeaponInfos[weaponType].m_AnimToPlay = animId;
ms_apWeaponInfos[weaponType].m_fAnimLoopStart = animLoopStart / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnimLoopEnd = animLoopEnd / 30.0f;
+ ms_apWeaponInfos[weaponType].m_fAnim2LoopStart = anim2LoopStart / 30.0f;
+ ms_apWeaponInfos[weaponType].m_fAnim2LoopEnd = anim2LoopEnd / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnim2FrameFire = delayBetweenAnim2AndFire / 30.0f;
+ ms_apWeaponInfos[weaponType].m_fAnimBreakout = animBreakout / 30.0f;
ms_apWeaponInfos[weaponType].m_nModelId = modelId;
+ ms_apWeaponInfos[weaponType].m_nModel2Id = modelId2;
+
ms_apWeaponInfos[weaponType].m_bUseGravity = flags;
ms_apWeaponInfos[weaponType].m_bSlowsDown = flags >> 1;
ms_apWeaponInfos[weaponType].m_bDissipates = flags >> 2;
@@ -171,6 +209,39 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_b1stPerson = flags >> 8;
ms_apWeaponInfos[weaponType].m_bHeavy = flags >> 9;
ms_apWeaponInfos[weaponType].m_bThrow = flags >> 10;
+ ms_apWeaponInfos[weaponType].m_bReloadLoop2Start = flags >> 11;
+ ms_apWeaponInfos[weaponType].m_bUse2nd = flags >> 12;
+ ms_apWeaponInfos[weaponType].m_bGround2nd = flags >> 13;
+ ms_apWeaponInfos[weaponType].m_bFinish3rd = flags >> 14;
+ ms_apWeaponInfos[weaponType].m_bReload = flags >> 15;
+ ms_apWeaponInfos[weaponType].m_bFightMode = flags >> 16;
+ ms_apWeaponInfos[weaponType].m_bCrouchFire = flags >> 17;
+ ms_apWeaponInfos[weaponType].m_bCop3rd = flags >> 18;
+ ms_apWeaponInfos[weaponType].m_bGround3rd = flags >> 19;
+ ms_apWeaponInfos[weaponType].m_bPartialAttack = flags >> 20;
+ ms_apWeaponInfos[weaponType].m_bAnimDetonate = flags >> 21;
+
+ ms_apWeaponInfos[weaponType].m_nWeaponSlot = weaponSlot;
+
+ // TODO(Miami): Enable once weapons are done
+ if (animLoopEnd < 98.0f && weaponType != WEAPONTYPE_FLAMETHROWER && weaponType != WEAPONTYPE_SHOTGUN
+ /*&& weaponType != 20 && weaponType != 21*/)
+ ms_apWeaponInfos[weaponType].m_nFiringRate = ((ms_apWeaponInfos[weaponType].m_fAnimLoopEnd - ms_apWeaponInfos[weaponType].m_fAnimLoopStart) * 900.0f);
+
+ if (weaponType == WEAPONTYPE_DETONATOR || weaponType == WEAPONTYPE_HELICANNON)
+ modelId = -1;
+ else if (weaponType == WEAPONTYPE_DETONATOR_GRENADE)
+ modelId = MI_BOMB;
+
+ if (modelId != -1)
+ ((CWeaponModelInfo*)CModelInfo::GetModelInfo(modelId))->SetWeaponInfo(weaponType);
+
+ for (int i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++) {
+ if (!strcmp(animToPlay, CAnimManager::GetAnimGroupName((AssocGroupId)i))) {
+ ms_apWeaponInfos[weaponType].m_AnimToPlay = (AssocGroupId)i;
+ break;
+ }
+ }
}
}
diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h
index b5882082..41450047 100644
--- a/src/weapons/WeaponInfo.h
+++ b/src/weapons/WeaponInfo.h
@@ -3,28 +3,34 @@
#include "AnimationId.h"
#include "WeaponType.h"
+enum AssocGroupId;
+
class CWeaponInfo {
-// static CWeaponInfo(&ms_apWeaponInfos)[14];
- static CWeaponInfo ms_apWeaponInfos[14];
+ static CWeaponInfo ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS];
public:
+ static int32 ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS];
+
eWeaponFire m_eWeaponFire;
float m_fRange;
uint32 m_nFiringRate;
uint32 m_nReload;
- uint32 m_nAmountofAmmunition;
+ int32 m_nAmountofAmmunition;
uint32 m_nDamage;
float m_fSpeed;
float m_fRadius;
float m_fLifespan;
float m_fSpread;
CVector m_vecFireOffset;
- AnimationId m_AnimToPlay;
- AnimationId m_Anim2ToPlay;
+ AssocGroupId m_AnimToPlay;
float m_fAnimLoopStart;
float m_fAnimLoopEnd;
float m_fAnimFrameFire;
+ float m_fAnim2LoopStart;
+ float m_fAnim2LoopEnd;
float m_fAnim2FrameFire;
+ float m_fAnimBreakout;
int32 m_nModelId;
+ int32 m_nModel2Id;
// flags
uint8 m_bUseGravity : 1;
uint8 m_bSlowsDown : 1;
@@ -34,9 +40,24 @@ public:
uint8 m_bExplodes : 1;
uint8 m_bCanAim : 1;
uint8 m_bCanAimWithArm : 1;
+
uint8 m_b1stPerson : 1;
uint8 m_bHeavy : 1;
uint8 m_bThrow : 1;
+ uint8 m_bReloadLoop2Start : 1;
+ uint8 m_bUse2nd : 1;
+ uint8 m_bGround2nd : 1;
+ uint8 m_bFinish3rd : 1;
+ uint8 m_bReload : 1;
+
+ uint8 m_bFightMode : 1;
+ uint8 m_bCrouchFire : 1;
+ uint8 m_bCop3rd : 1;
+ uint8 m_bGround3rd : 1;
+ uint8 m_bPartialAttack : 1;
+ uint8 m_bAnimDetonate : 1;
+
+ uint32 m_nWeaponSlot;
static void Initialise(void);
static void LoadWeaponData(void);
@@ -46,4 +67,4 @@ public:
static void Shutdown(void);
};
-VALIDATE_SIZE(CWeaponInfo, 0x54); \ No newline at end of file
+VALIDATE_SIZE(CWeaponInfo, 0x64);
diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h
index b45740b7..6516828a 100644
--- a/src/weapons/WeaponType.h
+++ b/src/weapons/WeaponType.h
@@ -1,22 +1,39 @@
#pragma once
+// --MIAMI: TODO
enum eWeaponType
{
WEAPONTYPE_UNARMED,
+ WEAPONTYPE_BRASSKNUCKLE,
+ WEAPONTYPE_SCREWDRIVER,
+ WEAPONTYPE_GOLFCLUB,
+ WEAPONTYPE_NIGHTSTICK,
+ WEAPONTYPE_KNIFE,
WEAPONTYPE_BASEBALLBAT,
+ WEAPONTYPE_HAMMER,
+ WEAPONTYPE_CLEAVER,
+ WEAPONTYPE_MACHETE,
+ WEAPONTYPE_KATANA,
+ WEAPONTYPE_CHAINSAW,
+ WEAPONTYPE_GRENADE,
+ WEAPONTYPE_DETONATOR_GRENADE,
+ WEAPONTYPE_MOLOTOV,
+ WEAPONTYPE_ROCKET,
WEAPONTYPE_COLT45,
- WEAPONTYPE_UZI,
WEAPONTYPE_SHOTGUN,
- WEAPONTYPE_AK47,
+ WEAPONTYPE_TEC9,
+ WEAPONTYPE_UZI,
+ WEAPONTYPE_SILENCED_INGRAM,
+ WEAPONTYPE_MP5,
WEAPONTYPE_M16,
+ WEAPONTYPE_AK47,
WEAPONTYPE_SNIPERRIFLE,
WEAPONTYPE_ROCKETLAUNCHER,
WEAPONTYPE_FLAMETHROWER,
- WEAPONTYPE_MOLOTOV,
- WEAPONTYPE_GRENADE,
WEAPONTYPE_DETONATOR,
WEAPONTYPE_HELICANNON,
WEAPONTYPE_LAST_WEAPONTYPE,
+ WEAPONTYPE_HEALTH,
WEAPONTYPE_ARMOUR,
WEAPONTYPE_RAMMEDBYCAR,
WEAPONTYPE_RUNOVERBYCAR,
@@ -27,7 +44,10 @@ enum eWeaponType
WEAPONTYPE_UNIDENTIFIED,
WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE,
- WEAPONTYPE_TOTAL_INVENTORY_WEAPONS = 13,
+};
+
+enum {
+ TOTAL_WEAPON_SLOTS = 10,
};
enum eWeaponFire {