summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFire-Head <Fire-Head@users.noreply.github.com>2020-12-07 21:50:18 +0300
committerFire-Head <Fire-Head@users.noreply.github.com>2020-12-07 21:50:18 +0300
commit87bca997a45c3364b3994fddb40230ef20a56d90 (patch)
tree1a4c6997451d097141386bf246dfeef97dd2794c /src
parentc5fbb594a51f37e5a3af6c6b98342a71c8fe4611 (diff)
parent66fc4e44fc25eeec3da8224e3cf5bc1a78bbd06b (diff)
Merge branch 'master' of https://github.com/GTAmodding/re3
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt113
-rw-r--r--src/animation/AnimBlendAssociation.cpp2
-rw-r--r--src/animation/AnimBlendAssociation.h2
-rw-r--r--src/animation/AnimBlendClumpData.cpp2
-rw-r--r--src/animation/AnimBlendHierarchy.cpp29
-rw-r--r--src/animation/AnimBlendHierarchy.h5
-rw-r--r--src/animation/AnimBlendSequence.cpp137
-rw-r--r--src/animation/AnimBlendSequence.h21
-rw-r--r--src/animation/AnimManager.cpp2
-rw-r--r--src/audio/AudioLogic.cpp1497
-rw-r--r--src/audio/AudioManager.cpp2
-rw-r--r--src/audio/AudioManager.h56
-rw-r--r--src/audio/MusicManager.cpp2
-rw-r--r--src/audio/oal/stream.cpp6
-rw-r--r--src/audio/sampman_miles.cpp16
-rw-r--r--src/collision/ColBox.cpp21
-rw-r--r--src/collision/ColBox.h16
-rw-r--r--src/collision/ColLine.cpp9
-rw-r--r--src/collision/ColLine.h14
-rw-r--r--src/collision/ColModel.cpp190
-rw-r--r--src/collision/ColModel.h37
-rw-r--r--src/collision/ColPoint.cpp16
-rw-r--r--src/collision/ColPoint.h34
-rw-r--r--src/collision/ColSphere.cpp11
-rw-r--r--src/collision/ColSphere.h13
-rw-r--r--src/collision/ColTriangle.cpp41
-rw-r--r--src/collision/ColTriangle.h68
-rw-r--r--src/collision/Collision.cpp (renamed from src/core/Collision.cpp)568
-rw-r--r--src/collision/Collision.h70
-rw-r--r--src/collision/CompressedVector.h36
-rw-r--r--src/collision/TempColModels.cpp (renamed from src/core/TempColModels.cpp)55
-rw-r--r--src/collision/TempColModels.h (renamed from src/core/TempColModels.h)0
-rw-r--r--src/collision/VuCollision.cpp282
-rw-r--r--src/collision/VuCollision.h32
-rw-r--r--src/collision/vu0Collision.dsm (renamed from src/core/vu0Collision.dsm)0
-rw-r--r--src/collision/vu0Collision_1.s (renamed from src/core/vu0Collision_1.s)0
-rw-r--r--src/collision/vu0Collision_2.s (renamed from src/core/vu0Collision_2.s)0
-rw-r--r--src/control/CarCtrl.cpp2
-rw-r--r--src/control/GameLogic.cpp10
-rw-r--r--src/control/Garages.cpp216
-rw-r--r--src/control/Garages.h3
-rw-r--r--src/control/NameGrid.cpp87
-rw-r--r--src/control/NameGrid.h53
-rw-r--r--src/control/PathFind.cpp24
-rw-r--r--src/control/Phones.cpp2
-rw-r--r--src/control/Pickups.cpp88
-rw-r--r--src/control/Replay.cpp3
-rw-r--r--src/control/Replay.h33
-rw-r--r--src/control/Restart.cpp4
-rw-r--r--src/control/SceneEdit.cpp3
-rw-r--r--src/control/SceneEdit.h3
-rw-r--r--src/control/Script.cpp8960
-rw-r--r--src/control/Script.h30
-rw-r--r--src/control/Script2.cpp1555
-rw-r--r--src/control/Script3.cpp2082
-rw-r--r--src/control/Script4.cpp2027
-rw-r--r--src/control/Script5.cpp2011
-rw-r--r--src/control/Script6.cpp1343
-rw-r--r--src/control/ScriptCommands.h2
-rw-r--r--src/core/AnimViewer.cpp10
-rw-r--r--src/core/Cam.cpp14
-rw-r--r--src/core/Camera.cpp36
-rw-r--r--src/core/Camera.h4
-rw-r--r--src/core/CdStream.cpp10
-rw-r--r--src/core/CdStreamPosix.cpp4
-rw-r--r--src/core/Collision.h254
-rw-r--r--src/core/ControllerConfig.cpp244
-rw-r--r--src/core/FileLoader.cpp40
-rw-r--r--src/core/Frontend.cpp1272
-rw-r--r--src/core/Frontend.h121
-rw-r--r--src/core/Frontend_PS2.cpp18
-rw-r--r--src/core/Frontend_PS2.h22
-rw-r--r--src/core/Game.cpp610
-rw-r--r--src/core/MenuScreens.cpp14
-rw-r--r--src/core/MenuScreensCustom.cpp878
-rw-r--r--src/core/Pad.cpp27
-rw-r--r--src/core/Pad.h3
-rw-r--r--src/core/Pools.cpp19
-rw-r--r--src/core/Streaming.cpp174
-rw-r--r--src/core/Streaming.h2
-rw-r--r--src/core/World.cpp52
-rw-r--r--src/core/ZoneCull.cpp1165
-rw-r--r--src/core/ZoneCull.h32
-rw-r--r--src/core/config.h107
-rw-r--r--src/core/main.cpp398
-rw-r--r--src/core/main.h4
-rw-r--r--src/core/re3.cpp511
-rw-r--r--src/core/templates.h28
-rw-r--r--src/entities/Entity.cpp5
-rw-r--r--src/entities/Physical.cpp26
-rw-r--r--src/extras/custompipes.cpp2
-rw-r--r--src/extras/custompipes.h1
-rw-r--r--src/extras/custompipes_d3d9.cpp1
-rw-r--r--src/extras/custompipes_gl.cpp47
-rw-r--r--src/extras/debugmenu.cpp2
-rw-r--r--src/extras/frontendoption.cpp238
-rw-r--r--src/extras/frontendoption.h121
-rw-r--r--src/extras/postfx.cpp33
-rw-r--r--src/extras/postfx.h1
-rw-r--r--src/extras/re3_inttypes.h (renamed from src/extras/inttypes.h)0
-rw-r--r--src/extras/screendroplets.cpp791
-rw-r--r--src/extras/screendroplets.h78
-rw-r--r--src/extras/shaders/Makefile69
-rw-r--r--src/extras/shaders/colourfilterIII.frag11
-rw-r--r--src/extras/shaders/colourfilterIII_fs_gl.inc (renamed from src/extras/shaders/colourfilterIII_fs_gl3.inc)11
-rw-r--r--src/extras/shaders/contrast.frag11
-rw-r--r--src/extras/shaders/contrast_fs_gl.inc (renamed from src/extras/shaders/contrast_fs_gl3.inc)11
-rw-r--r--src/extras/shaders/default_UV2.vert14
-rw-r--r--src/extras/shaders/default_UV2_gl.inc (renamed from src/extras/shaders/default_UV2_gl3.inc)14
-rw-r--r--src/extras/shaders/im2d.vert10
-rw-r--r--src/extras/shaders/im2d_UV2.vert21
-rw-r--r--src/extras/shaders/im2d_UV2_gl.inc23
-rw-r--r--src/extras/shaders/im2d_gl.inc (renamed from src/extras/shaders/im2d_gl3.inc)10
-rw-r--r--src/extras/shaders/neoGloss.frag14
-rw-r--r--src/extras/shaders/neoGloss.vert14
-rw-r--r--src/extras/shaders/neoGloss_fs_gl.inc (renamed from src/extras/shaders/neoGloss_fs_gl3.inc)14
-rw-r--r--src/extras/shaders/neoGloss_vs_gl.inc (renamed from src/extras/shaders/neoGloss_vs_gl3.inc)14
-rw-r--r--src/extras/shaders/neoRim.vert13
-rw-r--r--src/extras/shaders/neoRimSkin.vert15
-rw-r--r--src/extras/shaders/neoRimSkin_gl.inc (renamed from src/extras/shaders/neoRimSkin_gl3.inc)15
-rw-r--r--src/extras/shaders/neoRim_gl.inc (renamed from src/extras/shaders/neoRim_gl3.inc)13
-rw-r--r--src/extras/shaders/neoVehicle.frag15
-rw-r--r--src/extras/shaders/neoVehicle.vert17
-rw-r--r--src/extras/shaders/neoVehicle_fs_gl.inc (renamed from src/extras/shaders/neoVehicle_fs_gl3.inc)15
-rw-r--r--src/extras/shaders/neoVehicle_vs_gl.inc (renamed from src/extras/shaders/neoVehicle_vs_gl3.inc)17
-rw-r--r--src/extras/shaders/neoWorldIII.frag14
-rw-r--r--src/extras/shaders/neoWorldIII_fs_gl.inc (renamed from src/extras/shaders/neoWorldIII_fs_gl3.inc)14
-rw-r--r--src/extras/shaders/screenDroplet.frag18
-rw-r--r--src/extras/shaders/screenDroplet_PS.csobin0 -> 324 bytes
-rw-r--r--src/extras/shaders/screenDroplet_PS.hlsl17
-rw-r--r--src/extras/shaders/screenDroplet_PS.inc29
-rw-r--r--src/extras/shaders/screenDroplet_fs_gl.inc20
-rw-r--r--src/extras/shaders/simple.frag11
-rw-r--r--src/extras/shaders/simple_fs_gl.inc (renamed from src/extras/shaders/simple_fs_gl3.inc)11
-rw-r--r--src/fakerw/fake.cpp118
-rw-r--r--src/fakerw/rwcore.h2
-rw-r--r--src/fakerw/rwplcore.h6
-rw-r--r--src/modelinfo/BaseModelInfo.h4
-rw-r--r--src/modelinfo/ModelIndices.cpp2
-rw-r--r--src/modelinfo/PedModelInfo.h1
-rw-r--r--src/modelinfo/SimpleModelInfo.h12
-rw-r--r--src/modelinfo/VehicleModelInfo.cpp13
-rw-r--r--src/objects/CutsceneHead.cpp37
-rw-r--r--src/objects/ParticleObject.cpp6
-rw-r--r--src/objects/ParticleObject.h2
-rw-r--r--src/objects/Projectile.h2
-rw-r--r--src/peds/CivilianPed.cpp42
-rw-r--r--src/peds/CopPed.cpp2
-rw-r--r--src/peds/Ped.cpp18610
-rw-r--r--src/peds/Ped.h48
-rw-r--r--src/peds/PedAI.cpp5413
-rw-r--r--src/peds/PedChat.cpp53
-rw-r--r--src/peds/PedFight.cpp3250
-rw-r--r--src/peds/PedStats.cpp118
-rw-r--r--src/peds/PedStats.h80
-rw-r--r--src/peds/PedType.cpp113
-rw-r--r--src/peds/PedType.h79
-rw-r--r--src/render/2dEffect.h4
-rw-r--r--src/render/Clouds.cpp10
-rw-r--r--src/render/Font.cpp231
-rw-r--r--src/render/Font.h38
-rw-r--r--src/render/Hud.cpp9
-rw-r--r--src/render/Particle.cpp52
-rw-r--r--src/render/PlayerSkin.cpp1
-rw-r--r--src/render/Renderer.cpp246
-rw-r--r--src/render/Renderer.h22
-rw-r--r--src/render/Rubbish.cpp8
-rw-r--r--src/render/Skidmarks.cpp6
-rw-r--r--src/render/WaterLevel.cpp5
-rw-r--r--src/rw/Lights.cpp41
-rw-r--r--src/rw/Lights.h2
-rw-r--r--src/rw/MemoryHeap.cpp497
-rw-r--r--src/rw/MemoryHeap.h225
-rw-r--r--src/rw/MemoryMgr.cpp130
-rw-r--r--src/rw/MemoryMgr.h12
-rw-r--r--src/rw/RwHelper.cpp123
-rw-r--r--src/rw/RwHelper.h7
-rw-r--r--src/rw/TexRead.cpp108
-rw-r--r--src/rw/TexturePools.cpp221
-rw-r--r--src/rw/TexturePools.h42
-rw-r--r--src/rw/VisibilityPlugins.cpp172
-rw-r--r--src/save/MemoryCard.cpp1
-rw-r--r--src/skel/glfw/glfw.cpp47
-rw-r--r--src/skel/skeleton.cpp5
-rw-r--r--src/skel/win/win.cpp27
-rw-r--r--src/vehicles/Automobile.cpp89
-rw-r--r--src/vehicles/Boat.cpp2
-rw-r--r--src/vehicles/Cranes.cpp6
-rw-r--r--src/vehicles/HandlingMgr.cpp26
-rw-r--r--src/vehicles/HandlingMgr.h21
-rw-r--r--src/vehicles/Heli.cpp11
-rw-r--r--src/vehicles/Plane.cpp7
-rw-r--r--src/vehicles/Train.cpp2
-rw-r--r--src/vehicles/Vehicle.cpp9
-rw-r--r--src/vehicles/Vehicle.h11
-rw-r--r--src/weapons/Weapon.cpp10
-rw-r--r--src/weapons/WeaponEffects.cpp2
197 files changed, 33331 insertions, 27050 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 00000000..ef322a9a
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,113 @@
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads REQUIRED)
+
+if(${RE3_AUDIO} STREQUAL "OAL")
+ find_package(OpenAL REQUIRED)
+ find_package(MPG123 REQUIRED)
+ find_package(SndFile REQUIRED)
+endif()
+
+file(GLOB_RECURSE Sources "*.cpp" "*.h")
+
+MACRO(HEADER_DIRECTORIES return_list)
+ FILE(GLOB_RECURSE new_list *.cpp)
+ SET(dir_list "animation"
+ "audio"
+ "collision"
+ "control"
+ "core"
+ "entities"
+ "extras"
+ "fakerw"
+ "math"
+ "modelinfo"
+ "objects"
+ "peds"
+ "render"
+ "rw"
+ "save"
+ "skel"
+ "text"
+ "vehicles"
+ "weapons")
+ FOREACH(file_path ${new_list})
+ GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
+ SET(dir_list ${dir_list} ${dir_path})
+ ENDFOREACH()
+ LIST(REMOVE_DUPLICATES dir_list)
+ SET(${return_list} ${dir_list})
+ENDMACRO()
+
+HEADER_DIRECTORIES(header_list)
+include_directories(${header_list})
+
+
+add_executable(re3 ${Sources})
+target_link_libraries(re3 librw)
+target_link_libraries(re3 Threads::Threads)
+
+if(${RE3_AUDIO} STREQUAL "OAL")
+ target_link_libraries(re3 ${OPENAL_LIBRARY})
+ target_link_libraries(re3 ${MPG123_LIBRARIES})
+ target_link_libraries(re3 ${SNDFILE_LIBRARIES})
+endif()
+
+target_include_directories(re3
+ INTERFACE
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
+ )
+
+target_compile_definitions(re3
+ PRIVATE
+ "$<IF:$<CONFIG:DEBUG>,DEBUG,NDEBUG>"
+ PUBLIC
+ "RW_${RE3_PLATFORM}"
+ )
+
+target_compile_definitions(re3 PRIVATE LIBRW=1 AUDIO_OAL=1)
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+ target_compile_options(re3
+ PRIVATE
+ "-Wall"
+ )
+ if (NOT RE3_PLATFORM_PS2)
+ target_compile_options(re3
+ PRIVATE
+ "-Wextra"
+ "-Wdouble-promotion"
+ "-Wpedantic"
+ )
+ endif()
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ target_compile_options(re3
+ PUBLIC
+ /wd4996 /wd4244
+ )
+endif()
+
+set_target_properties(re3
+ PROPERTIES
+ C_STANDARD 11
+ C_EXTENSIONS OFF
+ C_STANDARD_REQUIRED ON
+ CXX_STANDARD 11
+ CXX_EXTENSIONS OFF
+ CXX_STANDARD_REQUIRED ON
+ PREFIX ""
+ )
+
+if(RE3_INSTALL)
+ target_include_directories(re3
+ INTERFACE
+ $<INSTALL_INTERFACE:${RE3_INSTALL_INCLUDEDIR}>
+ )
+
+ install(
+ TARGETS re3
+ EXPORT re3-targets
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ )
+endif()
diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp
index 8c99b694..b03571b0 100644
--- a/src/animation/AnimBlendAssociation.cpp
+++ b/src/animation/AnimBlendAssociation.cpp
@@ -5,7 +5,7 @@
#include "RpAnimBlend.h"
#include "AnimManager.h"
#include "AnimBlendAssociation.h"
-#include "RwHelper.h"
+#include "MemoryMgr.h"
CAnimBlendAssociation::CAnimBlendAssociation(void)
{
diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h
index 2dff4391..80927da2 100644
--- a/src/animation/AnimBlendAssociation.h
+++ b/src/animation/AnimBlendAssociation.h
@@ -13,7 +13,7 @@ enum {
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_IDLE = 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
diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp
index d40e8357..92515427 100644
--- a/src/animation/AnimBlendClumpData.cpp
+++ b/src/animation/AnimBlendClumpData.cpp
@@ -1,7 +1,7 @@
#include "common.h"
#include "AnimBlendClumpData.h"
-#include "RwHelper.h"
+#include "MemoryMgr.h"
CAnimBlendClumpData::CAnimBlendClumpData(void)
diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp
index feeaca3d..c7800de5 100644
--- a/src/animation/AnimBlendHierarchy.cpp
+++ b/src/animation/AnimBlendHierarchy.cpp
@@ -30,15 +30,14 @@ 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);
+ totalLength = Max(totalLength, seqTime);
}
- totalLength = totalTime;
}
void
@@ -61,6 +60,12 @@ CAnimBlendHierarchy::RemoveAnimSequences(void)
void
CAnimBlendHierarchy::Uncompress(void)
{
+#ifdef ANIM_COMPRESSION
+ int i;
+ assert(compressed);
+ for(i = 0; i < numSequences; i++)
+ sequences[i].Uncompress();
+#endif
if(totalLength == 0.0f)
CalcTotalTime();
compressed = 0;
@@ -69,6 +74,22 @@ CAnimBlendHierarchy::Uncompress(void)
void
CAnimBlendHierarchy::RemoveUncompressedData(void)
{
- // useless
+#ifdef ANIM_COMPRESSION
+ int i;
+ assert(!compressed);
+ for(i = 0; i < numSequences; i++)
+ sequences[i].RemoveUncompressedData();
+#endif
compressed = 1;
}
+
+#ifdef USE_CUSTOM_ALLOCATOR
+void
+CAnimBlendHierarchy::MoveMemory(bool onlyone)
+{
+ int i;
+ for(i = 0; i < numSequences; i++)
+ if(sequences[i].MoveMemory() && onlyone)
+ return;
+}
+#endif
diff --git a/src/animation/AnimBlendHierarchy.h b/src/animation/AnimBlendHierarchy.h
index 0144108d..e35b4925 100644
--- a/src/animation/AnimBlendHierarchy.h
+++ b/src/animation/AnimBlendHierarchy.h
@@ -2,6 +2,10 @@
#include "templates.h"
+#ifdef MoveMemory
+#undef MoveMemory // windows shit
+#endif
+
class CAnimBlendSequence;
// A collection of sequences
@@ -23,6 +27,7 @@ public:
void RemoveAnimSequences(void);
void Uncompress(void);
void RemoveUncompressedData(void);
+ void MoveMemory(bool onlyone = false);
};
VALIDATE_SIZE(CAnimBlendHierarchy, 0x28); \ No newline at end of file
diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp
index 4578ec50..c958b71a 100644
--- a/src/animation/AnimBlendSequence.cpp
+++ b/src/animation/AnimBlendSequence.cpp
@@ -1,6 +1,7 @@
#include "common.h"
#include "AnimBlendSequence.h"
+#include "MemoryHeap.h"
CAnimBlendSequence::CAnimBlendSequence(void)
{
@@ -15,6 +16,7 @@ CAnimBlendSequence::CAnimBlendSequence(void)
CAnimBlendSequence::~CAnimBlendSequence(void)
{
+ assert(keyFramesCompressed == nil);
if(keyFrames)
RwFree(keyFrames);
}
@@ -60,3 +62,138 @@ CAnimBlendSequence::RemoveQuaternionFlips(void)
last = frame->rotation;
}
}
+
+void
+CAnimBlendSequence::Uncompress(void)
+{
+ int i;
+
+ if(numFrames == 0)
+ return;
+
+ PUSH_MEMID(MEMID_ANIMATION);
+
+ float rotScale = 1.0f/4096.0f;
+ float timeScale = 1.0f/60.0f;
+ float transScale = 1.0f/128.0f;
+ if(type & KF_TRANS){
+ void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTrans));
+ KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)keyFramesCompressed;
+ KeyFrameTrans *kf = (KeyFrameTrans*)newKfs;
+ for(i = 0; i < numFrames; i++){
+ kf->rotation.x = ckf->rot[0]*rotScale;
+ kf->rotation.y = ckf->rot[1]*rotScale;
+ kf->rotation.z = ckf->rot[2]*rotScale;
+ kf->rotation.w = ckf->rot[3]*rotScale;
+ kf->deltaTime = ckf->deltaTime*timeScale;
+ kf->translation.x = ckf->trans[0]*transScale;
+ kf->translation.y = ckf->trans[1]*transScale;
+ kf->translation.z = ckf->trans[2]*transScale;
+ kf++;
+ ckf++;
+ }
+ keyFrames = newKfs;
+ }else{
+ void *newKfs = RwMalloc(numFrames * sizeof(KeyFrame));
+ KeyFrameCompressed *ckf = (KeyFrameCompressed*)keyFramesCompressed;
+ KeyFrame *kf = (KeyFrame*)newKfs;
+ for(i = 0; i < numFrames; i++){
+ kf->rotation.x = ckf->rot[0]*rotScale;
+ kf->rotation.y = ckf->rot[1]*rotScale;
+ kf->rotation.z = ckf->rot[2]*rotScale;
+ kf->rotation.w = ckf->rot[3]*rotScale;
+ kf->deltaTime = ckf->deltaTime*timeScale;
+ kf++;
+ ckf++;
+ }
+ keyFrames = newKfs;
+ }
+ REGISTER_MEMPTR(&keyFrames);
+
+ RwFree(keyFramesCompressed);
+ keyFramesCompressed = nil;
+
+ POP_MEMID();
+}
+
+void
+CAnimBlendSequence::CompressKeyframes(void)
+{
+ int i;
+
+ if(numFrames == 0)
+ return;
+
+ PUSH_MEMID(MEMID_ANIMATION);
+
+ float rotScale = 4096.0f;
+ float timeScale = 60.0f;
+ float transScale = 128.0f;
+ if(type & KF_TRANS){
+ void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTransCompressed));
+ KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)newKfs;
+ KeyFrameTrans *kf = (KeyFrameTrans*)keyFrames;
+ for(i = 0; i < numFrames; i++){
+ ckf->rot[0] = kf->rotation.x*rotScale;
+ ckf->rot[1] = kf->rotation.y*rotScale;
+ ckf->rot[2] = kf->rotation.z*rotScale;
+ ckf->rot[3] = kf->rotation.w*rotScale;
+ ckf->deltaTime = kf->deltaTime*timeScale + 0.5f;
+ ckf->trans[0] = kf->translation.x*transScale;
+ ckf->trans[1] = kf->translation.y*transScale;
+ ckf->trans[2] = kf->translation.z*transScale;
+ kf++;
+ ckf++;
+ }
+ keyFramesCompressed = newKfs;
+ }else{
+ void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameCompressed));
+ KeyFrameCompressed *ckf = (KeyFrameCompressed*)newKfs;
+ KeyFrame *kf = (KeyFrame*)keyFrames;
+ for(i = 0; i < numFrames; i++){
+ ckf->rot[0] = kf->rotation.x*rotScale;
+ ckf->rot[1] = kf->rotation.y*rotScale;
+ ckf->rot[2] = kf->rotation.z*rotScale;
+ ckf->rot[3] = kf->rotation.w*rotScale;
+ ckf->deltaTime = kf->deltaTime*timeScale + 0.5f;
+ kf++;
+ ckf++;
+ }
+ keyFramesCompressed = newKfs;
+ }
+ REGISTER_MEMPTR(&keyFramesCompressed);
+
+ POP_MEMID();
+}
+
+void
+CAnimBlendSequence::RemoveUncompressedData(void)
+{
+ if(numFrames == 0)
+ return;
+ CompressKeyframes();
+ RwFree(keyFrames);
+ keyFrames = nil;
+}
+
+#ifdef USE_CUSTOM_ALLOCATOR
+bool
+CAnimBlendSequence::MoveMemory(void)
+{
+ if(keyFrames){
+ void *newaddr = gMainHeap.MoveMemory(keyFrames);
+ if(newaddr != keyFrames){
+ keyFrames = newaddr;
+ return true;
+ }
+ }else if(keyFramesCompressed){
+ void *newaddr = gMainHeap.MoveMemory(keyFramesCompressed);
+ if(newaddr != keyFramesCompressed){
+ keyFramesCompressed = newaddr;
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
diff --git a/src/animation/AnimBlendSequence.h b/src/animation/AnimBlendSequence.h
index 44ac8886..c6e70f22 100644
--- a/src/animation/AnimBlendSequence.h
+++ b/src/animation/AnimBlendSequence.h
@@ -2,6 +2,10 @@
#include "Quaternion.h"
+#ifdef MoveMemory
+#undef MoveMemory // windows shit
+#endif
+
// TODO: put them somewhere else?
struct KeyFrame {
CQuaternion rotation;
@@ -12,6 +16,15 @@ struct KeyFrameTrans : KeyFrame {
CVector translation;
};
+struct KeyFrameCompressed {
+ int16 rot[4]; // 4096
+ int16 deltaTime; // 60
+};
+
+struct KeyFrameTransCompressed : KeyFrameCompressed {
+ int16 trans[3]; // 128
+};
+
// The sequence of key frames of one animated node
class CAnimBlendSequence
@@ -41,10 +54,10 @@ public:
&((KeyFrame*)keyFrames)[n];
}
bool HasTranslation(void) { return !!(type & KF_TRANS); }
- // TODO? these are unused
-// void Uncompress(void);
-// void CompressKeyframes(void);
-// void RemoveUncompressedData(void);
+ void Uncompress(void);
+ void CompressKeyframes(void);
+ void RemoveUncompressedData(void);
+ bool MoveMemory(void);
#ifdef PED_SKIN
void SetBoneTag(int tag) { boneTag = tag; }
diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp
index 444b6d45..877dcd76 100644
--- a/src/animation/AnimManager.cpp
+++ b/src/animation/AnimManager.cpp
@@ -176,7 +176,7 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ 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_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE },
{ ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL },
{ ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp
index 3fc9334f..7340e73e 100644
--- a/src/audio/AudioLogic.cpp
+++ b/src/audio/AudioLogic.cpp
@@ -599,78 +599,78 @@ cAudioManager::ProcessVehicle(CVehicle *veh)
case VEHICLE_TYPE_CAR:
UpdateGasPedalAudio((CAutomobile *)veh);
if (params.m_nIndex == RCBANDIT) {
- ProcessModelCarEngine(&params);
- ProcessVehicleOneShots(&params);
+ ProcessModelCarEngine(params);
+ ProcessVehicleOneShots(params);
((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange;
break;
}
if (params.m_nIndex == DODO) {
- if (!ProcessVehicleRoadNoise(&params)) {
- ProcessVehicleOneShots(&params);
+ if (!ProcessVehicleRoadNoise(params)) {
+ ProcessVehicleOneShots(params);
((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange;
break;
}
if (CWeather::WetRoads > 0.f)
- ProcessWetRoadNoise(&params);
- ProcessVehicleSkidding(&params);
+ ProcessWetRoadNoise(params);
+ ProcessVehicleSkidding(params);
} else {
- if (!ProcessVehicleRoadNoise(&params)) {
- ProcessVehicleOneShots(&params);
+ if (!ProcessVehicleRoadNoise(params)) {
+ ProcessVehicleOneShots(params);
((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange;
break;
}
- ProcessReverseGear(&params);
+ ProcessReverseGear(params);
if (CWeather::WetRoads > 0.f)
- ProcessWetRoadNoise(&params);
- ProcessVehicleSkidding(&params);
- ProcessVehicleHorn(&params);
- ProcessVehicleSirenOrAlarm(&params);
+ ProcessWetRoadNoise(params);
+ ProcessVehicleSkidding(params);
+ ProcessVehicleHorn(params);
+ ProcessVehicleSirenOrAlarm(params);
if (UsesReverseWarning(params.m_nIndex))
- ProcessVehicleReverseWarning(&params);
+ ProcessVehicleReverseWarning(params);
if (HasAirBrakes(params.m_nIndex))
- ProcessAirBrakes(&params);
+ ProcessAirBrakes(params);
}
- ProcessCarBombTick(&params);
- ProcessVehicleEngine(&params);
- ProcessEngineDamage(&params);
- ProcessVehicleDoors(&params);
+ ProcessCarBombTick(params);
+ ProcessVehicleEngine(params);
+ ProcessEngineDamage(params);
+ ProcessVehicleDoors(params);
- ProcessVehicleOneShots(&params);
+ ProcessVehicleOneShots(params);
((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange;
break;
case VEHICLE_TYPE_BOAT:
- ProcessBoatEngine(&params);
- ProcessBoatMovingOverWater(&params);
- ProcessVehicleOneShots(&params);
+ ProcessBoatEngine(params);
+ ProcessBoatMovingOverWater(params);
+ ProcessVehicleOneShots(params);
break;
case VEHICLE_TYPE_TRAIN:
- ProcessTrainNoise(&params);
- ProcessVehicleOneShots(&params);
+ ProcessTrainNoise(params);
+ ProcessVehicleOneShots(params);
break;
case VEHICLE_TYPE_HELI:
- ProcessHelicopter(&params);
- ProcessVehicleOneShots(&params);
+ ProcessHelicopter(params);
+ ProcessVehicleOneShots(params);
break;
case VEHICLE_TYPE_PLANE:
- ProcessPlane(&params);
- ProcessVehicleOneShots(&params);
+ ProcessPlane(params);
+ ProcessVehicleOneShots(params);
break;
default:
break;
}
- ProcessRainOnVehicle(&params);
+ ProcessRainOnVehicle(params);
}
void
-cAudioManager::ProcessRainOnVehicle(cVehicleParams *params)
+cAudioManager::ProcessRainOnVehicle(cVehicleParams& params)
{
const int rainOnVehicleIntensity = 22;
- if (params->m_fDistance < SQR(rainOnVehicleIntensity) && CWeather::Rain > 0.01f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) {
- CVehicle *veh = params->m_pVehicle;
+ if (params.m_fDistance < SQR(rainOnVehicleIntensity) && CWeather::Rain > 0.01f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) {
+ CVehicle *veh = params.m_pVehicle;
++veh->m_bRainAudioCounter;
if (veh->m_bRainAudioCounter >= 2) {
veh->m_bRainAudioCounter = 0;
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
float emittingVol = 30.f * CWeather::Rain;
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, rainOnVehicleIntensity, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
@@ -698,7 +698,7 @@ cAudioManager::ProcessRainOnVehicle(cVehicleParams *params)
}
bool
-cAudioManager::ProcessReverseGear(cVehicleParams *params)
+cAudioManager::ProcessReverseGear(cVehicleParams& params)
{
const int reverseGearIntensity = 30;
@@ -707,14 +707,14 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params)
int32 emittingVol;
float modificator;
- if (params->m_fDistance >= SQR(reverseGearIntensity))
+ if (params.m_fDistance >= SQR(reverseGearIntensity))
return false;
- veh = params->m_pVehicle;
+ veh = params.m_pVehicle;
if (veh->bEngineOn && (veh->m_fGasPedal < 0.0f || veh->m_nCurrentGear == 0)) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- automobile = (CAutomobile *)params->m_pVehicle;
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ automobile = (CAutomobile *)params.m_pVehicle;
if (automobile->m_nWheelsOnGround != 0) {
- modificator = params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity;
+ modificator = params.m_fVelocityChange / params.m_pTransmission->fMaxReverseVelocity;
} else {
if (automobile->m_nDriveWheelsOnGround != 0)
automobile->m_fGasPedalAudio *= 0.4f;
@@ -724,7 +724,7 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params)
emittingVol = (24.f * modificator);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, reverseGearIntensity, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
- if (params->m_pVehicle->m_fGasPedal >= 0.0f) {
+ if (params.m_pVehicle->m_fGasPedal >= 0.0f) {
m_sQueueSample.m_nCounter = 62;
m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR_2;
} else {
@@ -752,7 +752,7 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params)
}
void
-cAudioManager::ProcessModelCarEngine(cVehicleParams *params)
+cAudioManager::ProcessModelCarEngine(cVehicleParams& params)
{
const float SOUND_INTENSITY = 30.0f;
CAutomobile *automobile;
@@ -760,24 +760,24 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params)
int32 emittingVol;
float velocityChange;
- if (params->m_fDistance < SQR(SOUND_INTENSITY)) {
- automobile = (CAutomobile *)params->m_pVehicle;
+ if (params.m_fDistance < SQR(SOUND_INTENSITY)) {
+ automobile = (CAutomobile *)params.m_pVehicle;
if (automobile->bEngineOn) {
if (automobile->m_nWheelsOnGround == 0) {
if (automobile->m_nDriveWheelsOnGround != 0)
automobile->m_fGasPedalAudio *= 0.4f;
- velocityChange = automobile->m_fGasPedalAudio * params->m_pTransmission->fMaxVelocity;
+ velocityChange = automobile->m_fGasPedalAudio * params.m_pTransmission->fMaxVelocity;
} else {
- velocityChange = Abs(params->m_fVelocityChange);
+ velocityChange = Abs(params.m_fVelocityChange);
}
if (velocityChange > 0.001f) {
- allowedVelocity = 0.5f * params->m_pTransmission->fMaxVelocity;
+ allowedVelocity = 0.5f * params.m_pTransmission->fMaxVelocity;
if (velocityChange < allowedVelocity)
emittingVol = (90.f * velocityChange / allowedVelocity);
else
emittingVol = 90;
if (emittingVol) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 30.f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 2;
@@ -785,7 +785,7 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params)
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 1;
- m_sQueueSample.m_nFrequency = (11025.f * velocityChange / params->m_pTransmission->fMaxVelocity + 11025.f);
+ m_sQueueSample.m_nFrequency = (11025.f * velocityChange / params.m_pTransmission->fMaxVelocity + 11025.f);
m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_nEmittingVolume = emittingVol;
m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
@@ -807,7 +807,7 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params)
bool
-cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params)
+cAudioManager::ProcessVehicleRoadNoise(cVehicleParams& params)
{
const float SOUND_INTENSITY = 95.0f;
@@ -817,21 +817,21 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params)
int sampleFreq;
float velocity;
- if (params->m_fDistance >= SQR(SOUND_INTENSITY))
+ if (params.m_fDistance >= SQR(SOUND_INTENSITY))
return false;
- if (params->m_pTransmission != nil) {
- if (((CAutomobile*)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) {
- velocity = Abs(params->m_fVelocityChange);
+ if (params.m_pTransmission != nil) {
+ if (((CAutomobile*)params.m_pVehicle)->m_nDriveWheelsOnGround != 0) {
+ velocity = Abs(params.m_fVelocityChange);
if (velocity > 0.0f) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- emittingVol = 30.f * Min(1.f, velocity / (0.5f * params->m_pTransmission->fMaxVelocity));
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ emittingVol = 30.f * Min(1.f, velocity / (0.5f * params.m_pTransmission->fMaxVelocity));
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 0;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 3;
- if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) {
+ if (params.m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) {
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
freq = 6050 * emittingVol / 30 + 16000;
} else {
@@ -860,7 +860,7 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params)
}
bool
-cAudioManager::ProcessWetRoadNoise(cVehicleParams *params)
+cAudioManager::ProcessWetRoadNoise(cVehicleParams& params)
{
const float SOUND_INTENSITY = 30.0f;
@@ -870,14 +870,14 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params)
int freq;
float velChange;
- if (params->m_fDistance >= SQR(SOUND_INTENSITY))
+ if (params.m_fDistance >= SQR(SOUND_INTENSITY))
return false;
- if (params->m_pTransmission != nil) {
- if (((CAutomobile *)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) {
- velChange = Abs(params->m_fVelocityChange);
+ if (params.m_pTransmission != nil) {
+ if (((CAutomobile *)params.m_pVehicle)->m_nDriveWheelsOnGround != 0) {
+ velChange = Abs(params.m_fVelocityChange);
if (velChange > 0.f) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- relativeVelocity = Min(1.0f, velChange / (0.5f * params->m_pTransmission->fMaxVelocity));
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ relativeVelocity = Min(1.0f, velChange / (0.5f * params.m_pTransmission->fMaxVelocity));
emittingVol = 23.0f * relativeVelocity * CWeather::WetRoads;
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
@@ -912,7 +912,7 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params)
}
void
-cAudioManager::ProcessVehicleEngine(cVehicleParams *params)
+cAudioManager::ProcessVehicleEngine(cVehicleParams& params)
{
const float SOUND_INTENSITY = 50.0f;
@@ -929,17 +929,17 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params)
float modificator;
float traction = 0.f;
- if (params->m_fDistance < SQR(SOUND_INTENSITY)) {
+ if (params.m_fDistance < SQR(SOUND_INTENSITY)) {
playerVeh = FindPlayerVehicle();
- veh = params->m_pVehicle;
+ veh = params.m_pVehicle;
if (playerVeh == veh && veh->GetStatus() == STATUS_WRECKED) {
SampleManager.StopChannel(m_nActiveSamples);
return;
}
if (veh->bEngineOn) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- automobile = (CAutomobile *)params->m_pVehicle;
- if (params->m_nIndex == DODO) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ automobile = (CAutomobile *)params.m_pVehicle;
+ if (params.m_nIndex == DODO) {
ProcessCesna(params);
return;
}
@@ -947,14 +947,14 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params)
ProcessPlayersVehicleEngine(params, automobile);
return;
}
- transmission = params->m_pTransmission;
+ transmission = params.m_pTransmission;
if (transmission != nil) {
- currentGear = params->m_pVehicle->m_nCurrentGear;
+ currentGear = params.m_pVehicle->m_nCurrentGear;
if (automobile->m_nWheelsOnGround != 0) {
if (automobile->bIsHandbrakeOn) {
- if (params->m_fVelocityChange == 0.0f)
+ if (params.m_fVelocityChange == 0.0f)
traction = 0.9f;
- } else if (params->m_pVehicle->GetStatus() == STATUS_SIMPLE) {
+ } else if (params.m_pVehicle->GetStatus() == STATUS_SIMPLE) {
traction = 0.0f;
} else {
switch (transmission->nDriveType) {
@@ -982,15 +982,15 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params)
relativeChange = 0.f;
} else if (currentGear != 0) {
relativeGearChange =
- Min(1.0f, (params->m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f);
+ Min(1.0f, (params.m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f);
if (traction == 0.0f && automobile->GetStatus() != STATUS_SIMPLE &&
- params->m_fVelocityChange < transmission->Gears[1].fShiftUpVelocity) {
+ params.m_fVelocityChange < transmission->Gears[1].fShiftUpVelocity) {
traction = 0.7f;
}
relativeChange = traction * automobile->m_fGasPedalAudio * 0.95f + (1.0f - traction) * relativeGearChange;
} else
relativeChange =
- Min(1.0f, 1.0f - Abs((params->m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity));
+ Min(1.0f, 1.0f - Abs((params.m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity));
} else {
if (automobile->m_nDriveWheelsOnGround != 0)
automobile->m_fGasPedalAudio *= 0.4f;
@@ -1017,20 +1017,20 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params)
if (m_sQueueSample.m_nVolume != 0) {
if (automobile->GetStatus() == STATUS_SIMPLE) {
if (modificator < 0.02f) {
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1;
freq = modificator * 10000 + 22050;
m_sQueueSample.m_nCounter = 52;
} else {
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nAccelerationSampleIndex;
m_sQueueSample.m_nCounter = 2;
}
} else {
if (automobile->m_fGasPedal < 0.05f) {
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1;
freq = modificator * 10000 + 22050;
m_sQueueSample.m_nCounter = 52;
} else {
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nAccelerationSampleIndex;
m_sQueueSample.m_nCounter = 2;
}
}
@@ -1115,14 +1115,14 @@ cAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sampl
}
void
-cAudioManager::ProcessCesna(cVehicleParams *params)
+cAudioManager::ProcessCesna(cVehicleParams& params)
{
static uint8 nAccel = 0;
- //((CAutomobile *)params->m_pVehicle)->Damage.GetEngineStatus();
+ //((CAutomobile *)params.m_pVehicle)->Damage.GetEngineStatus();
- if (FindPlayerVehicle() == params->m_pVehicle) {
- if (params->m_nIndex == DODO) {
+ if (FindPlayerVehicle() == params.m_pVehicle) {
+ if (params.m_nIndex == DODO) {
if (Pads[0].GetAccelerate() <= 0) {
if (nAccel != 0)
--nAccel;
@@ -1132,10 +1132,10 @@ cAudioManager::ProcessCesna(cVehicleParams *params)
AddPlayerCarSample(85 * (60 - nAccel) / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_IDLE, SFX_BANK_0, 52, true);
AddPlayerCarSample(85 * nAccel / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_REV, SFX_BANK_0, 2, true);
}
- } else if (params->m_nIndex == DODO) {
+ } else if (params.m_nIndex == DODO) {
AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, SFX_BANK_0, 52, true);
- } else if (params->m_fDistance < SQR(200)) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ } else if (params.m_fDistance < SQR(200)) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 52;
@@ -1156,7 +1156,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params)
m_sQueueSample.m_bRequireReflection = false;
AddSampleToRequestedQueue();
}
- if (params->m_fDistance < SQR(90)) {
+ if (params.m_fDistance < SQR(90)) {
m_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 2;
@@ -1182,7 +1182,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params)
}
void
-cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile)
+cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile)
{
static int32 GearFreqAdj[] = {6000, 6000, 3400, 1200, 0, -1000};
@@ -1234,13 +1234,13 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
accelerateState = Pads[0].GetAccelerate();
channelUsed = SampleManager.GetChannelUsedFlag(m_nActiveSamples);
- transmission = params->m_pTransmission;
- velocityChange = params->m_fVelocityChange;
+ transmission = params.m_pTransmission;
+ velocityChange = params.m_fVelocityChange;
relativeVelocityChange = 2.0f * velocityChange / transmission->fMaxVelocity;
accelerationMultipler = clamp(relativeVelocityChange, 0.0f, 1.0f);
gasPedalAudio = accelerationMultipler;
- currentGear = params->m_pVehicle->m_nCurrentGear;
+ currentGear = params.m_pVehicle->m_nCurrentGear;
switch (transmission->nDriveType)
{
@@ -1265,20 +1265,20 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
}
if (velocityChange != 0.0f) {
- time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange;
+ time = params.m_pVehicle->m_vecMoveSpeed.z / velocityChange;
if (time > 0.0f)
freqModifier = -(Min(0.2f, time) * 3000.0f * 5.0f);
else
freqModifier = -(Max(-0.2f, time) * 3000.0f * 5.0f);
- if (params->m_fVelocityChange < -0.001f)
+ if (params.m_fVelocityChange < -0.001f)
freqModifier = -freqModifier;
} else
freqModifier = 0;
- engineSoundType = aVehicleSettings[params->m_nIndex].m_nBank;
+ engineSoundType = aVehicleSettings[params.m_nIndex].m_nBank;
soundOffset = 3 * (engineSoundType - CAR_SFX_BANKS_OFFSET);
if (accelerateState <= 0) {
- if (params->m_fVelocityChange < -0.001f) {
+ if (params.m_fVelocityChange < -0.001f) {
if (channelUsed) {
SampleManager.StopChannel(m_nActiveSamples);
bAccelSampleStopped = true;
@@ -1286,7 +1286,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction)
gasPedalAudio = automobile->m_fGasPedalAudio;
else
- gasPedalAudio = Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity);
+ gasPedalAudio = Min(1.0f, params.m_fVelocityChange / params.m_pTransmission->fMaxReverseVelocity);
gasPedalAudio = Max(0.0f, gasPedalAudio);
automobile->m_fGasPedalAudio = gasPedalAudio;
@@ -1297,7 +1297,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
}
nCruising = 0;
if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction ||
- params->m_fVelocityChange < 0.01f && automobile->m_fGasPedalAudio > 0.2f) {
+ params.m_fVelocityChange < 0.01f && automobile->m_fGasPedalAudio > 0.2f) {
automobile->m_fGasPedalAudio *= 0.6f;
gasPedalAudio = automobile->m_fGasPedalAudio;
}
@@ -1355,7 +1355,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
if (!channelUsed) {
if (!processedAccelSampleStopped) {
- if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1)
+ if (CurrentPretendGear < params.m_pTransmission->nNumberOfGears - 1)
++CurrentPretendGear;
else {
nCruising = 1;
@@ -1386,10 +1386,10 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
if (nCruising != 0) {
bAccelSampleStopped = true;
if (accelerateState < 150 || automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction ||
- currentGear < params->m_pTransmission->nNumberOfGears - 1) {
+ currentGear < params.m_pTransmission->nNumberOfGears - 1) {
nCruising = 0;
} else {
- if (accelerateState >= 220 && params->m_fVelocityChange + 0.001f < automobile->m_fVelocityChangeForAudio) {
+ if (accelerateState >= 220 && params.m_fVelocityChange + 0.001f < automobile->m_fVelocityChangeForAudio) {
if (nCruising < 800)
++nCruising;
} else if (nCruising > 3) {
@@ -1409,7 +1409,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *
}
bool
-cAudioManager::ProcessVehicleSkidding(cVehicleParams *params)
+cAudioManager::ProcessVehicleSkidding(cVehicleParams& params)
{
const float SOUND_INTENSITY = 40.0f;
@@ -1419,31 +1419,31 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params)
float newSkidVal = 0.0f;
float skidVal = 0.0f;
- if (params->m_fDistance >= SQR(SOUND_INTENSITY))
+ if (params.m_fDistance >= SQR(SOUND_INTENSITY))
return false;
- automobile = (CAutomobile *)params->m_pVehicle;
+ automobile = (CAutomobile *)params.m_pVehicle;
if (automobile->m_nWheelsOnGround == 0)
return true;
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) {
if (automobile->m_aWheelState[i] == WHEEL_STATE_NORMAL || automobile->Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING)
continue;
- transmission = params->m_pTransmission;
+ transmission = params.m_pTransmission;
switch (transmission->nDriveType) {
case '4':
- newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange);
+ newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange);
break;
case 'F':
if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
- newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange);
+ newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange);
else
- newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange);
+ newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange);
break;
case 'R':
if (i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT)
- newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange);
+ newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange);
else
- newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange);
+ newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange);
break;
default:
break;
@@ -1456,7 +1456,7 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params)
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 3;
- switch (params->m_pVehicle->m_nSurfaceTouched) {
+ switch (params.m_pVehicle->m_nSurfaceTouched) {
case SURFACE_GRASS:
case SURFACE_HEDGE:
m_sQueueSample.m_nSampleIndex = SFX_RAIN;
@@ -1547,17 +1547,17 @@ cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automo
}
void
-cAudioManager::ProcessVehicleHorn(cVehicleParams *params)
+cAudioManager::ProcessVehicleHorn(cVehicleParams& params)
{
const float SOUND_INTENSITY = 40.0f;
CAutomobile *automobile;
- if (params->m_fDistance < SQR(SOUND_INTENSITY)) {
- automobile = (CAutomobile *)params->m_pVehicle;
- if ((!automobile->m_bSirenOrAlarm || !UsesSirenSwitching(params->m_nIndex)) && automobile->GetModelIndex() != MI_MRWHOOP) {
+ if (params.m_fDistance < SQR(SOUND_INTENSITY)) {
+ automobile = (CAutomobile *)params.m_pVehicle;
+ if ((!automobile->m_bSirenOrAlarm || !UsesSirenSwitching(params.m_nIndex)) && automobile->GetModelIndex() != MI_MRWHOOP) {
if (automobile->m_nCarHornTimer) {
- if (params->m_pVehicle->GetStatus() != STATUS_PLAYER) {
+ if (params.m_pVehicle->GetStatus() != STATUS_PLAYER) {
automobile->m_nCarHornTimer = Min(44, automobile->m_nCarHornTimer);
if (automobile->m_nCarHornTimer == 44)
automobile->m_nCarHornPattern = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7;
@@ -1565,15 +1565,15 @@ cAudioManager::ProcessVehicleHorn(cVehicleParams *params)
return;
}
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 4;
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nHornSample;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nHornSample;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 2;
- m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nHornFrequency;
+ m_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nHornFrequency;
m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_nEmittingVolume = 80;
m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
@@ -1622,36 +1622,36 @@ cAudioManager::UsesSirenSwitching(int32 model) const
}
bool
-cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params)
+cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams& params)
{
const float SOUND_INTENSITY = 110.0f;
- if (params->m_fDistance < SQR(SOUND_INTENSITY)) {
- CVehicle *veh = params->m_pVehicle;
+ if (params.m_fDistance < SQR(SOUND_INTENSITY)) {
+ CVehicle *veh = params.m_pVehicle;
if (veh->m_bSirenOrAlarm == false && !veh->IsAlarmOn())
return true;
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 5;
- if (UsesSiren(params->m_nIndex)) {
- if (params->m_pVehicle->GetStatus() == STATUS_ABANDONED)
+ if (UsesSiren(params.m_nIndex)) {
+ if (params.m_pVehicle->GetStatus() == STATUS_ABANDONED)
return true;
- if (veh->m_nCarHornTimer && params->m_nIndex != FIRETRUK) {
+ if (veh->m_nCarHornTimer && params.m_nIndex != FIRETRUK) {
m_sQueueSample.m_nSampleIndex = SFX_SIREN_FAST;
- if (params->m_nIndex == FBICAR)
+ if (params.m_nIndex == FBICAR)
m_sQueueSample.m_nFrequency = 16113;
else
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SIREN_FAST);
m_sQueueSample.m_nCounter = 60;
} else {
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample;
- m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmSample;
+ m_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmFrequency;
}
} else {
- m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample;
- m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency;
+ m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmSample;
+ m_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmFrequency;
}
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = false;
@@ -1681,17 +1681,17 @@ cAudioManager::UsesReverseWarning(int32 model) const
}
bool
-cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params)
+cAudioManager::ProcessVehicleReverseWarning(cVehicleParams& params)
{
const float SOUND_INTENSITY = 50.0f;
- CVehicle *veh = params->m_pVehicle;
+ CVehicle *veh = params.m_pVehicle;
- if (params->m_fDistance >= SQR(SOUND_INTENSITY))
+ if (params.m_fDistance >= SQR(SOUND_INTENSITY))
return false;
if (veh->bEngineOn && veh->m_fGasPedal < 0.0f) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 12;
@@ -1717,7 +1717,7 @@ cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params)
}
bool
-cAudioManager::ProcessVehicleDoors(cVehicleParams *params)
+cAudioManager::ProcessVehicleDoors(cVehicleParams& params)
{
const float SOUND_INTENSITY = 40.0f;
@@ -1726,11 +1726,11 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params)
int32 emittingVol;
float velocity;
- if (params->m_fDistance >= SQR(SOUND_INTENSITY))
+ if (params.m_fDistance >= SQR(SOUND_INTENSITY))
return false;
- automobile = (CAutomobile *)params->m_pVehicle;
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ automobile = (CAutomobile *)params.m_pVehicle;
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
for (int32 i = 0; i < ARRAY_SIZE(automobile->Doors); i++) {
if (automobile->Damage.GetDoorStatus(i) == DOOR_STATUS_SWINGING) {
doorState = automobile->Doors[i].m_nDoorState;
@@ -1765,22 +1765,22 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params)
}
bool
-cAudioManager::ProcessAirBrakes(cVehicleParams *params)
+cAudioManager::ProcessAirBrakes(cVehicleParams& params)
{
CAutomobile *automobile;
uint8 rand;
- if (params->m_fDistance > SQR(30))
+ if (params.m_fDistance > SQR(30))
return false;
- automobile = (CAutomobile *)params->m_pVehicle;
+ automobile = (CAutomobile *)params.m_pVehicle;
if (!automobile->bEngineOn)
return true;
- if ((automobile->m_fVelocityChangeForAudio < 0.025f || params->m_fVelocityChange >= 0.025f) &&
- (automobile->m_fVelocityChangeForAudio > -0.025f || params->m_fVelocityChange <= 0.025f))
+ if ((automobile->m_fVelocityChangeForAudio < 0.025f || params.m_fVelocityChange >= 0.025f) &&
+ (automobile->m_fVelocityChangeForAudio > -0.025f || params.m_fVelocityChange <= 0.025f))
return true;
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
rand = m_anRandomTable[0] % 10 + 70;
m_sQueueSample.m_nVolume = ComputeVolume(rand, 30.0f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
@@ -1813,7 +1813,7 @@ cAudioManager::HasAirBrakes(int32 model) const
}
bool
-cAudioManager::ProcessEngineDamage(cVehicleParams *params)
+cAudioManager::ProcessEngineDamage(cVehicleParams& params)
{
const int engineDamageIntensity = 40;
@@ -1821,9 +1821,9 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params)
uint8 engineStatus;
uint8 emittingVolume;
- if (params->m_fDistance >= SQR(engineDamageIntensity))
+ if (params.m_fDistance >= SQR(engineDamageIntensity))
return false;
- veh = (CAutomobile *)params->m_pVehicle;
+ veh = (CAutomobile *)params.m_pVehicle;
if (veh->bEngineOn) {
engineStatus = veh->Damage.GetEngineStatus();
if (engineStatus > 250 || engineStatus < 100)
@@ -1839,7 +1839,7 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params)
m_sQueueSample.m_nReleasingVolumeModificator = 7;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE);
}
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, engineDamageIntensity, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 28;
@@ -1862,15 +1862,15 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params)
}
bool
-cAudioManager::ProcessCarBombTick(cVehicleParams *params)
+cAudioManager::ProcessCarBombTick(cVehicleParams& params)
{
CAutomobile *automobile;
- if (params->m_fDistance >= SQR(40.f))
+ if (params.m_fDistance >= SQR(40.f))
return false;
- automobile = (CAutomobile *)params->m_pVehicle;
+ automobile = (CAutomobile *)params.m_pVehicle;
if (automobile->bEngineOn && automobile->m_bombType == CARBOMB_TIMEDACTIVE) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(60, 40.f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 35;
@@ -1896,7 +1896,7 @@ cAudioManager::ProcessCarBombTick(cVehicleParams *params)
}
void
-cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
+cAudioManager::ProcessVehicleOneShots(cVehicleParams& params)
{
int16 event;
uint8 emittingVol;
@@ -1925,12 +1925,11 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
const float SOUND_INTENSITY = 50.0f;
maxDist = SQR(SOUND_INTENSITY);
emittingVol = m_anRandomTable[2] % 5 + 122;
- switch (aVehicleSettings[params->m_nIndex].m_bDoorType) {
+ switch (aVehicleSettings[params.m_nIndex].m_bDoorType) {
case OLD_DOOR:
m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE;
break;
case NEW_DOOR:
- default:
m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE;
break;
case TRUCK_DOOR:
@@ -1939,9 +1938,16 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
case BUS_DOOR:
m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES;
break;
+ default:
+ m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE;
+ break;
}
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
+#ifdef THIS_IS_STUPID
m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22;
+#else
+ m_sQueueSample.m_nCounter = event + 22;
+#endif
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -1959,7 +1965,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
const float SOUND_INTENSITY = 50.0f;
maxDist = SQR(SOUND_INTENSITY);
emittingVol = m_anRandomTable[1] % 10 + 117;
- switch (aVehicleSettings[params->m_nIndex].m_bDoorType) {
+ switch (aVehicleSettings[params.m_nIndex].m_bDoorType) {
case OLD_DOOR:
m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_OPEN;
break;
@@ -1975,7 +1981,11 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
break;
}
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
+#ifdef THIS_IS_STUPID
m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10;
+#else
+ m_sQueueSample.m_nCounter = event + 10;
+#endif
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -2007,7 +2017,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
iWheelIndex = 82;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BUMP);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
- if (params->m_nIndex == RCBANDIT) {
+ if (params.m_nIndex == RCBANDIT) {
m_sQueueSample.m_nFrequency *= 2;
emittingVol /= 2;
}
@@ -2236,17 +2246,17 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
pedParams.m_pPed = nil;
pedParams.m_bDistanceCalculated = false;
pedParams.m_fDistance = 0.0f;
- pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated;
- pedParams.m_fDistance = params->m_fDistance;
- SetupPedComments(&pedParams, SOUND_PED_HELI_PLAYER_FOUND);
+ pedParams.m_bDistanceCalculated = params.m_bDistanceCalculated;
+ pedParams.m_fDistance = params.m_fDistance;
+ SetupPedComments(pedParams, SOUND_PED_HELI_PLAYER_FOUND);
continue;
case SOUND_PED_BODYCAST_HIT:
pedParams.m_pPed = nil;
pedParams.m_bDistanceCalculated = false;
pedParams.m_fDistance = 0.0f;
- pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated;
- pedParams.m_fDistance = params->m_fDistance;
- SetupPedComments(&pedParams, SOUND_PED_BODYCAST_HIT);
+ pedParams.m_bDistanceCalculated = params.m_bDistanceCalculated;
+ pedParams.m_fDistance = params.m_fDistance;
+ SetupPedComments(pedParams, SOUND_PED_BODYCAST_HIT);
continue;
case SOUND_WATER_FALL: {
const float SOUND_INTENSITY = 40.0f;
@@ -2298,8 +2308,8 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
default:
continue;
}
- if (params->m_fDistance < maxDist) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ if (params.m_fDistance < maxDist) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
if (noReflections) {
@@ -2321,7 +2331,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params)
}
bool
-cAudioManager::ProcessTrainNoise(cVehicleParams *params)
+cAudioManager::ProcessTrainNoise(cVehicleParams& params)
{
const float SOUND_INTENSITY = 300.0f;
@@ -2329,12 +2339,12 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params)
uint8 emittingVol;
float speedMultipler;
- if (params->m_fDistance >= SQR(SOUND_INTENSITY))
+ if (params.m_fDistance >= SQR(SOUND_INTENSITY))
return false;
- if (params->m_fVelocityChange > 0.0f) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- train = (CTrain *)params->m_pVehicle;
+ if (params.m_fVelocityChange > 0.0f) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ train = (CTrain *)params.m_pVehicle;
speedMultipler = Min(1.0f, train->m_fSpeed * 250.f / 51.f);
emittingVol = (75.f * speedMultipler);
if (train->m_fWagonPosition == 0.0f) {
@@ -2360,7 +2370,7 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params)
}
}
const float SOUND_INTENSITY = 70.0f;
- if (params->m_fDistance < SQR(SOUND_INTENSITY)) {
+ if (params.m_fDistance < SQR(SOUND_INTENSITY)) {
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 33;
@@ -2387,7 +2397,7 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params)
}
bool
-cAudioManager::ProcessBoatEngine(cVehicleParams *params)
+cAudioManager::ProcessBoatEngine(cVehicleParams& params)
{
CBoat *boat;
float padRelativeAccerate;
@@ -2401,10 +2411,10 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params)
static const int intensity = 50;
- if (params->m_fDistance < SQR(intensity)) {
- boat = (CBoat *)params->m_pVehicle;
- if (params->m_nIndex == REEFER) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ if (params.m_fDistance < SQR(intensity)) {
+ boat = (CBoat *)params.m_pVehicle;
+ if (params.m_nIndex == REEFER) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(80, 50.f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
m_sQueueSample.m_nCounter = 39;
@@ -2426,7 +2436,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params)
m_sQueueSample.m_bRequireReflection = false;
AddSampleToRequestedQueue();
}
- if (FindPlayerVehicle() == params->m_pVehicle) {
+ if (FindPlayerVehicle() == params.m_pVehicle) {
padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake());
padRelativeAccerate = padAccelerate / 255;
emittingVol = (100.f * padRelativeAccerate) + 15;
@@ -2465,7 +2475,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params)
m_sQueueSample.m_bReverbFlag = true;
m_sQueueSample.m_bRequireReflection = false;
} else {
- if (FindPlayerVehicle() == params->m_pVehicle) {
+ if (FindPlayerVehicle() == params.m_pVehicle) {
padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake());
if (padAccelerate <= 20) {
emittingVol = 45 - 45 * padAccelerate / 40;
@@ -2502,7 +2512,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params)
m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL;
}
}
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 50.f, m_sQueueSample.m_fDistance);
if (!m_sQueueSample.m_nVolume)
return true;
@@ -2528,22 +2538,22 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params)
}
bool
-cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params)
+cAudioManager::ProcessBoatMovingOverWater(cVehicleParams& params)
{
float velocityChange;
int32 vol;
float multiplier;
- if (params->m_fDistance > SQR(50))
+ if (params.m_fDistance > SQR(50))
return false;
- velocityChange = Abs(params->m_fVelocityChange);
- if (velocityChange <= 0.0005f && ((CBoat*)params->m_pVehicle)->bBoatInWater)
+ velocityChange = Abs(params.m_fVelocityChange);
+ if (velocityChange <= 0.0005f && ((CBoat*)params.m_pVehicle)->bBoatInWater)
return true;
velocityChange = Min(0.75f, velocityChange);
multiplier = (velocityChange - 0.0005f) / (1499.0f / 2000.0f);
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
vol = (30.f * multiplier);
m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
@@ -2576,7 +2586,7 @@ struct tHelicopterSampleData {
};
bool
-cAudioManager::ProcessHelicopter(cVehicleParams *params)
+cAudioManager::ProcessHelicopter(cVehicleParams& params)
{
CHeli *heli;
float MaxDist;
@@ -2585,11 +2595,11 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params)
int32 emittingVol;
static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, MAX_VOLUME}, {60.f, 30.f, MAX_VOLUME}};
- if (SQR(gHeliSfxRanges[0].m_fMaxDistance) <= params->m_fDistance)
+ if (SQR(gHeliSfxRanges[0].m_fMaxDistance) <= params.m_fDistance)
return false;
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- heli = (CHeli *)params->m_pVehicle;
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ heli = (CHeli *)params.m_pVehicle;
for (uint32 i = 0; i < ARRAY_SIZE(gHeliSfxRanges); i++) {
MaxDist = gHeliSfxRanges[i].m_fMaxDistance;
dist = m_sQueueSample.m_fDistance;
@@ -2626,9 +2636,9 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params)
}
void
-cAudioManager::ProcessPlane(cVehicleParams *params)
+cAudioManager::ProcessPlane(cVehicleParams& params)
{
- switch (params->m_nIndex) {
+ switch (params.m_nIndex) {
case AIRTRAIN:
ProcessJumbo(params);
break;
@@ -2636,7 +2646,7 @@ cAudioManager::ProcessPlane(cVehicleParams *params)
ProcessCesna(params);
break;
default:
- debug("Plane Model Id is %d\n, ", params->m_pVehicle->GetModelIndex());
+ debug("Plane Model Id is %d\n, ", params.m_pVehicle->GetModelIndex());
break;
}
}
@@ -2652,14 +2662,14 @@ DoJumboVolOffset()
}
void
-cAudioManager::ProcessJumbo(cVehicleParams *params)
+cAudioManager::ProcessJumbo(cVehicleParams& params)
{
CPlane *plane;
float position;
- if (params->m_fDistance < SQR(440)) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
- plane = (CPlane *)params->m_pVehicle;
+ if (params.m_fDistance < SQR(440)) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
+ plane = (CPlane *)params.m_pVehicle;
DoJumboVolOffset();
position = PlanePathPosition[plane->m_nPlaneId];
if (position <= TakeOffPoint) {
@@ -2955,21 +2965,21 @@ cAudioManager::ProcessPed(CPhysical *ped)
params.m_pPed = (CPed *)ped;
params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);
if (ped->GetModelIndex() == MI_FATMALE02)
- ProcessPedHeadphones(&params);
- ProcessPedOneShots(&params);
+ ProcessPedHeadphones(params);
+ ProcessPedOneShots(params);
}
void
-cAudioManager::ProcessPedHeadphones(cPedParams *params)
+cAudioManager::ProcessPedHeadphones(cPedParams &params)
{
CPed *ped;
CAutomobile *veh;
uint8 emittingVol;
- if (params->m_fDistance < SQR(7)) {
- ped = params->m_pPed;
+ if (params.m_fDistance < SQR(7)) {
+ ped = params.m_pPed;
if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
if (ped->bInVehicle && ped->m_nPedState == PED_DRIVING) {
emittingVol = 10;
veh = (CAutomobile *)ped->m_pMyVehicle;
@@ -3011,36 +3021,36 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params)
}
void
-cAudioManager::ProcessPedOneShots(cPedParams *params)
+cAudioManager::ProcessPedOneShots(cPedParams &params)
{
uint8 emittingVol;
int32 sampleIndex;
- CPed *ped = params->m_pPed;
+ CPed *ped = params.m_pPed;
- bool stereo;
+ bool narrowSoundRange;
int16 sound;
- bool noReflection;
+ bool stereo;
CWeapon *weapon;
float maxDist = 0.f; // uninitialized variable
static uint8 iSound = 21;
- weapon = params->m_pPed->GetWeapon();
+ weapon = params.m_pPed->GetWeapon();
for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) {
- noReflection = false;
stereo = false;
+ narrowSoundRange = false;
m_sQueueSample.m_bRequireReflection = false;
sound = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];
switch (sound) {
case SOUND_STEP_START:
case SOUND_STEP_END:
- if (!params->m_pPed->bIsLooking) {
+ if (!params.m_pPed->bIsLooking) {
emittingVol = m_anRandomTable[3] % 15 + 45;
if (FindPlayerPed() != m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)
emittingVol /= 2;
maxDist = 400.f;
- switch (params->m_pPed->m_nSurfaceTouched) {
+ switch (params.m_pPed->m_nSurfaceTouched) {
case SURFACE_GRASS:
sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1;
break;
@@ -3084,7 +3094,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - 28;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
- switch (params->m_pPed->m_nMoveState) {
+ switch (params.m_pPed->m_nMoveState) {
case PEDMOVE_WALK:
emittingVol /= 4;
m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10;
@@ -3142,229 +3152,54 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
case SOUND_FIGHT_PUNCH_33:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;
m_sQueueSample.m_nFrequency = 18000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_KICK_34:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;
m_sQueueSample.m_nFrequency = 16500;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_HEADBUTT_35:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;
m_sQueueSample.m_nFrequency = 20000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_PUNCH_36:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2;
m_sQueueSample.m_nFrequency = 18000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_PUNCH_37:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2;
m_sQueueSample.m_nFrequency = 16500;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_CLOSE_PUNCH_38:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2;
m_sQueueSample.m_nFrequency = 20000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_PUNCH_39:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4;
m_sQueueSample.m_nFrequency = 18000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4;
m_sQueueSample.m_nFrequency = 16500;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_PUNCH_41:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4;
m_sQueueSample.m_nFrequency = 20000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_PUNCH_FROM_BEHIND_42:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;
m_sQueueSample.m_nFrequency = 18000;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_KNEE_OR_KICK_43:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;
m_sQueueSample.m_nFrequency = 16500;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = iSound;
- stereo = true;
- ++iSound;
- m_sQueueSample.m_nReleasingVolumeModificator = 3;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- maxDist = SQR(30);
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- emittingVol = m_anRandomTable[3] % 26 + 100;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
- break;
+ goto AddFightSound;
case SOUND_FIGHT_KICK_44:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;
m_sQueueSample.m_nFrequency = 20000;
+ AddFightSound:
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound;
- stereo = true;
+ narrowSoundRange = true;
++iSound;
m_sQueueSample.m_nReleasingVolumeModificator = 3;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
@@ -3383,7 +3218,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_BAT_HIT_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 22000;
m_sQueueSample.m_nReleasingVolumeModificator = 3;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
@@ -3399,7 +3234,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
case SOUND_WEAPON_SHOT_FIRED:
weapon = ped->GetWeapon();
@@ -3408,7 +3243,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_COLT45_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COLT45_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3425,13 +3260,13 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
case WEAPONTYPE_UZI:
m_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3450,7 +3285,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_SHOTGUN_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOTGUN_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3467,13 +3302,13 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
case WEAPONTYPE_AK47:
m_sQueueSample.m_nSampleIndex = SFX_AK47_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3492,7 +3327,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_M16_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3511,7 +3346,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_SNIPER_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SNIPER_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3528,13 +3363,13 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
case WEAPONTYPE_ROCKETLAUNCHER:
m_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);
m_sQueueSample.m_nReleasingVolumeModificator = 1;
@@ -3551,7 +3386,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
case WEAPONTYPE_FLAMETHROWER:
m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_LEFT;
@@ -3573,7 +3408,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
default:
continue;
@@ -3616,7 +3451,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
}
emittingVol = 75;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency += RandomDisplacement(300);
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nReleasingVolumeModificator = 5;
@@ -3637,7 +3472,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_UZI_END_LEFT;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_END_LEFT);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
m_sQueueSample.m_nReleasingVolumeModificator = 3;
@@ -3654,7 +3489,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
if (m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bRequireReflection = true;
else
- noReflection = true;
+ stereo = true;
break;
case SOUND_WEAPON_FLAMETHROWER_FIRE:
m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_START_LEFT;
@@ -3678,7 +3513,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_BULLET_PED;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BULLET_PED);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8);
m_sQueueSample.m_nReleasingVolumeModificator = 7;
@@ -3697,7 +3532,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
m_sQueueSample.m_nSampleIndex = SFX_SPLASH_1;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = iSound++;
- stereo = true;
+ narrowSoundRange = true;
m_sQueueSample.m_nFrequency = RandomDisplacement(1400) + 20000;
m_sQueueSample.m_nReleasingVolumeModificator = 1;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
@@ -3717,23 +3552,23 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
continue;
}
- if (stereo && iSound > 60)
+ if (narrowSoundRange && iSound > 60)
iSound = 21;
- if (params->m_fDistance < maxDist) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ if (params.m_fDistance < maxDist) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume != 0) {
- if (noReflection) {
+ if (stereo) {
if (m_sQueueSample.m_fDistance < 0.2f * m_sQueueSample.m_fSoundIntensity) {
m_sQueueSample.m_bIs2D = true;
m_sQueueSample.m_nOffset = 0;
} else {
- noReflection = false;
+ stereo = false;
}
}
m_sQueueSample.m_bReverbFlag = true;
AddSampleToRequestedQueue();
- if (noReflection) {
+ if (stereo) {
m_sQueueSample.m_nOffset = 127;
++m_sQueueSample.m_nSampleIndex;
if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] != SOUND_WEAPON_SHOT_FIRED ||
@@ -3752,9 +3587,9 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
}
void
-cAudioManager::SetupPedComments(cPedParams *params, uint32 sound)
+cAudioManager::SetupPedComments(cPedParams &params, uint16 sound)
{
- CPed *ped = params->m_pPed;
+ CPed *ped = params.m_pPed;
uint8 emittingVol;
float soundIntensity;
tPedComment pedComment;
@@ -3805,8 +3640,8 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound)
}
}
- if (params->m_fDistance < SQR(soundIntensity)) {
- CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance);
+ if (params.m_fDistance < SQR(soundIntensity)) {
+ CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);
if (sound != SOUND_PAGER) {
switch (sound) {
case SOUND_AMMUNATION_WELCOME_1:
@@ -3992,15 +3827,15 @@ cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound)
}
void
-cAudioManager::GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const
+cAudioManager::GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const
{
- *phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset;
+ phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset;
// check if the same sfx like last time, if yes, then try use next one,
// if exceeded range, then choose first available sample
- if (*phrase == *prevPhrase && ++*phrase >= sample + maxOffset)
- *phrase = sample;
- *prevPhrase = *phrase;
+ if (phrase == prevPhrase && ++phrase >= sample + maxOffset)
+ phrase = sample;
+ prevPhrase = phrase;
}
#pragma region PED_COMMENTS
@@ -4013,13 +3848,13 @@ cAudioManager::GetPlayerTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_DAMAGE:
- GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6);
break;
default:
sfx = NO_SAMPLE;
@@ -4037,13 +3872,13 @@ cAudioManager::GetCopTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_ARREST_COP:
- GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_COP_VOICE_1_ARREST_1, 6);
break;
case SOUND_PED_PURSUIT_COP:
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);
+ GetPhrase(sfx, lastSfx, SFX_COP_VOICE_1_CHASE_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4061,13 +3896,13 @@ cAudioManager::GetSwatTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_ARREST_SWAT:
- GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6);
break;
case SOUND_PED_PURSUIT_SWAT:
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);
+ GetPhrase(sfx, lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4085,13 +3920,13 @@ cAudioManager::GetFBITalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_ARREST_FBI:
- GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6);
break;
case SOUND_PED_PURSUIT_FBI:
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);
+ GetPhrase(sfx, lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4111,7 +3946,7 @@ cAudioManager::GetArmyTalkSfx(int16 sound)
case SOUND_PED_PURSUIT_ARMY:
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);
+ GetPhrase(sfx, lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15);
break;
default: return GetGenericMaleTalkSfx(sound);
}
@@ -4127,19 +3962,19 @@ cAudioManager::GetMedicTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4161,28 +3996,28 @@ cAudioManager::GetNormalMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7);
break;
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DODGE_1, 9);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_EYING_1, 8);
break;
case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10);
+ GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10);
break;
case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CHAT_1, 25);
+ GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CHAT_1, 25);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4198,10 +4033,10 @@ cAudioManager::GetTaxiDriverTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7);
+ GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4218,25 +4053,25 @@ cAudioManager::GetPimpTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_GUN_COOL_1, 7);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_GUN_COOL_1, 7);
break;
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_CARJACKED_1, 4);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_CARJACKED_1, 4);
break;
case SOUND_PED_DEFEND:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_FIGHT_1, 9);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_FIGHT_1, 9);
break;
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_DODGE_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5);
break;
case SOUND_PED_CHAT_EVENT:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_SHOCKED_1, 2);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_SHOCKED_1, 2);
break;
case SOUND_PED_CHAT:
- GetPhrase(&sfx, &lastSfx, SFX_PIMP_CHAT_1, 17);
+ GetPhrase(sfx, lastSfx, SFX_PIMP_CHAT_1, 17);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4252,25 +4087,25 @@ cAudioManager::GetMafiaTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4286,28 +4121,28 @@ cAudioManager::GetTriadTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4323,32 +4158,32 @@ cAudioManager::GetDiabloTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4364,22 +4199,22 @@ cAudioManager::GetYakuzaTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4398,25 +4233,25 @@ cAudioManager::GetYardieTalkSfx(int16 sound)
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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4432,25 +4267,25 @@ cAudioManager::GetColumbianTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKING:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4466,28 +4301,28 @@ cAudioManager::GetHoodTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6);
break;
default:
@@ -4505,22 +4340,22 @@ cAudioManager::GetBlackCriminalTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4537,22 +4372,22 @@ cAudioManager::GetWhiteCriminalTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4569,25 +4404,25 @@ cAudioManager::GetMaleNo2TalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4602,14 +4437,14 @@ cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model)
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_ANNOYED_DRIVER: 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); break;
+ 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_ANNOYED_DRIVER: 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); break;
default: return GetGenericMaleTalkSfx(sound);
}
@@ -4625,12 +4460,12 @@ cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound)
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_ANNOYED_DRIVER: 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); break;
+ 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_ANNOYED_DRIVER: 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); break;
default: return GetGenericMaleTalkSfx(sound);
}
return sfx;
@@ -4644,22 +4479,22 @@ cAudioManager::GetBlackFatMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -4675,28 +4510,28 @@ cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4712,28 +4547,28 @@ cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4749,28 +4584,28 @@ cAudioManager::GetFemaleNo3TalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4786,25 +4621,25 @@ cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4820,25 +4655,25 @@ cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4854,25 +4689,25 @@ cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4888,22 +4723,22 @@ cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4919,25 +4754,25 @@ cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4953,25 +4788,25 @@ cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -4987,25 +4822,25 @@ cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5021,25 +4856,25 @@ cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5055,22 +4890,22 @@ cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5086,22 +4921,22 @@ cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5117,25 +4952,25 @@ cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5151,22 +4986,22 @@ cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5182,22 +5017,22 @@ cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5213,22 +5048,22 @@ cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5244,22 +5079,22 @@ cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5275,28 +5110,28 @@ cAudioManager::GetScumMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5312,22 +5147,22 @@ cAudioManager::GetScumFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5343,22 +5178,22 @@ cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5374,22 +5209,22 @@ cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5405,28 +5240,28 @@ cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5445,28 +5280,28 @@ cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5482,28 +5317,28 @@ cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5522,28 +5357,28 @@ cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5);
+ 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);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5559,25 +5394,25 @@ cAudioManager::GetSupermodelMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5593,22 +5428,22 @@ cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5624,19 +5459,19 @@ cAudioManager::GetStewardMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5652,16 +5487,16 @@ cAudioManager::GetStewardFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5677,19 +5512,19 @@ cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model)
switch (sound) {
case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5711,16 +5546,16 @@ cAudioManager::GetFanFemaleTalkSfx(int16 sound)
sfx = SFX_FOOTBALL_FEMALE_VOICE_1_MUGGED_1;
break;
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4);
+ GetPhrase(sfx, lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5736,19 +5571,19 @@ cAudioManager::GetHospitalMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5764,13 +5599,13 @@ cAudioManager::GetHospitalFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5);
+ GetPhrase(sfx, lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5786,25 +5621,25 @@ cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5820,25 +5655,25 @@ cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5854,22 +5689,22 @@ cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model)
switch (sound) {
case SOUND_PED_CAR_JACKED:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -5891,25 +5726,25 @@ cAudioManager::GetStudentMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -5925,25 +5760,25 @@ cAudioManager::GetStudentFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_COWER:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4);
+ 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);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4);
break;
case SOUND_PED_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -6002,16 +5837,16 @@ cAudioManager::GetEightTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_GUN_COOL_1, 2);
+ GetPhrase(sfx, lastSfx, SFX_8BALL_GUN_COOL_1, 2);
break;
case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_MUGGED_1, 2);
+ GetPhrase(sfx, lastSfx, SFX_8BALL_MUGGED_1, 2);
break;
case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_FIGHT_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_8BALL_FIGHT_1, 6);
break;
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_8BALL_DODGE_1, 7);
+ GetPhrase(sfx, lastSfx, SFX_8BALL_DODGE_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -6027,16 +5862,16 @@ cAudioManager::GetFrankieTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_GUN_COOL_1, 4);
+ GetPhrase(sfx, lastSfx, SFX_SALVATORE_GUN_COOL_1, 4);
break;
case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_MUGGED_1, 2);
+ GetPhrase(sfx, lastSfx, SFX_SALVATORE_MUGGED_1, 2);
break;
case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_FIGHT_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_SALVATORE_FIGHT_1, 6);
break;
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_DODGE_1, 3);
+ GetPhrase(sfx, lastSfx, SFX_SALVATORE_DODGE_1, 3);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -6052,19 +5887,19 @@ cAudioManager::GetMistyTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_GUN_COOL_1, 5);
+ GetPhrase(sfx, lastSfx, SFX_MISTY_GUN_COOL_1, 5);
break;
case SOUND_PED_ROBBED:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_MUGGED_1, 2);
+ GetPhrase(sfx, lastSfx, SFX_MISTY_MUGGED_1, 2);
break;
case SOUND_PED_ATTACK:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_FIGHT_1, 4);
+ GetPhrase(sfx, lastSfx, SFX_MISTY_FIGHT_1, 4);
break;
case SOUND_PED_EVADE:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_DODGE_1, 5);
+ GetPhrase(sfx, lastSfx, SFX_MISTY_DODGE_1, 5);
break;
case SOUND_PED_TAXI_CALL:
- GetPhrase(&sfx, &lastSfx, SFX_MISTY_HERE_1, 4);
+ GetPhrase(sfx, lastSfx, SFX_MISTY_HERE_1, 4);
break;
default:
return GetGenericFemaleTalkSfx(sound);
@@ -6094,7 +5929,7 @@ cAudioManager::GetBomberTalkSfx(int16 sound)
switch (sound)
{
case SOUND_PED_BOMBER:
- GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7);
+ GetPhrase(sfx, lastSfx, SFX_BOMBERMAN_1, 7);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -6110,23 +5945,23 @@ cAudioManager::GetSecurityGuardTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_HANDS_UP:
- GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2);
+ 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_ANNOYED_DRIVER:
- GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6);
+ 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);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12);
#endif
break;
default:
@@ -6146,7 +5981,7 @@ cAudioManager::GetChunkyTalkSfx(int16 sound)
case SOUND_PED_DEATH:
return SFX_CHUNKY_DEATH;
case SOUND_PED_FLEE_RUN:
- GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5);
+ GetPhrase(sfx, lastSfx, SFX_CHUNKY_RUN_1, 5);
break;
default:
return GetGenericMaleTalkSfx(sound);
@@ -6163,17 +5998,17 @@ cAudioManager::GetGenericMaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_DEATH:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_DEATH_1, 8);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15);
break;
case SOUND_PED_BURNING:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_FIRE_1, 8);
+ GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_FIRE_1, 8);
break;
case SOUND_PED_FLEE_SPRINT:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_PANIC_1, 6);
+ GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_PANIC_1, 6);
break;
default:
return NO_SAMPLE;
@@ -6189,17 +6024,17 @@ cAudioManager::GetGenericFemaleTalkSfx(int16 sound)
switch (sound) {
case SOUND_PED_DEATH:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10);
+ 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);
+ GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11);
break;
case SOUND_PED_BURNING:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9);
+ GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9);
break;
case SOUND_PED_FLEE_SPRINT:
- GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8);
+ GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8);
break;
default:
return NO_SAMPLE;
@@ -6539,14 +6374,14 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound)
male.m_pPed = nil;
male.m_bDistanceCalculated = false;
male.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);
- SetupPedComments(&male, SOUND_INJURED_PED_MALE_OUCH);
+ SetupPedComments(male, SOUND_INJURED_PED_MALE_OUCH);
return;
case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_S:
case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_L:
female.m_pPed = nil;
female.m_bDistanceCalculated = false;
female.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);
- SetupPedComments(&female, SOUND_INJURED_PED_FEMALE);
+ SetupPedComments(female, SOUND_INJURED_PED_FEMALE);
return;
case SCRIPT_SOUND_GATE_START_CLUNK:
case SCRIPT_SOUND_GATE_STOP_CLUNK:
@@ -7924,7 +7759,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound)
params.m_bDistanceCalculated = true;
params.m_fDistance = distSquared;
params.m_pPed = nil;
- SetupPedComments(&params, SOUND_INJURED_PED_MALE_PRISON);
+ SetupPedComments(params, SOUND_INJURED_PED_MALE_PRISON);
}
gCellNextTime = time + 500 + m_anRandomTable[3] % 1500;
}
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index d8054181..947bda40 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -167,7 +167,7 @@ cAudioManager::SetEntityStatus(int32 id, uint8 status)
}
void
-cAudioManager::PlayOneShot(int32 index, int16 sound, float vol)
+cAudioManager::PlayOneShot(int32 index, uint16 sound, float vol)
{
static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h
index 40a2d056..d781ad71 100644
--- a/src/audio/AudioManager.h
+++ b/src/audio/AudioManager.h
@@ -332,7 +332,7 @@ public:
int8 GetMissionScriptPoliceAudioPlayingStatus() const;
uint8 GetNum3DProvidersAvailable() const;
int32 GetPedCommentSfx(CPed *ped, int32 sound);
- void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const;
+ void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const;
float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile,
cTransmission *transmission, float velocityChange);
float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile,
@@ -351,7 +351,7 @@ public:
bool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const;
void PlayLoadedMissionAudio();
- void PlayOneShot(int32 index, int16 sound, float vol);
+ void PlayOneShot(int32 index, uint16 sound, float vol);
void PlaySuspectLastSeen(float x, float y, float z);
void PlayerJustGotInCar() const;
void PlayerJustLeftCar() const;
@@ -362,29 +362,29 @@ public:
void PreTerminateGameSpecificShutdown();
/// processX - main logic of adding new sounds
void ProcessActiveQueues();
- bool ProcessAirBrakes(cVehicleParams *params);
+ bool ProcessAirBrakes(cVehicleParams& params);
void ProcessAirportScriptObject(uint8 sound);
- bool ProcessBoatEngine(cVehicleParams *params);
- bool ProcessBoatMovingOverWater(cVehicleParams *params);
+ bool ProcessBoatEngine(cVehicleParams& params);
+ bool ProcessBoatMovingOverWater(cVehicleParams& params);
void ProcessBridge();
void ProcessBridgeMotor();
void ProcessBridgeOneShots();
void ProcessBridgeWarning();
- bool ProcessCarBombTick(cVehicleParams *params);
- void ProcessCesna(cVehicleParams *params);
+ bool ProcessCarBombTick(cVehicleParams& params);
+ void ProcessCesna(cVehicleParams& params);
void ProcessCinemaScriptObject(uint8 sound);
void ProcessCrane();
void ProcessDocksScriptObject(uint8 sound);
- bool ProcessEngineDamage(cVehicleParams *params);
+ bool ProcessEngineDamage(cVehicleParams& params);
void ProcessEntity(int32 sound);
void ProcessExplosions(int32 explosion);
void ProcessFireHydrant();
void ProcessFires(int32 entity);
void ProcessFrontEnd();
void ProcessGarages();
- bool ProcessHelicopter(cVehicleParams *params);
+ bool ProcessHelicopter(cVehicleParams& params);
void ProcessHomeScriptObject(uint8 sound);
- void ProcessJumbo(cVehicleParams *);
+ void ProcessJumbo(cVehicleParams& params);
void ProcessJumboAccel(CPlane *plane);
void ProcessJumboDecel(CPlane *plane);
void ProcessJumboFlying();
@@ -394,37 +394,37 @@ public:
void ProcessLaunderetteScriptObject(uint8 sound);
void ProcessLoopingScriptObject(uint8 sound);
void ProcessMissionAudio();
- void ProcessModelCarEngine(cVehicleParams *params);
+ void ProcessModelCarEngine(cVehicleParams& params);
void ProcessOneShotScriptObject(uint8 sound);
void ProcessPed(CPhysical *ped);
- void ProcessPedHeadphones(cPedParams *params);
- void ProcessPedOneShots(cPedParams *params);
+ void ProcessPedHeadphones(cPedParams &params);
+ void ProcessPedOneShots(cPedParams &params);
void ProcessPhysical(int32 id);
- void ProcessPlane(cVehicleParams *params);
- void ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile);
+ void ProcessPlane(cVehicleParams& params);
+ void ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile);
void ProcessPoliceCellBeatingScriptObject(uint8 sound);
void ProcessPornCinema(uint8 sound);
void ProcessProjectiles();
- void ProcessRainOnVehicle(cVehicleParams *params);
+ void ProcessRainOnVehicle(cVehicleParams& params);
void ProcessReverb() const;
- bool ProcessReverseGear(cVehicleParams *params);
+ bool ProcessReverseGear(cVehicleParams& params);
void ProcessSawMillScriptObject(uint8 sound);
void ProcessScriptObject(int32 id);
void ProcessShopScriptObject(uint8 sound);
void ProcessSpecial();
- bool ProcessTrainNoise(cVehicleParams *params);
+ bool ProcessTrainNoise(cVehicleParams& params);
void ProcessVehicle(CVehicle *vehicle);
- bool ProcessVehicleDoors(cVehicleParams *params);
- void ProcessVehicleEngine(cVehicleParams *params);
- void ProcessVehicleHorn(cVehicleParams *params);
- void ProcessVehicleOneShots(cVehicleParams *params);
- bool ProcessVehicleReverseWarning(cVehicleParams *params);
- bool ProcessVehicleRoadNoise(cVehicleParams *params);
- bool ProcessVehicleSirenOrAlarm(cVehicleParams *params);
- bool ProcessVehicleSkidding(cVehicleParams *params);
+ bool ProcessVehicleDoors(cVehicleParams& params);
+ void ProcessVehicleEngine(cVehicleParams& params);
+ void ProcessVehicleHorn(cVehicleParams& params);
+ void ProcessVehicleOneShots(cVehicleParams& params);
+ bool ProcessVehicleReverseWarning(cVehicleParams& params);
+ bool ProcessVehicleRoadNoise(cVehicleParams& params);
+ bool ProcessVehicleSirenOrAlarm(cVehicleParams& params);
+ bool ProcessVehicleSkidding(cVehicleParams& params);
void ProcessWaterCannon(int32);
void ProcessWeather(int32 id);
- bool ProcessWetRoadNoise(cVehicleParams *params);
+ bool ProcessWetRoadNoise(cVehicleParams& params);
void ProcessWorkShopScriptObject(uint8 sound);
int32 RandomDisplacement(uint32 seed) const;
@@ -462,7 +462,7 @@ public:
bool SetupJumboRumbleSound(uint8 emittingVol);
bool SetupJumboTaxiSound(uint8 vol);
bool SetupJumboWhineSound(uint8 emittingVol, uint32 freq);
- void SetupPedComments(cPedParams *params, uint32 sound);
+ void SetupPedComments(cPedParams &params, uint16 sound);
void SetupSuspectLastSeenReport();
void Terminate();
diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp
index 0663bbd9..2514d963 100644
--- a/src/audio/MusicManager.cpp
+++ b/src/audio/MusicManager.cpp
@@ -161,7 +161,7 @@ cMusicManager::DisplayRadioStationName()
CFont::SetPropOn();
CFont::SetFontStyle(FONT_HEADING);
CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+ CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));
CFont::SetColor(CRGBA(0, 0, 0, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation);
diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp
index 3adb702a..90e90dd8 100644
--- a/src/audio/oal/stream.cpp
+++ b/src/audio/oal/stream.cpp
@@ -10,13 +10,15 @@
#ifdef _WIN32
#pragma comment( lib, "libsndfile-1.lib" )
#pragma comment( lib, "libmpg123-0.lib" )
-#else
-#include "crossplatform.h"
#endif
#include <sndfile.h>
#include <mpg123.h>
#endif
+#ifndef _WIN32
+#include "crossplatform.h"
+#endif
+
#ifndef AUDIO_OPUS
class CSndFile : public IDecoder
{
diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp
index 185e08d6..db38da64 100644
--- a/src/audio/sampman_miles.cpp
+++ b/src/audio/sampman_miles.cpp
@@ -65,7 +65,7 @@ uint32 _CurMP3Index;
int32 _CurMP3Pos;
bool _bIsMp3Active;
-#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK)
+#if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK)
bool _bUseHDDAudio;
char _aHDDPath[MAX_PATH];
#endif
@@ -1043,7 +1043,7 @@ cSampleManager::Initialise(void)
if ( !m_bInitialised )
{
-#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK)
+#if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK)
FrontEndMenuManager.WaitForUserCD();
if ( FrontEndMenuManager.m_bQuitGameNoCD )
{
@@ -1060,7 +1060,7 @@ cSampleManager::Initialise(void)
}
}
-#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK)
+#if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK)
// hddaudio
/**
Option for user to play audio files directly from hard disk.
@@ -1297,17 +1297,17 @@ cSampleManager::Terminate(void)
bool
cSampleManager::CheckForAnAudioFileOnCD(void)
{
-#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK)
+#if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK)
char filepath[MAX_PATH];
-#if defined(GTA3_1_1_PATCH)
+#if GTA_VERSION >= GTA3_PC_11
if (_bUseHDDAudio)
strcpy(filepath, _aHDDPath);
else
strcpy(filepath, m_szCDRomRootPath);
#else
strcpy(filepath, m_szCDRomRootPath);
-#endif // #if defined(GTA3_1_1_PATCH)
+#endif // #if GTA_VERSION >= GTA3_PC_11
strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]);
@@ -1324,13 +1324,13 @@ cSampleManager::CheckForAnAudioFileOnCD(void)
#else
return true;
-#endif // #if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK)
+#endif // #if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK)
}
char
cSampleManager::GetCDAudioDriveLetter(void)
{
-#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK)
+#if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK)
if (_bUseHDDAudio)
{
if ( strlen(_aHDDPath) != 0 )
diff --git a/src/collision/ColBox.cpp b/src/collision/ColBox.cpp
new file mode 100644
index 00000000..53cba88b
--- /dev/null
+++ b/src/collision/ColBox.cpp
@@ -0,0 +1,21 @@
+#include "common.h"
+#include "ColBox.h"
+
+void
+CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
+{
+ this->min = min;
+ this->max = max;
+ this->surface = surf;
+ this->piece = piece;
+}
+
+CColBox&
+CColBox::operator=(const CColBox& other)
+{
+ min = other.min;
+ max = other.max;
+ surface = other.surface;
+ piece = other.piece;
+ return *this;
+} \ No newline at end of file
diff --git a/src/collision/ColBox.h b/src/collision/ColBox.h
new file mode 100644
index 00000000..ac2cd675
--- /dev/null
+++ b/src/collision/ColBox.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "SurfaceTable.h"
+
+struct CColBox
+{
+ CVector min;
+ CVector max;
+ uint8 surface;
+ uint8 piece;
+
+ void Set(const CVector &min, const CVector &max, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
+ CVector GetSize(void) { return max - min; }
+
+ CColBox& operator=(const CColBox &other);
+}; \ No newline at end of file
diff --git a/src/collision/ColLine.cpp b/src/collision/ColLine.cpp
new file mode 100644
index 00000000..c6247449
--- /dev/null
+++ b/src/collision/ColLine.cpp
@@ -0,0 +1,9 @@
+#include "common.h"
+#include "ColLine.h"
+
+void
+CColLine::Set(const CVector &p0, const CVector &p1)
+{
+ this->p0 = p0;
+ this->p1 = p1;
+} \ No newline at end of file
diff --git a/src/collision/ColLine.h b/src/collision/ColLine.h
new file mode 100644
index 00000000..21587a06
--- /dev/null
+++ b/src/collision/ColLine.h
@@ -0,0 +1,14 @@
+#pragma once
+
+struct CColLine
+{
+ // NB: this has to be compatible with two CVuVectors
+ CVector p0;
+ int pad0;
+ CVector p1;
+ int pad1;
+
+ CColLine(void) { };
+ CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
+ void Set(const CVector &p0, const CVector &p1);
+}; \ No newline at end of file
diff --git a/src/collision/ColModel.cpp b/src/collision/ColModel.cpp
new file mode 100644
index 00000000..fb90e7dd
--- /dev/null
+++ b/src/collision/ColModel.cpp
@@ -0,0 +1,190 @@
+#include "common.h"
+#include "ColModel.h"
+#include "Game.h"
+#include "MemoryHeap.h"
+
+CColModel::CColModel(void)
+{
+ numSpheres = 0;
+ spheres = nil;
+ numLines = 0;
+ lines = nil;
+ numBoxes = 0;
+ boxes = nil;
+ numTriangles = 0;
+ vertices = nil;
+ triangles = nil;
+ trianglePlanes = nil;
+ level = CGame::currLevel;
+ ownsCollisionVolumes = true;
+}
+
+CColModel::~CColModel(void)
+{
+ RemoveCollisionVolumes();
+ RemoveTrianglePlanes();
+}
+
+void
+CColModel::RemoveCollisionVolumes(void)
+{
+ if(ownsCollisionVolumes){
+ RwFree(spheres);
+ RwFree(lines);
+ RwFree(boxes);
+ RwFree(vertices);
+ RwFree(triangles);
+ }
+ numSpheres = 0;
+ numLines = 0;
+ numBoxes = 0;
+ numTriangles = 0;
+ spheres = nil;
+ lines = nil;
+ boxes = nil;
+ vertices = nil;
+ triangles = nil;
+}
+
+void
+CColModel::CalculateTrianglePlanes(void)
+{
+ PUSH_MEMID(MEMID_COLLISION);
+
+ // HACK: allocate space for one more element to stuff the link pointer into
+ trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
+ REGISTER_MEMPTR(&trianglePlanes);
+ for(int i = 0; i < numTriangles; i++)
+ trianglePlanes[i].Set(vertices, triangles[i]);
+
+ POP_MEMID();
+}
+
+void
+CColModel::RemoveTrianglePlanes(void)
+{
+ RwFree(trianglePlanes);
+ trianglePlanes = nil;
+}
+
+void
+CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
+{
+ assert(trianglePlanes);
+ *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
+}
+
+CLink<CColModel*>*
+CColModel::GetLinkPtr(void)
+{
+ assert(trianglePlanes);
+ return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
+}
+
+void
+CColModel::GetTrianglePoint(CVector &v, int i) const
+{
+ v = vertices[i].Get();
+}
+
+CColModel&
+CColModel::operator=(const CColModel &other)
+{
+ int i;
+ int numVerts;
+
+ boundingSphere = other.boundingSphere;
+ boundingBox = other.boundingBox;
+
+ // copy spheres
+ if(other.numSpheres){
+ if(numSpheres != other.numSpheres){
+ numSpheres = other.numSpheres;
+ if(spheres)
+ RwFree(spheres);
+ spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
+ }
+ for(i = 0; i < numSpheres; i++)
+ spheres[i] = other.spheres[i];
+ }else{
+ numSpheres = 0;
+ if(spheres)
+ RwFree(spheres);
+ spheres = nil;
+ }
+
+ // copy lines
+ if(other.numLines){
+ if(numLines != other.numLines){
+ numLines = other.numLines;
+ if(lines)
+ RwFree(lines);
+ lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
+ }
+ for(i = 0; i < numLines; i++)
+ lines[i] = other.lines[i];
+ }else{
+ numLines = 0;
+ if(lines)
+ RwFree(lines);
+ lines = nil;
+ }
+
+ // copy boxes
+ if(other.numBoxes){
+ if(numBoxes != other.numBoxes){
+ numBoxes = other.numBoxes;
+ if(boxes)
+ RwFree(boxes);
+ boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
+ }
+ for(i = 0; i < numBoxes; i++)
+ boxes[i] = other.boxes[i];
+ }else{
+ numBoxes = 0;
+ if(boxes)
+ RwFree(boxes);
+ boxes = nil;
+ }
+
+ // copy mesh
+ if(other.numTriangles){
+ // copy vertices
+ numVerts = 0;
+ for(i = 0; i < other.numTriangles; i++){
+ if(other.triangles[i].a > numVerts)
+ numVerts = other.triangles[i].a;
+ if(other.triangles[i].b > numVerts)
+ numVerts = other.triangles[i].b;
+ if(other.triangles[i].c > numVerts)
+ numVerts = other.triangles[i].c;
+ }
+ numVerts++;
+ if(vertices)
+ RwFree(vertices);
+ if(numVerts){
+ vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
+ for(i = 0; i < numVerts; i++)
+ vertices[i] = other.vertices[i];
+ }
+
+ // copy triangles
+ if(numTriangles != other.numTriangles){
+ numTriangles = other.numTriangles;
+ if(triangles)
+ RwFree(triangles);
+ triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
+ }
+ for(i = 0; i < numTriangles; i++)
+ triangles[i] = other.triangles[i];
+ }else{
+ numTriangles = 0;
+ if(triangles)
+ RwFree(triangles);
+ triangles = nil;
+ if(vertices)
+ RwFree(vertices);
+ vertices = nil;
+ }
+ return *this;
+}
diff --git a/src/collision/ColModel.h b/src/collision/ColModel.h
new file mode 100644
index 00000000..7dcdfa4d
--- /dev/null
+++ b/src/collision/ColModel.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "templates.h"
+#include "ColBox.h"
+#include "ColSphere.h"
+#include "ColLine.h"
+#include "ColPoint.h"
+#include "ColTriangle.h"
+
+struct CColModel
+{
+ CColSphere boundingSphere;
+ CColBox boundingBox;
+ int16 numSpheres;
+ int16 numLines;
+ int16 numBoxes;
+ int16 numTriangles;
+ int32 level;
+ bool ownsCollisionVolumes; // missing on PS2
+ CColSphere *spheres;
+ CColLine *lines;
+ CColBox *boxes;
+ CompressedVector *vertices;
+ CColTriangle *triangles;
+ CColTrianglePlane *trianglePlanes;
+
+ CColModel(void);
+ ~CColModel(void);
+ void RemoveCollisionVolumes(void);
+ void CalculateTrianglePlanes(void);
+ void RemoveTrianglePlanes(void);
+ CLink<CColModel*> *GetLinkPtr(void);
+ void SetLinkPtr(CLink<CColModel*>*);
+ void GetTrianglePoint(CVector &v, int i) const;
+
+ CColModel& operator=(const CColModel& other);
+}; \ No newline at end of file
diff --git a/src/collision/ColPoint.cpp b/src/collision/ColPoint.cpp
new file mode 100644
index 00000000..fbf9e8c3
--- /dev/null
+++ b/src/collision/ColPoint.cpp
@@ -0,0 +1,16 @@
+#include "common.h"
+#include "ColPoint.h"
+
+CColPoint&
+CColPoint::operator=(const CColPoint &other)
+{
+ point = other.point;
+ normal = other.normal;
+ surfaceA = other.surfaceA;
+ pieceA = other.pieceA;
+ surfaceB = other.surfaceB;
+ pieceB = other.pieceB;
+
+ // no depth?
+ return *this;
+}
diff --git a/src/collision/ColPoint.h b/src/collision/ColPoint.h
new file mode 100644
index 00000000..a15b2345
--- /dev/null
+++ b/src/collision/ColPoint.h
@@ -0,0 +1,34 @@
+#pragma once
+
+struct CColPoint
+{
+ CVector point;
+ int pad1;
+ // the surface normal on the surface of point
+ CVector normal;
+ int pad2;
+ uint8 surfaceA;
+ uint8 pieceA;
+ uint8 surfaceB;
+ uint8 pieceB;
+ float depth;
+
+ const CVector &GetNormal() { return normal; }
+ float GetDepth() { return depth; }
+ void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
+ this->depth = depth;
+ this->surfaceA = surfA;
+ this->pieceA = pieceA;
+ this->surfaceB = surfB;
+ this->pieceB = pieceB;
+ }
+ void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
+ this->surfaceA = surfA;
+ this->pieceA = pieceA;
+ this->surfaceB = surfB;
+ this->pieceB = pieceB;
+ }
+
+ CColPoint &operator=(const CColPoint &other);
+};
+
diff --git a/src/collision/ColSphere.cpp b/src/collision/ColSphere.cpp
new file mode 100644
index 00000000..9aac01e0
--- /dev/null
+++ b/src/collision/ColSphere.cpp
@@ -0,0 +1,11 @@
+#include "common.h"
+#include "ColSphere.h"
+
+void
+CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
+{
+ this->radius = radius;
+ this->center = center;
+ this->surface = surf;
+ this->piece = piece;
+} \ No newline at end of file
diff --git a/src/collision/ColSphere.h b/src/collision/ColSphere.h
new file mode 100644
index 00000000..70e29763
--- /dev/null
+++ b/src/collision/ColSphere.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "SurfaceTable.h"
+
+struct CColSphere
+{
+ // NB: this has to be compatible with a CVuVector
+ CVector center;
+ float radius;
+ uint8 surface;
+ uint8 piece;
+ void Set(float radius, const CVector &center, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
+}; \ No newline at end of file
diff --git a/src/collision/ColTriangle.cpp b/src/collision/ColTriangle.cpp
new file mode 100644
index 00000000..9120fcff
--- /dev/null
+++ b/src/collision/ColTriangle.cpp
@@ -0,0 +1,41 @@
+#include "common.h"
+#include "ColTriangle.h"
+
+void
+CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
+{
+ this->a = a;
+ this->b = b;
+ this->c = c;
+ this->surface = surf;
+}
+
+#ifdef VU_COLLISION
+void
+CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
+{
+ CVector norm = CrossProduct(vc-va, vb-va);
+ norm.Normalise();
+ float d = DotProduct(norm, va);
+ normal.x = norm.x*4096.0f;
+ normal.y = norm.y*4096.0f;
+ normal.z = norm.z*4096.0f;
+ dist = d*128.0f;
+}
+#else
+void
+CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
+{
+ normal = CrossProduct(vc-va, vb-va);
+ normal.Normalise();
+ dist = DotProduct(normal, va);
+ CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
+ // find out largest component and its direction
+ if(an.x > an.y && an.x > an.z)
+ dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
+ else if(an.y > an.z)
+ dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
+ else
+ dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
+}
+#endif \ No newline at end of file
diff --git a/src/collision/ColTriangle.h b/src/collision/ColTriangle.h
new file mode 100644
index 00000000..9e918e38
--- /dev/null
+++ b/src/collision/ColTriangle.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "CompressedVector.h"
+
+enum Direction {
+ DIR_X_POS,
+ DIR_X_NEG,
+ DIR_Y_POS,
+ DIR_Y_NEG,
+ DIR_Z_POS,
+ DIR_Z_NEG,
+};
+
+struct CColTriangle
+{
+ uint16 a;
+ uint16 b;
+ uint16 c;
+ uint8 surface;
+
+ void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
+};
+
+struct CColTrianglePlane
+{
+#ifdef VU_COLLISION
+ CompressedVector normal;
+ int16 dist;
+
+ void Set(const CVector &va, const CVector &vb, const CVector &vc);
+ void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
+ void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }
+ float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };
+#ifdef GTA_PS2
+ void Unpack(uint128 &qword) const {
+ __asm__ volatile (
+ "lh $8, 0(%1)\n"
+ "lh $9, 2(%1)\n"
+ "lh $10, 4(%1)\n"
+ "lh $11, 6(%1)\n"
+ "pextlw $10, $8\n"
+ "pextlw $11, $9\n"
+ "pextlw $2, $11, $10\n"
+ "sq $2, %0\n"
+ : "=m" (qword)
+ : "r" (this)
+ : "$8", "$9", "$10", "$11", "$2"
+ );
+ }
+#else
+ void Unpack(int32 *qword) const {
+ qword[0] = normal.x;
+ qword[1] = normal.y;
+ qword[2] = normal.z;
+ qword[3] = dist;
+ }
+#endif
+#else
+ CVector normal;
+ float dist;
+ uint8 dir;
+
+ void Set(const CVector &va, const CVector &vb, const CVector &vc);
+ void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
+ void GetNormal(CVector &n) const { n = normal; }
+ float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
+#endif
+}; \ No newline at end of file
diff --git a/src/core/Collision.cpp b/src/collision/Collision.cpp
index d8603cd8..41997e32 100644
--- a/src/core/Collision.cpp
+++ b/src/collision/Collision.cpp
@@ -23,303 +23,8 @@
#include "Collision.h"
#include "Frontend.h"
-
-// TODO: where do these go?
-
#ifdef VU_COLLISION
-
-struct VuTriangle
-{
- // Compressed int16 but unpacked
-#ifdef GTA_PS2
- uint128 v0;
- uint128 v1;
- uint128 v2;
- uint128 plane;
-#else
- int32 v0[4];
- int32 v1[4];
- int32 v2[4];
- int32 plane[4];
-#endif
-};
-
-#ifndef GTA_PS2
-static int16 vi01;
-static CVuVector vf01;
-static CVuVector vf02;
-static CVuVector vf03;
-
-CVuVector
-DistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)
-{
- // center VF12
- // p0 VF14
- // line VF15
- CVuVector ret; // VF16
- CVuVector p1 = p0+line;
- CVuVector dist0 = center - p0; // VF20
- CVuVector dist1 = center - p1; // VF25
- float lenSq = line.MagnitudeSqr(); // VF21
- float distSq0 = dist0.MagnitudeSqr(); // VF22
- float distSq1 = dist1.MagnitudeSqr();
- float dot = DotProduct(dist0, line); // VF23
- if(dot < 0.0f){
- // not above line, closest to p0
- ret = p0;
- ret.w = distSq0;
- return ret;
- }
- float t = dot/lenSq; // param of nearest point on infinite line
- if(t > 1.0f){
- // not above line, closest to p1
- ret = p1;
- ret.w = distSq1;
- return ret;
- }
- // closest to line
- ret = p0 + line*t;
- ret.w = (ret - center).MagnitudeSqr();
- return ret;
-}
-inline int SignFlags(const CVector &v)
-{
- int f = 0;
- if(v.x < 0.0f) f |= 1;
- if(v.y < 0.0f) f |= 2;
- if(v.z < 0.0f) f |= 4;
- return f;
-}
-#endif
-
-extern "C" void
-LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
- const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
- const CVuVector &plane)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf13, 0x0(%1)\n"
- "lqc2 vf14, 0x0(%2)\n"
- "lqc2 vf15, 0x0(%3)\n"
- "lqc2 vf16, 0x0(%4)\n"
- "lqc2 vf17, 0x0(%5)\n"
- "vcallms Vu0LineToTriangleCollisionStart\n"
- ".set reorder\n"
- :
- : "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
- );
-#else
- float dot0 = DotProduct(plane, p0);
- float dot1 = DotProduct(plane, p1);
- float dist0 = plane.w - dot0;
- float dist1 = plane.w - dot1;
-
- // if points are on the same side, no collision
- if(dist0 * dist1 > 0.0f){
- vi01 = 0;
- return;
- }
-
- CVuVector diff = p1 - p0;
- float t = dist0/(dot1 - dot0);
- CVuVector p = p0 + diff*t;
- p.w = 0.0f;
- vf01 = p;
- vf03.x = t;
-
- // Check if point is inside
- CVector cross1 = CrossProduct(p-v0, v1-v0);
- CVector cross2 = CrossProduct(p-v1, v2-v1);
- CVector cross3 = CrossProduct(p-v2, v0-v2);
- // Only check relevant directions
- int flagmask = 0;
- if(Abs(plane.x) > 0.5f) flagmask |= 1;
- if(Abs(plane.y) > 0.5f) flagmask |= 2;
- if(Abs(plane.z) > 0.5f) flagmask |= 4;
- int flags1 = SignFlags(cross1) & flagmask;
- int flags2 = SignFlags(cross2) & flagmask;
- int flags3 = SignFlags(cross3) & flagmask;
- // inside if on the same side of all edges
- if(flags1 != flags2 || flags1 != flags3){
- vi01 = 0;
- return;
- }
- vi01 = 1;
- vf02 = plane;
- return;
-#endif
-}
-
-extern "C" void
-LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf13, 0x0(%1)\n"
- "lqc2 vf14, 0x0(%2)\n"
- "lqc2 vf15, 0x10(%2)\n"
- "lqc2 vf16, 0x20(%2)\n"
- "lqc2 vf17, 0x30(%2)\n"
- "vcallms Vu0LineToTriangleCollisionCompressedStart\n"
- ".set reorder\n"
- :
- : "r" (&p0), "r" (&p1), "r" (&tri)
- );
-#else
- CVuVector v0, v1, v2, plane;
- v0.x = tri.v0[0]/128.0f;
- v0.y = tri.v0[1]/128.0f;
- v0.z = tri.v0[2]/128.0f;
- v0.w = tri.v0[3]/128.0f;
- v1.x = tri.v1[0]/128.0f;
- v1.y = tri.v1[1]/128.0f;
- v1.z = tri.v1[2]/128.0f;
- v1.w = tri.v1[3]/128.0f;
- v2.x = tri.v2[0]/128.0f;
- v2.y = tri.v2[1]/128.0f;
- v2.z = tri.v2[2]/128.0f;
- v2.w = tri.v2[3]/128.0f;
- plane.x = tri.plane[0]/4096.0f;
- plane.y = tri.plane[1]/4096.0f;
- plane.z = tri.plane[2]/4096.0f;
- plane.w = tri.plane[3]/128.0f;
- LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
-#endif
-}
-
-extern "C" void
-SphereToTriangleCollision(const CVuVector &sph,
- const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
- const CVuVector &plane)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf14, 0x0(%1)\n"
- "lqc2 vf15, 0x0(%2)\n"
- "lqc2 vf16, 0x0(%3)\n"
- "lqc2 vf17, 0x0(%4)\n"
- "vcallms Vu0SphereToTriangleCollisionStart\n"
- ".set reorder\n"
- :
- : "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
- );
-#else
- float planedist = DotProduct(plane, sph) - plane.w; // VF02
- if(Abs(planedist) > sph.w){
- vi01 = 0;
- return;
- }
- // point on plane
- CVuVector p = sph - planedist*plane;
- p.w = 0.0f;
- vf01 = p;
- planedist = Abs(planedist);
- // edges
- CVuVector v01 = v1 - v0;
- CVuVector v12 = v2 - v1;
- CVuVector v20 = v0 - v2;
- // VU code calculates normal again for some weird reason...
- // Check sides of point
- CVector cross1 = CrossProduct(p-v0, v01);
- CVector cross2 = CrossProduct(p-v1, v12);
- CVector cross3 = CrossProduct(p-v2, v20);
- // Only check relevant directions
- int flagmask = 0;
- if(Abs(plane.x) > 0.1f) flagmask |= 1;
- if(Abs(plane.y) > 0.1f) flagmask |= 2;
- if(Abs(plane.z) > 0.1f) flagmask |= 4;
- int nflags = SignFlags(plane) & flagmask;
- int flags1 = SignFlags(cross1) & flagmask;
- int flags2 = SignFlags(cross2) & flagmask;
- int flags3 = SignFlags(cross3) & flagmask;
- int testcase = 0;
- CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
- if(flags1 == nflags){
- closest += v2;
- testcase++;
- }
- if(flags2 == nflags){
- closest += v0;
- testcase++;
- }
- if(flags3 == nflags){
- closest += v1;
- testcase++;
- }
- if(testcase == 3){
- // inside triangle - dist to plane already checked
- vf02 = plane;
- vf02.w = vf03.x = planedist;
- vi01 = 1;
- }else if(testcase == 1){
- // outside two sides - closest to point opposide inside edge
- vf01 = closest;
- vf02 = sph - closest;
- float distSq = vf02.MagnitudeSqr();
- vi01 = sph.w*sph.w > distSq;
- vf03.x = Sqrt(distSq);
- vf02 *= 1.0f/vf03.x;
- }else{
- // inside two sides - closest to third edge
- if(flags1 != nflags)
- closest = DistanceBetweenSphereAndLine(sph, v0, v01);
- else if(flags2 != nflags)
- closest = DistanceBetweenSphereAndLine(sph, v1, v12);
- else
- closest = DistanceBetweenSphereAndLine(sph, v2, v20);
- vi01 = sph.w*sph.w > closest.w;
- vf01 = closest;
- vf02 = sph - closest;
- vf03.x = Sqrt(closest.w);
- vf02 *= 1.0f/vf03.x;
- }
-#endif
-}
-
-extern "C" void
-SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf14, 0x0(%1)\n"
- "lqc2 vf15, 0x10(%1)\n"
- "lqc2 vf16, 0x20(%1)\n"
- "lqc2 vf17, 0x30(%1)\n"
- "vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
- ".set reorder\n"
- :
- : "r" (&sph), "r" (&tri)
- );
-#else
- CVuVector v0, v1, v2, plane;
- v0.x = tri.v0[0]/128.0f;
- v0.y = tri.v0[1]/128.0f;
- v0.z = tri.v0[2]/128.0f;
- v0.w = tri.v0[3]/128.0f;
- v1.x = tri.v1[0]/128.0f;
- v1.y = tri.v1[1]/128.0f;
- v1.z = tri.v1[2]/128.0f;
- v1.w = tri.v1[3]/128.0f;
- v2.x = tri.v2[0]/128.0f;
- v2.y = tri.v2[1]/128.0f;
- v2.z = tri.v2[2]/128.0f;
- v2.w = tri.v2[3]/128.0f;
- plane.x = tri.plane[0]/4096.0f;
- plane.y = tri.plane[1]/4096.0f;
- plane.z = tri.plane[2]/4096.0f;
- plane.w = tri.plane[3]/128.0f;
- SphereToTriangleCollision(sph, v0, v1, v2, plane);
-#endif
-}
+#include "VuCollision.h"
inline int
GetVUresult(void)
@@ -362,17 +67,6 @@ GetVUresult(CVuVector &point, CVuVector &normal, float &dist)
#endif
-
-enum Direction
-{
- DIR_X_POS,
- DIR_X_NEG,
- DIR_Y_POS,
- DIR_Y_NEG,
- DIR_Z_POS,
- DIR_Z_NEG,
-};
-
eLevelName CCollision::ms_collisionInMemory;
CLinkList<CColModel*> CCollision::ms_colModelCache;
@@ -2412,11 +2106,12 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space
- Invert(matrixB, matAB);
+ matAB = Invert(matrixB, matAB);
matAB *= matrixA;
CColSphere bsphereAB; // bounding sphere of A in B space
- bsphereAB.Set(modelA.boundingSphere.radius, matAB * modelA.boundingSphere.center);
+ bsphereAB.radius = modelA.boundingSphere.radius;
+ bsphereAB.center = matAB * modelA.boundingSphere.center;
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
return 0;
// B to A space
@@ -2449,7 +2144,8 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
int numBoxesB = 0;
int numTrianglesB = 0;
for(i = 0; i < modelB.numSpheres; i++){
- s.Set(modelB.spheres[i].radius, matBA * modelB.spheres[i].center);
+ s.radius = modelB.spheres[i].radius;
+ s.center = matBA * modelB.spheres[i].center;
if(TestSphereBox(s, modelA.boundingBox))
aSphereIndicesB[numSpheresB++] = i;
}
@@ -3037,254 +2733,4 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
-}
-
-
-/*
- * ColModel code
- */
-
-void
-CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
-{
- this->radius = radius;
- this->center = center;
- this->surface = surf;
- this->piece = piece;
-}
-
-void
-CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
-{
- this->min = min;
- this->max = max;
- this->surface = surf;
- this->piece = piece;
-}
-
-void
-CColLine::Set(const CVector &p0, const CVector &p1)
-{
- this->p0 = p0;
- this->p1 = p1;
-}
-
-void
-CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
-{
- this->a = a;
- this->b = b;
- this->c = c;
- this->surface = surf;
-}
-
-#ifdef VU_COLLISION
-void
-CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
-{
- CVector norm = CrossProduct(vc-va, vb-va);
- norm.Normalise();
- float d = DotProduct(norm, va);
- normal.x = norm.x*4096.0f;
- normal.y = norm.y*4096.0f;
- normal.z = norm.z*4096.0f;
- dist = d*128.0f;
-}
-#else
-void
-CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
-{
- normal = CrossProduct(vc-va, vb-va);
- normal.Normalise();
- dist = DotProduct(normal, va);
- CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
- // find out largest component and its direction
- if(an.x > an.y && an.x > an.z)
- dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
- else if(an.y > an.z)
- dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
- else
- dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
-}
-#endif
-
-CColModel::CColModel(void)
-{
- numSpheres = 0;
- spheres = nil;
- numLines = 0;
- lines = nil;
- numBoxes = 0;
- boxes = nil;
- numTriangles = 0;
- vertices = nil;
- triangles = nil;
- trianglePlanes = nil;
- level = CGame::currLevel;
- ownsCollisionVolumes = true;
-}
-
-CColModel::~CColModel(void)
-{
- RemoveCollisionVolumes();
- RemoveTrianglePlanes();
-}
-
-void
-CColModel::RemoveCollisionVolumes(void)
-{
- if(ownsCollisionVolumes){
- RwFree(spheres);
- RwFree(lines);
- RwFree(boxes);
- RwFree(vertices);
- RwFree(triangles);
- }
- numSpheres = 0;
- numLines = 0;
- numBoxes = 0;
- numTriangles = 0;
- spheres = nil;
- lines = nil;
- boxes = nil;
- vertices = nil;
- triangles = nil;
-}
-
-void
-CColModel::CalculateTrianglePlanes(void)
-{
- // HACK: allocate space for one more element to stuff the link pointer into
- trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
- for(int i = 0; i < numTriangles; i++)
- trianglePlanes[i].Set(vertices, triangles[i]);
-}
-
-void
-CColModel::RemoveTrianglePlanes(void)
-{
- RwFree(trianglePlanes);
- trianglePlanes = nil;
-}
-
-void
-CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
-{
- assert(trianglePlanes);
- *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
-}
-
-CLink<CColModel*>*
-CColModel::GetLinkPtr(void)
-{
- assert(trianglePlanes);
- return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
-}
-
-void
-CColModel::GetTrianglePoint(CVector &v, int i) const
-{
- v = vertices[i].Get();
-}
-
-CColModel&
-CColModel::operator=(const CColModel &other)
-{
- int i;
- int numVerts;
-
- boundingSphere = other.boundingSphere;
- boundingBox = other.boundingBox;
-
- // copy spheres
- if(other.numSpheres){
- if(numSpheres != other.numSpheres){
- numSpheres = other.numSpheres;
- if(spheres)
- RwFree(spheres);
- spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
- }
- for(i = 0; i < numSpheres; i++)
- spheres[i] = other.spheres[i];
- }else{
- numSpheres = 0;
- if(spheres)
- RwFree(spheres);
- spheres = nil;
- }
-
- // copy lines
- if(other.numLines){
- if(numLines != other.numLines){
- numLines = other.numLines;
- if(lines)
- RwFree(lines);
- lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
- }
- for(i = 0; i < numLines; i++)
- lines[i] = other.lines[i];
- }else{
- numLines = 0;
- if(lines)
- RwFree(lines);
- lines = nil;
- }
-
- // copy boxes
- if(other.numBoxes){
- if(numBoxes != other.numBoxes){
- numBoxes = other.numBoxes;
- if(boxes)
- RwFree(boxes);
- boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
- }
- for(i = 0; i < numBoxes; i++)
- boxes[i] = other.boxes[i];
- }else{
- numBoxes = 0;
- if(boxes)
- RwFree(boxes);
- boxes = nil;
- }
-
- // copy mesh
- if(other.numTriangles){
- // copy vertices
- numVerts = 0;
- for(i = 0; i < other.numTriangles; i++){
- if(other.triangles[i].a > numVerts)
- numVerts = other.triangles[i].a;
- if(other.triangles[i].b > numVerts)
- numVerts = other.triangles[i].b;
- if(other.triangles[i].c > numVerts)
- numVerts = other.triangles[i].c;
- }
- numVerts++;
- if(vertices)
- RwFree(vertices);
- if(numVerts){
- vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
- for(i = 0; i < numVerts; i++)
- vertices[i] = other.vertices[i];
- }
-
- // copy triangles
- if(numTriangles != other.numTriangles){
- numTriangles = other.numTriangles;
- if(triangles)
- RwFree(triangles);
- triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
- }
- for(i = 0; i < numTriangles; i++)
- triangles[i] = other.triangles[i];
- }else{
- numTriangles = 0;
- if(triangles)
- RwFree(triangles);
- triangles = nil;
- if(vertices)
- RwFree(vertices);
- vertices = nil;
- }
- return *this;
-}
+} \ No newline at end of file
diff --git a/src/collision/Collision.h b/src/collision/Collision.h
new file mode 100644
index 00000000..f4270bc5
--- /dev/null
+++ b/src/collision/Collision.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include "ColModel.h"
+#include "Game.h" // for eLevelName
+#ifdef VU_COLLISION
+#include "VuVector.h"
+#endif
+
+struct CStoredCollPoly
+{
+#ifdef VU_COLLISION
+ CVuVector verts[3];
+#else
+ CVector verts[3];
+#endif
+ bool valid;
+};
+
+// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
+#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
+#define MAX_COLLISION_POINTS 64
+#else
+#define MAX_COLLISION_POINTS 32
+#endif
+
+class CCollision
+{
+public:
+ static eLevelName ms_collisionInMemory;
+ static CLinkList<CColModel*> ms_colModelCache;
+#ifdef NO_ISLAND_LOADING
+ static bool bAlreadyLoaded;
+#endif
+
+ static void Init(void);
+ static void Shutdown(void);
+ static void Update(void);
+ static void LoadCollisionWhenINeedIt(bool changeLevel);
+ static void SortOutCollisionAfterLoad(void);
+ static void LoadCollisionScreen(eLevelName level);
+ static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
+ static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
+
+ 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 TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
+ static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
+ static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
+ static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough);
+
+ static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
+ static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
+ static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
+ static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
+ static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
+ static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
+ static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
+ static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
+ static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
+ static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
+ static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
+
+ static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);
+ static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);
+};
diff --git a/src/collision/CompressedVector.h b/src/collision/CompressedVector.h
new file mode 100644
index 00000000..d54e49b1
--- /dev/null
+++ b/src/collision/CompressedVector.h
@@ -0,0 +1,36 @@
+#pragma once
+
+struct CompressedVector
+{
+#ifdef COMPRESSED_COL_VECTORS
+ int16 x, y, z;
+ CVector Get(void) const { return CVector(x, y, z)/128.0f; };
+ void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };
+#ifdef GTA_PS2
+ void Unpack(uint128 &qword) const {
+ __asm__ volatile (
+ "lh $8, 0(%1)\n"
+ "lh $9, 2(%1)\n"
+ "lh $10, 4(%1)\n"
+ "pextlw $10, $8\n"
+ "pextlw $2, $9, $10\n"
+ "sq $2, %0\n"
+ : "=m" (qword)
+ : "r" (this)
+ : "$8", "$9", "$10", "$2"
+ );
+ }
+#else
+ void Unpack(int32 *qword) const {
+ qword[0] = x;
+ qword[1] = y;
+ qword[2] = z;
+ qword[3] = 0; // junk
+ }
+#endif
+#else
+ float x, y, z;
+ CVector Get(void) const { return CVector(x, y, z); };
+ void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; };
+#endif
+}; \ No newline at end of file
diff --git a/src/core/TempColModels.cpp b/src/collision/TempColModels.cpp
index f6796909..dabb6ebb 100644
--- a/src/core/TempColModels.cpp
+++ b/src/collision/TempColModels.cpp
@@ -1,7 +1,6 @@
#include "common.h"
#include "TempColModels.h"
-#include "SurfaceTable.h"
CColModel CTempColModels::ms_colModelPed1;
CColModel CTempColModels::ms_colModelPed2;
@@ -41,17 +40,17 @@ CTempColModels::Initialise(void)
colmodel.numSpheres = ARRAY_SIZE(sphrs);\
colmodel.spheres = sphrs;\
colmodel.level = LEVEL_GENERIC;\
- colmodel.ownsCollisionVolumes = false;\
+ colmodel.ownsCollisionVolumes = false;
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_GENERIC;
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_GENERIC;
}
@@ -73,8 +72,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
@@ -92,8 +91,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);
@@ -118,8 +117,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);
@@ -142,8 +141,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);
@@ -162,8 +161,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);
@@ -182,8 +181,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);
@@ -202,8 +201,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);
@@ -222,8 +221,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);
@@ -244,8 +243,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);
@@ -266,8 +265,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);
@@ -288,8 +287,8 @@ 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);
diff --git a/src/core/TempColModels.h b/src/collision/TempColModels.h
index 3e1dd5e1..3e1dd5e1 100644
--- a/src/core/TempColModels.h
+++ b/src/collision/TempColModels.h
diff --git a/src/collision/VuCollision.cpp b/src/collision/VuCollision.cpp
new file mode 100644
index 00000000..8828d2e1
--- /dev/null
+++ b/src/collision/VuCollision.cpp
@@ -0,0 +1,282 @@
+#include "common.h"
+#ifdef VU_COLLISION
+#include "VuVector.h"
+#include "VuCollision.h"
+
+#ifndef GTA_PS2
+int16 vi01;
+CVuVector vf01;
+CVuVector vf02;
+CVuVector vf03;
+
+CVuVector
+DistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)
+{
+ // center VF12
+ // p0 VF14
+ // line VF15
+ CVuVector ret; // VF16
+ CVuVector p1 = p0+line;
+ CVuVector dist0 = center - p0; // VF20
+ CVuVector dist1 = center - p1; // VF25
+ float lenSq = line.MagnitudeSqr(); // VF21
+ float distSq0 = dist0.MagnitudeSqr(); // VF22
+ float distSq1 = dist1.MagnitudeSqr();
+ float dot = DotProduct(dist0, line); // VF23
+ if(dot < 0.0f){
+ // not above line, closest to p0
+ ret = p0;
+ ret.w = distSq0;
+ return ret;
+ }
+ float t = dot/lenSq; // param of nearest point on infinite line
+ if(t > 1.0f){
+ // not above line, closest to p1
+ ret = p1;
+ ret.w = distSq1;
+ return ret;
+ }
+ // closest to line
+ ret = p0 + line*t;
+ ret.w = (ret - center).MagnitudeSqr();
+ return ret;
+}
+inline int SignFlags(const CVector &v)
+{
+ int f = 0;
+ if(v.x < 0.0f) f |= 1;
+ if(v.y < 0.0f) f |= 2;
+ if(v.z < 0.0f) f |= 4;
+ return f;
+}
+#endif
+
+extern "C" void
+LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
+ const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
+ const CVuVector &plane)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf13, 0x0(%1)\n"
+ "lqc2 vf14, 0x0(%2)\n"
+ "lqc2 vf15, 0x0(%3)\n"
+ "lqc2 vf16, 0x0(%4)\n"
+ "lqc2 vf17, 0x0(%5)\n"
+ "vcallms Vu0LineToTriangleCollisionStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
+ );
+#else
+ float dot0 = DotProduct(plane, p0);
+ float dot1 = DotProduct(plane, p1);
+ float dist0 = plane.w - dot0;
+ float dist1 = plane.w - dot1;
+
+ // if points are on the same side, no collision
+ if(dist0 * dist1 > 0.0f){
+ vi01 = 0;
+ return;
+ }
+
+ CVuVector diff = p1 - p0;
+ float t = dist0/(dot1 - dot0);
+ CVuVector p = p0 + diff*t;
+ p.w = 0.0f;
+ vf01 = p;
+ vf03.x = t;
+
+ // Check if point is inside
+ CVector cross1 = CrossProduct(p-v0, v1-v0);
+ CVector cross2 = CrossProduct(p-v1, v2-v1);
+ CVector cross3 = CrossProduct(p-v2, v0-v2);
+ // Only check relevant directions
+ int flagmask = 0;
+ if(Abs(plane.x) > 0.5f) flagmask |= 1;
+ if(Abs(plane.y) > 0.5f) flagmask |= 2;
+ if(Abs(plane.z) > 0.5f) flagmask |= 4;
+ int flags1 = SignFlags(cross1) & flagmask;
+ int flags2 = SignFlags(cross2) & flagmask;
+ int flags3 = SignFlags(cross3) & flagmask;
+ // inside if on the same side of all edges
+ if(flags1 != flags2 || flags1 != flags3){
+ vi01 = 0;
+ return;
+ }
+ vi01 = 1;
+ vf02 = plane;
+ return;
+#endif
+}
+
+extern "C" void
+LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf13, 0x0(%1)\n"
+ "lqc2 vf14, 0x0(%2)\n"
+ "lqc2 vf15, 0x10(%2)\n"
+ "lqc2 vf16, 0x20(%2)\n"
+ "lqc2 vf17, 0x30(%2)\n"
+ "vcallms Vu0LineToTriangleCollisionCompressedStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&p0), "r" (&p1), "r" (&tri)
+ );
+#else
+ CVuVector v0, v1, v2, plane;
+ v0.x = tri.v0[0]/128.0f;
+ v0.y = tri.v0[1]/128.0f;
+ v0.z = tri.v0[2]/128.0f;
+ v0.w = tri.v0[3]/128.0f;
+ v1.x = tri.v1[0]/128.0f;
+ v1.y = tri.v1[1]/128.0f;
+ v1.z = tri.v1[2]/128.0f;
+ v1.w = tri.v1[3]/128.0f;
+ v2.x = tri.v2[0]/128.0f;
+ v2.y = tri.v2[1]/128.0f;
+ v2.z = tri.v2[2]/128.0f;
+ v2.w = tri.v2[3]/128.0f;
+ plane.x = tri.plane[0]/4096.0f;
+ plane.y = tri.plane[1]/4096.0f;
+ plane.z = tri.plane[2]/4096.0f;
+ plane.w = tri.plane[3]/128.0f;
+ LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
+#endif
+}
+
+extern "C" void
+SphereToTriangleCollision(const CVuVector &sph,
+ const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
+ const CVuVector &plane)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf14, 0x0(%1)\n"
+ "lqc2 vf15, 0x0(%2)\n"
+ "lqc2 vf16, 0x0(%3)\n"
+ "lqc2 vf17, 0x0(%4)\n"
+ "vcallms Vu0SphereToTriangleCollisionStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
+ );
+#else
+ float planedist = DotProduct(plane, sph) - plane.w; // VF02
+ if(Abs(planedist) > sph.w){
+ vi01 = 0;
+ return;
+ }
+ // point on plane
+ CVuVector p = sph - planedist*plane;
+ p.w = 0.0f;
+ vf01 = p;
+ planedist = Abs(planedist);
+ // edges
+ CVuVector v01 = v1 - v0;
+ CVuVector v12 = v2 - v1;
+ CVuVector v20 = v0 - v2;
+ // VU code calculates normal again for some weird reason...
+ // Check sides of point
+ CVector cross1 = CrossProduct(p-v0, v01);
+ CVector cross2 = CrossProduct(p-v1, v12);
+ CVector cross3 = CrossProduct(p-v2, v20);
+ // Only check relevant directions
+ int flagmask = 0;
+ if(Abs(plane.x) > 0.1f) flagmask |= 1;
+ if(Abs(plane.y) > 0.1f) flagmask |= 2;
+ if(Abs(plane.z) > 0.1f) flagmask |= 4;
+ int nflags = SignFlags(plane) & flagmask;
+ int flags1 = SignFlags(cross1) & flagmask;
+ int flags2 = SignFlags(cross2) & flagmask;
+ int flags3 = SignFlags(cross3) & flagmask;
+ int testcase = 0;
+ CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
+ if(flags1 == nflags){
+ closest += v2;
+ testcase++;
+ }
+ if(flags2 == nflags){
+ closest += v0;
+ testcase++;
+ }
+ if(flags3 == nflags){
+ closest += v1;
+ testcase++;
+ }
+ if(testcase == 3){
+ // inside triangle - dist to plane already checked
+ vf02 = plane;
+ vf02.w = vf03.x = planedist;
+ vi01 = 1;
+ }else if(testcase == 1){
+ // outside two sides - closest to point opposide inside edge
+ vf01 = closest;
+ vf02 = sph - closest;
+ float distSq = vf02.MagnitudeSqr();
+ vi01 = sph.w*sph.w > distSq;
+ vf03.x = Sqrt(distSq);
+ vf02 *= 1.0f/vf03.x;
+ }else{
+ // inside two sides - closest to third edge
+ if(flags1 != nflags)
+ closest = DistanceBetweenSphereAndLine(sph, v0, v01);
+ else if(flags2 != nflags)
+ closest = DistanceBetweenSphereAndLine(sph, v1, v12);
+ else
+ closest = DistanceBetweenSphereAndLine(sph, v2, v20);
+ vi01 = sph.w*sph.w > closest.w;
+ vf01 = closest;
+ vf02 = sph - closest;
+ vf03.x = Sqrt(closest.w);
+ vf02 *= 1.0f/vf03.x;
+ }
+#endif
+}
+
+extern "C" void
+SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
+{
+#ifdef GTA_PS2
+ __asm__ volatile (
+ ".set noreorder\n"
+ "lqc2 vf12, 0x0(%0)\n"
+ "lqc2 vf14, 0x0(%1)\n"
+ "lqc2 vf15, 0x10(%1)\n"
+ "lqc2 vf16, 0x20(%1)\n"
+ "lqc2 vf17, 0x30(%1)\n"
+ "vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
+ ".set reorder\n"
+ :
+ : "r" (&sph), "r" (&tri)
+ );
+#else
+ CVuVector v0, v1, v2, plane;
+ v0.x = tri.v0[0]/128.0f;
+ v0.y = tri.v0[1]/128.0f;
+ v0.z = tri.v0[2]/128.0f;
+ v0.w = tri.v0[3]/128.0f;
+ v1.x = tri.v1[0]/128.0f;
+ v1.y = tri.v1[1]/128.0f;
+ v1.z = tri.v1[2]/128.0f;
+ v1.w = tri.v1[3]/128.0f;
+ v2.x = tri.v2[0]/128.0f;
+ v2.y = tri.v2[1]/128.0f;
+ v2.z = tri.v2[2]/128.0f;
+ v2.w = tri.v2[3]/128.0f;
+ plane.x = tri.plane[0]/4096.0f;
+ plane.y = tri.plane[1]/4096.0f;
+ plane.z = tri.plane[2]/4096.0f;
+ plane.w = tri.plane[3]/128.0f;
+ SphereToTriangleCollision(sph, v0, v1, v2, plane);
+#endif
+}
+#endif \ No newline at end of file
diff --git a/src/collision/VuCollision.h b/src/collision/VuCollision.h
new file mode 100644
index 00000000..29ca4cbf
--- /dev/null
+++ b/src/collision/VuCollision.h
@@ -0,0 +1,32 @@
+#pragma once
+
+
+struct VuTriangle
+{
+ // Compressed int16 but unpacked
+#ifdef GTA_PS2
+ uint128 v0;
+ uint128 v1;
+ uint128 v2;
+ uint128 plane;
+#else
+ int32 v0[4];
+ int32 v1[4];
+ int32 v2[4];
+ int32 plane[4];
+#endif
+};
+
+#ifndef GTA_PS2
+extern int16 vi01;
+extern CVuVector vf01;
+extern CVuVector vf02;
+extern CVuVector vf03;
+#endif
+
+extern "C" {
+void LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);
+void LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri);
+void SphereToTriangleCollision(const CVuVector &sph, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);
+void SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri);
+}
diff --git a/src/core/vu0Collision.dsm b/src/collision/vu0Collision.dsm
index 657c8b81..657c8b81 100644
--- a/src/core/vu0Collision.dsm
+++ b/src/collision/vu0Collision.dsm
diff --git a/src/core/vu0Collision_1.s b/src/collision/vu0Collision_1.s
index 055c8640..055c8640 100644
--- a/src/core/vu0Collision_1.s
+++ b/src/collision/vu0Collision_1.s
diff --git a/src/core/vu0Collision_2.s b/src/collision/vu0Collision_2.s
index 716c29ac..716c29ac 100644
--- a/src/core/vu0Collision_2.s
+++ b/src/collision/vu0Collision_2.s
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index 76ee47b0..627d7bad 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -2692,7 +2692,7 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
float distance = 30.0f;
CFire* pNearestFire = gFireManager.FindNearestFire(FindPlayerCoors(), &distance);
if (pNearestFire) {
- if (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 30000){
+ if (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 35000){
CStreaming::RequestModel(MI_FIRETRUCK, STREAMFLAGS_DEPENDENCY);
CStreaming::RequestModel(MI_FIREMAN, STREAMFLAGS_DONT_REMOVE);
if (CStreaming::HasModelLoaded(MI_FIRETRUCK) && CStreaming::HasModelLoaded(MI_FIREMAN)){
diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp
index 47b4586b..59c75dd4 100644
--- a/src/control/GameLogic.cpp
+++ b/src/control/GameLogic.cpp
@@ -19,6 +19,7 @@
#include "Fire.h"
#include "Script.h"
#include "Garages.h"
+#include "screendroplets.h"
uint8 CGameLogic::ActivePlayers;
@@ -117,6 +118,9 @@ CGameLogic::Update()
}
}
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
@@ -196,6 +200,9 @@ CGameLogic::Update()
}
}
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
@@ -245,6 +252,9 @@ CGameLogic::Update()
}
}
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index ab7024c7..c70d9592 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -129,7 +129,7 @@ int32 CGarages::PoliceCarsCollected;
CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
-int32 CGarages::AudioEntity = AEHANDLE_NONE;
+int32 hGarages = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde;
@@ -156,12 +156,12 @@ void CGarages::Init(void)
aCarsInSafeHouse2[i].Init();
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
aCarsInSafeHouse3[i].Init();
- AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);
- if (AudioEntity >= 0)
- DMAudio.SetEntityStatus(AudioEntity, 1);
+ hGarages = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);
+ if (hGarages >= 0)
+ DMAudio.SetEntityStatus(hGarages, 1);
AddOne(
- CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1,
- CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2,
+ CVector(CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1),
+ CVector(CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2),
GARAGE_CRUSHER, 0);
}
@@ -169,17 +169,17 @@ void CGarages::Init(void)
void CGarages::Shutdown(void)
{
NumGarages = 0;
- if (AudioEntity < 0)
+ if (hGarages < 0)
return;
- DMAudio.DestroyEntity(AudioEntity);
- AudioEntity = AEHANDLE_NONE;
+ DMAudio.DestroyEntity(hGarages);
+ hGarages = AEHANDLE_NONE;
}
#endif
void CGarages::Update(void)
{
static int GarageToBeTidied = 0;
-#ifndef PS2
+#ifndef GTA_PS2
if (CReplay::IsPlayingBack())
return;
#endif
@@ -202,23 +202,23 @@ 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(CVector p1, CVector p2, 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_fX1 = Min(p1.x, p2.x);
+ pGarage->m_fX2 = Max(p1.x, p2.x);
+ pGarage->m_fY1 = Min(p1.y, p2.y);
+ pGarage->m_fY2 = Max(p1.y, p2.y);
+ pGarage->m_fZ1 = Min(p1.z, p2.z);
+ pGarage->m_fZ2 = Max(p1.z, p2.z);
pGarage->m_pDoor1 = nil;
pGarage->m_pDoor2 = nil;
- pGarage->m_fDoor1Z = Z1;
- pGarage->m_fDoor2Z = Z1;
+ pGarage->m_fDoor1Z = p1.z;
+ pGarage->m_fDoor2Z = p1.z;
pGarage->m_eGarageType = type;
pGarage->m_bRecreateDoorOnNextRefresh = false;
pGarage->m_bRotatedDoor = false;
@@ -368,7 +368,7 @@ void CGarage::Update()
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_RESPRAY;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
CStats::CheckPointReachedSuccessfully();
}
UpdateDoorsHeight();
@@ -464,7 +464,7 @@ void CGarage::Update()
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_OPENEDCONTAINSCAR;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -510,7 +510,7 @@ void CGarage::Update()
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_SETUP_BOMB;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -575,7 +575,7 @@ void CGarage::Update()
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_OPENEDCONTAINSCAR;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -599,7 +599,8 @@ void CGarage::Update()
}
}
else if (!FindPlayerVehicle() && m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) &&
- !IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) {
+ !IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f) &&
+ !IsAnyOtherCarTouchingGarage(m_pTarget)) {
CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
m_eGarageState = GS_CLOSING;
@@ -609,7 +610,7 @@ void CGarage::Update()
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) {
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_bClosingWithoutTargetCar)
m_eGarageState = GS_FULLYCLOSED;
else {
@@ -639,7 +640,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -676,7 +677,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_pTarget) {
DestroyVehicleAndDriverAndPassengers(m_pTarget);
m_pTarget = nil;
@@ -723,7 +724,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -772,7 +773,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_pTarget) {
MarkThisCarAsCollectedForCraig(m_pTarget->GetModelIndex());
DestroyVehicleAndDriverAndPassengers(m_pTarget);
@@ -812,7 +813,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -833,7 +834,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
if (!IsGarageEmpty())
m_eGarageState = GS_OPENING;
@@ -844,7 +845,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -893,7 +894,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
}
else
@@ -913,7 +914,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateCrusherAngle();
break;
@@ -945,7 +946,7 @@ void CGarage::Update()
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) {
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_bClosingWithoutTargetCar)
m_eGarageState = GS_FULLYCLOSED;
else {
@@ -974,7 +975,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -994,7 +995,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -1014,7 +1015,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -1022,7 +1023,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -1045,8 +1046,8 @@ void CGarage::Update()
// Close car doors either if player is far, or if he is in vehicle and garage is full,
// or if player is very very far so that we can remove whatever is blocking garage door without him noticing
if ((distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR) ||
- !FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT) &&
- !IsAnyCarBlockingDoor()))
+ !FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT)) &&
+ !IsAnyCarBlockingDoor())
m_eGarageState = GS_CLOSING;
else if (FindPlayerVehicle() &&
CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >=
@@ -1064,7 +1065,7 @@ void CGarage::Update()
if (!IsPlayerOutsideGarage())
m_eGarageState = GS_OPENING;
else if (m_fDoorPos == 0.0f) {
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ DMAudio.PlayOneShot(hGarages, 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;
@@ -1111,7 +1112,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -1136,7 +1137,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -1152,7 +1153,7 @@ void CGarage::Update()
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);
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
}
UpdateDoorsHeight();
break;
@@ -1260,9 +1261,9 @@ 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 (m_fX1 - radius > pEntity->GetPosition().x || m_fX2 + radius < pEntity->GetPosition().x ||
+ m_fY1 - radius > pEntity->GetPosition().y || m_fY2 + radius < pEntity->GetPosition().y ||
+ m_fZ1 - radius > pEntity->GetPosition().z || m_fZ2 + radius < pEntity->GetPosition().z)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
@@ -1271,9 +1272,9 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
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;
+ return true;
}
- return true;
+ return false;
}
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
@@ -1387,7 +1388,9 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
if (!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
CWorld::Remove(pVehicle);
delete pVehicle;
- return; // WHY?
+#ifndef FIX_BUGS
+ return; // makes no sense
+#endif
}
}
}
@@ -1419,47 +1422,45 @@ void CGarages::PrintMessages()
float y_offset = SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(84.0f); // This is PC and results in text being written over some HUD elements
#endif
- if (MessageNumberInString2 < 0) {
- if (MessageNumberInString < 0) {
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
-#else
- CFont::PrintString(SCREEN_WIDTH / 2 - 2.0f, y_offset - 2.0f, TheText.Get(MessageIDString));
-#endif
- CFont::SetColor(CRGBA(89, 115, 150, 255));
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
- }
- else {
- CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);
+ if (MessageNumberInString2 >= 0) {
+ CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
+ CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
#else
- CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
+ CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
#endif
-
- CFont::SetColor(CRGBA(89, 115, 150, 255));
-
+ CFont::SetColor(CRGBA(89, 115, 150, 255));
#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
+ CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
#else
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
+ CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
#endif
- }
}
- else {
- CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
+ else if (MessageNumberInString >= 0) {
+ CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
#endif
+
CFont::SetColor(CRGBA(89, 115, 150, 255));
+
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
#endif
}
+ else {
+#ifdef FIX_BUGS
+ CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
+#else
+ CFont::PrintString(SCREEN_WIDTH / 2 - 2.0f, y_offset - 2.0f, TheText.Get(MessageIDString));
+#endif
+ CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
+ }
}
}
@@ -1534,41 +1535,54 @@ void CGarage::UpdateCrusherShake(float X, float Y)
m_pDoor2->GetMatrix().GetPosition().y -= Y;
}
-// This is dumb but there is no way to avoid goto. What was there originally even?
-static bool DoINeedToRefreshPointer(CEntity * pDoor, bool bIsDummy, uint8 nIndex)
+void CGarage::RefreshDoorPointers(bool bCreate)
{
- bool bNeedToFindDoorEntities = false;
- if (pDoor) {
- if (bIsDummy) {
- if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex((CDummy*)pDoor)))
- return true;
- if (nIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)pDoor) & 0x7F))
+ bool bNeedToFindDoorEntities = bCreate || m_bRecreateDoorOnNextRefresh;
+ m_bRecreateDoorOnNextRefresh = false;
+ if (m_pDoor1) {
+ if (m_bDoor1IsDummy) {
+ if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor1)))
bNeedToFindDoorEntities = true;
- if (!CGarages::IsModelIndexADoor(pDoor->GetModelIndex()))
- return true;
+ else {
+ if (m_bDoor1PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor1) & 0x7F))
+ bNeedToFindDoorEntities = true;
+ if (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex()))
+ bNeedToFindDoorEntities = true;
+ }
}
else {
- if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex((CObject*)pDoor)))
- return true;
- if (nIndex != (CPools::GetObjectPool()->GetIndex((CObject*)pDoor) & 0x7F))
+ if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor1)))
bNeedToFindDoorEntities = true;
- if (!CGarages::IsModelIndexADoor(pDoor->GetModelIndex()))
- return true;
+ else {
+ if (m_bDoor1PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor1) & 0x7F))
+ bNeedToFindDoorEntities = true;
+ if (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex()))
+ bNeedToFindDoorEntities = true;
+ }
+ }
+ }
+ if (m_pDoor2) {
+ if (m_bDoor2IsDummy) {
+ if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor2)))
+ bNeedToFindDoorEntities = true;
+ else {
+ if (m_bDoor2PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor2) & 0x7F))
+ bNeedToFindDoorEntities = true;
+ if (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex()))
+ bNeedToFindDoorEntities = true;
+ }
+ }
+ else {
+ if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor2)))
+ bNeedToFindDoorEntities = true;
+ else {
+ if (m_bDoor2PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor2) & 0x7F))
+ bNeedToFindDoorEntities = true;
+ if (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex()))
+ bNeedToFindDoorEntities = true;
+ }
}
}
- return bNeedToFindDoorEntities;
-}
-
-void CGarage::RefreshDoorPointers(bool bCreate)
-{
- bool bNeedToFindDoorEntities = true;
- if (!bCreate && !m_bRecreateDoorOnNextRefresh)
- bNeedToFindDoorEntities = false;
- m_bRecreateDoorOnNextRefresh = false;
- if (DoINeedToRefreshPointer(m_pDoor1, m_bDoor1IsDummy, m_bDoor1PoolIndex))
- bNeedToFindDoorEntities = true;
- if (DoINeedToRefreshPointer(m_pDoor2, m_bDoor2IsDummy, m_bDoor2PoolIndex))
- bNeedToFindDoorEntities = true;
if (bNeedToFindDoorEntities)
FindDoorsEntities();
}
diff --git a/src/control/Garages.h b/src/control/Garages.h
index 00020eb3..41b2afb7 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -198,7 +198,6 @@ class CGarages
static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
- static int32 AudioEntity;
static bool bCamShouldBeOutisde;
public:
@@ -208,7 +207,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(CVector pos1, CVector pos2, eGarageType type, int32 targetId);
static void ChangeGarageType(int16, eGarageType, int32);
static void PrintMessages(void);
static void TriggerMessage(const char* text, int16, uint16 time, int16);
diff --git a/src/control/NameGrid.cpp b/src/control/NameGrid.cpp
new file mode 100644
index 00000000..204e8b9c
--- /dev/null
+++ b/src/control/NameGrid.cpp
@@ -0,0 +1,87 @@
+#include "common.h"
+#include "NameGrid.h"
+
+// TODO: reverse mobile code
+
+CPlayerName::CPlayerName()
+{
+ // TODO
+}
+
+void
+CPlayerName::DisplayName(int)
+{
+ // TODO
+}
+
+CRow::CRow()
+{
+ // TODO
+}
+
+void
+CRow::SetLetter(int, wchar *)
+{
+ // TODO
+}
+
+CGrid::CGrid()
+{
+ // TODO
+}
+
+void
+CGrid::ProcessAnyLeftJustDown()
+{
+ unk_int2--;
+}
+
+void
+CGrid::ProcessAnyRightJustDown()
+{
+ unk_int2++;
+}
+
+void
+CGrid::ProcessAnyUpJustDown()
+{
+ unk_int1--;
+}
+
+void
+CGrid::ProcessAnyDownJustDown()
+{
+ unk_int1++;
+}
+
+void
+CGrid::AllDoneMakePlayerName()
+{
+ // TODO
+}
+
+void
+CGrid::ProcessDPadCrossJustDown()
+{
+ // TODO
+}
+
+void
+CGrid::DisplayGrid()
+{
+ // TODO
+}
+
+void
+CGrid::ProcessControllerInput()
+{
+ // TODO
+}
+
+void
+CGrid::Process()
+{
+ ProcessControllerInput();
+ DisplayGrid();
+ playerName.DisplayName(2 * playerName.unk_4c);
+} \ No newline at end of file
diff --git a/src/control/NameGrid.h b/src/control/NameGrid.h
new file mode 100644
index 00000000..d52cec73
--- /dev/null
+++ b/src/control/NameGrid.h
@@ -0,0 +1,53 @@
+#pragma once
+
+// TODO: reverse mobile code
+
+class CPlayerName
+{
+ friend class CGrid;
+
+ float x;
+ float y;
+ wchar unk_8[34];
+ int unk_4c;
+public:
+ CPlayerName();
+ void DisplayName(int);
+};
+
+class CRow
+{
+ friend class CGrid;
+
+ int unk_0;
+ int unk_4;
+ wchar unk_8[20];
+ int unk_30;
+public:
+ CRow();
+ void SetLetter(int, wchar *);
+};
+
+class CGrid
+{
+ CRow rows[5];
+ int unk_int1;
+ int unk_int2;
+ int unk_int3;
+ float unk_float1;
+ float unk_float2;
+ CPlayerName playerName;
+ char unk2[4];
+ char unk3[4];
+public:
+ CGrid();
+ void ProcessAnyLeftJustDown();
+ void ProcessAnyRightJustDown();
+ void ProcessAnyUpJustDown();
+ void ProcessAnyDownJustDown();
+ void AllDoneMakePlayerName();
+ void ProcessDPadCrossJustDown();
+ void DisplayGrid();
+ void ProcessControllerInput();
+ void Process();
+}; \ No newline at end of file
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index fb60250c..49e43c81 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -542,6 +542,22 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
int done, cont;
int tileStart;
+#ifndef MASTER
+ for (i = 0; i < m_numMapObjects-1; i++)
+ for (j = i+1; j < m_numMapObjects; j++) {
+ CTreadable *obj1 = m_mapObjects[i];
+ CTreadable *obj2 = m_mapObjects[j];
+ if (obj1->GetModelIndex() == obj2->GetModelIndex() &&
+ obj1->GetPosition().x == obj2->GetPosition().x && obj1->GetPosition().y == obj2->GetPosition().y && obj1->GetPosition().z == obj2->GetPosition().z &&
+ obj1->GetRight().x == obj2->GetRight().x && obj1->GetForward().x == obj2->GetForward().x && obj1->GetUp().x == obj2->GetUp().x &&
+ obj1->GetRight().y == obj2->GetRight().y && obj1->GetForward().y == obj2->GetForward().y && obj1->GetUp().y == obj2->GetUp().y &&
+ obj1->GetRight().z == obj2->GetRight().z && obj1->GetForward().z == obj2->GetForward().z && obj1->GetUp().z == obj2->GetUp().z) {
+ printf("THIS IS VERY BAD INDEED. FIX IMMEDIATELY!!!\n");
+ printf("Double road objects at the following coors: %f %f %f\n", obj1->GetPosition().x, obj1->GetPosition().y, obj1->GetPosition().z);
+ }
+ }
+#endif // !MASTER
+
oldNumPathNodes = m_numPathNodes;
oldNumLinks = m_numConnections;
@@ -1633,10 +1649,18 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
DoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1);
else
DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1);
+#ifdef FIX_BUGS
+ // dist has GenerationDistMultiplier as a factor, so our reference dist should have it too
+ if(type == PATH_CAR)
+ return dist < 160.0f*TheCamera.GenerationDistMultiplier;
+ else
+ return dist < 100.0f*TheCamera.GenerationDistMultiplier;
+#else
if(type == PATH_CAR)
return dist < 160.0f;
else
return dist < 100.0f;
+#endif
}
void
diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp
index ad29d4fb..c951e868 100644
--- a/src/control/Phones.cpp
+++ b/src/control/Phones.cpp
@@ -387,7 +387,7 @@ INITSAVEBUF
// Convert entity pointer to building pool index while saving
if (phone->m_pEntity) {
- phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex((CBuilding*)phone->m_pEntity) + 1);
+ phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1);
}
}
VALIDATESAVEBUF(*size)
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 950612ca..a6166554 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -353,11 +353,11 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
m_pObject->GetMatrix().UpdateRW();
m_pObject->UpdateRwFrame();
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z)
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false) && waterLevel >= m_pObject->GetPosition().z)
m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
break;
case PICKUP_FLOATINGPACKAGE_FLOATING:
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0))
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
m_pObject->GetMatrix().GetPosition().z = waterLevel;
m_pObject->GetMatrix().UpdateRW();
@@ -1013,7 +1013,7 @@ INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) {
CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
- buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1);
+ buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1);
}
WriteSaveBuf(buf, CollectedPickUpIndex);
@@ -1436,3 +1436,85 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer()
FindPlayerVehicle()->m_fForceMultiplier = 1.0f;
}
}
+
+void
+CPed::CreateDeadPedMoney(void)
+{
+ if (!CGame::nastyGame)
+ return;
+
+ int mi = GetModelIndex();
+
+ if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle)
+ return;
+
+ int money = CGeneral::GetRandomNumber() % 60;
+ if (money < 10)
+ return;
+
+ if (money == 43)
+ money = 700;
+
+ int pickupCount = money / 40 + 1;
+ 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;
+ if (found) {
+ CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
+ }
+ }
+}
+
+void
+CPed::CreateDeadPedWeaponPickups(void)
+{
+ bool found = false;
+ float angleToPed;
+ CVector pickupPos;
+
+ if (bInVehicle)
+ return;
+
+ 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.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+
+ CVector pedPos = GetPosition();
+ pedPos.z += 0.3f;
+
+ CVector pedToPickup = pickupPos - pedPos;
+ float distance = pedToPickup.Magnitude();
+
+ // outer edge of pickup
+ distance = (distance + 0.3f) / 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 (found)
+ CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon]));
+ }
+ ClearWeapons();
+} \ No newline at end of file
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index f21703ac..757af0a9 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1,5 +1,5 @@
#include "common.h"
-
+#ifdef GTA_REPLAY
#include "AnimBlendAssociation.h"
#include "Boat.h"
#include "SpecialFX.h"
@@ -1585,3 +1585,4 @@ void CReplay::Display()
if (Mode == MODE_PLAYBACK)
CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY"));
}
+#endif
diff --git a/src/control/Replay.h b/src/control/Replay.h
index 66bee3bf..cb58a602 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -63,6 +63,12 @@ struct CStoredDetailedAnimationState
void PlayReplayFromHD(void);
+#ifdef GTA_REPLAY
+#define REPLAY_STUB
+#else
+#define REPLAY_STUB {}
+#endif
+
class CReplay
{
enum {
@@ -273,20 +279,24 @@ private:
#endif
public:
- static void Init(void);
- static void DisableReplays(void);
- static void EnableReplays(void);
- static void Update(void);
- static void FinishPlayback(void);
- static void EmptyReplayBuffer(void);
- static void Display(void);
- static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene);
- static void StreamAllNecessaryCarsAndPeds(void);
- static bool ShouldStandardCameraBeProcessed(void);
+ static void Init(void) REPLAY_STUB;
+ static void DisableReplays(void) REPLAY_STUB;
+ static void EnableReplays(void) REPLAY_STUB;
+ static void Update(void) REPLAY_STUB;
+ static void FinishPlayback(void) REPLAY_STUB;
+ static void EmptyReplayBuffer(void) REPLAY_STUB;
+ static void Display(void) REPLAY_STUB;
+ static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) REPLAY_STUB;
+ static void StreamAllNecessaryCarsAndPeds(void) REPLAY_STUB;
+#ifndef GTA_REPLAY
+ static bool ShouldStandardCameraBeProcessed(void) { return true; }
+ static bool IsPlayingBack() { return false; }
+ static bool IsPlayingBackFromFile() { return false; }
+#else
+ static bool ShouldStandardCameraBeProcessed(void);
static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }
static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }
-
private:
static void RecordThisFrame(void);
static void StorePedUpdate(CPed *ped, int id);
@@ -314,4 +324,5 @@ private:
/* Absolute nonsense, but how could this function end up being outside of class? */
friend void PlayReplayFromHD(void);
+#endif
};
diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp
index a6482d04..4ca18c3b 100644
--- a/src/control/Restart.cpp
+++ b/src/control/Restart.cpp
@@ -81,7 +81,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
}
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
- float fMinDist = 16000000.0f;
+ float fMinDist = SQR(4000.0f);
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
@@ -128,7 +128,7 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo
}
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
- float fMinDist = 16000000.0f;
+ float fMinDist = SQR(4000.0f);
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp
index 154fe603..8224c1d4 100644
--- a/src/control/SceneEdit.cpp
+++ b/src/control/SceneEdit.cpp
@@ -1,7 +1,7 @@
#include "common.h"
#include "SceneEdit.h"
-
+#ifdef GTA_SCENE_EDIT
#include "Automobile.h"
#include "Camera.h"
#include "CarCtrl.h"
@@ -1096,3 +1096,4 @@ bool CSceneEdit::SelectWeapon(void)
}
return false;
}
+#endif
diff --git a/src/control/SceneEdit.h b/src/control/SceneEdit.h
index 6dcefa31..7c8fb98a 100644
--- a/src/control/SceneEdit.h
+++ b/src/control/SceneEdit.h
@@ -1,5 +1,5 @@
#pragma once
-
+#ifdef GTA_SCENE_EDIT
class CPed;
class CVehicle;
@@ -93,3 +93,4 @@ public:
static void SelectVehicle(void);
static bool SelectWeapon(void);
};
+#endif
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 6bde6b87..dbd477e2 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -4,94 +4,40 @@
#include "ScriptCommands.h"
#include "AnimBlendAssociation.h"
+#include "AudioManager.h"
#include "Boat.h"
-#include "BulletInfo.h"
#include "Camera.h"
-#include "CarAI.h"
#include "CarCtrl.h"
-#include "CarGen.h"
#include "CivilianPed.h"
#include "Clock.h"
#include "CopPed.h"
-#include "Coronas.h"
-#include "Cranes.h"
-#include "Credits.h"
-#include "CutsceneMgr.h"
#include "Debug.h"
#include "DMAudio.h"
-#include "Darkel.h"
#include "EmergencyPed.h"
-#include "Explosion.h"
#include "FileMgr.h"
-#include "Fire.h"
#include "Frontend.h"
-#include "Gangs.h"
-#include "Garages.h"
#include "General.h"
-#ifdef MISSION_REPLAY
-#include "GenericGameStorage.h"
-#endif
#include "HandlingMgr.h"
#include "Heli.h"
#include "Hud.h"
#include "Lines.h"
#include "Messages.h"
-#include "ModelIndices.h"
#include "Pad.h"
-#include "Particle.h"
-#include "ParticleObject.h"
-#include "PedRoutes.h"
-#include "Phones.h"
#include "Pickups.h"
-#include "Plane.h"
-#include "PlayerInfo.h"
-#include "PlayerPed.h"
-#include "PointLights.h"
#include "Pools.h"
#include "Population.h"
-#include "PowerPoints.h"
-#include "ProjectileInfo.h"
-#include "Radar.h"
-#include "Record.h"
#include "Remote.h"
#include "Replay.h"
-#include "Restart.h"
-#include "RpAnimBlend.h"
-#include "Rubbish.h"
-#include "Shadows.h"
-#include "SpecialFX.h"
#include "Stats.h"
#include "Streaming.h"
-#include "Text.h"
-#include "TxdStore.h"
#include "User.h"
-#include "WaterLevel.h"
+#include "Wanted.h"
#include "Weather.h"
-#include "World.h"
#include "Zones.h"
-#include "main.h"
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#include <stdarg.h>
#endif
-#define PICKUP_PLACEMENT_OFFSET 0.5f
-#define PED_FIND_Z_OFFSET 5.0f
-
-#define SPHERE_MARKER_R 0
-#define SPHERE_MARKER_G 128
-#define SPHERE_MARKER_B 255
-#define SPHERE_MARKER_A 128
-#define SPHERE_MARKER_PULSE_PERIOD 2048
-#define SPHERE_MARKER_PULSE_FRACTION 0.1f
-
-#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
-#define METERS_IN_FOOT 0.3048f
-#define FEET_IN_METER 3.28084f
-#else
-#define METERS_IN_FOOT 0.3f
-#define FEET_IN_METER 3.33f
-#endif
-
uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE];
CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS];
int32 CTheScripts::BaseBriefIdForContact[MAX_NUM_CONTACTS];
@@ -1327,7 +1273,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
REGISTER_COMMAND(COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
#endif
#endif
@@ -1362,7 +1308,7 @@ static void PrintToLog(const char* format, ...)
#endif
-static void FlushLog()
+void FlushLog()
{
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2
@@ -1372,7 +1318,6 @@ static void FlushLog()
#endif
}
-#define script_assert(_Expression) FlushLog(); assert(_Expression);
const uint32 CRunningScript::nSaveStructSize =
#ifdef COMPATIBLE_SAVES
@@ -2696,8 +2641,10 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
#ifdef MISSION_REPLAY
if (m_bMissionFlag) {
CPlayerInfo* pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus];
+#if 0 // makeing autosave is pointless and is a bit buggy
if (pPlayerInfo->m_pPed->GetPedState() != PED_DEAD && pPlayerInfo->m_WBState == WBSTATE_PLAYING && !m_bDeatharrestExecuted)
SaveGameForPause(1);
+#endif
oldTargetX = oldTargetY = 0.0f;
if (AllowMissionReplay == 1)
AllowMissionReplay = 2;
@@ -4367,8860 +4314,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
return -1;
}
-int8 CRunningScript::ProcessCommands300To399(int32 command)
-{
- switch (command) {
- /* Not implemented.
- case COMMAND_SET_CHAR_INVINCIBLE:
- case COMMAND_SET_PLAYER_INVINCIBLE:
- case COMMAND_SET_CHAR_GRAPHIC_TYPE:
- case COMMAND_SET_PLAYER_GRAPHIC_TYPE:
- */
- case COMMAND_HAS_PLAYER_BEEN_ARRESTED:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED);
- return 0;
- /* Not implemented.
- case COMMAND_STOP_CHAR_DRIVING:
- case COMMAND_KILL_CHAR:
- case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR:
- case COMMAND_SET_CHAR_OCCUPATION:
- */
- case COMMAND_CHANGE_CAR_LOCK:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1];
- return 0;
- }
- case COMMAND_SHAKE_CAM_WITH_POINT:
- CollectParameters(&m_nIp, 4);
- TheCamera.CamShake(ScriptParams[0] / 1000.0f,
- *(float*)&ScriptParams[1],
- *(float*)&ScriptParams[2],
- *(float*)&ScriptParams[3]);
- return 0;
- case COMMAND_IS_CAR_MODEL:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]);
- return 0;
- }
- /* Not implemented.
- case COMMAND_IS_CAR_REMAP:
- case COMMAND_HAS_CAR_JUST_SUNK:
- case COMMAND_SET_CAR_NO_COLLIDE:
- */
- case COMMAND_IS_CAR_DEAD_IN_AREA_2D:
- {
- CollectParameters(&m_nIp, 6);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- float x1 = *(float*)&ScriptParams[1];
- float y1 = *(float*)&ScriptParams[2];
- float x2 = *(float*)&ScriptParams[3];
- float y2 = *(float*)&ScriptParams[4];
- UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED &&
- pVehicle->IsWithinArea(x1, y1, x2, y2));
- if (ScriptParams[5])
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag)
- CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
- return 0;
- }
- case COMMAND_IS_CAR_DEAD_IN_AREA_3D:
- {
- CollectParameters(&m_nIp, 8);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- float x1 = *(float*)&ScriptParams[1];
- float y1 = *(float*)&ScriptParams[2];
- float z1 = *(float*)&ScriptParams[3];
- float x2 = *(float*)&ScriptParams[4];
- float y2 = *(float*)&ScriptParams[5];
- float z2 = *(float*)&ScriptParams[6];
- UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED &&
- pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));
- if (ScriptParams[7])
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2);
- if (CTheScripts::DbgFlag)
- CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);
- return 0;
- }
- /* Not implemented.
- case COMMAND_IS_TRAILER_ATTACHED:
- case COMMAND_IS_CAR_ON_TRAILER:
- case COMMAND_HAS_CAR_GOT_WEAPON:
- case COMMAND_PARK:
- case COMMAND_HAS_PARK_FINISHED:
- case COMMAND_KILL_ALL_PASSENGERS:
- case COMMAND_SET_CAR_BULLETPROOF:
- case COMMAND_SET_CAR_FLAMEPROOF:
- case COMMAND_SET_CAR_ROCKETPROOF:
- case COMMAND_IS_CARBOMB_ACTIVE:
- case COMMAND_GIVE_CAR_ALARM:
- case COMMAND_PUT_CAR_ON_TRAILER:
- */
- case COMMAND_IS_CAR_CRUSHED:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0]));
- return 0;
- /* Not implemented.
- case COMMAND_CREATE_GANG_CAR:
- */
- case COMMAND_CREATE_CAR_GENERATOR:
- CollectParameters(&m_nIp, 12);
- ScriptParams[0] = CTheCarGenerators::CreateCarGenerator(
- *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7],
- ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_SWITCH_CAR_GENERATOR:
- {
- CollectParameters(&m_nIp, 2);
- CCarGenerator* pCarGen = &CTheCarGenerators::CarGeneratorArray[ScriptParams[0]];
- if (ScriptParams[1] == 0){
- pCarGen->SwitchOff();
- }else if (ScriptParams[1] <= 100){
- pCarGen->SwitchOn();
- pCarGen->SetUsesRemaining(ScriptParams[1]);
- }else{
- pCarGen->SwitchOn();
- }
- return 0;
- }
- case COMMAND_ADD_PAGER_MESSAGE:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 3);
- CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- case COMMAND_DISPLAY_ONSCREEN_TIMER:
- {
- script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
- m_nIp++;
- CUserDisplay::OnscnTimer.AddClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp), nil);
- return 0;
- }
- case COMMAND_CLEAR_ONSCREEN_TIMER:
- {
- script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
- m_nIp++;
- CUserDisplay::OnscnTimer.ClearClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp));
- return 0;
- }
- case COMMAND_DISPLAY_ONSCREEN_COUNTER:
- {
- script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
- m_nIp++;
- uint16 counter = CTheScripts::Read2BytesFromScript(&m_nIp);
- CollectParameters(&m_nIp, 1);
- CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil);
- return 0;
- }
- case COMMAND_CLEAR_ONSCREEN_COUNTER:
- {
- script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
- m_nIp++;
- CUserDisplay::OnscnTimer.ClearCounter((uint16)CTheScripts::Read2BytesFromScript(&m_nIp));
- return 0;
- }
- case COMMAND_SET_ZONE_CAR_INFO:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 16);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(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]);
- return 0;
- }
- /* Not implemented.
- case COMMAND_IS_CHAR_IN_GANG_ZONE:
- */
- case COMMAND_IS_CHAR_IN_ZONE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- 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)));
- return 0;
- }
- 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);
- // ScriptParams[0] is unused.
- TheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
- return 0;
- }
- case COMMAND_POINT_CAMERA_AT_CAR:
- {
- CollectParameters(&m_nIp, 3);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
- return 0;
- }
- case COMMAND_POINT_CAMERA_AT_CHAR:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
- return 0;
- }
- case COMMAND_RESTORE_CAMERA:
- TheCamera.Restore();
- return 0;
- case COMMAND_SHAKE_PAD:
- CPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]);
- return 0;
- case COMMAND_SET_ZONE_PED_INFO:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 10);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- 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]);
- return 0;
- }
- case COMMAND_SET_TIME_SCALE:
- CollectParameters(&m_nIp, 1);
- CTimer::SetTimeScale(*(float*)&ScriptParams[0]);
- return 0;
- case COMMAND_IS_CAR_IN_AIR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle && pVehicle->IsCar());
- CAutomobile* pCar = (CAutomobile*)pVehicle;
- UpdateCompareFlag(pCar->GetAllWheelsOffGround());
- return 0;
- }
- case COMMAND_SET_FIXED_CAMERA_POSITION:
- {
- CollectParameters(&m_nIp, 6);
- TheCamera.SetCamPositionForFixedMode(
- CVector(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]),
- CVector(*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5]));
- return 0;
- }
- case COMMAND_POINT_CAMERA_AT_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);
- TheCamera.TakeControlNoEntity(pos, ScriptParams[3], CAMCONTROL_SCRIPT);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_CAR_OLD:
- {
- CollectParameters(&m_nIp, 3);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- // Useless call.
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_CHAR_OLD:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- // Useless call.
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_OBJECT_OLD:
- {
- CollectParameters(&m_nIp, 3);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- // Useless call.
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_REMOVE_BLIP:
- CollectParameters(&m_nIp, 1);
- CRadar::ClearBlip(ScriptParams[0]);
- return 0;
- case COMMAND_CHANGE_BLIP_COLOUR:
- CollectParameters(&m_nIp, 2);
- CRadar::ChangeBlipColour(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_DIM_BLIP:
- CollectParameters(&m_nIp, 2);
- CRadar::ChangeBlipBrightness(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_ADD_BLIP_FOR_COORD_OLD:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- // Useless call
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- ScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_CHANGE_BLIP_SCALE:
- CollectParameters(&m_nIp, 2);
- CRadar::ChangeBlipScale(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_SET_FADING_COLOUR:
- CollectParameters(&m_nIp, 3);
- TheCamera.SetFadeColour(ScriptParams[0], ScriptParams[1], ScriptParams[2]);
- return 0;
- case COMMAND_DO_FADE:
- CollectParameters(&m_nIp, 2);
- TheCamera.Fade(ScriptParams[0] / 1000.0f, ScriptParams[1]);
- return 0;
- case COMMAND_GET_FADING_STATUS:
- UpdateCompareFlag(TheCamera.GetFading());
- return 0;
- case COMMAND_ADD_HOSPITAL_RESTART:
- {
- CollectParameters(&m_nIp, 4);
- CVector pos = *(CVector*)&ScriptParams[0];
- float angle = *(float*)&ScriptParams[3];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CRestart::AddHospitalRestartPoint(pos, angle);
- return 0;
- }
- case COMMAND_ADD_POLICE_RESTART:
- {
- CollectParameters(&m_nIp, 4);
- CVector pos = *(CVector*)&ScriptParams[0];
- float angle = *(float*)&ScriptParams[3];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CRestart::AddPoliceRestartPoint(pos, angle);
- return 0;
- }
- case COMMAND_OVERRIDE_NEXT_RESTART:
- {
- CollectParameters(&m_nIp, 4);
- CVector pos = *(CVector*)&ScriptParams[0];
- float angle = *(float*)&ScriptParams[3];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CRestart::OverrideNextRestart(pos, angle);
- return 0;
- }
- case COMMAND_DRAW_SHADOW:
- {
- CollectParameters(&m_nIp, 10);
- CVector pos = *(CVector*)&ScriptParams[1];
- float angle = *(float*)&ScriptParams[4];
- float length = *(float*)&ScriptParams[5];
- float x, y;
- if (angle != 0.0f){
- y = cos(angle) * length;
- x = sin(angle) * length;
- }else{
- y = length;
- x = 0.0f;
- }
- float frontX = -x;
- float frontY = y;
- float sideX = y;
- float sideY = x;
- /* Not very nicely named intermediate variables. */
- CShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY,
- ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]);
- return 0;
- }
- case COMMAND_GET_PLAYER_HEADING:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_PLAYER_HEADING:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- if (pPed->bInVehicle){
- // Is script_assertion required?
- return 0;
- }
- pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);
- pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
- return 0;
- }
- case COMMAND_GET_CHAR_HEADING:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CHAR_HEADING:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- if (pPed->bInVehicle) {
- // Is script_assertion required?
- return 0;
- }
- pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);
- pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
- return 0;
- }
- case COMMAND_GET_CAR_HEADING:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- float angle = pVehicle->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CAR_HEADING:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
- return 0;
- }
- case COMMAND_GET_OBJECT_HEADING:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- float angle = pObject->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_OBJECT_HEADING:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CWorld::Remove(pObject);
- pObject->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
- pObject->GetMatrix().UpdateRW();
- pObject->UpdateRwFrame();
- CWorld::Add(pObject);
- return 0;
- }
- case COMMAND_IS_PLAYER_TOUCHING_OBJECT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- script_assert(pObject);
- CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed;
- UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));
- return 0;
- }
- case COMMAND_IS_CHAR_TOUCHING_OBJECT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- script_assert(pObject);
- CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed;
- UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));
- return 0;
- }
- case COMMAND_SET_PLAYER_AMMO:
- {
- CollectParameters(&m_nIp, 3);
- CWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- case COMMAND_SET_CHAR_AMMO:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- /* Not implemented.
- case COMMAND_SET_CAR_AMMO:
- case COMMAND_LOAD_CAMERA_SPLINE:
- case COMMAND_MOVE_CAMERA_ALONG_SPLINE:
- case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE:
- */
- case COMMAND_DECLARE_MISSION_FLAG:
- CTheScripts::OnAMissionFlag = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp);
- return 0;
- case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
- CollectParameters(&m_nIp, 1);
- CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = (uint16)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_IS_PLAYER_HEALTH_GREATER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]);
- return 0;
- }
- case COMMAND_IS_CHAR_HEALTH_GREATER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]);
- return 0;
- }
- case COMMAND_IS_CAR_HEALTH_GREATER:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->m_fHealth > ScriptParams[1]);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- // Useless call.
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);
- CRadar::ChangeBlipScale(handle, 3);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_CHAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- // Useless call.
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);
- CRadar::ChangeBlipScale(handle, 3);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_OBJECT:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- // Useless call.
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);
- CRadar::ChangeBlipScale(handle, 3);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_CONTACT_POINT:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- // Useless call
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
- CRadar::ChangeBlipScale(handle, 3);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_COORD:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- // Useless call
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
- CRadar::ChangeBlipScale(handle, 3);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_CHANGE_BLIP_DISPLAY:
- CollectParameters(&m_nIp, 2);
- CRadar::ChangeBlipDisplay(ScriptParams[0], (eBlipDisplay)ScriptParams[1]);
- return 0;
- case COMMAND_ADD_ONE_OFF_SOUND:
- {
- CollectParameters(&m_nIp, 4);
- switch (ScriptParams[3]) {
- case SCRIPT_SOUND_EVIDENCE_PICKUP:
- DMAudio.PlayFrontEndSound(SOUND_EVIDENCE_PICKUP, 0);
- return 0;
- case SCRIPT_SOUND_UNLOAD_GOLD:
- DMAudio.PlayFrontEndSound(SOUND_UNLOAD_GOLD, 0);
- return 0;
- case SCRIPT_SOUND_PART_MISSION_COMPLETE:
- DMAudio.PlayFrontEndSound(SOUND_PART_MISSION_COMPLETE, 0);
- return 0;
- case SCRIPT_SOUND_RACE_START_3:
- DMAudio.PlayFrontEndSound(SOUND_RACE_START_3, 0);
- return 0;
- case SCRIPT_SOUND_RACE_START_2:
- DMAudio.PlayFrontEndSound(SOUND_RACE_START_2, 0);
- return 0;
- case SCRIPT_SOUND_RACE_START_1:
- DMAudio.PlayFrontEndSound(SOUND_RACE_START_1, 0);
- return 0;
- case SCRIPT_SOUND_RACE_START_GO:
- DMAudio.PlayFrontEndSound(SOUND_RACE_START_GO, 0);
- return 0;
- default:
- break;
- }
-#ifdef FIX_BUGS
- /* BUG: if audio is not initialized, this object will not be freed. */
- if (!DMAudio.IsAudioInitialised())
- return 0;
-#endif
- cAudioScriptObject* obj = new cAudioScriptObject();
- obj->Posn = *(CVector*)&ScriptParams[0];
- obj->AudioId = ScriptParams[3];
- obj->AudioEntity = AEHANDLE_NONE;
- DMAudio.CreateOneShotScriptObject(obj);
- return 0;
- }
- case COMMAND_ADD_CONTINUOUS_SOUND:
- {
- CollectParameters(&m_nIp, 4);
- cAudioScriptObject* obj = new cAudioScriptObject();
- obj->Posn = *(CVector*)&ScriptParams[0];
- obj->AudioId = ScriptParams[3];
- obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj);
- ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_REMOVE_SOUND:
- {
- CollectParameters(&m_nIp, 1);
- cAudioScriptObject* obj = CPools::GetAudioScriptObjectPool()->GetAt(ScriptParams[0]);
- if (!obj){
- debug("REMOVE_SOUND - Sound doesn't exist\n");
- return 0;
- }
- DMAudio.DestroyLoopingScriptObject(obj->AudioEntity);
- delete obj;
- return 0;
- }
- case COMMAND_IS_CAR_STUCK_ON_ROOF:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(CTheScripts::UpsideDownCars.HasCarBeenUpsideDownForAWhile(ScriptParams[0]));
- return 0;
- }
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands400To499(int32 command)
-{
- switch (command) {
- case COMMAND_ADD_UPSIDEDOWN_CAR_CHECK:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CTheScripts::UpsideDownCars.AddCarToCheck(ScriptParams[0]);
- return 0;
- }
- case COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CTheScripts::UpsideDownCars.RemoveCarFromCheck(ScriptParams[0]);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GUARD_SPOT:
- {
- CollectParameters(&m_nIp, 4);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GUARD_AREA:
- {
- CollectParameters(&m_nIp, 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- float infX = *(float*)&ScriptParams[1];
- float infY = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- if (infX > supX){
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[1];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[2];
- }
- CVector pos;
- pos.x = (infX + supX) / 2;
- pos.y = (infY + supY) / 2;
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float radius = Max(pos.x - infX, pos.y - infY);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos, radius);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_WAIT_IN_CAR);
- return 0;
- }
- case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
- PlayerInAreaCheckCommand(command, &m_nIp);
- return 0;
- case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
- CharInAreaCheckCommand(command, &m_nIp);
- return 0;
- case COMMAND_IS_CAR_STOPPED_IN_AREA_2D:
- case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
- CarInAreaCheckCommand(command, &m_nIp);
- return 0;
- case COMMAND_LOCATE_CAR_2D:
- case COMMAND_LOCATE_STOPPED_CAR_2D:
- case COMMAND_LOCATE_CAR_3D:
- case COMMAND_LOCATE_STOPPED_CAR_3D:
- LocateCarCommand(command, &m_nIp);
- return 0;
- case COMMAND_GIVE_WEAPON_TO_PLAYER:
- {
- CollectParameters(&m_nIp, 3);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- pPed->m_nSelectedWepSlot = pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- case COMMAND_GIVE_WEAPON_TO_CHAR:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]));
- if (pPed->bInVehicle)
- pPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);
- return 0;
- }
- /* Not implemented */
- //case COMMAND_GIVE_WEAPON_TO_CAR:
- case COMMAND_SET_PLAYER_CONTROL:
- {
- 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);
- }
- }else{
- pPlayer->MakePlayerSafe(true);
- if (strcmp(m_abScriptName, "camera") == 0){
- pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pPlayer->m_pPed->SetTurnSpeed(0.0f, 0.0f, 0.0f);
- CAnimManager::BlendAnimation((RpClump*)pPlayer->m_pPed->m_rwObject, pPlayer->m_pPed->m_animGroup, ANIM_IDLE_STANCE, 1000.0f);
- }
- }
- return 0;
- }
- case COMMAND_FORCE_WEATHER:
- CollectParameters(&m_nIp, 1);
- CWeather::ForceWeather(ScriptParams[0]);
- return 0;
- case COMMAND_FORCE_WEATHER_NOW:
- CollectParameters(&m_nIp, 1);
- CWeather::ForceWeatherNow(ScriptParams[0]);
- return 0;
- case COMMAND_RELEASE_WEATHER:
- CWeather::ReleaseWeather();
- return 0;
- case COMMAND_SET_CURRENT_PLAYER_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++){
- if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
- pPed->m_nSelectedWepSlot = i;
- }
- return 0;
- }
- case COMMAND_SET_CURRENT_CHAR_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
- if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
- pPed->SetCurrentWeapon(i);
- }
- return 0;
- }
- /* Not implemented */
- //case COMMAND_SET_CURRENT_CAR_WEAPON:
- case COMMAND_GET_OBJECT_COORDINATES:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- *(CVector*)&ScriptParams[0] = pObject->GetPosition();
- StoreParameters(&m_nIp, 3);
- return 0;
- }
- case COMMAND_SET_OBJECT_COORDINATES:
- {
- CollectParameters(&m_nIp, 4);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pObject->Teleport(pos);
- CTheScripts::ClearSpaceForMissionEntity(pos, pObject);
- return 0;
- }
- case COMMAND_GET_GAME_TIMER:
- ScriptParams[0] = CTimer::GetTimeInMilliseconds();
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_TURN_CHAR_TO_FACE_COORD:
- {
- CollectParameters(&m_nIp, 4);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle;
- CVector pos;
- if (pPed->bInVehicle)
- pVehicle = pPed->m_pMyVehicle;
- else
- pVehicle = nil;
- if (pVehicle)
- pos = pVehicle->GetPosition();
- else
- pos = pPed->GetPosition();
- float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]);
- heading += HALFPI;
- if (heading > TWOPI)
- heading -= TWOPI;
- if (!pVehicle){
- pPed->m_fRotationCur = heading;
- pPed->m_fRotationDest = heading;
- pPed->SetHeading(heading);
- }
- return 0;
- }
- case COMMAND_TURN_PLAYER_TO_FACE_COORD:
- {
- CollectParameters(&m_nIp, 4);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CVehicle* pVehicle;
- CVector pos;
- if (pPed->bInVehicle)
- pVehicle = pPed->m_pMyVehicle;
- else
- pVehicle = nil;
- if (pVehicle)
- pos = pVehicle->GetPosition();
- else
- pos = pPed->GetPosition();
- float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]);
- heading += HALFPI;
- if (heading > TWOPI)
- heading -= TWOPI;
- if (!pVehicle) {
- pPed->m_fRotationCur = heading;
- pPed->m_fRotationDest = heading;
- pPed->SetHeading(heading);
- }
- return 0;
- }
- case COMMAND_STORE_WANTED_LEVEL:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- ScriptParams[0] = pPed->m_pWanted->m_nWantedLevel;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_IS_CAR_STOPPED:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(CTheScripts::IsVehicleStopped(pVehicle));
- return 0;
- }
- case COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- CTheScripts::CleanUpThisPed(pPed);
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
- return 0;
- }
- case COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- CTheScripts::CleanUpThisVehicle(pVehicle);
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
- return 0;
- }
- case COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- CTheScripts::CleanUpThisObject(pObject);
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
- return 0;
- }
- case COMMAND_DONT_REMOVE_CHAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
- return 0;
- }
- case COMMAND_DONT_REMOVE_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
- return 0;
- }
- case COMMAND_DONT_REMOVE_OBJECT:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
- return 0;
- }
- case COMMAND_CREATE_CHAR_AS_PASSENGER:
- {
- CollectParameters(&m_nIp, 4);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- switch (ScriptParams[2]) {
- case MI_COP:
- if (ScriptParams[1] == PEDTYPE_COP)
- ScriptParams[2] = COP_STREET;
- break;
- case MI_SWAT:
- if (ScriptParams[1] == PEDTYPE_COP)
- ScriptParams[2] = COP_SWAT;
- break;
- case MI_FBI:
- if (ScriptParams[1] == PEDTYPE_COP)
- ScriptParams[2] = COP_FBI;
- break;
- case MI_ARMY:
- if (ScriptParams[1] == PEDTYPE_COP)
- ScriptParams[2] = COP_ARMY;
- break;
- case MI_MEDIC:
- if (ScriptParams[1] == PEDTYPE_EMERGENCY)
- ScriptParams[2] = PEDTYPE_EMERGENCY;
- break;
- case MI_FIREMAN:
- if (ScriptParams[1] == PEDTYPE_FIREMAN)
- ScriptParams[2] = PEDTYPE_FIREMAN;
- break;
- default:
- break;
- }
- CPed* pPed;
- if (ScriptParams[1] == PEDTYPE_COP)
- pPed = new CCopPed((eCopType)ScriptParams[2]);
- else if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN)
- pPed = new CEmergencyPed(ScriptParams[2]);
- else
- pPed = new CCivilianPed((ePedType)ScriptParams[1], ScriptParams[2]);
- pPed->CharCreatedBy = MISSION_CHAR;
- pPed->bRespondsToThreats = false;
- pPed->bAllowMedicsToReviveMe = false;
- pPed->SetPosition(pVehicle->GetPosition());
- pPed->SetOrientation(0.0f, 0.0f, 0.0f);
- pPed->SetPedState(PED_DRIVING);
- CPopulation::ms_nTotalMissionPeds++;
- if (ScriptParams[3] >= 0)
- pVehicle->AddPassenger(pPed, ScriptParams[3]);
- else
- pVehicle->AddPassenger(pPed);
- pPed->m_pMyVehicle = pVehicle;
- pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
- pPed->bInVehicle = true;
- 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->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
- CWorld::Add(pPed);
- 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_OBJ_KILL_CHAR_ON_FOOT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_LEAVE_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pVehicle);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
- return 0;
- }
- /* Not implemented.
- case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR:
- case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
- case COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT:
- */
- case COMMAND_SET_CHAR_OBJ_DESTROY_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT:
- {
- CollectParameters(&m_nIp, 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- float infX = *(float*)&ScriptParams[1];
- float infY = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[1];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[2];
- }
- CVector pos;
- pos.x = (infX + supX) / 2;
- pos.y = (infY + supY) / 2;
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float radius = Max(pos.x - infX, pos.y - infY);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius);
- return 0;
- }
- /* Not implemented.
- case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR:
- case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
- case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK:
- */
- case COMMAND_SET_CHAR_AS_LEADER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget);
- return 0;
- }
- case COMMAND_SET_PLAYER_AS_LEADER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
- pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget);
- return 0;
- }
- case COMMAND_LEAVE_GROUP:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->ClearLeader();
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FOLLOW_ROUTE, ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- case COMMAND_ADD_ROUTE_POINT:
- {
- CollectParameters(&m_nIp, 4);
- CRouteNode::AddRoutePoint(ScriptParams[0], *(CVector*)&ScriptParams[1]);
- return 0;
- }
- case COMMAND_PRINT_WITH_NUMBER_BIG:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 3);
- CMessages::AddBigMessageWithNumber(text, ScriptParams[1], ScriptParams[2] - 1, ScriptParams[0], -1, -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_NUMBER:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 3);
- CMessages::AddMessageWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_NUMBER_NOW:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 3);
- CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
- return 0;
- }
- /* Not implemented.
- case COMMAND_PRINT_WITH_NUMBER_SOON:
- */
- case COMMAND_SWITCH_ROADS_ON:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false);
- return 0;
- }
- case COMMAND_SWITCH_ROADS_OFF:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true);
- return 0;
- }
- case COMMAND_GET_NUMBER_OF_PASSENGERS:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- ScriptParams[0] = pVehicle->m_nNumPassengers;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- ScriptParams[0] = pVehicle->m_nNumMaxPassengers;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CAR_DENSITY_MULTIPLIER:
- {
- CollectParameters(&m_nIp, 1);
- CCarCtrl::CarDensityMultiplier = *(float*)&ScriptParams[0];
- return 0;
- }
- case COMMAND_SET_CAR_HEAVY:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bIsHeavy = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_CLEAR_CHAR_THREAT_SEARCH:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->m_fearFlags = 0;
- return 0;
- }
- case COMMAND_ACTIVATE_CRANE:
- {
- CollectParameters(&m_nIp, 10);
- float infX = *(float*)&ScriptParams[2];
- float infY = *(float*)&ScriptParams[3];
- float supX = *(float*)&ScriptParams[4];
- float supY = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[4];
- supX = *(float*)&ScriptParams[2];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[5];
- supY = *(float*)&ScriptParams[3];
- }
- CCranes::ActivateCrane(infX, supX, infY, supY,
- *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
- DEGTORAD(*(float*)&ScriptParams[9]), false, false,
- *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
- return 0;
- }
- case COMMAND_DEACTIVATE_CRANE:
- {
- CollectParameters(&m_nIp, 2);
- CCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
- return 0;
- }
- case COMMAND_SET_MAX_WANTED_LEVEL:
- {
- CollectParameters(&m_nIp, 1);
- CWanted::SetMaximumWantedLevel(ScriptParams[0]);
- return 0;
- }
- /* Debug commands?
- case COMMAND_SAVE_VAR_INT:
- case COMMAND_SAVE_VAR_FLOAT:
- */
- case COMMAND_IS_CAR_IN_AIR_PROPER:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0);
- return 0;
- }
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands500To599(int32 command)
-{
- switch (command) {
- case COMMAND_IS_CAR_UPSIDEDOWN:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->GetUp().z <= -0.97f);
- return 0;
- }
- case COMMAND_GET_PLAYER_CHAR:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_CANCEL_OVERRIDE_RESTART:
- CRestart::CancelOverrideRestart();
- return 0;
- case COMMAND_SET_POLICE_IGNORE_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- if (ScriptParams[1]) {
- pPed->m_pWanted->m_bIgnoredByCops = true;
- CWorld::StopAllLawEnforcersInTheirTracks();
- }
- else {
- pPed->m_pWanted->m_bIgnoredByCops = false;
- }
- return 0;
- }
- case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 4);
- CUserDisplay::Pager.AddMessageWithNumber(text, ScriptParams[0], -1, -1, -1, -1, -1,
- ScriptParams[1], ScriptParams[2], ScriptParams[3]);
- return 0;
- }
- case COMMAND_START_KILL_FRENZY:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 8);
- CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],
- ScriptParams[3], text, ScriptParams[4], ScriptParams[5],
- ScriptParams[6], ScriptParams[7] != 0, false);
- return 0;
- }
- case COMMAND_READ_KILL_FRENZY_STATUS:
- {
- ScriptParams[0] = CDarkel::ReadStatus();
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SQRT:
- {
- CollectParameters(&m_nIp, 1);
- *(float*)&ScriptParams[0] = Sqrt(*(float*)&ScriptParams[0]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D:
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:
- LocatePlayerCarCommand(command, &m_nIp);
- return 0;
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D:
- case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D:
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:
- case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:
- LocateCharCarCommand(command, &m_nIp);
- return 0;
- case COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE:
- CollectParameters(&m_nIp, 2);
- *(float*)&ScriptParams[0] = CGeneral::GetRandomNumberInRange(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_GENERATE_RANDOM_INT_IN_RANGE:
- CollectParameters(&m_nIp, 2);
- ScriptParams[0] = CGeneral::GetRandomNumberInRange(ScriptParams[0], ScriptParams[1]);
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_LOCK_CAR_DOORS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1];
- return 0;
- }
- case COMMAND_EXPLODE_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->BlowUpCar(nil);
- return 0;
- }
- case COMMAND_ADD_EXPLOSION:
- CollectParameters(&m_nIp, 4);
- CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0);
- return 0;
-
- case COMMAND_IS_CAR_UPRIGHT:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->GetUp().z >= 0.0f);
- return 0;
- }
- case COMMAND_TURN_CHAR_TO_FACE_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;
- CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();
- CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();
- float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;
- if (angle > TWOPI)
- angle -= TWOPI;
- if (!pVehicle) {
- pSourcePed->m_fRotationCur = angle;
- pSourcePed->m_fRotationDest = angle;
- pSourcePed->SetHeading(angle);
- }
- return 0;
- }
- case COMMAND_TURN_CHAR_TO_FACE_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed;
- CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;
- CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();
- CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();
- float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;
- if (angle > TWOPI)
- angle -= TWOPI;
- if (!pVehicle) {
- pSourcePed->m_fRotationCur = angle;
- pSourcePed->m_fRotationDest = angle;
- pSourcePed->SetHeading(angle);
- }
- return 0;
- }
- case COMMAND_TURN_PLAYER_TO_FACE_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
- CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;
- CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();
- CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();
- float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;
- if (angle > TWOPI)
- angle -= TWOPI;
- if (!pVehicle) {
- pSourcePed->m_fRotationCur = angle;
- pSourcePed->m_fRotationDest = angle;
- pSourcePed->SetHeading(angle);
- }
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVector target;
- target.x = *(float*)&ScriptParams[1];
- target.y = *(float*)&ScriptParams[2];
- target.z = CWorld::FindGroundZForCoord(target.x, target.y);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target);
- return 0;
- }
- /* Not implemented*/
- //case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR:
- case COMMAND_CREATE_PICKUP:
- {
- CollectParameters(&m_nIp, 5);
- int16 model = ScriptParams[0];
- if (model < 0)
- model = CTheScripts::UsedObjectArray[-model].index;
- CVector pos = *(CVector*)&ScriptParams[2];
- 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, model, ScriptParams[1], 0);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_HAS_PICKUP_BEEN_COLLECTED:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CPickups::IsPickUpPickedUp(ScriptParams[0]) != 0);
- return 0;
- case COMMAND_REMOVE_PICKUP:
- CollectParameters(&m_nIp, 1);
- CPickups::RemovePickUp(ScriptParams[0]);
- return 0;
- case COMMAND_SET_TAXI_LIGHTS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- ((CAutomobile*)pVehicle)->SetTaxiLight(ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_PRINT_BIG_Q:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 2);
- CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1);
- return 0;
- }
- case COMMAND_PRINT_WITH_NUMBER_BIG_Q:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 3);
- CMessages::AddBigMessageWithNumberQ(text, ScriptParams[1], ScriptParams[2] - 1,
- ScriptParams[0], -1, -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_SET_GARAGE:
- {
- CollectParameters(&m_nIp, 7);
- 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);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_GARAGE_WITH_CAR_MODEL:
- {
- CollectParameters(&m_nIp, 8);
- 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]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pTarget;
- if (ScriptParams[1] >= 0) {
- pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- }
- else {
- pTarget = nil;
- }
- CGarages::SetTargetCarForMissonGarage(ScriptParams[0], pTarget);
- return 0;
- }
- case COMMAND_IS_CAR_IN_MISSION_GARAGE:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CGarages::HasCarBeenDroppedOffYet(ScriptParams[0]));
- return 0;
- case COMMAND_SET_FREE_BOMBS:
- CollectParameters(&m_nIp, 1);
- CGarages::SetFreeBombs(ScriptParams[0] != 0);
- return 0;
-#ifdef GTA_PS2
- case COMMAND_SET_POWERPOINT:
- {
- CollectParameters(&m_nIp, 7);
- float f1 = *(float*)&ScriptParams[0];
- float f2 = *(float*)&ScriptParams[1];
- float f3 = *(float*)&ScriptParams[2];
- float f4 = *(float*)&ScriptParams[3];
- float f5 = *(float*)&ScriptParams[4];
- float f6 = *(float*)&ScriptParams[5];
- float temp;
-
- if (f1 > f4) {
- temp = f1;
- f1 = f4;
- f4 = temp;
- }
-
- if (f2 > f5) {
- temp = f2;
- f2 = f5;
- f5 = temp;
- }
-
- if (f3 > f6) {
- temp = f3;
- f3 = f6;
- f6 = temp;
- }
-
- CPowerPoints::GenerateNewOne(f1, f2, f3, f4, f5, f6, *(uint8*)&ScriptParams[6]);
-
- return 0;
- }
-#endif // GTA_PS2
- case COMMAND_SET_ALL_TAXI_LIGHTS:
- CollectParameters(&m_nIp, 1);
- CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0);
- return 0;
- case COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB:
- {
- CollectParameters(&m_nIp, 1);
- CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pCar);
- script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);
- UpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum
- return 0;
- }
- case COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR:
- CollectParameters(&m_nIp, 2);
- CPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0);
- return 0;
- case COMMAND_SET_PLAYER_HEALTH:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- pPed->m_fHealth = ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_CHAR_HEALTH:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- if (ScriptParams[1]) {
- pPed->m_fHealth = ScriptParams[1];
- }
- else if (pPed->bInVehicle) {
- pPed->SetDead();
- if (!pPed->IsPlayer())
- pPed->FlagToDestroyWhenNextProcessed();
- }
- else {
- pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
- return 0;
- }
- case COMMAND_SET_CAR_HEALTH:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->m_fHealth = ScriptParams[1];
- return 0;
- }
- case COMMAND_GET_PLAYER_HEALTH:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- ScriptParams[0] = pPed->m_fHealth; // correct cast float to int
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_CHAR_HEALTH:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- ScriptParams[0] = pPed->m_fHealth; // correct cast float to int
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_CAR_HEALTH:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- ScriptParams[0] = pVehicle->m_fHealth; // correct cast float to int
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_IS_CAR_ARMED_WITH_BOMB:
- {
- CollectParameters(&m_nIp, 2);
- CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pCar);
- script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);
- UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); //TODO: enum
- return 0;
- }
- case COMMAND_CHANGE_CAR_COLOUR:
- {
- CollectParameters(&m_nIp, 3);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- if (ScriptParams[1] >= 256 || ScriptParams[2] >= 256)
- debug("CHANGE_CAR_COLOUR - Colours must be less than %d", 256);
- pVehicle->m_currentColour1 = ScriptParams[1];
- pVehicle->m_currentColour2 = ScriptParams[2];
- return 0;
- }
- case COMMAND_SWITCH_PED_ROADS_ON:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false);
- return 0;
- }
- case COMMAND_SWITCH_PED_ROADS_OFF:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true);
- return 0;
- }
- case COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pSourcePed);
- CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pTargetPed);
- pSourcePed->SetLookFlag(pTargetPed, true);
- pSourcePed->SetLookTimer(60000);
- return 0;
- }
- case COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pSourcePed);
- CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed;
- script_assert(pTargetPed);
- pSourcePed->SetLookFlag(pTargetPed, true);
- pSourcePed->SetLookTimer(60000);
- return 0;
- }
- case COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pSourcePed);
- CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pTargetPed);
- pSourcePed->SetLookFlag(pTargetPed, true);
- pSourcePed->SetLookTimer(60000);
- return 0;
- }
- case COMMAND_STOP_CHAR_LOOKING:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pSourcePed);
- pSourcePed->ClearLookFlag();
- pSourcePed->bKeepTryingToLook = false;
- if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)
- pSourcePed->RestorePreviousState();
- return 0;
- }
- case COMMAND_STOP_PLAYER_LOOKING:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pSourcePed);
- pSourcePed->ClearLookFlag();
- pSourcePed->bKeepTryingToLook = false;
- if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)
- pSourcePed->RestorePreviousState();
- return 0;
- }
- case COMMAND_SWITCH_HELICOPTER:
- CollectParameters(&m_nIp, 1);
- CHeli::ActivateHeli(ScriptParams[0] != 0);
- return 0;
-
- //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_CAR_MODEL:
- CollectParameters(&m_nIp, 2);
- CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_SET_GANG_WEAPONS:
- CollectParameters(&m_nIp, 3);
- CGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]);
- return 0;
- case COMMAND_SET_CHAR_OBJ_RUN_TO_AREA:
- {
- CollectParameters(&m_nIp, 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- float infX = *(float*)&ScriptParams[1];
- float infY = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[1];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[2];
- }
- CVector pos;
- pos.x = (infX + supX) / 2;
- pos.y = (infY + supY) / 2;
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float radius = Max(pos.x - infX, pos.y - infY);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_RUN_TO_COORD:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVector pos;
- pos.x = *(float*)&ScriptParams[1];
- pos.y = *(float*)&ScriptParams[2];
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos);
- return 0;
- }
- case COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- bool isTouching = false;
- if (pPed->bInVehicle)
- isTouching = false;
- else if (pPed->GetHasCollidedWith(pObject))
- isTouching = true;
- UpdateCompareFlag(isTouching);
- return 0;
- }
- case COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- bool isTouching = false;
- if (pPed->InVehicle())
- isTouching = false;
- else if (pPed->GetHasCollidedWith(pObject))
- isTouching = true;
- UpdateCompareFlag(isTouching);
- return 0;
- }
- case COMMAND_LOAD_SPECIAL_CHARACTER:
- {
- CollectParameters(&m_nIp, 1);
- char name[16];
- strncpy(name, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- name[i] = tolower(name[i]);
- CStreaming::RequestSpecialChar(ScriptParams[0] - 1, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- return 0;
- }
- case COMMAND_HAS_SPECIAL_CHARACTER_LOADED:
- {
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1));
- return 0;
- }
- case COMMAND_FLASH_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bHasBlip = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_FLASH_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bHasBlip = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_FLASH_OBJECT:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- pObject->bHasBlip = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_IS_PLAYER_IN_REMOTE_MODE:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode());
- return 0;
- case COMMAND_ARM_CAR_WITH_BOMB:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- ((CAutomobile*)pVehicle)->m_bombType = ScriptParams[1];
- ((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed();
- return 0;
- }
- case COMMAND_SET_CHAR_PERSONALITY:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->SetPedStats((ePedStats)ScriptParams[1]);
- return 0;
- }
- case COMMAND_SET_CUTSCENE_OFFSET:
- CollectParameters(&m_nIp, 3);
- CCutsceneMgr::SetCutsceneOffset(*(CVector*)&ScriptParams[0]);
- return 0;
- case COMMAND_SET_ANIM_GROUP_FOR_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->m_animGroup = (AssocGroupId)ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_ANIM_GROUP_FOR_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- pPed->m_animGroup = (AssocGroupId)ScriptParams[1];
- return 0;
- }
- case COMMAND_REQUEST_MODEL:
- {
- CollectParameters(&m_nIp, 1);
- int model = ScriptParams[0];
- if (model < 0)
- model = CTheScripts::UsedObjectArray[-model].index;
- CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_NOFADE | STREAMFLAGS_SCRIPTOWNED);
- return 0;
- }
- case COMMAND_HAS_MODEL_LOADED:
- {
- CollectParameters(&m_nIp, 1);
- int model = ScriptParams[0];
- if (model < 0)
- model = CTheScripts::UsedObjectArray[-model].index;
- UpdateCompareFlag(CStreaming::HasModelLoaded(model));
- return 0;
- }
- case COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED:
- {
- CollectParameters(&m_nIp, 1);
- int model = ScriptParams[0];
- if (model < 0)
- model = CTheScripts::UsedObjectArray[-model].index;
- CStreaming::SetMissionDoesntRequireModel(model);
- return 0;
- }
- case COMMAND_GRAB_PHONE:
- {
- CollectParameters(&m_nIp, 2);
- ScriptParams[0] = gPhoneInfo.GrabPhone(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_REPEATED_PHONE_MESSAGE:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text, nil, nil, nil, nil, nil);
- return 0;
- }
- case COMMAND_SET_PHONE_MESSAGE:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text, nil, nil, nil, nil, nil);
- return 0;
- }
- case COMMAND_HAS_PHONE_DISPLAYED_MESSAGE:
- {
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0]));
- return 0;
- }
- case COMMAND_TURN_PHONE_OFF:
- {
- CollectParameters(&m_nIp, 1);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], nil, nil, nil, nil, nil, nil);
- return 0;
- }
- case COMMAND_DRAW_CORONA:
- {
- CollectParameters(&m_nIp, 9);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8],
- 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f);
- return 0;
- }
- case COMMAND_DRAW_LIGHT:
- {
- CollectParameters(&m_nIp, 6);
- CVector pos = *(CVector*)&ScriptParams[0];
- CVector unused(0.0f, 0.0f, 0.0f);
- CPointLights::AddLight(0, *(CVector*)&ScriptParams[0], CVector(0.0f, 0.0f, 0.0f), 12.0f,
- 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_CLOCK:
- CClock::StoreClock();
- return 0;
- case COMMAND_RESTORE_CLOCK:
- CClock::RestoreClock();
- return 0;
- case COMMAND_RESTART_CRITICAL_MISSION:
- {
- CollectParameters(&m_nIp, 4);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]);
- if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING)
- printf("RESTART_CRITICAL_MISSION - Player state is not PLAYING\n");
- CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission();
- return 0;
- }
- case COMMAND_IS_PLAYER_PLAYING:
- {
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_PLAYING);
- return 0;
- }
- //case COMMAND_SET_COLL_OBJ_NO_OBJ:
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands600To699(int32 command)
-{
- switch (command){
- /* Collective commands are not implemented until LCS.
- case COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE:
- case COMMAND_SET_COLL_OBJ_GUARD_SPOT:
- case COMMAND_SET_COLL_OBJ_GUARD_AREA:
- case COMMAND_SET_COLL_OBJ_WAIT_IN_CAR:
- case COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS:
- case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS:
- case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:
- case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:
- case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:
- case COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_LEAVE_CAR:
- case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER:
- case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER:
- case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR:
- case COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
- case COMMAND_SET_COLL_OBJ_DESTROY_OBJECT:
- case COMMAND_SET_COLL_OBJ_DESTROY_CAR:
- case COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR:
- case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
- case COMMAND_SET_COLL_OBJ_GUARD_ATTACK:
- case COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE:
- case COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT:
- case COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR:
- case COMMAND_SET_COLL_OBJ_RUN_TO_AREA:
- case COMMAND_SET_COLL_OBJ_RUN_TO_COORD:
- case COMMAND_ADD_PEDS_IN_AREA_TO_COLL:
- case COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL:
- case COMMAND_CLEAR_COLL:
- case COMMAND_IS_COLL_IN_CARS:
- case COMMAND_LOCATE_COLL_ANY_MEANS_2D:
- case COMMAND_LOCATE_COLL_ON_FOOT_2D:
- case COMMAND_LOCATE_COLL_IN_CAR_2D:
- case COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:
- case COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:
- case COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:
- case COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D:
- case COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D:
- case COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D:
- case COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D:
- case COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D:
- case COMMAND_LOCATE_COLL_IN_CAR_CAR_2D:
- case COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D:
- case COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D:
- case COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D:
- case COMMAND_IS_COLL_IN_AREA_2D:
- case COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_COLL_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_COLL_STOPPED_IN_AREA_2D:
- case COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:
- case COMMAND_GET_NUMBER_OF_PEDS_IN_COLL:
- */
- case COMMAND_SET_CHAR_HEED_THREATS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bRespondsToThreats = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_PLAYER_HEED_THREATS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- pPed->bRespondsToThreats = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_GET_CONTROLLER_MODE:
-#if defined(GTA_PC) && !defined(DETECT_PAD_INPUT_SWITCH)
- ScriptParams[0] = 0;
-#else
- ScriptParams[0] = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
-#endif
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_SET_CAN_RESPRAY_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0);
- return 0;
- }
- case COMMAND_IS_TAXI:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- int mi = pVehicle->GetModelIndex();
- UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE);
- return 0;
- }
- case COMMAND_UNLOAD_SPECIAL_CHARACTER:
- CollectParameters(&m_nIp, 1);
- CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1);
- return 0;
- case COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER:
- CDarkel::ResetModelsKilledByPlayer();
- return 0;
- case COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER:
- CollectParameters(&m_nIp, 1);
- ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]);
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_ACTIVATE_GARAGE:
- CollectParameters(&m_nIp, 1);
- CGarages::ActivateGarage(ScriptParams[0]);
- return 0;
- case COMMAND_SWITCH_TAXI_TIMER:
- {
- CollectParameters(&m_nIp, 1);
- if (ScriptParams[0] != 0){
- CWorld::Players[CWorld::PlayerInFocus].m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
- CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = true;
- }else{
- CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = false;
- }
- return 0;
- }
- case COMMAND_CREATE_OBJECT_NO_OFFSET:
- {
- CollectParameters(&m_nIp, 4);
- int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;
- CObject* pObj = new CObject(mi, false);
-; pObj->ObjectCreatedBy = MISSION_OBJECT;
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pObj->SetPosition(pos);
- pObj->SetOrientation(0.0f, 0.0f, 0.0f);
- pObj->GetMatrix().UpdateRW();
- pObj->UpdateRwFrame();
- CTheScripts::ClearSpaceForMissionEntity(pos, pObj);
- CWorld::Add(pObj);
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
- StoreParameters(&m_nIp, 1);
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
- return 0;
- }
- case COMMAND_IS_BOAT:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS:
- {
- CollectParameters(&m_nIp, 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- float infX = *(float*)&ScriptParams[1];
- float infY = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[1];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[2];
- }
- CVector pos;
- pos.x = (infX + supX) / 2;
- pos.y = (infY + supY) / 2;
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float radius = Max(pos.x - infX, pos.y - infY);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius);
- return 0;
- }
- //case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS:
- case COMMAND_IS_PLAYER_STOPPED:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
- UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer));
- return 0;
- }
- case COMMAND_IS_CHAR_STOPPED:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(CTheScripts::IsPedStopped(pPed));
- return 0;
- }
- case COMMAND_MESSAGE_WAIT:
- CollectParameters(&m_nIp, 2);
- m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0];
- if (ScriptParams[1] != 0)
- m_bSkipWakeTime = true;
- return 1;
- case COMMAND_ADD_PARTICLE_EFFECT:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);
- return 0;
- }
- case COMMAND_SWITCH_WIDESCREEN:
- CollectParameters(&m_nIp, 1);
- if (ScriptParams[0] != 0)
- TheCamera.SetWideScreenOn();
- else
- TheCamera.SetWideScreenOff();
- return 0;
- case COMMAND_ADD_SPRITE_BLIP_FOR_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int id = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);
- CRadar::SetBlipSprite(id, ScriptParams[1]);
- ScriptParams[0] = id;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_SPRITE_BLIP_FOR_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int id = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);
- CRadar::SetBlipSprite(id, ScriptParams[1]);
- ScriptParams[0] = id;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int id = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);
- CRadar::SetBlipSprite(id, ScriptParams[1]);
- ScriptParams[0] = id;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_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::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
- CRadar::SetBlipSprite(id, ScriptParams[3]);
- ScriptParams[0] = id;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_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::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
- CRadar::SetBlipSprite(id, ScriptParams[3]);
- ScriptParams[0] = id;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_CHAR_PROOFS:
- {
- CollectParameters(&m_nIp, 6);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bBulletProof = (ScriptParams[1] != 0);
- pPed->bFireProof = (ScriptParams[2] != 0);
- pPed->bExplosionProof = (ScriptParams[3] != 0);
- pPed->bCollisionProof = (ScriptParams[4] != 0);
- pPed->bMeleeProof = (ScriptParams[5] != 0);
- return 0;
- }
- case COMMAND_SET_CAR_PROOFS:
- {
- CollectParameters(&m_nIp, 6);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bBulletProof = (ScriptParams[1] != 0);
- pVehicle->bFireProof = (ScriptParams[2] != 0);
- pVehicle->bExplosionProof = (ScriptParams[3] != 0);
- pVehicle->bCollisionProof = (ScriptParams[4] != 0);
- pVehicle->bMeleeProof = (ScriptParams[5] != 0);
- return 0;
- }
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
- PlayerInAngledAreaCheckCommand(command, &m_nIp);
- return 0;
- case COMMAND_DEACTIVATE_GARAGE:
- CollectParameters(&m_nIp, 1);
- CGarages::DeActivateGarage(ScriptParams[0]);
- return 0;
- case COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE:
- CollectParameters(&m_nIp, 1);
- ScriptParams[0] = CGarages::QueryCarsCollected(ScriptParams[0]);
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE:
- CollectParameters(&m_nIp, 2);
- UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1));
- return 0;
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands700To799(int32 command)
-{
- switch (command){
- case COMMAND_SET_SWAT_REQUIRED:
- CollectParameters(&m_nIp, 1);
- FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0);
- return 0;
- case COMMAND_SET_FBI_REQUIRED:
- CollectParameters(&m_nIp, 1);
- FindPlayerPed()->m_pWanted->m_bFbiRequired = (ScriptParams[0] != 0);
- return 0;
- case COMMAND_SET_ARMY_REQUIRED:
- CollectParameters(&m_nIp, 1);
- FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0);
- return 0;
- case COMMAND_IS_CAR_IN_WATER:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(pVehicle && pVehicle->bIsInWater);
- return 0;
- }
- case COMMAND_GET_CLOSEST_CHAR_NODE:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)];
- *(CVector*)&ScriptParams[0] = pNode->GetPosition();
- StoreParameters(&m_nIp, 3);
- return 0;
- }
- case COMMAND_GET_CLOSEST_CAR_NODE:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)];
- *(CVector*)&ScriptParams[0] = pNode->GetPosition();
- StoreParameters(&m_nIp, 3);
- return 0;
- }
- case COMMAND_CAR_GOTO_COORDINATES_ACCURATE:
- {
- CollectParameters(&m_nIp, 4);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
- if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false))
- pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
- else
- pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE;
- pVehicle->SetStatus(STATUS_PHYSICS);
- pVehicle->bEngineOn = true;
- pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
- pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
- return 0;
- }
- case COMMAND_START_PACMAN_RACE:
- CollectParameters(&m_nIp, 1);
- CPacManPickups::StartPacManRace(ScriptParams[0]);
- return 0;
- case COMMAND_START_PACMAN_RECORD:
- CPacManPickups::StartPacManRecord();
- return 0;
- case COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN:
- ScriptParams[0] = CPacManPickups::QueryPowerPillsEatenInRace();
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_CLEAR_PACMAN:
- CPacManPickups::CleanUpPacManStuff();
- return 0;
- case COMMAND_START_PACMAN_SCRAMBLE:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]);
- return 0;
- }
- case COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED:
- ScriptParams[0] = CPacManPickups::QueryPowerPillsCarriedByPlayer();
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED:
- CPacManPickups::ResetPowerPillsCarriedByPlayer();
- return 0;
- case COMMAND_IS_CAR_ON_SCREEN:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(TheCamera.IsSphereVisible(pVehicle->GetBoundCentre(), pVehicle->GetBoundRadius()));
- return 0;
- }
- case COMMAND_IS_CHAR_ON_SCREEN:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(TheCamera.IsSphereVisible(pPed->GetBoundCentre(), pPed->GetBoundRadius()));
- return 0;
- }
- case COMMAND_IS_OBJECT_ON_SCREEN:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius()));
- return 0;
- }
- case COMMAND_GOSUB_FILE:
- {
- CollectParameters(&m_nIp, 2);
- script_assert(m_nStackPointer < MAX_STACK_DEPTH);
- m_anStack[m_nStackPointer++] = m_nIp;
- SetIP(ScriptParams[0]);
- // ScriptParams[1] == filename
- return 0;
- }
- case COMMAND_GET_GROUND_Z_FOR_3D_COORD:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- bool success;
- *(float*)&ScriptParams[0] = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &success);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_START_SCRIPT_FIRE:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- ScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(gFireManager.IsScriptFireExtinguish(ScriptParams[0]));
- return 0;
- case COMMAND_REMOVE_SCRIPT_FIRE:
- CollectParameters(&m_nIp, 1);
- gFireManager.RemoveScriptFire(ScriptParams[0]);
- return 0;
- case COMMAND_SET_COMEDY_CONTROLS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bComedyControls = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_BOAT_GOTO_COORDS:
- {
- CollectParameters(&m_nIp, 4);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
- CBoat* pBoat = (CBoat*)pVehicle;
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false);
- pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS;
- pBoat->AutoPilot.m_vecDestinationCoors = pos;
- pBoat->SetStatus(STATUS_PHYSICS);
- pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed);
- pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
- return 0;
- }
- case COMMAND_BOAT_STOP:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
- CBoat* pBoat = (CBoat*)pVehicle;
- pBoat->AutoPilot.m_nCarMission = MISSION_NONE;
- pBoat->SetStatus(STATUS_PHYSICS);
- pBoat->bEngineOn = false;
- pBoat->AutoPilot.m_nCruiseSpeed = 0;
- return 0;
- }
- case COMMAND_IS_PLAYER_SHOOTING_IN_AREA:
- {
- CollectParameters(&m_nIp, 6);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- float x1 = *(float*)&ScriptParams[1];
- float y1 = *(float*)&ScriptParams[2];
- float x2 = *(float*)&ScriptParams[3];
- float y2 = *(float*)&ScriptParams[4];
- UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
- if (ScriptParams[5])
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag)
- CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
- return 0;
- }
- case COMMAND_IS_CHAR_SHOOTING_IN_AREA:
- {
- CollectParameters(&m_nIp, 6);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- float x1 = *(float*)&ScriptParams[1];
- float y1 = *(float*)&ScriptParams[2];
- float x2 = *(float*)&ScriptParams[3];
- float y2 = *(float*)&ScriptParams[4];
- UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
- if (ScriptParams[5])
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag)
- CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
- return 0;
- }
- case COMMAND_IS_CURRENT_PLAYER_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
- return 0;
- }
- case COMMAND_IS_CURRENT_CHAR_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
- return 0;
- }
- case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN:
- CPacManPickups::ResetPowerPillsEatenInRace();
- return 0;
- case COMMAND_ADD_POWER_PILL:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CPacManPickups::GenerateOnePMPickUp(pos);
- return 0;
- }
- case COMMAND_SET_BOAT_CRUISE_SPEED:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
- CBoat* pBoat = (CBoat*)pVehicle;
- pBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];
- return 0;
- }
- case COMMAND_GET_RANDOM_CHAR_IN_AREA:
- {
- CollectParameters(&m_nIp, 4);
- int ped_handle = -1;
- CVector pos = FindPlayerCoors();
- float x1 = *(float*)&ScriptParams[0];
- float y1 = *(float*)&ScriptParams[1];
- float x2 = *(float*)&ScriptParams[2];
- float y2 = *(float*)&ScriptParams[3];
- int i = CPools::GetPedPool()->GetSize();
- while (--i && ped_handle == -1){
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
- continue;
- if (pPed->CharCreatedBy != RANDOM_CHAR)
- continue;
- if (!pPed->IsPedInControl())
- continue;
- if (pPed->bRemoveFromWorld)
- continue;
- if (pPed->bFadeOut)
- 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)
- continue;
- if (!pPed->IsWithinArea(x1, y1, x2, y2))
- continue;
- if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
- continue;
- if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
- continue;
- ped_handle = CPools::GetPedPool()->GetIndex(pPed);
- CTheScripts::LastRandomPedId = ped_handle;
- pPed->CharCreatedBy = MISSION_CHAR;
- pPed->bRespondsToThreats = false;
- ++CPopulation::ms_nTotalMissionPeds;
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
- }
- ScriptParams[0] = ped_handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_RANDOM_CHAR_IN_ZONE:
- {
- char zone[KEY_LENGTH_IN_SCRIPT];
- strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
- if (nZone != -1)
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
- int ped_handle = -1;
- CVector pos = FindPlayerCoors();
- int i = CPools::GetPedPool()->GetSize();
- while (--i && ped_handle == -1) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
- continue;
- if (pPed->CharCreatedBy != RANDOM_CHAR)
- continue;
- if (!pPed->IsPedInControl())
- continue;
- if (pPed->bRemoveFromWorld)
- continue;
- if (pPed->bFadeOut)
- 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)
- continue;
- if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))
- continue;
- if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
- continue;
- if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
- continue;
- ped_handle = CPools::GetPedPool()->GetIndex(pPed);
- CTheScripts::LastRandomPedId = ped_handle;
- pPed->CharCreatedBy = MISSION_CHAR;
- pPed->bRespondsToThreats = false;
- ++CPopulation::ms_nTotalMissionPeds;
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
- }
- ScriptParams[0] = ped_handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_IS_PLAYER_IN_TAXI:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->IsTaxi());
- return 0;
- }
- case COMMAND_IS_PLAYER_SHOOTING:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(pPed->bIsShooting);
- return 0;
- }
- case COMMAND_IS_CHAR_SHOOTING:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(pPed->bIsShooting);
- return 0;
- }
- case COMMAND_CREATE_MONEY_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_MONEY, PICKUP_MONEY, ScriptParams[3]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CHAR_ACCURACY:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->m_wepAccuracy = ScriptParams[1];
- return 0;
- }
- case COMMAND_GET_CAR_SPEED:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- *(float*)&ScriptParams[0] = pVehicle->GetSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_LOAD_CUTSCENE:
- {
- char name[KEY_LENGTH_IN_SCRIPT];
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CCutsceneMgr::LoadCutsceneData(name);
- return 0;
- }
- case COMMAND_CREATE_CUTSCENE_OBJECT:
- {
- CollectParameters(&m_nIp, 1);
- CCutsceneObject* pCutObj = CCutsceneMgr::CreateCutsceneObject(ScriptParams[0]);
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutObj);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CUTSCENE_ANIM:
- {
- CollectParameters(&m_nIp, 1);
- char name[KEY_LENGTH_IN_SCRIPT];
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CCutsceneMgr::SetCutsceneAnim(name, pObject);
- return 0;
- }
- case COMMAND_START_CUTSCENE:
- CCutsceneMgr::ms_cutsceneLoadStatus = 1;
- return 0;
- case COMMAND_GET_CUTSCENE_TIME:
- ScriptParams[0] = CCutsceneMgr::GetCutsceneTimeInMilleseconds();
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_HAS_CUTSCENE_FINISHED:
- UpdateCompareFlag(CCutsceneMgr::HasCutsceneFinished());
- return 0;
- case COMMAND_CLEAR_CUTSCENE:
- CCutsceneMgr::DeleteCutsceneData();
- return 0;
- case COMMAND_RESTORE_CAMERA_JUMPCUT:
- TheCamera.RestoreWithJumpCut();
- return 0;
- case COMMAND_CREATE_COLLECTABLE1:
- {
- 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;
- CPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0);
- return 0;
- }
- case COMMAND_SET_COLLECTABLE1_TOTAL:
- CollectParameters(&m_nIp, 1);
- CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0];
- return 0;
- case COMMAND_IS_PROJECTILE_IN_AREA:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, false));
- if (CTheScripts::DbgFlag)
- CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
- return 0;
- }
- case COMMAND_DESTROY_PROJECTILES_IN_AREA:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, true));
- if (CTheScripts::DbgFlag)
- CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
- return 0;
- }
- case COMMAND_DROP_MINE:
- {
- 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;
- CPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0);
- return 0;
- }
- case COMMAND_DROP_NAUTICAL_MINE:
- {
- 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;
- CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0);
- return 0;
- }
- case COMMAND_IS_CHAR_MODEL:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(ScriptParams[1] == pPed->GetModelIndex());
- return 0;
- }
- case COMMAND_LOAD_SPECIAL_MODEL:
- {
- CollectParameters(&m_nIp, 1);
- char name[KEY_LENGTH_IN_SCRIPT];
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- name[i] = tolower(name[i]);
- CStreaming::RequestSpecialModel(ScriptParams[0], name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- return 0;
- }
- case COMMAND_CREATE_CUTSCENE_HEAD:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]);
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CUTSCENE_HEAD_ANIM:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_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();
- return 0;
- }
- case COMMAND_SIN:
- CollectParameters(&m_nIp, 1);
- *(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0]));
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_COS:
- CollectParameters(&m_nIp, 1);
- *(float*)&ScriptParams[0] = Cos(DEGTORAD(*(float*)&ScriptParams[0]));
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_GET_CAR_FORWARD_X:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- float forwardX = pVehicle->GetForward().x / pVehicle->GetForward().Magnitude2D();
- *(float*)&ScriptParams[0] = forwardX;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_CAR_FORWARD_Y:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- float forwardY = pVehicle->GetForward().y / pVehicle->GetForward().Magnitude2D();
- *(float*)&ScriptParams[0] = forwardY;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_CHANGE_GARAGE_TYPE:
- CollectParameters(&m_nIp, 2);
- CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], 0);
- return 0;
- case COMMAND_ACTIVATE_CRUSHER_CRANE:
- {
- CollectParameters(&m_nIp, 10);
- float infX = *(float*)&ScriptParams[2];
- float infY = *(float*)&ScriptParams[3];
- float supX = *(float*)&ScriptParams[4];
- float supY = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[4];
- supX = *(float*)&ScriptParams[2];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[5];
- supY = *(float*)&ScriptParams[3];
- }
- CCranes::ActivateCrane(infX, supX, infY, supY,
- *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
- DEGTORAD(*(float*)&ScriptParams[9]), true, false,
- *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
- return 0;
- }
- case COMMAND_PRINT_WITH_2_NUMBERS:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 4);
- CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_2_NUMBERS_NOW:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 4);
- CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_2_NUMBERS_SOON:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 4);
- CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_3_NUMBERS:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 5);
- CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_3_NUMBERS_NOW:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 5);
- CMessages::AddMessageJumpQWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_3_NUMBERS_SOON:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 5);
- CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_4_NUMBERS:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 6);
- CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_4_NUMBERS_NOW:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 6);
- CMessages::AddMessageJumpQWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_4_NUMBERS_SOON:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 6);
- CMessages::AddMessageSoonWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_5_NUMBERS:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 7);
- CMessages::AddMessageWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_5_NUMBERS_NOW:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 7);
- CMessages::AddMessageJumpQWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_5_NUMBERS_SOON:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 7);
- CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_6_NUMBERS:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 8);
- CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
- return 0;
- }
- case COMMAND_PRINT_WITH_6_NUMBERS_NOW:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 8);
- CMessages::AddMessageJumpQWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
- return 0;
- }
- case COMMAND_PRINT_WITH_6_NUMBERS_SOON:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 8);
- CMessages::AddMessageSoonWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, pTargetPed);
- pPed->SetFormation((eFormation)ScriptParams[2]);
- return 0;
- }
- case COMMAND_PLAYER_MADE_PROGRESS:
- CollectParameters(&m_nIp, 1);
- CStats::ProgressMade += ScriptParams[0];
- return 0;
- case COMMAND_SET_PROGRESS_TOTAL:
- CollectParameters(&m_nIp, 1);
- CStats::TotalProgressInGame = ScriptParams[0];
- return 0;
- case COMMAND_REGISTER_JUMP_DISTANCE:
- CollectParameters(&m_nIp, 1);
- CStats::MaximumJumpDistance = Max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_JUMP_HEIGHT:
- CollectParameters(&m_nIp, 1);
- CStats::MaximumJumpHeight = Max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_JUMP_FLIPS:
- CollectParameters(&m_nIp, 1);
- CStats::MaximumJumpFlips = Max(CStats::MaximumJumpFlips, ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_JUMP_SPINS:
- CollectParameters(&m_nIp, 1);
- CStats::MaximumJumpSpins = Max(CStats::MaximumJumpSpins, ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_JUMP_STUNT:
- CollectParameters(&m_nIp, 1);
- CStats::BestStuntJump = Max(CStats::BestStuntJump, ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_UNIQUE_JUMP_FOUND:
- ++CStats::NumberOfUniqueJumpsFound;
- return 0;
- case COMMAND_SET_UNIQUE_JUMPS_TOTAL:
- CollectParameters(&m_nIp, 1);
- CStats::TotalNumberOfUniqueJumps = ScriptParams[0];
- return 0;
- case COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI:
- ++CStats::PassengersDroppedOffWithTaxi;
- return 0;
- case COMMAND_REGISTER_MONEY_MADE_TAXI:
- CollectParameters(&m_nIp, 1);
- CStats::MoneyMadeWithTaxi += ScriptParams[0];
- return 0;
- case COMMAND_REGISTER_MISSION_GIVEN:
- ++CStats::MissionsGiven;
- return 0;
- case COMMAND_REGISTER_MISSION_PASSED:
- {
- char name[KEY_LENGTH_IN_SCRIPT];
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- strncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT);
- ++CStats::MissionsPassed;
- CStats::CheckPointReachedSuccessfully();
- return 0;
- }
- case COMMAND_SET_CHAR_RUNNING:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bIsRunning = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_REMOVE_ALL_SCRIPT_FIRES:
- gFireManager.RemoveAllScriptFires();
- return 0;
- case COMMAND_IS_FIRST_CAR_COLOUR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->m_currentColour1 == ScriptParams[1]);
- return 0;
- }
- case COMMAND_IS_SECOND_CAR_COLOUR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]);
- return 0;
- }
- case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- if (!pPed)
- printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n");
- UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]);
- return 0;
- }
- case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- if (!pVehicle)
- printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n");
- UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]);
- return 0;
- }
- case COMMAND_IS_CHAR_IN_CHARS_GROUP:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pPed);
- script_assert(pLeader);
- UpdateCompareFlag(pPed->m_leader == pLeader);
- return 0;
- }
- default:
- script_assert(0);
- }
- return -1;
-}
-int8 CRunningScript::ProcessCommands800To899(int32 command)
-{
- CMatrix tmp_matrix;
- switch (command) {
- case COMMAND_IS_CHAR_IN_PLAYERS_GROUP:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed;
- script_assert(pPed);
- script_assert(pLeader);
- UpdateCompareFlag(pPed->m_leader == pLeader);
- return 0;
- }
- case COMMAND_EXPLODE_CHAR_HEAD:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- if (pPed->m_nPedState == PED_DRIVING) {
- pPed->SetDead();
- if (!pPed->IsPlayer())
- pPed->FlagToDestroyWhenNextProcessed();
- }
- else if (CGame::nastyGame && pPed->IsPedInControl()) {
- pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true);
- }
- else {
- pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
- return 0;
- }
- case COMMAND_EXPLODE_PLAYER_HEAD:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- if (CGame::nastyGame) {
- pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true);
- }
- else {
- pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
- return 0;
- }
- case COMMAND_ANCHOR_BOAT:
- {
- CollectParameters(&m_nIp, 2);
- CBoat* pBoat = (CBoat*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pBoat && pBoat->m_vehType == VEHICLE_TYPE_BOAT);
- pBoat->m_bIsAnchored = (ScriptParams[1] == 0);
- return 0;
- }
- case COMMAND_SET_ZONE_GROUP:
- {
- char zone[KEY_LENGTH_IN_SCRIPT];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 2);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
- if (zone_id < 0) {
- printf("Couldn't find zone - %s\n", zone);
- return 0;
- }
- CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]);
- return 0;
- }
- case COMMAND_START_CAR_FIRE:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- ScriptParams[0] = gFireManager.StartScriptFire(pVehicle->GetPosition(), pVehicle, 0.8f, 1);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_START_CHAR_FIRE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- ScriptParams[0] = gFireManager.StartScriptFire(pPed->GetPosition(), pPed, 0.8f, 1);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA:
- {
- CollectParameters(&m_nIp, 5);
- int handle = -1;
- uint32 i = CPools::GetVehiclePool()->GetSize();
- float infX = *(float*)&ScriptParams[0];
- float infY = *(float*)&ScriptParams[1];
- float supX = *(float*)&ScriptParams[2];
- float supY = *(float*)&ScriptParams[3];
- while (i--) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)
- continue;
- if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
- continue;
- if (!pVehicle->IsWithinArea(infX, infY, supX, supY))
- continue;
- handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
- pVehicle->VehicleCreatedBy = MISSION_VEHICLE;
- ++CCarCtrl::NumMissionCars;
- --CCarCtrl::NumRandomCars;
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
- }
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:
- {
- char zone[KEY_LENGTH_IN_SCRIPT];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
- if (zone_id != -1)
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
- CollectParameters(&m_nIp, 1);
- int handle = -1;
- uint32 i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- if (ScriptParams[0] != pVehicle->GetModelIndex() && ScriptParams[0] >= 0)
- continue;
- if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
- continue;
- if (!CTheZones::PointLiesWithinZone(&pVehicle->GetPosition(), pZone))
- continue;
- handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
- pVehicle->VehicleCreatedBy = MISSION_VEHICLE;
- ++CCarCtrl::NumMissionCars;
- --CCarCtrl::NumRandomCars;
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
- }
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_HAS_RESPRAY_HAPPENED:
- {
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CGarages::HasResprayHappened(ScriptParams[0]));
- return 0;
- }
- case COMMAND_SET_CAMERA_ZOOM:
- {
- CollectParameters(&m_nIp, 1);
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED)
- TheCamera.SetZoomValueFollowPedScript(ScriptParams[0]);
- else if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING)
- TheCamera.SetZoomValueCamStringScript(ScriptParams[0]);
- return 0;
- }
- case COMMAND_CREATE_PICKUP_WITH_AMMO:
- {
- CollectParameters(&m_nIp, 6);
- int16 model = ScriptParams[0];
- if (model < 0)
- model = CTheScripts::UsedObjectArray[-model].index;
- CVector pos = *(CVector*)&ScriptParams[3];
- 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, model, ScriptParams[1], ScriptParams[2]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CAR_RAM_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CCarAI::TellCarToRamOtherCar(pVehicle, pTarget);
- return 0;
- }
- case COMMAND_SET_CAR_BLOCK_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CCarAI::TellCarToBlockOtherCar(pVehicle, pTarget);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_CATCH_TRAIN:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_CATCH_TRAIN);
- return 0;
- }
- //case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
- case COMMAND_SET_PLAYER_NEVER_GETS_TIRED:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
- pPlayer->m_bInfiniteSprint = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_PLAYER_FAST_RELOAD:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
- pPlayer->m_bFastReload = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_CHAR_BLEEDING:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bPedIsBleeding = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_CAR_FUNNY_SUSPENSION:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- // no action
- return 0;
- }
- case COMMAND_SET_CAR_BIG_WHEELS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- CAutomobile* pCar = (CAutomobile*)pVehicle;
- pCar->bBigWheels = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_FREE_RESPRAYS:
- CollectParameters(&m_nIp, 1);
- CGarages::SetFreeResprays(ScriptParams[0] != 0);
- return 0;
- case COMMAND_SET_PLAYER_VISIBLE:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- pPed->bIsVisible = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_CHAR_VISIBLE:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bIsVisible = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_SET_CAR_VISIBLE:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bIsVisible = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_IS_AREA_OCCUPIED:
- {
- CollectParameters(&m_nIp, 11);
- 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];
- }
- int16 total;
- CWorld::FindObjectsIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil,
- !!ScriptParams[6], !!ScriptParams[7], !!ScriptParams[8], !!ScriptParams[9], !!ScriptParams[10]);
- UpdateCompareFlag(total > 0);
- return 0;
- }
- case COMMAND_START_DRUG_RUN:
- CPlane::CreateIncomingCesna();
- return 0;
- case COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED:
- UpdateCompareFlag(CPlane::HasCesnaLanded());
- return 0;
- case COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN:
- UpdateCompareFlag(CPlane::HasCesnaBeenDestroyed());
- return 0;
- case COMMAND_SAVE_PLAYER_FROM_FIRES:
- CollectParameters(&m_nIp, 1);
- gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f);
- return 0;
- case COMMAND_DISPLAY_TEXT:
- {
- CollectParameters(&m_nIp, 2);
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
- uint16 len = CMessages::GetWideStringLength(text);
- for (uint16 i = 0; i < len; i++)
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = text[i];
- for (uint16 i = len; i < SCRIPT_TEXT_MAX_LENGTH; i++)
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = 0;
- ++CTheScripts::NumberOfIntroTextLinesThisFrame;
- return 0;
- }
- case COMMAND_SET_TEXT_SCALE:
- {
- CollectParameters(&m_nIp, 2);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleX = *(float*)&ScriptParams[0];
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleY = *(float*)&ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_TEXT_COLOUR:
- {
- CollectParameters(&m_nIp, 4);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sColor =
- CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);
- return 0;
- }
- case COMMAND_SET_TEXT_JUSTIFY:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bJustify = (ScriptParams[0] != 0);
- return 0;
- }
- case COMMAND_SET_TEXT_CENTRE:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bCentered = (ScriptParams[0] != 0);
- return 0;
- }
- case COMMAND_SET_TEXT_WRAPX:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0];
- return 0;
- }
- case COMMAND_SET_TEXT_CENTRE_SIZE:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0];
- return 0;
- }
- case COMMAND_SET_TEXT_BACKGROUND:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0);
- return 0;
- }
- case COMMAND_SET_TEXT_BACKGROUND_COLOUR:
- {
- CollectParameters(&m_nIp, 4);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sBackgroundColor =
- CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);
- return 0;
- }
- case COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0);
- return 0;
- }
- case COMMAND_SET_TEXT_PROPORTIONAL:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0);
- return 0;
- }
- case COMMAND_SET_TEXT_FONT:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_nFont = ScriptParams[0];
- return 0;
- }
- case COMMAND_INDUSTRIAL_PASSED:
- CStats::IndustrialPassed = true;
- DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_COMMERCIAL_OPEN);
- return 0;
- case COMMAND_COMMERCIAL_PASSED:
- CStats::CommercialPassed = true;
- DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_SUBURBAN_OPEN);
- return 0;
- case COMMAND_SUBURBAN_PASSED:
- CStats::SuburbanPassed = true;
- return 0;
- case COMMAND_ROTATE_OBJECT:
- {
- CollectParameters(&m_nIp, 4);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- float heading = LimitAngleOnCircle(
- RADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y)));
- float headingTarget = *(float*)&ScriptParams[1];
-#ifdef FIX_BUGS
- float rotateBy = *(float*)&ScriptParams[2] * CTimer::GetTimeStepFix();
-#else
- float rotateBy = *(float*)&ScriptParams[2];
-#endif
- if (headingTarget == heading) { // using direct comparasion here is fine
- UpdateCompareFlag(true);
- return 0;
- }
- float angleClockwise = LimitAngleOnCircle(headingTarget - heading);
- float angleCounterclockwise = LimitAngleOnCircle(heading - headingTarget);
- float newHeading;
- if (angleClockwise < angleCounterclockwise)
- newHeading = rotateBy < angleClockwise ? heading + rotateBy : headingTarget;
- else
- newHeading = rotateBy < angleCounterclockwise ? heading - rotateBy : headingTarget;
- bool obstacleInPath = false;
- if (ScriptParams[3]) {
- CVector pos = pObject->GetPosition();
- tmp_matrix.SetRotateZ(DEGTORAD(newHeading));
- tmp_matrix.GetPosition() += pos;
- CColModel* pColModel = pObject->GetColModel();
- CVector cp1 = tmp_matrix * pColModel->boundingBox.min;
- CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);
- CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);
- CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);
- int16 collisions;
- CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos,
- Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))),
- Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))),
- Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))),
- Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))),
- &collisions, 2, nil, false, true, true, false, false);
- if (collisions > 0)
- obstacleInPath = true;
- }
- if (obstacleInPath) {
- UpdateCompareFlag(true);
- return 0;
- }
- pObject->SetHeading(DEGTORAD(newHeading));
- pObject->GetMatrix().UpdateRW();
- pObject->UpdateRwFrame();
- UpdateCompareFlag(newHeading == headingTarget); // using direct comparasion here is fine
- return 0;
- }
- case COMMAND_SLIDE_OBJECT:
- {
- CollectParameters(&m_nIp, 8);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CVector pos = pObject->GetPosition();
- CVector posTarget = *(CVector*)&ScriptParams[1];
-#ifdef FIX_BUGS
- CVector slideBy = *(CVector*)&ScriptParams[4] * CTimer::GetTimeStepFix();
-#else
- CVector slideBy = *(CVector*)&ScriptParams[4];
-#endif
- if (posTarget == pos) { // using direct comparasion here is fine
- UpdateCompareFlag(true);
- return 0;
- }
- CVector posDiff = pos - posTarget;
- CVector newPosition;
- if (posDiff.x < 0)
- newPosition.x = -posDiff.x < slideBy.x ? posTarget.x : pos.x + slideBy.x;
- else
- newPosition.x = posDiff.x < slideBy.x ? posTarget.x : pos.x - slideBy.x;
- if (posDiff.y < 0)
- newPosition.y = -posDiff.y < slideBy.y ? posTarget.y : pos.y + slideBy.y;
- else
- newPosition.y = posDiff.y < slideBy.y ? posTarget.y : pos.y - slideBy.y;
- if (posDiff.z < 0)
- newPosition.z = -posDiff.z < slideBy.z ? posTarget.z : pos.z + slideBy.z;
- else
- newPosition.z = posDiff.z < slideBy.z ? posTarget.z : pos.z - slideBy.z;
- bool obstacleInPath = false;
- if (ScriptParams[7]) {
- tmp_matrix = pObject->GetMatrix();
- tmp_matrix.GetPosition() = newPosition;
- CColModel* pColModel = pObject->GetColModel();
- CVector cp1 = tmp_matrix * pColModel->boundingBox.min;
- CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);
- CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);
- CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);
- int16 collisions;
- CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition,
- Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))),
- Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))),
- Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))),
- Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))),
- &collisions, 2, nil, false, true, true, false, false);
- if (collisions > 0)
- obstacleInPath = true;
- }
- if (obstacleInPath) {
- UpdateCompareFlag(true);
- return 0;
- }
- pObject->Teleport(newPosition);
- UpdateCompareFlag(newPosition == posTarget); // using direct comparasion here is fine
- return 0;
- }
- case COMMAND_REMOVE_CHAR_ELEGANTLY:
- {
- CollectParameters(&m_nIp, 1);
- 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{
- pPed->CharCreatedBy = RANDOM_CHAR;
- pPed->bRespondsToThreats = true;
- pPed->bScriptObjectiveCompleted = false;
- pPed->ClearLeader();
- --CPopulation::ms_nTotalMissionPeds;
- pPed->bFadeOut = true;
- }
- }
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
- return 0;
- }
- case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_IS_NASTY_GAME:
- UpdateCompareFlag(CGame::nastyGame);
- return 0;
- case COMMAND_UNDRESS_CHAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- char name[KEY_LENGTH_IN_SCRIPT];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, name);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- name[i] = tolower(name[i]);
- int mi = pPed->GetModelIndex();
- pPed->DeleteRwObject();
- if (pPed->IsPlayer())
- mi = 0;
- CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CWorld::Remove(pPed);
- return 0;
- }
- case COMMAND_DRESS_CHAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- int mi = pPed->GetModelIndex();
- pPed->m_modelIndex = -1;
- pPed->SetModelIndex(mi);
- CWorld::Add(pPed);
- return 0;
- }
- case COMMAND_START_CHASE_SCENE:
- CollectParameters(&m_nIp, 1);
- CTimer::Suspend();
- CStreaming::DeleteAllRwObjects();
- CRecordDataForChase::StartChaseScene(*(float*)&ScriptParams[0]);
- CTimer::Resume();
- return 0;
- case COMMAND_STOP_CHASE_SCENE:
- CRecordDataForChase::CleanUpChaseScene();
- return 0;
- case COMMAND_IS_EXPLOSION_IN_AREA:
- {
- CollectParameters(&m_nIp, 7);
- float infX = *(float*)&ScriptParams[1];
- float infY = *(float*)&ScriptParams[2];
- float infZ = *(float*)&ScriptParams[3];
- float supX = *(float*)&ScriptParams[4];
- float supY = *(float*)&ScriptParams[5];
- float supZ = *(float*)&ScriptParams[6];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[4];
- supX = *(float*)&ScriptParams[1];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[5];
- supY = *(float*)&ScriptParams[2];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[6];
- supZ = *(float*)&ScriptParams[3];
- }
- UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
- infX, supX, infY, supY, infZ, supZ));
- return 0;
- }
- case COMMAND_IS_EXPLOSION_IN_ZONE:
- {
- CollectParameters(&m_nIp, 1);
- char zone[KEY_LENGTH_IN_SCRIPT];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
- if (zone_id != -1)
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
- UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
- pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));
- return 0;
- }
- case COMMAND_START_DRUG_DROP_OFF:
- CPlane::CreateDropOffCesna();
- return 0;
- case COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN:
- UpdateCompareFlag(CPlane::HasDropOffCesnaBeenShotDown());
- return 0;
- case COMMAND_FIND_DROP_OFF_PLANE_COORDINATES:
- {
- CVector pos = CPlane::FindDropOffCesnaCoordinates();
- *(CVector*)&ScriptParams[0] = pos;
- StoreParameters(&m_nIp, 3);
- return 0;
- }
- 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);
- return 0;
- }
- case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:
- {
- CollectParameters(&m_nIp, 5);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- CVector offset = *(CVector*)&ScriptParams[2];
- CPhysical::PlacePhysicalRelativeToOtherPhysical(pVehicle, pObject, offset);
- return 0;
- }
- case COMMAND_MAKE_OBJECT_TARGETTABLE:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CPlayerPed* pPlayerPed = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
- script_assert(pPlayerPed);
- pPlayerPed->MakeObjectTargettable(ScriptParams[0]);
- return 0;
- }
- case COMMAND_ADD_ARMOUR_TO_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPlayerPed);
- pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
- return 0;
- }
- case COMMAND_ADD_ARMOUR_TO_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->m_fArmour = clamp(pPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
- return 0;
- }
- case COMMAND_OPEN_GARAGE:
- {
- CollectParameters(&m_nIp, 1);
- CGarages::OpenGarage(ScriptParams[0]);
- return 0;
- }
- case COMMAND_CLOSE_GARAGE:
- {
- CollectParameters(&m_nIp, 1);
- CGarages::CloseGarage(ScriptParams[0]);
- return 0;
- }
- case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
- {
- CollectParameters(&m_nIp, 4);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- if (pPed->bInVehicle){
- if (pPed->m_pMyVehicle->bIsBus)
- pPed->bRenderPedInCar = true;
- if (pPed->m_pMyVehicle->pDriver == pPed){
- pPed->m_pMyVehicle->RemoveDriver();
- pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- pPed->m_pMyVehicle->bEngineOn = false;
- pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- }else{
- pPed->m_pMyVehicle->RemovePassenger(pPed);
- }
- pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f);
- pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f);
- }
- pPed->bInVehicle = false;
- pPed->m_pMyVehicle = nil;
- pPed->SetPedState(PED_IDLE);
- 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->RemoveInCarAnims();
- if (pPed->m_pVehicleAnim)
- pPed->m_pVehicleAnim->blendDelta = -1000.0f;
- pPed->m_pVehicleAnim = nil;
- pPed->RestartNonPartialAnims();
- pPed->SetMoveState(PEDMOVE_NONE);
- CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel();
- pPed->Teleport(pos);
- CTheScripts::ClearSpaceForMissionEntity(pos, pPed);
- return 0;
- }
- case COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE:
- {
- CollectParameters(&m_nIp, 6);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float range = *(float*)&ScriptParams[3];
- int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];
- int16 total;
- CEntity* apEntities[16];
- CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true);
- if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities);
- if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities);
- CEntity* pClosestEntity = nil;
- float min_dist = 2.0f * range;
- for (int i = 0; i < total; i++) {
- float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
- if (dist < min_dist) {
- min_dist = dist;
- pClosestEntity = apEntities[i];
- }
- }
- if (pClosestEntity) {
- pClosestEntity->bIsVisible = (ScriptParams[5] != 0);
- CTheScripts::AddToInvisibilitySwapArray(pClosestEntity, ScriptParams[5] != 0);
- }
- return 0;
- }
- case COMMAND_HAS_CHAR_SPOTTED_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget));
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_HAIL_TAXI:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_HAIL_TAXI);
- return 0;
- }
- case COMMAND_HAS_OBJECT_BEEN_DAMAGED:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- UpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible);
- return 0;
- }
- case COMMAND_START_KILL_FRENZY_HEADSHOT:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 8);
- CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],
- ScriptParams[3], text, ScriptParams[4], ScriptParams[5],
- ScriptParams[6], ScriptParams[7] != 0, true);
- return 0;
- }
- case COMMAND_ACTIVATE_MILITARY_CRANE:
- {
- CollectParameters(&m_nIp, 10);
- float infX = *(float*)&ScriptParams[2];
- float infY = *(float*)&ScriptParams[3];
- float supX = *(float*)&ScriptParams[4];
- float supY = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[4];
- supX = *(float*)&ScriptParams[2];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[5];
- supY = *(float*)&ScriptParams[3];
- }
- CCranes::ActivateCrane(infX, supX, infY, supY,
- *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
- DEGTORAD(*(float*)&ScriptParams[9]), false, true,
- *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
- return 0;
- }
- case COMMAND_WARP_PLAYER_INTO_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
- pPed->WarpPedIntoCar(pVehicle);
- return 0;
- }
- case COMMAND_WARP_CHAR_INTO_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
- pPed->WarpPedIntoCar(pVehicle);
- return 0;
- }
- //case COMMAND_SWITCH_CAR_RADIO:
- //case COMMAND_SET_AUDIO_STREAM:
- case COMMAND_PRINT_WITH_2_NUMBERS_BIG:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 4);
- CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_3_NUMBERS_BIG:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 5);
- CMessages::AddBigMessageWithNumber(text, ScriptParams[3], ScriptParams[4] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_4_NUMBERS_BIG:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 6);
- CMessages::AddBigMessageWithNumber(text, ScriptParams[4], ScriptParams[5] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_5_NUMBERS_BIG:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 7);
- CMessages::AddBigMessageWithNumber(text, ScriptParams[5], ScriptParams[6] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
- return 0;
- }
- case COMMAND_PRINT_WITH_6_NUMBERS_BIG:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 8);
- CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
- return 0;
- }
- case COMMAND_SET_CHAR_WAIT_STATE:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->SetWaitState((eWaitState)ScriptParams[1], ScriptParams[2] >= 0 ? &ScriptParams[2] : nil);
- return 0;
- }
- case COMMAND_SET_CAMERA_BEHIND_PLAYER:
- TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString();
- return 0;
- case COMMAND_SET_MOTION_BLUR:
- CollectParameters(&m_nIp, 1);
- TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]);
- return 0;
- case COMMAND_PRINT_STRING_IN_STRING:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* string = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 2);
- CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string);
- return 0;
- }
- case COMMAND_CREATE_RANDOM_CHAR:
- {
- CollectParameters(&m_nIp, 3);
- CZoneInfo zoneinfo;
- CTheZones::GetZoneInfoForTimeOfDay(&CWorld::Players[CWorld::PlayerInFocus].GetPos(), &zoneinfo);
- int mi;
- ePedType pedtype = PEDTYPE_COP;
- int attempt = 0;
- while (pedtype != PEDTYPE_CIVMALE && pedtype != PEDTYPE_CIVFEMALE && attempt < 5) {
- mi = CPopulation::ChooseCivilianOccupation(zoneinfo.pedGroup);
- if (CModelInfo::GetModelInfo(mi)->GetRwObject())
- pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;
- attempt++;
- }
- if (!CModelInfo::GetModelInfo(mi)->GetRwObject()) {
- mi = MI_MALE01;
- pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;
- }
- CPed* ped = new CCivilianPed(pedtype, mi);
- ped->CharCreatedBy = MISSION_CHAR;
- ped->bRespondsToThreats = false;
- ped->bAllowMedicsToReviveMe = false;
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pos.z += 1.0f;
- ped->SetPosition(pos);
- ped->SetOrientation(0.0f, 0.0f, 0.0f);
- CTheScripts::ClearSpaceForMissionEntity(pos, ped);
- CWorld::Add(ped);
- ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
- CPopulation::ms_nTotalMissionPeds++;
- ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
- StoreParameters(&m_nIp, 1);
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR);
- return 0;
- }
- case COMMAND_SET_2_REPEATED_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, nil, nil, nil, nil);
- return 0;
- }
- case COMMAND_SET_2_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, nil, nil, nil, nil);
- return 0;
- }
- case COMMAND_SET_3_REPEATED_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, nil, nil, nil);
- return 0;
- }
- case COMMAND_SET_3_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, nil, nil, nil);
- return 0;
- }
- case COMMAND_SET_4_REPEATED_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, nil, nil);
- return 0;
- }
- case COMMAND_SET_4_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil);
- return 0;
- }
- case COMMAND_IS_SNIPER_BULLET_IN_AREA:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ));
- return 0;
- }
- case COMMAND_GIVE_PLAYER_DETONATOR:
- CGarages::GivePlayerDetonator();
- return 0;
- //case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:
- case COMMAND_SET_OBJECT_VELOCITY:
- {
- CollectParameters(&m_nIp, 4);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- pObject->SetMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED);
- return 0;
- }
- case COMMAND_SET_OBJECT_COLLISION:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- pObject->bUsesCollision = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_IS_ICECREAM_JINGLE_ON:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- // Adding this check to correspond to command name.
- // All original game scripts always assume that the vehicle is actually Mr. Whoopee,
- // but maybe there are mods that use it as "is alarm activated"?
- script_assert(pVehicle->GetModelIndex() == MI_MRWHOOP);
- UpdateCompareFlag(pVehicle->m_bSirenOrAlarm);
- return 0;
- }
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands900To999(int32 command)
-{
- char str[52];
- char onscreen_str[KEY_LENGTH_IN_SCRIPT];
- switch (command) {
- case COMMAND_PRINT_STRING_IN_STRING_NOW:
- {
- wchar* source = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* pstr = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CollectParameters(&m_nIp, 2);
- CMessages::AddMessageJumpQWithString(source, ScriptParams[0], ScriptParams[1], pstr);
- return 0;
- }
- //case COMMAND_PRINT_STRING_IN_STRING_SOON:
- case COMMAND_SET_5_REPEATED_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, nil);
- return 0;
- }
- case COMMAND_SET_5_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, nil);
- return 0;
- }
- case COMMAND_SET_6_REPEATED_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, text6);
- return 0;
- }
- case COMMAND_SET_6_PHONE_MESSAGES:
- {
- CollectParameters(&m_nIp, 1);
- wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6);
- return 0;
- }
- case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY:
- {
- CollectParameters(&m_nIp, 6);
- float infX = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[3];
- float supX = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[3];
- float infY = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[4];
- float supY = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[4];
- float infZ = *(float*)&ScriptParams[2] - *(float*)&ScriptParams[5];
- float supZ = *(float*)&ScriptParams[2] + *(float*)&ScriptParams[5];
- if (infX > supX) {
- float tmp = infX;
- infX = supX;
- supX = tmp;
- }
- if (infY > supY) {
- float tmp = infY;
- infY = supY;
- supY = tmp;
- }
- if (infZ > supZ) {
- float tmp = infZ;
- infZ = supZ;
- supZ = tmp;
- }
- int16 total;
- CWorld::FindMissionEntitiesIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, true, true, true);
- UpdateCompareFlag(total > 0);
- return 0;
- }
- case COMMAND_LOAD_ALL_MODELS_NOW:
- CTimer::Stop();
- CStreaming::LoadAllRequestedModels(false);
- CTimer::Update();
- return 0;
- case COMMAND_ADD_TO_OBJECT_VELOCITY:
- {
- CollectParameters(&m_nIp, 4);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- pObject->SetMoveSpeed(pObject->GetMoveSpeed() + METERS_PER_SECOND_TO_GAME_SPEED * *(CVector*)&ScriptParams[1]);
- return 0;
- }
- case COMMAND_DRAW_SPRITE:
- {
- CollectParameters(&m_nIp, 9);
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true;
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = ScriptParams[0] - 1;
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect(
- *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3], *(float*)&ScriptParams[2] + *(float*)&ScriptParams[4]);
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]);
- CTheScripts::NumberOfIntroRectanglesThisFrame++;
- return 0;
- }
- case COMMAND_DRAW_RECT:
- {
- CollectParameters(&m_nIp, 8);
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true;
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = -1;
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect(
- *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3]);
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7]);
- CTheScripts::NumberOfIntroRectanglesThisFrame++;
- return 0;
- }
- case COMMAND_LOAD_SPRITE:
- {
- CollectParameters(&m_nIp, 1);
- strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- str[i] = tolower(str[i]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- int slot = CTxdStore::FindTxdSlot("script");
- CTxdStore::PushCurrentTxd();
- CTxdStore::SetCurrentTxd(slot);
- CTheScripts::ScriptSprites[ScriptParams[0] - 1].SetTexture(str);
- CTxdStore::PopCurrentTxd();
- return 0;
- }
- case COMMAND_LOAD_TEXTURE_DICTIONARY:
- {
- strcpy(str, "models\\");
- strncpy(str + sizeof("models\\"), (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- strcat(str, ".txd");
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- int slot = CTxdStore::FindTxdSlot("script");
- if (slot == -1)
- slot = CTxdStore::AddTxdSlot("script");
- CTxdStore::LoadTxd(slot, str);
- CTxdStore::AddRef(slot);
- return 0;
- }
- case COMMAND_REMOVE_TEXTURE_DICTIONARY:
- {
- for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)
- CTheScripts::ScriptSprites[i].Delete();
- CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script"));
- return 0;
- }
- case COMMAND_SET_OBJECT_DYNAMIC:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- if (ScriptParams[1]) {
- if (pObject->bIsStatic) {
- pObject->SetIsStatic(false);
- pObject->AddToMovingList();
- }
- }
- else {
- if (!pObject->bIsStatic) {
- pObject->SetIsStatic(true);
- pObject->RemoveFromMovingList();
- }
- }
- return 0;
- }
- case COMMAND_SET_CHAR_ANIM_SPEED:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetFirstAssociation(pPed->GetClump());
- if (pAssoc)
- pAssoc->speed = *(float*)&ScriptParams[1];
- return 0;
- }
- case COMMAND_PLAY_MISSION_PASSED_TUNE:
- {
- CollectParameters(&m_nIp, 1);
- DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);
- DMAudio.PlayFrontEndTrack(ScriptParams[0] + STREAMED_SOUND_MISSION_COMPLETED - 1, 0);
- return 0;
- }
- case COMMAND_CLEAR_AREA:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CWorld::ClearExcitingStuffFromArea(pos, *(float*)&ScriptParams[3], ScriptParams[4]);
- return 0;
- }
- case COMMAND_FREEZE_ONSCREEN_TIMER:
- CollectParameters(&m_nIp, 1);
- CUserDisplay::OnscnTimer.m_bDisabled = ScriptParams[0] != 0;
- return 0;
- case COMMAND_SWITCH_CAR_SIREN:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0;
- return 0;
- }
- case COMMAND_SWITCH_PED_ROADS_ON_ANGLED:
- {
- CollectParameters(&m_nIp, 7);
- ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
- *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 1);
- return 0;
- }
- case COMMAND_SWITCH_PED_ROADS_OFF_ANGLED:
- CollectParameters(&m_nIp, 7);
- ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
- *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 0);
- return 0;
- case COMMAND_SWITCH_ROADS_ON_ANGLED:
- CollectParameters(&m_nIp, 7);
- ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
- *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 1);
- return 0;
- case COMMAND_SWITCH_ROADS_OFF_ANGLED:
- CollectParameters(&m_nIp, 7);
- ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
- *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0);
- return 0;
- case COMMAND_SET_CAR_WATERTIGHT:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- CAutomobile* pCar = (CAutomobile*)pVehicle;
- pCar->bWaterTight = ScriptParams[1] != 0;
- return 0;
- }
- case COMMAND_ADD_MOVING_PARTICLE_EFFECT:
- {
- CollectParameters(&m_nIp, 12);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float size = Max(0.0f, *(float*)&ScriptParams[7]);
- eParticleObjectType type = (eParticleObjectType)ScriptParams[0];
- RwRGBA color;
- if (type == POBJECT_SMOKE_TRAIL){
- color.alpha = -1;
- color.red = ScriptParams[8];
- color.green = ScriptParams[9];
- color.blue = ScriptParams[10];
- }else{
- color.alpha = color.red = color.blue = color.green = 0;
- }
- CVector target = *(CVector*)&ScriptParams[4];
- CParticleObject::AddObject(type, pos, target, size, ScriptParams[11], color, 1);
- return 0;
- }
- case COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bDontDragMeOutCar = ScriptParams[1] != 0;
- return 0;
- }
- case COMMAND_TURN_CAR_TO_FACE_COORD:
- {
- CollectParameters(&m_nIp, 3);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- const CVector& pos = pVehicle->GetPosition();
- float heading = CGeneral::GetATanOfXY(pos.y - *(float*)&ScriptParams[2], pos.x - *(float*)&ScriptParams[1]) + HALFPI;
- if (heading > TWOPI)
- heading -= TWOPI;
- pVehicle->SetHeading(heading);
- return 0;
- }
- case COMMAND_IS_CRANE_LIFTING_CAR:
- {
- CollectParameters(&m_nIp, 3);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[2]);
- UpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle));
- return 0;
- }
- case COMMAND_DRAW_SPHERE:
- {
- CollectParameters(&m_nIp, 4);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- C3dMarkers::PlaceMarkerSet((uintptr)this + m_nIp, MARKERTYPE_CYLINDER, pos, *(float*)&ScriptParams[3],
- SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A,
- SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0);
- return 0;
- }
- case COMMAND_SET_CAR_STATUS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->SetStatus((eEntityStatus)ScriptParams[1]);
- return 0;
- }
- case COMMAND_IS_CHAR_MALE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(pPed->m_nPedType != PEDTYPE_CIVFEMALE && pPed->m_nPedType != PEDTYPE_PROSTITUTE);
- return 0;
- }
- case COMMAND_SCRIPT_NAME:
- {
- strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- str[i] = tolower(str[i]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- strncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT);
- return 0;
- }
- case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL:
- {
- CollectParameters(&m_nIp, 3);
- CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- case COMMAND_FIND_DRUG_PLANE_COORDINATES:
- *(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates();
- StoreParameters(&m_nIp, 3);
- return 0;
- case COMMAND_SAVE_INT_TO_DEBUG_FILE:
- // TODO: implement something here
- CollectParameters(&m_nIp, 1);
- return 0;
- case COMMAND_SAVE_FLOAT_TO_DEBUG_FILE:
- CollectParameters(&m_nIp, 1);
- return 0;
- case COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE:
- return 0;
- case COMMAND_POLICE_RADIO_MESSAGE:
- CollectParameters(&m_nIp, 3);
- DMAudio.PlaySuspectLastSeen(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]);
- return 0;
- case COMMAND_SET_CAR_STRONG:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bTakeLessDamage = ScriptParams[1] != 0;
- return 0;
- }
- case COMMAND_REMOVE_ROUTE:
- CollectParameters(&m_nIp, 1);
- CRouteNode::RemoveRoute(ScriptParams[0]);
- return 0;
- case COMMAND_SWITCH_RUBBISH:
- CollectParameters(&m_nIp, 1);
- CRubbish::SetVisibility(ScriptParams[0] != 0);;
- return 0;
- case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA:
- {
- CollectParameters(&m_nIp, 6);
- float x1 = *(float*)&ScriptParams[0];
- float y1 = *(float*)&ScriptParams[1];
- float z1 = *(float*)&ScriptParams[2];
- float x2 = *(float*)&ScriptParams[3];
- float y2 = *(float*)&ScriptParams[4];
- float z2 = *(float*)&ScriptParams[5];
- CParticleObject* tmp = CParticleObject::pCloseListHead;
- while (tmp) {
- CParticleObject* next = tmp->m_pNext;
- if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2))
- tmp->RemoveObject();
- tmp = next;
- }
- tmp = CParticleObject::pFarListHead;
- while (tmp) {
- CParticleObject* next = tmp->m_pNext;
- if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2))
- tmp->RemoveObject();
- tmp = next;
- }
- return 0;
- }
- case COMMAND_SWITCH_STREAMING:
- CollectParameters(&m_nIp, 1);
- CStreaming::ms_disableStreaming = ScriptParams[0] == 0;
- return 0;
- case COMMAND_IS_GARAGE_OPEN:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CGarages::IsGarageOpen(ScriptParams[0]));
- return 0;
- case COMMAND_IS_GARAGE_CLOSED:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0]));
- return 0;
- case COMMAND_START_CATALINA_HELI:
- CHeli::StartCatalinaFlyBy();
- return 0;
- case COMMAND_CATALINA_HELI_TAKE_OFF:
- CHeli::CatalinaTakeOff();
- return 0;
- case COMMAND_REMOVE_CATALINA_HELI:
- CHeli::RemoveCatalinaHeli();
- return 0;
- case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN:
- UpdateCompareFlag(CHeli::HasCatalinaBeenShotDown());
- return 0;
- case COMMAND_SWAP_NEAREST_BUILDING_MODEL:
- {
- CollectParameters(&m_nIp, 6);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float radius = *(float*)&ScriptParams[3];
- int mi1 = ScriptParams[4] >= 0 ? ScriptParams[4] : CTheScripts::UsedObjectArray[-ScriptParams[4]].index;
- int mi2 = ScriptParams[5] >= 0 ? ScriptParams[5] : CTheScripts::UsedObjectArray[-ScriptParams[5]].index;
- int16 total;
- CEntity* apEntities[16];
- CWorld::FindObjectsOfTypeInRange(mi1, pos, radius, true, &total, 16, apEntities, true, false, false, false, false);
- if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities);
- if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities);
- CEntity* pClosestEntity = nil;
- float min_dist = 2.0f * radius;
- for (int i = 0; i < total; i++) {
- float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
- if (dist < min_dist) {
- min_dist = dist;
- pClosestEntity = apEntities[i];
- }
- }
- if (!pClosestEntity) {
- printf("Failed to find building\n");
- return 0;
- }
- CBuilding* pReplacedBuilding = ((CBuilding*)pClosestEntity);
- pReplacedBuilding->ReplaceWithNewModel(mi2);
- CTheScripts::AddToBuildingSwapArray(pReplacedBuilding, mi1, mi2);
- return 0;
- }
- case COMMAND_SWITCH_WORLD_PROCESSING:
- CollectParameters(&m_nIp, 1);
- CWorld::bProcessCutsceneOnly = ScriptParams[0] == 0;
- return 0;
- case COMMAND_REMOVE_ALL_PLAYER_WEAPONS:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- pPed->ClearWeapons();
- return 0;
- }
- case COMMAND_GRAB_CATALINA_HELI:
- {
- CHeli* pHeli = CHeli::FindPointerToCatalinasHeli();
- ScriptParams[0] = pHeli ? CPools::GetVehiclePool()->GetIndex(pHeli) : -1;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_CLEAR_AREA_OF_CARS:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- CWorld::ClearCarsFromArea(infX, infY, infZ, supX, supY, supZ);
- return 0;
- }
- case COMMAND_SET_ROTATING_GARAGE_DOOR:
- CollectParameters(&m_nIp, 1);
- CGarages::SetGarageDoorToRotate(ScriptParams[0]);
- return 0;
- case COMMAND_ADD_SPHERE:
- {
- CollectParameters(&m_nIp, 4);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float radius = *(float*)&ScriptParams[3];
- CTheScripts::GetActualScriptSphereIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- ScriptParams[0] = CTheScripts::AddScriptSphere((uintptr)this + m_nIp, pos, radius);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_REMOVE_SPHERE:
- CollectParameters(&m_nIp, 1);
- CTheScripts::RemoveScriptSphere(ScriptParams[0]);
- return 0;
- case COMMAND_CATALINA_HELI_FLY_AWAY:
- CHeli::MakeCatalinaHeliFlyAway();
- return 0;
- case COMMAND_SET_EVERYONE_IGNORE_PLAYER:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- if (ScriptParams[1]) {
- pPed->m_pWanted->m_bIgnoredByEveryone = true;
- CWorld::StopAllLawEnforcersInTheirTracks();
- }
- else {
- pPed->m_pWanted->m_bIgnoredByEveryone = false;
- }
- return 0;
- }
- case COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;
- ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;
- ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_IS_PHONE_DISPLAYING_MESSAGE:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0]));
- return 0;
- case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING:
- {
- script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
- uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
- wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
- strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CUserDisplay::OnscnTimer.AddClock(var, onscreen_str);
- return 0;
- }
- case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING:
- {
- script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
- uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
- CollectParameters(&m_nIp, 1);
- wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
- strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str);
- return 0;
- }
- case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK:
- {
- CollectParameters(&m_nIp, 4);
- if (CCarCtrl::NumRandomCars >= 30)
- return 0;
- int attempts;
- int model = -1;
- int index = CGeneral::GetRandomNumberInRange(0, 50);
- for (attempts = 0; attempts < 50; attempts++) {
- if (model != -1)
- break;
- model = CStreaming::ms_vehiclesLoaded[index];
- if (model == -1)
- continue;
- // desperatly want to believe this was inlined :|
- CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(model);
- script_assert(pInfo->GetModelType() == MITYPE_VEHICLE);
- CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo;
- if (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR) {
- switch (model) {
- case MI_LANDSTAL:
- case MI_LINERUN:
- case MI_FIRETRUCK:
- case MI_TRASH:
- case MI_STRETCH:
- case MI_MULE:
- case MI_AMBULAN:
- case MI_FBICAR:
- case MI_MRWHOOP:
- case MI_BFINJECT:
- case MI_CORPSE:
- case MI_POLICE:
- case MI_ENFORCER:
- case MI_SECURICA:
- case MI_PREDATOR:
- case MI_BUS:
- case MI_RHINO:
- case MI_BARRACKS:
- case MI_TRAIN:
- case MI_CHOPPER:
- 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_AIRTRAIN:
- case MI_DEADDODO:
- case MI_SPEEDER:
- case MI_REEFER:
- 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:
- model = -1;
- break;
- case MI_IDAHO:
- case MI_STINGER:
- case MI_PEREN:
- case MI_SENTINEL:
- case MI_PATRIOT:
- case MI_MANANA:
- case MI_INFERNUS:
- case MI_BLISTA:
- case MI_PONY:
- case MI_CHEETAH:
- case MI_MOONBEAM:
- case MI_ESPERANT:
- case MI_TAXI:
- case MI_KURUMA:
- case MI_BOBCAT:
- case MI_BANSHEE:
- case MI_CABBIE:
- case MI_STALLION:
- case MI_RUMPO:
- case 151:
- case 152:
- case 153:
- break;
- default:
- printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]);
- model = -1;
- break;
- }
- }
- else
- model = -1;
- if (++index >= 50)
- index = 0;
- }
- if (model == -1)
- return 0;
- CVehicle* car;
- if (!CModelInfo::IsBikeModel(model))
- car = new CAutomobile(model, RANDOM_VEHICLE);
- CVector pos = *(CVector*)&ScriptParams[0];
- pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();
- car->SetPosition(pos);
- car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3]));
- CTheScripts::ClearSpaceForMissionEntity(pos, car);
- car->SetStatus(STATUS_ABANDONED);
- car->bIsLocked = false;
- car->bIsCarParkVehicle = true;
- CCarCtrl::JoinCarWithRoadSystem(car);
- car->AutoPilot.m_nCarMission = MISSION_NONE;
- 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);
- CWorld::Add(car);
- return 0;
- }
- case COMMAND_IS_COLLISION_IN_MEMORY:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]);
- return 0;
- case COMMAND_SET_WANTED_MULTIPLIER:
- CollectParameters(&m_nIp, 1);
- FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0];
- return 0;
- case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER:
- TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
- return 0;
- case COMMAND_IS_CAR_VISIBLY_DAMAGED:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(pVehicle->bIsDamaged);
- return 0;
- }
- case COMMAND_DOES_OBJECT_EXIST:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0]));
- return 0;
- case COMMAND_LOAD_SCENE:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- CTimer::Stop();
- CStreaming::LoadScene(pos);
- CTimer::Update();
- return 0;
- }
- case COMMAND_ADD_STUCK_CAR_CHECK:
- {
- CollectParameters(&m_nIp, 3);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CTheScripts::StuckCars.AddCarToCheck(ScriptParams[0], *(float*)&ScriptParams[1], ScriptParams[2]);
- return 0;
- }
- case COMMAND_REMOVE_STUCK_CAR_CHECK:
- {
- CollectParameters(&m_nIp, 1);
- CTheScripts::StuckCars.RemoveCarFromCheck(ScriptParams[0]);
- return 0;
- }
- case COMMAND_IS_CAR_STUCK:
- CollectParameters(&m_nIp, 1);
- UpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0]));
- return 0;
- case COMMAND_LOAD_MISSION_AUDIO:
- strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- str[i] = tolower(str[i]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- DMAudio.PreloadMissionAudio(str);
- return 0;
- case COMMAND_HAS_MISSION_AUDIO_LOADED:
- UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1);
- return 0;
- case COMMAND_PLAY_MISSION_AUDIO:
- DMAudio.PlayLoadedMissionAudio();
- return 0;
- case COMMAND_HAS_MISSION_AUDIO_FINISHED:
- UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished());
- return 0;
- case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
- *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition();
- *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node);
- StoreParameters(&m_nIp, 4);
- return 0;
- }
- case COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED:
- {
- CollectParameters(&m_nIp, 2);
- UpdateCompareFlag(CGarages::HasImportExportGarageCollectedThisCar(ScriptParams[0], ScriptParams[1] - 1));
- return 0;
- }
- case COMMAND_CLEAR_THIS_PRINT:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CMessages::ClearThisPrint(text);
- return 0;
- }
- case COMMAND_CLEAR_THIS_BIG_PRINT:
- {
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CMessages::ClearThisBigPrint(text);
- return 0;
- }
- case COMMAND_SET_MISSION_AUDIO_POSITION:
- {
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z);
- return 0;
- }
- case COMMAND_ACTIVATE_SAVE_MENU:
- FrontEndMenuManager.m_bSaveMenuActive = true;
- return 0;
- case COMMAND_HAS_SAVE_GAME_FINISHED:
- UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive);
- return 0;
- case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE:
- CollectParameters(&m_nIp, 1);
- CGarages::SetLeaveCameraForThisGarage(ScriptParams[0]);
- return 0;
- case COMMAND_ADD_BLIP_FOR_PICKUP_OLD:
- {
- CollectParameters(&m_nIp, 3);
- CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_BLIP_FOR_PICKUP:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH);
- CRadar::ChangeBlipScale(handle, 3);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;
- CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
- int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH);
- CRadar::SetBlipSprite(handle, ScriptParams[1]);
- ScriptParams[0] = handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_PED_DENSITY_MULTIPLIER:
- CollectParameters(&m_nIp, 1);
- CPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0];
- return 0;
- case COMMAND_FORCE_RANDOM_PED_TYPE:
- CollectParameters(&m_nIp, 1);
- CPopulation::m_AllRandomPedsThisType = ScriptParams[0];
- return 0;
- case COMMAND_SET_TEXT_DRAW_BEFORE_FADE:
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0;
- return 0;
- case COMMAND_GET_COLLECTABLE1S_COLLECTED:
- ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages;
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_REGISTER_EL_BURRO_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterElBurroTime(ScriptParams[0]);
- return 0;
- case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0;
- return 0;
- case COMMAND_SET_TEXT_RIGHT_JUSTIFY:
- CollectParameters(&m_nIp, 1);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bRightJustify = ScriptParams[0] != 0;
- return 0;
- case COMMAND_PRINT_HELP:
- {
- if (CCamera::m_bUseMouse3rdPerson && (
- strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 ||
- strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 ||
- strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_3A", 7) == 0 ||
- strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_4A", 7) == 0)) {
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- return 0;
- }
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CHud::SetHelpMessage(text, false);
- return 0;
- }
- case COMMAND_CLEAR_HELP:
- CHud::SetHelpMessage(nil, false);
- return 0;
- case COMMAND_FLASH_HUD_OBJECT:
- CollectParameters(&m_nIp, 1);
- CHud::m_ItemToFlash = ScriptParams[0];
- return 0;
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands1000To1099(int32 command)
-{
-#ifdef GTA_PS2
- char tmp[48];
-#endif
- switch (command) {
- //case COMMAND_FLASH_RADAR_BLIP:
- case COMMAND_IS_CHAR_IN_CONTROL:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(pPed->IsPedInControl());
- return 0;
- }
- case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA:
- CollectParameters(&m_nIp, 1);
- CCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0);
- return 0;
- case COMMAND_CLEAR_SMALL_PRINTS:
- CMessages::ClearSmallMessagesOnly();
- return 0;
- case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS:
- UpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane());
- return 0;
- case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- CAutomobile* pCar = (CAutomobile*)pVehicle;
- pCar->bNotDamagedUpsideDown = (ScriptParams[1] != 0);
- return 0;
- }
- case COMMAND_CAN_PLAYER_START_MISSION:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPlayerPed);
- UpdateCompareFlag(pPlayerPed->IsPedInControl() || pPlayerPed->m_nPedState == PED_DRIVING);
- return 0;
- }
- case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE:
- {
- CollectParameters(&m_nIp, 1);
-#ifdef MISSION_REPLAY
- AllowMissionReplay = 0;
- SaveGameForPause(3);
-#endif
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- CPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE);
- pPlayerInfo->MakePlayerSafe(true);
- CCutsceneMgr::StartCutsceneProcessing();
- return 0;
- }
- case COMMAND_USE_TEXT_COMMANDS:
- CollectParameters(&m_nIp, 1);
- CTheScripts::UseTextCommands = (ScriptParams[0] != 0) ? 2 : 1;
- return 0;
- case COMMAND_SET_THREAT_FOR_PED_TYPE:
- CollectParameters(&m_nIp, 2);
- CPedType::AddThreat(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_CLEAR_THREAT_FOR_PED_TYPE:
- CollectParameters(&m_nIp, 2);
- CPedType::RemoveThreat(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_GET_CAR_COLOURS:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- ScriptParams[0] = pVehicle->m_currentColour1;
- ScriptParams[1] = pVehicle->m_currentColour2;
- StoreParameters(&m_nIp, 2);
- return 0;
- }
- case COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED:
- CollectParameters(&m_nIp, 1);
- CWorld::SetAllCarsCanBeDamaged(ScriptParams[0] != 0);
- if (!ScriptParams[0])
- CWorld::ExtinguishAllCarFiresInArea(FindPlayerCoors(), 4000.0f);
- return 0;
- case COMMAND_SET_CAR_CAN_BE_DAMAGED:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- pVehicle->bCanBeDamaged = ScriptParams[1] != 0;
- if (!ScriptParams[1])
- pVehicle->ExtinguishCarFire();
- return 0;
- }
- //case COMMAND_MAKE_PLAYER_UNSAFE:
- case COMMAND_LOAD_COLLISION:
- {
- CollectParameters(&m_nIp, 1);
- CTimer::Stop();
- CGame::currLevel = (eLevelName)ScriptParams[0];
- ISLAND_LOADING_IS(LOW)
- {
- CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
- CStreaming::RemoveUnusedBuildings(CGame::currLevel);
- }
- CCollision::SortOutCollisionAfterLoad();
- ISLAND_LOADING_ISNT(HIGH)
- {
- CStreaming::RequestIslands(CGame::currLevel);
- CStreaming::LoadAllRequestedModels(true);
- }
- CTimer::Update();
- return 0;
- }
- case COMMAND_GET_BODY_CAST_HEALTH:
- ScriptParams[0] = CObject::nBodyCastHealth;
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_SET_CHARS_CHATTING:
- {
- CollectParameters(&m_nIp, 3);
- CPed* pPed1 = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- CPed* pPed2 = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pPed1 && pPed2);
- pPed1->SetChat(pPed2, ScriptParams[2]);
- pPed2->SetChat(pPed1, ScriptParams[2]);
- return 0;
- }
- //case COMMAND_MAKE_PLAYER_SAFE:
- case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- if (ScriptParams[1])
- pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
- else
- pVehicle->m_nZoneLevel = LEVEL_GENERIC;
- return 0;
- }
- case COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- if (ScriptParams[1])
- pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
- else
- pPed->m_nZoneLevel = LEVEL_GENERIC;
- return 0;
- }
- case COMMAND_REGISTER_4X4_ONE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4OneTime(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_4X4_TWO_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4TwoTime(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_4X4_THREE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4ThreeTime(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_4X4_MAYHEM_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4MayhemTime(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_LIFE_SAVED:
- CStats::AnotherLifeSavedWithAmbulance();
- return 0;
- case COMMAND_REGISTER_CRIMINAL_CAUGHT:
- CStats::AnotherCriminalCaught();
- return 0;
- case COMMAND_REGISTER_AMBULANCE_LEVEL:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterLevelAmbulanceMission(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_FIRE_EXTINGUISHED:
- CStats::AnotherFireExtinguished();
- return 0;
- case COMMAND_TURN_PHONE_ON:
- CollectParameters(&m_nIp, 1);
- gPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9;
- return 0;
- case COMMAND_REGISTER_LONGEST_DODO_FLIGHT:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterLongestFlightInDodo(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_DEFUSE_BOMB_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]);
- return 0;
- case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:
- CollectParameters(&m_nIp, 1);
- CStats::SetTotalNumberKillFrenzies(ScriptParams[0]);
- return 0;
- case COMMAND_BLOW_UP_RC_BUGGY:
- CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy();
- return 0;
- case COMMAND_REMOVE_CAR_FROM_CHASE:
- CollectParameters(&m_nIp, 1);
- CRecordDataForChase::RemoveCarFromChase(ScriptParams[0]);
- return 0;
- case COMMAND_IS_FRENCH_GAME:
- UpdateCompareFlag(CGame::frenchGame);
- return 0;
- case COMMAND_IS_GERMAN_GAME:
- UpdateCompareFlag(CGame::germanGame);
- return 0;
- case COMMAND_CLEAR_MISSION_AUDIO:
- DMAudio.ClearMissionAudio();
- return 0;
- case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST:
- CollectParameters(&m_nIp, 1);
- CRestart::bFadeInAfterNextArrest = !!ScriptParams[0];
- return 0;
- case COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH:
- CollectParameters(&m_nIp, 1);
- CRestart::bFadeInAfterNextDeath = !!ScriptParams[0];
- return 0;
- case COMMAND_SET_GANG_PED_MODEL_PREFERENCE:
- CollectParameters(&m_nIp, 2);
- CGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_SET_CHAR_USE_PEDNODE_SEEK:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- if (ScriptParams[1])
- pPed->m_pNextPathNode = nil;
- pPed->bUsePedNodeSeek = !!ScriptParams[1];
- return 0;
- }
- case COMMAND_SWITCH_VEHICLE_WEAPONS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->bGunSwitchedOff = !ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_GET_OUT_OF_JAIL_FREE:
- CollectParameters(&m_nIp, 2);
- CWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1];
- return 0;
- case COMMAND_SET_FREE_HEALTH_CARE:
- CollectParameters(&m_nIp, 2);
- CWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1];
- return 0;
- case COMMAND_IS_CAR_DOOR_CLOSED:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- UpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1]));
- return 0;
- }
- case COMMAND_LOAD_AND_LAUNCH_MISSION:
- return 0;
- case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL:
- {
- CollectParameters(&m_nIp, 1);
-#ifdef MISSION_REPLAY
- missionRetryScriptIndex = ScriptParams[0];
- if (missionRetryScriptIndex == 19)
- CStats::LastMissionPassedName[0] = '\0';
-#endif
- CTimer::Suspend();
- int offset = CTheScripts::MultiScriptArray[ScriptParams[0]];
- CFileMgr::ChangeDir("\\");
- int handle = CFileMgr::OpenFile("data\\main.scm", "rb");
- CFileMgr::Seek(handle, offset, 0);
- CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);
- CFileMgr::CloseFile(handle);
- CRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT);
- CTimer::Resume();
- pMissionScript->m_bIsMissionScript = true;
- pMissionScript->m_bMissionFlag = true;
- CTheScripts::bAlreadyRunningAMissionScript = true;
- return 0;
- }
- case COMMAND_SET_OBJECT_DRAW_LAST:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- pObject->bDrawLast = !!ScriptParams[1];
- return 0;
- }
- case COMMAND_GET_AMMO_IN_PLAYER_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]];
- if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1])
- ScriptParams[0] = pWeaponSlot->m_nAmmoTotal;
- else
- ScriptParams[0] = 0;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_AMMO_IN_CHAR_WEAPON:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]];
- if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1])
- ScriptParams[0] = pWeaponSlot->m_nAmmoTotal;
- else
- ScriptParams[0] = 0;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_REGISTER_KILL_FRENZY_PASSED:
- CStats::AnotherKillFrenzyPassed();
- return 0;
- case COMMAND_SET_CHAR_SAY:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- switch (ScriptParams[1]) {
- case SCRIPT_SOUND_CHUNKY_RUN_SHOUT:
- pPed->Say(SOUND_PED_FLEE_RUN);
- break;
- case SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT:
- pPed->Say(SOUND_PED_FLEE_RUN);
- break;
- case SCRIPT_SOUND_SWAT_PED_SHOUT:
- pPed->Say(SOUND_PED_PURSUIT_SWAT);
- break;
- case SCRIPT_SOUND_AMMUNATION_CHAT_1:
- pPed->Say(SOUND_AMMUNATION_WELCOME_1);
- break;
- case SCRIPT_SOUND_AMMUNATION_CHAT_2:
- pPed->Say(SOUND_AMMUNATION_WELCOME_2);
- break;
- case SCRIPT_SOUND_AMMUNATION_CHAT_3:
- pPed->Say(SOUND_AMMUNATION_WELCOME_3);
- break;
- default:
- break;
- }
- return 0;
- }
- case COMMAND_SET_NEAR_CLIP:
- CollectParameters(&m_nIp, 1);
- TheCamera.SetNearClipScript(*(float*)&ScriptParams[0]);
- return 0;
- case COMMAND_SET_RADIO_CHANNEL:
- CollectParameters(&m_nIp, 2);
- DMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_OVERRIDE_HOSPITAL_LEVEL:
- CollectParameters(&m_nIp, 1);
- CRestart::OverrideHospitalLevel = ScriptParams[0];
- return 0;
- case COMMAND_OVERRIDE_POLICE_STATION_LEVEL:
- CollectParameters(&m_nIp, 1);
- CRestart::OverridePoliceStationLevel = ScriptParams[0];
- return 0;
- case COMMAND_FORCE_RAIN:
- CollectParameters(&m_nIp, 1);
- CWeather::bScriptsForceRain = !!ScriptParams[0];
- return 0;
- case COMMAND_DOES_GARAGE_CONTAIN_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- UpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle));
- return 0;
- }
- case COMMAND_SET_CAR_TRACTION:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- float fTraction = *(float*)&ScriptParams[1];
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR || pVehicle->m_vehType == VEHICLE_TYPE_BIKE);
- if (pVehicle->m_vehType == VEHICLE_TYPE_CAR)
- ((CAutomobile*)pVehicle)->m_fTraction = fTraction;
- else
- // this is certainly not a boat, trane, heli or plane field
- //((CBike*)pVehicle)->m_fTraction = fTraction;
- *(float*)(((char*)pVehicle) + 1088) = fTraction;
- return 0;
- }
- case COMMAND_ARE_MEASUREMENTS_IN_METRES:
-#ifdef USE_MEASUREMENTS_IN_METERS
- UpdateCompareFlag(true);
-#else
- UpdateCompareFlag(false)
-#endif
- return 0;
- case COMMAND_CONVERT_METRES_TO_FEET:
- {
- CollectParameters(&m_nIp, 1);
- float fMeterValue = *(float*)&ScriptParams[0];
- float fFeetValue = fMeterValue / METERS_IN_FOOT;
- *(float*)&ScriptParams[0] = fFeetValue;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_MARK_ROADS_BETWEEN_LEVELS:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- ThePaths.MarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);
- return 0;
- }
- case COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- ThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);
- return 0;
- }
- case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pPed);
- // not implemented
- return 0;
- }
- case COMMAND_IS_THREAT_FOR_PED_TYPE:
- CollectParameters(&m_nIp, 2);
- UpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1]));
- return 0;
- case COMMAND_CLEAR_AREA_OF_CHARS:
- {
- CollectParameters(&m_nIp, 6);
- 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];
- }
- CWorld::ClearPedsFromArea(infX, infY, infZ, supX, supY, supZ);
- return 0;
- }
- case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS:
- CollectParameters(&m_nIp, 1);
- CStats::SetTotalNumberMissions(ScriptParams[0]);
- return 0;
- case COMMAND_CONVERT_METRES_TO_FEET_INT:
- CollectParameters(&m_nIp, 1);
- ScriptParams[0] *= FEET_IN_METER;
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_REGISTER_FASTEST_TIME:
- CollectParameters(&m_nIp, 2);
- CStats::RegisterFastestTime(ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_REGISTER_HIGHEST_SCORE:
- CollectParameters(&m_nIp, 2);
- CStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]);
- return 0;
- //case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER:
- //case COMMAND_IS_CAR_PASSENGER_SEAT_FREE:
- case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(ScriptParams[1] >= 0 && ScriptParams[1] < ARRAY_SIZE(pVehicle->pPassengers));
- CPed* pPassenger = pVehicle->pPassengers[ScriptParams[1]];
- ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPassenger);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bChrisCriminal = !!ScriptParams[1];
- return 0;
- }
- case COMMAND_START_CREDITS:
- CCredits::Start();
- return 0;
- case COMMAND_STOP_CREDITS:
- CCredits::Stop();
- return 0;
- case COMMAND_ARE_CREDITS_FINISHED:
- UpdateCompareFlag(CCredits::AreCreditsDone());
- return 0;
- case COMMAND_CREATE_SINGLE_PARTICLE:
- CollectParameters(&m_nIp, 8);
- CParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1],
- *(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0);
- return 0;
- case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- if (ScriptParams[1])
- pPed->m_nZoneLevel = LEVEL_IGNORE;
- else
- pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
- return 0;
- }
- case COMMAND_GET_CHASE_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CRecordDataForChase::TurnChaseCarIntoScriptCar(ScriptParams[0]);
- ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
- StoreParameters(&m_nIp, 1);
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CAR);
- return 0;
- }
- case COMMAND_START_BOAT_FOAM_ANIMATION:
- CSpecialParticleStuff::StartBoatFoamAnimation();
- return 0;
- case COMMAND_UPDATE_BOAT_FOAM_ANIMATION:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix());
- return 0;
- }
- case COMMAND_SET_MUSIC_DOES_FADE:
- CollectParameters(&m_nIp, 1);
- TheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0);
- return 0;
- case COMMAND_SET_INTRO_IS_PLAYING:
- CollectParameters(&m_nIp, 1);
- if (ScriptParams[0]) {
- CGame::playingIntro = true;
- CStreaming::RemoveCurrentZonesModels();
- } else {
- CGame::playingIntro = false;
- DMAudio.ChangeMusicMode(MUSICMODE_GAME);
- int mi;
- CModelInfo::GetModelInfo("bridgefukb", &mi);
- CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
- CStreaming::LoadAllRequestedModels(false);
- }
- return 0;
- case COMMAND_SET_PLAYER_HOOKER:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- if (ScriptParams[1] < 0) {
- pPlayerInfo->m_pHooker = nil;
- pPlayerInfo->m_nNextSexFrequencyUpdateTime = 0;
- pPlayerInfo->m_nNextSexMoneyUpdateTime = 0;
- } else {
- CPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pHooker);
- pPlayerInfo->m_pHooker = (CCivilianPed*)pHooker;
- pPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
- pPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
- }
- return 0;
- }
- case COMMAND_PLAY_END_OF_GAME_TUNE:
- DMAudio.PlayPreloadedCutSceneMusic();
- return 0;
- case COMMAND_STOP_END_OF_GAME_TUNE:
- DMAudio.StopCutSceneMusic();
- DMAudio.ChangeMusicMode(MUSICMODE_GAME);
- return 0;
- case COMMAND_GET_CAR_MODEL:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- ScriptParams[0] = pVehicle->GetModelIndex();
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_IS_PLAYER_SITTING_IN_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle);
- return 0;
- }
- case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING);
- return 0;
- }
- case COMMAND_SET_SCRIPT_FIRE_AUDIO:
- CollectParameters(&m_nIp, 2);
- gFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]);
- return 0;
- case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED:
- UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3);
- return 0;
- case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->bNoCriticalHits = (ScriptParams[0] == 0);
- return 0;
- }
- case COMMAND_IS_PLAYER_LIFTING_A_PHONE:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL);
- return 0;
- }
- case COMMAND_IS_CHAR_SITTING_IN_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle);
- return 0;
- }
- case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING);
- return 0;
- }
- case COMMAND_IS_PLAYER_ON_FOOT:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER &&
- pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
- return 0;
- }
- case COMMAND_IS_CHAR_ON_FOOT:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER &&
- pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
- return 0;
- }
-#ifndef GTA_PS2
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int8 CRunningScript::ProcessCommands1100To1199(int32 command)
-{
- char tmp[48];
- switch (command) {
-#endif
- case COMMAND_LOAD_COLLISION_WITH_SCREEN:
- CollectParameters(&m_nIp, 1);
- CTimer::Stop();
- CGame::currLevel = (eLevelName)ScriptParams[0];
- if (CGame::currLevel != CCollision::ms_collisionInMemory) {
- ISLAND_LOADING_IS(LOW)
- {
- DMAudio.SetEffectsFadeVol(0);
- CPad::StopPadsShaking();
- CCollision::LoadCollisionScreen(CGame::currLevel);
- DMAudio.Service();
- }
- CPopulation::DealWithZoneChange(CCollision::ms_collisionInMemory, CGame::currLevel, false);
-
- ISLAND_LOADING_IS(LOW)
- {
- CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
- CStreaming::RemoveUnusedBuildings(CGame::currLevel);
- }
- CCollision::SortOutCollisionAfterLoad();
-
- ISLAND_LOADING_ISNT(HIGH)
- CStreaming::RequestIslands(CGame::currLevel);
-
- ISLAND_LOADING_IS(LOW)
- CStreaming::RequestBigBuildings(CGame::currLevel);
-
- ISLAND_LOADING_ISNT(HIGH)
- CStreaming::LoadAllRequestedModels(true);
-
- ISLAND_LOADING_IS(LOW)
- DMAudio.SetEffectsFadeVol(127);
- }
- CTimer::Update();
- return 0;
- case COMMAND_LOAD_SPLASH_SCREEN:
- CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- tmp[i] = tolower(tmp[i]);
- m_nIp += 8;
- LoadSplash(tmp);
- return 0;
- case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- if (ScriptParams[1])
- pVehicle->m_nZoneLevel = LEVEL_IGNORE;
- else
- pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
- return 0;
- }
- case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- CAutomobile* pCar = (CAutomobile*)pVehicle;
- pCar->bMoreResistantToDamage = ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), false);
- return 0;
- }
- case COMMAND_LOAD_END_OF_GAME_TUNE:
- DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
- printf("Start preload end of game audio\n");
- DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED);
- printf("End preload end of game audio\n");
- return 0;
- case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA);
- 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);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CWorld::Remove(pObject);
- pObject->SetOrientation(
- DEGTORAD(*(float*)&ScriptParams[1]),
- DEGTORAD(*(float*)&ScriptParams[2]),
- DEGTORAD(*(float*)&ScriptParams[3]));
- pObject->GetMatrix().UpdateRW();
- pObject->UpdateRwFrame();
- CWorld::Add(pObject);
- return 0;
- }
- case COMMAND_GET_DEBUG_CAMERA_COORDINATES:
- *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source;
- StoreParameters(&m_nIp, 3);
- return 0;
- case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR:
- *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front;
- StoreParameters(&m_nIp, 3);
- return 0;
- case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR:
- {
- CollectParameters(&m_nIp, 1);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CEntity* pTarget = pPed->m_pPointGunAt;
- UpdateCompareFlag(pTarget && pTarget->IsPed());
- return 0;
- }
- case COMMAND_IS_PLAYER_TARGETTING_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pTestedPed);
- CEntity* pTarget = pPed->m_pPointGunAt;
- UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed);
- return 0;
- }
- case COMMAND_IS_PLAYER_TARGETTING_OBJECT:
- {
- CollectParameters(&m_nIp, 2);
- CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- CObject* pTestedObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- script_assert(pTestedObject);
- CEntity* pTarget = pPed->m_pPointGunAt;
- UpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject);
- return 0;
- }
- case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME:
- {
- CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
- for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
- tmp[i] = tolower(tmp[i]);
- m_nIp += 8;
- CRunningScript* pScript = CTheScripts::pActiveScripts;
- while (pScript) {
- CRunningScript* pNext = pScript->next;
- if (strcmp(pScript->m_abScriptName, tmp) == 0) {
- pScript->RemoveScriptFromList(&CTheScripts::pActiveScripts);
- pScript->AddScriptToList(&CTheScripts::pIdleScripts);
- }
- pScript = pNext;
- }
- return 0;
- }
- case COMMAND_DISPLAY_TEXT_WITH_NUMBER:
- {
- CollectParameters(&m_nIp, 2);
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
- CollectParameters(&m_nIp, 1);
- CMessages::InsertNumberInString(text, ScriptParams[0], -1, -1, -1, -1, -1,
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text);
- return 0;
- }
- case COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS:
- {
- CollectParameters(&m_nIp, 2);
- wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
- CollectParameters(&m_nIp, 2);
- CMessages::InsertNumberInString(text, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1,
- CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text);
- return 0;
- }
- case COMMAND_FAIL_CURRENT_MISSION:
- CTheScripts::FailCurrentMission = 2;
- return 0;
- case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float range = *(float*)&ScriptParams[3];
- int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];
- int16 total;
- CEntity* apEntities[16];
- CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true);
- CEntity* pClosestEntity = nil;
- float min_dist = 2.0f * range;
- for (int i = 0; i < total; i++) {
- float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
- if (dist < min_dist) {
- min_dist = dist;
- pClosestEntity = apEntities[i];
- }
- }
- if (pClosestEntity && pClosestEntity->IsDummy()) {
- CPopulation::ConvertToRealObject((CDummyObject*)pClosestEntity);
- CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true);
- pClosestEntity = nil;
- float min_dist = 2.0f * range;
- for (int i = 0; i < total; i++) {
- float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
- if (dist < min_dist) {
- min_dist = dist;
- pClosestEntity = apEntities[i];
- }
- }
- if (pClosestEntity->IsDummy())
- pClosestEntity = nil;
- }
- if (pClosestEntity) {
- script_assert(pClosestEntity->IsObject());
- CObject* pObject = (CObject*)pClosestEntity;
- pObject->ObjectCreatedBy = MISSION_OBJECT;
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObject);
- } else {
- ScriptParams[0] = -1;
- }
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT:
- {
- CollectParameters(&m_nIp, 5);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CVector offset = *(CVector*)&ScriptParams[2];
- CPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset);
- return 0;
- }
- case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- if (pVehicle->pDriver) {
- pVehicle->pDriver->bScriptObjectiveCompleted = false;
- pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, 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_CAR, pVehicle);
- }
- }
- return 0;
- }
- case COMMAND_SET_INTERPOLATION_PARAMETERS:
- CollectParameters(&m_nIp, 2);
- TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]);
- return 0;
- case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float destX = *(float*)&ScriptParams[3];
- float destY = *(float*)&ScriptParams[4];
- int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
- CPathNode* pNode = &ThePaths.m_pathNodes[nid];
- *(CVector*)&ScriptParams[0] = pNode->GetPosition();
- *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true);
- StoreParameters(&m_nIp, 4);
- return 0;
- }
- case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT:
- {
- CollectParameters(&m_nIp, 5);
- CVector pos = *(CVector*)&ScriptParams[0];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- float destX = *(float*)&ScriptParams[3];
- float destY = *(float*)&ScriptParams[4];
- int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
- CPathNode* pNode = &ThePaths.m_pathNodes[nid];
- *(CVector*)&ScriptParams[0] = pNode->GetPosition();
- *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false);
- StoreParameters(&m_nIp, 4);
- return 0;
- }
- case COMMAND_GET_DEBUG_CAMERA_POINT_AT:
- *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front;
- StoreParameters(&m_nIp, 3);
- return 0;
- case COMMAND_ATTACH_CHAR_TO_CAR:
- // empty implementation
- return 0;
- case COMMAND_DETACH_CHAR_FROM_CAR:
- // empty implementation
- return 0;
- case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->AutoPilot.m_bStayInFastLane = !ScriptParams[1];
- return 0;
- }
- case COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->m_lastWepDam = -1;
- return 0;
- }
- case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- pVehicle->m_nLastWeaponDamage = -1;
- return 0;
- }
- case COMMAND_GET_RANDOM_COP_IN_AREA:
- {
- CollectParameters(&m_nIp, 4);
- int ped_handle = -1;
- CVector pos = FindPlayerCoors();
- float x1 = *(float*)&ScriptParams[0];
- float y1 = *(float*)&ScriptParams[1];
- float x2 = *(float*)&ScriptParams[2];
- float y2 = *(float*)&ScriptParams[3];
- int i = CPools::GetPedPool()->GetSize();
- while (--i && ped_handle == -1) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
- continue;
- if (pPed->m_nPedType != PEDTYPE_COP)
- continue;
- if (pPed->CharCreatedBy != RANDOM_CHAR)
- continue;
- if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)
- continue;
- if (pPed->bRemoveFromWorld)
- continue;
- if (pPed->bFadeOut)
- continue;
- if (pPed->bIsLeader || pPed->m_leader)
- continue;
- if (!pPed->IsWithinArea(x1, y1, x2, y2))
- continue;
- if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
- continue;
- if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
- continue;
- ped_handle = CPools::GetPedPool()->GetIndex(pPed);
- CTheScripts::LastRandomPedId = ped_handle;
- pPed->CharCreatedBy = MISSION_CHAR;
- pPed->bRespondsToThreats = false;
- ++CPopulation::ms_nTotalMissionPeds;
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
- }
- ScriptParams[0] = ped_handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_RANDOM_COP_IN_ZONE:
- {
- char zone[KEY_LENGTH_IN_SCRIPT];
- strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
- if (nZone != -1)
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
- int ped_handle = -1;
- CVector pos = FindPlayerCoors();
- int i = CPools::GetPedPool()->GetSize();
- while (--i && ped_handle == -1) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
- continue;
- if (pPed->m_nPedType != PEDTYPE_COP)
- continue;
- if (pPed->CharCreatedBy != RANDOM_CHAR)
- continue;
- if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)
- continue;
- if (pPed->bRemoveFromWorld)
- continue;
- if (pPed->bFadeOut)
- continue;
- if (pPed->bIsLeader || pPed->m_leader)
- continue;
- if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))
- continue;
- if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
- continue;
- if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
- continue;
- ped_handle = CPools::GetPedPool()->GetIndex(pPed);
- CTheScripts::LastRandomPedId = ped_handle;
- pPed->CharCreatedBy = MISSION_CHAR;
- pPed->bRespondsToThreats = false;
- ++CPopulation::ms_nTotalMissionPeds;
- if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
- }
- ScriptParams[0] = ped_handle;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CHAR_OBJ_FLEE_CAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- pPed->bScriptObjectiveCompleted = false;
- pPed->SetObjective(OBJECTIVE_FLEE_CAR, pVehicle);
- return 0;
- }
- case COMMAND_GET_DRIVER_OF_CAR:
- {
- CollectParameters(&m_nIp, 1);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CPed* pDriver = pVehicle->pDriver;
- if (pDriver)
- ScriptParams[0] = CPools::GetPedPool()->GetIndex(pDriver);
- else
- ScriptParams[0] = -1;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_NUMBER_OF_FOLLOWERS:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pLeader);
- int total = 0;
- int i = CPools::GetPedPool()->GetSize();
- while (--i) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- if (pPed->m_leader == pLeader)
- total++;
- }
- ScriptParams[0] = total;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER:
- {
- CollectParameters(&m_nIp, 6);
- CVector pos = *(CVector*)&ScriptParams[1];
- if (pos.z <= MAP_Z_LOW_LIMIT)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), ScriptParams[5]);
- return 0;
- }
- case COMMAND_GET_CURRENT_PLAYER_WEAPON:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_GET_CURRENT_CHAR_WEAPON:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:
- case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:
- case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
- 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
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT;
- pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNRIGHT;
- pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
- return 0;
- }
- case COMMAND_SET_CAR_HANDBRAKE_STOP:
- {
- CollectParameters(&m_nIp, 2);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
- pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
- return 0;
- }
- case COMMAND_IS_CHAR_ON_ANY_BIKE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
- return 0;
- }
- case COMMAND_LOCATE_SNIPER_BULLET_2D:
- case COMMAND_LOCATE_SNIPER_BULLET_3D:
- LocateSniperBulletCommand(command, &m_nIp);
- return 0;
- case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL:
- CollectParameters(&m_nIp, 1);
- ScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1;
- StoreParameters(&m_nIp, 1);
- return 0;
- case COMMAND_IS_PLAYER_ON_ANY_BIKE:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- script_assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
- return 0;
- }
- case COMMAND_IS_CHAR_LYING_DOWN:
- {
- CollectParameters(&m_nIp, 1);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- UpdateCompareFlag(pPed->bFallenDown);
- return 0;
- }
- case COMMAND_CAN_CHAR_SEE_DEAD_CHAR:
- {
- CollectParameters(&m_nIp, 2);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- int pedtype = ScriptParams[1];
- bool can = false;
- for (int i = 0; i < pPed->m_numNearPeds; i++) {
- CPed* pTestPed = pPed->m_nearPeds[i];
- if (pTestPed->m_fHealth <= 0.0f && pTestPed->m_nPedType == pedtype && pPed->OurPedCanSeeThisOne(pTestPed))
- can = true;
- }
- UpdateCompareFlag(can);
- return 0;
- }
- 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
- default:
- script_assert(0);
- }
- return -1;
-}
-
-int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index)
-{
- if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1)
- ScriptSphereArray[index].m_Index = 1;
- else
- ScriptSphereArray[index].m_Index++;
- return (uint16)index | ScriptSphereArray[index].m_Index << 16;
-}
-
-int32 CTheScripts::GetActualScriptSphereIndex(int32 index)
-{
- if (index == -1)
- return -1;
- uint16 check = (uint32)index >> 16;
- uint16 array_idx = index & (0xFFFF);
- script_assert(array_idx < ARRAY_SIZE(ScriptSphereArray));
- if (check != ScriptSphereArray[array_idx].m_Index)
- return -1;
- return array_idx;
-}
-
-void CTheScripts::DrawScriptSpheres()
-{
- for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) {
- if (ScriptSphereArray[i].m_bInUse)
- C3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius,
- SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0);
- }
-}
-
-int32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius)
-{
- int16 i = 0;
- for (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) {
- if (!ScriptSphereArray[i].m_bInUse)
- break;
- }
-#ifdef FIX_BUGS
- if (i == MAX_NUM_SCRIPT_SPHERES)
- return -1;
-#endif
- ScriptSphereArray[i].m_bInUse = true;
- ScriptSphereArray[i].m_Id = id;
- ScriptSphereArray[i].m_vecCenter = pos;
- ScriptSphereArray[i].m_fRadius = radius;
- return GetNewUniqueScriptSphereIndex(i);
-}
-
-void CTheScripts::RemoveScriptSphere(int32 index)
-{
- index = GetActualScriptSphereIndex(index);
- if (index == -1)
- return;
- ScriptSphereArray[index].m_bInUse = false;
- ScriptSphereArray[index].m_Id = 0;
-}
-
-void CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model)
-{
- int i = 0;
- bool found = false;
- while (i < MAX_NUM_BUILDING_SWAPS && !found) {
- if (BuildingSwapArray[i].m_pBuilding == pBuilding)
- found = true;
- else
- i++;
- }
- if (found) {
- if (BuildingSwapArray[i].m_nOldModel == new_model) {
- BuildingSwapArray[i].m_pBuilding = nil;
- BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1;
- }
- else {
- BuildingSwapArray[i].m_nNewModel = new_model;
- }
- }
- else {
- i = 0;
- while (i < MAX_NUM_BUILDING_SWAPS && !found) {
- if (BuildingSwapArray[i].m_pBuilding == nil)
- found = true;
- else
- i++;
- }
- if (found) {
- BuildingSwapArray[i].m_pBuilding = pBuilding;
- BuildingSwapArray[i].m_nNewModel = new_model;
- BuildingSwapArray[i].m_nOldModel = old_model;
- }
- }
-}
-
-void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove)
-{
- int i = 0;
- bool found = false;
- while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {
- if (InvisibilitySettingArray[i] == pEntity)
- found = true;
- else
- i++;
- }
- if (found) {
- if (remove)
- InvisibilitySettingArray[i] = nil;
- }
- else if (!remove) {
- i = 0;
- while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {
- if (InvisibilitySettingArray[i] == nil)
- found = true;
- else
- i++;
- }
- if (found)
- InvisibilitySettingArray[i] = pEntity;
- }
-}
-
-void CTheScripts::UndoBuildingSwaps()
-{
- for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
- if (BuildingSwapArray[i].m_pBuilding) {
- BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel);
- BuildingSwapArray[i].m_pBuilding = nil;
- BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1;
- }
- }
-}
-
-void CTheScripts::UndoEntityInvisibilitySettings()
-{
- for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {
- if (InvisibilitySettingArray[i]) {
- InvisibilitySettingArray[i]->bIsVisible = true;
- InvisibilitySettingArray[i] = nil;
- }
- }
-}
-
-void CRunningScript::UpdateCompareFlag(bool flag)
-{
- if (m_bNotFlag)
- flag = !flag;
- if (m_nAndOrState == ANDOR_NONE) {
- m_bCondResult = flag;
- return;
- }
- if (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8) {
- m_bCondResult &= flag;
- if (m_nAndOrState == ANDS_1) {
- m_nAndOrState = ANDOR_NONE;
- return;
- }
- }
- else if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8) {
- m_bCondResult |= flag;
- if (m_nAndOrState == ORS_1) {
- m_nAndOrState = ANDOR_NONE;
- return;
- }
- }
- else {
- return;
- }
- m_nAndOrState--;
-}
-
-void CRunningScript::LocatePlayerCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_3D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 8 : 6);
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- switch (command) {
- case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:
- case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:
- if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- X = *(float*)&ScriptParams[1];
- Y = *(float*)&ScriptParams[2];
- if (b3D) {
- Z = *(float*)&ScriptParams[3];
- dX = *(float*)&ScriptParams[4];
- dY = *(float*)&ScriptParams[5];
- dZ = *(float*)&ScriptParams[6];
- debug = ScriptParams[7];
- } else {
- dX = *(float*)&ScriptParams[3];
- dY = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- if (!decided) {
- CVector pos = pPlayerInfo->GetPos();
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- } else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D:
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:
- result = true;
- break;
- case COMMAND_LOCATE_PLAYER_ON_FOOT_2D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:
- case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:
- result = !pPlayerInfo->m_pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_PLAYER_IN_CAR_2D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_3D:
- case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:
- case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:
- result = pPlayerInfo->m_pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocatePlayerCharCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 6 : 5);
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CVector pos = pPlayerInfo->GetPos();
- if (pTarget->bInVehicle) {
- X = pTarget->m_pMyVehicle->GetPosition().x;
- Y = pTarget->m_pMyVehicle->GetPosition().y;
- Z = pTarget->m_pMyVehicle->GetPosition().z;
- } else {
- X = pTarget->GetPosition().x;
- Y = pTarget->GetPosition().y;
- Z = pTarget->GetPosition().z;
- }
- dX = *(float*)&ScriptParams[2];
- dY = *(float*)&ScriptParams[3];
- if (b3D) {
- dZ = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- else {
- debug = ScriptParams[4];
- }
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D:
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:
- result = true;
- break;
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:
- result = !pPlayerInfo->m_pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:
- result = pPlayerInfo->m_pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- UpdateCompareFlag(result);
- if (debug)
-#ifdef FIX_BUGS
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
-#else
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT);
-#endif
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocatePlayerCarCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 6 : 5);
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CVector pos = pPlayerInfo->GetPos();
- X = pTarget->GetPosition().x;
- Y = pTarget->GetPosition().y;
- Z = pTarget->GetPosition().z;
- dX = *(float*)&ScriptParams[2];
- dY = *(float*)&ScriptParams[3];
- if (b3D) {
- dZ = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- else {
- debug = ScriptParams[4];
- }
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D:
- case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:
- result = true;
- break;
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D:
- case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:
- result = !pPlayerInfo->m_pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D:
- case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:
- result = pPlayerInfo->m_pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocateCharCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_3D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_3D:
- case COMMAND_LOCATE_CHAR_IN_CAR_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 8 : 6);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- switch (command) {
- case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:
- case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:
- case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:
- case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:
- if (!CTheScripts::IsPedStopped(pPed)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- X = *(float*)&ScriptParams[1];
- Y = *(float*)&ScriptParams[2];
- if (b3D) {
- Z = *(float*)&ScriptParams[3];
- dX = *(float*)&ScriptParams[4];
- dY = *(float*)&ScriptParams[5];
- dZ = *(float*)&ScriptParams[6];
- debug = ScriptParams[7];
- }
- else {
- dX = *(float*)&ScriptParams[3];
- dY = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- if (!decided) {
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_2D:
- case COMMAND_LOCATE_CHAR_ANY_MEANS_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:
- case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
- result = true;
- break;
- case COMMAND_LOCATE_CHAR_ON_FOOT_2D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:
- case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:
- result = !pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_CHAR_IN_CAR_2D:
- case COMMAND_LOCATE_CHAR_IN_CAR_3D:
- case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:
- case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:
- result = pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocateCharCharCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:
- case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 6 : 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- if (pTarget->bInVehicle) {
- X = pTarget->m_pMyVehicle->GetPosition().x;
- Y = pTarget->m_pMyVehicle->GetPosition().y;
- Z = pTarget->m_pMyVehicle->GetPosition().z;
- }
- else {
- X = pTarget->GetPosition().x;
- Y = pTarget->GetPosition().y;
- Z = pTarget->GetPosition().z;
- }
- dX = *(float*)&ScriptParams[2];
- dY = *(float*)&ScriptParams[3];
- if (b3D) {
- dZ = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- else {
- debug = ScriptParams[4];
- }
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D:
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:
- result = true;
- break;
- case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:
- result = !pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D:
- case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:
- result = pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- UpdateCompareFlag(result);
- if (debug)
-#ifdef FIX_BUGS
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
-#else
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT);
-#endif
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocateCharCarCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:
- case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 6 : 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- X = pTarget->GetPosition().x;
- Y = pTarget->GetPosition().y;
- Z = pTarget->GetPosition().z;
- dX = *(float*)&ScriptParams[2];
- dY = *(float*)&ScriptParams[3];
- if (b3D) {
- dZ = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- else {
- debug = ScriptParams[4];
- }
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D:
- case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:
- result = true;
- break;
- case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:
- result = !pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D:
- case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:
- result = pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocateCharObjectCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
- case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 6 : 5);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
- script_assert(pTarget);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- X = pTarget->GetPosition().x;
- Y = pTarget->GetPosition().y;
- Z = pTarget->GetPosition().z;
- dX = *(float*)&ScriptParams[2];
- dY = *(float*)&ScriptParams[3];
- if (b3D) {
- dZ = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- else {
- debug = ScriptParams[4];
- }
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:
- case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
- result = true;
- break;
- case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:
- case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
- result = !pPed->bInVehicle;
- break;
- case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:
- case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
- result = pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocateCarCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_CAR_3D:
- case COMMAND_LOCATE_STOPPED_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 8 : 6);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CVector pos = pVehicle->GetPosition();
- switch (command) {
- case COMMAND_LOCATE_STOPPED_CAR_2D:
- case COMMAND_LOCATE_STOPPED_CAR_3D:
- if (!CTheScripts::IsVehicleStopped(pVehicle)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- X = *(float*)&ScriptParams[1];
- Y = *(float*)&ScriptParams[2];
- if (b3D) {
- Z = *(float*)&ScriptParams[3];
- dX = *(float*)&ScriptParams[4];
- dY = *(float*)&ScriptParams[5];
- dZ = *(float*)&ScriptParams[6];
- debug = ScriptParams[7];
- }
- else {
- dX = *(float*)&ScriptParams[3];
- dY = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- if (!decided) {
- result = false;
- bool in_area;
- if (b3D) {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y &&
- Z - dZ <= pos.z &&
- Z + dZ >= pos.z;
- }
- else {
- in_area = X - dX <= pos.x &&
- X + dX >= pos.x &&
- Y - dY <= pos.y &&
- Y + dY >= pos.y;
- }
- result = in_area;
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug;
- float X, Y, Z, dX, dY, dZ;
- switch (command) {
- case COMMAND_LOCATE_SNIPER_BULLET_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 7 : 5);
- X = *(float*)&ScriptParams[0];
- Y = *(float*)&ScriptParams[1];
- if (b3D) {
- Z = *(float*)&ScriptParams[2];
- dX = *(float*)&ScriptParams[3];
- dY = *(float*)&ScriptParams[4];
- dZ = *(float*)&ScriptParams[5];
- debug = ScriptParams[6];
- }
- else {
- dX = *(float*)&ScriptParams[2];
- dY = *(float*)&ScriptParams[3];
- debug = ScriptParams[4];
- }
- result = CBulletInfo::TestForSniperBullet(X - dX, X + dX, Y - dY, Y + dY, b3D ? Z - dZ : -1000.0f, b3D ? Z + dZ : 1000.0f);
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
- else
- CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
- }
-}
-
-void CRunningScript::PlayerInAreaCheckCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float infX, infY, infZ, supX, supY, supZ;
- switch (command) {
- case COMMAND_IS_PLAYER_IN_AREA_3D:
- case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 8 : 6);
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- switch (command) {
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:
- if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- infX = *(float*)&ScriptParams[1];
- infY = *(float*)&ScriptParams[2];
- if (b3D) {
- infZ = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[6];
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[6];
- supZ = *(float*)&ScriptParams[3];
- }
- debug = ScriptParams[7];
- }
- else {
- supX = *(float*)&ScriptParams[3];
- supY = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- if (infX > supX) {
- float tmp = infX;
- infX = supX;
- supX = tmp;
- }
- if (infY > supY) {
- float tmp = infY;
- infY = supY;
- supY = tmp;
- }
- if (!decided) {
- CVector pos = pPlayerInfo->GetPos();
- result = false;
- bool in_area;
- if (b3D) {
- in_area = infX <= pos.x &&
- supX >= pos.x &&
- infY <= pos.y &&
- supY >= pos.y &&
- infZ <= pos.z &&
- supZ >= pos.z;
- }
- else {
- in_area = infX <= pos.x &&
- supX >= pos.x &&
- infY <= pos.y &&
- supY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_IS_PLAYER_IN_AREA_2D:
- case COMMAND_IS_PLAYER_IN_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
- result = true;
- break;
- case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
- result = !pPlayerInfo->m_pPed->bInVehicle;
- break;
- case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
- result = pPlayerInfo->m_pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
- else
- CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
- }
-}
-
-void CRunningScript::PlayerInAngledAreaCheckCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float infX, infY, infZ, supX, supY, supZ, side2length;
- switch (command) {
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 9 : 7);
- CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
- switch (command) {
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
- if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- infX = *(float*)&ScriptParams[1];
- infY = *(float*)&ScriptParams[2];
- if (b3D) {
- infZ = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[6];
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[6];
- supZ = *(float*)&ScriptParams[3];
- }
- side2length = *(float*)&ScriptParams[7];
- debug = ScriptParams[8];
- }
- else {
- supX = *(float*)&ScriptParams[3];
- supY = *(float*)&ScriptParams[4];
- side2length = *(float*)&ScriptParams[5];
- debug = ScriptParams[6];
- }
- float initAngle = CGeneral::GetRadianAngleBetweenPoints(infX, infY, supX, supY) + HALFPI;
- while (initAngle < 0.0f)
- initAngle += TWOPI;
- while (initAngle > TWOPI)
- initAngle -= TWOPI;
- // it looks like the idea is to use a rectangle using the diagonal of the rectangle as
- // the side of new rectangle, with "length" being the length of second side
- float rotatedSupX = supX + side2length * sin(initAngle);
- float rotatedSupY = supY - side2length * cos(initAngle);
- float rotatedInfX = infX + side2length * sin(initAngle);
- float rotatedInfY = infY - side2length * cos(initAngle);
- float side1X = supX - infX;
- float side1Y = supY - infY;
- float side1Length = CVector2D(side1X, side1Y).Magnitude();
- float side2X = rotatedInfX - infX;
- float side2Y = rotatedInfY - infY;
- float side2Length = CVector2D(side2X, side2Y).Magnitude(); // == side2length?
- if (!decided) {
- CVector pos = pPlayerInfo->GetPos();
- result = false;
- float X = pos.x - infX;
- float Y = pos.y - infY;
- float positionAlongSide1 = X * side1X / side1Length + Y * side1Y / side1Length;
- bool in_area = false;
- if (positionAlongSide1 >= 0.0f && positionAlongSide1 <= side1Length) {
- float positionAlongSide2 = X * side2X / side2Length + Y * side2Y / side2Length;
- if (positionAlongSide2 >= 0.0f && positionAlongSide2 <= side2Length) {
- in_area = !b3D || pos.z >= infZ && pos.z <= supZ;
- }
- }
-
- if (in_area) {
- switch (command) {
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
- result = true;
- break;
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
- result = !pPlayerInfo->m_pPed->bInVehicle;
- break;
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
- case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
- result = pPlayerInfo->m_pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantAngledArea((uintptr)this + m_nIp, infX, infY, supX, supY,
- rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugAngledCube(infX, infY, infZ, supX, supY, supZ,
- rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY);
- else
- CTheScripts::DrawDebugAngledSquare(infX, infY, supX, supY,
- rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY);
- }
-}
-
-void CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float infX, infY, infZ, supX, supY, supZ;
- switch (command) {
- case COMMAND_IS_CHAR_IN_AREA_3D:
- case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 8 : 6);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- switch (command) {
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:
- if (!CTheScripts::IsPedStopped(pPed)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- infX = *(float*)&ScriptParams[1];
- infY = *(float*)&ScriptParams[2];
- if (b3D) {
- infZ = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[6];
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[6];
- supZ = *(float*)&ScriptParams[3];
- }
- debug = ScriptParams[7];
- }
- else {
- supX = *(float*)&ScriptParams[3];
- supY = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- if (infX > supX) {
- float tmp = infX;
- infX = supX;
- supX = tmp;
- }
- if (infY > supY) {
- float tmp = infY;
- infY = supY;
- supY = tmp;
- }
- if (!decided) {
- result = false;
- bool in_area;
- if (b3D) {
- in_area = infX <= pos.x &&
- supX >= pos.x &&
- infY <= pos.y &&
- supY >= pos.y &&
- infZ <= pos.z &&
- supZ >= pos.z;
- }
- else {
- in_area = infX <= pos.x &&
- supX >= pos.x &&
- infY <= pos.y &&
- supY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_IS_CHAR_IN_AREA_2D:
- case COMMAND_IS_CHAR_IN_AREA_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
- result = true;
- break;
- case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
- result = !pPed->bInVehicle;
- break;
- case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:
- case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
- result = pPed->bInVehicle;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
- else
- CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
- }
-}
-
-void CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp)
-{
- bool b3D, result, debug, decided = false;
- float infX, infY, infZ, supX, supY, supZ;
- switch (command) {
- case COMMAND_IS_CAR_IN_AREA_3D:
- case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
- b3D = true;
- break;
- default:
- b3D = false;
- break;
- }
- CollectParameters(pIp, b3D ? 8 : 6);
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- CVector pos = pVehicle->GetPosition();
- switch (command) {
- case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
- case COMMAND_IS_CAR_STOPPED_IN_AREA_2D:
- if (!CTheScripts::IsVehicleStopped(pVehicle)) {
- result = false;
- decided = true;
- }
- break;
- default:
- break;
- }
- infX = *(float*)&ScriptParams[1];
- infY = *(float*)&ScriptParams[2];
- if (b3D) {
- infZ = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[6];
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[6];
- supZ = *(float*)&ScriptParams[3];
- }
- debug = ScriptParams[7];
- }
- else {
- supX = *(float*)&ScriptParams[3];
- supY = *(float*)&ScriptParams[4];
- debug = ScriptParams[5];
- }
- if (infX > supX) {
- float tmp = infX;
- infX = supX;
- supX = tmp;
- }
- if (infY > supY) {
- float tmp = infY;
- infY = supY;
- supY = tmp;
- }
- if (!decided) {
- result = false;
- bool in_area;
- if (b3D) {
- in_area = infX <= pos.x &&
- supX >= pos.x &&
- infY <= pos.y &&
- supY >= pos.y &&
- infZ <= pos.z &&
- supZ >= pos.z;
- }
- else {
- in_area = infX <= pos.x &&
- supX >= pos.x &&
- infY <= pos.y &&
- supY >= pos.y;
- }
- if (in_area) {
- switch (command) {
- case COMMAND_IS_CAR_IN_AREA_2D:
- case COMMAND_IS_CAR_IN_AREA_3D:
- case COMMAND_IS_CAR_STOPPED_IN_AREA_2D:
- case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
- result = true;
- break;
- default:
- script_assert(false);
- break;
- }
- }
- }
- UpdateCompareFlag(result);
- if (debug)
- CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
- if (CTheScripts::DbgFlag) {
- if (b3D)
- CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
- else
- CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
- }
-}
-
-void CRunningScript::DoDeatharrestCheck()
-{
- if (!m_bDeatharrestEnabled)
- return;
- if (!CTheScripts::IsPlayerOnAMission())
- return;
- CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
- if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest() && !CTheScripts::UpsideDownCars.AreAnyCarsUpsideDown())
- return;
-#ifdef MISSION_REPLAY
- if (AllowMissionReplay != 0)
- return;
- if (CanAllowMissionReplay())
- AllowMissionReplay = 1;
-#endif
- script_assert(m_nStackPointer > 0);
- 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;
-}
-
-int16 CRunningScript::GetPadState(uint16 pad, uint16 button)
-{
- CPad* pPad = CPad::GetPad(pad);
- switch (button) {
- case 0: return pPad->NewState.LeftStickX;
- case 1: return pPad->NewState.LeftStickY;
- case 2: return pPad->NewState.RightStickX;
- case 3: return pPad->NewState.RightStickY;
- case 4: return pPad->NewState.LeftShoulder1;
- case 5: return pPad->NewState.LeftShoulder2;
- case 6: return pPad->NewState.RightShoulder1;
- case 7: return pPad->NewState.RightShoulder2;
- case 8: return pPad->NewState.DPadUp;
- case 9: return pPad->NewState.DPadDown;
- case 10: return pPad->NewState.DPadLeft;
- case 11: return pPad->NewState.DPadRight;
- case 12: return pPad->NewState.Start;
- case 13: return pPad->NewState.Select;
- case 14: return pPad->NewState.Square;
- case 15: return pPad->NewState.Triangle;
- case 16: return pPad->NewState.Cross;
- case 17: return pPad->NewState.Circle;
- case 18: return pPad->NewState.LeftShock;
- case 19: return pPad->NewState.RightShock;
- default: break;
- }
- return 0;
-}
-
-void CTheScripts::PrintListSizes()
-{
- int active = 0;
- int idle = 0;
-
- for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
- active++;
- for (CRunningScript* pScript = pIdleScripts; pScript; pScript = pScript->GetNext())
- idle++;
-
- debug("active: %d, idle: %d", active, idle);
-}
-
-uint32 DbgLineColour = 0x0000FFFF; // r = 0, g = 0, b = 255, a = 255
-
-void CTheScripts::DrawDebugSquare(float infX, float infY, float supX, float supY)
-{
- CColPoint tmpCP;
- CEntity* tmpEP;
- CVector p1, p2, p3, p4;
- p1 = CVector(infX, infY, -1000.0f);
- CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p1.z = 2.0f + tmpCP.point.z;
- p2 = CVector(supX, supY, -1000.0f);
- CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p2.z = 2.0f + tmpCP.point.z;
- p3 = CVector(infX, supY, -1000.0f);
- CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p3.z = 2.0f + tmpCP.point.z;
- p4 = CVector(supX, infY, -1000.0f);
- CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p4.z = 2.0f + tmpCP.point.z;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour);
-}
-
-void CTheScripts::DrawDebugAngledSquare(float infX, float infY, float supX, float supY, float rotSupX, float rotSupY, float rotInfX, float rotInfY)
-{
- CColPoint tmpCP;
- CEntity* tmpEP;
- CVector p1, p2, p3, p4;
- p1 = CVector(infX, infY, -1000.0f);
- CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p1.z = 2.0f + tmpCP.point.z;
- p2 = CVector(supX, supY, -1000.0f);
- CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p2.z = 2.0f + tmpCP.point.z;
- p3 = CVector(rotSupX, rotSupY, -1000.0f);
- CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p3.z = 2.0f + tmpCP.point.z;
- p4 = CVector(rotInfX, rotInfY, -1000.0f);
- CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
- p4.z = 2.0f + tmpCP.point.z;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour);
-}
-
-void CTheScripts::DrawDebugCube(float infX, float infY, float infZ, float supX, float supY, float supZ)
-{
- CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, infY, infZ, supX, supY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, supY, infZ, infX, supY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, supY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, supY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, supY, supZ, infX, supY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, supY, supZ, supX, supY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, supY, infZ, DbgLineColour, DbgLineColour);
-}
-
-void CTheScripts::DrawDebugAngledCube(float infX, float infY, float infZ, float supX, float supY, float supZ, float rotSupX, float rotSupY, float rotInfX, float rotInfY)
-{
- CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, infY, infZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, infZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, infY, supZ, rotSupX, rotSupY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, rotInfX, rotInfY, supY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, supZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour);
- CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour);
-}
-
-void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2)
-{
- if (NumScriptDebugLines >= MAX_NUM_STORED_LINES)
- return;
- aStoredLines[NumScriptDebugLines].vecInf = CVector(x1, y1, z1);
- aStoredLines[NumScriptDebugLines].vecSup = CVector(x2, y2, z2);
- aStoredLines[NumScriptDebugLines].color1 = col;
- aStoredLines[NumScriptDebugLines++].color2 = col2;
-}
-
-void CTheScripts::RenderTheScriptDebugLines()
-{
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1);
- for (int i = 0; i < NumScriptDebugLines; i++) {
- CLines::RenderLineWithClipping(
- aStoredLines[i].vecInf.x,
- aStoredLines[i].vecInf.y,
- aStoredLines[i].vecInf.z,
- aStoredLines[i].vecSup.x,
- aStoredLines[i].vecSup.y,
- aStoredLines[i].vecSup.z,
- aStoredLines[i].color1,
- aStoredLines[i].color2);
- }
- NumScriptDebugLines = 0;
- 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)
-
-void CTheScripts::SaveAllScripts(uint8* buf, uint32* size)
-{
-INITSAVEBUF
- uint32 varSpace = GetSizeOfVariableSpace();
- uint32 runningScripts = 0;
- for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
- runningScripts++;
- *size = CRunningScript::nSaveStructSize * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32);
- WriteSaveHeader(buf, 'S', 'C', 'R', '\0', *size - SAVE_HEADER_SIZE);
- WriteSaveBuf(buf, varSpace);
- for (uint32 i = 0; i < varSpace; i++)
- WriteSaveBuf(buf, ScriptSpace[i]);
-#ifdef CHECK_STRUCT_SIZES
- static_assert(SCRIPT_DATA_SIZE == 968, "CTheScripts::SaveAllScripts");
-#endif
- 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;
- uint32 type, handle;
- if (!pBuilding) {
- type = 0;
- handle = 0;
- } else if (pBuilding->GetIsATreadable()) {
- type = 1;
- handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding) + 1;
- } else {
- type = 2;
- handle = CPools::GetBuildingPool()->GetJustIndex(pBuilding) + 1;
- }
- WriteSaveBuf(buf, type);
- WriteSaveBuf(buf, handle);
- WriteSaveBuf(buf, BuildingSwapArray[i].m_nNewModel);
- WriteSaveBuf(buf, BuildingSwapArray[i].m_nOldModel);
- }
- for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {
- CEntity* pEntity = InvisibilitySettingArray[i];
- uint32 type, handle;
- if (!pEntity) {
- type = 0;
- handle = 0;
- } else {
- switch (pEntity->GetType()) {
- case ENTITY_TYPE_BUILDING:
- if (((CBuilding*)pEntity)->GetIsATreadable()) {
- type = 1;
- handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pEntity) + 1;
- } else {
- type = 2;
- handle = CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pEntity) + 1;
- }
- break;
- case ENTITY_TYPE_OBJECT:
- type = 3;
- handle = CPools::GetObjectPool()->GetJustIndex((CObject*)pEntity) + 1;
- break;
- case ENTITY_TYPE_DUMMY:
- type = 4;
- handle = CPools::GetDummyPool()->GetJustIndex((CDummy*)pEntity) + 1;
- default: break;
- }
- }
- WriteSaveBuf(buf, type);
- WriteSaveBuf(buf, handle);
- }
- WriteSaveBuf(buf, bUsingAMultiScriptFile);
- WriteSaveBuf(buf, (uint8)0);
- WriteSaveBuf(buf, (uint16)0);
- WriteSaveBuf(buf, MainScriptSize);
- WriteSaveBuf(buf, LargestMissionScriptSize);
- WriteSaveBuf(buf, NumberOfMissionScripts);
- WriteSaveBuf(buf, (uint16)0);
- WriteSaveBuf(buf, runningScripts);
- for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
- pScript->Save(buf);
-VALIDATESAVEBUF(*size)
-}
-
-void CTheScripts::LoadAllScripts(uint8* buf, uint32 size)
-{
- Init();
-INITSAVEBUF
- CheckSaveHeader(buf, 'S', 'C', 'R', '\0', size - SAVE_HEADER_SIZE);
- uint32 varSpace = ReadSaveBuf<uint32>(buf);
- for (uint32 i = 0; i < varSpace; i++)
- ScriptSpace[i] = ReadSaveBuf<uint8>(buf);
- script_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);
- uint32 handle = ReadSaveBuf<uint32>(buf);
- switch (type) {
- case 0:
- BuildingSwapArray[i].m_pBuilding = nil;
- break;
- case 1:
- BuildingSwapArray[i].m_pBuilding = CPools::GetTreadablePool()->GetSlot(handle - 1);
- break;
- case 2:
- BuildingSwapArray[i].m_pBuilding = CPools::GetBuildingPool()->GetSlot(handle - 1);
- break;
- default:
- script_assert(false);
- }
- BuildingSwapArray[i].m_nNewModel = ReadSaveBuf<uint32>(buf);
- BuildingSwapArray[i].m_nOldModel = ReadSaveBuf<uint32>(buf);
- if (BuildingSwapArray[i].m_pBuilding)
- BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nNewModel);
- }
- for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {
- uint32 type = ReadSaveBuf<uint32>(buf);
- uint32 handle = ReadSaveBuf<uint32>(buf);
- switch (type) {
- case 0:
- InvisibilitySettingArray[i] = nil;
- break;
- case 1:
- InvisibilitySettingArray[i] = CPools::GetTreadablePool()->GetSlot(handle - 1);
- break;
- case 2:
- InvisibilitySettingArray[i] = CPools::GetBuildingPool()->GetSlot(handle - 1);
- break;
- case 3:
- InvisibilitySettingArray[i] = CPools::GetObjectPool()->GetSlot(handle - 1);
- break;
- case 4:
- InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);
- break;
- default:
- script_assert(false);
- }
- if (InvisibilitySettingArray[i])
- InvisibilitySettingArray[i]->bIsVisible = false;
- }
- script_assert(ReadSaveBuf<bool>(buf) == bUsingAMultiScriptFile);
- ReadSaveBuf<uint8>(buf);
- ReadSaveBuf<uint16>(buf);
- script_assert(ReadSaveBuf<uint32>(buf) == MainScriptSize);
- script_assert(ReadSaveBuf<uint32>(buf) == LargestMissionScriptSize);
- script_assert(ReadSaveBuf<uint16>(buf) == NumberOfMissionScripts);
- ReadSaveBuf<uint16>(buf);
- uint32 runningScripts = ReadSaveBuf<uint32>(buf);
- for (uint32 i = 0; i < runningScripts; i++)
- StartNewScript(0)->Load(buf);
-VALIDATESAVEBUF(size)
-}
-
-#undef SCRIPT_DATA_SIZE
-
-void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity)
-{
- static CColPoint aTempColPoints[MAX_COLLISION_POINTS];
- int16 entities = 0;
- CEntity* aEntities[16];
- CWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false);
- if (entities <= 0)
- return;
- for (uint16 i = 0; i < entities; i++) {
- if (aEntities[i] != pEntity && aEntities[i]->IsPed() && ((CPed*)aEntities[i])->bInVehicle)
- aEntities[i] = nil;
- }
- for (uint16 i = 0; i < entities; i++) {
- if (aEntities[i] == pEntity || !aEntities[i])
- continue;
- CEntity* pFound = aEntities[i];
- int cols;
- if (pEntity->GetColModel()->numLines <= 0)
- cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
- pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil);
- else {
- float lines[4];
- lines[0] = lines[1] = lines[2] = lines[3] = 1.0f;
- CColPoint tmp[4];
- cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
- pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines);
- }
- if (cols <= 0)
- continue;
- switch (pFound->GetType()) {
- case ENTITY_TYPE_VEHICLE:
- {
- printf("Will try to delete a vehicle where a mission entity should be\n");
- CVehicle* pVehicle = (CVehicle*)pFound;
- if (pVehicle->bIsLocked || !pVehicle->CanBeDeleted())
- break;
- if (pVehicle->pDriver) {
- CPopulation::RemovePed(pVehicle->pDriver);
- pVehicle->pDriver = nil;
- }
- for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
- if (pVehicle->pPassengers[i]) {
- CPopulation::RemovePed(pVehicle->pPassengers[i]);
- pVehicle->pPassengers[i] = 0;
- pVehicle->m_nNumPassengers--;
- }
- }
- CCarCtrl::RemoveFromInterestingVehicleList(pVehicle);
- CWorld::Remove(pVehicle);
- delete pVehicle;
- break;
- }
- case ENTITY_TYPE_PED:
- {
- CPed* pPed = (CPed*)pFound;
- if (pPed->IsPlayer() || !pPed->CanBeDeleted())
- break;
- CPopulation::RemovePed(pPed);
- printf("Deleted a ped where a mission entity should be\n");
- break;
- }
- default: break;
- }
- }
-}
-
-void CTheScripts::HighlightImportantArea(uint32 id, float x1, float y1, float x2, float y2, float z)
-{
- float infX, infY, supX, supY;
- if (x1 < x2) {
- infX = x1;
- supX = x2;
- } else {
- infX = x2;
- supX = x1;
- }
- if (y1 < y2) {
- infY = y1;
- supY = y2;
- }
- else {
- infY = y2;
- supY = y1;
- }
- CVector center;
- center.x = (infX + supX) / 2;
- center.y = (infY + supY) / 2;
- center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z;
- CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, &center, supX - center.x, 0.0f, 0.0f, center.y - supY, 0);
-}
-
-void CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float z)
-{
- float infX, infY, supX, supY, X, Y;
- X = (x1 + x2) / 2;
- Y = (y1 + y2) / 2;
- supX = infX = X;
- supY = infY = Y;
- X = (x2 + x3) / 2;
- Y = (y2 + y3) / 2;
- infX = Min(infX, X);
- supX = Max(supX, X);
- infY = Min(infY, Y);
- supY = Max(supY, Y);
- X = (x3 + x4) / 2;
- Y = (y3 + y4) / 2;
- infX = Min(infX, X);
- supX = Max(supX, X);
- infY = Min(infY, Y);
- supY = Max(supY, Y);
- X = (x4 + x1) / 2;
- Y = (y4 + y1) / 2;
- infX = Min(infX, X);
- supX = Max(supX, X);
- infY = Min(infY, Y);
- supY = Max(supY, Y);
- CVector center;
- center.x = (infX + supX) / 2;
- center.y = (infY + supY) / 2;
- center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z;
- CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, &center, supX - center.x, 0.0f, 0.0f, center.y - supY, 0);
-}
-
-bool CTheScripts::IsPedStopped(CPed* pPed)
-{
- if (pPed->bInVehicle)
- return IsVehicleStopped(pPed->m_pMyVehicle);
- return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL;
-}
-
-bool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer)
-{
- CPed* pPed = pPlayer->m_pPed;
- if (pPed->bInVehicle)
- return IsVehicleStopped(pPed->m_pMyVehicle);
- if (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP) ||
- RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP_R) ||
- RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_LAUNCH) ||
- RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_GLIDE))
- return false;
- return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL;
-}
-
-bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
-{
- return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;
-}
-
-void CTheScripts::CleanUpThisPed(CPed* pPed)
-{
- if (!pPed)
- return;
- if (pPed->CharCreatedBy != MISSION_CHAR)
- return;
- pPed->CharCreatedBy = RANDOM_CHAR;
- if (pPed->m_nPedType == PEDTYPE_PROSTITUTE)
- pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000;
- if (pPed->bInVehicle) {
- if (pPed->m_pMyVehicle->pDriver == pPed) {
- if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {
- CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle);
- pPed->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- }
- }
- else {
- if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {
- pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle);
- pPed->bWanderPathAfterExitingCar = true;
- }
- }
- }
- bool flees = false;
- PedState state;
- eMoveState ms;
- if (pPed->m_nPedState == PED_FLEE_ENTITY || pPed->m_nPedState == PED_FLEE_POS) {
- ms = pPed->m_nMoveState;
- state = pPed->m_nPedState;
- flees = true;
- }
- pPed->ClearObjective();
- pPed->bRespondsToThreats = true;
- pPed->bScriptObjectiveCompleted = false;
- pPed->ClearLeader();
- if (pPed->IsPedInControl())
- pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7);
- if (flees) {
- pPed->m_nPedState = state;
- pPed->SetMoveState(ms);
- }
- --CPopulation::ms_nTotalMissionPeds;
-}
-
-void CTheScripts::CleanUpThisVehicle(CVehicle* pVehicle)
-{
- if (!pVehicle)
- return;
- if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE)
- return;
- pVehicle->bIsLocked = false;
- CCarCtrl::RemoveFromInterestingVehicleList(pVehicle);
- pVehicle->VehicleCreatedBy = RANDOM_VEHICLE;
- ++CCarCtrl::NumRandomCars;
- --CCarCtrl::NumMissionCars;
-}
-
-void CTheScripts::CleanUpThisObject(CObject* pObject)
-{
- if (!pObject)
- return;
- if (pObject->ObjectCreatedBy != MISSION_OBJECT)
- return;
- pObject->ObjectCreatedBy = TEMP_OBJECT;
- pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;
- pObject->m_nRefModelIndex = -1;
- pObject->bUseVehicleColours = false;
- ++CObject::nNoTempObjects;
-}
-
-void CTheScripts::ReadObjectNamesFromScript()
-{
- int32 varSpace = GetSizeOfVariableSpace();
- uint32 ip = varSpace + 8;
- NumberOfUsedObjects = Read2BytesFromScript(&ip);
- ip += 2;
- for (uint16 i = 0; i < NumberOfUsedObjects; i++) {
- for (int j = 0; j < USED_OBJECT_NAME_LENGTH; j++)
- UsedObjectArray[i].name[j] = ScriptSpace[ip++];
- UsedObjectArray[i].index = 0;
- }
-}
-
-void CTheScripts::UpdateObjectIndices()
-{
- char name[USED_OBJECT_NAME_LENGTH];
- char error[112];
- for (int i = 1; i < NumberOfUsedObjects; i++) {
- bool found = false;
- for (int j = 0; j < MODELINFOSIZE && !found; j++) {
- CBaseModelInfo* pModel = CModelInfo::GetModelInfo(j);
- if (!pModel)
- continue;
- strcpy(name, pModel->GetName());
-#ifdef FIX_BUGS
- for (int k = 0; k < USED_OBJECT_NAME_LENGTH && name[k]; k++)
-#else
- for (int k = 0; k < USED_OBJECT_NAME_LENGTH; k++)
-#endif
- name[k] = toupper(name[k]);
- if (strcmp(name, UsedObjectArray[i].name) == 0) {
- found = true;
- UsedObjectArray[i].index = j;
- }
- }
- if (!found) {
- sprintf(error, "CTheScripts::UpdateObjectIndices - Couldn't find %s", UsedObjectArray[i].name);
- debug("%s\n", error);
- }
- }
-}
-
-void CTheScripts::ReadMultiScriptFileOffsetsFromScript()
-{
- int32 varSpace = GetSizeOfVariableSpace();
- uint32 ip = varSpace + 3;
- int32 objectSize = Read4BytesFromScript(&ip);
- ip = objectSize + 8;
- MainScriptSize = Read4BytesFromScript(&ip);
- LargestMissionScriptSize = Read4BytesFromScript(&ip);
- NumberOfMissionScripts = Read2BytesFromScript(&ip);
- ip += 2;
- for (int i = 0; i < NumberOfMissionScripts; i++) {
- MultiScriptArray[i] = Read4BytesFromScript(&ip);
- }
-}
void CRunningScript::Save(uint8*& buf)
{
@@ -13335,3 +4428,44 @@ void RetryMission(int type, int unk)
}
#endif
+
+#ifdef MISSION_SWITCHER
+void
+CTheScripts::SwitchToMission(int32 mission)
+{
+ for (CRunningScript* pScript = CTheScripts::pActiveScripts; pScript != nil; pScript = pScript->GetNext()) {
+ if (!pScript->m_bIsMissionScript || !pScript->m_bDeatharrestEnabled) {
+ continue;
+ }
+ while (pScript->m_nStackPointer > 0)
+ --pScript->m_nStackPointer;
+
+ pScript->m_nIp = pScript->m_anStack[pScript->m_nStackPointer];
+ *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0;
+ pScript->m_nWakeTime = 0;
+ pScript->m_bDeatharrestExecuted = true;
+
+ while (!pScript->ProcessOneCommand());
+
+ CMessages::ClearMessages();
+ }
+
+#ifdef MISSION_REPLAY
+ missionRetryScriptIndex = mission;
+ if (missionRetryScriptIndex == 19)
+ CStats::LastMissionPassedName[0] = '\0';
+#endif
+ CTimer::Suspend();
+ int offset = CTheScripts::MultiScriptArray[mission];
+ CFileMgr::ChangeDir("\\");
+ int handle = CFileMgr::OpenFile("data\\main.scm", "rb");
+ CFileMgr::Seek(handle, offset, 0);
+ CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);
+ CFileMgr::CloseFile(handle);
+ CRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT);
+ CTimer::Resume();
+ pMissionScript->m_bIsMissionScript = true;
+ pMissionScript->m_bMissionFlag = true;
+ CTheScripts::bAlreadyRunningAMissionScript = true;
+}
+#endif
diff --git a/src/control/Script.h b/src/control/Script.h
index e0ed314e..12f3233f 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -13,6 +13,29 @@ class CPlayerInfo;
class CRunningScript;
+extern int32 ScriptParams[32];
+
+void FlushLog();
+#define script_assert(_Expression) FlushLog(); assert(_Expression);
+
+#define PICKUP_PLACEMENT_OFFSET 0.5f
+#define PED_FIND_Z_OFFSET 5.0f
+
+#define SPHERE_MARKER_R 0
+#define SPHERE_MARKER_G 128
+#define SPHERE_MARKER_B 255
+#define SPHERE_MARKER_A 128
+#define SPHERE_MARKER_PULSE_PERIOD 2048
+#define SPHERE_MARKER_PULSE_FRACTION 0.1f
+
+#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
+#define METERS_IN_FOOT 0.3048f
+#define FEET_IN_METER 3.28084f
+#else
+#define METERS_IN_FOOT 0.3f
+#define FEET_IN_METER 3.33f
+#endif
+
#define KEY_LENGTH_IN_SCRIPT 8
struct intro_script_rectangle
@@ -376,6 +399,11 @@ private:
#ifdef FIX_BUGS
friend void RetryMission(int, int);
#endif
+
+#ifdef MISSION_SWITCHER
+public:
+ static void SwitchToMission(int32 mission);
+#endif
};
@@ -514,6 +542,8 @@ private:
return false;
}
}
+
+ friend class CTheScripts;
};
#ifdef MISSION_REPLAY
diff --git a/src/control/Script2.cpp b/src/control/Script2.cpp
new file mode 100644
index 00000000..562125c6
--- /dev/null
+++ b/src/control/Script2.cpp
@@ -0,0 +1,1555 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "Camera.h"
+#include "CarCtrl.h"
+#include "CarGen.h"
+#include "CivilianPed.h"
+#include "CopPed.h"
+#include "Cranes.h"
+#include "DMAudio.h"
+#include "EmergencyPed.h"
+#include "Garages.h"
+#include "General.h"
+#include "Messages.h"
+#include "Pad.h"
+#include "PedRoutes.h"
+#include "Pools.h"
+#include "Population.h"
+#include "Radar.h"
+#include "Restart.h"
+#include "Shadows.h"
+#include "User.h"
+#include "Wanted.h"
+#include "WaterLevel.h"
+#include "Weather.h"
+#include "World.h"
+#include "Zones.h"
+
+int8 CRunningScript::ProcessCommands300To399(int32 command)
+{
+ switch (command) {
+ /* Not implemented.
+ case COMMAND_SET_CHAR_INVINCIBLE:
+ case COMMAND_SET_PLAYER_INVINCIBLE:
+ case COMMAND_SET_CHAR_GRAPHIC_TYPE:
+ case COMMAND_SET_PLAYER_GRAPHIC_TYPE:
+ */
+ case COMMAND_HAS_PLAYER_BEEN_ARRESTED:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED);
+ return 0;
+ /* Not implemented.
+ case COMMAND_STOP_CHAR_DRIVING:
+ case COMMAND_KILL_CHAR:
+ case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR:
+ case COMMAND_SET_CHAR_OCCUPATION:
+ */
+ case COMMAND_CHANGE_CAR_LOCK:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SHAKE_CAM_WITH_POINT:
+ CollectParameters(&m_nIp, 4);
+ TheCamera.CamShake(ScriptParams[0] / 1000.0f,
+ *(float*)&ScriptParams[1],
+ *(float*)&ScriptParams[2],
+ *(float*)&ScriptParams[3]);
+ return 0;
+ case COMMAND_IS_CAR_MODEL:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_IS_CAR_REMAP:
+ case COMMAND_HAS_CAR_JUST_SUNK:
+ case COMMAND_SET_CAR_NO_COLLIDE:
+ */
+ case COMMAND_IS_CAR_DEAD_IN_AREA_2D:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ float x1 = *(float*)&ScriptParams[1];
+ float y1 = *(float*)&ScriptParams[2];
+ float x2 = *(float*)&ScriptParams[3];
+ float y2 = *(float*)&ScriptParams[4];
+ UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED &&
+ pVehicle->IsWithinArea(x1, y1, x2, y2));
+ if (ScriptParams[5])
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag)
+ CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
+ return 0;
+ }
+ case COMMAND_IS_CAR_DEAD_IN_AREA_3D:
+ {
+ CollectParameters(&m_nIp, 8);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ float x1 = *(float*)&ScriptParams[1];
+ float y1 = *(float*)&ScriptParams[2];
+ float z1 = *(float*)&ScriptParams[3];
+ float x2 = *(float*)&ScriptParams[4];
+ float y2 = *(float*)&ScriptParams[5];
+ float z2 = *(float*)&ScriptParams[6];
+ UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED &&
+ pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));
+ if (ScriptParams[7])
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2);
+ if (CTheScripts::DbgFlag)
+ CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_IS_TRAILER_ATTACHED:
+ case COMMAND_IS_CAR_ON_TRAILER:
+ case COMMAND_HAS_CAR_GOT_WEAPON:
+ case COMMAND_PARK:
+ case COMMAND_HAS_PARK_FINISHED:
+ case COMMAND_KILL_ALL_PASSENGERS:
+ case COMMAND_SET_CAR_BULLETPROOF:
+ case COMMAND_SET_CAR_FLAMEPROOF:
+ case COMMAND_SET_CAR_ROCKETPROOF:
+ case COMMAND_IS_CARBOMB_ACTIVE:
+ case COMMAND_GIVE_CAR_ALARM:
+ case COMMAND_PUT_CAR_ON_TRAILER:
+ */
+ case COMMAND_IS_CAR_CRUSHED:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0]));
+ return 0;
+ /* Not implemented.
+ case COMMAND_CREATE_GANG_CAR:
+ */
+ case COMMAND_CREATE_CAR_GENERATOR:
+ CollectParameters(&m_nIp, 12);
+ ScriptParams[0] = CTheCarGenerators::CreateCarGenerator(
+ *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3],
+ ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7],
+ ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SWITCH_CAR_GENERATOR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CCarGenerator* pCarGen = &CTheCarGenerators::CarGeneratorArray[ScriptParams[0]];
+ if (ScriptParams[1] == 0){
+ pCarGen->SwitchOff();
+ }else if (ScriptParams[1] <= 100){
+ pCarGen->SwitchOn();
+ pCarGen->SetUsesRemaining(ScriptParams[1]);
+ }else{
+ pCarGen->SwitchOn();
+ }
+ return 0;
+ }
+ case COMMAND_ADD_PAGER_MESSAGE:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 3);
+ CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_DISPLAY_ONSCREEN_TIMER:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
+ m_nIp++;
+ CUserDisplay::OnscnTimer.AddClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp), nil);
+ return 0;
+ }
+ case COMMAND_CLEAR_ONSCREEN_TIMER:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
+ m_nIp++;
+ CUserDisplay::OnscnTimer.ClearClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp));
+ return 0;
+ }
+ case COMMAND_DISPLAY_ONSCREEN_COUNTER:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
+ m_nIp++;
+ uint16 counter = CTheScripts::Read2BytesFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 1);
+ CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil);
+ return 0;
+ }
+ case COMMAND_CLEAR_ONSCREEN_COUNTER:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
+ m_nIp++;
+ CUserDisplay::OnscnTimer.ClearCounter((uint16)CTheScripts::Read2BytesFromScript(&m_nIp));
+ return 0;
+ }
+ case COMMAND_SET_ZONE_CAR_INFO:
+ {
+ char label[12];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CollectParameters(&m_nIp, 16);
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(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]);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_IS_CHAR_IN_GANG_ZONE:
+ */
+ case COMMAND_IS_CHAR_IN_ZONE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ char label[12];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ 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)));
+ return 0;
+ }
+ 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);
+ // ScriptParams[0] is unused.
+ TheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
+ return 0;
+ }
+ case COMMAND_POINT_CAMERA_AT_CAR:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
+ return 0;
+ }
+ case COMMAND_POINT_CAMERA_AT_CHAR:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
+ return 0;
+ }
+ case COMMAND_RESTORE_CAMERA:
+ TheCamera.Restore();
+ return 0;
+ case COMMAND_SHAKE_PAD:
+ CPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]);
+ return 0;
+ case COMMAND_SET_ZONE_PED_INFO:
+ {
+ char label[12];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CollectParameters(&m_nIp, 10);
+ int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ 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]);
+ return 0;
+ }
+ case COMMAND_SET_TIME_SCALE:
+ CollectParameters(&m_nIp, 1);
+ CTimer::SetTimeScale(*(float*)&ScriptParams[0]);
+ return 0;
+ case COMMAND_IS_CAR_IN_AIR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle && pVehicle->IsCar());
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ UpdateCompareFlag(pCar->GetAllWheelsOffGround());
+ return 0;
+ }
+ case COMMAND_SET_FIXED_CAMERA_POSITION:
+ {
+ CollectParameters(&m_nIp, 6);
+ TheCamera.SetCamPositionForFixedMode(
+ CVector(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]),
+ CVector(*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5]));
+ return 0;
+ }
+ case COMMAND_POINT_CAMERA_AT_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);
+ TheCamera.TakeControlNoEntity(pos, ScriptParams[3], CAMCONTROL_SCRIPT);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_CAR_OLD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ // Useless call.
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_CHAR_OLD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ // Useless call.
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_OBJECT_OLD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ // Useless call.
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_REMOVE_BLIP:
+ CollectParameters(&m_nIp, 1);
+ CRadar::ClearBlip(ScriptParams[0]);
+ return 0;
+ case COMMAND_CHANGE_BLIP_COLOUR:
+ CollectParameters(&m_nIp, 2);
+ CRadar::ChangeBlipColour(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_DIM_BLIP:
+ CollectParameters(&m_nIp, 2);
+ CRadar::ChangeBlipBrightness(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_ADD_BLIP_FOR_COORD_OLD:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ // Useless call
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CHANGE_BLIP_SCALE:
+ CollectParameters(&m_nIp, 2);
+ CRadar::ChangeBlipScale(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_SET_FADING_COLOUR:
+ CollectParameters(&m_nIp, 3);
+ TheCamera.SetFadeColour(ScriptParams[0], ScriptParams[1], ScriptParams[2]);
+ return 0;
+ case COMMAND_DO_FADE:
+ CollectParameters(&m_nIp, 2);
+ TheCamera.Fade(ScriptParams[0] / 1000.0f, ScriptParams[1]);
+ return 0;
+ case COMMAND_GET_FADING_STATUS:
+ UpdateCompareFlag(TheCamera.GetFading());
+ return 0;
+ case COMMAND_ADD_HOSPITAL_RESTART:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ float angle = *(float*)&ScriptParams[3];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRestart::AddHospitalRestartPoint(pos, angle);
+ return 0;
+ }
+ case COMMAND_ADD_POLICE_RESTART:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ float angle = *(float*)&ScriptParams[3];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRestart::AddPoliceRestartPoint(pos, angle);
+ return 0;
+ }
+ case COMMAND_OVERRIDE_NEXT_RESTART:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ float angle = *(float*)&ScriptParams[3];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRestart::OverrideNextRestart(pos, angle);
+ return 0;
+ }
+ case COMMAND_DRAW_SHADOW:
+ {
+ CollectParameters(&m_nIp, 10);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ float angle = *(float*)&ScriptParams[4];
+ float length = *(float*)&ScriptParams[5];
+ float x, y;
+ if (angle != 0.0f){
+ y = cos(angle) * length;
+ x = sin(angle) * length;
+ }else{
+ y = length;
+ x = 0.0f;
+ }
+ float frontX = -x;
+ float frontY = y;
+ float sideX = y;
+ float sideY = x;
+ /* Not very nicely named intermediate variables. */
+ CShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY,
+ ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]);
+ return 0;
+ }
+ case COMMAND_GET_PLAYER_HEADING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();
+ *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_HEADING:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ if (pPed->bInVehicle){
+ // Is script_assertion required?
+ return 0;
+ }
+ pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);
+ pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
+ return 0;
+ }
+ case COMMAND_GET_CHAR_HEADING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();
+ *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_HEADING:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (pPed->bInVehicle) {
+ // Is script_assertion required?
+ return 0;
+ }
+ pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);
+ pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
+ return 0;
+ }
+ case COMMAND_GET_CAR_HEADING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ float angle = pVehicle->GetForward().Heading();
+ *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CAR_HEADING:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
+ return 0;
+ }
+ case COMMAND_GET_OBJECT_HEADING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ float angle = pObject->GetForward().Heading();
+ *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_HEADING:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CWorld::Remove(pObject);
+ pObject->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
+ pObject->GetMatrix().UpdateRW();
+ pObject->UpdateRwFrame();
+ CWorld::Add(pObject);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_TOUCHING_OBJECT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ script_assert(pObject);
+ CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed;
+ UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));
+ return 0;
+ }
+ case COMMAND_IS_CHAR_TOUCHING_OBJECT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ script_assert(pObject);
+ CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed;
+ UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_AMMO:
+ {
+ CollectParameters(&m_nIp, 3);
+ CWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_AMMO:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_SET_CAR_AMMO:
+ case COMMAND_LOAD_CAMERA_SPLINE:
+ case COMMAND_MOVE_CAMERA_ALONG_SPLINE:
+ case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE:
+ */
+ case COMMAND_DECLARE_MISSION_FLAG:
+ CTheScripts::OnAMissionFlag = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp);
+ return 0;
+ case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = (uint16)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_IS_PLAYER_HEALTH_GREATER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_HEALTH_GREATER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_IS_CAR_HEALTH_GREATER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->m_fHealth > ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ // Useless call.
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);
+ CRadar::ChangeBlipScale(handle, 3);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_CHAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ // Useless call.
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);
+ CRadar::ChangeBlipScale(handle, 3);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_OBJECT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ // Useless call.
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);
+ CRadar::ChangeBlipScale(handle, 3);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_CONTACT_POINT:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ // Useless call
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
+ CRadar::ChangeBlipScale(handle, 3);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_COORD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ // Useless call
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
+ CRadar::ChangeBlipScale(handle, 3);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CHANGE_BLIP_DISPLAY:
+ CollectParameters(&m_nIp, 2);
+ CRadar::ChangeBlipDisplay(ScriptParams[0], (eBlipDisplay)ScriptParams[1]);
+ return 0;
+ case COMMAND_ADD_ONE_OFF_SOUND:
+ {
+ CollectParameters(&m_nIp, 4);
+ switch (ScriptParams[3]) {
+ case SCRIPT_SOUND_EVIDENCE_PICKUP:
+ DMAudio.PlayFrontEndSound(SOUND_EVIDENCE_PICKUP, 0);
+ return 0;
+ case SCRIPT_SOUND_UNLOAD_GOLD:
+ DMAudio.PlayFrontEndSound(SOUND_UNLOAD_GOLD, 0);
+ return 0;
+ case SCRIPT_SOUND_PART_MISSION_COMPLETE:
+ DMAudio.PlayFrontEndSound(SOUND_PART_MISSION_COMPLETE, 0);
+ return 0;
+ case SCRIPT_SOUND_RACE_START_3:
+ DMAudio.PlayFrontEndSound(SOUND_RACE_START_3, 0);
+ return 0;
+ case SCRIPT_SOUND_RACE_START_2:
+ DMAudio.PlayFrontEndSound(SOUND_RACE_START_2, 0);
+ return 0;
+ case SCRIPT_SOUND_RACE_START_1:
+ DMAudio.PlayFrontEndSound(SOUND_RACE_START_1, 0);
+ return 0;
+ case SCRIPT_SOUND_RACE_START_GO:
+ DMAudio.PlayFrontEndSound(SOUND_RACE_START_GO, 0);
+ return 0;
+ default:
+ break;
+ }
+#ifdef FIX_BUGS
+ /* BUG: if audio is not initialized, this object will not be freed. */
+ if (!DMAudio.IsAudioInitialised())
+ return 0;
+#endif
+ cAudioScriptObject* obj = new cAudioScriptObject();
+ obj->Posn = *(CVector*)&ScriptParams[0];
+ obj->AudioId = ScriptParams[3];
+ obj->AudioEntity = AEHANDLE_NONE;
+ DMAudio.CreateOneShotScriptObject(obj);
+ return 0;
+ }
+ case COMMAND_ADD_CONTINUOUS_SOUND:
+ {
+ CollectParameters(&m_nIp, 4);
+ cAudioScriptObject* obj = new cAudioScriptObject();
+ obj->Posn = *(CVector*)&ScriptParams[0];
+ obj->AudioId = ScriptParams[3];
+ obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj);
+ ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_REMOVE_SOUND:
+ {
+ CollectParameters(&m_nIp, 1);
+ cAudioScriptObject* obj = CPools::GetAudioScriptObjectPool()->GetAt(ScriptParams[0]);
+ if (!obj){
+ debug("REMOVE_SOUND - Sound doesn't exist\n");
+ return 0;
+ }
+ DMAudio.DestroyLoopingScriptObject(obj->AudioEntity);
+ delete obj;
+ return 0;
+ }
+ case COMMAND_IS_CAR_STUCK_ON_ROOF:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(CTheScripts::UpsideDownCars.HasCarBeenUpsideDownForAWhile(ScriptParams[0]));
+ return 0;
+ }
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands400To499(int32 command)
+{
+ switch (command) {
+ case COMMAND_ADD_UPSIDEDOWN_CAR_CHECK:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CTheScripts::UpsideDownCars.AddCarToCheck(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CTheScripts::UpsideDownCars.RemoveCarFromCheck(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GUARD_SPOT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GUARD_AREA:
+ {
+ CollectParameters(&m_nIp, 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ float infX = *(float*)&ScriptParams[1];
+ float infY = *(float*)&ScriptParams[2];
+ float supX = *(float*)&ScriptParams[3];
+ float supY = *(float*)&ScriptParams[4];
+ if (infX > supX){
+ infX = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[1];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[2];
+ }
+ CVector pos;
+ pos.x = (infX + supX) / 2;
+ pos.y = (infY + supY) / 2;
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = Max(pos.x - infX, pos.y - infY);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos, radius);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_WAIT_IN_CAR);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
+ PlayerInAreaCheckCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
+ CharInAreaCheckCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
+ CarInAreaCheckCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_LOCATE_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_CAR_2D:
+ case COMMAND_LOCATE_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_CAR_3D:
+ LocateCarCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_GIVE_WEAPON_TO_PLAYER:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->m_nSelectedWepSlot = pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_GIVE_WEAPON_TO_CHAR:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]));
+ if (pPed->bInVehicle)
+ pPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);
+ return 0;
+ }
+ /* Not implemented */
+ //case COMMAND_GIVE_WEAPON_TO_CAR:
+ case COMMAND_SET_PLAYER_CONTROL:
+ {
+ 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);
+ }
+ }else{
+ pPlayer->MakePlayerSafe(true);
+ if (strcmp(m_abScriptName, "camera") == 0){
+ pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ pPlayer->m_pPed->SetTurnSpeed(0.0f, 0.0f, 0.0f);
+ CAnimManager::BlendAnimation((RpClump*)pPlayer->m_pPed->m_rwObject, pPlayer->m_pPed->m_animGroup, ANIM_IDLE_STANCE, 1000.0f);
+ }
+ }
+ return 0;
+ }
+ case COMMAND_FORCE_WEATHER:
+ CollectParameters(&m_nIp, 1);
+ CWeather::ForceWeather(ScriptParams[0]);
+ return 0;
+ case COMMAND_FORCE_WEATHER_NOW:
+ CollectParameters(&m_nIp, 1);
+ CWeather::ForceWeatherNow(ScriptParams[0]);
+ return 0;
+ case COMMAND_RELEASE_WEATHER:
+ CWeather::ReleaseWeather();
+ return 0;
+ case COMMAND_SET_CURRENT_PLAYER_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++){
+ if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
+ pPed->m_nSelectedWepSlot = i;
+ }
+ return 0;
+ }
+ case COMMAND_SET_CURRENT_CHAR_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
+ if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
+ pPed->SetCurrentWeapon(i);
+ }
+ return 0;
+ }
+ /* Not implemented */
+ //case COMMAND_SET_CURRENT_CAR_WEAPON:
+ case COMMAND_GET_OBJECT_COORDINATES:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ *(CVector*)&ScriptParams[0] = pObject->GetPosition();
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_COORDINATES:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pObject->Teleport(pos);
+ CTheScripts::ClearSpaceForMissionEntity(pos, pObject);
+ return 0;
+ }
+ case COMMAND_GET_GAME_TIMER:
+ ScriptParams[0] = CTimer::GetTimeInMilliseconds();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_TURN_CHAR_TO_FACE_COORD:
+ {
+ CollectParameters(&m_nIp, 4);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle;
+ CVector pos;
+ if (pPed->bInVehicle)
+ pVehicle = pPed->m_pMyVehicle;
+ else
+ pVehicle = nil;
+ if (pVehicle)
+ pos = pVehicle->GetPosition();
+ else
+ pos = pPed->GetPosition();
+ float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]);
+ heading += HALFPI;
+ if (heading > TWOPI)
+ heading -= TWOPI;
+ if (!pVehicle){
+ pPed->m_fRotationCur = heading;
+ pPed->m_fRotationDest = heading;
+ pPed->SetHeading(heading);
+ }
+ return 0;
+ }
+ case COMMAND_TURN_PLAYER_TO_FACE_COORD:
+ {
+ CollectParameters(&m_nIp, 4);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CVehicle* pVehicle;
+ CVector pos;
+ if (pPed->bInVehicle)
+ pVehicle = pPed->m_pMyVehicle;
+ else
+ pVehicle = nil;
+ if (pVehicle)
+ pos = pVehicle->GetPosition();
+ else
+ pos = pPed->GetPosition();
+ float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]);
+ heading += HALFPI;
+ if (heading > TWOPI)
+ heading -= TWOPI;
+ if (!pVehicle) {
+ pPed->m_fRotationCur = heading;
+ pPed->m_fRotationDest = heading;
+ pPed->SetHeading(heading);
+ }
+ return 0;
+ }
+ case COMMAND_STORE_WANTED_LEVEL:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ ScriptParams[0] = pPed->m_pWanted->m_nWantedLevel;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CAR_STOPPED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(CTheScripts::IsVehicleStopped(pVehicle));
+ return 0;
+ }
+ case COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CTheScripts::CleanUpThisPed(pPed);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ CTheScripts::CleanUpThisVehicle(pVehicle);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
+ return 0;
+ }
+ case COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ CTheScripts::CleanUpThisObject(pObject);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
+ return 0;
+ }
+ case COMMAND_DONT_REMOVE_CHAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_DONT_REMOVE_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
+ return 0;
+ }
+ case COMMAND_DONT_REMOVE_OBJECT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
+ return 0;
+ }
+ case COMMAND_CREATE_CHAR_AS_PASSENGER:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ switch (ScriptParams[2]) {
+ case MI_COP:
+ if (ScriptParams[1] == PEDTYPE_COP)
+ ScriptParams[2] = COP_STREET;
+ break;
+ case MI_SWAT:
+ if (ScriptParams[1] == PEDTYPE_COP)
+ ScriptParams[2] = COP_SWAT;
+ break;
+ case MI_FBI:
+ if (ScriptParams[1] == PEDTYPE_COP)
+ ScriptParams[2] = COP_FBI;
+ break;
+ case MI_ARMY:
+ if (ScriptParams[1] == PEDTYPE_COP)
+ ScriptParams[2] = COP_ARMY;
+ break;
+ case MI_MEDIC:
+ if (ScriptParams[1] == PEDTYPE_EMERGENCY)
+ ScriptParams[2] = PEDTYPE_EMERGENCY;
+ break;
+ case MI_FIREMAN:
+ if (ScriptParams[1] == PEDTYPE_FIREMAN)
+ ScriptParams[2] = PEDTYPE_FIREMAN;
+ break;
+ default:
+ break;
+ }
+ CPed* pPed;
+ if (ScriptParams[1] == PEDTYPE_COP)
+ pPed = new CCopPed((eCopType)ScriptParams[2]);
+ else if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN)
+ pPed = new CEmergencyPed(ScriptParams[2]);
+ else
+ pPed = new CCivilianPed((ePedType)ScriptParams[1], ScriptParams[2]);
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ pPed->bAllowMedicsToReviveMe = false;
+ pPed->SetPosition(pVehicle->GetPosition());
+ pPed->SetOrientation(0.0f, 0.0f, 0.0f);
+ pPed->SetPedState(PED_DRIVING);
+ CPopulation::ms_nTotalMissionPeds++;
+ if (ScriptParams[3] >= 0)
+ pVehicle->AddPassenger(pPed, ScriptParams[3]);
+ else
+ pVehicle->AddPassenger(pPed);
+ pPed->m_pMyVehicle = pVehicle;
+ pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
+ pPed->bInVehicle = true;
+ 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->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
+ CWorld::Add(pPed);
+ 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_OBJ_KILL_CHAR_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_LEAVE_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pVehicle);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR:
+ case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
+ case COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT:
+ */
+ case COMMAND_SET_CHAR_OBJ_DESTROY_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ float infX = *(float*)&ScriptParams[1];
+ float infY = *(float*)&ScriptParams[2];
+ float supX = *(float*)&ScriptParams[3];
+ float supY = *(float*)&ScriptParams[4];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[1];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[2];
+ }
+ CVector pos;
+ pos.x = (infX + supX) / 2;
+ pos.y = (infY + supY) / 2;
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = Max(pos.x - infX, pos.y - infY);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR:
+ case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+ case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK:
+ */
+ case COMMAND_SET_CHAR_AS_LEADER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_AS_LEADER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;
+ pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget);
+ return 0;
+ }
+ case COMMAND_LEAVE_GROUP:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->ClearLeader();
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FOLLOW_ROUTE, ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_ADD_ROUTE_POINT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CRouteNode::AddRoutePoint(ScriptParams[0], *(CVector*)&ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_NUMBER_BIG:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 3);
+ CMessages::AddBigMessageWithNumber(text, ScriptParams[1], ScriptParams[2] - 1, ScriptParams[0], -1, -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_NUMBER:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 3);
+ CMessages::AddMessageWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_NUMBER_NOW:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 3);
+ CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
+ return 0;
+ }
+ /* Not implemented.
+ case COMMAND_PRINT_WITH_NUMBER_SOON:
+ */
+ case COMMAND_SWITCH_ROADS_ON:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false);
+ return 0;
+ }
+ case COMMAND_SWITCH_ROADS_OFF:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true);
+ return 0;
+ }
+ case COMMAND_GET_NUMBER_OF_PASSENGERS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ ScriptParams[0] = pVehicle->m_nNumPassengers;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ ScriptParams[0] = pVehicle->m_nNumMaxPassengers;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CAR_DENSITY_MULTIPLIER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CCarCtrl::CarDensityMultiplier = *(float*)&ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_CAR_HEAVY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bIsHeavy = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_THREAT_SEARCH:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_fearFlags = 0;
+ return 0;
+ }
+ case COMMAND_ACTIVATE_CRANE:
+ {
+ CollectParameters(&m_nIp, 10);
+ float infX = *(float*)&ScriptParams[2];
+ float infY = *(float*)&ScriptParams[3];
+ float supX = *(float*)&ScriptParams[4];
+ float supY = *(float*)&ScriptParams[5];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[4];
+ supX = *(float*)&ScriptParams[2];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[5];
+ supY = *(float*)&ScriptParams[3];
+ }
+ CCranes::ActivateCrane(infX, supX, infY, supY,
+ *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
+ DEGTORAD(*(float*)&ScriptParams[9]), false, false,
+ *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_DEACTIVATE_CRANE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_SET_MAX_WANTED_LEVEL:
+ {
+ CollectParameters(&m_nIp, 1);
+ CWanted::SetMaximumWantedLevel(ScriptParams[0]);
+ return 0;
+ }
+ /* Debug commands?
+ case COMMAND_SAVE_VAR_INT:
+ case COMMAND_SAVE_VAR_FLOAT:
+ */
+ case COMMAND_IS_CAR_IN_AIR_PROPER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+#ifdef FIX_BUGS
+ // don't wanna get stuck in unique stunt jump cam forever
+ bool usj_with_dodo = strcmp(m_abScriptName, "usj") == 0 && pVehicle->GetModelIndex() == MI_DODO;
+ UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0 && !usj_with_dodo);
+#else
+ UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0);
+#endif
+ return 0;
+ }
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp
new file mode 100644
index 00000000..23ab453c
--- /dev/null
+++ b/src/control/Script3.cpp
@@ -0,0 +1,2082 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "Boat.h"
+#include "CarCtrl.h"
+#include "Clock.h"
+#include "Coronas.h"
+#include "Cranes.h"
+#include "CutsceneMgr.h"
+#include "Darkel.h"
+#include "Explosion.h"
+#include "Fire.h"
+#include "General.h"
+#include "Garages.h"
+#include "Heli.h"
+#include "Messages.h"
+#include "Pad.h"
+#include "ParticleObject.h"
+#include "Phones.h"
+#include "Pickups.h"
+#include "PointLights.h"
+#include "Population.h"
+#include "Pools.h"
+#include "ProjectileInfo.h"
+#include "Radar.h"
+#include "Restart.h"
+#include "Stats.h"
+#include "Streaming.h"
+#include "User.h"
+#include "WaterLevel.h"
+#include "Weather.h"
+#include "Zones.h"
+
+int8 CRunningScript::ProcessCommands500To599(int32 command)
+{
+ switch (command) {
+ case COMMAND_IS_CAR_UPSIDEDOWN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->GetUp().z <= -0.97f);
+ return 0;
+ }
+ case COMMAND_GET_PLAYER_CHAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CANCEL_OVERRIDE_RESTART:
+ CRestart::CancelOverrideRestart();
+ return 0;
+ case COMMAND_SET_POLICE_IGNORE_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ if (ScriptParams[1]) {
+ pPed->m_pWanted->m_bIgnoredByCops = true;
+ CWorld::StopAllLawEnforcersInTheirTracks();
+ }
+ else {
+ pPed->m_pWanted->m_bIgnoredByCops = false;
+ }
+ return 0;
+ }
+ case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 4);
+ CUserDisplay::Pager.AddMessageWithNumber(text, ScriptParams[0], -1, -1, -1, -1, -1,
+ ScriptParams[1], ScriptParams[2], ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_START_KILL_FRENZY:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 8);
+ CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],
+ ScriptParams[3], text, ScriptParams[4], ScriptParams[5],
+ ScriptParams[6], ScriptParams[7] != 0, false);
+ return 0;
+ }
+ case COMMAND_READ_KILL_FRENZY_STATUS:
+ {
+ ScriptParams[0] = CDarkel::ReadStatus();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SQRT:
+ {
+ CollectParameters(&m_nIp, 1);
+ *(float*)&ScriptParams[0] = Sqrt(*(float*)&ScriptParams[0]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:
+ LocatePlayerCarCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D:
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:
+ LocateCharCarCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE:
+ CollectParameters(&m_nIp, 2);
+ *(float*)&ScriptParams[0] = CGeneral::GetRandomNumberInRange(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_GENERATE_RANDOM_INT_IN_RANGE:
+ CollectParameters(&m_nIp, 2);
+ ScriptParams[0] = CGeneral::GetRandomNumberInRange(ScriptParams[0], ScriptParams[1]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_LOCK_CAR_DOORS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_EXPLODE_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->BlowUpCar(nil);
+ return 0;
+ }
+ case COMMAND_ADD_EXPLOSION:
+ CollectParameters(&m_nIp, 4);
+ CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0);
+ return 0;
+
+ case COMMAND_IS_CAR_UPRIGHT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->GetUp().z >= 0.0f);
+ return 0;
+ }
+ case COMMAND_TURN_CHAR_TO_FACE_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;
+ CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();
+ CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();
+ float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;
+ if (angle > TWOPI)
+ angle -= TWOPI;
+ if (!pVehicle) {
+ pSourcePed->m_fRotationCur = angle;
+ pSourcePed->m_fRotationDest = angle;
+ pSourcePed->SetHeading(angle);
+ }
+ return 0;
+ }
+ case COMMAND_TURN_CHAR_TO_FACE_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed;
+ CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;
+ CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();
+ CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();
+ float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;
+ if (angle > TWOPI)
+ angle -= TWOPI;
+ if (!pVehicle) {
+ pSourcePed->m_fRotationCur = angle;
+ pSourcePed->m_fRotationDest = angle;
+ pSourcePed->SetHeading(angle);
+ }
+ return 0;
+ }
+ case COMMAND_TURN_PLAYER_TO_FACE_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;
+ CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();
+ CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();
+ float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;
+ if (angle > TWOPI)
+ angle -= TWOPI;
+ if (!pVehicle) {
+ pSourcePed->m_fRotationCur = angle;
+ pSourcePed->m_fRotationDest = angle;
+ pSourcePed->SetHeading(angle);
+ }
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector target;
+ target.x = *(float*)&ScriptParams[1];
+ target.y = *(float*)&ScriptParams[2];
+ target.z = CWorld::FindGroundZForCoord(target.x, target.y);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target);
+ return 0;
+ }
+ /* Not implemented*/
+ //case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR:
+ case COMMAND_CREATE_PICKUP:
+ {
+ CollectParameters(&m_nIp, 5);
+ int16 model = ScriptParams[0];
+ if (model < 0)
+ model = CTheScripts::UsedObjectArray[-model].index;
+ CVector pos = *(CVector*)&ScriptParams[2];
+ 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, model, ScriptParams[1], 0);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_HAS_PICKUP_BEEN_COLLECTED:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CPickups::IsPickUpPickedUp(ScriptParams[0]) != 0);
+ return 0;
+ case COMMAND_REMOVE_PICKUP:
+ CollectParameters(&m_nIp, 1);
+ CPickups::RemovePickUp(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_TAXI_LIGHTS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ ((CAutomobile*)pVehicle)->SetTaxiLight(ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_PRINT_BIG_Q:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 2);
+ CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_NUMBER_BIG_Q:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 3);
+ CMessages::AddBigMessageWithNumberQ(text, ScriptParams[1], ScriptParams[2] - 1,
+ ScriptParams[0], -1, -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_SET_GARAGE:
+ {
+ CollectParameters(&m_nIp, 7);
+ 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(CVector(infX, infY, infZ), CVector(supX, supY, supZ), (eGarageType)ScriptParams[6], 0);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_GARAGE_WITH_CAR_MODEL:
+ {
+ CollectParameters(&m_nIp, 8);
+ 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(CVector(infX, infY, infZ), CVector(supX, supY, supZ), (eGarageType)ScriptParams[6], ScriptParams[7]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pTarget;
+ if (ScriptParams[1] >= 0) {
+ pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ }
+ else {
+ pTarget = nil;
+ }
+ CGarages::SetTargetCarForMissonGarage(ScriptParams[0], pTarget);
+ return 0;
+ }
+ case COMMAND_IS_CAR_IN_MISSION_GARAGE:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CGarages::HasCarBeenDroppedOffYet(ScriptParams[0]));
+ return 0;
+ case COMMAND_SET_FREE_BOMBS:
+ CollectParameters(&m_nIp, 1);
+ CGarages::SetFreeBombs(ScriptParams[0] != 0);
+ return 0;
+#ifdef GTA_PS2
+ case COMMAND_SET_POWERPOINT:
+ {
+ CollectParameters(&m_nIp, 7);
+ float f1 = *(float*)&ScriptParams[0];
+ float f2 = *(float*)&ScriptParams[1];
+ float f3 = *(float*)&ScriptParams[2];
+ float f4 = *(float*)&ScriptParams[3];
+ float f5 = *(float*)&ScriptParams[4];
+ float f6 = *(float*)&ScriptParams[5];
+ float temp;
+
+ if (f1 > f4) {
+ temp = f1;
+ f1 = f4;
+ f4 = temp;
+ }
+
+ if (f2 > f5) {
+ temp = f2;
+ f2 = f5;
+ f5 = temp;
+ }
+
+ if (f3 > f6) {
+ temp = f3;
+ f3 = f6;
+ f6 = temp;
+ }
+
+ CPowerPoints::GenerateNewOne(f1, f2, f3, f4, f5, f6, *(uint8*)&ScriptParams[6]);
+
+ return 0;
+ }
+#endif // GTA_PS2
+ case COMMAND_SET_ALL_TAXI_LIGHTS:
+ CollectParameters(&m_nIp, 1);
+ CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0);
+ return 0;
+ case COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB:
+ {
+ CollectParameters(&m_nIp, 1);
+ CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pCar);
+ script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);
+ UpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum
+ return 0;
+ }
+ case COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR:
+ CollectParameters(&m_nIp, 2);
+ CPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0);
+ return 0;
+ case COMMAND_SET_PLAYER_HEALTH:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->m_fHealth = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CHAR_HEALTH:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1]) {
+ pPed->m_fHealth = ScriptParams[1];
+ }
+ else if (pPed->bInVehicle) {
+ pPed->SetDead();
+ if (!pPed->IsPlayer())
+ pPed->FlagToDestroyWhenNextProcessed();
+ }
+ else {
+ pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ }
+ return 0;
+ }
+ case COMMAND_SET_CAR_HEALTH:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->m_fHealth = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_PLAYER_HEALTH:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ ScriptParams[0] = pPed->m_fHealth; // correct cast float to int
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_CHAR_HEALTH:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ ScriptParams[0] = pPed->m_fHealth; // correct cast float to int
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_CAR_HEALTH:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ ScriptParams[0] = pVehicle->m_fHealth; // correct cast float to int
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CAR_ARMED_WITH_BOMB:
+ {
+ CollectParameters(&m_nIp, 2);
+ CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pCar);
+ script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);
+ UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); //TODO: enum
+ return 0;
+ }
+ case COMMAND_CHANGE_CAR_COLOUR:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ if (ScriptParams[1] >= 256 || ScriptParams[2] >= 256)
+ debug("CHANGE_CAR_COLOUR - Colours must be less than %d", 256);
+ pVehicle->m_currentColour1 = ScriptParams[1];
+ pVehicle->m_currentColour2 = ScriptParams[2];
+ return 0;
+ }
+ case COMMAND_SWITCH_PED_ROADS_ON:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false);
+ return 0;
+ }
+ case COMMAND_SWITCH_PED_ROADS_OFF:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true);
+ return 0;
+ }
+ case COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pSourcePed);
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTargetPed);
+ pSourcePed->SetLookFlag(pTargetPed, true);
+ pSourcePed->SetLookTimer(60000);
+ return 0;
+ }
+ case COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pSourcePed);
+ CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed;
+ script_assert(pTargetPed);
+ pSourcePed->SetLookFlag(pTargetPed, true);
+ pSourcePed->SetLookTimer(60000);
+ return 0;
+ }
+ case COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pSourcePed);
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTargetPed);
+ pSourcePed->SetLookFlag(pTargetPed, true);
+ pSourcePed->SetLookTimer(60000);
+ return 0;
+ }
+ case COMMAND_STOP_CHAR_LOOKING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pSourcePed);
+ pSourcePed->ClearLookFlag();
+ pSourcePed->bKeepTryingToLook = false;
+ if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)
+ pSourcePed->RestorePreviousState();
+ return 0;
+ }
+ case COMMAND_STOP_PLAYER_LOOKING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pSourcePed);
+ pSourcePed->ClearLookFlag();
+ pSourcePed->bKeepTryingToLook = false;
+ if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)
+ pSourcePed->RestorePreviousState();
+ return 0;
+ }
+ case COMMAND_SWITCH_HELICOPTER:
+ CollectParameters(&m_nIp, 1);
+ CHeli::ActivateHeli(ScriptParams[0] != 0);
+ return 0;
+
+ //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_CAR_MODEL:
+ CollectParameters(&m_nIp, 2);
+ CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_SET_GANG_WEAPONS:
+ CollectParameters(&m_nIp, 3);
+ CGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]);
+ return 0;
+ case COMMAND_SET_CHAR_OBJ_RUN_TO_AREA:
+ {
+ CollectParameters(&m_nIp, 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ float infX = *(float*)&ScriptParams[1];
+ float infY = *(float*)&ScriptParams[2];
+ float supX = *(float*)&ScriptParams[3];
+ float supY = *(float*)&ScriptParams[4];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[1];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[2];
+ }
+ CVector pos;
+ pos.x = (infX + supX) / 2;
+ pos.y = (infY + supY) / 2;
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = Max(pos.x - infX, pos.y - infY);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_RUN_TO_COORD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector pos;
+ pos.x = *(float*)&ScriptParams[1];
+ pos.y = *(float*)&ScriptParams[2];
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ bool isTouching = false;
+ if (pPed->bInVehicle)
+ isTouching = false;
+ else if (pPed->GetHasCollidedWith(pObject))
+ isTouching = true;
+ UpdateCompareFlag(isTouching);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ bool isTouching = false;
+ if (pPed->InVehicle())
+ isTouching = false;
+ else if (pPed->GetHasCollidedWith(pObject))
+ isTouching = true;
+ UpdateCompareFlag(isTouching);
+ return 0;
+ }
+ case COMMAND_LOAD_SPECIAL_CHARACTER:
+ {
+ CollectParameters(&m_nIp, 1);
+ char name[16];
+ strncpy(name, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ name[i] = tolower(name[i]);
+ CStreaming::RequestSpecialChar(ScriptParams[0] - 1, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ return 0;
+ }
+ case COMMAND_HAS_SPECIAL_CHARACTER_LOADED:
+ {
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1));
+ return 0;
+ }
+ case COMMAND_FLASH_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bHasBlip = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_FLASH_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bHasBlip = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_FLASH_OBJECT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->bHasBlip = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_REMOTE_MODE:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode());
+ return 0;
+ case COMMAND_ARM_CAR_WITH_BOMB:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ ((CAutomobile*)pVehicle)->m_bombType = ScriptParams[1];
+ ((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed();
+ return 0;
+ }
+ case COMMAND_SET_CHAR_PERSONALITY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->SetPedStats((ePedStats)ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_SET_CUTSCENE_OFFSET:
+ CollectParameters(&m_nIp, 3);
+ CCutsceneMgr::SetCutsceneOffset(*(CVector*)&ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_ANIM_GROUP_FOR_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_animGroup = (AssocGroupId)ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_ANIM_GROUP_FOR_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->m_animGroup = (AssocGroupId)ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_REQUEST_MODEL:
+ {
+ CollectParameters(&m_nIp, 1);
+ int model = ScriptParams[0];
+ if (model < 0)
+ model = CTheScripts::UsedObjectArray[-model].index;
+ CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_NOFADE | STREAMFLAGS_SCRIPTOWNED);
+ return 0;
+ }
+ case COMMAND_HAS_MODEL_LOADED:
+ {
+ CollectParameters(&m_nIp, 1);
+ int model = ScriptParams[0];
+ if (model < 0)
+ model = CTheScripts::UsedObjectArray[-model].index;
+ UpdateCompareFlag(CStreaming::HasModelLoaded(model));
+ return 0;
+ }
+ case COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED:
+ {
+ CollectParameters(&m_nIp, 1);
+ int model = ScriptParams[0];
+ if (model < 0)
+ model = CTheScripts::UsedObjectArray[-model].index;
+ CStreaming::SetMissionDoesntRequireModel(model);
+ return 0;
+ }
+ case COMMAND_GRAB_PHONE:
+ {
+ CollectParameters(&m_nIp, 2);
+ ScriptParams[0] = gPhoneInfo.GrabPhone(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_REPEATED_PHONE_MESSAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text, nil, nil, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_SET_PHONE_MESSAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text, nil, nil, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_HAS_PHONE_DISPLAYED_MESSAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0]));
+ return 0;
+ }
+ case COMMAND_TURN_PHONE_OFF:
+ {
+ CollectParameters(&m_nIp, 1);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], nil, nil, nil, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_DRAW_CORONA:
+ {
+ CollectParameters(&m_nIp, 9);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8],
+ 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f);
+ return 0;
+ }
+ case COMMAND_DRAW_LIGHT:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ CVector unused(0.0f, 0.0f, 0.0f);
+ CPointLights::AddLight(0, *(CVector*)&ScriptParams[0], CVector(0.0f, 0.0f, 0.0f), 12.0f,
+ 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_CLOCK:
+ CClock::StoreClock();
+ return 0;
+ case COMMAND_RESTORE_CLOCK:
+ CClock::RestoreClock();
+ return 0;
+ case COMMAND_RESTART_CRITICAL_MISSION:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]);
+ if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING)
+ printf("RESTART_CRITICAL_MISSION - Player state is not PLAYING\n");
+ CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission();
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_PLAYING:
+ {
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_PLAYING);
+ return 0;
+ }
+ //case COMMAND_SET_COLL_OBJ_NO_OBJ:
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands600To699(int32 command)
+{
+ switch (command){
+ /* Collective commands are not implemented until LCS.
+ case COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE:
+ case COMMAND_SET_COLL_OBJ_GUARD_SPOT:
+ case COMMAND_SET_COLL_OBJ_GUARD_AREA:
+ case COMMAND_SET_COLL_OBJ_WAIT_IN_CAR:
+ case COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS:
+ case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS:
+ case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:
+ case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:
+ case COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_LEAVE_CAR:
+ case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER:
+ case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER:
+ case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR:
+ case COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
+ case COMMAND_SET_COLL_OBJ_DESTROY_OBJECT:
+ case COMMAND_SET_COLL_OBJ_DESTROY_CAR:
+ case COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR:
+ case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+ case COMMAND_SET_COLL_OBJ_GUARD_ATTACK:
+ case COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE:
+ case COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT:
+ case COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR:
+ case COMMAND_SET_COLL_OBJ_RUN_TO_AREA:
+ case COMMAND_SET_COLL_OBJ_RUN_TO_COORD:
+ case COMMAND_ADD_PEDS_IN_AREA_TO_COLL:
+ case COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL:
+ case COMMAND_CLEAR_COLL:
+ case COMMAND_IS_COLL_IN_CARS:
+ case COMMAND_LOCATE_COLL_ANY_MEANS_2D:
+ case COMMAND_LOCATE_COLL_ON_FOOT_2D:
+ case COMMAND_LOCATE_COLL_IN_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:
+ case COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:
+ case COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:
+ case COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D:
+ case COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D:
+ case COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D:
+ case COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D:
+ case COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D:
+ case COMMAND_LOCATE_COLL_IN_CAR_CAR_2D:
+ case COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D:
+ case COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D:
+ case COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D:
+ case COMMAND_IS_COLL_IN_AREA_2D:
+ case COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_COLL_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_COLL_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:
+ case COMMAND_GET_NUMBER_OF_PEDS_IN_COLL:
+ */
+ case COMMAND_SET_CHAR_HEED_THREATS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bRespondsToThreats = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_HEED_THREATS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->bRespondsToThreats = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_GET_CONTROLLER_MODE:
+#if defined(GTA_PC) && !defined(DETECT_PAD_INPUT_SWITCH)
+ ScriptParams[0] = 0;
+#else
+ ScriptParams[0] = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
+#endif
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SET_CAN_RESPRAY_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0);
+ return 0;
+ }
+ case COMMAND_IS_TAXI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ int mi = pVehicle->GetModelIndex();
+ UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE);
+ return 0;
+ }
+ case COMMAND_UNLOAD_SPECIAL_CHARACTER:
+ CollectParameters(&m_nIp, 1);
+ CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1);
+ return 0;
+ case COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER:
+ CDarkel::ResetModelsKilledByPlayer();
+ return 0;
+ case COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER:
+ CollectParameters(&m_nIp, 1);
+ ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_ACTIVATE_GARAGE:
+ CollectParameters(&m_nIp, 1);
+ CGarages::ActivateGarage(ScriptParams[0]);
+ return 0;
+ case COMMAND_SWITCH_TAXI_TIMER:
+ {
+ CollectParameters(&m_nIp, 1);
+ if (ScriptParams[0] != 0){
+ CWorld::Players[CWorld::PlayerInFocus].m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
+ CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = true;
+ }else{
+ CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = false;
+ }
+ return 0;
+ }
+ case COMMAND_CREATE_OBJECT_NO_OFFSET:
+ {
+ CollectParameters(&m_nIp, 4);
+ int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;
+ CObject* pObj = new CObject(mi, false);
+; pObj->ObjectCreatedBy = MISSION_OBJECT;
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pObj->SetPosition(pos);
+ pObj->SetOrientation(0.0f, 0.0f, 0.0f);
+ pObj->GetMatrix().UpdateRW();
+ pObj->UpdateRwFrame();
+ CTheScripts::ClearSpaceForMissionEntity(pos, pObj);
+ CWorld::Add(pObj);
+ ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
+ return 0;
+ }
+ case COMMAND_IS_BOAT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS:
+ {
+ CollectParameters(&m_nIp, 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ float infX = *(float*)&ScriptParams[1];
+ float infY = *(float*)&ScriptParams[2];
+ float supX = *(float*)&ScriptParams[3];
+ float supY = *(float*)&ScriptParams[4];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[1];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[2];
+ }
+ CVector pos;
+ pos.x = (infX + supX) / 2;
+ pos.y = (infY + supY) / 2;
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = Max(pos.x - infX, pos.y - infY);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius);
+ return 0;
+ }
+ //case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS:
+ case COMMAND_IS_PLAYER_STOPPED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
+ UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer));
+ return 0;
+ }
+ case COMMAND_IS_CHAR_STOPPED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(CTheScripts::IsPedStopped(pPed));
+ return 0;
+ }
+ case COMMAND_MESSAGE_WAIT:
+ CollectParameters(&m_nIp, 2);
+ m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0];
+ if (ScriptParams[1] != 0)
+ m_bSkipWakeTime = true;
+ return 1;
+ case COMMAND_ADD_PARTICLE_EFFECT:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);
+ return 0;
+ }
+ case COMMAND_SWITCH_WIDESCREEN:
+ CollectParameters(&m_nIp, 1);
+ if (ScriptParams[0] != 0)
+ TheCamera.SetWideScreenOn();
+ else
+ TheCamera.SetWideScreenOff();
+ return 0;
+ case COMMAND_ADD_SPRITE_BLIP_FOR_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[1]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_SPRITE_BLIP_FOR_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[1]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[1]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_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::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_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::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_PROOFS:
+ {
+ CollectParameters(&m_nIp, 6);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bBulletProof = (ScriptParams[1] != 0);
+ pPed->bFireProof = (ScriptParams[2] != 0);
+ pPed->bExplosionProof = (ScriptParams[3] != 0);
+ pPed->bCollisionProof = (ScriptParams[4] != 0);
+ pPed->bMeleeProof = (ScriptParams[5] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CAR_PROOFS:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bBulletProof = (ScriptParams[1] != 0);
+ pVehicle->bFireProof = (ScriptParams[2] != 0);
+ pVehicle->bExplosionProof = (ScriptParams[3] != 0);
+ pVehicle->bCollisionProof = (ScriptParams[4] != 0);
+ pVehicle->bMeleeProof = (ScriptParams[5] != 0);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
+ PlayerInAngledAreaCheckCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_DEACTIVATE_GARAGE:
+ CollectParameters(&m_nIp, 1);
+ CGarages::DeActivateGarage(ScriptParams[0]);
+ return 0;
+ case COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE:
+ CollectParameters(&m_nIp, 1);
+ ScriptParams[0] = CGarages::QueryCarsCollected(ScriptParams[0]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE:
+ CollectParameters(&m_nIp, 2);
+ UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1));
+ return 0;
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands700To799(int32 command)
+{
+ switch (command){
+ case COMMAND_SET_SWAT_REQUIRED:
+ CollectParameters(&m_nIp, 1);
+ FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0);
+ return 0;
+ case COMMAND_SET_FBI_REQUIRED:
+ CollectParameters(&m_nIp, 1);
+ FindPlayerPed()->m_pWanted->m_bFbiRequired = (ScriptParams[0] != 0);
+ return 0;
+ case COMMAND_SET_ARMY_REQUIRED:
+ CollectParameters(&m_nIp, 1);
+ FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0);
+ return 0;
+ case COMMAND_IS_CAR_IN_WATER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(pVehicle && pVehicle->bIsInWater);
+ return 0;
+ }
+ case COMMAND_GET_CLOSEST_CHAR_NODE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)];
+ *(CVector*)&ScriptParams[0] = pNode->GetPosition();
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_GET_CLOSEST_CAR_NODE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)];
+ *(CVector*)&ScriptParams[0] = pNode->GetPosition();
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_CAR_GOTO_COORDINATES_ACCURATE:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
+ if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false))
+ pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
+ else
+ pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE;
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ pVehicle->bEngineOn = true;
+ pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
+ pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
+ return 0;
+ }
+ case COMMAND_START_PACMAN_RACE:
+ CollectParameters(&m_nIp, 1);
+ CPacManPickups::StartPacManRace(ScriptParams[0]);
+ return 0;
+ case COMMAND_START_PACMAN_RECORD:
+ CPacManPickups::StartPacManRecord();
+ return 0;
+ case COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN:
+ ScriptParams[0] = CPacManPickups::QueryPowerPillsEatenInRace();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_CLEAR_PACMAN:
+ CPacManPickups::CleanUpPacManStuff();
+ return 0;
+ case COMMAND_START_PACMAN_SCRAMBLE:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]);
+ return 0;
+ }
+ case COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED:
+ ScriptParams[0] = CPacManPickups::QueryPowerPillsCarriedByPlayer();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED:
+ CPacManPickups::ResetPowerPillsCarriedByPlayer();
+ return 0;
+ case COMMAND_IS_CAR_ON_SCREEN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(TheCamera.IsSphereVisible(pVehicle->GetBoundCentre(), pVehicle->GetBoundRadius()));
+ return 0;
+ }
+ case COMMAND_IS_CHAR_ON_SCREEN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(TheCamera.IsSphereVisible(pPed->GetBoundCentre(), pPed->GetBoundRadius()));
+ return 0;
+ }
+ case COMMAND_IS_OBJECT_ON_SCREEN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius()));
+ return 0;
+ }
+ case COMMAND_GOSUB_FILE:
+ {
+ CollectParameters(&m_nIp, 2);
+ script_assert(m_nStackPointer < MAX_STACK_DEPTH);
+ m_anStack[m_nStackPointer++] = m_nIp;
+ SetIP(ScriptParams[0]);
+ // ScriptParams[1] == filename
+ return 0;
+ }
+ case COMMAND_GET_GROUND_Z_FOR_3D_COORD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ bool success;
+ *(float*)&ScriptParams[0] = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &success);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_START_SCRIPT_FIRE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ ScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(gFireManager.IsScriptFireExtinguish(ScriptParams[0]));
+ return 0;
+ case COMMAND_REMOVE_SCRIPT_FIRE:
+ CollectParameters(&m_nIp, 1);
+ gFireManager.RemoveScriptFire(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_COMEDY_CONTROLS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bComedyControls = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_BOAT_GOTO_COORDS:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+ CBoat* pBoat = (CBoat*)pVehicle;
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false);
+ pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS;
+ pBoat->AutoPilot.m_vecDestinationCoors = pos;
+ pBoat->SetStatus(STATUS_PHYSICS);
+ pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed);
+ pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
+ return 0;
+ }
+ case COMMAND_BOAT_STOP:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+ CBoat* pBoat = (CBoat*)pVehicle;
+ pBoat->AutoPilot.m_nCarMission = MISSION_NONE;
+ pBoat->SetStatus(STATUS_PHYSICS);
+ pBoat->bEngineOn = false;
+ pBoat->AutoPilot.m_nCruiseSpeed = 0;
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_SHOOTING_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 6);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ float x1 = *(float*)&ScriptParams[1];
+ float y1 = *(float*)&ScriptParams[2];
+ float x2 = *(float*)&ScriptParams[3];
+ float y2 = *(float*)&ScriptParams[4];
+ UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
+ if (ScriptParams[5])
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag)
+ CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_SHOOTING_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 6);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ float x1 = *(float*)&ScriptParams[1];
+ float y1 = *(float*)&ScriptParams[2];
+ float x2 = *(float*)&ScriptParams[3];
+ float y2 = *(float*)&ScriptParams[4];
+ UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
+ if (ScriptParams[5])
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag)
+ CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
+ return 0;
+ }
+ case COMMAND_IS_CURRENT_PLAYER_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
+ return 0;
+ }
+ case COMMAND_IS_CURRENT_CHAR_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
+ return 0;
+ }
+ case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN:
+ CPacManPickups::ResetPowerPillsEatenInRace();
+ return 0;
+ case COMMAND_ADD_POWER_PILL:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CPacManPickups::GenerateOnePMPickUp(pos);
+ return 0;
+ }
+ case COMMAND_SET_BOAT_CRUISE_SPEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+ CBoat* pBoat = (CBoat*)pVehicle;
+ pBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_CHAR_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 4);
+ int ped_handle = -1;
+ CVector pos = FindPlayerCoors();
+ float x1 = *(float*)&ScriptParams[0];
+ float y1 = *(float*)&ScriptParams[1];
+ float x2 = *(float*)&ScriptParams[2];
+ float y2 = *(float*)&ScriptParams[3];
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i && ped_handle == -1){
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+ continue;
+ if (pPed->CharCreatedBy != RANDOM_CHAR)
+ continue;
+ if (!pPed->IsPedInControl())
+ continue;
+ if (pPed->bRemoveFromWorld)
+ continue;
+ if (pPed->bFadeOut)
+ 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)
+ continue;
+ if (!pPed->IsWithinArea(x1, y1, x2, y2))
+ continue;
+ if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ continue;
+ if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ continue;
+ ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+ CTheScripts::LastRandomPedId = ped_handle;
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ ++CPopulation::ms_nTotalMissionPeds;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ }
+ ScriptParams[0] = ped_handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_CHAR_IN_ZONE:
+ {
+ char zone[KEY_LENGTH_IN_SCRIPT];
+ strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ if (nZone != -1)
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CZone* pZone = CTheZones::GetZone(nZone);
+ int ped_handle = -1;
+ CVector pos = FindPlayerCoors();
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i && ped_handle == -1) {
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+ continue;
+ if (pPed->CharCreatedBy != RANDOM_CHAR)
+ continue;
+ if (!pPed->IsPedInControl())
+ continue;
+ if (pPed->bRemoveFromWorld)
+ continue;
+ if (pPed->bFadeOut)
+ 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)
+ continue;
+ if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))
+ continue;
+ if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ continue;
+ if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ continue;
+ ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+ CTheScripts::LastRandomPedId = ped_handle;
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ ++CPopulation::ms_nTotalMissionPeds;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ }
+ ScriptParams[0] = ped_handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_TAXI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->IsTaxi());
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_SHOOTING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bIsShooting);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_SHOOTING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bIsShooting);
+ return 0;
+ }
+ case COMMAND_CREATE_MONEY_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_MONEY, PICKUP_MONEY, ScriptParams[3]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_ACCURACY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_wepAccuracy = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_CAR_SPEED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ *(float*)&ScriptParams[0] = pVehicle->GetSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_LOAD_CUTSCENE:
+ {
+ char name[KEY_LENGTH_IN_SCRIPT];
+ strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CCutsceneMgr::LoadCutsceneData(name);
+ return 0;
+ }
+ case COMMAND_CREATE_CUTSCENE_OBJECT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CCutsceneObject* pCutObj = CCutsceneMgr::CreateCutsceneObject(ScriptParams[0]);
+ ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutObj);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CUTSCENE_ANIM:
+ {
+ CollectParameters(&m_nIp, 1);
+ char name[KEY_LENGTH_IN_SCRIPT];
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CCutsceneMgr::SetCutsceneAnim(name, pObject);
+ return 0;
+ }
+ case COMMAND_START_CUTSCENE:
+ CCutsceneMgr::ms_cutsceneLoadStatus = 1;
+ return 0;
+ case COMMAND_GET_CUTSCENE_TIME:
+ ScriptParams[0] = CCutsceneMgr::GetCutsceneTimeInMilleseconds();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_HAS_CUTSCENE_FINISHED:
+ UpdateCompareFlag(CCutsceneMgr::HasCutsceneFinished());
+ return 0;
+ case COMMAND_CLEAR_CUTSCENE:
+ CCutsceneMgr::DeleteCutsceneData();
+ return 0;
+ case COMMAND_RESTORE_CAMERA_JUMPCUT:
+ TheCamera.RestoreWithJumpCut();
+ return 0;
+ case COMMAND_CREATE_COLLECTABLE1:
+ {
+ 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;
+ CPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0);
+ return 0;
+ }
+ case COMMAND_SET_COLLECTABLE1_TOTAL:
+ CollectParameters(&m_nIp, 1);
+ CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0];
+ return 0;
+ case COMMAND_IS_PROJECTILE_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, false));
+ if (CTheScripts::DbgFlag)
+ CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+ return 0;
+ }
+ case COMMAND_DESTROY_PROJECTILES_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, true));
+ if (CTheScripts::DbgFlag)
+ CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+ return 0;
+ }
+ case COMMAND_DROP_MINE:
+ {
+ 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;
+ CPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0);
+ return 0;
+ }
+ case COMMAND_DROP_NAUTICAL_MINE:
+ {
+ 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;
+ CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_MODEL:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(ScriptParams[1] == pPed->GetModelIndex());
+ return 0;
+ }
+ case COMMAND_LOAD_SPECIAL_MODEL:
+ {
+ CollectParameters(&m_nIp, 1);
+ char name[KEY_LENGTH_IN_SCRIPT];
+ strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ name[i] = tolower(name[i]);
+ CStreaming::RequestSpecialModel(ScriptParams[0], name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ return 0;
+ }
+ case COMMAND_CREATE_CUTSCENE_HEAD:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]);
+ ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CUTSCENE_HEAD_ANIM:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_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();
+ return 0;
+ }
+ case COMMAND_SIN:
+ CollectParameters(&m_nIp, 1);
+ *(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0]));
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_COS:
+ CollectParameters(&m_nIp, 1);
+ *(float*)&ScriptParams[0] = Cos(DEGTORAD(*(float*)&ScriptParams[0]));
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_GET_CAR_FORWARD_X:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ float forwardX = pVehicle->GetForward().x / pVehicle->GetForward().Magnitude2D();
+ *(float*)&ScriptParams[0] = forwardX;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_CAR_FORWARD_Y:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ float forwardY = pVehicle->GetForward().y / pVehicle->GetForward().Magnitude2D();
+ *(float*)&ScriptParams[0] = forwardY;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CHANGE_GARAGE_TYPE:
+ CollectParameters(&m_nIp, 2);
+ CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], 0);
+ return 0;
+ case COMMAND_ACTIVATE_CRUSHER_CRANE:
+ {
+ CollectParameters(&m_nIp, 10);
+ float infX = *(float*)&ScriptParams[2];
+ float infY = *(float*)&ScriptParams[3];
+ float supX = *(float*)&ScriptParams[4];
+ float supY = *(float*)&ScriptParams[5];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[4];
+ supX = *(float*)&ScriptParams[2];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[5];
+ supY = *(float*)&ScriptParams[3];
+ }
+ CCranes::ActivateCrane(infX, supX, infY, supY,
+ *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
+ DEGTORAD(*(float*)&ScriptParams[9]), true, false,
+ *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_2_NUMBERS:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 4);
+ CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_2_NUMBERS_NOW:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 4);
+ CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_2_NUMBERS_SOON:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 4);
+ CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_3_NUMBERS:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 5);
+ CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_3_NUMBERS_NOW:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 5);
+ CMessages::AddMessageJumpQWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_3_NUMBERS_SOON:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 5);
+ CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_4_NUMBERS:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 6);
+ CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_4_NUMBERS_NOW:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 6);
+ CMessages::AddMessageJumpQWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_4_NUMBERS_SOON:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 6);
+ CMessages::AddMessageSoonWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_5_NUMBERS:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 7);
+ CMessages::AddMessageWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_5_NUMBERS_NOW:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 7);
+ CMessages::AddMessageJumpQWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_5_NUMBERS_SOON:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 7);
+ CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_6_NUMBERS:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 8);
+ CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_6_NUMBERS_NOW:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 8);
+ CMessages::AddMessageJumpQWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_6_NUMBERS_SOON:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 8);
+ CMessages::AddMessageSoonWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, pTargetPed);
+ pPed->SetFormation((eFormation)ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_PLAYER_MADE_PROGRESS:
+ CollectParameters(&m_nIp, 1);
+ CStats::ProgressMade += ScriptParams[0];
+ return 0;
+ case COMMAND_SET_PROGRESS_TOTAL:
+ CollectParameters(&m_nIp, 1);
+ CStats::TotalProgressInGame = ScriptParams[0];
+ return 0;
+ case COMMAND_REGISTER_JUMP_DISTANCE:
+ CollectParameters(&m_nIp, 1);
+ CStats::MaximumJumpDistance = Max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_JUMP_HEIGHT:
+ CollectParameters(&m_nIp, 1);
+ CStats::MaximumJumpHeight = Max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_JUMP_FLIPS:
+ CollectParameters(&m_nIp, 1);
+ CStats::MaximumJumpFlips = Max(CStats::MaximumJumpFlips, ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_JUMP_SPINS:
+ CollectParameters(&m_nIp, 1);
+ CStats::MaximumJumpSpins = Max(CStats::MaximumJumpSpins, ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_JUMP_STUNT:
+ CollectParameters(&m_nIp, 1);
+ CStats::BestStuntJump = Max(CStats::BestStuntJump, ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_UNIQUE_JUMP_FOUND:
+ ++CStats::NumberOfUniqueJumpsFound;
+ return 0;
+ case COMMAND_SET_UNIQUE_JUMPS_TOTAL:
+ CollectParameters(&m_nIp, 1);
+ CStats::TotalNumberOfUniqueJumps = ScriptParams[0];
+ return 0;
+ case COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI:
+ ++CStats::PassengersDroppedOffWithTaxi;
+ return 0;
+ case COMMAND_REGISTER_MONEY_MADE_TAXI:
+ CollectParameters(&m_nIp, 1);
+ CStats::MoneyMadeWithTaxi += ScriptParams[0];
+ return 0;
+ case COMMAND_REGISTER_MISSION_GIVEN:
+ ++CStats::MissionsGiven;
+ return 0;
+ case COMMAND_REGISTER_MISSION_PASSED:
+ {
+ char name[KEY_LENGTH_IN_SCRIPT];
+ strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ strncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT);
+ ++CStats::MissionsPassed;
+ CStats::CheckPointReachedSuccessfully();
+ return 0;
+ }
+ case COMMAND_SET_CHAR_RUNNING:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bIsRunning = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_REMOVE_ALL_SCRIPT_FIRES:
+ gFireManager.RemoveAllScriptFires();
+ return 0;
+ case COMMAND_IS_FIRST_CAR_COLOUR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->m_currentColour1 == ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_IS_SECOND_CAR_COLOUR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ if (!pPed)
+ printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n");
+ UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ if (!pVehicle)
+ printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n");
+ UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_CHARS_GROUP:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pPed);
+ script_assert(pLeader);
+ UpdateCompareFlag(pPed->m_leader == pLeader);
+ return 0;
+ }
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp
new file mode 100644
index 00000000..78da2d96
--- /dev/null
+++ b/src/control/Script4.cpp
@@ -0,0 +1,2027 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "AnimBlendAssociation.h"
+#include "BulletInfo.h"
+#include "CarAI.h"
+#include "CarCtrl.h"
+#include "CivilianPed.h"
+#include "Cranes.h"
+#include "DMAudio.h"
+#include "Darkel.h"
+#include "Explosion.h"
+#include "Fire.h"
+#include "Frontend.h"
+#include "Garages.h"
+#include "General.h"
+#include "Heli.h"
+#include "Hud.h"
+#include "Messages.h"
+#include "ParticleObject.h"
+#include "PedRoutes.h"
+#include "Phones.h"
+#include "Pickups.h"
+#include "Plane.h"
+#include "Pools.h"
+#include "Population.h"
+#include "Radar.h"
+#include "Record.h"
+#include "RpAnimBlend.h"
+#include "Rubbish.h"
+#include "SpecialFX.h"
+#include "Stats.h"
+#include "Streaming.h"
+#include "TxdStore.h"
+#include "User.h"
+#include "WaterLevel.h"
+#include "World.h"
+#include "Zones.h"
+
+int8 CRunningScript::ProcessCommands800To899(int32 command)
+{
+ CMatrix tmp_matrix;
+ switch (command) {
+ case COMMAND_IS_CHAR_IN_PLAYERS_GROUP:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed;
+ script_assert(pPed);
+ script_assert(pLeader);
+ UpdateCompareFlag(pPed->m_leader == pLeader);
+ return 0;
+ }
+ case COMMAND_EXPLODE_CHAR_HEAD:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (pPed->m_nPedState == PED_DRIVING) {
+ pPed->SetDead();
+ if (!pPed->IsPlayer())
+ pPed->FlagToDestroyWhenNextProcessed();
+ }
+ else if (CGame::nastyGame && pPed->IsPedInControl()) {
+ pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true);
+ }
+ else {
+ pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ }
+ return 0;
+ }
+ case COMMAND_EXPLODE_PLAYER_HEAD:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ if (CGame::nastyGame) {
+ pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true);
+ }
+ else {
+ pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ }
+ return 0;
+ }
+ case COMMAND_ANCHOR_BOAT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CBoat* pBoat = (CBoat*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pBoat && pBoat->m_vehType == VEHICLE_TYPE_BOAT);
+ pBoat->m_bIsAnchored = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_ZONE_GROUP:
+ {
+ char zone[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CollectParameters(&m_nIp, 2);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ if (zone_id < 0) {
+ printf("Couldn't find zone - %s\n", zone);
+ return 0;
+ }
+ CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_START_CAR_FIRE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ ScriptParams[0] = gFireManager.StartScriptFire(pVehicle->GetPosition(), pVehicle, 0.8f, 1);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_START_CHAR_FIRE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ ScriptParams[0] = gFireManager.StartScriptFire(pPed->GetPosition(), pPed, 0.8f, 1);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 5);
+ int handle = -1;
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ float infX = *(float*)&ScriptParams[0];
+ float infY = *(float*)&ScriptParams[1];
+ float supX = *(float*)&ScriptParams[2];
+ float supY = *(float*)&ScriptParams[3];
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)
+ continue;
+ if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
+ continue;
+ if (!pVehicle->IsWithinArea(infX, infY, supX, supY))
+ continue;
+ handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ pVehicle->VehicleCreatedBy = MISSION_VEHICLE;
+ ++CCarCtrl::NumMissionCars;
+ --CCarCtrl::NumRandomCars;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+ }
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:
+ {
+ char zone[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ if (zone_id != -1)
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CZone* pZone = CTheZones::GetZone(zone_id);
+ CollectParameters(&m_nIp, 1);
+ int handle = -1;
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (ScriptParams[0] != pVehicle->GetModelIndex() && ScriptParams[0] >= 0)
+ continue;
+ if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
+ continue;
+ if (!CTheZones::PointLiesWithinZone(&pVehicle->GetPosition(), pZone))
+ continue;
+ handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ pVehicle->VehicleCreatedBy = MISSION_VEHICLE;
+ ++CCarCtrl::NumMissionCars;
+ --CCarCtrl::NumRandomCars;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+ }
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_HAS_RESPRAY_HAPPENED:
+ {
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CGarages::HasResprayHappened(ScriptParams[0]));
+ return 0;
+ }
+ case COMMAND_SET_CAMERA_ZOOM:
+ {
+ CollectParameters(&m_nIp, 1);
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED)
+ TheCamera.SetZoomValueFollowPedScript(ScriptParams[0]);
+ else if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING)
+ TheCamera.SetZoomValueCamStringScript(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_CREATE_PICKUP_WITH_AMMO:
+ {
+ CollectParameters(&m_nIp, 6);
+ int16 model = ScriptParams[0];
+ if (model < 0)
+ model = CTheScripts::UsedObjectArray[-model].index;
+ CVector pos = *(CVector*)&ScriptParams[3];
+ 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, model, ScriptParams[1], ScriptParams[2]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CAR_RAM_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CCarAI::TellCarToRamOtherCar(pVehicle, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CAR_BLOCK_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CCarAI::TellCarToBlockOtherCar(pVehicle, pTarget);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_CATCH_TRAIN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_CATCH_TRAIN);
+ return 0;
+ }
+ //case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
+ case COMMAND_SET_PLAYER_NEVER_GETS_TIRED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
+ pPlayer->m_bInfiniteSprint = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_FAST_RELOAD:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
+ pPlayer->m_bFastReload = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_BLEEDING:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bPedIsBleeding = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CAR_FUNNY_SUSPENSION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ // no action
+ return 0;
+ }
+ case COMMAND_SET_CAR_BIG_WHEELS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ pCar->bBigWheels = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_FREE_RESPRAYS:
+ CollectParameters(&m_nIp, 1);
+ CGarages::SetFreeResprays(ScriptParams[0] != 0);
+ return 0;
+ case COMMAND_SET_PLAYER_VISIBLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->bIsVisible = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_VISIBLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bIsVisible = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_SET_CAR_VISIBLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bIsVisible = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_IS_AREA_OCCUPIED:
+ {
+ CollectParameters(&m_nIp, 11);
+ 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];
+ }
+ int16 total;
+ CWorld::FindObjectsIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil,
+ !!ScriptParams[6], !!ScriptParams[7], !!ScriptParams[8], !!ScriptParams[9], !!ScriptParams[10]);
+ UpdateCompareFlag(total > 0);
+ return 0;
+ }
+ case COMMAND_START_DRUG_RUN:
+ CPlane::CreateIncomingCesna();
+ return 0;
+ case COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED:
+ UpdateCompareFlag(CPlane::HasCesnaLanded());
+ return 0;
+ case COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN:
+ UpdateCompareFlag(CPlane::HasCesnaBeenDestroyed());
+ return 0;
+ case COMMAND_SAVE_PLAYER_FROM_FIRES:
+ CollectParameters(&m_nIp, 1);
+ gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f);
+ return 0;
+ case COMMAND_DISPLAY_TEXT:
+ {
+ CollectParameters(&m_nIp, 2);
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
+ uint16 len = CMessages::GetWideStringLength(text);
+ for (uint16 i = 0; i < len; i++)
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = text[i];
+ for (uint16 i = len; i < SCRIPT_TEXT_MAX_LENGTH; i++)
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = 0;
+ ++CTheScripts::NumberOfIntroTextLinesThisFrame;
+ return 0;
+ }
+ case COMMAND_SET_TEXT_SCALE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleX = *(float*)&ScriptParams[0];
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleY = *(float*)&ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_TEXT_COLOUR:
+ {
+ CollectParameters(&m_nIp, 4);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sColor =
+ CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_JUSTIFY:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bJustify = (ScriptParams[0] != 0);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_CENTRE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bCentered = (ScriptParams[0] != 0);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_WRAPX:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_TEXT_CENTRE_SIZE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_TEXT_BACKGROUND:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_BACKGROUND_COLOUR:
+ {
+ CollectParameters(&m_nIp, 4);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sBackgroundColor =
+ CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_PROPORTIONAL:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0);
+ return 0;
+ }
+ case COMMAND_SET_TEXT_FONT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_nFont = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_INDUSTRIAL_PASSED:
+ CStats::IndustrialPassed = true;
+ DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_COMMERCIAL_OPEN);
+ return 0;
+ case COMMAND_COMMERCIAL_PASSED:
+ CStats::CommercialPassed = true;
+ DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_SUBURBAN_OPEN);
+ return 0;
+ case COMMAND_SUBURBAN_PASSED:
+ CStats::SuburbanPassed = true;
+ return 0;
+ case COMMAND_ROTATE_OBJECT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ float heading = LimitAngleOnCircle(
+ RADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y)));
+ float headingTarget = *(float*)&ScriptParams[1];
+#ifdef FIX_BUGS
+ float rotateBy = *(float*)&ScriptParams[2] * CTimer::GetTimeStepFix();
+#else
+ float rotateBy = *(float*)&ScriptParams[2];
+#endif
+ if (headingTarget == heading) { // using direct comparasion here is fine
+ UpdateCompareFlag(true);
+ return 0;
+ }
+ float angleClockwise = LimitAngleOnCircle(headingTarget - heading);
+ float angleCounterclockwise = LimitAngleOnCircle(heading - headingTarget);
+ float newHeading;
+ if (angleClockwise < angleCounterclockwise)
+ newHeading = rotateBy < angleClockwise ? heading + rotateBy : headingTarget;
+ else
+ newHeading = rotateBy < angleCounterclockwise ? heading - rotateBy : headingTarget;
+ bool obstacleInPath = false;
+ if (ScriptParams[3]) {
+ CVector pos = pObject->GetPosition();
+ tmp_matrix.SetRotateZ(DEGTORAD(newHeading));
+ tmp_matrix.GetPosition() += pos;
+ CColModel* pColModel = pObject->GetColModel();
+ CVector cp1 = tmp_matrix * pColModel->boundingBox.min;
+ CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);
+ CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);
+ CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);
+ int16 collisions;
+ CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos,
+ Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))),
+ Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))),
+ Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))),
+ Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))),
+ &collisions, 2, nil, false, true, true, false, false);
+ if (collisions > 0)
+ obstacleInPath = true;
+ }
+ if (obstacleInPath) {
+ UpdateCompareFlag(true);
+ return 0;
+ }
+ pObject->SetHeading(DEGTORAD(newHeading));
+ pObject->GetMatrix().UpdateRW();
+ pObject->UpdateRwFrame();
+ UpdateCompareFlag(newHeading == headingTarget); // using direct comparasion here is fine
+ return 0;
+ }
+ case COMMAND_SLIDE_OBJECT:
+ {
+ CollectParameters(&m_nIp, 8);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CVector pos = pObject->GetPosition();
+ CVector posTarget = *(CVector*)&ScriptParams[1];
+#ifdef FIX_BUGS
+ CVector slideBy = *(CVector*)&ScriptParams[4] * CTimer::GetTimeStepFix();
+#else
+ CVector slideBy = *(CVector*)&ScriptParams[4];
+#endif
+ if (posTarget == pos) { // using direct comparasion here is fine
+ UpdateCompareFlag(true);
+ return 0;
+ }
+ CVector posDiff = pos - posTarget;
+ CVector newPosition;
+ if (posDiff.x < 0)
+ newPosition.x = -posDiff.x < slideBy.x ? posTarget.x : pos.x + slideBy.x;
+ else
+ newPosition.x = posDiff.x < slideBy.x ? posTarget.x : pos.x - slideBy.x;
+ if (posDiff.y < 0)
+ newPosition.y = -posDiff.y < slideBy.y ? posTarget.y : pos.y + slideBy.y;
+ else
+ newPosition.y = posDiff.y < slideBy.y ? posTarget.y : pos.y - slideBy.y;
+ if (posDiff.z < 0)
+ newPosition.z = -posDiff.z < slideBy.z ? posTarget.z : pos.z + slideBy.z;
+ else
+ newPosition.z = posDiff.z < slideBy.z ? posTarget.z : pos.z - slideBy.z;
+ bool obstacleInPath = false;
+ if (ScriptParams[7]) {
+ tmp_matrix = pObject->GetMatrix();
+ tmp_matrix.GetPosition() = newPosition;
+ CColModel* pColModel = pObject->GetColModel();
+ CVector cp1 = tmp_matrix * pColModel->boundingBox.min;
+ CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);
+ CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);
+ CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);
+ int16 collisions;
+ CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition,
+ Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))),
+ Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))),
+ Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))),
+ Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))),
+ &collisions, 2, nil, false, true, true, false, false);
+ if (collisions > 0)
+ obstacleInPath = true;
+ }
+ if (obstacleInPath) {
+ UpdateCompareFlag(true);
+ return 0;
+ }
+ pObject->Teleport(newPosition);
+ UpdateCompareFlag(newPosition == posTarget); // using direct comparasion here is fine
+ return 0;
+ }
+ case COMMAND_REMOVE_CHAR_ELEGANTLY:
+ {
+ CollectParameters(&m_nIp, 1);
+ 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{
+ pPed->CharCreatedBy = RANDOM_CHAR;
+ pPed->bRespondsToThreats = true;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->ClearLeader();
+ --CPopulation::ms_nTotalMissionPeds;
+ pPed->bFadeOut = true;
+ }
+ }
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_IS_NASTY_GAME:
+ UpdateCompareFlag(CGame::nastyGame);
+ return 0;
+ case COMMAND_UNDRESS_CHAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ char name[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, name);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ name[i] = tolower(name[i]);
+ int mi = pPed->GetModelIndex();
+ pPed->DeleteRwObject();
+ if (pPed->IsPlayer())
+ mi = 0;
+ CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CWorld::Remove(pPed);
+ return 0;
+ }
+ case COMMAND_DRESS_CHAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ int mi = pPed->GetModelIndex();
+ pPed->m_modelIndex = -1;
+ pPed->SetModelIndex(mi);
+ CWorld::Add(pPed);
+ return 0;
+ }
+ case COMMAND_START_CHASE_SCENE:
+ CollectParameters(&m_nIp, 1);
+ CTimer::Suspend();
+ CStreaming::DeleteAllRwObjects();
+ CRecordDataForChase::StartChaseScene(*(float*)&ScriptParams[0]);
+ CTimer::Resume();
+ return 0;
+ case COMMAND_STOP_CHASE_SCENE:
+ CRecordDataForChase::CleanUpChaseScene();
+ return 0;
+ case COMMAND_IS_EXPLOSION_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 7);
+ float infX = *(float*)&ScriptParams[1];
+ float infY = *(float*)&ScriptParams[2];
+ float infZ = *(float*)&ScriptParams[3];
+ float supX = *(float*)&ScriptParams[4];
+ float supY = *(float*)&ScriptParams[5];
+ float supZ = *(float*)&ScriptParams[6];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[4];
+ supX = *(float*)&ScriptParams[1];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[5];
+ supY = *(float*)&ScriptParams[2];
+ }
+ if (infZ > supZ) {
+ infZ = *(float*)&ScriptParams[6];
+ supZ = *(float*)&ScriptParams[3];
+ }
+ UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
+ infX, supX, infY, supY, infZ, supZ));
+ return 0;
+ }
+ case COMMAND_IS_EXPLOSION_IN_ZONE:
+ {
+ CollectParameters(&m_nIp, 1);
+ char zone[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ if (zone_id != -1)
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CZone* pZone = CTheZones::GetZone(zone_id);
+ UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
+ pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));
+ return 0;
+ }
+ case COMMAND_START_DRUG_DROP_OFF:
+ CPlane::CreateDropOffCesna();
+ return 0;
+ case COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN:
+ UpdateCompareFlag(CPlane::HasDropOffCesnaBeenShotDown());
+ return 0;
+ case COMMAND_FIND_DROP_OFF_PLANE_COORDINATES:
+ {
+ CVector pos = CPlane::FindDropOffCesnaCoordinates();
+ *(CVector*)&ScriptParams[0] = pos;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ 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);
+ return 0;
+ }
+ case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:
+ {
+ CollectParameters(&m_nIp, 5);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ CVector offset = *(CVector*)&ScriptParams[2];
+ CPhysical::PlacePhysicalRelativeToOtherPhysical(pVehicle, pObject, offset);
+ return 0;
+ }
+ case COMMAND_MAKE_OBJECT_TARGETTABLE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CPlayerPed* pPlayerPed = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ script_assert(pPlayerPed);
+ pPlayerPed->MakeObjectTargettable(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_ADD_ARMOUR_TO_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPlayerPed);
+ pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
+ return 0;
+ }
+ case COMMAND_ADD_ARMOUR_TO_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_fArmour = clamp(pPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
+ return 0;
+ }
+ case COMMAND_OPEN_GARAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CGarages::OpenGarage(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_CLOSE_GARAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CGarages::CloseGarage(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
+ {
+ CollectParameters(&m_nIp, 4);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ if (pPed->bInVehicle){
+ if (pPed->m_pMyVehicle->bIsBus)
+ pPed->bRenderPedInCar = true;
+ if (pPed->m_pMyVehicle->pDriver == pPed){
+ pPed->m_pMyVehicle->RemoveDriver();
+ pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ pPed->m_pMyVehicle->bEngineOn = false;
+ pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ }else{
+ pPed->m_pMyVehicle->RemovePassenger(pPed);
+ }
+ pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f);
+ pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f);
+ }
+ pPed->bInVehicle = false;
+ pPed->m_pMyVehicle = nil;
+ pPed->SetPedState(PED_IDLE);
+ 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->RemoveInCarAnims();
+ if (pPed->m_pVehicleAnim)
+ pPed->m_pVehicleAnim->blendDelta = -1000.0f;
+ pPed->m_pVehicleAnim = nil;
+ pPed->RestartNonPartialAnims();
+ pPed->SetMoveState(PEDMOVE_NONE);
+ CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel();
+ pPed->Teleport(pos);
+ CTheScripts::ClearSpaceForMissionEntity(pos, pPed);
+ return 0;
+ }
+ case COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float range = *(float*)&ScriptParams[3];
+ int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];
+ int16 total;
+ CEntity* apEntities[16];
+ CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true);
+ if (total == 0)
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities);
+ if (total == 0)
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities);
+ CEntity* pClosestEntity = nil;
+ float min_dist = 2.0f * range;
+ for (int i = 0; i < total; i++) {
+ float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
+ if (dist < min_dist) {
+ min_dist = dist;
+ pClosestEntity = apEntities[i];
+ }
+ }
+ if (pClosestEntity) {
+ pClosestEntity->bIsVisible = (ScriptParams[5] != 0);
+ CTheScripts::AddToInvisibilitySwapArray(pClosestEntity, ScriptParams[5] != 0);
+ }
+ return 0;
+ }
+ case COMMAND_HAS_CHAR_SPOTTED_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget));
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_HAIL_TAXI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_HAIL_TAXI);
+ return 0;
+ }
+ case COMMAND_HAS_OBJECT_BEEN_DAMAGED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ UpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible);
+ return 0;
+ }
+ case COMMAND_START_KILL_FRENZY_HEADSHOT:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 8);
+ CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],
+ ScriptParams[3], text, ScriptParams[4], ScriptParams[5],
+ ScriptParams[6], ScriptParams[7] != 0, true);
+ return 0;
+ }
+ case COMMAND_ACTIVATE_MILITARY_CRANE:
+ {
+ CollectParameters(&m_nIp, 10);
+ float infX = *(float*)&ScriptParams[2];
+ float infY = *(float*)&ScriptParams[3];
+ float supX = *(float*)&ScriptParams[4];
+ float supY = *(float*)&ScriptParams[5];
+ if (infX > supX) {
+ infX = *(float*)&ScriptParams[4];
+ supX = *(float*)&ScriptParams[2];
+ }
+ if (infY > supY) {
+ infY = *(float*)&ScriptParams[5];
+ supY = *(float*)&ScriptParams[3];
+ }
+ CCranes::ActivateCrane(infX, supX, infY, supY,
+ *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
+ DEGTORAD(*(float*)&ScriptParams[9]), false, true,
+ *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_WARP_PLAYER_INTO_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
+ pPed->WarpPedIntoCar(pVehicle);
+ return 0;
+ }
+ case COMMAND_WARP_CHAR_INTO_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
+ pPed->WarpPedIntoCar(pVehicle);
+ return 0;
+ }
+ //case COMMAND_SWITCH_CAR_RADIO:
+ //case COMMAND_SET_AUDIO_STREAM:
+ case COMMAND_PRINT_WITH_2_NUMBERS_BIG:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 4);
+ CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_3_NUMBERS_BIG:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 5);
+ CMessages::AddBigMessageWithNumber(text, ScriptParams[3], ScriptParams[4] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_4_NUMBERS_BIG:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 6);
+ CMessages::AddBigMessageWithNumber(text, ScriptParams[4], ScriptParams[5] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_5_NUMBERS_BIG:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 7);
+ CMessages::AddBigMessageWithNumber(text, ScriptParams[5], ScriptParams[6] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+ return 0;
+ }
+ case COMMAND_PRINT_WITH_6_NUMBERS_BIG:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 8);
+ CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_WAIT_STATE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->SetWaitState((eWaitState)ScriptParams[1], ScriptParams[2] >= 0 ? &ScriptParams[2] : nil);
+ return 0;
+ }
+ case COMMAND_SET_CAMERA_BEHIND_PLAYER:
+ TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString();
+ return 0;
+ case COMMAND_SET_MOTION_BLUR:
+ CollectParameters(&m_nIp, 1);
+ TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]);
+ return 0;
+ case COMMAND_PRINT_STRING_IN_STRING:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* string = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 2);
+ CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string);
+ return 0;
+ }
+ case COMMAND_CREATE_RANDOM_CHAR:
+ {
+ CollectParameters(&m_nIp, 3);
+ CZoneInfo zoneinfo;
+ CTheZones::GetZoneInfoForTimeOfDay(&CWorld::Players[CWorld::PlayerInFocus].GetPos(), &zoneinfo);
+ int mi;
+ ePedType pedtype = PEDTYPE_COP;
+ int attempt = 0;
+ while (pedtype != PEDTYPE_CIVMALE && pedtype != PEDTYPE_CIVFEMALE && attempt < 5) {
+ mi = CPopulation::ChooseCivilianOccupation(zoneinfo.pedGroup);
+ if (CModelInfo::GetModelInfo(mi)->GetRwObject())
+ pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;
+ attempt++;
+ }
+ if (!CModelInfo::GetModelInfo(mi)->GetRwObject()) {
+ mi = MI_MALE01;
+ pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;
+ }
+ CPed* ped = new CCivilianPed(pedtype, mi);
+ ped->CharCreatedBy = MISSION_CHAR;
+ ped->bRespondsToThreats = false;
+ ped->bAllowMedicsToReviveMe = false;
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pos.z += 1.0f;
+ ped->SetPosition(pos);
+ ped->SetOrientation(0.0f, 0.0f, 0.0f);
+ CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ CWorld::Add(ped);
+ ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
+ CPopulation::ms_nTotalMissionPeds++;
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR);
+ return 0;
+ }
+ case COMMAND_SET_2_REPEATED_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, nil, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_SET_2_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, nil, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_SET_3_REPEATED_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_SET_3_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, nil, nil, nil);
+ return 0;
+ }
+ case COMMAND_SET_4_REPEATED_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, nil, nil);
+ return 0;
+ }
+ case COMMAND_SET_4_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil);
+ return 0;
+ }
+ case COMMAND_IS_SNIPER_BULLET_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ));
+ return 0;
+ }
+ case COMMAND_GIVE_PLAYER_DETONATOR:
+ CGarages::GivePlayerDetonator();
+ return 0;
+ //case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:
+ case COMMAND_SET_OBJECT_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->SetMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED);
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_COLLISION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->bUsesCollision = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_IS_ICECREAM_JINGLE_ON:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ // Adding this check to correspond to command name.
+ // All original game scripts always assume that the vehicle is actually Mr. Whoopee,
+ // but maybe there are mods that use it as "is alarm activated"?
+ script_assert(pVehicle->GetModelIndex() == MI_MRWHOOP);
+ UpdateCompareFlag(pVehicle->m_bSirenOrAlarm);
+ return 0;
+ }
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands900To999(int32 command)
+{
+ char str[52];
+ char onscreen_str[KEY_LENGTH_IN_SCRIPT];
+ switch (command) {
+ case COMMAND_PRINT_STRING_IN_STRING_NOW:
+ {
+ wchar* source = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* pstr = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 2);
+ CMessages::AddMessageJumpQWithString(source, ScriptParams[0], ScriptParams[1], pstr);
+ return 0;
+ }
+ //case COMMAND_PRINT_STRING_IN_STRING_SOON:
+ case COMMAND_SET_5_REPEATED_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, nil);
+ return 0;
+ }
+ case COMMAND_SET_5_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, nil);
+ return 0;
+ }
+ case COMMAND_SET_6_REPEATED_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, text6);
+ return 0;
+ }
+ case COMMAND_SET_6_PHONE_MESSAGES:
+ {
+ CollectParameters(&m_nIp, 1);
+ wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6);
+ return 0;
+ }
+ case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY:
+ {
+ CollectParameters(&m_nIp, 6);
+ float infX = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[3];
+ float supX = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[3];
+ float infY = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[4];
+ float supY = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[4];
+ float infZ = *(float*)&ScriptParams[2] - *(float*)&ScriptParams[5];
+ float supZ = *(float*)&ScriptParams[2] + *(float*)&ScriptParams[5];
+ if (infX > supX) {
+ float tmp = infX;
+ infX = supX;
+ supX = tmp;
+ }
+ if (infY > supY) {
+ float tmp = infY;
+ infY = supY;
+ supY = tmp;
+ }
+ if (infZ > supZ) {
+ float tmp = infZ;
+ infZ = supZ;
+ supZ = tmp;
+ }
+ int16 total;
+ CWorld::FindMissionEntitiesIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, true, true, true);
+ UpdateCompareFlag(total > 0);
+ return 0;
+ }
+ case COMMAND_LOAD_ALL_MODELS_NOW:
+ CTimer::Stop();
+ CStreaming::LoadAllRequestedModels(false);
+ CTimer::Update();
+ return 0;
+ case COMMAND_ADD_TO_OBJECT_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->SetMoveSpeed(pObject->GetMoveSpeed() + METERS_PER_SECOND_TO_GAME_SPEED * *(CVector*)&ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_DRAW_SPRITE:
+ {
+ CollectParameters(&m_nIp, 9);
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true;
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = ScriptParams[0] - 1;
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect(
+ *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3], *(float*)&ScriptParams[2] + *(float*)&ScriptParams[4]);
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]);
+ CTheScripts::NumberOfIntroRectanglesThisFrame++;
+ return 0;
+ }
+ case COMMAND_DRAW_RECT:
+ {
+ CollectParameters(&m_nIp, 8);
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true;
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = -1;
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect(
+ *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3]);
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7]);
+ CTheScripts::NumberOfIntroRectanglesThisFrame++;
+ return 0;
+ }
+ case COMMAND_LOAD_SPRITE:
+ {
+ CollectParameters(&m_nIp, 1);
+ strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ str[i] = tolower(str[i]);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ int slot = CTxdStore::FindTxdSlot("script");
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(slot);
+ CTheScripts::ScriptSprites[ScriptParams[0] - 1].SetTexture(str);
+ CTxdStore::PopCurrentTxd();
+ return 0;
+ }
+ case COMMAND_LOAD_TEXTURE_DICTIONARY:
+ {
+ strcpy(str, "models\\");
+ strncpy(str + sizeof("models\\"), (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ strcat(str, ".txd");
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ int slot = CTxdStore::FindTxdSlot("script");
+ if (slot == -1)
+ slot = CTxdStore::AddTxdSlot("script");
+ CTxdStore::LoadTxd(slot, str);
+ CTxdStore::AddRef(slot);
+ return 0;
+ }
+ case COMMAND_REMOVE_TEXTURE_DICTIONARY:
+ {
+ for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)
+ CTheScripts::ScriptSprites[i].Delete();
+ CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script"));
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_DYNAMIC:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ if (ScriptParams[1]) {
+ if (pObject->bIsStatic) {
+ pObject->SetIsStatic(false);
+ pObject->AddToMovingList();
+ }
+ }
+ else {
+ if (!pObject->bIsStatic) {
+ pObject->SetIsStatic(true);
+ pObject->RemoveFromMovingList();
+ }
+ }
+ return 0;
+ }
+ case COMMAND_SET_CHAR_ANIM_SPEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetFirstAssociation(pPed->GetClump());
+ if (pAssoc)
+ pAssoc->speed = *(float*)&ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_PLAY_MISSION_PASSED_TUNE:
+ {
+ CollectParameters(&m_nIp, 1);
+ DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);
+ DMAudio.PlayFrontEndTrack(ScriptParams[0] + STREAMED_SOUND_MISSION_COMPLETED - 1, 0);
+ return 0;
+ }
+ case COMMAND_CLEAR_AREA:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CWorld::ClearExcitingStuffFromArea(pos, *(float*)&ScriptParams[3], ScriptParams[4]);
+ return 0;
+ }
+ case COMMAND_FREEZE_ONSCREEN_TIMER:
+ CollectParameters(&m_nIp, 1);
+ CUserDisplay::OnscnTimer.m_bDisabled = ScriptParams[0] != 0;
+ return 0;
+ case COMMAND_SWITCH_CAR_SIREN:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0;
+ return 0;
+ }
+ case COMMAND_SWITCH_PED_ROADS_ON_ANGLED:
+ {
+ CollectParameters(&m_nIp, 7);
+ ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
+ *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 1);
+ return 0;
+ }
+ case COMMAND_SWITCH_PED_ROADS_OFF_ANGLED:
+ CollectParameters(&m_nIp, 7);
+ ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
+ *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 0);
+ return 0;
+ case COMMAND_SWITCH_ROADS_ON_ANGLED:
+ CollectParameters(&m_nIp, 7);
+ ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
+ *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 1);
+ return 0;
+ case COMMAND_SWITCH_ROADS_OFF_ANGLED:
+ CollectParameters(&m_nIp, 7);
+ ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
+ *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0);
+ return 0;
+ case COMMAND_SET_CAR_WATERTIGHT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ pCar->bWaterTight = ScriptParams[1] != 0;
+ return 0;
+ }
+ case COMMAND_ADD_MOVING_PARTICLE_EFFECT:
+ {
+ CollectParameters(&m_nIp, 12);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float size = Max(0.0f, *(float*)&ScriptParams[7]);
+ eParticleObjectType type = (eParticleObjectType)ScriptParams[0];
+ RwRGBA color;
+ if (type == POBJECT_SMOKE_TRAIL){
+ color.alpha = -1;
+ color.red = ScriptParams[8];
+ color.green = ScriptParams[9];
+ color.blue = ScriptParams[10];
+ }else{
+ color.alpha = color.red = color.blue = color.green = 0;
+ }
+ CVector target = *(CVector*)&ScriptParams[4];
+ CParticleObject::AddObject(type, pos, target, size, ScriptParams[11], color, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bDontDragMeOutCar = ScriptParams[1] != 0;
+ return 0;
+ }
+ case COMMAND_TURN_CAR_TO_FACE_COORD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ const CVector& pos = pVehicle->GetPosition();
+ float heading = CGeneral::GetATanOfXY(pos.y - *(float*)&ScriptParams[2], pos.x - *(float*)&ScriptParams[1]) + HALFPI;
+ if (heading > TWOPI)
+ heading -= TWOPI;
+ pVehicle->SetHeading(heading);
+ return 0;
+ }
+ case COMMAND_IS_CRANE_LIFTING_CAR:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[2]);
+ UpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle));
+ return 0;
+ }
+ case COMMAND_DRAW_SPHERE:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ C3dMarkers::PlaceMarkerSet((uintptr)this + m_nIp, MARKERTYPE_CYLINDER, pos, *(float*)&ScriptParams[3],
+ SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A,
+ SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0);
+ return 0;
+ }
+ case COMMAND_SET_CAR_STATUS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->SetStatus((eEntityStatus)ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_MALE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->m_nPedType != PEDTYPE_CIVFEMALE && pPed->m_nPedType != PEDTYPE_PROSTITUTE);
+ return 0;
+ }
+ case COMMAND_SCRIPT_NAME:
+ {
+ strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ str[i] = tolower(str[i]);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ strncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT);
+ return 0;
+ }
+ case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL:
+ {
+ CollectParameters(&m_nIp, 3);
+ CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_FIND_DRUG_PLANE_COORDINATES:
+ *(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates();
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ case COMMAND_SAVE_INT_TO_DEBUG_FILE:
+ // TODO: implement something here
+ CollectParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SAVE_FLOAT_TO_DEBUG_FILE:
+ CollectParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE:
+ return 0;
+ case COMMAND_POLICE_RADIO_MESSAGE:
+ CollectParameters(&m_nIp, 3);
+ DMAudio.PlaySuspectLastSeen(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]);
+ return 0;
+ case COMMAND_SET_CAR_STRONG:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bTakeLessDamage = ScriptParams[1] != 0;
+ return 0;
+ }
+ case COMMAND_REMOVE_ROUTE:
+ CollectParameters(&m_nIp, 1);
+ CRouteNode::RemoveRoute(ScriptParams[0]);
+ return 0;
+ case COMMAND_SWITCH_RUBBISH:
+ CollectParameters(&m_nIp, 1);
+ CRubbish::SetVisibility(ScriptParams[0] != 0);;
+ return 0;
+ case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 6);
+ float x1 = *(float*)&ScriptParams[0];
+ float y1 = *(float*)&ScriptParams[1];
+ float z1 = *(float*)&ScriptParams[2];
+ float x2 = *(float*)&ScriptParams[3];
+ float y2 = *(float*)&ScriptParams[4];
+ float z2 = *(float*)&ScriptParams[5];
+ CParticleObject* tmp = CParticleObject::pCloseListHead;
+ while (tmp) {
+ CParticleObject* next = tmp->m_pNext;
+ if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2))
+ tmp->RemoveObject();
+ tmp = next;
+ }
+ tmp = CParticleObject::pFarListHead;
+ while (tmp) {
+ CParticleObject* next = tmp->m_pNext;
+ if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2))
+ tmp->RemoveObject();
+ tmp = next;
+ }
+ return 0;
+ }
+ case COMMAND_SWITCH_STREAMING:
+ CollectParameters(&m_nIp, 1);
+ CStreaming::ms_disableStreaming = ScriptParams[0] == 0;
+ return 0;
+ case COMMAND_IS_GARAGE_OPEN:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CGarages::IsGarageOpen(ScriptParams[0]));
+ return 0;
+ case COMMAND_IS_GARAGE_CLOSED:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0]));
+ return 0;
+ case COMMAND_START_CATALINA_HELI:
+ CHeli::StartCatalinaFlyBy();
+ return 0;
+ case COMMAND_CATALINA_HELI_TAKE_OFF:
+ CHeli::CatalinaTakeOff();
+ return 0;
+ case COMMAND_REMOVE_CATALINA_HELI:
+ CHeli::RemoveCatalinaHeli();
+ return 0;
+ case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN:
+ UpdateCompareFlag(CHeli::HasCatalinaBeenShotDown());
+ return 0;
+ case COMMAND_SWAP_NEAREST_BUILDING_MODEL:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = *(float*)&ScriptParams[3];
+ int mi1 = ScriptParams[4] >= 0 ? ScriptParams[4] : CTheScripts::UsedObjectArray[-ScriptParams[4]].index;
+ int mi2 = ScriptParams[5] >= 0 ? ScriptParams[5] : CTheScripts::UsedObjectArray[-ScriptParams[5]].index;
+ int16 total;
+ CEntity* apEntities[16];
+ CWorld::FindObjectsOfTypeInRange(mi1, pos, radius, true, &total, 16, apEntities, true, false, false, false, false);
+ if (total == 0)
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities);
+ if (total == 0)
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities);
+ CEntity* pClosestEntity = nil;
+ float min_dist = 2.0f * radius;
+ for (int i = 0; i < total; i++) {
+ float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
+ if (dist < min_dist) {
+ min_dist = dist;
+ pClosestEntity = apEntities[i];
+ }
+ }
+ if (!pClosestEntity) {
+ printf("Failed to find building\n");
+ return 0;
+ }
+ CBuilding* pReplacedBuilding = ((CBuilding*)pClosestEntity);
+ pReplacedBuilding->ReplaceWithNewModel(mi2);
+ CTheScripts::AddToBuildingSwapArray(pReplacedBuilding, mi1, mi2);
+ return 0;
+ }
+ case COMMAND_SWITCH_WORLD_PROCESSING:
+ CollectParameters(&m_nIp, 1);
+ CWorld::bProcessCutsceneOnly = ScriptParams[0] == 0;
+ return 0;
+ case COMMAND_REMOVE_ALL_PLAYER_WEAPONS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->ClearWeapons();
+ return 0;
+ }
+ case COMMAND_GRAB_CATALINA_HELI:
+ {
+ CHeli* pHeli = CHeli::FindPointerToCatalinasHeli();
+ ScriptParams[0] = pHeli ? CPools::GetVehiclePool()->GetIndex(pHeli) : -1;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CLEAR_AREA_OF_CARS:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ CWorld::ClearCarsFromArea(infX, infY, infZ, supX, supY, supZ);
+ return 0;
+ }
+ case COMMAND_SET_ROTATING_GARAGE_DOOR:
+ CollectParameters(&m_nIp, 1);
+ CGarages::SetGarageDoorToRotate(ScriptParams[0]);
+ return 0;
+ case COMMAND_ADD_SPHERE:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = *(float*)&ScriptParams[3];
+ CTheScripts::GetActualScriptSphereIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CTheScripts::AddScriptSphere((uintptr)this + m_nIp, pos, radius);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_REMOVE_SPHERE:
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::RemoveScriptSphere(ScriptParams[0]);
+ return 0;
+ case COMMAND_CATALINA_HELI_FLY_AWAY:
+ CHeli::MakeCatalinaHeliFlyAway();
+ return 0;
+ case COMMAND_SET_EVERYONE_IGNORE_PLAYER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ if (ScriptParams[1]) {
+ pPed->m_pWanted->m_bIgnoredByEveryone = true;
+ CWorld::StopAllLawEnforcersInTheirTracks();
+ }
+ else {
+ pPed->m_pWanted->m_bIgnoredByEveryone = false;
+ }
+ return 0;
+ }
+ case COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;
+ ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;
+ ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_PHONE_DISPLAYING_MESSAGE:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0]));
+ return 0;
+ case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
+ uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
+ wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
+ strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CUserDisplay::OnscnTimer.AddClock(var, onscreen_str);
+ return 0;
+ }
+ case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
+ uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 1);
+ wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
+ strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str);
+ return 0;
+ }
+ case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK:
+ {
+ CollectParameters(&m_nIp, 4);
+ if (CCarCtrl::NumRandomCars >= 30)
+ return 0;
+ int attempts;
+ int model = -1;
+ int index = CGeneral::GetRandomNumberInRange(0, 50);
+ for (attempts = 0; attempts < 50; attempts++) {
+ if (model != -1)
+ break;
+ model = CStreaming::ms_vehiclesLoaded[index];
+ if (model == -1)
+ continue;
+ // desperatly want to believe this was inlined :|
+ CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(model);
+ script_assert(pInfo->GetModelType() == MITYPE_VEHICLE);
+ CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo;
+ if (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR) {
+ switch (model) {
+ case MI_LANDSTAL:
+ case MI_LINERUN:
+ case MI_FIRETRUCK:
+ case MI_TRASH:
+ case MI_STRETCH:
+ case MI_MULE:
+ case MI_AMBULAN:
+ case MI_FBICAR:
+ case MI_MRWHOOP:
+ case MI_BFINJECT:
+ case MI_CORPSE:
+ case MI_POLICE:
+ case MI_ENFORCER:
+ case MI_SECURICA:
+ case MI_PREDATOR:
+ case MI_BUS:
+ case MI_RHINO:
+ case MI_BARRACKS:
+ case MI_TRAIN:
+ case MI_CHOPPER:
+ 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_AIRTRAIN:
+ case MI_DEADDODO:
+ case MI_SPEEDER:
+ case MI_REEFER:
+ 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:
+ model = -1;
+ break;
+ case MI_IDAHO:
+ case MI_STINGER:
+ case MI_PEREN:
+ case MI_SENTINEL:
+ case MI_PATRIOT:
+ case MI_MANANA:
+ case MI_INFERNUS:
+ case MI_BLISTA:
+ case MI_PONY:
+ case MI_CHEETAH:
+ case MI_MOONBEAM:
+ case MI_ESPERANT:
+ case MI_TAXI:
+ case MI_KURUMA:
+ case MI_BOBCAT:
+ case MI_BANSHEE:
+ case MI_CABBIE:
+ case MI_STALLION:
+ case MI_RUMPO:
+ case 151:
+ case 152:
+ case 153:
+ break;
+ default:
+ printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]);
+ model = -1;
+ break;
+ }
+ }
+ else
+ model = -1;
+ if (++index >= 50)
+ index = 0;
+ }
+ if (model == -1)
+ return 0;
+ CVehicle* car;
+ if (!CModelInfo::IsBikeModel(model))
+ car = new CAutomobile(model, RANDOM_VEHICLE);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();
+ car->SetPosition(pos);
+ car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3]));
+ CTheScripts::ClearSpaceForMissionEntity(pos, car);
+ car->SetStatus(STATUS_ABANDONED);
+ car->bIsLocked = false;
+ car->bIsCarParkVehicle = true;
+ CCarCtrl::JoinCarWithRoadSystem(car);
+ car->AutoPilot.m_nCarMission = MISSION_NONE;
+ 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);
+ CWorld::Add(car);
+ return 0;
+ }
+ case COMMAND_IS_COLLISION_IN_MEMORY:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_WANTED_MULTIPLIER:
+ CollectParameters(&m_nIp, 1);
+ FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0];
+ return 0;
+ case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER:
+ TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
+ return 0;
+ case COMMAND_IS_CAR_VISIBLY_DAMAGED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->bIsDamaged);
+ return 0;
+ }
+ case COMMAND_DOES_OBJECT_EXIST:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0]));
+ return 0;
+ case COMMAND_LOAD_SCENE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ CTimer::Stop();
+ CStreaming::LoadScene(pos);
+ CTimer::Update();
+ return 0;
+ }
+ case COMMAND_ADD_STUCK_CAR_CHECK:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CTheScripts::StuckCars.AddCarToCheck(ScriptParams[0], *(float*)&ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_REMOVE_STUCK_CAR_CHECK:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::StuckCars.RemoveCarFromCheck(ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_CAR_STUCK:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0]));
+ return 0;
+ case COMMAND_LOAD_MISSION_AUDIO:
+ strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ str[i] = tolower(str[i]);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ DMAudio.PreloadMissionAudio(str);
+ return 0;
+ case COMMAND_HAS_MISSION_AUDIO_LOADED:
+ UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1);
+ return 0;
+ case COMMAND_PLAY_MISSION_AUDIO:
+ DMAudio.PlayLoadedMissionAudio();
+ return 0;
+ case COMMAND_HAS_MISSION_AUDIO_FINISHED:
+ UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished());
+ return 0;
+ case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
+ *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition();
+ *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node);
+ StoreParameters(&m_nIp, 4);
+ return 0;
+ }
+ case COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED:
+ {
+ CollectParameters(&m_nIp, 2);
+ UpdateCompareFlag(CGarages::HasImportExportGarageCollectedThisCar(ScriptParams[0], ScriptParams[1] - 1));
+ return 0;
+ }
+ case COMMAND_CLEAR_THIS_PRINT:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CMessages::ClearThisPrint(text);
+ return 0;
+ }
+ case COMMAND_CLEAR_THIS_BIG_PRINT:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CMessages::ClearThisBigPrint(text);
+ return 0;
+ }
+ case COMMAND_SET_MISSION_AUDIO_POSITION:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z);
+ return 0;
+ }
+ case COMMAND_ACTIVATE_SAVE_MENU:
+ FrontEndMenuManager.m_bSaveMenuActive = true;
+ return 0;
+ case COMMAND_HAS_SAVE_GAME_FINISHED:
+ UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive);
+ return 0;
+ case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE:
+ CollectParameters(&m_nIp, 1);
+ CGarages::SetLeaveCameraForThisGarage(ScriptParams[0]);
+ return 0;
+ case COMMAND_ADD_BLIP_FOR_PICKUP_OLD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_BLIP_FOR_PICKUP:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH);
+ CRadar::ChangeBlipScale(handle, 3);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(handle, ScriptParams[1]);
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_PED_DENSITY_MULTIPLIER:
+ CollectParameters(&m_nIp, 1);
+ CPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0];
+ return 0;
+ case COMMAND_FORCE_RANDOM_PED_TYPE:
+ CollectParameters(&m_nIp, 1);
+ CPopulation::m_AllRandomPedsThisType = ScriptParams[0];
+ return 0;
+ case COMMAND_SET_TEXT_DRAW_BEFORE_FADE:
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0;
+ return 0;
+ case COMMAND_GET_COLLECTABLE1S_COLLECTED:
+ ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_REGISTER_EL_BURRO_TIME:
+ CollectParameters(&m_nIp, 1);
+ CStats::RegisterElBurroTime(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0;
+ return 0;
+ case COMMAND_SET_TEXT_RIGHT_JUSTIFY:
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bRightJustify = ScriptParams[0] != 0;
+ return 0;
+ case COMMAND_PRINT_HELP:
+ {
+ if (CCamera::m_bUseMouse3rdPerson && (
+ strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 ||
+ strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 ||
+ strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_3A", 7) == 0 ||
+ strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_4A", 7) == 0)) {
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ return 0;
+ }
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CHud::SetHelpMessage(text, false);
+ return 0;
+ }
+ case COMMAND_CLEAR_HELP:
+ CHud::SetHelpMessage(nil, false);
+ return 0;
+ case COMMAND_FLASH_HUD_OBJECT:
+ CollectParameters(&m_nIp, 1);
+ CHud::m_ItemToFlash = ScriptParams[0];
+ return 0;
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp
new file mode 100644
index 00000000..164ca036
--- /dev/null
+++ b/src/control/Script5.cpp
@@ -0,0 +1,2011 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "CarCtrl.h"
+#include "BulletInfo.h"
+#include "General.h"
+#include "Lines.h"
+#include "Messages.h"
+#include "Pad.h"
+#include "Pools.h"
+#include "Population.h"
+#include "RpAnimBlend.h"
+#include "Shadows.h"
+#include "SpecialFX.h"
+#include "World.h"
+#include "main.h"
+
+int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index)
+{
+ if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1)
+ ScriptSphereArray[index].m_Index = 1;
+ else
+ ScriptSphereArray[index].m_Index++;
+ return (uint16)index | ScriptSphereArray[index].m_Index << 16;
+}
+
+int32 CTheScripts::GetActualScriptSphereIndex(int32 index)
+{
+ if (index == -1)
+ return -1;
+ uint16 check = (uint32)index >> 16;
+ uint16 array_idx = index & (0xFFFF);
+ script_assert(array_idx < ARRAY_SIZE(ScriptSphereArray));
+ if (check != ScriptSphereArray[array_idx].m_Index)
+ return -1;
+ return array_idx;
+}
+
+void CTheScripts::DrawScriptSpheres()
+{
+ for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) {
+ if (ScriptSphereArray[i].m_bInUse)
+ C3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius,
+ SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0);
+ }
+}
+
+int32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius)
+{
+ int16 i = 0;
+ for (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) {
+ if (!ScriptSphereArray[i].m_bInUse)
+ break;
+ }
+#ifdef FIX_BUGS
+ if (i == MAX_NUM_SCRIPT_SPHERES)
+ return -1;
+#endif
+ ScriptSphereArray[i].m_bInUse = true;
+ ScriptSphereArray[i].m_Id = id;
+ ScriptSphereArray[i].m_vecCenter = pos;
+ ScriptSphereArray[i].m_fRadius = radius;
+ return GetNewUniqueScriptSphereIndex(i);
+}
+
+void CTheScripts::RemoveScriptSphere(int32 index)
+{
+ index = GetActualScriptSphereIndex(index);
+ if (index == -1)
+ return;
+ ScriptSphereArray[index].m_bInUse = false;
+ ScriptSphereArray[index].m_Id = 0;
+}
+
+void CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model)
+{
+ int i = 0;
+ bool found = false;
+ while (i < MAX_NUM_BUILDING_SWAPS && !found) {
+ if (BuildingSwapArray[i].m_pBuilding == pBuilding)
+ found = true;
+ else
+ i++;
+ }
+ if (found) {
+ if (BuildingSwapArray[i].m_nOldModel == new_model) {
+ BuildingSwapArray[i].m_pBuilding = nil;
+ BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1;
+ }
+ else {
+ BuildingSwapArray[i].m_nNewModel = new_model;
+ }
+ }
+ else {
+ i = 0;
+ while (i < MAX_NUM_BUILDING_SWAPS && !found) {
+ if (BuildingSwapArray[i].m_pBuilding == nil)
+ found = true;
+ else
+ i++;
+ }
+ if (found) {
+ BuildingSwapArray[i].m_pBuilding = pBuilding;
+ BuildingSwapArray[i].m_nNewModel = new_model;
+ BuildingSwapArray[i].m_nOldModel = old_model;
+ }
+ }
+}
+
+void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove)
+{
+ int i = 0;
+ bool found = false;
+ while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {
+ if (InvisibilitySettingArray[i] == pEntity)
+ found = true;
+ else
+ i++;
+ }
+ if (found) {
+ if (remove)
+ InvisibilitySettingArray[i] = nil;
+ }
+ else if (!remove) {
+ i = 0;
+ while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {
+ if (InvisibilitySettingArray[i] == nil)
+ found = true;
+ else
+ i++;
+ }
+ if (found)
+ InvisibilitySettingArray[i] = pEntity;
+ }
+}
+
+void CTheScripts::UndoBuildingSwaps()
+{
+ for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
+ if (BuildingSwapArray[i].m_pBuilding) {
+ BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel);
+ BuildingSwapArray[i].m_pBuilding = nil;
+ BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1;
+ }
+ }
+}
+
+void CTheScripts::UndoEntityInvisibilitySettings()
+{
+ for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {
+ if (InvisibilitySettingArray[i]) {
+ InvisibilitySettingArray[i]->bIsVisible = true;
+ InvisibilitySettingArray[i] = nil;
+ }
+ }
+}
+
+
+void CRunningScript::UpdateCompareFlag(bool flag)
+{
+ if (m_bNotFlag)
+ flag = !flag;
+ if (m_nAndOrState == ANDOR_NONE) {
+ m_bCondResult = flag;
+ return;
+ }
+ if (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8) {
+ m_bCondResult &= flag;
+ if (m_nAndOrState == ANDS_1) {
+ m_nAndOrState = ANDOR_NONE;
+ return;
+ }
+ }
+ else if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8) {
+ m_bCondResult |= flag;
+ if (m_nAndOrState == ORS_1) {
+ m_nAndOrState = ANDOR_NONE;
+ return;
+ }
+ }
+ else {
+ return;
+ }
+ m_nAndOrState--;
+}
+
+void CRunningScript::LocatePlayerCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_3D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ switch (command) {
+ case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:
+ if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ X = *(float*)&ScriptParams[1];
+ Y = *(float*)&ScriptParams[2];
+ if (b3D) {
+ Z = *(float*)&ScriptParams[3];
+ dX = *(float*)&ScriptParams[4];
+ dY = *(float*)&ScriptParams[5];
+ dZ = *(float*)&ScriptParams[6];
+ debug = ScriptParams[7];
+ } else {
+ dX = *(float*)&ScriptParams[3];
+ dY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (!decided) {
+ CVector pos = pPlayerInfo->GetPos();
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ } else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D:
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_2D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:
+ result = !pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_PLAYER_IN_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:
+ result = pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocatePlayerCharCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 6 : 5);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CVector pos = pPlayerInfo->GetPos();
+ if (pTarget->bInVehicle) {
+ X = pTarget->m_pMyVehicle->GetPosition().x;
+ Y = pTarget->m_pMyVehicle->GetPosition().y;
+ Z = pTarget->m_pMyVehicle->GetPosition().z;
+ } else {
+ X = pTarget->GetPosition().x;
+ Y = pTarget->GetPosition().y;
+ Z = pTarget->GetPosition().z;
+ }
+ dX = *(float*)&ScriptParams[2];
+ dY = *(float*)&ScriptParams[3];
+ if (b3D) {
+ dZ = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ else {
+ debug = ScriptParams[4];
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D:
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:
+ result = !pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:
+ result = pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+#ifdef FIX_BUGS
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+#else
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT);
+#endif
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocatePlayerCarCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 6 : 5);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CVector pos = pPlayerInfo->GetPos();
+ X = pTarget->GetPosition().x;
+ Y = pTarget->GetPosition().y;
+ Z = pTarget->GetPosition().z;
+ dX = *(float*)&ScriptParams[2];
+ dY = *(float*)&ScriptParams[3];
+ if (b3D) {
+ dZ = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ else {
+ debug = ScriptParams[4];
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:
+ result = !pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D:
+ case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:
+ result = pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocateCharCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_3D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_3D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ switch (command) {
+ case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:
+ if (!CTheScripts::IsPedStopped(pPed)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ X = *(float*)&ScriptParams[1];
+ Y = *(float*)&ScriptParams[2];
+ if (b3D) {
+ Z = *(float*)&ScriptParams[3];
+ dX = *(float*)&ScriptParams[4];
+ dY = *(float*)&ScriptParams[5];
+ dZ = *(float*)&ScriptParams[6];
+ debug = ScriptParams[7];
+ }
+ else {
+ dX = *(float*)&ScriptParams[3];
+ dY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (!decided) {
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_2D:
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_CHAR_ON_FOOT_2D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:
+ case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:
+ result = !pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_CHAR_IN_CAR_2D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:
+ result = pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocateCharCharCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 6 : 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ if (pTarget->bInVehicle) {
+ X = pTarget->m_pMyVehicle->GetPosition().x;
+ Y = pTarget->m_pMyVehicle->GetPosition().y;
+ Z = pTarget->m_pMyVehicle->GetPosition().z;
+ }
+ else {
+ X = pTarget->GetPosition().x;
+ Y = pTarget->GetPosition().y;
+ Z = pTarget->GetPosition().z;
+ }
+ dX = *(float*)&ScriptParams[2];
+ dY = *(float*)&ScriptParams[3];
+ if (b3D) {
+ dZ = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ else {
+ debug = ScriptParams[4];
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D:
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:
+ result = !pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:
+ result = pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+#ifdef FIX_BUGS
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+#else
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT);
+#endif
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocateCharCarCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 6 : 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ X = pTarget->GetPosition().x;
+ Y = pTarget->GetPosition().y;
+ Z = pTarget->GetPosition().z;
+ dX = *(float*)&ScriptParams[2];
+ dY = *(float*)&ScriptParams[3];
+ if (b3D) {
+ dZ = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ else {
+ debug = ScriptParams[4];
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D:
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:
+ result = !pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:
+ result = pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocateCharObjectCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 6 : 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ X = pTarget->GetPosition().x;
+ Y = pTarget->GetPosition().y;
+ Z = pTarget->GetPosition().z;
+ dX = *(float*)&ScriptParams[2];
+ dY = *(float*)&ScriptParams[3];
+ if (b3D) {
+ dZ = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ else {
+ debug = ScriptParams[4];
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
+ result = true;
+ break;
+ case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
+ result = !pPed->bInVehicle;
+ break;
+ case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
+ result = pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocateCarCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_CAR_3D:
+ case COMMAND_LOCATE_STOPPED_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVector pos = pVehicle->GetPosition();
+ switch (command) {
+ case COMMAND_LOCATE_STOPPED_CAR_2D:
+ case COMMAND_LOCATE_STOPPED_CAR_3D:
+ if (!CTheScripts::IsVehicleStopped(pVehicle)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ X = *(float*)&ScriptParams[1];
+ Y = *(float*)&ScriptParams[2];
+ if (b3D) {
+ Z = *(float*)&ScriptParams[3];
+ dX = *(float*)&ScriptParams[4];
+ dY = *(float*)&ScriptParams[5];
+ dZ = *(float*)&ScriptParams[6];
+ debug = ScriptParams[7];
+ }
+ else {
+ dX = *(float*)&ScriptParams[3];
+ dY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (!decided) {
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ result = in_area;
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_SNIPER_BULLET_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 7 : 5);
+ X = *(float*)&ScriptParams[0];
+ Y = *(float*)&ScriptParams[1];
+ if (b3D) {
+ Z = *(float*)&ScriptParams[2];
+ dX = *(float*)&ScriptParams[3];
+ dY = *(float*)&ScriptParams[4];
+ dZ = *(float*)&ScriptParams[5];
+ debug = ScriptParams[6];
+ }
+ else {
+ dX = *(float*)&ScriptParams[2];
+ dY = *(float*)&ScriptParams[3];
+ debug = ScriptParams[4];
+ }
+ result = CBulletInfo::TestForSniperBullet(X - dX, X + dX, Y - dY, Y + dY, b3D ? Z - dZ : -1000.0f, b3D ? Z + dZ : 1000.0f);
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
+void CRunningScript::PlayerInAreaCheckCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float infX, infY, infZ, supX, supY, supZ;
+ switch (command) {
+ case COMMAND_IS_PLAYER_IN_AREA_3D:
+ case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ switch (command) {
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:
+ if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ infX = *(float*)&ScriptParams[1];
+ infY = *(float*)&ScriptParams[2];
+ if (b3D) {
+ infZ = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[5];
+ supZ = *(float*)&ScriptParams[6];
+ if (infZ > supZ) {
+ infZ = *(float*)&ScriptParams[6];
+ supZ = *(float*)&ScriptParams[3];
+ }
+ debug = ScriptParams[7];
+ }
+ else {
+ supX = *(float*)&ScriptParams[3];
+ supY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (infX > supX) {
+ float tmp = infX;
+ infX = supX;
+ supX = tmp;
+ }
+ if (infY > supY) {
+ float tmp = infY;
+ infY = supY;
+ supY = tmp;
+ }
+ if (!decided) {
+ CVector pos = pPlayerInfo->GetPos();
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y &&
+ infZ <= pos.z &&
+ supZ >= pos.z;
+ }
+ else {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_IS_PLAYER_IN_AREA_2D:
+ case COMMAND_IS_PLAYER_IN_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:
+ result = true;
+ break;
+ case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:
+ result = !pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:
+ result = pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+ else
+ CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
+ }
+}
+
+void CRunningScript::PlayerInAngledAreaCheckCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float infX, infY, infZ, supX, supY, supZ, side2length;
+ switch (command) {
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 9 : 7);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ switch (command) {
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
+ if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ infX = *(float*)&ScriptParams[1];
+ infY = *(float*)&ScriptParams[2];
+ if (b3D) {
+ infZ = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[5];
+ supZ = *(float*)&ScriptParams[6];
+ if (infZ > supZ) {
+ infZ = *(float*)&ScriptParams[6];
+ supZ = *(float*)&ScriptParams[3];
+ }
+ side2length = *(float*)&ScriptParams[7];
+ debug = ScriptParams[8];
+ }
+ else {
+ supX = *(float*)&ScriptParams[3];
+ supY = *(float*)&ScriptParams[4];
+ side2length = *(float*)&ScriptParams[5];
+ debug = ScriptParams[6];
+ }
+ float initAngle = CGeneral::GetRadianAngleBetweenPoints(infX, infY, supX, supY) + HALFPI;
+ while (initAngle < 0.0f)
+ initAngle += TWOPI;
+ while (initAngle > TWOPI)
+ initAngle -= TWOPI;
+ // it looks like the idea is to use a rectangle using the diagonal of the rectangle as
+ // the side of new rectangle, with "length" being the length of second side
+ float rotatedSupX = supX + side2length * sin(initAngle);
+ float rotatedSupY = supY - side2length * cos(initAngle);
+ float rotatedInfX = infX + side2length * sin(initAngle);
+ float rotatedInfY = infY - side2length * cos(initAngle);
+ float side1X = supX - infX;
+ float side1Y = supY - infY;
+ float side1Length = CVector2D(side1X, side1Y).Magnitude();
+ float side2X = rotatedInfX - infX;
+ float side2Y = rotatedInfY - infY;
+ float side2Length = CVector2D(side2X, side2Y).Magnitude(); // == side2length?
+ if (!decided) {
+ CVector pos = pPlayerInfo->GetPos();
+ result = false;
+ float X = pos.x - infX;
+ float Y = pos.y - infY;
+ float positionAlongSide1 = X * side1X / side1Length + Y * side1Y / side1Length;
+ bool in_area = false;
+ if (positionAlongSide1 >= 0.0f && positionAlongSide1 <= side1Length) {
+ float positionAlongSide2 = X * side2X / side2Length + Y * side2Y / side2Length;
+ if (positionAlongSide2 >= 0.0f && positionAlongSide2 <= side2Length) {
+ in_area = !b3D || pos.z >= infZ && pos.z <= supZ;
+ }
+ }
+
+ if (in_area) {
+ switch (command) {
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
+ result = true;
+ break;
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
+ result = !pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
+ case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
+ result = pPlayerInfo->m_pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantAngledArea((uintptr)this + m_nIp, infX, infY, supX, supY,
+ rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugAngledCube(infX, infY, infZ, supX, supY, supZ,
+ rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY);
+ else
+ CTheScripts::DrawDebugAngledSquare(infX, infY, supX, supY,
+ rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY);
+ }
+}
+
+void CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float infX, infY, infZ, supX, supY, supZ;
+ switch (command) {
+ case COMMAND_IS_CHAR_IN_AREA_3D:
+ case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ switch (command) {
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:
+ if (!CTheScripts::IsPedStopped(pPed)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ infX = *(float*)&ScriptParams[1];
+ infY = *(float*)&ScriptParams[2];
+ if (b3D) {
+ infZ = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[5];
+ supZ = *(float*)&ScriptParams[6];
+ if (infZ > supZ) {
+ infZ = *(float*)&ScriptParams[6];
+ supZ = *(float*)&ScriptParams[3];
+ }
+ debug = ScriptParams[7];
+ }
+ else {
+ supX = *(float*)&ScriptParams[3];
+ supY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (infX > supX) {
+ float tmp = infX;
+ infX = supX;
+ supX = tmp;
+ }
+ if (infY > supY) {
+ float tmp = infY;
+ infY = supY;
+ supY = tmp;
+ }
+ if (!decided) {
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y &&
+ infZ <= pos.z &&
+ supZ >= pos.z;
+ }
+ else {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_IS_CHAR_IN_AREA_2D:
+ case COMMAND_IS_CHAR_IN_AREA_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
+ result = true;
+ break;
+ case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
+ result = !pPed->bInVehicle;
+ break;
+ case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:
+ case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:
+ result = pPed->bInVehicle;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+ else
+ CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
+ }
+}
+
+void CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug, decided = false;
+ float infX, infY, infZ, supX, supY, supZ;
+ switch (command) {
+ case COMMAND_IS_CAR_IN_AREA_3D:
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVector pos = pVehicle->GetPosition();
+ switch (command) {
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_2D:
+ if (!CTheScripts::IsVehicleStopped(pVehicle)) {
+ result = false;
+ decided = true;
+ }
+ break;
+ default:
+ break;
+ }
+ infX = *(float*)&ScriptParams[1];
+ infY = *(float*)&ScriptParams[2];
+ if (b3D) {
+ infZ = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[5];
+ supZ = *(float*)&ScriptParams[6];
+ if (infZ > supZ) {
+ infZ = *(float*)&ScriptParams[6];
+ supZ = *(float*)&ScriptParams[3];
+ }
+ debug = ScriptParams[7];
+ }
+ else {
+ supX = *(float*)&ScriptParams[3];
+ supY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (infX > supX) {
+ float tmp = infX;
+ infX = supX;
+ supX = tmp;
+ }
+ if (infY > supY) {
+ float tmp = infY;
+ infY = supY;
+ supY = tmp;
+ }
+ if (!decided) {
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y &&
+ infZ <= pos.z &&
+ supZ >= pos.z;
+ }
+ else {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_IS_CAR_IN_AREA_2D:
+ case COMMAND_IS_CAR_IN_AREA_3D:
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_2D:
+ case COMMAND_IS_CAR_STOPPED_IN_AREA_3D:
+ result = true;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+ else
+ CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
+ }
+}
+
+void CRunningScript::DoDeatharrestCheck()
+{
+ if (!m_bDeatharrestEnabled)
+ return;
+ if (!CTheScripts::IsPlayerOnAMission())
+ return;
+ CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
+ if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest() && !CTheScripts::UpsideDownCars.AreAnyCarsUpsideDown())
+ return;
+#ifdef MISSION_REPLAY
+ if (AllowMissionReplay != 0)
+ return;
+ if (CanAllowMissionReplay())
+ AllowMissionReplay = 1;
+#endif
+ script_assert(m_nStackPointer > 0);
+ 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;
+}
+
+int16 CRunningScript::GetPadState(uint16 pad, uint16 button)
+{
+ CPad* pPad = CPad::GetPad(pad);
+ switch (button) {
+ case 0: return pPad->NewState.LeftStickX;
+ case 1: return pPad->NewState.LeftStickY;
+ case 2: return pPad->NewState.RightStickX;
+ case 3: return pPad->NewState.RightStickY;
+ case 4: return pPad->NewState.LeftShoulder1;
+ case 5: return pPad->NewState.LeftShoulder2;
+ case 6: return pPad->NewState.RightShoulder1;
+ case 7: return pPad->NewState.RightShoulder2;
+ case 8: return pPad->NewState.DPadUp;
+ case 9: return pPad->NewState.DPadDown;
+ case 10: return pPad->NewState.DPadLeft;
+ case 11: return pPad->NewState.DPadRight;
+ case 12: return pPad->NewState.Start;
+ case 13: return pPad->NewState.Select;
+ case 14: return pPad->NewState.Square;
+ case 15: return pPad->NewState.Triangle;
+ case 16: return pPad->NewState.Cross;
+ case 17: return pPad->NewState.Circle;
+ case 18: return pPad->NewState.LeftShock;
+ case 19: return pPad->NewState.RightShock;
+ default: break;
+ }
+ return 0;
+}
+
+
+void CTheScripts::PrintListSizes()
+{
+ int active = 0;
+ int idle = 0;
+
+ for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
+ active++;
+ for (CRunningScript* pScript = pIdleScripts; pScript; pScript = pScript->GetNext())
+ idle++;
+
+ debug("active: %d, idle: %d", active, idle);
+}
+
+uint32 DbgLineColour = 0x0000FFFF; // r = 0, g = 0, b = 255, a = 255
+
+void CTheScripts::DrawDebugSquare(float infX, float infY, float supX, float supY)
+{
+ CColPoint tmpCP;
+ CEntity* tmpEP;
+ CVector p1, p2, p3, p4;
+ p1 = CVector(infX, infY, -1000.0f);
+ CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p1.z = 2.0f + tmpCP.point.z;
+ p2 = CVector(supX, supY, -1000.0f);
+ CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p2.z = 2.0f + tmpCP.point.z;
+ p3 = CVector(infX, supY, -1000.0f);
+ CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p3.z = 2.0f + tmpCP.point.z;
+ p4 = CVector(supX, infY, -1000.0f);
+ CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p4.z = 2.0f + tmpCP.point.z;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour);
+}
+
+void CTheScripts::DrawDebugAngledSquare(float infX, float infY, float supX, float supY, float rotSupX, float rotSupY, float rotInfX, float rotInfY)
+{
+ CColPoint tmpCP;
+ CEntity* tmpEP;
+ CVector p1, p2, p3, p4;
+ p1 = CVector(infX, infY, -1000.0f);
+ CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p1.z = 2.0f + tmpCP.point.z;
+ p2 = CVector(supX, supY, -1000.0f);
+ CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p2.z = 2.0f + tmpCP.point.z;
+ p3 = CVector(rotSupX, rotSupY, -1000.0f);
+ CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p3.z = 2.0f + tmpCP.point.z;
+ p4 = CVector(rotInfX, rotInfY, -1000.0f);
+ CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);
+ p4.z = 2.0f + tmpCP.point.z;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour);
+}
+
+void CTheScripts::DrawDebugCube(float infX, float infY, float infZ, float supX, float supY, float supZ)
+{
+ CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, infY, infZ, supX, supY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, supY, infZ, infX, supY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, supY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, supY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, supY, supZ, infX, supY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, supY, supZ, supX, supY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, supY, infZ, DbgLineColour, DbgLineColour);
+}
+
+void CTheScripts::DrawDebugAngledCube(float infX, float infY, float infZ, float supX, float supY, float supZ, float rotSupX, float rotSupY, float rotInfX, float rotInfY)
+{
+ CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, infY, infZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, infZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, infY, supZ, rotSupX, rotSupY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, rotInfX, rotInfY, supY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, supZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour);
+ CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour);
+}
+
+void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2)
+{
+ if (NumScriptDebugLines >= MAX_NUM_STORED_LINES)
+ return;
+ aStoredLines[NumScriptDebugLines].vecInf = CVector(x1, y1, z1);
+ aStoredLines[NumScriptDebugLines].vecSup = CVector(x2, y2, z2);
+ aStoredLines[NumScriptDebugLines].color1 = col;
+ aStoredLines[NumScriptDebugLines++].color2 = col2;
+}
+
+void CTheScripts::RenderTheScriptDebugLines()
+{
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1);
+ for (int i = 0; i < NumScriptDebugLines; i++) {
+ CLines::RenderLineWithClipping(
+ aStoredLines[i].vecInf.x,
+ aStoredLines[i].vecInf.y,
+ aStoredLines[i].vecInf.z,
+ aStoredLines[i].vecSup.x,
+ aStoredLines[i].vecSup.y,
+ aStoredLines[i].vecSup.z,
+ aStoredLines[i].color1,
+ aStoredLines[i].color2);
+ }
+ NumScriptDebugLines = 0;
+ 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)
+
+void CTheScripts::SaveAllScripts(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ uint32 varSpace = GetSizeOfVariableSpace();
+ uint32 runningScripts = 0;
+ for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
+ runningScripts++;
+ *size = CRunningScript::nSaveStructSize * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32);
+ WriteSaveHeader(buf, 'S', 'C', 'R', '\0', *size - SAVE_HEADER_SIZE);
+ WriteSaveBuf(buf, varSpace);
+ for (uint32 i = 0; i < varSpace; i++)
+ WriteSaveBuf(buf, ScriptSpace[i]);
+#ifdef CHECK_STRUCT_SIZES
+ static_assert(SCRIPT_DATA_SIZE == 968, "CTheScripts::SaveAllScripts");
+#endif
+ 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;
+ uint32 type, handle;
+ if (!pBuilding) {
+ type = 0;
+ handle = 0;
+ } else if (pBuilding->GetIsATreadable()) {
+ type = 1;
+ handle = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pBuilding) + 1;
+ } else {
+ type = 2;
+ handle = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pBuilding) + 1;
+ }
+ WriteSaveBuf(buf, type);
+ WriteSaveBuf(buf, handle);
+ WriteSaveBuf(buf, BuildingSwapArray[i].m_nNewModel);
+ WriteSaveBuf(buf, BuildingSwapArray[i].m_nOldModel);
+ }
+ for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {
+ CEntity* pEntity = InvisibilitySettingArray[i];
+ uint32 type, handle;
+ if (!pEntity) {
+ type = 0;
+ handle = 0;
+ } else {
+ switch (pEntity->GetType()) {
+ case ENTITY_TYPE_BUILDING:
+ if (((CBuilding*)pEntity)->GetIsATreadable()) {
+ type = 1;
+ handle = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pEntity) + 1;
+ } else {
+ type = 2;
+ handle = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)pEntity) + 1;
+ }
+ break;
+ case ENTITY_TYPE_OBJECT:
+ type = 3;
+ handle = CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)pEntity) + 1;
+ break;
+ case ENTITY_TYPE_DUMMY:
+ type = 4;
+ handle = CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)pEntity) + 1;
+ default: break;
+ }
+ }
+ WriteSaveBuf(buf, type);
+ WriteSaveBuf(buf, handle);
+ }
+ WriteSaveBuf(buf, bUsingAMultiScriptFile);
+ WriteSaveBuf(buf, (uint8)0);
+ WriteSaveBuf(buf, (uint16)0);
+ WriteSaveBuf(buf, MainScriptSize);
+ WriteSaveBuf(buf, LargestMissionScriptSize);
+ WriteSaveBuf(buf, NumberOfMissionScripts);
+ WriteSaveBuf(buf, (uint16)0);
+ WriteSaveBuf(buf, runningScripts);
+ for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
+ pScript->Save(buf);
+VALIDATESAVEBUF(*size)
+}
+
+void CTheScripts::LoadAllScripts(uint8* buf, uint32 size)
+{
+ Init();
+INITSAVEBUF
+ CheckSaveHeader(buf, 'S', 'C', 'R', '\0', size - SAVE_HEADER_SIZE);
+ uint32 varSpace = ReadSaveBuf<uint32>(buf);
+ for (uint32 i = 0; i < varSpace; i++)
+ ScriptSpace[i] = ReadSaveBuf<uint8>(buf);
+ script_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);
+ uint32 handle = ReadSaveBuf<uint32>(buf);
+ switch (type) {
+ case 0:
+ BuildingSwapArray[i].m_pBuilding = nil;
+ break;
+ case 1:
+ BuildingSwapArray[i].m_pBuilding = CPools::GetTreadablePool()->GetSlot(handle - 1);
+ break;
+ case 2:
+ BuildingSwapArray[i].m_pBuilding = CPools::GetBuildingPool()->GetSlot(handle - 1);
+ break;
+ default:
+ script_assert(false);
+ }
+ BuildingSwapArray[i].m_nNewModel = ReadSaveBuf<uint32>(buf);
+ BuildingSwapArray[i].m_nOldModel = ReadSaveBuf<uint32>(buf);
+ if (BuildingSwapArray[i].m_pBuilding)
+ BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nNewModel);
+ }
+ for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {
+ uint32 type = ReadSaveBuf<uint32>(buf);
+ uint32 handle = ReadSaveBuf<uint32>(buf);
+ switch (type) {
+ case 0:
+ InvisibilitySettingArray[i] = nil;
+ break;
+ case 1:
+ InvisibilitySettingArray[i] = CPools::GetTreadablePool()->GetSlot(handle - 1);
+ break;
+ case 2:
+ InvisibilitySettingArray[i] = CPools::GetBuildingPool()->GetSlot(handle - 1);
+ break;
+ case 3:
+ InvisibilitySettingArray[i] = CPools::GetObjectPool()->GetSlot(handle - 1);
+ break;
+ case 4:
+ InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);
+ break;
+ default:
+ script_assert(false);
+ }
+ if (InvisibilitySettingArray[i])
+ InvisibilitySettingArray[i]->bIsVisible = false;
+ }
+ script_assert(ReadSaveBuf<bool>(buf) == bUsingAMultiScriptFile);
+ ReadSaveBuf<uint8>(buf);
+ ReadSaveBuf<uint16>(buf);
+ script_assert(ReadSaveBuf<uint32>(buf) == MainScriptSize);
+ script_assert(ReadSaveBuf<uint32>(buf) == LargestMissionScriptSize);
+ script_assert(ReadSaveBuf<uint16>(buf) == NumberOfMissionScripts);
+ ReadSaveBuf<uint16>(buf);
+ uint32 runningScripts = ReadSaveBuf<uint32>(buf);
+ for (uint32 i = 0; i < runningScripts; i++)
+ StartNewScript(0)->Load(buf);
+VALIDATESAVEBUF(size)
+}
+
+#undef SCRIPT_DATA_SIZE
+
+void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity)
+{
+ static CColPoint aTempColPoints[MAX_COLLISION_POINTS];
+ int16 entities = 0;
+ CEntity* aEntities[16];
+ CWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false);
+ if (entities <= 0)
+ return;
+ for (uint16 i = 0; i < entities; i++) {
+ if (aEntities[i] != pEntity && aEntities[i]->IsPed() && ((CPed*)aEntities[i])->bInVehicle)
+ aEntities[i] = nil;
+ }
+ for (uint16 i = 0; i < entities; i++) {
+ if (aEntities[i] == pEntity || !aEntities[i])
+ continue;
+ CEntity* pFound = aEntities[i];
+ int cols;
+ if (pEntity->GetColModel()->numLines <= 0)
+ cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
+ pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil);
+ else {
+ float lines[4];
+ lines[0] = lines[1] = lines[2] = lines[3] = 1.0f;
+ CColPoint tmp[4];
+ cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
+ pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines);
+ }
+ if (cols <= 0)
+ continue;
+ switch (pFound->GetType()) {
+ case ENTITY_TYPE_VEHICLE:
+ {
+ printf("Will try to delete a vehicle where a mission entity should be\n");
+ CVehicle* pVehicle = (CVehicle*)pFound;
+ if (pVehicle->bIsLocked || !pVehicle->CanBeDeleted())
+ break;
+ if (pVehicle->pDriver) {
+ CPopulation::RemovePed(pVehicle->pDriver);
+ pVehicle->pDriver = nil;
+ }
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ CPopulation::RemovePed(pVehicle->pPassengers[i]);
+ pVehicle->pPassengers[i] = 0;
+ pVehicle->m_nNumPassengers--;
+ }
+ }
+ CCarCtrl::RemoveFromInterestingVehicleList(pVehicle);
+ CWorld::Remove(pVehicle);
+ delete pVehicle;
+ break;
+ }
+ case ENTITY_TYPE_PED:
+ {
+ CPed* pPed = (CPed*)pFound;
+ if (pPed->IsPlayer() || !pPed->CanBeDeleted())
+ break;
+ CPopulation::RemovePed(pPed);
+ printf("Deleted a ped where a mission entity should be\n");
+ break;
+ }
+ default: break;
+ }
+ }
+}
+
+void CTheScripts::HighlightImportantArea(uint32 id, float x1, float y1, float x2, float y2, float z)
+{
+ float infX, infY, supX, supY;
+ if (x1 < x2) {
+ infX = x1;
+ supX = x2;
+ } else {
+ infX = x2;
+ supX = x1;
+ }
+ if (y1 < y2) {
+ infY = y1;
+ supY = y2;
+ }
+ else {
+ infY = y2;
+ supY = y1;
+ }
+ CVector center;
+ center.x = (infX + supX) / 2;
+ center.y = (infY + supY) / 2;
+ center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z;
+ CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, &center, supX - center.x, 0.0f, 0.0f, center.y - supY, 0);
+}
+
+void CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float z)
+{
+ float infX, infY, supX, supY, X, Y;
+ X = (x1 + x2) / 2;
+ Y = (y1 + y2) / 2;
+ supX = infX = X;
+ supY = infY = Y;
+ X = (x2 + x3) / 2;
+ Y = (y2 + y3) / 2;
+ infX = Min(infX, X);
+ supX = Max(supX, X);
+ infY = Min(infY, Y);
+ supY = Max(supY, Y);
+ X = (x3 + x4) / 2;
+ Y = (y3 + y4) / 2;
+ infX = Min(infX, X);
+ supX = Max(supX, X);
+ infY = Min(infY, Y);
+ supY = Max(supY, Y);
+ X = (x4 + x1) / 2;
+ Y = (y4 + y1) / 2;
+ infX = Min(infX, X);
+ supX = Max(supX, X);
+ infY = Min(infY, Y);
+ supY = Max(supY, Y);
+ CVector center;
+ center.x = (infX + supX) / 2;
+ center.y = (infY + supY) / 2;
+ center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z;
+ CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, &center, supX - center.x, 0.0f, 0.0f, center.y - supY, 0);
+}
+
+bool CTheScripts::IsPedStopped(CPed* pPed)
+{
+ if (pPed->bInVehicle)
+ return IsVehicleStopped(pPed->m_pMyVehicle);
+ return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL;
+}
+
+bool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer)
+{
+ CPed* pPed = pPlayer->m_pPed;
+ if (pPed->bInVehicle)
+ return IsVehicleStopped(pPed->m_pMyVehicle);
+ if (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP) ||
+ RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP_R) ||
+ RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_LAUNCH) ||
+ RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_GLIDE))
+ return false;
+ return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL;
+}
+
+bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
+{
+ return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;
+}
+
+void CTheScripts::CleanUpThisPed(CPed* pPed)
+{
+ if (!pPed)
+ return;
+ if (pPed->CharCreatedBy != MISSION_CHAR)
+ return;
+ pPed->CharCreatedBy = RANDOM_CHAR;
+ if (pPed->m_nPedType == PEDTYPE_PROSTITUTE)
+ pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ if (pPed->bInVehicle) {
+ if (pPed->m_pMyVehicle->pDriver == pPed) {
+ if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {
+ CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle);
+ pPed->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ }
+ }
+ else {
+ if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {
+ pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle);
+ pPed->bWanderPathAfterExitingCar = true;
+ }
+ }
+ }
+ bool flees = false;
+ PedState state;
+ eMoveState ms;
+ if (pPed->m_nPedState == PED_FLEE_ENTITY || pPed->m_nPedState == PED_FLEE_POS) {
+ ms = pPed->m_nMoveState;
+ state = pPed->m_nPedState;
+ flees = true;
+ }
+ pPed->ClearObjective();
+ pPed->bRespondsToThreats = true;
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->ClearLeader();
+ if (pPed->IsPedInControl())
+ pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ if (flees) {
+ pPed->m_nPedState = state;
+ pPed->SetMoveState(ms);
+ }
+ --CPopulation::ms_nTotalMissionPeds;
+}
+
+void CTheScripts::CleanUpThisVehicle(CVehicle* pVehicle)
+{
+ if (!pVehicle)
+ return;
+ if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE)
+ return;
+ pVehicle->bIsLocked = false;
+ CCarCtrl::RemoveFromInterestingVehicleList(pVehicle);
+ pVehicle->VehicleCreatedBy = RANDOM_VEHICLE;
+ ++CCarCtrl::NumRandomCars;
+ --CCarCtrl::NumMissionCars;
+}
+
+void CTheScripts::CleanUpThisObject(CObject* pObject)
+{
+ if (!pObject)
+ return;
+ if (pObject->ObjectCreatedBy != MISSION_OBJECT)
+ return;
+ pObject->ObjectCreatedBy = TEMP_OBJECT;
+ pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;
+ pObject->m_nRefModelIndex = -1;
+ pObject->bUseVehicleColours = false;
+ ++CObject::nNoTempObjects;
+}
+
+void CTheScripts::ReadObjectNamesFromScript()
+{
+ int32 varSpace = GetSizeOfVariableSpace();
+ uint32 ip = varSpace + 8;
+ NumberOfUsedObjects = Read2BytesFromScript(&ip);
+ ip += 2;
+ for (uint16 i = 0; i < NumberOfUsedObjects; i++) {
+ for (int j = 0; j < USED_OBJECT_NAME_LENGTH; j++)
+ UsedObjectArray[i].name[j] = ScriptSpace[ip++];
+ UsedObjectArray[i].index = 0;
+ }
+}
+
+void CTheScripts::UpdateObjectIndices()
+{
+ char name[USED_OBJECT_NAME_LENGTH];
+ char error[112];
+ for (int i = 1; i < NumberOfUsedObjects; i++) {
+ bool found = false;
+ for (int j = 0; j < MODELINFOSIZE && !found; j++) {
+ CBaseModelInfo* pModel = CModelInfo::GetModelInfo(j);
+ if (!pModel)
+ continue;
+ strcpy(name, pModel->GetName());
+#ifdef FIX_BUGS
+ for (int k = 0; k < USED_OBJECT_NAME_LENGTH && name[k]; k++)
+#else
+ for (int k = 0; k < USED_OBJECT_NAME_LENGTH; k++)
+#endif
+ name[k] = toupper(name[k]);
+ if (strcmp(name, UsedObjectArray[i].name) == 0) {
+ found = true;
+ UsedObjectArray[i].index = j;
+ }
+ }
+ if (!found) {
+ sprintf(error, "CTheScripts::UpdateObjectIndices - Couldn't find %s", UsedObjectArray[i].name);
+ debug("%s\n", error);
+ }
+ }
+}
+
+void CTheScripts::ReadMultiScriptFileOffsetsFromScript()
+{
+ int32 varSpace = GetSizeOfVariableSpace();
+ uint32 ip = varSpace + 3;
+ int32 objectSize = Read4BytesFromScript(&ip);
+ ip = objectSize + 8;
+ MainScriptSize = Read4BytesFromScript(&ip);
+ LargestMissionScriptSize = Read4BytesFromScript(&ip);
+ NumberOfMissionScripts = Read2BytesFromScript(&ip);
+ ip += 2;
+ for (int i = 0; i < NumberOfMissionScripts; i++) {
+ MultiScriptArray[i] = Read4BytesFromScript(&ip);
+ }
+}
diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp
new file mode 100644
index 00000000..acd9e424
--- /dev/null
+++ b/src/control/Script6.cpp
@@ -0,0 +1,1343 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "CarCtrl.h"
+#include "Cranes.h"
+#include "Credits.h"
+#include "CutsceneMgr.h"
+#include "DMAudio.h"
+#include "FileMgr.h"
+#include "Fire.h"
+#include "Frontend.h"
+#include "Garages.h"
+#include "General.h"
+#ifdef MISSION_REPLAY
+#include "GenericGameStorage.h"
+#endif
+#include "Messages.h"
+#include "Pad.h"
+#include "Particle.h"
+#include "Phones.h"
+#include "Population.h"
+#include "Pools.h"
+#include "Record.h"
+#include "Remote.h"
+#include "Restart.h"
+#include "SpecialFX.h"
+#include "Stats.h"
+#include "Streaming.h"
+#include "Weather.h"
+#include "Zones.h"
+#include "main.h"
+
+int8 CRunningScript::ProcessCommands1000To1099(int32 command)
+{
+#ifdef GTA_PS2
+ char tmp[48];
+#endif
+ switch (command) {
+ //case COMMAND_FLASH_RADAR_BLIP:
+ case COMMAND_IS_CHAR_IN_CONTROL:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(pPed->IsPedInControl());
+ return 0;
+ }
+ case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA:
+ CollectParameters(&m_nIp, 1);
+ CCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0);
+ return 0;
+ case COMMAND_CLEAR_SMALL_PRINTS:
+ CMessages::ClearSmallMessagesOnly();
+ return 0;
+ case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS:
+ UpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane());
+ return 0;
+ case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ pCar->bNotDamagedUpsideDown = (ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_CAN_PLAYER_START_MISSION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPlayerPed);
+ UpdateCompareFlag(pPlayerPed->IsPedInControl() || pPlayerPed->m_nPedState == PED_DRIVING);
+ return 0;
+ }
+ case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE:
+ {
+ CollectParameters(&m_nIp, 1);
+#ifdef MISSION_REPLAY
+ AllowMissionReplay = 0;
+ SaveGameForPause(3);
+#endif
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ CPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE);
+ pPlayerInfo->MakePlayerSafe(true);
+ CCutsceneMgr::StartCutsceneProcessing();
+ return 0;
+ }
+ case COMMAND_USE_TEXT_COMMANDS:
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::UseTextCommands = (ScriptParams[0] != 0) ? 2 : 1;
+ return 0;
+ case COMMAND_SET_THREAT_FOR_PED_TYPE:
+ CollectParameters(&m_nIp, 2);
+ CPedType::AddThreat(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_CLEAR_THREAT_FOR_PED_TYPE:
+ CollectParameters(&m_nIp, 2);
+ CPedType::RemoveThreat(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_GET_CAR_COLOURS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ ScriptParams[0] = pVehicle->m_currentColour1;
+ ScriptParams[1] = pVehicle->m_currentColour2;
+ StoreParameters(&m_nIp, 2);
+ return 0;
+ }
+ case COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED:
+ CollectParameters(&m_nIp, 1);
+ CWorld::SetAllCarsCanBeDamaged(ScriptParams[0] != 0);
+ if (!ScriptParams[0])
+ CWorld::ExtinguishAllCarFiresInArea(FindPlayerCoors(), 4000.0f);
+ return 0;
+ case COMMAND_SET_CAR_CAN_BE_DAMAGED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ pVehicle->bCanBeDamaged = ScriptParams[1] != 0;
+ if (!ScriptParams[1])
+ pVehicle->ExtinguishCarFire();
+ return 0;
+ }
+ //case COMMAND_MAKE_PLAYER_UNSAFE:
+ case COMMAND_LOAD_COLLISION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTimer::Stop();
+ CGame::currLevel = (eLevelName)ScriptParams[0];
+ ISLAND_LOADING_IS(LOW)
+ {
+ CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
+ CStreaming::RemoveUnusedBuildings(CGame::currLevel);
+ }
+ CCollision::SortOutCollisionAfterLoad();
+ ISLAND_LOADING_ISNT(HIGH)
+ {
+ CStreaming::RequestIslands(CGame::currLevel);
+ CStreaming::LoadAllRequestedModels(true);
+ }
+ CTimer::Update();
+ return 0;
+ }
+ case COMMAND_GET_BODY_CAST_HEALTH:
+ ScriptParams[0] = CObject::nBodyCastHealth;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SET_CHARS_CHATTING:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed1 = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed* pPed2 = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pPed1 && pPed2);
+ pPed1->SetChat(pPed2, ScriptParams[2]);
+ pPed2->SetChat(pPed1, ScriptParams[2]);
+ return 0;
+ }
+ //case COMMAND_MAKE_PLAYER_SAFE:
+ case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ if (ScriptParams[1])
+ pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
+ else
+ pVehicle->m_nZoneLevel = LEVEL_GENERIC;
+ return 0;
+ }
+ case COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1])
+ pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
+ else
+ pPed->m_nZoneLevel = LEVEL_GENERIC;
+ return 0;
+ }
+ case COMMAND_REGISTER_4X4_ONE_TIME:
+ CollectParameters(&m_nIp, 1);
+ CStats::Register4x4OneTime(ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_4X4_TWO_TIME:
+ CollectParameters(&m_nIp, 1);
+ CStats::Register4x4TwoTime(ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_4X4_THREE_TIME:
+ CollectParameters(&m_nIp, 1);
+ CStats::Register4x4ThreeTime(ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_4X4_MAYHEM_TIME:
+ CollectParameters(&m_nIp, 1);
+ CStats::Register4x4MayhemTime(ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_LIFE_SAVED:
+ CStats::AnotherLifeSavedWithAmbulance();
+ return 0;
+ case COMMAND_REGISTER_CRIMINAL_CAUGHT:
+ CStats::AnotherCriminalCaught();
+ return 0;
+ case COMMAND_REGISTER_AMBULANCE_LEVEL:
+ CollectParameters(&m_nIp, 1);
+ CStats::RegisterLevelAmbulanceMission(ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_FIRE_EXTINGUISHED:
+ CStats::AnotherFireExtinguished();
+ return 0;
+ case COMMAND_TURN_PHONE_ON:
+ CollectParameters(&m_nIp, 1);
+ gPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9;
+ return 0;
+ case COMMAND_REGISTER_LONGEST_DODO_FLIGHT:
+ CollectParameters(&m_nIp, 1);
+ CStats::RegisterLongestFlightInDodo(ScriptParams[0]);
+ return 0;
+ case COMMAND_REGISTER_DEFUSE_BOMB_TIME:
+ CollectParameters(&m_nIp, 1);
+ CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:
+ CollectParameters(&m_nIp, 1);
+ CStats::SetTotalNumberKillFrenzies(ScriptParams[0]);
+ return 0;
+ case COMMAND_BLOW_UP_RC_BUGGY:
+ CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy();
+ return 0;
+ case COMMAND_REMOVE_CAR_FROM_CHASE:
+ CollectParameters(&m_nIp, 1);
+ CRecordDataForChase::RemoveCarFromChase(ScriptParams[0]);
+ return 0;
+ case COMMAND_IS_FRENCH_GAME:
+ UpdateCompareFlag(CGame::frenchGame);
+ return 0;
+ case COMMAND_IS_GERMAN_GAME:
+ UpdateCompareFlag(CGame::germanGame);
+ return 0;
+ case COMMAND_CLEAR_MISSION_AUDIO:
+ DMAudio.ClearMissionAudio();
+ return 0;
+ case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST:
+ CollectParameters(&m_nIp, 1);
+ CRestart::bFadeInAfterNextArrest = !!ScriptParams[0];
+ return 0;
+ case COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH:
+ CollectParameters(&m_nIp, 1);
+ CRestart::bFadeInAfterNextDeath = !!ScriptParams[0];
+ return 0;
+ case COMMAND_SET_GANG_PED_MODEL_PREFERENCE:
+ CollectParameters(&m_nIp, 2);
+ CGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_SET_CHAR_USE_PEDNODE_SEEK:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1])
+ pPed->m_pNextPathNode = nil;
+ pPed->bUsePedNodeSeek = !!ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SWITCH_VEHICLE_WEAPONS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bGunSwitchedOff = !ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_GET_OUT_OF_JAIL_FREE:
+ CollectParameters(&m_nIp, 2);
+ CWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1];
+ return 0;
+ case COMMAND_SET_FREE_HEALTH_CARE:
+ CollectParameters(&m_nIp, 2);
+ CWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1];
+ return 0;
+ case COMMAND_IS_CAR_DOOR_CLOSED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1]));
+ return 0;
+ }
+ case COMMAND_LOAD_AND_LAUNCH_MISSION:
+ return 0;
+ case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL:
+ {
+ CollectParameters(&m_nIp, 1);
+#ifdef MISSION_REPLAY
+ missionRetryScriptIndex = ScriptParams[0];
+ if (missionRetryScriptIndex == 19)
+ CStats::LastMissionPassedName[0] = '\0';
+#endif
+ CTimer::Suspend();
+ int offset = CTheScripts::MultiScriptArray[ScriptParams[0]];
+ CFileMgr::ChangeDir("\\");
+ int handle = CFileMgr::OpenFile("data\\main.scm", "rb");
+ CFileMgr::Seek(handle, offset, 0);
+ CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);
+ CFileMgr::CloseFile(handle);
+ CRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT);
+ CTimer::Resume();
+ pMissionScript->m_bIsMissionScript = true;
+ pMissionScript->m_bMissionFlag = true;
+ CTheScripts::bAlreadyRunningAMissionScript = true;
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_DRAW_LAST:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->bDrawLast = !!ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_AMMO_IN_PLAYER_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]];
+ if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1])
+ ScriptParams[0] = pWeaponSlot->m_nAmmoTotal;
+ else
+ ScriptParams[0] = 0;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_AMMO_IN_CHAR_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]];
+ if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1])
+ ScriptParams[0] = pWeaponSlot->m_nAmmoTotal;
+ else
+ ScriptParams[0] = 0;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_REGISTER_KILL_FRENZY_PASSED:
+ CStats::AnotherKillFrenzyPassed();
+ return 0;
+ case COMMAND_SET_CHAR_SAY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ switch (ScriptParams[1]) {
+ case SCRIPT_SOUND_CHUNKY_RUN_SHOUT:
+ pPed->Say(SOUND_PED_FLEE_RUN);
+ break;
+ case SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT:
+ pPed->Say(SOUND_PED_FLEE_RUN);
+ break;
+ case SCRIPT_SOUND_SWAT_PED_SHOUT:
+ pPed->Say(SOUND_PED_PURSUIT_SWAT);
+ break;
+ case SCRIPT_SOUND_AMMUNATION_CHAT_1:
+ pPed->Say(SOUND_AMMUNATION_WELCOME_1);
+ break;
+ case SCRIPT_SOUND_AMMUNATION_CHAT_2:
+ pPed->Say(SOUND_AMMUNATION_WELCOME_2);
+ break;
+ case SCRIPT_SOUND_AMMUNATION_CHAT_3:
+ pPed->Say(SOUND_AMMUNATION_WELCOME_3);
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+ case COMMAND_SET_NEAR_CLIP:
+ CollectParameters(&m_nIp, 1);
+ TheCamera.SetNearClipScript(*(float*)&ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_RADIO_CHANNEL:
+ CollectParameters(&m_nIp, 2);
+ DMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_OVERRIDE_HOSPITAL_LEVEL:
+ CollectParameters(&m_nIp, 1);
+ CRestart::OverrideHospitalLevel = ScriptParams[0];
+ return 0;
+ case COMMAND_OVERRIDE_POLICE_STATION_LEVEL:
+ CollectParameters(&m_nIp, 1);
+ CRestart::OverridePoliceStationLevel = ScriptParams[0];
+ return 0;
+ case COMMAND_FORCE_RAIN:
+ CollectParameters(&m_nIp, 1);
+ CWeather::bScriptsForceRain = !!ScriptParams[0];
+ return 0;
+ case COMMAND_DOES_GARAGE_CONTAIN_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle));
+ return 0;
+ }
+ case COMMAND_SET_CAR_TRACTION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ float fTraction = *(float*)&ScriptParams[1];
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR || pVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ if (pVehicle->m_vehType == VEHICLE_TYPE_CAR)
+ ((CAutomobile*)pVehicle)->m_fTraction = fTraction;
+ else
+ // this is certainly not a boat, trane, heli or plane field
+ //((CBike*)pVehicle)->m_fTraction = fTraction;
+ *(float*)(((char*)pVehicle) + 1088) = fTraction;
+ return 0;
+ }
+ case COMMAND_ARE_MEASUREMENTS_IN_METRES:
+#ifdef USE_MEASUREMENTS_IN_METERS
+ UpdateCompareFlag(true);
+#else
+ UpdateCompareFlag(false)
+#endif
+ return 0;
+ case COMMAND_CONVERT_METRES_TO_FEET:
+ {
+ CollectParameters(&m_nIp, 1);
+ float fMeterValue = *(float*)&ScriptParams[0];
+ float fFeetValue = fMeterValue / METERS_IN_FOOT;
+ *(float*)&ScriptParams[0] = fFeetValue;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_MARK_ROADS_BETWEEN_LEVELS:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ ThePaths.MarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);
+ return 0;
+ }
+ case COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ ThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);
+ return 0;
+ }
+ case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pPed);
+ // not implemented
+ return 0;
+ }
+ case COMMAND_IS_THREAT_FOR_PED_TYPE:
+ CollectParameters(&m_nIp, 2);
+ UpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1]));
+ return 0;
+ case COMMAND_CLEAR_AREA_OF_CHARS:
+ {
+ CollectParameters(&m_nIp, 6);
+ 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];
+ }
+ CWorld::ClearPedsFromArea(infX, infY, infZ, supX, supY, supZ);
+ return 0;
+ }
+ case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS:
+ CollectParameters(&m_nIp, 1);
+ CStats::SetTotalNumberMissions(ScriptParams[0]);
+ return 0;
+ case COMMAND_CONVERT_METRES_TO_FEET_INT:
+ CollectParameters(&m_nIp, 1);
+ ScriptParams[0] *= FEET_IN_METER;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_REGISTER_FASTEST_TIME:
+ CollectParameters(&m_nIp, 2);
+ CStats::RegisterFastestTime(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_REGISTER_HIGHEST_SCORE:
+ CollectParameters(&m_nIp, 2);
+ CStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ //case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER:
+ //case COMMAND_IS_CAR_PASSENGER_SEAT_FREE:
+ case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(ScriptParams[1] >= 0 && ScriptParams[1] < ARRAY_SIZE(pVehicle->pPassengers));
+ CPed* pPassenger = pVehicle->pPassengers[ScriptParams[1]];
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPassenger);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bChrisCriminal = !!ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_START_CREDITS:
+ CCredits::Start();
+ return 0;
+ case COMMAND_STOP_CREDITS:
+ CCredits::Stop();
+ return 0;
+ case COMMAND_ARE_CREDITS_FINISHED:
+ UpdateCompareFlag(CCredits::AreCreditsDone());
+ return 0;
+ case COMMAND_CREATE_SINGLE_PARTICLE:
+ CollectParameters(&m_nIp, 8);
+ CParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1],
+ *(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0);
+ return 0;
+ case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1])
+ pPed->m_nZoneLevel = LEVEL_IGNORE;
+ else
+ pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
+ return 0;
+ }
+ case COMMAND_GET_CHASE_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CRecordDataForChase::TurnChaseCarIntoScriptCar(ScriptParams[0]);
+ ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CAR);
+ return 0;
+ }
+ case COMMAND_START_BOAT_FOAM_ANIMATION:
+ CSpecialParticleStuff::StartBoatFoamAnimation();
+ return 0;
+ case COMMAND_UPDATE_BOAT_FOAM_ANIMATION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix());
+ return 0;
+ }
+ case COMMAND_SET_MUSIC_DOES_FADE:
+ CollectParameters(&m_nIp, 1);
+ TheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0);
+ return 0;
+ case COMMAND_SET_INTRO_IS_PLAYING:
+ CollectParameters(&m_nIp, 1);
+ if (ScriptParams[0]) {
+ CGame::playingIntro = true;
+ CStreaming::RemoveCurrentZonesModels();
+ } else {
+ CGame::playingIntro = false;
+ DMAudio.ChangeMusicMode(MUSICMODE_GAME);
+ int mi;
+ CModelInfo::GetModelInfo("bridgefukb", &mi);
+ CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
+ CStreaming::LoadAllRequestedModels(false);
+ }
+ return 0;
+ case COMMAND_SET_PLAYER_HOOKER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ if (ScriptParams[1] < 0) {
+ pPlayerInfo->m_pHooker = nil;
+ pPlayerInfo->m_nNextSexFrequencyUpdateTime = 0;
+ pPlayerInfo->m_nNextSexMoneyUpdateTime = 0;
+ } else {
+ CPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pHooker);
+ pPlayerInfo->m_pHooker = (CCivilianPed*)pHooker;
+ pPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
+ pPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
+ }
+ return 0;
+ }
+ case COMMAND_PLAY_END_OF_GAME_TUNE:
+ DMAudio.PlayPreloadedCutSceneMusic();
+ return 0;
+ case COMMAND_STOP_END_OF_GAME_TUNE:
+ DMAudio.StopCutSceneMusic();
+ DMAudio.ChangeMusicMode(MUSICMODE_GAME);
+ return 0;
+ case COMMAND_GET_CAR_MODEL:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ ScriptParams[0] = pVehicle->GetModelIndex();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_SITTING_IN_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING);
+ return 0;
+ }
+ case COMMAND_SET_SCRIPT_FIRE_AUDIO:
+ CollectParameters(&m_nIp, 2);
+ gFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]);
+ return 0;
+ case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED:
+ UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3);
+ return 0;
+ case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bNoCriticalHits = (ScriptParams[0] == 0);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_LIFTING_A_PHONE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_SITTING_IN_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER &&
+ pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_ON_FOOT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER &&
+ pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
+ return 0;
+ }
+#ifndef GTA_PS2
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands1100To1199(int32 command)
+{
+ char tmp[48];
+ switch (command) {
+#endif
+ case COMMAND_LOAD_COLLISION_WITH_SCREEN:
+ CollectParameters(&m_nIp, 1);
+ CTimer::Stop();
+ CGame::currLevel = (eLevelName)ScriptParams[0];
+ if (CGame::currLevel != CCollision::ms_collisionInMemory) {
+ ISLAND_LOADING_IS(LOW)
+ {
+ DMAudio.SetEffectsFadeVol(0);
+ CPad::StopPadsShaking();
+ CCollision::LoadCollisionScreen(CGame::currLevel);
+ DMAudio.Service();
+ }
+ CPopulation::DealWithZoneChange(CCollision::ms_collisionInMemory, CGame::currLevel, false);
+
+ ISLAND_LOADING_IS(LOW)
+ {
+ CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
+ CStreaming::RemoveUnusedBuildings(CGame::currLevel);
+ }
+ CCollision::SortOutCollisionAfterLoad();
+
+ ISLAND_LOADING_ISNT(HIGH)
+ CStreaming::RequestIslands(CGame::currLevel);
+
+ ISLAND_LOADING_IS(LOW)
+ CStreaming::RequestBigBuildings(CGame::currLevel);
+
+ ISLAND_LOADING_ISNT(HIGH)
+ CStreaming::LoadAllRequestedModels(true);
+
+ ISLAND_LOADING_IS(LOW)
+ DMAudio.SetEffectsFadeVol(127);
+ }
+ CTimer::Update();
+ return 0;
+ case COMMAND_LOAD_SPLASH_SCREEN:
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ tmp[i] = tolower(tmp[i]);
+ m_nIp += 8;
+ LoadSplash(tmp);
+ return 0;
+ case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ if (ScriptParams[1])
+ pVehicle->m_nZoneLevel = LEVEL_IGNORE;
+ else
+ pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
+ return 0;
+ }
+ case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ pCar->bMoreResistantToDamage = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), false);
+ return 0;
+ }
+ case COMMAND_LOAD_END_OF_GAME_TUNE:
+ DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
+ printf("Start preload end of game audio\n");
+ DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED);
+ printf("End preload end of game audio\n");
+ return 0;
+ case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA);
+ 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);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CWorld::Remove(pObject);
+ pObject->SetOrientation(
+ DEGTORAD(*(float*)&ScriptParams[1]),
+ DEGTORAD(*(float*)&ScriptParams[2]),
+ DEGTORAD(*(float*)&ScriptParams[3]));
+ pObject->GetMatrix().UpdateRW();
+ pObject->UpdateRwFrame();
+ CWorld::Add(pObject);
+ return 0;
+ }
+ case COMMAND_GET_DEBUG_CAMERA_COORDINATES:
+ *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR:
+ *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CEntity* pTarget = pPed->m_pPointGunAt;
+ UpdateCompareFlag(pTarget && pTarget->IsPed());
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_TARGETTING_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTestedPed);
+ CEntity* pTarget = pPed->m_pPointGunAt;
+ UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_TARGETTING_OBJECT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CObject* pTestedObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ script_assert(pTestedObject);
+ CEntity* pTarget = pPed->m_pPointGunAt;
+ UpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject);
+ return 0;
+ }
+ case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME:
+ {
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ tmp[i] = tolower(tmp[i]);
+ m_nIp += 8;
+ CRunningScript* pScript = CTheScripts::pActiveScripts;
+ while (pScript) {
+ CRunningScript* pNext = pScript->next;
+ if (strcmp(pScript->m_abScriptName, tmp) == 0) {
+ pScript->RemoveScriptFromList(&CTheScripts::pActiveScripts);
+ pScript->AddScriptToList(&CTheScripts::pIdleScripts);
+ }
+ pScript = pNext;
+ }
+ return 0;
+ }
+ case COMMAND_DISPLAY_TEXT_WITH_NUMBER:
+ {
+ CollectParameters(&m_nIp, 2);
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
+ CollectParameters(&m_nIp, 1);
+ CMessages::InsertNumberInString(text, ScriptParams[0], -1, -1, -1, -1, -1,
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text);
+ return 0;
+ }
+ case COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS:
+ {
+ CollectParameters(&m_nIp, 2);
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
+ CollectParameters(&m_nIp, 2);
+ CMessages::InsertNumberInString(text, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1,
+ CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text);
+ return 0;
+ }
+ case COMMAND_FAIL_CURRENT_MISSION:
+ CTheScripts::FailCurrentMission = 2;
+ return 0;
+ case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float range = *(float*)&ScriptParams[3];
+ int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];
+ int16 total;
+ CEntity* apEntities[16];
+ CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true);
+ CEntity* pClosestEntity = nil;
+ float min_dist = 2.0f * range;
+ for (int i = 0; i < total; i++) {
+ float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
+ if (dist < min_dist) {
+ min_dist = dist;
+ pClosestEntity = apEntities[i];
+ }
+ }
+ if (pClosestEntity && pClosestEntity->IsDummy()) {
+ CPopulation::ConvertToRealObject((CDummyObject*)pClosestEntity);
+ CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true);
+ pClosestEntity = nil;
+ float min_dist = 2.0f * range;
+ for (int i = 0; i < total; i++) {
+ float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
+ if (dist < min_dist) {
+ min_dist = dist;
+ pClosestEntity = apEntities[i];
+ }
+ }
+ if (pClosestEntity->IsDummy())
+ pClosestEntity = nil;
+ }
+ if (pClosestEntity) {
+ script_assert(pClosestEntity->IsObject());
+ CObject* pObject = (CObject*)pClosestEntity;
+ pObject->ObjectCreatedBy = MISSION_OBJECT;
+ ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObject);
+ } else {
+ ScriptParams[0] = -1;
+ }
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT:
+ {
+ CollectParameters(&m_nIp, 5);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ script_assert(pTarget);
+ CVector offset = *(CVector*)&ScriptParams[2];
+ CPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset);
+ return 0;
+ }
+ case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ if (pVehicle->pDriver) {
+ pVehicle->pDriver->bScriptObjectiveCompleted = false;
+ pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, 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_CAR, pVehicle);
+ }
+ }
+ return 0;
+ }
+ case COMMAND_SET_INTERPOLATION_PARAMETERS:
+ CollectParameters(&m_nIp, 2);
+ TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float destX = *(float*)&ScriptParams[3];
+ float destY = *(float*)&ScriptParams[4];
+ int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
+ CPathNode* pNode = &ThePaths.m_pathNodes[nid];
+ *(CVector*)&ScriptParams[0] = pNode->GetPosition();
+ *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true);
+ StoreParameters(&m_nIp, 4);
+ return 0;
+ }
+ case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float destX = *(float*)&ScriptParams[3];
+ float destY = *(float*)&ScriptParams[4];
+ int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
+ CPathNode* pNode = &ThePaths.m_pathNodes[nid];
+ *(CVector*)&ScriptParams[0] = pNode->GetPosition();
+ *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false);
+ StoreParameters(&m_nIp, 4);
+ return 0;
+ }
+ case COMMAND_GET_DEBUG_CAMERA_POINT_AT:
+ *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ case COMMAND_ATTACH_CHAR_TO_CAR:
+ // empty implementation
+ return 0;
+ case COMMAND_DETACH_CHAR_FROM_CAR:
+ // empty implementation
+ return 0;
+ case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->AutoPilot.m_bStayInFastLane = !ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_lastWepDam = -1;
+ return 0;
+ }
+ case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ pVehicle->m_nLastWeaponDamage = -1;
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_COP_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 4);
+ int ped_handle = -1;
+ CVector pos = FindPlayerCoors();
+ float x1 = *(float*)&ScriptParams[0];
+ float y1 = *(float*)&ScriptParams[1];
+ float x2 = *(float*)&ScriptParams[2];
+ float y2 = *(float*)&ScriptParams[3];
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i && ped_handle == -1) {
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+ continue;
+ if (pPed->m_nPedType != PEDTYPE_COP)
+ continue;
+ if (pPed->CharCreatedBy != RANDOM_CHAR)
+ continue;
+ if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)
+ continue;
+ if (pPed->bRemoveFromWorld)
+ continue;
+ if (pPed->bFadeOut)
+ continue;
+ if (pPed->bIsLeader || pPed->m_leader)
+ continue;
+ if (!pPed->IsWithinArea(x1, y1, x2, y2))
+ continue;
+ if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ continue;
+ if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ continue;
+ ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+ CTheScripts::LastRandomPedId = ped_handle;
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ ++CPopulation::ms_nTotalMissionPeds;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ }
+ ScriptParams[0] = ped_handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_COP_IN_ZONE:
+ {
+ char zone[KEY_LENGTH_IN_SCRIPT];
+ strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ if (nZone != -1)
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CZone* pZone = CTheZones::GetZone(nZone);
+ int ped_handle = -1;
+ CVector pos = FindPlayerCoors();
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i && ped_handle == -1) {
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+ continue;
+ if (pPed->m_nPedType != PEDTYPE_COP)
+ continue;
+ if (pPed->CharCreatedBy != RANDOM_CHAR)
+ continue;
+ if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)
+ continue;
+ if (pPed->bRemoveFromWorld)
+ continue;
+ if (pPed->bFadeOut)
+ continue;
+ if (pPed->bIsLeader || pPed->m_leader)
+ continue;
+ if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))
+ continue;
+ if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ continue;
+ if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ continue;
+ ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+ CTheScripts::LastRandomPedId = ped_handle;
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ ++CPopulation::ms_nTotalMissionPeds;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ }
+ ScriptParams[0] = ped_handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_FLEE_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_FLEE_CAR, pVehicle);
+ return 0;
+ }
+ case COMMAND_GET_DRIVER_OF_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CPed* pDriver = pVehicle->pDriver;
+ if (pDriver)
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pDriver);
+ else
+ ScriptParams[0] = -1;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_NUMBER_OF_FOLLOWERS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pLeader);
+ int total = 0;
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i) {
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (pPed->m_leader == pLeader)
+ total++;
+ }
+ ScriptParams[0] = total;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), ScriptParams[5]);
+ return 0;
+ }
+ case COMMAND_GET_CURRENT_PLAYER_WEAPON:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_CURRENT_CHAR_WEAPON:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:
+ case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:
+ case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
+ case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
+ 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
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNRIGHT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CAR_HANDBRAKE_STOP:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_IS_CHAR_ON_ANY_BIKE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ return 0;
+ }
+ case COMMAND_LOCATE_SNIPER_BULLET_2D:
+ case COMMAND_LOCATE_SNIPER_BULLET_3D:
+ LocateSniperBulletCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL:
+ CollectParameters(&m_nIp, 1);
+ ScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_IS_PLAYER_ON_ANY_BIKE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_LYING_DOWN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bFallenDown);
+ return 0;
+ }
+ case COMMAND_CAN_CHAR_SEE_DEAD_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ int pedtype = ScriptParams[1];
+ bool can = false;
+ for (int i = 0; i < pPed->m_numNearPeds; i++) {
+ CPed* pTestPed = pPed->m_nearPeds[i];
+ if (pTestPed->m_fHealth <= 0.0f && pTestPed->m_nPedType == pedtype && pPed->OurPedCanSeeThisOne(pTestPed))
+ can = true;
+ }
+ UpdateCompareFlag(can);
+ return 0;
+ }
+ 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
+#if GTA_VERSION < GTA3_PC_11
+ 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
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h
index 56908edb..b9067bea 100644
--- a/src/control/ScriptCommands.h
+++ b/src/control/ScriptCommands.h
@@ -1156,7 +1156,7 @@ enum {
COMMAND_IS_CHAR_LYING_DOWN,
COMMAND_CAN_CHAR_SEE_DEAD_CHAR,
COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER,
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER,
#endif
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp
index c8d8cb56..b8354d93 100644
--- a/src/core/AnimViewer.cpp
+++ b/src/core/AnimViewer.cpp
@@ -49,7 +49,7 @@ CAnimViewer::Render(void) {
if (pTarget) {
#ifdef FIX_BUGS
#ifdef PED_SKIN
- if(pTarget->IsPed())
+ if(pTarget->IsPed() && IsClumpSkinned(pTarget->GetClump()))
((CPed*)pTarget)->UpdateRpHAnim();
#endif
#endif
@@ -100,6 +100,9 @@ CAnimViewer::Initialise(void) {
CRadar::Initialise();
CRadar::LoadTextures();
CVehicleModelInfo::LoadVehicleColours();
+#ifdef FIX_BUGS
+ CVehicleModelInfo::LoadEnvironmentMaps();
+#endif
CAnimManager::LoadAnimFiles();
CWorld::PlayerInFocus = 0;
CWeapon::InitialiseWeapons();
@@ -294,7 +297,12 @@ CAnimViewer::Update(void)
if (pTarget->IsVehicle() || pTarget->IsPed() || pTarget->IsObject()) {
((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
}
+#ifdef FIX_BUGS
+ // so we don't end up in the water
+ pTarget->GetMatrix().GetPosition().z = 10.0f;
+#else
pTarget->GetMatrix().GetPosition().z = 0.0f;
+#endif
if (modelInfo->GetModelType() == MITYPE_PED) {
((CPed*)pTarget)->bKindaStayInSamePlace = true;
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index 3e016667..b20e6db3 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -263,9 +263,11 @@ CCam::Process(void)
case MODE_FIGHT_CAM_RUNABOUT:
Process_1rstPersonPedOnPC(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
+#ifdef GTA_SCENE_EDIT
case MODE_EDITOR:
Process_Editor(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
+#endif
default:
Source = CVector(0.0f, 0.0f, 0.0f);
Front = CVector(0.0f, 1.0f, 0.0f);
@@ -2570,7 +2572,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
ResetStatics = false;
}
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
Source = HeadPos;
Source.z += 0.1f;
@@ -2605,7 +2607,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
HeadPos.x = 0.0f;
HeadPos.y = 0.0f;
HeadPos.z = 0.0f;
@@ -3919,6 +3921,7 @@ CCam::Process_Debug(const CVector&, float, float, float)
}
#endif
+#ifdef GTA_SCENE_EDIT
void
CCam::Process_Editor(const CVector&, float, float, float)
{
@@ -3997,6 +4000,7 @@ CCam::Process_Editor(const CVector&, float, float, float)
sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
}
}
+#endif
void
CCam::Process_ModelView(const CVector &CameraTarget, float, float, float)
@@ -4010,6 +4014,12 @@ CCam::Process_ModelView(const CVector &CameraTarget, float, float, float)
Distance += CPad::GetPad(0)->GetLeftStickY()/1000.0f;
else
Distance += CPad::GetPad(0)->GetLeftStickY() * ((Distance - 10.0f)/20.0f + 1.0f) / 1000.0f;
+#ifdef IMPROVED_CAMERA
+ if(CPad::GetPad(0)->GetLeftMouse()){
+ Distance += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f);
+ Angle += DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f);
+ }
+#endif
if(Distance < 1.5f)
Distance = 1.5f;
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 13d03213..4551e36f 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -74,7 +74,7 @@ bool bDidWeProcessAnyCinemaCam;
CCamera::CCamera(void)
{
-#if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS)
+#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS)
m_fMouseAccelHorzntl = 0.0025f;
m_fMouseAccelVertical = 0.003f;
#endif
@@ -88,15 +88,15 @@ CCamera::CCamera(float)
void
CCamera::Init(void)
{
-#if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS)
+#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS)
float fMouseAccelHorzntl = m_fMouseAccelHorzntl;
float fMouseAccelVertical = m_fMouseAccelVertical;
#endif
#ifdef PS2_MENU
- if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart ) {
+ if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart )
#endif
-
+ {
#ifdef FIX_BUGS
static const CCamera DummyCamera = CCamera(0.f);
*this = DummyCamera;
@@ -104,15 +104,13 @@ CCamera::Init(void)
memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh?
#endif
- #if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS)
+ #if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS)
m_fMouseAccelHorzntl = fMouseAccelHorzntl;
m_fMouseAccelVertical = fMouseAccelVertical;
#endif
m_pRwCamera = nil;
-#ifdef PS2_MENU
}
-#endif
m_1rstPersonRunCloseToAWall = false;
m_fPositionAlongSpline = 0.0f;
@@ -123,7 +121,7 @@ CCamera::Init(void)
Cams[0].Mode = CCam::MODE_FOLLOWPED;
Cams[1].Mode = CCam::MODE_FOLLOWPED;
unknown = 0;
- m_bJustJumpedOutOf1stPersonBecauseOfTarget = false;
+ m_bUnknown = false;
ClearPlayerWeaponMode();
m_bInATunnelAndABigVehicle = false;
m_iModeObbeCamIsInForCar = OBBE_INVALID;
@@ -237,7 +235,7 @@ CCamera::Init(void)
m_uiTransitionState = 0;
m_uiTimeTransitionStart = 0;
m_bLookingAtPlayer = true;
-#if !defined(GTA3_1_1_PATCH) && !defined(FIX_BUGS)
+#if GTA_VERSION < GTA3_PC_11 && !defined(FIX_BUGS)
m_fMouseAccelHorzntl = 0.0025f;
m_fMouseAccelVertical = 0.003f;
#endif
@@ -715,14 +713,18 @@ CCamera::Process(void)
DistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y);
// LOD dist
- if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier())
- LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f);
- else
+ if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){
+ LODDistMultiplier = 70.0f/CDraw::GetFOV();
+#ifndef FIX_BUGS
+ // makes no sense and gone in VC
+ LODDistMultiplier *= CDraw::GetAspectRatio()/(4.0f/3.0f);
+#endif
+ }else
LODDistMultiplier = 1.0f;
- // missing on PS2
+#if GTA_VERSION > GTA3_PS2_160
GenerationDistMultiplier = LODDistMultiplier;
LODDistMultiplier *= CRenderer::ms_lodDistScale;
- //
+#endif
// Keep track of speed
if(m_bJustInitalised || m_bJust_Switched){
@@ -1574,8 +1576,10 @@ CCamera::CamControl(void)
switchByJumpCut = true;
}
}
+#ifdef GTA_SCENE_EDIT
if(CSceneEdit::m_bEditOn)
ReqMode = CCam::MODE_EDITOR;
+#endif
if((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){
if(switchByJumpCut){
@@ -3398,10 +3402,10 @@ CCamera::Fade(float timeout, int16 direction)
m_fTimeToFadeMusic = timeout;
m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds();
// Not on PS2
- if(!m_bJustJumpedOutOf1stPersonBecauseOfTarget && m_iMusicFadingDirection == FADE_OUT){
+ if(!m_bUnknown && m_iMusicFadingDirection == FADE_OUT){
unknown++;
if(unknown >= 2){
- m_bJustJumpedOutOf1stPersonBecauseOfTarget = true;
+ m_bUnknown = true;
unknown = 0;
}else
m_bMoveCamToAvoidGeom = true;
diff --git a/src/core/Camera.h b/src/core/Camera.h
index dd78d952..ca1bd135 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -213,7 +213,9 @@ public:
void PrintMode(void);
void Process_Debug(const CVector&, float, float, float);
+#ifdef GTA_SCENE_EDIT
void Process_Editor(const CVector&, float, float, float);
+#endif
void Process_ModelView(const CVector &CameraTarget, float, float, float);
void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float);
@@ -348,7 +350,7 @@ public:
bool m_bcutsceneFinished;
bool m_bCullZoneChecksOn;
bool m_bFirstPersonBeingUsed;
- bool m_bJustJumpedOutOf1stPersonBecauseOfTarget;
+ bool m_bUnknown;
bool m_bIdleOn;
bool m_bInATunnelAndABigVehicle;
bool m_bInitialNodeFound;
diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp
index c11fb72a..f987dea5 100644
--- a/src/core/CdStream.cpp
+++ b/src/core/CdStream.cpp
@@ -5,6 +5,7 @@
#include "CdStream.h"
#include "rwcore.h"
#include "RwHelper.h"
+#include "MemoryMgr.h"
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
@@ -242,8 +243,15 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
else
return STREAM_SUCCESS;
}
-
+
+#ifdef BIG_IMG
+ LARGE_INTEGER liDistanceToMove;
+ liDistanceToMove.QuadPart = _GET_OFFSET(offset);
+ liDistanceToMove.QuadPart *= CDSTREAM_SECTOR_SIZE;
+ SetFilePointerEx(hImage, liDistanceToMove, nil, FILE_BEGIN);
+#else
SetFilePointer(hImage, _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN);
+#endif
DWORD NumberOfBytesRead;
diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp
index 5c8d1b16..0854d850 100644
--- a/src/core/CdStreamPosix.cpp
+++ b/src/core/CdStreamPosix.cpp
@@ -16,7 +16,7 @@
#include "CdStream.h"
#include "rwcore.h"
-#include "RwHelper.h"
+#include "MemoryMgr.h"
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
@@ -429,7 +429,7 @@ void *CdStreamThread(void *param)
ASSERT(pChannel->hFile >= 0);
ASSERT(pChannel->pBuffer != nil );
- lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET);
+ lseek(pChannel->hFile, (size_t)pChannel->nSectorOffset * (size_t)CDSTREAM_SECTOR_SIZE, SEEK_SET);
if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) {
// pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel
// STREAM_WAITING is a little hack to make CStreaming not process this data
diff --git a/src/core/Collision.h b/src/core/Collision.h
deleted file mode 100644
index da94dd34..00000000
--- a/src/core/Collision.h
+++ /dev/null
@@ -1,254 +0,0 @@
-#pragma once
-
-#include "templates.h"
-#include "Game.h" // for eLevelName
-#ifdef VU_COLLISION
-#include "VuVector.h"
-#endif
-
-// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
-#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
-#define MAX_COLLISION_POINTS 64
-#else
-#define MAX_COLLISION_POINTS 32
-#endif
-
-struct CompressedVector
-{
-#ifdef COMPRESSED_COL_VECTORS
- int16 x, y, z;
- CVector Get(void) const { return CVector(x, y, z)/128.0f; };
- void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };
-#ifdef GTA_PS2
- void Unpack(uint128 &qword) const {
- __asm__ volatile (
- "lh $8, 0(%1)\n"
- "lh $9, 2(%1)\n"
- "lh $10, 4(%1)\n"
- "pextlw $10, $8\n"
- "pextlw $2, $9, $10\n"
- "sq $2, %0\n"
- : "=m" (qword)
- : "r" (this)
- : "$8", "$9", "$10", "$2"
- );
- }
-#else
- void Unpack(int32 *qword) const {
- qword[0] = x;
- qword[1] = y;
- qword[2] = z;
- qword[3] = 0; // junk
- }
-#endif
-#else
- float x, y, z;
- CVector Get(void) const { return CVector(x, y, z); };
- void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; };
-#endif
-};
-
-struct CColSphere
-{
- // NB: this has to be compatible with a CVuVector
- CVector center;
- float radius;
- 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; }
-};
-
-struct CColBox
-{
- 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; }
-};
-
-struct CColLine
-{
- // NB: this has to be compatible with two CVuVectors
- CVector p0;
- int pad0;
- CVector p1;
- int pad1;
-
- CColLine(void) { };
- CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
- void Set(const CVector &p0, const CVector &p1);
-};
-
-struct CColTriangle
-{
- uint16 a;
- uint16 b;
- uint16 c;
- uint8 surface;
-
- void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
-};
-
-struct CColTrianglePlane
-{
-#ifdef VU_COLLISION
- CompressedVector normal;
- int16 dist;
-
- void Set(const CVector &va, const CVector &vb, const CVector &vc);
- void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
- void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }
- float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };
-#ifdef GTA_PS2
- void Unpack(uint128 &qword) const {
- __asm__ volatile (
- "lh $8, 0(%1)\n"
- "lh $9, 2(%1)\n"
- "lh $10, 4(%1)\n"
- "lh $11, 6(%1)\n"
- "pextlw $10, $8\n"
- "pextlw $11, $9\n"
- "pextlw $2, $11, $10\n"
- "sq $2, %0\n"
- : "=m" (qword)
- : "r" (this)
- : "$8", "$9", "$10", "$11", "$2"
- );
- }
-#else
- void Unpack(int32 *qword) const {
- qword[0] = normal.x;
- qword[1] = normal.y;
- qword[2] = normal.z;
- qword[3] = dist;
- }
-#endif
-#else
- CVector normal;
- float dist;
- uint8 dir;
-
- void Set(const CVector &va, const CVector &vb, const CVector &vc);
- void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
- void GetNormal(CVector &n) const { n = normal; }
- float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
-#endif
-};
-
-struct CColPoint
-{
- CVector point;
- int pad1;
- // the surface normal on the surface of point
- CVector normal;
- int pad2;
- uint8 surfaceA;
- uint8 pieceA;
- uint8 surfaceB;
- uint8 pieceB;
- float depth;
-
- void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
- this->depth = depth;
- this->surfaceA = surfA;
- this->pieceA = pieceA;
- this->surfaceB = surfB;
- this->pieceB = pieceB;
- }
- void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
- this->surfaceA = surfA;
- this->pieceA = pieceA;
- this->surfaceB = surfB;
- this->pieceB = pieceB;
- }
-};
-
-struct CStoredCollPoly
-{
-#ifdef VU_COLLISION
- CVuVector verts[3];
-#else
- CVector verts[3];
-#endif
- bool valid;
-};
-
-struct CColModel
-{
- CColSphere boundingSphere;
- CColBox boundingBox;
- int16 numSpheres;
- int16 numLines;
- int16 numBoxes;
- int16 numTriangles;
- int32 level;
- bool ownsCollisionVolumes; // missing on PS2
- CColSphere *spheres;
- CColLine *lines;
- CColBox *boxes;
- CompressedVector *vertices;
- CColTriangle *triangles;
- CColTrianglePlane *trianglePlanes;
-
- CColModel(void);
- ~CColModel(void);
- void RemoveCollisionVolumes(void);
- void CalculateTrianglePlanes(void);
- void RemoveTrianglePlanes(void);
- CLink<CColModel*> *GetLinkPtr(void);
- void SetLinkPtr(CLink<CColModel*>*);
- void GetTrianglePoint(CVector &v, int i) const;
-
- CColModel& operator=(const CColModel& other);
-};
-
-class CCollision
-{
-public:
- static eLevelName ms_collisionInMemory;
- static CLinkList<CColModel*> ms_colModelCache;
-#ifdef NO_ISLAND_LOADING
- static bool bAlreadyLoaded;
-#endif
-
- static void Init(void);
- static void Shutdown(void);
- static void Update(void);
- static void LoadCollisionWhenINeedIt(bool changeLevel);
- static void SortOutCollisionAfterLoad(void);
- static void LoadCollisionScreen(eLevelName level);
- static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
- static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
-
- 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 TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
- static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
- static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
- static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough);
-
- static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
- static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
- static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
- static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
- static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
- static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
- static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
- static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
- static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
- static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
- static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
-
- static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);
- static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);
-};
diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp
index 576a58b1..cadba7f2 100644
--- a/src/core/ControllerConfig.cpp
+++ b/src/core/ControllerConfig.cpp
@@ -2316,8 +2316,252 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
return num;
}
+#ifdef BIND_VEHICLE_FIREWEAPON
+#define VFB(b) b,
+#else
+#define VFB(b)
+#endif
+
+#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT) \
+ {{ \
+ O, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ Q, /* PED_SNIPER_ZOOM_IN */ \
+ X, /* PED_SNIPER_ZOOM_OUT */ \
+ T, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ X, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(O) /* VEHICLE_FIREWEAPON */ \
+ X, /* VEHICLE_ACCELERATE */ \
+ Q, /* VEHICLE_BRAKE */ \
+ L1, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ L3, /* VEHICLE_HORN */ \
+ R3, /* TOGGLE_SUBMISSIONS */ \
+ R1, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ R1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }, \
+ { \
+ O, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ Q, /* PED_SNIPER_ZOOM_IN */ \
+ X, /* PED_SNIPER_ZOOM_OUT */ \
+ T, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ X, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(O) /* VEHICLE_FIREWEAPON */ \
+ X, /* VEHICLE_ACCELERATE */ \
+ Q, /* VEHICLE_BRAKE */ \
+ SELECT, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ L1, /* VEHICLE_HORN */ \
+ R3, /* TOGGLE_SUBMISSIONS */ \
+ R1, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ R1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }, \
+ { \
+ X, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ T, /* PED_SNIPER_ZOOM_IN */ \
+ Q, /* PED_SNIPER_ZOOM_OUT */ \
+ L1, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ O, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(O) /* VEHICLE_FIREWEAPON */ \
+ X, /* VEHICLE_ACCELERATE */ \
+ Q, /* VEHICLE_BRAKE */ \
+ L3, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ R1, /* VEHICLE_HORN */ \
+ R3, /* TOGGLE_SUBMISSIONS */ \
+ T, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ T, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ R1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }, \
+ { \
+ R1, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ Q, /* PED_SNIPER_ZOOM_IN */ \
+ X, /* PED_SNIPER_ZOOM_OUT */ \
+ T, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ X, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(R1) /* VEHICLE_FIREWEAPON */ \
+ nil, /* VEHICLE_ACCELERATE */ \
+ nil, /* VEHICLE_BRAKE */ \
+ O, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ L3, /* VEHICLE_HORN */ \
+ Q, /* TOGGLE_SUBMISSIONS */ \
+ L1, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ O, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ L1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }}
+
+
+const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK");
+
+#ifdef BUTTON_ICONS
+const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK");
+#endif
+
+
+#if 0 // set 1 for ps2 fonts
+#define PS2_TRIANGLE "\""
+#define PS2_CIRCLE "|"
+#define PS2_CROSS "/"
+#define PS2_SQUARE "^"
+#elif defined(BUTTON_ICONS)
+#define PS2_TRIANGLE "~T~"
+#define PS2_CIRCLE "~O~"
+#define PS2_CROSS "~X~"
+#define PS2_SQUARE "~Q~"
+#else
+#define PS2_TRIANGLE "TRIANGLE"
+#define PS2_CIRCLE "CIRCLE"
+#define PS2_CROSS "CROSS"
+#define PS2_SQUARE "SQUARE"
+#endif
+
+const char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] =
+ CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT");
+
+#ifdef BUTTON_ICONS
+const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =
+ CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT");
+#endif
+
+#undef PS2_TRIANGLE
+#undef PS2_CIRCLE
+#undef PS2_CROSS
+#undef PS2_SQUARE
+
+#undef CONTROLLER_BUTTONS
+#undef VFB
+
void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *text, uint16 leight)
{
+#ifdef DETECT_PAD_INPUT_SWITCH
+ if (CPad::GetPad(0)->IsAffectedByController) {
+ wchar wstr[16];
+
+ // TODO: INI and/or menu setting for Xbox/PS switch
+#ifdef BUTTON_ICONS
+ const char *(*Buttons)[MAX_CONTROLLERACTIONS] = CFont::ButtonsSlot != -1 ? XboxButtons : XboxButtons_noIcons;
+#else
+ const char *(*Buttons)[MAX_CONTROLLERACTIONS] = XboxButtons_noIcons;
+#endif
+
+ assert(Buttons[CPad::GetPad(0)->Mode][action] != nil); // we cannot use these
+ AsciiToUnicode(Buttons[CPad::GetPad(0)->Mode][action], wstr);
+
+ CMessages::WideStringCopy(text, wstr, leight);
+ return;
+ }
+#endif
+
int32 nums = GetNumOfSettingsForAction((e_ControllerAction)action);
int32 sets = 0;
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index aadafc29..b9d475b8 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -11,7 +11,6 @@
#include "HandlingMgr.h"
#include "CarCtrl.h"
#include "PedType.h"
-#include "PedStats.h"
#include "AnimManager.h"
#include "Game.h"
#include "RwHelper.h"
@@ -25,6 +24,7 @@
#include "ZoneCull.h"
#include "CdStream.h"
#include "FileLoader.h"
+#include "MemoryHeap.h"
char CFileLoader::ms_line[256];
@@ -59,7 +59,13 @@ CFileLoader::LoadLevel(const char *filename)
savedTxd = RwTexDictionaryCreate();
RwTexDictionarySetCurrent(savedTxd);
}
+#if GTA_VERSION <= GTA3_PS2_160
+ CFileMgr::ChangeDir("\\DATA\\");
+ fd = CFileMgr::OpenFile(filename, "r");
+ CFileMgr::ChangeDir("\\");
+#else
fd = CFileMgr::OpenFile(filename, "r");
+#endif
assert(fd > 0);
for(line = LoadLine(fd); line; line = LoadLine(fd)){
@@ -72,11 +78,13 @@ CFileLoader::LoadLevel(const char *filename)
if(strncmp(line, "IMAGEPATH", 9) == 0){
RwImageSetPath(line + 10);
}else if(strncmp(line, "TEXDICTION", 10) == 0){
+ PUSH_MEMID(MEMID_TEXTURES);
strcpy(txdname, line+11);
LoadingScreenLoadingFile(txdname);
RwTexDictionary *txd = LoadTexDictionary(txdname);
AddTexDictionaries(savedTxd, txd);
RwTexDictionaryDestroy(txd);
+ POP_MEMID();
}else if(strncmp(line, "COLFILE", 7) == 0){
int level;
sscanf(line+8, "%d", &level);
@@ -95,12 +103,16 @@ CFileLoader::LoadLevel(const char *filename)
LoadObjectTypes(line + 4);
}else if(strncmp(line, "IPL", 3) == 0){
if(!objectsLoaded){
+ PUSH_MEMID(MEMID_DEF_MODELS);
CModelInfo::ConstructMloClumps();
+ POP_MEMID();
CObjectData::Initialise("DATA\\OBJECT.DAT");
objectsLoaded = true;
}
+ PUSH_MEMID(MEMID_WORLD);
LoadingScreenLoadingFile(line + 4);
LoadScene(line + 4);
+ POP_MEMID();
}else if(strncmp(line, "MAPZONE", 7) == 0){
LoadingScreenLoadingFile(line + 8);
LoadMapZones(line + 8);
@@ -189,6 +201,8 @@ CFileLoader::LoadCollisionFile(const char *filename)
CBaseModelInfo *mi;
ColHeader header;
+ PUSH_MEMID(MEMID_COLLISION);
+
debug("Loading collision file %s\n", filename);
fd = CFileMgr::OpenFile(filename, "rb");
@@ -212,6 +226,8 @@ CFileLoader::LoadCollisionFile(const char *filename)
}
CFileMgr::CloseFile(fd);
+
+ POP_MEMID();
}
void
@@ -233,6 +249,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 44;
if(model.numSpheres > 0){
model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));
+ REGISTER_MEMPTR(&model.spheres);
for(i = 0; i < model.numSpheres; i++){
model.spheres[i].Set(*(float*)buf, *(CVector*)(buf+4), buf[16], buf[17]);
buf += 20;
@@ -244,6 +261,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(model.numLines > 0){
model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine));
+ REGISTER_MEMPTR(&model.lines);
for(i = 0; i < model.numLines; i++){
model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12));
buf += 24;
@@ -255,6 +273,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(model.numBoxes > 0){
model.boxes = (CColBox*)RwMalloc(model.numBoxes*sizeof(CColBox));
+ REGISTER_MEMPTR(&model.boxes);
for(i = 0; i < model.numBoxes; i++){
model.boxes[i].Set(*(CVector*)buf, *(CVector*)(buf+12), buf[24], buf[25]);
buf += 28;
@@ -266,6 +285,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(numVertices > 0){
model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector));
+ REGISTER_MEMPTR(&model.vertices);
for(i = 0; i < numVertices; i++){
model.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8));
if(Abs(*(float*)buf) >= 256.0f ||
@@ -281,6 +301,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(model.numTriangles > 0){
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
+ REGISTER_MEMPTR(&model.triangles);
for(i = 0; i < model.numTriangles; i++){
model.triangles[i].Set(model.vertices, *(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12], buf[13]);
buf += 16;
@@ -332,6 +353,16 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
return atomic;
}
+#ifdef LIBRW
+void
+InitClump(RpClump *clump)
+{
+ RpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil);
+}
+#else
+#define InitClump(clump)
+#endif
+
void
CFileLoader::LoadModelFile(const char *filename)
{
@@ -343,6 +374,7 @@ CFileLoader::LoadModelFile(const char *filename)
if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){
clump = RpClumpStreamRead(stream);
if(clump){
+ InitClump(clump);
RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump);
RpClumpDestroy(clump);
}
@@ -368,6 +400,7 @@ CFileLoader::LoadClumpFile(const char *filename)
GetNameAndLOD(nodename, name, &n);
mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil);
if(mi){
+ InitClump(clump);
assert(mi->IsClump());
mi->SetClump(clump);
}else
@@ -393,6 +426,7 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id)
if (mi->GetModelType() == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) {
// Read LOD ped
clump = RpClumpStreamRead(stream);
+ InitClump(clump);
if(clump){
((CPedModelInfo*)mi)->SetLowDetailClump(clump);
RpClumpDestroy(clump);
@@ -423,6 +457,7 @@ CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id)
clump = RpClumpGtaStreamRead2(stream);
if(clump){
+ InitClump(clump);
mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);
mi->SetClump(clump);
return true;
@@ -443,6 +478,7 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id)
clump = RpClumpStreamRead(stream);
if(clump == nil)
return false;
+ InitClump(clump);
gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump);
RpClumpDestroy(clump);
@@ -806,6 +842,8 @@ CFileLoader::LoadAtomicFile2Return(const char *filename)
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
clump = RpClumpStreamRead(stream);
+ if(clump)
+ InitClump(clump);
RwStreamClose(stream, nil);
return clump;
}
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index 89b5ba3d..5597b358 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -41,14 +41,7 @@
#define TIDY_UP_PBP // ProcessButtonPresses
#define MAX_VISIBLE_LIST_ROW 30
#define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result
-
-#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
-#define MILES_IN_METER 0.000621371192f
-#define FEET_IN_METER 3.28084f
-#else
-#define MILES_IN_METER 0.00059880241f
-#define FEET_IN_METER 3.33f
-#endif
+#define SCROLLABLE_PAGES
#ifdef SCROLLABLE_STATS_PAGE
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS)
@@ -56,6 +49,34 @@
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS)
#endif
+#define hasNativeList(screen) (screen == MENUPAGE_MULTIPLAYER_FIND_GAME || screen == MENUPAGE_SKIN_SELECT \
+ || screen == MENUPAGE_KEYBOARD_CONTROLS)
+
+#ifdef SCROLLABLE_PAGES
+#define MAX_VISIBLE_OPTION 12
+#define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION)
+
+int GetOptionCount(int screen)
+{
+ int i = 0;
+ for (; i < NUM_MENUROWS && aScreens[screen].m_aEntries[i].m_Action != MENUACTION_NOTHING; i++);
+ return i;
+}
+
+#define SETUP_SCROLLING(screen) \
+ if (!hasNativeList(screen)) { \
+ m_nTotalListRow = GetOptionCount(screen); \
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION) { \
+ m_nSelectedListRow = 0; \
+ m_nFirstVisibleRowOnList = 0; \
+ m_nScrollbarTopMargin = 0; \
+ } \
+ }
+#else
+#define MAX_VISIBLE_OPTION_ON_SCREEN MAX_VISIBLE_LIST_ROW
+#define SETUP_SCROLLING(screen)
+#endif
+
#ifdef TRIANGLE_BACK_BUTTON
#define GetBackJustUp GetTriangleJustUp
#define GetBackJustDown GetTriangleJustDown
@@ -80,13 +101,40 @@ float CMenuManager::fMapCenterX;
BottomBarOption bbNames[8];
int bbTabCount = 0;
bool bottomBarActive = false;
-bool reverseAlpha = false;
int pendingScreen = -1;
int pendingOption = -1;
int curBottomBarOption = -1;
int hoveredBottomBarOption = -1;
#endif
+#ifdef CUTSCENE_BORDERS_SWITCH
+bool CMenuManager::m_PrefsCutsceneBorders = true;
+#endif
+
+#ifdef MULTISAMPLING
+int8 CMenuManager::m_nPrefsMSAALevel = 0;
+int8 CMenuManager::m_nDisplayMSAALevel = 0;
+#endif
+
+#ifdef NO_ISLAND_LOADING
+int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
+#endif
+
+// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
+#ifdef PS2_LIKE_MENU
+const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255);
+#else
+const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color
+#endif
+
+#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
+#define MILES_IN_METER 0.000621371192f
+#define FEET_IN_METER 3.28084f
+#else
+#define MILES_IN_METER 0.00059880241f
+#define FEET_IN_METER 3.33f
+#endif
+
int32 CMenuManager::OS_Language = LANG_ENGLISH;
int8 CMenuManager::m_PrefsUseVibration;
int8 CMenuManager::m_DisplayControllerOnFoot;
@@ -112,31 +160,11 @@ int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt;
int32 CMenuManager::m_PrefsMusicVolume = 102;
int32 CMenuManager::m_PrefsSfxVolume = 102;
-#ifdef CUTSCENE_BORDERS_SWITCH
-bool CMenuManager::m_PrefsCutsceneBorders = true;
-#endif
-
-#ifdef MULTISAMPLING
-int8 CMenuManager::m_nPrefsMSAALevel = 0;
-int8 CMenuManager::m_nDisplayMSAALevel = 0;
-#endif
-
-#ifdef NO_ISLAND_LOADING
-int8 CMenuManager::m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
-#endif
char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME;
int32 CMenuManager::m_KeyPressedCode = -1;
-// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
-#ifdef PS2_LIKE_MENU
-const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255);
-#else
-const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color
-#endif
-
float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE;
float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE;
@@ -254,35 +282,12 @@ const char* MenuFilenames[][2] = {
#define PAGE_NAME_X SCREEN_SCALE_FROM_RIGHT
#endif
-#ifdef PS2_LIKE_MENU
-#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \
- do { \
- if (reverseAlpha) { \
- m_nPrevScreen = m_nCurrScreen; \
- m_nCurrScreen = pendingScreen; \
- m_nCurrOption = pendingOption; \
- reverseAlpha = false; \
- if (updateDelay) \
- m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \
- } \
- if (withReverseAlpha && !m_bRenderGameInMenu) { \
- pendingOption = option; \
- pendingScreen = screen; \
- reverseAlpha = true; \
- } else { \
- m_nPrevScreen = m_nCurrScreen; \
- m_nCurrScreen = screen; \
- m_nCurrOption = option; \
- if (updateDelay) \
- m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \
- } \
- m_nMenuFadeAlpha = 255; \
- } while(0)
-#else
+// Seperate func. in VC
#define ChangeScreen(screen, option, updateDelay, clearAlpha) \
do { \
m_nPrevScreen = m_nCurrScreen; \
int newOpt = option; \
+ SETUP_SCROLLING(screen) \
m_nCurrScreen = screen; \
m_nCurrOption = newOpt; \
if(updateDelay) \
@@ -290,7 +295,6 @@ const char* MenuFilenames[][2] = {
if(clearAlpha) \
m_nMenuFadeAlpha = 0; \
} while(0)
-#endif
#define PREPARE_MENU_HEADER \
CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \
@@ -341,8 +345,8 @@ CMenuManager::ScrollUpListByOne()
void
CMenuManager::ScrollDownListByOne()
{
- if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) {
- if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
+ if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1) {
+ if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) {
m_nSelectedListRow++;
m_nFirstVisibleRowOnList++;
m_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow;
@@ -357,13 +361,13 @@ CMenuManager::ScrollDownListByOne()
void
CMenuManager::PageUpList(bool playSoundOnSuccess)
{
- if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) {
if (m_nFirstVisibleRowOnList > 0) {
if(playSoundOnSuccess)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW);
- m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1);
+ m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_OPTION_ON_SCREEN);
+ m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1);
} else {
m_nFirstVisibleRowOnList = 0;
m_nSelectedListRow = 0;
@@ -375,15 +379,15 @@ CMenuManager::PageUpList(bool playSoundOnSuccess)
void
CMenuManager::PageDownList(bool playSoundOnSuccess)
{
- if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
- if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) {
+ if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) {
if(playSoundOnSuccess)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW);
+ m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN, m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN);
m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList);
} else {
- m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW;
+ m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN;
m_nSelectedListRow = m_nTotalListRow - 1;
}
m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
@@ -434,30 +438,26 @@ CMenuManager::ThingsToDoBeforeGoingBack()
m_nTotalListRow = 0;
}
-#ifdef CUSTOM_FRONTEND_OPTIONS
- for (int i = 0; i < numCustomFrontendOptions; i++) {
- FrontendOption &option = customFrontendOptions[i];
- if (option.type != FEOPTION_REDIRECT && option.type != FEOPTION_GOBACK && m_nCurrScreen == option.screen) {
- if (option.returnPrevPageFunc)
- option.returnPrevPageFunc();
-
- if (m_nCurrOption == option.screenOptionOrder && (option.type == FEOPTION_DYNAMIC || option.type == FEOPTION_BUILTIN_ACTION))
- if(option.buttonPressFunc)
- option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
-
- if (option.type == FEOPTION_SELECT && option.onlyApplyOnEnter && option.lastSavedValue != option.displayedValue)
- option.displayedValue = *option.value = option.lastSavedValue;
- }
+#ifdef SCROLLABLE_PAGES
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) {
+ m_nSelectedListRow = 0;
+ m_nFirstVisibleRowOnList = 0;
+ m_nScrollbarTopMargin = 0;
}
+#endif
- if (m_nCurrScreen > lastOgScreen) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id && screen.returnPrevPageFunc) {
- screen.returnPrevPageFunc();
- break;
- }
- }
+#ifdef CUSTOM_FRONTEND_OPTIONS
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
+
+ if (option.m_Action == MENUACTION_CFO_DYNAMIC)
+ if(option.m_CFODynamic->buttonPressFunc)
+ option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
+
+ if (option.m_Action == MENUACTION_CFO_SELECT && option.m_CFOSelect->onlyApplyOnEnter && option.m_CFOSelect->lastSavedValue != option.m_CFOSelect->displayedValue)
+ option.m_CFOSelect->displayedValue = *option.m_CFO->value = option.m_CFOSelect->lastSavedValue;
+
+ if (aScreens[m_nCurrScreen].returnPrevPageFunc) {
+ aScreens[m_nCurrScreen].returnPrevPageFunc();
}
#endif
}
@@ -476,21 +476,248 @@ CMenuManager::GetPreviousPageOption()
prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage;
for (int i = 0; i < NUM_MENUROWS; i++) {
- if (aScreens[prevPage].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption &option = customFrontendOptions[aScreens[prevPage].m_aEntries[i].m_TargetMenu];
- if(option.type == FEOPTION_REDIRECT && option.to == m_nCurrScreen) {
+ if (aScreens[prevPage].m_aEntries[i].m_Action >= MENUACTION_NOTHING) { // CFO check
+ if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) {
return i;
}
- } else if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) {
- return i;
}
}
-
- // Couldn't find current screen option on previous page, use default behaviour (maybe save-related screen?)
- return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0];
+
+ // This shouldn't happen
+ return 0;
#endif
}
+void
+CMenuManager::ProcessList(bool &goBack, bool &optionSelected)
+{
+ if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {
+ m_nTotalListRow = m_nSkinsTotal;
+ }
+ if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {
+ m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25;
+ if (m_nSelectedListRow > m_nTotalListRow)
+ m_nSelectedListRow = m_nTotalListRow - 1;
+ }
+
+#ifndef TIDY_UP_PBP
+ if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {
+ m_bShowMouse = 0;
+ optionSelected = true;
+ }
+#endif
+ if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) {
+ if (m_nCurrExLayer == HOVEROPTION_LIST) {
+ m_nHoverOption = HOVEROPTION_NOT_HOVERING;
+ m_bWaitingForNewKeyBind = true;
+ m_bStartWaitingForKeyBind = true;
+ m_bKeyChangeNotProcessed = true;
+ pControlEdit = &m_KeyPressedCode;
+ }
+ } else {
+ field_535 = false;
+ }
+
+ static uint32 lastTimeClickedScrollButton = 0;
+
+ if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) {
+ m_bPressedPgUpOnList = false;
+ m_bPressedPgDnOnList = false;
+ m_bPressedUpOnList = false;
+ m_bPressedDownOnList = false;
+ m_bPressedScrollButton = false;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ }
+
+ if (CPad::GetPad(0)->GetTabJustDown()) {
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ m_bShowMouse = false;
+ switch (m_nCurrExLayer) {
+ case HOVEROPTION_BACK:
+ default:
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ break;
+ case HOVEROPTION_LIST:
+ m_nCurrExLayer = HOVEROPTION_USESKIN;
+ break;
+ case HOVEROPTION_USESKIN:
+ m_nCurrExLayer = HOVEROPTION_BACK;
+ }
+ if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) {
+ m_nCurrExLayer = HOVEROPTION_BACK;
+ }
+ if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) {
+ m_nCurrExLayer = HOVEROPTION_BACK;
+ }
+ }
+
+ bool pressed = false;
+ if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {
+ m_bShowMouse = false;
+ pressed = true;
+ } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) {
+ m_bShowMouse = true;
+ pressed = true;
+ }
+
+ // Up
+ if (pressed) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedUpOnList) {
+ m_bPressedUpOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ ScrollUpListByOne();
+ }
+ } else {
+ m_bPressedUpOnList = false;
+ }
+
+ pressed = false;
+ if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {
+ m_bShowMouse = false;
+ pressed = true;
+ } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {
+ m_bShowMouse = true;
+ pressed = true;
+ }
+
+ // Down
+ if (pressed) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedDownOnList) {
+ m_bPressedDownOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ ScrollDownListByOne();
+ }
+ } else {
+ m_bPressedDownOnList = false;
+ }
+
+ if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
+ if (!CPad::GetPad(0)->GetPageUp()) {
+ m_bPressedPgUpOnList = false;
+ } else {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedPgUpOnList) {
+ m_bPressedPgUpOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ PageUpList(false);
+ }
+ }
+ if (!CPad::GetPad(0)->GetPageDown()) {
+ m_bPressedPgDnOnList = false;
+ } else {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedPgDnOnList) {
+ m_bPressedPgDnOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ PageDownList(false);
+ }
+ }
+ if (CPad::GetPad(0)->GetHome()) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) {
+ m_nFirstVisibleRowOnList = 0;
+ }
+ m_nSelectedListRow = 0;
+ m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
+ }
+ if (CPad::GetPad(0)->GetEnd()) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) {
+ m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN;
+ }
+ m_nSelectedListRow = m_nTotalListRow - 1;
+ m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
+ }
+ }
+
+#ifndef TIDY_UP_PBP
+ if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) {
+ m_bShowMouse = false;
+ goBack = true;
+ }
+#endif
+
+ if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
+ switch (m_nHoverOption) {
+ case HOVEROPTION_BACK:
+ goBack = true;
+ break;
+ case HOVEROPTION_PAGEUP:
+ PageUpList(true);
+ break;
+ case HOVEROPTION_PAGEDOWN:
+ PageDownList(true);
+ break;
+ case HOVEROPTION_USESKIN:
+ if (m_nSkinsTotal > 0) {
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
+ m_pSelectedSkin = m_pSkinListHead.nextSkin;
+ strcpy(m_PrefsSkinFile, m_aSkinName);
+ CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
+ SaveSettings();
+ }
+ }
+ }
+
+ if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
+ switch (m_nHoverOption) {
+ case HOVEROPTION_OVER_SCROLL_UP:
+ m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP;
+ break;
+ case HOVEROPTION_OVER_SCROLL_DOWN:
+ m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN;
+ break;
+ case HOVEROPTION_LIST:
+ m_nHoverOption = HOVEROPTION_SKIN;
+ }
+ } else if ((CPad::GetPad(0)->GetLeftMouseJustUp())
+ && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) {
+ m_nHoverOption = HOVEROPTION_NOT_HOVERING;
+ }
+
+ if (!CPad::GetPad(0)->GetLeftMouse()) {
+ holdingScrollBar = false;
+ } else {
+ if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) {
+ holdingScrollBar = true;
+ // TODO: This part is a bit hard to reverse. Not much code tho
+ assert(0 && "Holding scrollbar isn't done yet");
+ } else {
+ switch (m_nHoverOption) {
+ case HOVEROPTION_OVER_SCROLL_UP:
+ case HOVEROPTION_CLICKED_SCROLL_UP:
+ if (!m_bPressedScrollButton) {
+ m_bPressedScrollButton = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ ScrollUpListByOne();
+ }
+ break;
+ case HOVEROPTION_OVER_SCROLL_DOWN:
+ case HOVEROPTION_CLICKED_SCROLL_DOWN:
+ if (!m_bPressedScrollButton) {
+ m_bPressedScrollButton = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ ScrollDownListByOne();
+ }
+ break;
+ default:
+ m_bPressedScrollButton = false;
+ }
+ }
+ }
+}
// ------ Functions not in the game/inlined ends
void
@@ -782,19 +1009,21 @@ CMenuManager::Draw()
CFont::SetCentreOff();
CFont::SetJustifyOn();
CFont::SetBackGroundOnlyTextOn();
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
+#ifdef DRAW_MENU_VERSION_TEXT
CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255)));
CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING);
CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f));
- CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+ CFont::SetWrapx(SCREEN_WIDTH);
CFont::SetRightJustifyWrap(0.0f);
strcpy(gString, "V1.1");
AsciiToUnicode(gString, gUString);
CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString);
#endif
+#endif
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
+ CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f));
switch (m_nCurrScreen) {
case MENUPAGE_STATS:
@@ -854,13 +1083,6 @@ CMenuManager::Draw()
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
break;
default:
-#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[0].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[0].m_TargetMenu];
- str = (wchar*)option.leftText;
- }
- else
-#endif
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
break;
}
@@ -873,7 +1095,11 @@ CMenuManager::Draw()
#endif
}
+#ifdef ASPECT_RATIO_SCALE
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+#else
+ CFont::SetCentreSize(SCREEN_WIDTH);
+#endif
#ifdef PS2_LIKE_MENU
bool itemsAreSelectable = !bottomBarActive;
@@ -959,30 +1185,22 @@ CMenuManager::Draw()
#endif
default:
#ifdef CUSTOM_FRONTEND_OPTIONS
- bool custom = m_nCurrScreen > lastOgScreen;
+ CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout;
if (custom) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id) {
- columnWidth = screen.columnWidth;
- headerHeight = screen.headerHeight;
- lineHeight = screen.lineHeight;
- CFont::SetFontStyle(FONT_LOCALE(screen.font));
- CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = screen.fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = screen.fontScaleY));
- if (screen.alignment == FESCREEN_LEFT_ALIGN) {
- CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
- } else if (screen.alignment == FESCREEN_RIGHT_ALIGN) {
- CFont::SetCentreOff();
- CFont::SetRightJustifyOn();
- } else {
- CFont::SetRightJustifyOff();
- CFont::SetCentreOn();
- }
- break;
- }
- if (i == numCustomFrontendScreens - 1)
- custom = false;
+ columnWidth = custom->columnWidth;
+ headerHeight = custom->headerHeight;
+ lineHeight = custom->lineHeight;
+ CFont::SetFontStyle(FONT_LOCALE(custom->font));
+ CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = custom->fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = custom->fontScaleY));
+ if (custom->alignment == FESCREEN_LEFT_ALIGN) {
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ } else if (custom->alignment == FESCREEN_RIGHT_ALIGN) {
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOn();
+ } else {
+ CFont::SetRightJustifyOff();
+ CFont::SetCentreOn();
}
}
if (!custom)
@@ -1043,13 +1261,24 @@ CMenuManager::Draw()
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- static int lastOption = m_nCurrOption;
+ static int lastSelectedOpt = m_nCurrOption;
#endif
+#ifdef SCROLLABLE_PAGES
+ int firstOption = m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen) ? m_nFirstVisibleRowOnList : 0;
+ for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) {
+#else
for (int i = 0; i < NUM_MENUROWS; ++i) {
+#endif
+
#ifdef CUSTOM_FRONTEND_OPTIONS
bool isOptionDisabled = false;
#endif
+ // Hide back button
+#ifdef PS2_LIKE_MENU
+ if ((i == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[i+1].m_EntryName[0] == '\0') && strncmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEDS_TB", 8) == 0)
+ break;
+#endif
if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') {
wchar *rightText = nil;
wchar *leftText;
@@ -1066,28 +1295,22 @@ CMenuManager::Draw()
leftText = TheText.Get(gString);
}
} else {
-#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO){
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu];
- leftText = (wchar*)option.leftText;
- } else
-#endif
leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName);
}
#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption &option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu];
- if (option.type == FEOPTION_SELECT) {
- if (option.onlyApplyOnEnter){
+ if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action < MENUACTION_NOTHING) { // CFO check
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (option.m_CFOSelect->onlyApplyOnEnter){
if (m_nCurrOption != i) {
- if (option.displayedValue != option.lastSavedValue)
+ if (option.m_CFOSelect->displayedValue != option.m_CFOSelect->lastSavedValue)
SetHelperText(3); // Restored original value
-// option.displayedValue = option.lastSavedValue = *option.value;
+// option.displayedValue = option.lastSavedValue = *option.m_CFO->value;
} else {
- if (option.displayedValue != *option.value)
+ if (option.m_CFOSelect->displayedValue != *option.m_CFO->value)
SetHelperText(1); // Enter to apply
else if (m_nHelperTextMsgId == 1)
ResetHelperText(); // Applied
@@ -1095,14 +1318,14 @@ CMenuManager::Draw()
}
}
- if (m_nCurrOption != lastOption && lastOption == i) {
- FrontendOption &oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu];
- if (oldOption.type == FEOPTION_DYNAMIC || oldOption.type == FEOPTION_BUILTIN_ACTION)
- if(oldOption.buttonPressFunc)
- oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
+ if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) {
+ CMenuScreenCustom::CMenuEntry &oldOption = aScreens[m_nCurrScreen].m_aEntries[lastSelectedOpt];
+ if (oldOption.m_Action == MENUACTION_CFO_DYNAMIC)
+ if(oldOption.m_CFODynamic->buttonPressFunc)
+ oldOption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
- if (oldOption.onlyApplyOnEnter && oldOption.type == FEOPTION_SELECT)
- oldOption.displayedValue = oldOption.lastSavedValue = *oldOption.value;
+ if (oldOption.m_Action == MENUACTION_CFO_SELECT && oldOption.m_CFOSelect->onlyApplyOnEnter)
+ oldOption.m_CFOSelect->displayedValue = oldOption.m_CFOSelect->lastSavedValue = *oldOption.m_CFO->value;
}
}
#endif
@@ -1270,21 +1493,6 @@ CMenuManager::Draw()
AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp);
rightText = unicodeTemp;
break;
-//#ifdef NO_ISLAND_LOADING
-// case MENUACTION_ISLANDLOADING:
-// switch (m_DisplayIslandLoading) {
-// case ISLAND_LOADING_LOW:
-// rightText = TheText.Get("FEM_LOW");
-// break;
-// case ISLAND_LOADING_MEDIUM:
-// rightText = TheText.Get("FEM_MED");
-// break;
-// case ISLAND_LOADING_HIGH:
-// rightText = TheText.Get("FEM_HIG");
-// break;
-// }
-// break;
-//#endif
case MENUACTION_AUDIOHW:
if (m_nPrefsAudio3DProviderIndex == -1)
rightText = TheText.Get("FEA_NAH");
@@ -1336,29 +1544,24 @@ CMenuManager::Draw()
rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON");
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
- case MENUACTION_TRIGGERFUNC:
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu];
- if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) {
- if (option.type == FEOPTION_SELECT) {
- // To whom manipulate option.value of static options externally (like RestoreDef functions)
- if (*option.value != option.lastSavedValue)
- option.displayedValue = option.lastSavedValue = *option.value;
-
- if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0)
- option.displayedValue = 0;
-
- rightText = (wchar*)option.rightTexts[option.displayedValue];
-
- } else if (option.type == FEOPTION_DYNAMIC) {
- if (option.drawFunc) {
- rightText = option.drawFunc(&isOptionDisabled, m_nCurrOption == i);
- }
+ case MENUACTION_CFO_DYNAMIC:
+ case MENUACTION_CFO_SELECT:
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ // To whom manipulate option.m_CFO->value of static options externally (like RestoreDef functions)
+ if (*option.m_CFO->value != option.m_CFOSelect->lastSavedValue)
+ option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value;
+
+ if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)
+ option.m_CFOSelect->displayedValue = 0;
+
+ rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]);
+
+ } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) {
+ if (option.m_CFODynamic->drawFunc) {
+ rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i);
}
- } else {
- debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder);
- assert(0 && "Custom frontend options is borked");
}
-
break;
#endif
}
@@ -1368,9 +1571,20 @@ CMenuManager::Draw()
int nextYToCheck = bitAboveNextItemY;
if (!foundTheHoveringItem) {
+#ifdef SCROLLABLE_PAGES
+ for (int rowToCheck = firstOption + (aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Action == MENUACTION_LABEL); rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) {
+#else
for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) {
+#endif
if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING)
break;
+
+ // Hide back button
+#ifdef PS2_LIKE_MENU
+ if ((rowToCheck == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[rowToCheck+1].m_EntryName[0] == '\0') &&
+ strncmp(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName, "FEDS_TB", 8) == 0)
+ break;
+#endif
int extraOffset = 0;
if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO)
@@ -1469,12 +1683,6 @@ CMenuManager::Draw()
if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1)
ResetHelperText();
}
-//#ifdef NO_ISLAND_LOADING
-// if (m_DisplayIslandLoading == m_PrefsIslandLoading) {
-// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL") && m_nHelperTextMsgId == 1)
-// ResetHelperText();
-// }
-//#endif
if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) {
if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH"))
SetHelperText(1);
@@ -1483,12 +1691,6 @@ CMenuManager::Draw()
if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES"))
SetHelperText(1);
}
-//#ifdef NO_ISLAND_LOADING
-// if (m_DisplayIslandLoading != m_PrefsIslandLoading) {
-// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL"))
-// SetHelperText(1);
-// }
-//#endif
if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) {
if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0
// To make assigning built-in actions to new custom options possible.
@@ -1535,6 +1737,12 @@ CMenuManager::Draw()
break;
}
+ // Needed after the bug fix in Font.cpp
+#ifdef FIX_BUGS
+ if (!CFont::Details.centre)
+ CFont::SetRightJustifyOff();
+#endif
+
// 60.0 is silly
nextYToUse += lineHeight * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText);
@@ -1559,7 +1767,36 @@ CMenuManager::Draw()
}
#ifdef CUSTOM_FRONTEND_OPTIONS
- lastOption = m_nCurrOption;
+ lastSelectedOpt = m_nCurrOption;
+#endif
+
+#ifdef SCROLLABLE_PAGES
+ #define SCROLLBAR_BOTTOM_X 125.0f // only for background, scrollbar's itself is calculated
+ #define SCROLLBAR_RIGHT_X 36.0f
+ #define SCROLLBAR_WIDTH 9.5f
+ #define SCROLLBAR_TOP_X 64
+
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) {
+ // Scrollbar background
+ CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_X),
+ MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_X)), CRGBA(100, 100, 66, FadeIn(205)));
+
+ float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION);
+ float scrollbarBottom, scrollbarTop;
+
+ scrollbarBottom = MENU_Y(SCROLLBAR_TOP_X - 8 + m_nScrollbarTopMargin + scrollbarHeight);
+ scrollbarTop = MENU_Y(SCROLLBAR_TOP_X + m_nScrollbarTopMargin);
+ // Scrollbar shadow
+ CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop,
+ MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)),
+ CRGBA(50, 50, 50, FadeIn(255)));
+
+ // Scrollbar
+ CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop,
+ MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - SCROLLBAR_WIDTH), scrollbarBottom),
+ CRGBA(235, 170, 50, FadeIn(255)));
+
+ }
#endif
switch (m_nCurrScreen) {
@@ -1573,13 +1810,9 @@ CMenuManager::Draw()
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
default:
- if (m_nCurrScreen > lastOgScreen) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id && screen.showLeftRightHelper) {
- DisplayHelperText();
- break;
- }
+ if (aScreens[m_nCurrScreen].layout) {
+ if (aScreens[m_nCurrScreen].layout->showLeftRightHelper) {
+ DisplayHelperText();
}
}
break;
@@ -2047,7 +2280,7 @@ CMenuManager::DrawControllerSetupScreen()
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
+ CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f));
PREPARE_MENU_HEADER
@@ -2236,27 +2469,28 @@ CMenuManager::DrawFrontEnd()
CFont::SetAlphaFade(255.0f);
#ifdef PS2_LIKE_MENU
+ #define setBbItem(a, b, c) strcpy(a.name, b); a.screenId = c;
if (m_nCurrScreen == MENUPAGE_NONE) {
if (m_bGameNotLoaded) {
if (bbTabCount != 6) {
- bbNames[0] = { "FEB_SAV",MENUPAGE_NEW_GAME };
- bbNames[1] = { "FEB_CON",MENUPAGE_CONTROLLER_PC };
- bbNames[2] = { "FEB_AUD",MENUPAGE_SOUND_SETTINGS };
- bbNames[3] = { "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS };
- bbNames[4] = { "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS };
- bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT };
+ setBbItem(bbNames[0], "FEB_SAV",MENUPAGE_NEW_GAME)
+ setBbItem(bbNames[1], "FEB_CON",MENUPAGE_CONTROLLER_PC)
+ setBbItem(bbNames[2], "FEB_AUD",MENUPAGE_SOUND_SETTINGS)
+ setBbItem(bbNames[3], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS)
+ setBbItem(bbNames[4], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS)
+ setBbItem(bbNames[5], "FESZ_QU",MENUPAGE_EXIT)
bbTabCount = 6;
}
} else {
if (bbTabCount != 8) {
- bbNames[0] = { "FEB_STA",MENUPAGE_STATS };
- bbNames[1] = { "FEB_SAV",MENUPAGE_NEW_GAME };
- bbNames[2] = { "FEB_BRI",MENUPAGE_BRIEFS };
- bbNames[3] = { "FEB_CON",MENUPAGE_CONTROLLER_PC };
- bbNames[4] = { "FEB_AUD",MENUPAGE_SOUND_SETTINGS };
- bbNames[5] = { "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS };
- bbNames[6] = { "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS };
- bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT };
+ setBbItem(bbNames[0], "FEB_STA",MENUPAGE_STATS)
+ setBbItem(bbNames[1], "FEB_SAV",MENUPAGE_NEW_GAME)
+ setBbItem(bbNames[2], "FEB_BRI",MENUPAGE_BRIEFS)
+ setBbItem(bbNames[3], "FEB_CON",MENUPAGE_CONTROLLER_PC)
+ setBbItem(bbNames[4], "FEB_AUD",MENUPAGE_SOUND_SETTINGS)
+ setBbItem(bbNames[5], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS)
+ setBbItem(bbNames[6], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS)
+ setBbItem(bbNames[7], "FESZ_QU",MENUPAGE_EXIT)
bbTabCount = 8;
}
}
@@ -2264,6 +2498,7 @@ CMenuManager::DrawFrontEnd()
bottomBarActive = true;
curBottomBarOption = 0;
}
+ #undef setBbItem
#else
if (m_nCurrScreen == MENUPAGE_NONE) {
if (m_bGameNotLoaded) {
@@ -2354,7 +2589,7 @@ CMenuManager::DrawFrontEndNormal()
m_aFrontEndSprites[FE2_MAINPANEL_UR].Draw(CRect(SCREEN_WIDTH / 2, 0.0f, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255));
m_aFrontEndSprites[FE2_MAINPANEL_DL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), SCREEN_HEIGHT / 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
m_aFrontEndSprites[FE2_MAINPANEL_DR].Draw(CRect(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
-
+
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
eFrontendSprites currentSprite;
switch (m_nCurrScreen) {
@@ -2394,39 +2629,15 @@ CMenuManager::DrawFrontEndNormal()
break;
}
- m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha));
-
static float fadeAlpha = 0.0f;
- static int lastState = 0;
- // reverseAlpha = PS2 fading (wait for 255->0, then change screen)
if (m_nMenuFadeAlpha < 255) {
- if (lastState == 1 && !reverseAlpha)
- fadeAlpha = 0.f;
-
- if (m_nMenuFadeAlpha <= 0 && reverseAlpha) {
- reverseAlpha = false;
- ChangeScreen(pendingScreen, pendingOption, true, false);
- } else {
- // +20 per every 33 ms (1000.f/30.f - original frame limiter fps)
- if (!reverseAlpha)
- fadeAlpha += (frameTime) * 20.f / 33.f;
- else
- fadeAlpha = max(0.0f, fadeAlpha - (frameTime) * 30.f / 33.f);
-
- m_nMenuFadeAlpha = fadeAlpha;
- }
- lastState = 0;
+ if (m_nMenuFadeAlpha == 0 && fadeAlpha > 1.0f) fadeAlpha = 0.0f;
+
+ // +20 per every 33 ms (1000.f/30.f - original frame limiter fps)
+ fadeAlpha += (frameTime) * 20.f / 33.f;
+ m_nMenuFadeAlpha = fadeAlpha;
} else {
- if (lastState == 0) fadeAlpha = 255.f;
-
- if (reverseAlpha) {
- fadeAlpha -= (frameTime) * 30.f / 33.f;
-
- m_nMenuFadeAlpha = fadeAlpha;
- }
- lastState = 1;
-
// TODO: what is this? waiting mouse?
if(field_518 == 4){
if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 ||
@@ -2438,6 +2649,8 @@ CMenuManager::DrawFrontEndNormal()
}
}
+ m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha));
+
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
@@ -2463,7 +2676,7 @@ CMenuManager::DrawFrontEndNormal()
CFont::SetJustifyOn();
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
- CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(40.0f)); // 600.0f
+ CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); // 600.0f
CFont::SetColor(CRGBA(16, 16, 16, 255));
switch (m_nCurrScreen) {
@@ -2612,17 +2825,10 @@ CMenuManager::DrawFrontEndNormal()
break;
default:
#ifdef CUSTOM_FRONTEND_OPTIONS
- bool custom = m_nPrevScreen > lastOgScreen;
+ CCustomScreenLayout *custom = aScreens[m_nPrevScreen].layout;
if (custom) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nPrevScreen == screen.id) {
- previousSprite = screen.sprite;
- break;
- }
- if (i == numCustomFrontendScreens - 1)
- custom = false;
- }
+ previousSprite = custom->sprite;
+ break;
}
if (!custom)
#endif
@@ -2678,15 +2884,9 @@ CMenuManager::DrawFrontEndNormal()
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
default:
- bool custom = m_nCurrScreen > lastOgScreen;
+ CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout;
if (custom) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id) {
- currentSprite = screen.sprite;
- break;
- }
- }
+ previousSprite = custom->sprite;
}
break;
#endif
@@ -2794,7 +2994,7 @@ CMenuManager::DrawPlayerSetupScreen()
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
+ CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f));
PREPARE_MENU_HEADER
@@ -2986,14 +3186,13 @@ CMenuManager::DrawPlayerSetupScreen()
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205)));
- // Scrollbar
- float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float) MAX_VISIBLE_LIST_ROW;
+ float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nSkinsTotal / (float) MAX_VISIBLE_LIST_ROW);
float scrollbarBottom, scrollbarTop;
if (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) {
scrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f);
scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP);
- // Shadow
+ // Scrollbar shadow
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255)));
} else {
@@ -3004,12 +3203,13 @@ CMenuManager::DrawPlayerSetupScreen()
scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 4 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal);
scrollbarTop = MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin);
#endif
- // Shadow
+ // Scrollbar shadow
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)),
CRGBA(50, 50, 50, FadeIn(255)));
}
+ // Scrollbar
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom),
CRGBA(235, 170, 50, FadeIn(255)));
@@ -3301,10 +3501,6 @@ CMenuManager::InitialiseChangedLanguageSettings()
default:
break;
}
-
-#ifdef CUSTOM_FRONTEND_OPTIONS
- CustomFrontendOptionsPopulate();
-#endif
}
}
@@ -3342,7 +3538,7 @@ CMenuManager::LoadAllTextures()
CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD");
CTxdStore::AddRef(frontendTxdSlot);
CTxdStore::SetCurrentTxd(frontendTxdSlot);
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
CStreaming::IHaveUsedStreamingMemory();
CTimer::Update();
#endif
@@ -3372,7 +3568,7 @@ CMenuManager::LoadAllTextures()
m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
}
#endif
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
CStreaming::IHaveUsedStreamingMemory();
CTimer::Update();
#endif
@@ -3387,7 +3583,7 @@ CMenuManager::LoadSettings()
int fileHandle = CFileMgr::OpenFile("gta3.set", "r");
int32 prevLang = m_PrefsLanguage;
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
CMBlur::BlurOn = (_dwOperatingSystemVersion != OS_WIN98);
#else
CMBlur::BlurOn = true;
@@ -3494,6 +3690,9 @@ CMenuManager::LoadSettings()
strcpy(m_PrefsSkinFile, DEFAULT_SKIN_NAME);
strcpy(m_aSkinName, DEFAULT_SKIN_NAME);
}
+#ifdef LOAD_INI_SETTINGS
+ LoadINISettings(); // needs frontend options to be loaded
+#endif
}
void
@@ -3575,8 +3774,8 @@ CMenuManager::MessageScreen(const char *text)
CFont::SetPropOn();
CFont::SetJustifyOn();
CFont::SetBackGroundOnlyTextOn();
- CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // not used
- CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // not used
+ CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // unused
+ CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // unused
CSprite2d::DrawRect(CRect(StretchX(120.0f), StretchY(150.0f), SCREEN_WIDTH - StretchX(120.0f), SCREEN_HEIGHT - StretchY(220.0f)), CRGBA(50, 50, 50, 210));
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
CFont::SetCentreSize(SCREEN_SCALE_X(380.0f));
@@ -3670,7 +3869,7 @@ CMenuManager::PrintErrorMessage()
CFont::SetJustifyOn();
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
- CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f));
+ CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(MENU_X_MARGIN));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(180.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT"));
#else
@@ -3683,7 +3882,7 @@ void
CMenuManager::PrintStats()
{
int rowNum = ConstructStatLine(99999);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
#endif
CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why
@@ -3958,12 +4157,22 @@ CMenuManager::ProcessButtonPresses(void)
DoSettingsBeforeStartingAGame();
return;
}
+ if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_D) == GLFW_PRESS) {
+ scriptToLoad = 2;
+ DoSettingsBeforeStartingAGame();
+ return;
+ }
#elif defined _WIN32
if (GetAsyncKeyState('R') & 0x8000) {
scriptToLoad = 1;
DoSettingsBeforeStartingAGame();
return;
}
+ if (GetAsyncKeyState('D') & 0x8000) {
+ scriptToLoad = 2;
+ DoSettingsBeforeStartingAGame();
+ return;
+ }
#endif
}
#endif
@@ -3982,235 +4191,10 @@ CMenuManager::ProcessButtonPresses(void)
if (m_nMousePosY < 0) m_nMousePosY = 0;
if (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT;
- if (m_nCurrScreen == MENUPAGE_MULTIPLAYER_FIND_GAME || m_nCurrScreen == MENUPAGE_SKIN_SELECT
- || m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {
-
- if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {
- m_nTotalListRow = m_nSkinsTotal;
- }
- if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {
- m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25;
- if (m_nSelectedListRow > m_nTotalListRow)
- m_nSelectedListRow = m_nTotalListRow - 1;
- }
-
-#ifndef TIDY_UP_PBP
- if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {
- m_bShowMouse = 0;
- optionSelected = true;
- }
-#endif
- if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) {
- if (m_nCurrExLayer == HOVEROPTION_LIST) {
- m_nHoverOption = HOVEROPTION_NOT_HOVERING;
- m_bWaitingForNewKeyBind = true;
- m_bStartWaitingForKeyBind = true;
- m_bKeyChangeNotProcessed = true;
- pControlEdit = &m_KeyPressedCode;
- }
- } else {
- field_535 = false;
- }
-
- static uint32 lastTimeClickedScrollButton = 0;
-
- if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) {
- m_bPressedPgUpOnList = false;
- m_bPressedPgDnOnList = false;
- m_bPressedUpOnList = false;
- m_bPressedDownOnList = false;
- m_bPressedScrollButton = false;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- }
-
- if (CPad::GetPad(0)->GetTabJustDown()) {
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- m_bShowMouse = false;
- switch (m_nCurrExLayer) {
- case HOVEROPTION_BACK:
- default:
- m_nCurrExLayer = HOVEROPTION_LIST;
- break;
- case HOVEROPTION_LIST:
- m_nCurrExLayer = HOVEROPTION_USESKIN;
- break;
- case HOVEROPTION_USESKIN:
- m_nCurrExLayer = HOVEROPTION_BACK;
- }
- if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) {
- m_nCurrExLayer = HOVEROPTION_BACK;
- }
- if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) {
- m_nCurrExLayer = HOVEROPTION_BACK;
- }
- }
-
- bool pressed = false;
- if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {
- m_bShowMouse = false;
- pressed = true;
- } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) {
- m_bShowMouse = true;
- pressed = true;
- }
-
- // Up
- if (pressed) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedUpOnList) {
- m_bPressedUpOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- ScrollUpListByOne();
- }
- } else {
- m_bPressedUpOnList = false;
- }
-
- pressed = false;
- if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {
- m_bShowMouse = false;
- pressed = true;
- } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {
- m_bShowMouse = true;
- pressed = true;
- }
-
- // Down
- if (pressed) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedDownOnList) {
- m_bPressedDownOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- ScrollDownListByOne();
- }
- } else {
- m_bPressedDownOnList = false;
- }
-
- if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
- if (!CPad::GetPad(0)->GetPageUp()) {
- m_bPressedPgUpOnList = false;
- } else {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedPgUpOnList) {
- m_bPressedPgUpOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- PageUpList(false);
- }
- }
- if (!CPad::GetPad(0)->GetPageDown()) {
- m_bPressedPgDnOnList = false;
- } else {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedPgDnOnList) {
- m_bPressedPgDnOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- PageDownList(false);
- }
- }
- if (CPad::GetPad(0)->GetHome()) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) {
- m_nFirstVisibleRowOnList = 0;
- }
- m_nSelectedListRow = 0;
- m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
- }
- if (CPad::GetPad(0)->GetEnd()) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) {
- m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW;
- }
- m_nSelectedListRow = m_nTotalListRow - 1;
- m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
- }
- }
-
-#ifndef TIDY_UP_PBP
- if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) {
- m_bShowMouse = false;
- goBack = true;
- }
-#endif
-
- if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
- switch (m_nHoverOption) {
- case HOVEROPTION_BACK:
- goBack = true;
- break;
- case HOVEROPTION_PAGEUP:
- PageUpList(true);
- break;
- case HOVEROPTION_PAGEDOWN:
- PageDownList(true);
- break;
- case HOVEROPTION_USESKIN:
- if (m_nSkinsTotal > 0) {
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
- m_pSelectedSkin = m_pSkinListHead.nextSkin;
- strcpy(m_PrefsSkinFile, m_aSkinName);
- CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
- SaveSettings();
- }
- }
- }
+ if (hasNativeList(m_nCurrScreen)) {
+ // Not split to seperate function in III as in VC, but we need it for scrollable pages :)
+ ProcessList(goBack, optionSelected);
- if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
- switch (m_nHoverOption) {
- case HOVEROPTION_OVER_SCROLL_UP:
- m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP;
- break;
- case HOVEROPTION_OVER_SCROLL_DOWN:
- m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN;
- break;
- case HOVEROPTION_LIST:
- m_nHoverOption = HOVEROPTION_SKIN;
- }
- } else if ((CPad::GetPad(0)->GetLeftMouseJustUp())
- && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) {
- m_nHoverOption = HOVEROPTION_NOT_HOVERING;
- }
-
- if (!CPad::GetPad(0)->GetLeftMouse()) {
- holdingScrollBar = false;
- } else {
- if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) {
- holdingScrollBar = true;
- // TODO: This part is a bit hard to reverse. Not much code tho
- assert(0 && "Holding scrollbar isn't done yet");
- } else {
- switch (m_nHoverOption) {
- case HOVEROPTION_OVER_SCROLL_UP:
- case HOVEROPTION_CLICKED_SCROLL_UP:
- if (!m_bPressedScrollButton) {
- m_bPressedScrollButton = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- ScrollUpListByOne();
- }
- break;
- case HOVEROPTION_OVER_SCROLL_DOWN:
- case HOVEROPTION_CLICKED_SCROLL_DOWN:
- if (!m_bPressedScrollButton) {
- m_bPressedScrollButton = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- ScrollDownListByOne();
- }
- break;
- default:
- m_bPressedScrollButton = false;
- }
- }
- }
} else if (isPlainTextScreen(m_nCurrScreen)) {
#ifndef TIDY_UP_PBP
if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) {
@@ -4449,7 +4433,7 @@ CMenuManager::ProcessButtonPresses(void)
TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl;
SaveSettings();
break;
- }
+ }
#else
switch (m_nHoverOption) {
case HOVEROPTION_INCREASE_BRIGHTNESS:
@@ -4468,7 +4452,26 @@ CMenuManager::ProcessButtonPresses(void)
break;
}
#endif
- }
+ }
+
+#ifdef SCROLLABLE_PAGES
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION) {
+ bool temp = false;
+
+ m_nSelectedListRow = m_nCurrOption;
+
+ // ignore detected back/select states, it's our screen's job
+ ProcessList(temp, temp);
+
+ // and ignore our screen's goUp/Down, now it's ProcessList's job
+ goUp = false;
+ goDown = false;
+ m_nCurrOption = m_nSelectedListRow;
+ }
+
+ // Prevent sound on scroll. Mouse wheel is now belongs to us!
+ if (!(m_nTotalListRow > MAX_VISIBLE_OPTION && (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown())))
+#endif
if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp()
|| CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp()
@@ -4483,6 +4486,7 @@ CMenuManager::ProcessButtonPresses(void)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
}
+
#ifndef TIDY_UP_PBP
if (CPad::GetPad(0)->GetBackJustDown()) {
if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU) {
@@ -4502,7 +4506,7 @@ CMenuManager::ProcessButtonPresses(void)
goBack = false;
}
#endif
- }
+ }
// Centralized enter/back (except some conditions)
#ifdef TIDY_UP_PBP
@@ -4555,16 +4559,10 @@ CMenuManager::ProcessButtonPresses(void)
if (bbNames[curBottomBarOption].screenId == MENUPAGE_SOUND_SETTINGS)
DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1);
- // If there's a menu change with fade ongoing, finish it now
- if (reverseAlpha)
- m_nMenuFadeAlpha = 0;
return;
} else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()
|| CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {
- if (reverseAlpha && m_nMenuFadeAlpha > 30)
- return;
-
m_bShowMouse = false;
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
curBottomBarOption = ((curBottomBarOption + bbTabCount) - 1) % bbTabCount;
@@ -4573,9 +4571,6 @@ CMenuManager::ProcessButtonPresses(void)
} else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()
|| CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {
- if (reverseAlpha && m_nMenuFadeAlpha > 30)
- return;
-
m_bShowMouse = false;
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
curBottomBarOption = ((curBottomBarOption + bbTabCount) + 1) % bbTabCount;
@@ -4606,6 +4601,12 @@ CMenuManager::ProcessButtonPresses(void)
}
}
+ // Hide back button
+#ifdef PS2_LIKE_MENU
+ if ((goUp || goDown) && m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME && strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0)
+ m_nCurrOption = goUp ? m_nCurrOption - 1 : (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL);
+#endif
+
if (optionSelected) {
int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action;
if ((option == MENUACTION_CHANGEMENU) || (option == MENUACTION_POPULATESLOTS_CHANGEMENU)) {
@@ -4879,45 +4880,6 @@ CMenuManager::ProcessButtonPresses(void)
SaveSettings();
}
break;
-//#ifdef NO_ISLAND_LOADING
-// case MENUACTION_ISLANDLOADING:
-// if (m_DisplayIslandLoading != m_PrefsIslandLoading) {
-// if (!m_bGameNotLoaded) {
-// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) {
-// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH)
-// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
-// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) {
-// if (CGame::currLevel != LEVEL_INDUSTRIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
-// if (CGame::currLevel != LEVEL_COMMERCIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
-// if (CGame::currLevel != LEVEL_SUBURBAN)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
-// CCollision::bAlreadyLoaded = true;
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestBigBuildings(CGame::currLevel);
-// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) {
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestIslands(CGame::currLevel);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// } else { // low
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CCollision::bAlreadyLoaded = false;
-// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
-// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
-// CStreaming::RemoveUnusedBuildings(CGame::currLevel);
-// CStreaming::RequestIslands(CGame::currLevel);
-// }
-//
-// CStreaming::LoadAllRequestedModels(true);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// SetHelperText(0);
-// SaveSettings();
-// }
-// break;
-//#endif
case MENUACTION_AUDIOHW:
{
int selectedProvider = m_nPrefsAudio3DProviderIndex;
@@ -4974,7 +4936,7 @@ CMenuManager::ProcessButtonPresses(void)
m_PrefsUseWideScreen = false;
m_PrefsShowSubtitles = true;
m_nDisplayVideoMode = m_nPrefsVideoMode;
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
if (_dwOperatingSystemVersion == OS_WIN98) {
CMBlur::BlurOn = false;
CMBlur::MotionBlurClose();
@@ -4992,40 +4954,6 @@ CMenuManager::ProcessButtonPresses(void)
RestoreDefGraphics(FEOPTION_ACTION_SELECT);
RestoreDefDisplay(FEOPTION_ACTION_SELECT);
#endif
-//#ifdef NO_ISLAND_LOADING
-// m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-// if (!m_bGameNotLoaded) {
-// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) {
-// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH)
-// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
-// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) {
-// if (CGame::currLevel != LEVEL_INDUSTRIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
-// if (CGame::currLevel != LEVEL_COMMERCIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
-// if (CGame::currLevel != LEVEL_SUBURBAN)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
-// CCollision::bAlreadyLoaded = true;
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestBigBuildings(CGame::currLevel);
-// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) {
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestIslands(CGame::currLevel);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// } else { // low
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CCollision::bAlreadyLoaded = false;
-// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
-// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
-// CStreaming::RemoveUnusedBuildings(CGame::currLevel);
-// CStreaming::RequestIslands(CGame::currLevel);
-// }
-//
-// CStreaming::LoadAllRequestedModels(true);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-//#endif // NO_ISLAND_LOADING
SaveSettings();
} else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) {
ControlsManager.MakeControllerActionsBlank();
@@ -5086,29 +5014,28 @@ CMenuManager::ProcessButtonPresses(void)
return;
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- case MENUACTION_TRIGGERFUNC:
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu];
- if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) {
- if (option.type == FEOPTION_SELECT) {
- if (!option.onlyApplyOnEnter) {
- option.displayedValue++;
- if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0)
- option.displayedValue = 0;
- }
- option.changeFunc(option.displayedValue);
- *option.value = option.lastSavedValue = option.displayedValue;
-
- } else if (option.type == FEOPTION_DYNAMIC) {
- if (option.buttonPressFunc)
- option.buttonPressFunc(FEOPTION_ACTION_SELECT);
- } else if (option.type == FEOPTION_REDIRECT) {
- ChangeScreen(option.to, option.option, true, option.fadeIn);
- } else if (option.type == FEOPTION_GOBACK) {
- goBack = true;
+ case MENUACTION_CFO_SELECT:
+ case MENUACTION_CFO_DYNAMIC:
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (!option.m_CFOSelect->onlyApplyOnEnter) {
+ option.m_CFOSelect->displayedValue++;
+ if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)
+ option.m_CFOSelect->displayedValue = 0;
}
- } else {
- debug("B- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder);
- assert(0 && "Custom frontend options are borked");
+ int8 oldValue = *option.m_CFO->value;
+
+ *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue;
+
+ if (option.m_CFOSelect->save)
+ SaveSettings();
+
+ if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc)
+ option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue);
+
+ } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) {
+ if (option.m_CFODynamic->buttonPressFunc)
+ option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT);
}
break;
@@ -5116,14 +5043,6 @@ CMenuManager::ProcessButtonPresses(void)
}
}
ProcessOnOffMenuOptions();
-#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu];
- if (option.type == FEOPTION_BUILTIN_ACTION && option.buttonPressFunc) {
- option.buttonPressFunc(FEOPTION_ACTION_SELECT);
- }
- }
-#endif
}
if (goBack) {
@@ -5213,23 +5132,27 @@ CMenuManager::ProcessButtonPresses(void)
if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) {
m_bShowMouse = false;
increase = true;
- } else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
+ } else if (
+#ifdef SCROLLABLE_PAGES
+ !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) &&
+#endif
+ CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
increase = true;
CheckSliderMovement(1);
m_bShowMouse = true;
}
- if (!CPad::GetPad(0)->GetLeftJustDown() && !CPad::GetPad(0)->GetAnaloguePadLeft() && !CPad::GetPad(0)->GetDPadLeftJustDown()) {
- if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {
- if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
- decrease = true;
- CheckSliderMovement(-1);
- m_bShowMouse = true;
- }
- }
- } else {
+ if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) {
m_bShowMouse = false;
decrease = true;
+ } else if (
+#ifdef SCROLLABLE_PAGES
+ !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) &&
+#endif
+ CPad::GetPad(0)->GetMouseWheelDownJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
+ decrease = true;
+ CheckSliderMovement(-1);
+ m_bShowMouse = true;
}
if (increase)
@@ -5294,15 +5217,6 @@ CMenuManager::ProcessButtonPresses(void)
}
}
break;
-//#ifdef NO_ISLAND_LOADING
-// case MENUACTION_ISLANDLOADING:
-// m_DisplayIslandLoading += changeValueBy;
-// if (m_DisplayIslandLoading > ISLAND_LOADING_HIGH)
-// m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-// else if (m_DisplayIslandLoading < ISLAND_LOADING_LOW)
-// m_DisplayIslandLoading = ISLAND_LOADING_HIGH;
-// break;
-//#endif
case MENUACTION_AUDIOHW:
if (m_nPrefsAudio3DProviderIndex != -1) {
m_nPrefsAudio3DProviderIndex += changeValueBy;
@@ -5326,32 +5240,34 @@ CMenuManager::ProcessButtonPresses(void)
SaveSettings();
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
- case MENUACTION_TRIGGERFUNC:
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu];
- if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) {
- if (option.type == FEOPTION_SELECT) {
- if (changeValueBy > 0) {
- option.displayedValue++;
- if (option.displayedValue >= option.numRightTexts)
- option.displayedValue = 0;
- } else {
- option.displayedValue--;
- if (option.displayedValue < 0)
- option.displayedValue = option.numRightTexts - 1;
- }
- if (!option.onlyApplyOnEnter) {
- option.changeFunc(option.displayedValue);
- *option.value = option.lastSavedValue = option.displayedValue;
- }
- } else if (option.type == FEOPTION_DYNAMIC && option.buttonPressFunc) {
- option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT);
+ case MENUACTION_CFO_SELECT:
+ case MENUACTION_CFO_DYNAMIC:
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (changeValueBy > 0) {
+ option.m_CFOSelect->displayedValue++;
+ if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts)
+ option.m_CFOSelect->displayedValue = 0;
+ } else {
+ option.m_CFOSelect->displayedValue--;
+ if (option.m_CFOSelect->displayedValue < 0)
+ option.m_CFOSelect->displayedValue = option.m_CFOSelect->numRightTexts - 1;
}
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
- }
- else {
- debug("C- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder);
- assert(0 && "Custom frontend options are borked");
+ if (!option.m_CFOSelect->onlyApplyOnEnter) {
+ int8 oldValue = *option.m_CFO->value;
+
+ *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue;
+
+ if (option.m_CFOSelect->save)
+ SaveSettings();
+
+ if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc)
+ option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue);
+ }
+ } else if (option.m_Action == MENUACTION_CFO_DYNAMIC && option.m_CFODynamic->buttonPressFunc) {
+ option.m_CFODynamic->buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT);
}
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
break;
#endif
@@ -5527,6 +5443,10 @@ CMenuManager::SetHelperText(int text)
void
CMenuManager::ShutdownJustMenu()
{
+ // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions.
+#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE)
+ glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+#endif
m_bMenuActive = false;
CTimer::EndUserPause();
}
@@ -5623,8 +5543,14 @@ CMenuManager::SwitchMenuOnAndOff()
gMusicPlaying = 0;
}
*/
- if (m_bMenuActive != menuWasActive)
+ if (m_bMenuActive != menuWasActive) {
m_bMenuStateChanged = true;
+
+ // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions.
+#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE)
+ glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, m_bMenuActive && m_nPrefsWindowed ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED);
+#endif
+ }
m_bStartUpFrontEndRequested = false;
m_bShutDownFrontEndRequested = false;
@@ -5662,7 +5588,7 @@ CMenuManager::WaitForUserCD()
CSprite2d *splash;
char *splashscreen = nil;
-#if (!(defined RANDOMSPLASH) && !(defined GTA3_1_1_PATCH))
+#if (!(defined RANDOMSPLASH) && GTA_VERSION < GTA3_PC_11)
if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame)
splashscreen = "mainsc2";
else
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 848148e7..21124fdb 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -18,7 +18,6 @@
#define MENU_X_MARGIN 40.0f
#define MENUACTION_POS_Y 60.0f
-#define MENUACTION_WIDTH 38.0f
#define MENUACTION_SCALE_MULT 0.9f
#define MENURADIO_ICON_SCALE 60.0f
@@ -156,9 +155,6 @@ enum eSaveSlot
SAVESLOT_7,
SAVESLOT_8,
SAVESLOT_LABEL = 36,
-#ifdef CUSTOM_FRONTEND_OPTIONS
- SAVESLOT_CFO
-#endif
};
#ifdef MENU_MAP
@@ -239,18 +235,31 @@ enum eMenuScreen
MENUPAGE_MOUSE_CONTROLS = 56,
MENUPAGE_MISSION_RETRY = 57,
#ifdef MENU_MAP
- MENUPAGE_MAP,
+ MENUPAGE_MAP = 58,
#endif
- MENUPAGE_UNK, // 58 in game. Map page is added above, because last screen in CMenuScreens should always be empty to make CFO work
#ifdef CUSTOM_FRONTEND_OPTIONS
- MENUPAGES = 65 // for some room to add more screen
+
+#ifdef GRAPHICS_MENU_OPTIONS
+ MENUPAGE_GRAPHICS_SETTINGS,
#else
- MENUPAGES
+ MENUPAGE_ADVANCED_DISPLAY_SETTINGS,
+#endif
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+ MENUPAGE_DETECT_JOYSTICK,
#endif
+
+#endif
+ MENUPAGE_UNK, // originally 58. Custom screens are inserted above, because last screen in CMenuScreens should always be empty to make CFO work
+ MENUPAGES
+
};
enum eMenuAction
{
+#ifdef CUSTOM_FRONTEND_OPTIONS
+ MENUACTION_CFO_SELECT = -2,
+ MENUACTION_CFO_DYNAMIC = -1,
+#endif
MENUACTION_NOTHING,
MENUACTION_LABEL,
MENUACTION_CHANGEMENU,
@@ -370,12 +379,6 @@ enum eMenuAction
// MENUACTION_MIPMAPS,
// MENUACTION_TEXTURE_FILTERING,
//#endif
-//#ifdef NO_ISLAND_LOADING
-// MENUACTION_ISLANDLOADING,
-//#endif
-#ifdef CUSTOM_FRONTEND_OPTIONS
- MENUACTION_TRIGGERFUNC
-#endif
};
enum eCheckHover
@@ -458,6 +461,7 @@ struct BottomBarOption
int32 screenId;
};
+#ifndef CUSTOM_FRONTEND_OPTIONS
struct CMenuScreen
{
char m_ScreenName[8];
@@ -470,9 +474,91 @@ struct CMenuScreen
int32 m_Action; // eMenuAction
char m_EntryName[8];
int32 m_SaveSlot; // eSaveSlot
- int32 m_TargetMenu; // eMenuScreen // FrontendOption ID if it's a custom option
+ int32 m_TargetMenu; // eMenuScreen
} m_aEntries[NUM_MENUROWS];
};
+extern CMenuScreen aScreens[MENUPAGES];
+#else
+#include "frontendoption.h"
+struct CCustomScreenLayout {
+ eMenuSprites sprite;
+ int columnWidth;
+ int headerHeight;
+ int lineHeight;
+ int8 font;
+ int8 alignment;
+ bool showLeftRightHelper;
+ float fontScaleX;
+ float fontScaleY;
+};
+
+struct CCFO
+{
+ int8 *value;
+ const char *save;
+};
+
+struct CCFOSelect : CCFO
+{
+ char** rightTexts;
+ int8 numRightTexts;
+ bool onlyApplyOnEnter;
+ int8 displayedValue; // only if onlyApplyOnEnter enabled for now
+ int8 lastSavedValue; // only if onlyApplyOnEnter enabled
+ ChangeFunc changeFunc;
+
+ CCFOSelect() {};
+ CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc){
+ this->value = value;
+ if (value)
+ this->lastSavedValue = this->displayedValue = *value;
+
+ this->save = save;
+ this->rightTexts = (char**)rightTexts;
+ this->numRightTexts = numRightTexts;
+ this->onlyApplyOnEnter = onlyApplyOnEnter;
+ this->changeFunc = changeFunc;
+ }
+};
+
+struct CCFODynamic : CCFO
+{
+ DrawFunc drawFunc;
+ ButtonPressFunc buttonPressFunc;
+
+ CCFODynamic() {};
+ CCFODynamic(int8* value, const char* save, DrawFunc drawFunc, ButtonPressFunc buttonPressFunc){
+ this->value = value;
+ this->save = save;
+ this->drawFunc = drawFunc;
+ this->buttonPressFunc = buttonPressFunc;
+ }
+};
+
+struct CMenuScreenCustom
+{
+ char m_ScreenName[8];
+ int32 m_PreviousPage[2]; // eMenuScreen
+ CCustomScreenLayout *layout;
+ ReturnPrevPageFunc returnPrevPageFunc;
+
+ struct CMenuEntry
+ {
+ int32 m_Action; // eMenuAction - below zero is CFO
+ char m_EntryName[8];
+ struct {
+ union {
+ CCFO *m_CFO; // for initializing
+ CCFOSelect *m_CFOSelect;
+ CCFODynamic *m_CFODynamic;
+ };
+ int32 m_SaveSlot; // eSaveSlot
+ int32 m_TargetMenu; // eMenuScreen
+ };
+ } m_aEntries[NUM_MENUROWS];
+};
+extern CMenuScreenCustom aScreens[MENUPAGES];
+#endif
class CMenuManager
{
@@ -628,7 +714,6 @@ public:
ISLAND_LOADING_HIGH
};
- static int8 m_DisplayIslandLoading;
static int8 m_PrefsIslandLoading;
#define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p)
@@ -696,6 +781,7 @@ public:
void PageUpList(bool);
void PageDownList(bool);
int8 GetPreviousPageOption();
+ void ProcessList(bool &goBack, bool &optionSelected);
};
#ifndef IMPROVED_VIDEOMODE
@@ -703,6 +789,5 @@ VALIDATE_SIZE(CMenuManager, 0x564);
#endif
extern CMenuManager FrontEndMenuManager;
-extern CMenuScreen aScreens[MENUPAGES];
-#endif \ No newline at end of file
+#endif
diff --git a/src/core/Frontend_PS2.cpp b/src/core/Frontend_PS2.cpp
index a76ac279..1cb944d1 100644
--- a/src/core/Frontend_PS2.cpp
+++ b/src/core/Frontend_PS2.cpp
@@ -22,7 +22,7 @@
#include "Game.h"
#include "World.h"
#include "PlayerInfo.h"
-#include "FrontendControls.h"
+#include "FrontEndControls.h"
#include "MemoryCard.h"
#define CRect_SZ(x, y, w, h) CRect(x, y, x+w, y+h)
@@ -203,20 +203,6 @@ static const char* FrontendFilenames[][2] =
{"fe_radio9", "" },
};
-#ifdef CUTSCENE_BORDERS_SWITCH
-bool CMenuManager::m_PrefsCutsceneBorders = true;
-#endif
-
-#ifdef MULTISAMPLING
-int8 CMenuManager::m_nPrefsMSAALevel = 0;
-int8 CMenuManager::m_nDisplayMSAALevel = 0;
-#endif
-
-#ifdef NO_ISLAND_LOADING
-int8 CMenuManager::m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
-#endif
-
int32 CMenuManager::m_PrefsSfxVolume = 102;
int32 CMenuManager::m_PrefsMusicVolume = 102;
int32 CMenuManager::m_PrefsBrightness = 256;
@@ -3044,4 +3030,4 @@ CMenuManager::FilterOutColorMarkersFromString(wchar *string, CRGBA &color)
*dst = '\0';
}
-#endif \ No newline at end of file
+#endif
diff --git a/src/core/Frontend_PS2.h b/src/core/Frontend_PS2.h
index c1e42291..4bab7df9 100644
--- a/src/core/Frontend_PS2.h
+++ b/src/core/Frontend_PS2.h
@@ -160,31 +160,9 @@ public:
static int32 m_PrefsLanguage;
static CONTRCONFIG m_PrefsControllerConfig;
static bool m_PrefsUseVibration;
-#ifdef NO_ISLAND_LOADING
- enum
- {
- ISLAND_LOADING_LOW = 0,
- ISLAND_LOADING_MEDIUM,
- ISLAND_LOADING_HIGH
- };
-
- static int8 m_DisplayIslandLoading;
- static int8 m_PrefsIslandLoading;
-#define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p)
-#define ISLAND_LOADING_ISNT(p) if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_##p)
-#else
#define ISLAND_LOADING_IS(p)
#define ISLAND_LOADING_ISNT(p)
-#endif
-#ifdef CUTSCENE_BORDERS_SWITCH
- static bool m_PrefsCutsceneBorders;
-#endif
-#ifdef MULTISAMPLING
- static int8 m_nPrefsMSAALevel;
- static int8 m_nDisplayMSAALevel;
-#endif
-
#ifdef GTA_PC
bool m_bQuitGameNoCD;
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index ef4800c5..33302653 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -86,10 +86,14 @@
#include "ZoneCull.h"
#include "Zones.h"
#include "debugmenu.h"
-#include "frontendoption.h"
#include "postfx.h"
#include "custompipes.h"
+#include "screendroplets.h"
#include "crossplatform.h"
+#include "MemoryHeap.h"
+#ifdef USE_TEXTURE_POOL
+#include "TexturePools.h"
+#endif
eLevelName CGame::currLevel;
bool CGame::bDemoMode = true;
@@ -129,7 +133,7 @@ void MessageScreen(char *msg)
CFont::SetFontStyle(FONT_BANK);
CFont::SetBackgroundOff();
- CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f // unused
+ CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f
CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f));
CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_SCALE_X(450.0f)); // 450.0f
@@ -172,19 +176,33 @@ CGame::InitialiseRenderWare(void)
#ifdef USE_TEXTURE_POOL
_TexturePoolsInitialise();
#endif
-
- CTxdStore::Initialise();
- CVisibilityPlugins::Initialise();
-
+
+#if GTA_VERSION > GTA3_PS2_160
+ CTxdStore::Initialise(); // in GameInit on ps2
+ CVisibilityPlugins::Initialise(); // in plugin attach on ps2
+#endif
+
+ //InitialiseScene(Scene); // PS2 only, only clears Scene.camera
+
+#ifdef GTA_PS2
+ RpSkySelectTrueTSClipper(TRUE);
+ RpSkySelectTrueTLClipper(TRUE);
+
+ // PS2ManagerApplyDirectionalLightingCB() uploads the GTA lights
+ // directly without going through RpWorld and all that
+ SetupPS2ManagerDefaultLightingCallback();
+ PreAllocateRwObjects();
+#endif
+
/* Create camera */
- Scene.camera = CameraCreate(RsGlobal.width, RsGlobal.height, TRUE);
+ Scene.camera = CameraCreate(SCREEN_WIDTH, SCREEN_HEIGHT, TRUE);
ASSERT(Scene.camera != nil);
if (!Scene.camera)
{
return (false);
}
- RwCameraSetFarClipPlane(Scene.camera, 2000.0f);
+ RwCameraSetFarClipPlane(Scene.camera, 2000.0f); // 250.0f on PS2 but who cares
RwCameraSetNearClipPlane(Scene.camera, 0.9f);
CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
@@ -207,8 +225,12 @@ CGame::InitialiseRenderWare(void)
/* Add the camera to the world */
RpWorldAddCamera(Scene.world, Scene.camera);
LightsCreate(Scene.world);
-
- CreateDebugFont();
+
+#if GTA_VERSION > GTA3_PS2_160
+ CreateDebugFont(); // in GameInit on PS2
+#else
+ RwImageSetPath("textures");
+#endif
#ifdef LIBRW
#ifdef PS2_MATFX
@@ -224,14 +246,22 @@ CGame::InitialiseRenderWare(void)
ReplaceAtomicPipeCallback();
#endif // PS2_ALPHA_TEST
#endif // LIBRW
-
+
+
+#if GTA_VERSION > GTA3_PS2_160
+ // in GameInit on PS2
+ PUSH_MEMID(MEMID_TEXTURES);
CFont::Initialise();
CHud::Initialise();
+ POP_MEMID();
+#endif
+ // TODO: define
CPlayerSkin::Initialise();
return (true);
}
+// missing altogether on PS2
void CGame::ShutdownRenderWare(void)
{
CMBlur::MotionBlurClose();
@@ -241,7 +271,8 @@ void CGame::ShutdownRenderWare(void)
for ( int32 i = 0; i < NUMPLAYERS; i++ )
CWorld::Players[i].DeletePlayerSkin();
-
+
+ // TODO: define
CPlayerSkin::Shutdown();
DestroyDebugFont();
@@ -264,16 +295,19 @@ void CGame::ShutdownRenderWare(void)
#endif
}
+// missing altogether on PS2
bool CGame::InitialiseOnceAfterRW(void)
{
+#if GTA_VERSION > GTA3_PS2_160
TheText.Load();
- DMAudio.Initialise();
+ DMAudio.Initialise(); // before TheGame() on PS2
CTimer::Initialise();
CTempColModels::Initialise();
mod_HandlingManager.Initialise();
CSurfaceTable::Initialise("DATA\\SURFACE.DAT");
CPedStats::Initialise();
CTimeCycle::Initialise();
+#endif
if ( DMAudio.GetNum3DProvidersAvailable() == 0 )
FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1;
@@ -314,19 +348,10 @@ bool CGame::InitialiseOnceAfterRW(void)
DMAudio.SetMusicFadeVol(127);
CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile);
-#ifdef CUSTOM_FRONTEND_OPTIONS
- // Apparently this func. can be run multiple times at the start.
- if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) {
- // needs stored language and TheText to be loaded, and last TheText reload is at the start of here
- CustomFrontendOptionsPopulate();
- }
-#endif
-#ifdef LOAD_INI_SETTINGS
- LoadINISettings(); // needs frontend options to be loaded
-#endif
return true;
}
+// missing altogether on PS2
void
CGame::FinalShutdown(void)
{
@@ -337,21 +362,40 @@ CGame::FinalShutdown(void)
bool CGame::Initialise(const char* datFile)
{
+#ifdef GTA_PS2
+ // TODO: upload VU0 collision code here
+#endif
+
+#if GTA_VERSION > GTA3_PS2_160
ResetLoadingScreenBar();
strcpy(aDatFile, datFile);
- CPools::Initialise();
+ CPools::Initialise(); // done in CWorld on PS2
+#endif
+
+#ifndef GTA_PS2
CIniFile::LoadIniFile();
+#endif
+
currLevel = LEVEL_INDUSTRIAL;
+
+ PUSH_MEMID(MEMID_TEXTURES);
LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen());
gameTxdSlot = CTxdStore::AddTxdSlot("generic");
CTxdStore::Create(gameTxdSlot);
CTxdStore::AddRef(gameTxdSlot);
+
LoadingScreen("Loading the Game", "Loading particles", nil);
int particleTxdSlot = CTxdStore::AddTxdSlot("particle");
CTxdStore::LoadTxd(particleTxdSlot, "MODELS/PARTICLE.TXD");
CTxdStore::AddRef(particleTxdSlot);
CTxdStore::SetCurrentTxd(gameTxdSlot);
LoadingScreen("Loading the Game", "Setup game variables", nil);
+ POP_MEMID();
+
+#ifdef GTA_PS2
+ CDma::SyncChannel(0, true);
+#endif
+
CGameLogic::InitAtStartOfGame();
CReferences::Init();
TheCamera.Init();
@@ -362,32 +406,72 @@ bool CGame::Initialise(const char* datFile)
CWeather::Init();
CCullZones::Init();
CCollision::Init();
-#ifdef PS2_MENU
+#ifdef PS2_MENU // TODO: is this the right define?
TheText.Load();
#endif
CTheZones::Init();
CUserDisplay::Init();
CMessages::Init();
+#if GTA_VERSION > GTA3_PS2_160
CMessages::ClearAllMessagesDisplayedByGame();
+#endif
CRecordDataForGame::Init();
CRestart::Initialise();
+
+ PUSH_MEMID(MEMID_WORLD);
CWorld::Initialise();
+ POP_MEMID();
+
+#if GTA_VERSION <= GTA3_PS2_160
+ mod_HandlingManager.Initialise();
+ CSurfaceTable::Initialise("DATA\\SURFACE.DAT");
+ CTempColModels::Initialise();
+#endif
+
+ PUSH_MEMID(MEMID_TEXTURES);
CParticle::Initialise();
-#ifdef PS2
+ POP_MEMID();
+
+#if GTA_VERSION <= GTA3_PS2_160
gStartX = -180.0f;
gStartY = 180.0f;
gStartZ = 14.0f;
#endif
+
+ PUSH_MEMID(MEMID_ANIMATION);
CAnimManager::Initialise();
CCutsceneMgr::Initialise();
+ POP_MEMID();
+
+ PUSH_MEMID(MEMID_CARS);
CCarCtrl::Init();
+ POP_MEMID();
+
+#if GTA_VERSION > GTA3_PS2_160
InitModelIndices();
+#endif
+
+ PUSH_MEMID(MEMID_DEF_MODELS);
CModelInfo::Initialise();
+#if GTA_VERSION <= GTA3_PS2_160
+ CPedStats::Initialise(); // InitialiseOnceAfterRW
+#else
+ // probably moved before LoadLevel for multiplayer maps?
CPickups::Init();
CTheCarGenerators::Init();
+#endif
+
+#ifndef GTA_PS2 // or GTA_VERSION?
CdStreamAddImage("MODELS\\GTA3.IMG");
+#endif
+
+#if GTA_VERSION > GTA3_PS2_160
CFileLoader::LoadLevel("DATA\\DEFAULT.DAT");
CFileLoader::LoadLevel(datFile);
+#else
+ CFileLoader::LoadLevel("GTA3.DAT");
+#endif
+
#ifdef EXTENDED_PIPELINES
// for generic fallback
CustomPipes::SetTxdFindCallback();
@@ -396,17 +480,30 @@ bool CGame::Initialise(const char* datFile)
CVehicleModelInfo::LoadVehicleColours();
CVehicleModelInfo::LoadEnvironmentMaps();
CTheZones::PostZoneCreation();
+ POP_MEMID();
+
+#if GTA_VERSION <= GTA3_PS2_160
+ TestModelIndices();
+#endif
LoadingScreen("Loading the Game", "Setup paths", GetRandomSplashScreen());
ThePaths.PreparePathData();
+#if GTA_VERSION > GTA3_PS2_160
for (int i = 0; i < NUMPLAYERS; i++)
CWorld::Players[i].Clear();
CWorld::Players[0].LoadPlayerSkin();
TestModelIndices();
+#endif
+
LoadingScreen("Loading the Game", "Setup water", nil);
CWaterLevel::Initialise("DATA\\WATER.DAT");
+#if GTA_VERSION <= GTA3_PS2_160
+ CTimeCycle::Initialise(); // InitialiseOnceAfterRW
+#else
TheConsole.Init();
+#endif
CDraw::SetFOV(120.0f);
CDraw::ms_fLODDistance = 500.0f;
+
LoadingScreen("Loading the Game", "Setup streaming", nil);
CStreaming::Init();
CStreaming::LoadInitialVehicles();
@@ -414,22 +511,37 @@ bool CGame::Initialise(const char* datFile)
CStreaming::RequestBigBuildings(LEVEL_GENERIC);
CStreaming::LoadAllRequestedModels(false);
printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d
+
LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen());
+ PUSH_MEMID(MEMID_ANIMATION);
CAnimManager::LoadAnimFiles();
+ POP_MEMID();
+
CPed::Initialise();
CRouteNode::Initialise();
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
LoadingScreen("Loading the Game", "Find big buildings", nil);
CRenderer::Init();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
CRadar::Initialise();
CRadar::LoadTextures();
CWeapon::InitialiseWeapons();
+
LoadingScreen("Loading the Game", "Setup traffic lights", nil);
CTrafficLights::ScanForLightsOnMap();
CRoadBlocks::Init();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
CPopulation::Initialise();
+#if GTA_VERSION <= GTA3_PS2_160
+ for (int i = 0; i < NUMPLAYERS; i++)
+ CWorld::Players[i].Clear();
+// CWorld::Players[0].LoadPlayerSkin(); // TODO: use a define for this
+#endif
CWorld::PlayerInFocus = 0;
CCoronas::Init();
CShadows::Init();
@@ -438,44 +550,74 @@ bool CGame::Initialise(const char* datFile)
CAntennas::Init();
CGlass::Init();
gPhoneInfo.Initialise();
+#ifdef GTA_SCENE_EDIT
CSceneEdit::Initialise();
+#endif
+
LoadingScreen("Loading the Game", "Load scripts", nil);
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Init();
CGangs::Initialise();
+ POP_MEMID();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
+#if GTA_VERSION <= GTA3_PS2_160
+ CTimer::Initialise();
+#endif
CClock::Initialise(1000);
+#if GTA_VERSION <= GTA3_PS2_160
+ CTheCarGenerators::Init();
+#endif
CHeli::InitHelis();
CCranes::InitCranes();
CMovingThings::Init();
CDarkel::Init();
CStats::Init();
+#if GTA_VERSION <= GTA3_PS2_160
+ CPickups::Init();
+#endif
CPacManPickups::Init();
+#if GTA_VERSION <= GTA3_PS2_160
+ CGarages::Init();
+#endif
CRubbish::Init();
CClouds::Init();
+#if GTA_VERSION <= GTA3_PS2_160
+ CRemote::Init();
+#endif
CSpecialFX::Init();
CWaterCannons::Init();
CBridge::Init();
+#if GTA_VERSION > GTA3_PS2_160
CGarages::Init();
+#endif
+
LoadingScreen("Loading the Game", "Position dynamic objects", nil);
CWorld::RepositionCertainDynamicObjects();
+#if GTA_VERSION <= GTA3_PS2_160
+ CCullZones::ResolveVisibilities();
+#endif
+
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
+#if GTA_VERSION > GTA3_PS2_160
CCullZones::ResolveVisibilities();
+#endif
CTrain::InitTrains();
CPlane::InitPlanes();
CCredits::Init();
CRecordDataForChase::Init();
CReplay::Init();
+
#ifdef PS2_MENU
if ( !TheMemoryCard.m_bWantToLoad )
- {
#endif
- LoadingScreen("Loading the Game", "Start script", nil);
- CTheScripts::StartTestScript();
- CTheScripts::Process();
- TheCamera.Process();
-#ifdef PS2_MENU
+ {
+ LoadingScreen("Loading the Game", "Start script", nil);
+ CTheScripts::StartTestScript();
+ CTheScripts::Process();
+ TheCamera.Process();
}
-#endif
+
LoadingScreen("Loading the Game", "Load scene", nil);
CModelInfo::RemoveColModelsFromOtherLevels(currLevel);
CCollision::ms_collisionInMemory = currLevel;
@@ -490,7 +632,7 @@ bool CGame::ShutDown(void)
CPlane::Shutdown();
CTrain::Shutdown();
CSpecialFX::Shutdown();
-#ifndef PS2
+#if GTA_VERSION > GTA3_PS2_160
CGarages::Shutdown();
#endif
CMovingThings::Shutdown();
@@ -531,7 +673,9 @@ bool CGame::ShutDown(void)
CSkidmarks::Shutdown();
CWeaponEffects::Shutdown();
CParticle::Shutdown();
+#if GTA_VERSION > GTA3_PS2_160
CPools::ShutDown();
+#endif
CTxdStore::RemoveTxdSlot(gameTxdSlot);
CdStreamRemoveImages();
return true;
@@ -542,13 +686,11 @@ void CGame::ReInitGameObjectVariables(void)
CGameLogic::InitAtStartOfGame();
#ifdef PS2_MENU
if ( !TheMemoryCard.m_bWantToLoad )
- {
#endif
- TheCamera.Init();
- TheCamera.SetRwCamera(Scene.camera);
-#ifdef PS2_MENU
+ {
+ TheCamera.Init();
+ TheCamera.SetRwCamera(Scene.camera);
}
-#endif
CDebug::DebugInitTextBuffer();
CWeather::Init();
CUserDisplay::Init();
@@ -557,7 +699,7 @@ void CGame::ReInitGameObjectVariables(void)
CWorld::bDoingCarCollisions = false;
CHud::ReInitialise();
CRadar::Initialise();
-#ifdef PS2
+#if GTA_VERSION <= GTA3_PS2_160
gStartX = -180.0f;
gStartY = 180.0f;
gStartZ = 14.0f;
@@ -570,6 +712,9 @@ void CGame::ReInitGameObjectVariables(void)
CStreaming::LoadAllRequestedModels(false);
CPed::Initialise();
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
CWeapon::InitialiseWeapons();
CPopulation::Initialise();
@@ -577,15 +722,19 @@ void CGame::ReInitGameObjectVariables(void)
CWorld::Players[i].Clear();
CWorld::PlayerInFocus = 0;
-#ifdef PS2
+#if GTA_VERSION <= GTA3_PS2_160
CWeaponEffects::Init();
CSkidmarks::Init();
#endif
CAntennas::Init();
CGlass::Init();
gPhoneInfo.Initialise();
+
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Init();
CGangs::Initialise();
+ POP_MEMID();
+
CTimer::Initialise();
CClock::Initialise(1000);
CTheCarGenerators::Init();
@@ -596,7 +745,7 @@ void CGame::ReInitGameObjectVariables(void)
CPickups::Init();
CPacManPickups::Init();
CGarages::Init();
-#ifdef PS2
+#if GTA_VERSION <= GTA3_PS2_160
CClouds::Init();
CRemote::Init();
#endif
@@ -666,7 +815,7 @@ void CGame::ShutDownForRestart(void)
CRadar::RemoveRadarSections();
FrontEndMenuManager.UnloadTextures();
CParticleObject::RemoveAllParticleObjects();
-#ifndef PS2
+#if GTA_VERSION >= GTA3_PS2_160
CPedType::Shutdown();
CSpecialFX::Shutdown();
#endif
@@ -745,10 +894,10 @@ void CGame::InitialiseWhenRestarting(void)
//CFont::SetFontStyle(?);
CFont::SetBackgroundOff();
- CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f // unused
+ CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f
CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f));
CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_SCALE_X(480.0f)); // 480.0f
+ CFont::SetCentreSize(SCREEN_SCALE_X(480.0f));
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 255, 255));
CFont::SetBackGroundOnlyTextOff();
@@ -811,7 +960,7 @@ void CGame::InitialiseWhenRestarting(void)
void CGame::Process(void)
{
CPad::UpdatePads();
-#ifdef GTA_PS2
+#ifdef USE_CUSTOM_ALLOCATOR
ProcessTidyUpMemory();
#endif
TheCamera.SetMotionBlurAlpha(0);
@@ -821,8 +970,12 @@ void CGame::Process(void)
DebugMenuProcess();
#endif
CCutsceneMgr::Update();
+
+ PUSH_MEMID(MEMID_FRONTEND);
if (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused())
FrontEndMenuManager.Process();
+ POP_MEMID();
+
CStreaming::Update();
if (!CTimer::GetIsPaused())
{
@@ -835,7 +988,11 @@ void CGame::Process(void)
CPad::DoCheats();
CClock::Update();
CWeather::Update();
+
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Process();
+ POP_MEMID();
+
CCollision::Update();
CTrain::UpdateTrains();
CPlane::UpdatePlanes();
@@ -844,7 +1001,9 @@ void CGame::Process(void)
CSkidmarks::Update();
CAntennas::Update();
CGlass::Update();
+#ifdef GTA_SCENE_EDIT
CSceneEdit::Update();
+#endif
CEventList::Update();
CParticle::Update();
gFireManager.Update();
@@ -859,7 +1018,11 @@ void CGame::Process(void)
CWaterCannons::Update();
CUserDisplay::Process();
CReplay::Update();
+
+ PUSH_MEMID(MEMID_WORLD);
CWorld::Process();
+ POP_MEMID();
+
gAccidentManager.Update();
CPacManPickups::Update();
CPickups::Update();
@@ -880,33 +1043,370 @@ void CGame::Process(void)
gPhoneInfo.Update();
if (!CReplay::IsPlayingBack())
{
+ PUSH_MEMID(MEMID_CARS);
CCarCtrl::GenerateRandomCars();
CRoadBlocks::GenerateRoadBlocks();
CCarCtrl::RemoveDistantCars();
+ POP_MEMID();
}
}
-#ifdef PS2
+#ifdef GTA_PS2
CMemCheck::DoTest();
#endif
}
-void CGame::DrasticTidyUpMemory(bool)
+#ifdef USE_CUSTOM_ALLOCATOR
+
+int32 gNumMemMoved;
+
+bool
+MoveMem(void **ptr)
+{
+ if(*ptr){
+ gNumMemMoved++;
+ void *newPtr = gMainHeap.MoveMemory(*ptr);
+ if(*ptr != newPtr){
+ *ptr = newPtr;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Some convenience structs
+struct SkyDataPrefix
+{
+ uint32 pktSize1;
+ uint32 data; // pointer to data as read from TXD
+ uint32 pktSize2;
+ uint32 unused;
+};
+
+struct DMAGIFUpload
+{
+ uint32 tag1_qwc, tag1_addr; // dmaref
+ uint32 nop1, vif_direct1;
+
+ uint32 giftag[4];
+ uint32 gs_bitbltbuf[4];
+
+ uint32 tag2_qwc, tag2_addr; // dmaref
+ uint32 nop2, vif_direct2;
+};
+
+// This is very scary. it depends on the exact memory layout of the DMA chains and whatnot
+RwTexture *
+MoveTextureMemoryCB(RwTexture *texture, void *pData)
+{
+#ifdef GTA_PS2
+ bool *pRet = (bool*)pData;
+ RwRaster *raster = RwTextureGetRaster(texture);
+ _SkyRasterExt *rasterExt = RASTEREXTFROMRASTER(raster);
+ if(raster->originalPixels == nil || // the raw data
+ raster->cpPixels == raster->originalPixels || // old format, can't handle it
+ rasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0)
+ return texture;
+
+ // this is the allocated pointer we will move
+ SkyDataPrefix *prefix = (SkyDataPrefix*)raster->originalPixels;
+ DMAGIFUpload *uploads = (DMAGIFUpload*)(prefix+1);
+
+ // We have 4qw for each upload,
+ // i.e. for each buffer width of mip levels,
+ // and the palette if there is one.
+ // NB: this code does NOT support mipmaps!
+ // so we assume two uploads (pixels and palette)
+ //
+ // each upload looks like this:
+ // (DMAcnt; NOP; VIF DIRECT(2))
+ // giftag (1, A+D)
+ // GS_BITBLTBUF
+ // (DMAref->pixel data; NOP; VIF DIRECT(5))
+ // the DMArefs are what we have to adjust
+ uintptr dataDiff, upload1Diff, upload2Diff, pixelDiff, paletteDiff;
+ dataDiff = prefix->data - (uintptr)raster->originalPixels;
+ upload1Diff = uploads[0].tag2_addr - (uintptr)raster->originalPixels;
+ if(raster->palette)
+ upload2Diff = uploads[1].tag2_addr - (uintptr)raster->originalPixels;
+ pixelDiff = (uintptr)raster->cpPixels - (uintptr)raster->originalPixels;
+ if(raster->palette)
+ paletteDiff = (uintptr)raster->palette - (uintptr)raster->originalPixels;
+ uint8 *newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels);
+ if(newptr != raster->originalPixels){
+ // adjust everything
+ prefix->data = (uintptr)newptr + dataDiff;
+ uploads[0].tag2_addr = (uintptr)newptr + upload1Diff;
+ if(raster->palette)
+ uploads[1].tag2_addr = (uintptr)newptr + upload2Diff;
+ raster->originalPixels = newptr;
+ raster->cpPixels = newptr + pixelDiff;
+ if(raster->palette)
+ raster->palette = newptr + paletteDiff;
+
+ if(pRet){
+ *pRet = true;
+ return nil;
+ }
+ }
+#else
+ // nothing to do here really, everything should be in videomemory
+#endif
+ return texture;
+}
+
+bool
+MoveAtomicMemory(RpAtomic *atomic, bool onlyOne)
+{
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+
+#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
+ if(MoveMem((void**)&geo->triangles) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->matList.materials) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->preLitLum) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->texCoords[0]) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->texCoords[1]) && onlyOne)
+ return true;
+
+ // verts and normals of morph target are allocated together
+ int vertDiff;
+ if(geo->morphTarget->normals)
+ vertDiff = geo->morphTarget->normals - geo->morphTarget->verts;
+ if(MoveMem((void**)&geo->morphTarget->verts)){
+ if(geo->morphTarget->normals)
+ geo->morphTarget->normals = geo->morphTarget->verts + vertDiff;
+ if(onlyOne)
+ return true;
+ }
+
+ RpMeshHeader *oldmesh = geo->mesh;
+ if(MoveMem((void**)&geo->mesh)){
+ // index pointers are allocated together with meshes,
+ // have to relocate those too
+ RpMesh *mesh = (RpMesh*)(geo->mesh+1);
+ uintptr reloc = (uintptr)geo->mesh - (uintptr)oldmesh;
+ for(int i = 0; i < geo->mesh->numMeshes; i++)
+ mesh[i].indices = (RxVertexIndex*)((uintptr)mesh[i].indices + reloc);
+ if(onlyOne)
+ return true;
+ }
+#else
+ // we could do something in librw here
+#endif
+ return false;
+}
+
+bool
+MoveColModelMemory(CColModel &colModel, bool onlyOne)
+{
+#if GTA_VERSION >= GTA3_PS2_160
+ // hm...should probably only do this if ownsCollisionVolumes
+ // but it doesn't exist on PS2...
+ if(!colModel.ownsCollisionVolumes)
+ return false;
+#endif
+
+ if(MoveMem((void**)&colModel.spheres) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.lines) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.boxes) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.vertices) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.triangles) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.trianglePlanes) && onlyOne)
+ return true;
+ return false;
+}
+
+RpAtomic*
+MoveAtomicMemoryCB(RpAtomic *atomic, void *pData)
+{
+ bool *pRet = (bool*)pData;
+ if(pRet == nil)
+ MoveAtomicMemory(atomic, false);
+ else if(MoveAtomicMemory(atomic, true)){
+ *pRet = true;
+ return nil;
+ }
+ return atomic;
+}
+
+bool
+TidyUpModelInfo(CBaseModelInfo *modelInfo, bool onlyone)
{
-#ifdef PS2
- // meow
+ if(modelInfo->GetColModel() && modelInfo->DoesOwnColModel())
+ if(MoveColModelMemory(*modelInfo->GetColModel(), onlyone))
+ return true;
+
+ RwObject *rwobj = modelInfo->GetRwObject();
+ if(RwObjectGetType(rwobj) == rpATOMIC)
+ if(MoveAtomicMemory((RpAtomic*)rwobj, onlyone))
+ return true;
+ if(RwObjectGetType(rwobj) == rpCLUMP){
+ bool ret = false;
+ if(onlyone)
+ RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, &ret);
+ else
+ RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, nil);
+ if(ret)
+ return true;
+ }
+
+ if(modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel)
+ if(MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone))
+ return true;
+
+ return false;
+}
+#endif
+
+void CGame::DrasticTidyUpMemory(bool flushDraw)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+ bool removedCol = false;
+
+ TidyUpMemory(true, flushDraw);
+
+ if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){
+ CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
+ CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
+ CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
+ TidyUpMemory(true, flushDraw);
+ }
+
+ if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){
+ CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);
+ TidyUpMemory(true, flushDraw);
+ removedCol = true;
+ }
+
+ if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){
+ CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
+ CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
+ CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
+ TidyUpMemory(true, flushDraw);
+ }
+
+ if(removedCol){
+ // different on PS2
+ CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory);
+ }
+
+ if(!playingIntro)
+ CStreaming::RequestBigBuildings(currLevel);
+
+ CStreaming::LoadAllRequestedModels(true);
#endif
}
-void CGame::TidyUpMemory(bool, bool)
+void CGame::TidyUpMemory(bool moveTextures, bool flushDraw)
{
-#ifdef PS2
- // meow
+#ifdef USE_CUSTOM_ALLOCATOR
+ printf("Largest free block before tidy %d\n", gMainHeap.GetLargestFreeBlock());
+
+ if(moveTextures){
+ if(flushDraw){
+#ifdef GTA_PS2
+ for(int i = 0; i < sweMaxFlips+1; i++){
+#else
+ for(int i = 0; i < 5; i++){ // probably more than needed
+#endif
+ RwCameraBeginUpdate(Scene.camera);
+ RwCameraEndUpdate(Scene.camera);
+ RwCameraShowRaster(Scene.camera, nil, 0);
+ }
+ }
+ int fontSlot = CTxdStore::FindTxdSlot("fonts");
+
+ for(int i = 0; i < TXDSTORESIZE; i++){
+ if(i == fontSlot ||
+ CTxdStore::GetSlot(i) == nil)
+ continue;
+ RwTexDictionary *txd = CTxdStore::GetSlot(i)->texDict;
+ if(txd)
+ RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, nil);
+ }
+ }
+
+ // animations
+ for(int i = 0; i < NUMANIMATIONS; i++){
+ CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(i);
+ if(anim == nil)
+ continue; // cannot happen
+ anim->MoveMemory();
+ }
+
+ // model info
+ for(int i = 0; i < MODELINFOSIZE; i++){
+ CBaseModelInfo *mi = CModelInfo::GetModelInfo(i);
+ if(mi == nil)
+ continue;
+ TidyUpModelInfo(mi, false);
+ }
+
+ printf("Largest free block after tidy %d\n", gMainHeap.GetLargestFreeBlock());
#endif
}
void CGame::ProcessTidyUpMemory(void)
{
-#ifdef PS2
- // meow
+#ifdef USE_CUSTOM_ALLOCATOR
+ static int32 modelIndex = 0;
+ static int32 animIndex = 0;
+ static int32 txdIndex = 0;
+ bool txdReturn = false;
+ RwTexDictionary *txd = nil;
+ gNumMemMoved = 0;
+
+ // model infos
+ for(int numCleanedUp = 0; numCleanedUp < 10; numCleanedUp++){
+ CBaseModelInfo *mi;
+ do{
+ mi = CModelInfo::GetModelInfo(modelIndex);
+ modelIndex++;
+ if(modelIndex >= MODELINFOSIZE)
+ modelIndex = 0;
+ }while(mi == nil);
+
+ if(TidyUpModelInfo(mi, true))
+ return;
+ }
+
+ // tex dicts
+ for(int numCleanedUp = 0; numCleanedUp < 3; numCleanedUp++){
+ if(gNumMemMoved > 80)
+ break;
+
+ do{
+#ifdef FIX_BUGS
+ txd = nil;
+#endif
+ if(CTxdStore::GetSlot(txdIndex))
+ txd = CTxdStore::GetSlot(txdIndex)->texDict;
+ txdIndex++;
+ if(txdIndex >= TXDSTORESIZE)
+ txdIndex = 0;
+ }while(txd == nil);
+
+ RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, &txdReturn);
+ if(txdReturn)
+ return;
+ }
+
+ // animations
+ CAnimBlendHierarchy *anim;
+ do{
+ anim = CAnimManager::GetAnimation(animIndex);
+ animIndex++;
+ if(animIndex >= NUMANIMATIONS)
+ animIndex = 0;
+ }while(anim == nil); // always != nil
+ anim->MoveMemory(true);
#endif
}
diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp
index 533fc755..9eff09e6 100644
--- a/src/core/MenuScreens.cpp
+++ b/src/core/MenuScreens.cpp
@@ -2,8 +2,10 @@
#include "Frontend.h"
#ifdef PC_MENU
-// If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp.
+// Please don't touch this file, except for bug fixing or ports.
+// Check MenuScreensCustom.cpp
+#ifndef CUSTOM_FRONTEND_OPTIONS
CMenuScreen aScreens[MENUPAGES] = {
// MENUPAGE_NONE = 0
{ "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, },
@@ -390,6 +392,9 @@ CMenuScreen aScreens[MENUPAGES] = {
{ "FET_PAU", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
+#ifdef MENU_MAP
+ MENUACTION_CHANGEMENU, "FEG_MAP", SAVESLOT_NONE, MENUPAGE_MAP,
+#endif
MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS,
MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS,
MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS,
@@ -436,10 +441,10 @@ CMenuScreen aScreens[MENUPAGES] = {
#ifdef MENU_MAP
// MENUPAGE_MAP
- { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2,
+ { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 2,
MENUACTION_UNK110, "", SAVESLOT_NONE, MENUPAGE_NONE, // to prevent cross/enter to go back
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
- },
+ },
#endif
// MENUPAGE_UNK
@@ -449,4 +454,5 @@ CMenuScreen aScreens[MENUPAGES] = {
};
-#endif \ No newline at end of file
+#endif
+#endif
diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp
new file mode 100644
index 00000000..ae08f5f5
--- /dev/null
+++ b/src/core/MenuScreensCustom.cpp
@@ -0,0 +1,878 @@
+#include "common.h"
+#include "platform.h"
+#include "crossplatform.h"
+#include "Renderer.h"
+#include "Frontend.h"
+#include "Font.h"
+#include "Camera.h"
+#include "main.h"
+#include "MBlur.h"
+#include "postfx.h"
+#include "custompipes.h"
+#include "RwHelper.h"
+#include "Text.h"
+#include "Streaming.h"
+#include "FileLoader.h"
+#include "Collision.h"
+#include "ModelInfo.h"
+#include "Pad.h"
+
+// Menu screens array is at the bottom of the file.
+
+#ifdef PC_MENU
+
+#ifdef CUSTOM_FRONTEND_OPTIONS
+
+#ifdef IMPROVED_VIDEOMODE
+ #define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, nil, screenModes, 2, true, ScreenModeAfterChange) },
+#else
+ #define VIDEOMODE_SELECTOR
+#endif
+
+#ifdef MULTISAMPLING
+ #define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) },
+#else
+ #define MULTISAMPLING_SELECTOR
+#endif
+
+#ifdef CUTSCENE_BORDERS_SWITCH
+ #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&CMenuManager::m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false, nil) },
+#else
+ #define CUTSCENE_BORDERS_TOGGLE
+#endif
+
+#ifdef FREE_CAM
+ #define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "FreeCam", off_on, 2, false, nil) },
+#else
+ #define FREE_CAM_TOGGLE
+#endif
+
+#ifdef PS2_ALPHA_TEST
+ #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "PS2AlphaTest", off_on, 2, false, nil) },
+#else
+ #define DUALPASS_SELECTOR
+#endif
+
+#ifdef NO_ISLAND_LOADING
+ #define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&CMenuManager::m_PrefsIslandLoading, "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) },
+#else
+ #define ISLAND_LOADING_SELECTOR
+#endif
+
+#ifdef EXTENDED_COLOURFILTER
+ #define POSTFX_SELECTORS \
+ MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) },
+#else
+ #define POSTFX_SELECTORS
+#endif
+
+#ifdef EXTENDED_PIPELINES
+ #define PIPELINES_SELECTOR \
+ MENUACTION_CFO_SELECT, "FED_VPL", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_PRM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_WLM", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_RGL", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) },
+#else
+ #define PIPELINES_SELECTOR
+#endif
+
+#ifdef INVERT_LOOK_FOR_PAD
+ #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_IVP", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, "InvertPad", off_on, 2, false, nil) },
+#else
+ #define INVERT_PAD_SELECTOR
+#endif
+
+const char *filterNames[] = { "FEM_NON", "FEM_SIM", "FEM_NRM", "FEM_MOB" };
+const char *vehPipelineNames[] = { "FED_MFX", "FED_NEO" };
+const char *off_on[] = { "FEM_OFF", "FEM_ON" };
+
+void RestoreDefGraphics(int8 action) {
+ if (action != FEOPTION_ACTION_SELECT)
+ return;
+
+ #ifdef PS2_ALPHA_TEST
+ gPS2alphaTest = false;
+ #endif
+ #ifdef MULTISAMPLING
+ FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0;
+ #endif
+ #ifdef NO_ISLAND_LOADING
+ if (!FrontEndMenuManager.m_bGameNotLoaded) {
+ FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;
+ CCollision::bAlreadyLoaded = false;
+ CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
+ CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
+ CStreaming::RemoveUnusedBuildings(CGame::currLevel);
+ CStreaming::RequestIslands(CGame::currLevel);
+ CStreaming::LoadAllRequestedModels(true);
+ } else
+ FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;
+ #endif
+ #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
+ CMenuManager::m_PrefsFrameLimiter = true;
+ CMenuManager::m_PrefsVsyncDisp = true;
+ CMenuManager::m_PrefsVsync = true;
+ CMenuManager::m_PrefsUseWideScreen = false;
+ FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode;
+ #if GTA_VERSION >= GTA3_PC_11
+ if (_dwOperatingSystemVersion == OS_WIN98) {
+ CMBlur::BlurOn = false;
+ CMBlur::MotionBlurClose();
+ } else {
+ CMBlur::BlurOn = true;
+ CMBlur::MotionBlurOpen(Scene.camera);
+ }
+ #else
+ CMBlur::BlurOn = true;
+ #endif
+ FrontEndMenuManager.SaveSettings();
+ #endif
+}
+
+void RestoreDefDisplay(int8 action) {
+ if (action != FEOPTION_ACTION_SELECT)
+ return;
+
+ #ifdef CUTSCENE_BORDERS_SWITCH
+ CMenuManager::m_PrefsCutsceneBorders = true;
+ #endif
+ #ifdef FREE_CAM
+ TheCamera.bFreeCam = false;
+ #endif
+ #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
+ CMenuManager::m_PrefsBrightness = 256;
+ CMenuManager::m_PrefsLOD = 1.2f;
+ CRenderer::ms_lodDistScale = 1.2f;
+ CMenuManager::m_PrefsShowSubtitles = true;
+ FrontEndMenuManager.SaveSettings();
+ #endif
+}
+
+#ifdef NO_ISLAND_LOADING
+const char *islandLoadingOpts[] = { "FEM_LOW", "FEM_MED", "FEM_HIG" };
+void IslandLoadingAfterChange(int8 before, int8 after) {
+ if (!FrontEndMenuManager.m_bGameNotLoaded) {
+ if (after > FrontEndMenuManager.ISLAND_LOADING_LOW) {
+ FrontEndMenuManager.m_PrefsIslandLoading = before; // calls below needs previous mode :shrug:
+
+ if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH)
+ CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
+ if (before == FrontEndMenuManager.ISLAND_LOADING_LOW) {
+ if (CGame::currLevel != LEVEL_INDUSTRIAL)
+ CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
+ if (CGame::currLevel != LEVEL_COMMERCIAL)
+ CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
+ if (CGame::currLevel != LEVEL_SUBURBAN)
+ CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
+ CCollision::bAlreadyLoaded = true;
+ FrontEndMenuManager.m_PrefsIslandLoading = after;
+ CStreaming::RequestBigBuildings(CGame::currLevel);
+
+ } else if (before == FrontEndMenuManager.ISLAND_LOADING_HIGH) {
+ FrontEndMenuManager.m_PrefsIslandLoading = after;
+ CStreaming::RequestIslands(CGame::currLevel);
+ } else
+ FrontEndMenuManager.m_PrefsIslandLoading = after;
+
+ } else { // low
+ CCollision::bAlreadyLoaded = false;
+ CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
+ CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
+ CStreaming::RemoveUnusedBuildings(CGame::currLevel);
+ CStreaming::RequestIslands(CGame::currLevel);
+ }
+
+ CStreaming::LoadAllRequestedModels(true);
+ }
+
+ FrontEndMenuManager.SetHelperText(0);
+}
+#endif
+
+#ifdef MORE_LANGUAGES
+void LangPolSelect(int8 action)
+{
+ if (action == FEOPTION_ACTION_SELECT) {
+ FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH;
+ FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
+ FrontEndMenuManager.InitialiseChangedLanguageSettings();
+ FrontEndMenuManager.SaveSettings();
+ }
+}
+
+void LangRusSelect(int8 action)
+{
+ if (action == FEOPTION_ACTION_SELECT) {
+ FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN;
+ FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
+ FrontEndMenuManager.InitialiseChangedLanguageSettings();
+ FrontEndMenuManager.SaveSettings();
+ }
+}
+
+void LangJapSelect(int8 action)
+{
+ if (action == FEOPTION_ACTION_SELECT) {
+ FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE;
+ FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
+ FrontEndMenuManager.InitialiseChangedLanguageSettings();
+ FrontEndMenuManager.SaveSettings();
+ }
+}
+#endif
+
+#ifndef MULTISAMPLING
+void GraphicsGoBack() {
+}
+#else
+void GraphicsGoBack() {
+ FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
+}
+
+void MultiSamplingButtonPress(int8 action) {
+ if (action == FEOPTION_ACTION_SELECT) {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
+ FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel;
+ _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode);
+ FrontEndMenuManager.SetHelperText(0);
+ FrontEndMenuManager.SaveSettings();
+ }
+ } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) {
+ if (FrontEndMenuManager.m_bGameNotLoaded) {
+ FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1);
+
+ int i = 0;
+ int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();
+ while (maxAA != 1) {
+ i++;
+ maxAA >>= 1;
+ }
+
+ if (FrontEndMenuManager.m_nDisplayMSAALevel < 0)
+ FrontEndMenuManager.m_nDisplayMSAALevel = i;
+ else if (FrontEndMenuManager.m_nDisplayMSAALevel > i)
+ FrontEndMenuManager.m_nDisplayMSAALevel = 0;
+ }
+ } else if (action == FEOPTION_ACTION_FOCUSLOSS) {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
+ FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
+ FrontEndMenuManager.SetHelperText(3);
+ }
+ }
+}
+
+wchar* MultiSamplingDraw(bool *disabled, bool userHovering) {
+ static wchar unicodeTemp[64];
+ if (userHovering) {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) {
+ if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply
+ FrontEndMenuManager.ResetHelperText();
+ } else {
+ FrontEndMenuManager.SetHelperText(1);
+ }
+ } else {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
+ FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
+ }
+ }
+
+ if (!FrontEndMenuManager.m_bGameNotLoaded)
+ *disabled = true;
+
+ switch (FrontEndMenuManager.m_nDisplayMSAALevel) {
+ case 0:
+ return TheText.Get("FEM_OFF");
+ default:
+ sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel));
+ AsciiToUnicode(gString, unicodeTemp);
+ return unicodeTemp;
+ }
+}
+#endif
+
+#ifdef IMPROVED_VIDEOMODE
+const char* screenModes[] = { "FED_FLS", "FED_WND" };
+void ScreenModeAfterChange(int8 before, int8 after)
+{
+ _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution
+ FrontEndMenuManager.SetHelperText(0);
+}
+
+#endif
+
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+wchar selectedJoystickUnicode[128];
+
+wchar* DetectJoystickDraw(bool* disabled, bool userHovering) {
+ int numButtons;
+ int found = -1;
+ const char *joyname;
+ if (userHovering) {
+ for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
+ if ((joyname = glfwGetJoystickName(i))) {
+ const uint8* buttons = glfwGetJoystickButtons(i, &numButtons);
+ for (int j = 0; j < numButtons; j++) {
+ if (buttons[j]) {
+ found = i;
+ break;
+ }
+ }
+ if (found != -1)
+ break;
+ }
+ }
+
+ if (found != -1 && PSGLOBAL(joy1id) != found) {
+ if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)
+ PSGLOBAL(joy2id) = PSGLOBAL(joy1id);
+ else
+ PSGLOBAL(joy2id) = -1;
+
+ strcpy(gSelectedJoystickName, joyname);
+ PSGLOBAL(joy1id) = found;
+ }
+ }
+ if (PSGLOBAL(joy1id) == -1)
+ AsciiToUnicode("Not found", selectedJoystickUnicode);
+ else
+ AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);
+
+ return selectedJoystickUnicode;
+}
+#endif
+
+CMenuScreenCustom aScreens[MENUPAGES] = {
+ // MENUPAGE_NONE = 0
+ { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, },
+
+ // MENUPAGE_STATS = 1
+ { "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_NEW_GAME = 2
+ { "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FES_SNG", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD },
+ MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
+ MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_BRIEFS = 3
+ { "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_SETTINGS = 4
+ { "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+ MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+ MENUACTION_CTRLVIBRATION, "FEC_VIB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SOUND_SETTINGS = 5
+ { "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_MUSICVOLUME, "FEA_MUS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_SFXVOLUME, "FEA_SFX", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_AUDIOHW, "FEA_3DH", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_SPEAKERCONF, "FEA_SPK", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_DYNAMICACOUSTIC, "FET_DAM", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_RADIO, "FEA_RSS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+#ifndef GRAPHICS_MENU_OPTIONS
+ // MENUPAGE_DISPLAY_SETTINGS = 6
+ { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#ifndef EXTENDED_COLOURFILTER
+ MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#endif
+ MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ VIDEOMODE_SELECTOR
+ MULTISAMPLING_SELECTOR
+ MENUACTION_CHANGEMENU, "FET_ADV", { nil, SAVESLOT_NONE, MENUPAGE_ADVANCED_DISPLAY_SETTINGS },
+ MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ // MENUPAGE_DISPLAY_SETTINGS = 6
+ { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ CUTSCENE_BORDERS_TOGGLE
+ FREE_CAM_TOGGLE
+ MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefDisplay) },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+ // MENUPAGE_LANGUAGE_SETTINGS = 7
+ { "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_LANG_ENG, "FEL_ENG", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_FRE, "FEL_FRE", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_GER, "FEL_GER", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_ITA, "FEL_ITA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_SPA, "FEL_SPA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+#ifdef MORE_LANGUAGES
+ MENUACTION_CFO_DYNAMIC, "FEL_POL", { new CCFODynamic(nil, nil, nil, LangPolSelect) },
+ MENUACTION_CFO_DYNAMIC, "FEL_RUS", { new CCFODynamic(nil, nil, nil, LangRusSelect) },
+ MENUACTION_CFO_DYNAMIC, "FEL_JAP", { new CCFODynamic(nil, nil, nil, LangJapSelect) },
+#endif
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CHOOSE_LOAD_SLOT = 8
+ { "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_CHECKSAVE, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM },
+ },
+
+ // MENUPAGE_CHOOSE_DELETE_SLOT = 9
+ { "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_CHANGEMENU, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM },
+ },
+
+ // MENUPAGE_NEW_GAME_RELOAD = 10
+ { "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
+ MENUACTION_LABEL, "FESZ_QR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_NEWGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD },
+ },
+
+ // MENUPAGE_LOAD_SLOT_CONFIRM = 11
+ { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil,
+ MENUACTION_LABEL, "FESZ_QL", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS },
+ },
+
+ // MENUPAGE_DELETE_SLOT_CONFIRM = 12
+ { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FESZ_QD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_DELETING },
+ },
+
+ // MENUPAGE_NO_MEMORY_CARD = 13
+ { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ // hud adjustment page in mobile
+ },
+
+ // MENUPAGE_LOADING_IN_PROGRESS = 14
+ { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FED_LDW", { nil, SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM },
+ },
+
+ // MENUPAGE_DELETING_IN_PROGRESS = 15
+ { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FEDL_WR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_PS2_LOAD_FAILED = 16
+ { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FES_LOE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_DELETE_FAILED = 17
+ { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FES_DEE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ },
+
+ // MENUPAGE_DEBUG_MENU = 18
+ { "FED_DBG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_RELOADIDE, "FED_RID", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_RELOADIPL, "FED_RIP", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SETDBGFLAG, "FED_DFL", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_PEDROADGROUPS, "FED_SPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CARROADGROUPS, "FED_SCR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_COLLISIONPOLYS, "FED_SCP", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_PARSEHEAP, "FED_PAH", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SHOWCULL, "FED_SCZ", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_DEBUGSTREAM, "FED_DSR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_MEMORY_CARD_DEBUG = 19
+ { "FEM_MCM", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_REGMEMCARD1, "FEM_RMC", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_TESTFORMATMEMCARD1, "FEM_TFM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_TESTUNFORMATMEMCARD1, "FEM_TUM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CREATEROOTDIR, "FEM_CRD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CREATELOADICONS, "FEM_CLI", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_FILLWITHGUFF, "FEM_FFF", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SAVEONLYTHEGAME, "FEM_SOG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SAVEGAME, "FEM_STG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SAVEGAMEUNDERGTA, "FEM_STS", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CREATECOPYPROTECTED, "FEM_CPD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_MEMORY_CARD_TEST = 20
+ { "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_MAIN = 21
+ { "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_PS2_SAVE_FAILED = 22
+ { "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_PS2_SAVE_FAILED_2 = 23
+ { "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // Unused in PC but anyway
+ // MENUPAGE_SAVE = 24
+#ifdef PS2_SAVE_DIALOG
+ { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_SA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FES_SCG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+ // MENUPAGE_NO_MEMORY_CARD_2 = 25
+ { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CHOOSE_SAVE_SLOT = 26
+ { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL8", { nil, SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ },
+
+ // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FESZ_QO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ },
+
+ // MENUPAGE_MULTIPLAYER_MAP = 28
+ { "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_CONNECTION = 29
+ { "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_FIND_GAME = 30
+ { "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_MODE = 31
+ { "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_CREATE = 32
+ { "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_START = 33
+ { "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_SKIN_SELECT_OLD = 34
+ { "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_CONTROLLER_PC = 35
+ { "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_CTRLMETHOD, "FET_CME", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ MENUACTION_KEYBOARDCTRLS,"FET_RDK", { nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS },
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+ MENUACTION_CHANGEMENU, "FEC_JOD", { nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK },
+#endif
+ MENUACTION_CHANGEMENU, "FET_AMS", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD1 = 36
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_GETKEY, "FEC_PLB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_CWL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_CWR", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_LKT", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_PJP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_PSP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_TLF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_TRG", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_CCM", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD2 = 37
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD3 = 38
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_GETKEY, "FEC_LUP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_GETKEY, "FEC_LDN", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_SHOWHEADBOB, "FEC_GSL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD4 = 39
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+
+ },
+
+ // MENUPAGE_CONTROLLER_DEBUG = 40
+ { "FEC_DBG", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_GETKEY, "FEC_TGD", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_GETKEY, "FEC_TDO", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_GETKEY, "FEC_TSS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_OPTIONS = 41
+ { "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FET_CTL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ MENUACTION_LOADRADIO, "FET_AUD", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_CHANGEMENU, "FET_DIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#ifdef GRAPHICS_MENU_OPTIONS
+ MENUACTION_CHANGEMENU, "FET_GRA", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
+#endif
+ MENUACTION_CHANGEMENU, "FET_LAN", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_PLAYERSETUP, "FET_PSU", { nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_EXIT = 42
+ { "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_LABEL, "FEQ_SRE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_DONTCANCEL, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CANCELGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SAVING_IN_PROGRESS = 43
+ { "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FES_WAR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SAVE_SUCCESSFUL = 44
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FES_SSC", { nil, SAVESLOT_LABEL, MENUPAGE_NONE },
+ MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ },
+
+ // MENUPAGE_DELETING = 45
+ { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FED_DLW", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_DELETE_SUCCESS = 46
+ { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
+ MENUACTION_LABEL, "DEL_FNM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ },
+
+ // MENUPAGE_SAVE_FAILED = 47
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ },
+
+ // MENUPAGE_LOAD_FAILED = 48
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_LOAD_FAILED_2 = 49
+ { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FEC_LUN", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
+ },
+
+ // MENUPAGE_FILTER_GAME = 50
+ { "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_START_MENU = 51
+ { "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS },
+ MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT },
+ },
+
+ // MENUPAGE_PAUSE_MENU = 52
+ { "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_RESUME, "FEM_RES", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+#ifdef MENU_MAP
+ MENUACTION_CHANGEMENU, "FEG_MAP", { nil, SAVESLOT_NONE, MENUPAGE_MAP },
+#endif
+ MENUACTION_CHANGEMENU, "FEP_STA", { nil, SAVESLOT_NONE, MENUPAGE_STATS },
+ MENUACTION_CHANGEMENU, "FEP_BRI", { nil, SAVESLOT_NONE, MENUPAGE_BRIEFS },
+ MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS },
+ MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT },
+ },
+
+ // MENUPAGE_CHOOSE_MODE = 53
+ { "FEN_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FET_SP", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_INITMP, "FET_MP", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SKIN_SELECT = 54
+ { "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN },
+ },
+
+ // MENUPAGE_KEYBOARD_CONTROLS = 55
+ { "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ },
+
+ // MENUPAGE_MOUSE_CONTROLS = 56
+ { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_MOUSESENS, "FEC_MSH", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ MENUACTION_INVVERT, "FEC_IVV", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ INVERT_PAD_SELECTOR
+ MENUACTION_MOUSESTEER, "FET_MST", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+ // MENUPAGE_MISSION_RETRY = 57
+#ifdef MISSION_REPLAY
+
+ { "M_FAIL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FESZ_RM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS },
+ MENUACTION_REJECT_RETRY, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ // mission failed, wanna restart page in mobile
+ },
+#endif
+
+#ifdef MENU_MAP
+ // MENUPAGE_MAP
+ { "FEG_MAP", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_UNK110, "", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, // to prevent cross/enter to go back
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+#ifdef GRAPHICS_MENU_OPTIONS
+ // MENUPAGE_GRAPHICS_SETTINGS
+ { "FET_GRA", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS,
+ new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), GraphicsGoBack,
+
+ MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
+ MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
+ VIDEOMODE_SELECTOR
+ MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MULTISAMPLING_SELECTOR
+#ifdef EXTENDED_COLOURFILTER
+ POSTFX_SELECTORS
+#else
+ MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#endif
+#ifdef EXTENDED_PIPELINES
+ PIPELINES_SELECTOR
+#endif
+ ISLAND_LOADING_SELECTOR
+ DUALPASS_SELECTOR
+ MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefGraphics) },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ // MENUPAGE_ADVANCED_DISPLAY_SETTINGS
+ { "FET_ADV", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS,
+ new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil,
+
+ ISLAND_LOADING_SELECTOR
+ DUALPASS_SELECTOR
+ CUTSCENE_BORDERS_TOGGLE
+ FREE_CAM_TOGGLE
+#ifdef EXTENDED_COLOURFILTER
+ POSTFX_SELECTORS
+#endif
+#ifdef EXTENDED_PIPELINES
+ PIPELINES_SELECTOR
+#endif
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+ // MENUPAGE_DETECT_JOYSTICK
+ { "FEC_JOD", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC,
+ new CCustomScreenLayout({MENUSPRITE_MAINMENU, 40, 60, 20, FONT_BANK, FESCREEN_LEFT_ALIGN, false, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil,
+
+ MENUACTION_LABEL, "FEC_JPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CFO_DYNAMIC, "FEC_JDE", { new CCFODynamic(nil, nil, DetectJoystickDraw, nil) },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+ // MENUPAGE_UNK
+ { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+
+ },
+
+};
+
+#endif
+#endif
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index 0e2f06a6..b971f3ec 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -59,6 +59,9 @@ bool CPad::bDisplayNoControllerMessage;
bool CPad::bObsoleteControllerMessage;
bool CPad::bOldDisplayNoControllerMessage;
bool CPad::m_bMapPadOneToPadTwo;
+#ifdef INVERT_LOOK_FOR_PAD
+bool CPad::bInvertLook4Pad;
+#endif
#ifdef GTA_PS2
unsigned char act_direct[6];
unsigned char act_align[6];
@@ -934,7 +937,7 @@ void CPad::AddToPCCheatString(char c)
if ( !_CHEATCMP("GNIROOOOOB") )
SlowTimeCheat();
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
// "TURTOISE"
if ( !_CHEATCMP("ESIOTRUT") )
ArmourCheat();
@@ -1281,7 +1284,7 @@ void CPad::Update(int16 pad)
{
if ( ShakeDur )
{
- ShakeDur = Max(ShakeDur - CTimer::GetTimeStepInMilliseconds(), 0);
+ ShakeDur = Max(ShakeDur - (int32)CTimer::GetTimeStepInMilliseconds(), 0);
if ( ShakeDur == 0 )
{
@@ -2534,10 +2537,20 @@ int16 CPad::SniperModeLookLeftRight(void)
int16 CPad::SniperModeLookUpDown(void)
{
int16 axis = NewState.LeftStickY;
+ int16 dpad;
#ifdef FIX_BUGS
axis = -axis;
#endif
- int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
+#ifndef INVERT_LOOK_FOR_PAD
+ dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
+#else
+ if (CPad::bInvertLook4Pad) {
+ axis = -axis;
+ dpad = (NewState.DPadDown - NewState.DPadUp) / 2;
+ } else {
+ dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
+ }
+#endif
if ( Abs(axis) > Abs(dpad) )
return axis;
@@ -2567,6 +2580,10 @@ int16 CPad::LookAroundUpDown(void)
#ifdef FIX_BUGS
axis = -axis;
#endif
+#ifdef INVERT_LOOK_FOR_PAD
+ if (CPad::bInvertLook4Pad)
+ axis = -axis;
+#endif
if ( Abs(axis) > 85 && !GetLookBehindForPed() )
return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
@@ -2593,7 +2610,7 @@ void CPad::PrintErrorMessage(void)
CFont::SetScale(0.85f, 1.0f);
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
- CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
+ CFont::SetCentreSize(SCREEN_SCALE_X(SCREEN_WIDTH - 20));
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetColor(CRGBA(255, 255, 200, 200));
@@ -2610,7 +2627,7 @@ void CPad::PrintErrorMessage(void)
CFont::SetScale(0.85f, 1.0f);
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
- CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
+ CFont::SetCentreSize(SCREEN_SCALE_X(SCREEN_WIDTH - 20));
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetColor(CRGBA(255, 255, 200, 200));
diff --git a/src/core/Pad.h b/src/core/Pad.h
index 8c5d7ba3..20a676ef 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -170,6 +170,9 @@ public:
static bool bObsoleteControllerMessage;
static bool bOldDisplayNoControllerMessage;
static bool m_bMapPadOneToPadTwo;
+#ifdef INVERT_LOOK_FOR_PAD
+ static bool bInvertLook4Pad;
+#endif
static CKeyboardState OldKeyState;
static CKeyboardState NewKeyState;
diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp
index bd0814d0..79841c14 100644
--- a/src/core/Pools.cpp
+++ b/src/core/Pools.cpp
@@ -12,6 +12,7 @@
#include "Streaming.h"
#include "Wanted.h"
#include "World.h"
+#include "MemoryHeap.h"
CCPtrNodePool *CPools::ms_pPtrNodePool;
CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool;
@@ -23,18 +24,36 @@ CObjectPool *CPools::ms_pObjectPool;
CDummyPool *CPools::ms_pDummyPool;
CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool;
+#ifdef GTA_PS2 // or USE_CUSTOM_ALLOCATOR
+#define CHECKMEM(msg) CMemCheck::AllocateMemCheckBlock(msg)
+#else
+#define CHECKMEM(msg)
+#endif
+
void
CPools::Initialise(void)
{
+ PUSH_MEMID(MEMID_POOLS);
+ CHECKMEM("before pools");
ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES);
+ CHECKMEM("after CPtrNodePool");
ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS);
+ CHECKMEM("after CEntryInfoNodePool");
ms_pPedPool = new CPedPool(NUMPEDS);
+ CHECKMEM("after CPedPool");
ms_pVehiclePool = new CVehiclePool(NUMVEHICLES);
+ CHECKMEM("after CVehiclePool");
ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS);
+ CHECKMEM("after CBuildingPool");
ms_pTreadablePool = new CTreadablePool(NUMTREADABLES);
+ CHECKMEM("after CTreadablePool");
ms_pObjectPool = new CObjectPool(NUMOBJECTS);
+ CHECKMEM("after CObjectPool");
ms_pDummyPool = new CDummyPool(NUMDUMMIES);
+ CHECKMEM("after CDummyPool");
ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS);
+ CHECKMEM("after pools");
+ POP_MEMID();
}
void
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index 3c5689fd..03b49fd6 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -33,6 +33,9 @@
#endif
#include "main.h"
#include "Frontend.h"
+#include "Font.h"
+#include "MemoryMgr.h"
+#include "MemoryHeap.h"
bool CStreaming::ms_disableStreaming;
bool CStreaming::ms_bLoadingBigModel;
@@ -289,6 +292,11 @@ CStreaming::Shutdown(void)
}
}
+#ifndef MASTER
+uint64 timeProcessingTXD;
+uint64 timeProcessingDFF;
+#endif
+
void
CStreaming::Update(void)
{
@@ -296,6 +304,11 @@ CStreaming::Update(void)
CStreamingInfo *si, *prev;
bool requestedSubway = false;
+#ifndef MASTER
+ timeProcessingTXD = 0;
+ timeProcessingDFF = 0;
+#endif
+
UpdateMemoryUsed();
if(ms_channelError != -1){
@@ -331,6 +344,14 @@ CStreaming::Update(void)
LoadRequestedModels();
+#ifndef MASTER
+ if (CPad::GetPad(1)->GetLeftShoulder1JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2())
+ PrintStreamingBufferState();
+
+ // TODO: PrintRequestList
+ //if (CPad::GetPad(1)->GetLeftShoulder2JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2())
+ // PrintRequestList();
+#endif
for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){
prev = si->m_prev;
@@ -390,6 +411,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
assert(sizeof(direntry) == 32);
while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){
dot = strchr(direntry.name, '.');
+ assert(dot);
if(dot) *dot = '\0';
if(direntry.size > (uint32)ms_streamingBufferSize)
ms_streamingBufferSize = direntry.size;
@@ -436,6 +458,35 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
CFileMgr::CloseFile(fd);
}
+#ifdef USE_CUSTOM_ALLOCATOR
+RpAtomic*
+RegisterAtomicMemPtrsCB(RpAtomic *atomic, void *data)
+{
+#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
+ // not quite sure what's going on here:
+ // gta3's RW 3.1 allocates separate memory for geometry data of RpGeometry.
+ // Is that a R* change? rpDefaultGeometryInstance also depends on it
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ if(geo->triangles)
+ REGISTER_MEMPTR(&geo->triangles);
+ if(geo->matList.materials)
+ REGISTER_MEMPTR(&geo->matList.materials);
+ if(geo->preLitLum)
+ REGISTER_MEMPTR(&geo->preLitLum);
+ if(geo->texCoords[0])
+ REGISTER_MEMPTR(&geo->texCoords[0]);
+ if(geo->texCoords[1])
+ REGISTER_MEMPTR(&geo->texCoords[1]);
+#else
+ // normally RpGeometry is allocated in one block (excluding morph targets)
+ // so we don't really have allocated pointers in the struct.
+ // NB: in librw we actually do it in two allocations (geometry itself and data)
+ // so we could conceivably come up with something here
+#endif
+ return atomic;
+}
+#endif
+
bool
CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
{
@@ -469,10 +520,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Set Txd to use
CTxdStore::AddRef(mi->GetTxdSlot());
- CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
if(mi->IsSimple()){
success = CFileLoader::LoadAtomicFile(stream, streamId);
+#ifdef USE_CUSTOM_ALLOCATOR
+ RegisterAtomicMemPtrsCB(((CSimpleModelInfo*)mi)->m_atomics[0], nil);
+#endif
} else if (mi->GetModelType() == MITYPE_VEHICLE) {
// load vehicles in two parts
CModelInfo::GetModelInfo(streamId)->AddRef();
@@ -481,7 +536,12 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;
}else{
success = CFileLoader::LoadClumpFile(stream, streamId);
+#ifdef USE_CUSTOM_ALLOCATOR
+ if(success)
+ RpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil);
+#endif
}
+ POP_MEMID();
UpdateMemoryUsed();
// Txd no longer needed unless we only read part of the file
@@ -505,12 +565,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
return false;
}
+ PUSH_MEMID(MEMID_STREAM_TEXUTRES);
if(ms_bLoadingBigModel || cdsize > 200){
success = CTxdStore::StartLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
if(success)
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;
}else
success = CTxdStore::LoadTxd(streamId - STREAM_OFFSET_TXD, stream);
+ POP_MEMID();
UpdateMemoryUsed();
if(!success){
@@ -560,7 +622,9 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Mark objects as loaded
if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
+#ifndef USE_CUSTOM_ALLOCATOR
ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;
+#endif
}
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
@@ -600,31 +664,42 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)
if(streamId < STREAM_OFFSET_TXD){
// Model
mi = CModelInfo::GetModelInfo(streamId);
+ PUSH_MEMID(MEMID_STREAM_MODELS);
CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
success = CFileLoader::FinishLoadClumpFile(stream, streamId);
- if(success)
+ if(success){
+#ifdef USE_CUSTOM_ALLOCATOR
+ RpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil);
+#endif
success = AddToLoadedVehiclesList(streamId);
+ }
+ POP_MEMID();
mi->RemoveRef();
CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());
}else{
// Txd
CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD);
+ PUSH_MEMID(MEMID_STREAM_TEXUTRES);
success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
+ POP_MEMID();
CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD);
}
RwStreamClose(stream, &mem);
- ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
+
+ ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; // only done if success on PS2
+#ifndef USE_CUSTOM_ALLOCATOR
ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;
+#endif
if(!success){
RemoveModel(streamId);
ReRequestModel(streamId);
- UpdateMemoryUsed();
+ UpdateMemoryUsed(); // directly after pop on PS2
return false;
}
- UpdateMemoryUsed();
+ UpdateMemoryUsed(); // directly after pop on PS2
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
timeDiff = endTime - startTime;
@@ -741,7 +816,9 @@ CStreaming::RequestBigBuildings(eLevelName level)
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding
#ifdef NO_ISLAND_LOADING
- && ((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) || (b->m_level == level))
+ && (((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODindustEntity) && (b != pIslandLODcomIndEntity) &&
+ (b != pIslandLODcomSubEntity) && (b != pIslandLODsubIndEntity) && (b != pIslandLODsubComEntity)
+ ) || (b->m_level == level))
#else
&& b->m_level == level
#endif
@@ -855,7 +932,11 @@ CStreaming::RemoveModel(int32 id)
CModelInfo::GetModelInfo(id)->DeleteRwObject();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+#ifdef USE_CUSTOM_ALLOCATOR
+ UpdateMemoryUsed();
+#else
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
+#endif
}
if(ms_aInfoForModel[id].m_next){
@@ -877,6 +958,9 @@ CStreaming::RemoveModel(int32 id)
RpClumpGtaCancelStream();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+#ifdef USE_CUSTOM_ALLOCATOR
+ UpdateMemoryUsed();
+#endif
}
ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED;
@@ -2041,19 +2125,25 @@ CStreaming::FlushRequestList(void)
void
CStreaming::ImGonnaUseStreamingMemory(void)
{
- // empty
+ PUSH_MEMID(MEMID_STREAM);
}
void
CStreaming::IHaveUsedStreamingMemory(void)
{
+ POP_MEMID();
UpdateMemoryUsed();
}
void
CStreaming::UpdateMemoryUsed(void)
{
- // empty
+#ifdef USE_CUSTOM_ALLOCATOR
+ ms_memoryUsed =
+ gMainHeap.GetMemoryUsed(MEMID_STREAM) +
+ gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS) +
+ gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES);
+#endif
}
#define STREAM_DIST 80.0f
@@ -2633,3 +2723,71 @@ CStreaming::UpdateForAnimViewer(void)
CStreaming::RetryLoadFile(CStreaming::ms_channelError);
}
}
+
+
+void
+CStreaming::PrintStreamingBufferState()
+{
+ char str[128];
+ wchar wstr[128];
+ uint32 offset, size;
+
+ CTimer::Stop();
+ int i = 0;
+ while (i < NUMSTREAMINFO) {
+ while (true) {
+ int j = 0;
+ DoRWStuffStartOfFrame(50, 50, 50, 0, 0, 0, 255);
+ CPad::UpdatePads();
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+ DefinedState();
+
+ CRect unusedRect(0, 0, RsGlobal.maximumWidth, RsGlobal.maximumHeight);
+ CRGBA unusedColor(255, 255, 255, 255);
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetBackgroundOff();
+ CFont::SetWrapx(DEFAULT_SCREEN_WIDTH);
+ CFont::SetScale(0.5f, 0.75f);
+ CFont::SetCentreOff();
+ CFont::SetCentreSize(DEFAULT_SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+ CFont::SetColor(CRGBA(200, 200, 200, 200));
+ CFont::SetBackGroundOnlyTextOff();
+ int modelIndex = i;
+ if (modelIndex < NUMSTREAMINFO) {
+ int y = 24;
+ for ( ; j < 34 && modelIndex < NUMSTREAMINFO; modelIndex++) {
+ CStreamingInfo *streamingInfo = &ms_aInfoForModel[modelIndex];
+ CBaseModelInfo *modelInfo = CModelInfo::GetModelInfo(modelIndex);
+ if (streamingInfo->m_loadState != STREAMSTATE_LOADED || !streamingInfo->GetCdPosnAndSize(offset, size))
+ continue;
+
+ if (modelIndex >= STREAM_OFFSET_TXD)
+ sprintf(str, "txd %s, refs %d, size %dK, flags 0x%x", CTxdStore::GetTxdName(modelIndex - STREAM_OFFSET_TXD),
+ CTxdStore::GetNumRefs(modelIndex - STREAM_OFFSET_TXD), 2 * size, streamingInfo->m_flags);
+ else
+ sprintf(str, "model %d,%s, refs%d, size%dK, flags%x", modelIndex, modelInfo->GetName(), modelInfo->GetNumRefs(), 2 * size,
+ streamingInfo->m_flags);
+ AsciiToUnicode(str, wstr);
+ CFont::PrintString(24.0f, y, wstr);
+ y += 12;
+ j++;
+ }
+ }
+
+ if (CPad::GetPad(1)->GetCrossJustDown())
+ i = modelIndex;
+
+ if (!CPad::GetPad(1)->GetTriangleJustDown())
+ break;
+
+ i = 0;
+ CFont::DrawFonts();
+ DoRWStuffEndOfFrame();
+ }
+ CFont::DrawFonts();
+ DoRWStuffEndOfFrame();
+ }
+ CTimer::Update();
+} \ No newline at end of file
diff --git a/src/core/Streaming.h b/src/core/Streaming.h
index 0b2ff124..ee9183a5 100644
--- a/src/core/Streaming.h
+++ b/src/core/Streaming.h
@@ -188,4 +188,6 @@ public:
static void MemoryCardLoad(uint8 *buffer, uint32 length);
static void UpdateForAnimViewer(void);
+
+ static void PrintStreamingBufferState();
};
diff --git a/src/core/World.cpp b/src/core/World.cpp
index d65d57dd..0bc564ff 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -53,6 +53,9 @@ bool CWorld::bIncludeCarTyres;
void
CWorld::Initialise()
{
+#if GTA_VERSION <= GTA3_PS2_160
+ CPools::Initialise();
+#endif
pIgnoreEntity = nil;
bDoingCarCollisions = false;
bSecondShift = false;
@@ -919,24 +922,24 @@ CEntity *
CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore,
bool ignoreSomeObjects)
{
- static CColModel sphereCol;
-
- sphereCol.boundingSphere.center.x = 0.0f;
- sphereCol.boundingSphere.center.y = 0.0f;
- sphereCol.boundingSphere.center.z = 0.0f;
- sphereCol.boundingSphere.radius = radius;
- sphereCol.boundingBox.min.x = -radius;
- sphereCol.boundingBox.min.y = -radius;
- sphereCol.boundingBox.min.z = -radius;
- sphereCol.boundingBox.max.x = radius;
- sphereCol.boundingBox.max.y = radius;
- sphereCol.boundingBox.max.z = radius;
- sphereCol.numSpheres = 1;
- sphereCol.spheres = &sphereCol.boundingSphere;
- sphereCol.numLines = 0;
- sphereCol.numBoxes = 0;
- sphereCol.numTriangles = 0;
- sphereCol.ownsCollisionVolumes = false;
+ static CColModel OurColModel;
+
+ OurColModel.boundingSphere.center.x = 0.0f;
+ OurColModel.boundingSphere.center.y = 0.0f;
+ OurColModel.boundingSphere.center.z = 0.0f;
+ OurColModel.boundingSphere.radius = radius;
+ OurColModel.boundingBox.min.x = -radius;
+ OurColModel.boundingBox.min.y = -radius;
+ OurColModel.boundingBox.min.z = -radius;
+ OurColModel.boundingBox.max.x = radius;
+ OurColModel.boundingBox.max.y = radius;
+ OurColModel.boundingBox.max.z = radius;
+ OurColModel.numSpheres = 1;
+ OurColModel.spheres = &OurColModel.boundingSphere;
+ OurColModel.numLines = 0;
+ OurColModel.numBoxes = 0;
+ OurColModel.numTriangles = 0;
+ OurColModel.ownsCollisionVolumes = false;
CMatrix sphereMat;
sphereMat.SetTranslate(spherePos);
@@ -959,7 +962,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
if(e->GetBoundRadius() + radius > distance) {
CColModel *eCol = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
int collidedSpheres =
- CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), *eCol,
+ CCollision::ProcessColModels(sphereMat, OurColModel, e->GetMatrix(), *eCol,
gaTempSphereColPoints, nil, nil);
if(collidedSpheres != 0 ||
@@ -1735,10 +1738,12 @@ CWorld::ShutDown(void)
CWorld::Remove(pEntity);
delete pEntity;
}
+#ifndef FIX_BUGS
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
+#endif
}
for(int32 i = 0; i < 4; i++) {
for(CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) {
@@ -1750,6 +1755,12 @@ CWorld::ShutDown(void)
}
for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {
CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);
+#ifdef FIX_BUGS
+ pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
+ pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
+ pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
+ pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
+#endif
if(pSector->m_lists[ENTITYLIST_BUILDINGS].first) {
sprintf(gString, "Building list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
@@ -1780,6 +1791,9 @@ CWorld::ShutDown(void)
}
}
ms_listMovingEntityPtrs.Flush();
+#if GTA_VERSION <= GTA3_PS2_160
+ CPools::Shutdown();
+#endif
}
void
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index c376e11f..075a13bc 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -1,5 +1,6 @@
#include "common.h"
+#include "General.h"
#include "Building.h"
#include "Treadable.h"
#include "Train.h"
@@ -11,6 +12,9 @@
#include "ZoneCull.h"
#include "Zones.h"
+#include "Debug.h"
+#include "Renderer.h"
+
int32 CCullZones::NumCullZones;
CCullZone CCullZones::aZones[NUMCULLZONES];
int32 CCullZones::NumAttributeZones;
@@ -27,6 +31,8 @@ int32 CCullZones::EntityIndicesUsed;
bool CCullZones::bCurrentSubwayIsInvisible;
bool CCullZones::bCullZonesDisabled;
+#define NUMUNCOMPRESSED (6000)
+#define NUMTEMPINDICES (140000)
void
CCullZones::Init(void)
@@ -48,26 +54,6 @@ CCullZones::Init(void)
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;
@@ -89,19 +75,25 @@ CCullZones::ResolveVisibilities(void)
CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
CFileMgr::CloseFile(fd);
}else{
-#if 0
- // TODO: implement code from mobile to generate data here
+#ifndef MASTER
EntityIndicesUsed = 0;
BuildListForBigBuildings();
- pTempArrayIndices = new uint16[140000];
+ pTempArrayIndices = new uint16[NUMTEMPINDICES];
TempEntityIndicesUsed = 0;
- for (int i = 0; i < NumCullZones; i++) {
- DoVisibilityTestCullZone(i, true);
+// if(!LoadTempFile()) // not in final game
+ {
+ for (int i = 0; i < NumCullZones; i++) {
+//printf("testing zone %d (%d indices)\n", i, TempEntityIndicesUsed);
+ DoVisibilityTestCullZone(i, true);
+ }
+
+// SaveTempFile(); // not in final game
}
CompressIndicesArray();
delete[] pTempArrayIndices;
+ pTempArrayIndices = nil;
fd = CFileMgr::OpenFileForWriting("data\\cullzone.dat");
if (fd != 0) {
@@ -118,16 +110,53 @@ CCullZones::ResolveVisibilities(void)
}
}
+bool
+CCullZones::LoadTempFile(void)
+{
+ int fd = CFileMgr::OpenFile("cullzone.tmp");
+ 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*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16));
+ CFileMgr::Read(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed));
+ CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
+ CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
+ CFileMgr::CloseFile(fd);
+ return true;
+ }
+ return false;
+}
+
+void
+CCullZones::SaveTempFile(void)
+{
+ int fd = CFileMgr::OpenFileForWriting("cullzone.tmp");
+ 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*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16));
+ CFileMgr::Write(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed));
+ CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
+ CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
+ CFileMgr::CloseFile(fd);
+ }
+}
+
+
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];
+ CSimpleModelInfo *nonlod = ((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->GetRelatedModel();
if (nonlod == nil) continue;
- for (int j = i; j >= 0; j--) {
+ for (int j = CPools::GetBuildingPool()->GetSize()-1; j >= 0; j--) {
CBuilding *building2 = CPools::GetBuildingPool()->GetSlot(j);
if (building2 == nil || building2->bIsBIGBuilding) continue;
if (CModelInfo::GetModelInfo(building2->GetModelIndex()) == nonlod) {
@@ -150,7 +179,7 @@ CCullZones::BuildListForBigBuildings()
}
void
-CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
+CCullZones::DoVisibilityTestCullZone(int zoneId, bool findIndices)
{
aZones[zoneId].m_groupIndexCount[0] = 0;
aZones[zoneId].m_groupIndexCount[1] = 0;
@@ -158,16 +187,17 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
aZones[zoneId].m_indexStart = TempEntityIndicesUsed;
aZones[zoneId].FindTestPoints();
- if (!doIt) return;
+ if (!findIndices) 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;
+ CBuilding *LODbuilding = nil;
if (aPointersToBigBuildingsForBuildings[i] != -1)
- building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
+ LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) {
+ assert(TempEntityIndicesUsed < NUMTEMPINDICES);
pTempArrayIndices[TempEntityIndicesUsed++] = i;
aZones[zoneId].m_groupIndexCount[0]++;
}
@@ -175,13 +205,14 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
}
for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CTreadable* building = CPools::GetTreadablePool()->GetSlot(i);
+ CBuilding* building = CPools::GetTreadablePool()->GetSlot(i);
if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) {
- CTreadable* building2 = nil;
+ CBuilding *LODbuilding = nil;
if (aPointersToBigBuildingsForTreadables[i] != -1)
- building2 = CPools::GetTreadablePool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
+ LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, building2)) {
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, LODbuilding)) {
+ assert(TempEntityIndicesUsed < NUMTEMPINDICES);
pTempArrayIndices[TempEntityIndicesUsed++] = i;
aZones[zoneId].m_groupIndexCount[1]++;
}
@@ -189,23 +220,28 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
}
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) {
+ CBuilding *building = CPools::GetTreadablePool()->GetSlot(i);
+ if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < SQR(200.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++) {
+#ifdef FIX_BUGS
+ if (pTempArrayIndices[k] == i)
+#else
if (aIndices[k] == i)
+#endif
alreadyAdded = true;
}
if (!alreadyAdded) {
- CBuilding *building2 = nil;
+ CBuilding *LODbuilding = nil;
if (aPointersToBigBuildingsForTreadables[i] != -1)
- building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
+ LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) {
+ assert(TempEntityIndicesUsed < NUMTEMPINDICES);
pTempArrayIndices[TempEntityIndicesUsed++] = i;
aZones[zoneId].m_groupIndexCount[2]++;
}
@@ -353,7 +389,9 @@ CCullZones::AddCullZone(CVector const &position,
if((flag & ATTRZONE_NOTCULLZONE) == 0){
cull = &aZones[NumCullZones++];
v = position;
- // WTF is this?
+ // reposition start point to the start/end of the
+ // alley next to the big building in the industrial district.
+ // probably isn't analyzed correctly otherwise?s
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)
@@ -385,6 +423,208 @@ CCullZones::AddCullZone(CVector const &position,
}
}
+uint16 *pExtraArrayIndices;
+
+void
+CCullZones::CompressIndicesArray()
+{
+ uint16 set[3];
+
+ // These are used to hold the compressed groups in sets of 3
+ int numExtraIndices = 0;
+ pExtraArrayIndices = new uint16[NUMTEMPINDICES];
+
+ for(int numOccurrences = 6; numOccurrences > 1; numOccurrences--){
+ if(NumCullZones == 0)
+ break;
+
+//printf("checking occurrences %d\n", numOccurrences);
+ int attempt = 0;
+ while(attempt < 10000){
+ for(;;){
+ attempt++;
+
+ int zone = CGeneral::GetRandomNumber() % NumCullZones;
+ int group = CGeneral::GetRandomNumber() % 3;
+ if(!PickRandomSetForGroup(zone, group, set))
+ break;
+ if(!DoWeHaveMoreThanXOccurencesOfSet(numOccurrences, set))
+ break;
+
+ // add this set
+ attempt = 1;
+ int setId = numExtraIndices + NUMUNCOMPRESSED;
+ pExtraArrayIndices[numExtraIndices++] = set[0];
+ pExtraArrayIndices[numExtraIndices++] = set[1];
+ pExtraArrayIndices[numExtraIndices++] = set[2];
+ ReplaceSetForAllGroups(set, setId);
+ }
+ }
+ }
+
+ TidyUpAndMergeLists(pExtraArrayIndices, numExtraIndices);
+
+ delete[] pExtraArrayIndices;
+}
+
+// Get three random indices for this group of a zone
+bool
+CCullZones::PickRandomSetForGroup(int32 zone, int32 group, uint16 *set)
+{
+ int32 start;
+ int32 size;
+
+ aZones[zone].GetGroupStartAndSize(group, start, size);
+ if(size <= 0)
+ return false;
+
+ int numIndices = 0;
+ for(int i = 0; i < size; i++)
+ if(pTempArrayIndices[start + i] != 0xFFFF)
+ numIndices++;
+ if(numIndices < 3)
+ return false;
+
+ int first = CGeneral::GetRandomNumber() % (numIndices-2);
+
+ numIndices = 0;
+ int n = 0;
+ for(int i = 0; i < size; i++)
+ if(pTempArrayIndices[start + i] != 0xFFFF){
+ if(n++ < first) continue;
+
+ set[numIndices++] = pTempArrayIndices[start + i];
+ if(numIndices == 3)
+ break;
+ }
+ return true;
+}
+
+bool
+CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
+{
+ int32 curCount;
+ int32 start;
+ int32 size;
+
+ curCount = 0;
+ for (int i = 0; i < NumCullZones; i++) {
+ for (int group = 0; group < 3; group++) {
+ aZones[i].GetGroupStartAndSize(group, start, size);
+ if(size <= 0) continue;
+
+ // check if the set is a subset of the group
+ int n = 0;
+ for (int j = 0; j < size; j++) {
+ for (int k = 0; k < 3; k++) {
+ if (pTempArrayIndices[start+j] == set[k])
+ n++;
+ }
+ }
+ // yes it is
+ if(n == 3){
+ curCount++;
+ // check if we have seen this set often enough
+ if(curCount >= count)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void
+CCullZones::ReplaceSetForAllGroups(uint16 *set, uint16 setid)
+{
+ int32 start;
+ int32 size;
+
+ for(int i = 0; i < NumCullZones; i++)
+ for(int group = 0; group < 3; group++){
+ aZones[i].GetGroupStartAndSize(group, start, size);
+ if(size <= 0) continue;
+
+ // check if the set is a subset of the group
+ int n = 0;
+ for(int j = 0; j < size; j++){
+ for(int k = 0; k < 3; k++){
+ if(pTempArrayIndices[start+j] == set[k])
+ n++;
+ }
+ }
+
+ // yes it is, so replace it
+ if(n == 3){
+ bool insertedSet = false;
+ for(int j = 0; j < size; j++){
+ for(int k = 0; k < 3; k++){
+ // replace first element by set, invalidate others
+ if(pTempArrayIndices[start+j] == set[k]){
+ if(!insertedSet)
+ pTempArrayIndices[start+j] = setid;
+ else
+ pTempArrayIndices[start+j] = 0xFFFF;
+ insertedSet = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CCullZones::TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices)
+{
+ int numTempIndices = 0;
+ for(int i = 0; i < TempEntityIndicesUsed; i++)
+ if(pTempArrayIndices[i] != 0xFFFF)
+ numTempIndices++;
+
+ // Fix up zone ranges such that there are no holes
+ for(int i = 0; i < NumCullZones; i++){
+ int j;
+ int start = 0;
+ for(j = 0; j < aZones[i].m_indexStart; j++)
+ if(pTempArrayIndices[j] != 0xFFFF)
+ start++;
+
+ aZones[i].m_indexStart = start;
+ aZones[i].m_numBuildings = 0;
+ aZones[i].m_numTreadablesPlus10m = 0;
+ aZones[i].m_numTreadables = 0;
+
+ for(int k = 0; k < aZones[i].m_groupIndexCount[0]; k++)
+ if(pTempArrayIndices[j++] != 0xFFFF)
+ aZones[i].m_numBuildings++;
+ for(int k = 0; k < aZones[i].m_groupIndexCount[1]; k++)
+ if(pTempArrayIndices[j++] != 0xFFFF)
+ aZones[i].m_numTreadablesPlus10m++;
+ for(int k = 0; k < aZones[i].m_groupIndexCount[2]; k++)
+ if(pTempArrayIndices[j++] != 0xFFFF)
+ aZones[i].m_numTreadables++;
+ }
+
+ // Now copy the actually used indices
+ EntityIndicesUsed = 0;
+ for(int i = 0; i < TempEntityIndicesUsed; i++)
+ if(pTempArrayIndices[i] != 0xFFFF){
+ assert(EntityIndicesUsed < NUMZONEINDICES);
+ if(pTempArrayIndices[i] < NUMUNCOMPRESSED)
+ aIndices[EntityIndicesUsed++] = pTempArrayIndices[i];
+ else
+ aIndices[EntityIndicesUsed++] = pTempArrayIndices[i] + numTempIndices;
+ }
+ for(int i = 0; i < numExtraIndices; i++)
+ if(extraIndices[i] != 0xFFFF){
+ assert(EntityIndicesUsed < NUMZONEINDICES);
+ if(extraIndices[i] < NUMUNCOMPRESSED)
+ aIndices[EntityIndicesUsed++] = extraIndices[i];
+ else
+ aIndices[EntityIndicesUsed++] = extraIndices[i] + numTempIndices;
+ }
+}
+
+
void
CCullZone::DoStuffLeavingZone(void)
@@ -403,13 +643,14 @@ CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+
+ if(i < NUMUNCOMPRESSED){
CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
}
@@ -421,14 +662,14 @@ CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
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;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]);
}
@@ -453,13 +694,13 @@ CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]);
}
@@ -471,14 +712,14 @@ CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
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;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]);
}
@@ -490,13 +731,13 @@ CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[i+j]);
}
@@ -519,6 +760,68 @@ CCullZone::CalcDistToCullZoneSquared(float x, float y)
}
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);
+}
+
+bool
+CCullZone::DoThoroughLineTest(CVector start, CVector end, CEntity *testEntity)
+{
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if(CWorld::ProcessLineOfSight(start, end, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+
+ CVector side;
+#ifdef FIX_BUGS
+ if(start.x != end.x || start.y != end.y)
+#else
+ if(start.x != end.x && start.y != end.y)
+#endif
+ side = CVector(0.0f, 0.0f, 1.0f);
+ else
+ side = CVector(1.0f, 0.0f, 0.0f);
+ CVector up = CrossProduct(side, end - start);
+ side = CrossProduct(up, end - start);
+ side.Normalise();
+ up.Normalise();
+ side *= 0.1f;
+ up *= 0.1f;
+
+ if(CWorld::ProcessLineOfSight(start+side, end+side, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ if(CWorld::ProcessLineOfSight(start-side, end-side, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ if(CWorld::ProcessLineOfSight(start+up, end+up, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ if(CWorld::ProcessLineOfSight(start-up, end-up, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ return true;
+}
+
+bool
CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
{
const CVector &pos = entity->GetPosition();
@@ -526,10 +829,10 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
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;
+ if (minfo->m_noFade)
+ lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE;
else
- lodDist = minfo->GetLargestLodDistance() + 50.0f;
+ lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE + FADE_DISTANCE;
if (lodDist > distToZone) return true;
if (!checkLevel) return false;
@@ -538,27 +841,749 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
}
bool
-CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
+CCullZone::PointFallsWithinZone(CVector pos, float radius)
{
- int32 curCount;
- int32 start;
- int32 size;
+ if(minx - radius > pos.x ||
+ maxx + radius < pos.x ||
+ miny - radius > pos.y ||
+ maxy + radius < pos.y ||
+ minz - radius > pos.z ||
+ maxz + radius < pos.z)
+ return false;
+ return true;
+}
- 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++;
+CVector ExtraFudgePointsCoors[] = {
+ CVector(978.0, -394.0, 18.0),
+ CVector(1189.7, -414.6, 27.0),
+ CVector(978.8, -391.0, 19.0),
+ CVector(1199.0, -502.3, 28.0),
+ CVector(1037.0, -391.9, 18.4),
+ CVector(1140.0, -608.7, 16.0),
+ CVector(1051.0, -26.0, 11.0),
+ CVector(951.5, -345.1, 12.0),
+ CVector(958.2, -394.6, 16.0),
+ CVector(1036.5, -390.0, 15.2),
+ CVector(960.6, -390.5, 20.9),
+ CVector(1061.0, -640.6, 16.3),
+ CVector(1034.5, -388.96, 14.78),
+ CVector(1038.4, -13.98, 12.2),
+ CVector(1047.2, -16.7, 10.6),
+ CVector(1257.9, -333.3, 40.0),
+ CVector(885.6, -424.9, 17.0),
+ CVector(1127.5, -795.8, 17.7),
+ CVector(1133.0, -716.0, 19.0),
+ CVector(1125.0, -694.0, 18.5),
+ CVector(1125.0, -670.0, 16.3),
+ CVector(1051.6, 36.3, 17.9),
+ CVector(1054.6, -11.4, 15.0),
+ CVector(1058.9, -278.0, 15.0),
+ CVector(1059.4, -261.0, 10.9),
+ CVector(1051.5, -638.5, 16.5),
+ CVector(1058.2, -643.4, 15.5),
+ CVector(1058.2, -643.4, 18.0),
+ CVector(826.0, -260.0, 7.0),
+ CVector(826.0, -260.0, 11.0),
+ CVector(833.0, -603.6, 16.4),
+ CVector(833.0, -603.6, 20.0),
+ CVector(1002.0, -318.5, 10.5),
+ CVector(998.0, -318.0, 9.8),
+ CVector(1127.0, -183.0, 18.1),
+ CVector(1123.0, -331.5, 23.8),
+ CVector(1123.8, -429.0, 24.0),
+ CVector(1197.0, -30.0, 13.7),
+ CVector(1117.5, -230.0, 17.3),
+ CVector(1117.5, -230.0, 20.0),
+ CVector(1120.0, -281.6, 21.5),
+ CVector(1120.0, -281.6, 24.0),
+ CVector(1084.5, -1022.7, 17.0),
+ CVector(1071.5, 5.4, 4.6),
+ CVector(1177.2, -215.7, 27.6),
+ CVector(841.6, -460.0, 19.7),
+ CVector(874.8, -456.6, 16.6),
+ CVector(918.3, -451.8, 17.8),
+ CVector(844.0, -495.7, 16.7),
+ CVector(842.0, -493.4, 21.0),
+ CVector(1433.5, -774.4, 16.9),
+ CVector(1051.0, -205.0, 7.5),
+ CVector(885.5, -425.6, 15.6),
+ CVector(182.6, -470.4, 27.8),
+ CVector(132.5, -930.2, 29.0),
+ CVector(124.7, -904.0, 28.0),
+ CVector(-50.0, -686.0, 22.0),
+ CVector(-49.1, -694.5, 22.5),
+ CVector(1063.8, -404.45, 16.2),
+ CVector(1062.2, -405.5, 17.0)
+};
+int32 NumTestPoints;
+int32 aTestPointsX[100];
+int32 aTestPointsY[100];
+int32 aTestPointsZ[100];
+CVector aTestPoints[100];
+int32 ElementsX, ElementsY, ElementsZ;
+float StepX, StepY, StepZ;
+int32 Memsize;
+uint8 *pMem;
+#define MEM(x, y, z) pMem[((x)*ElementsY + (y))*ElementsZ + (z)]
+#define FLAG_FREE 1
+#define FLAG_PROCESSED 2
+
+int32 MinValX, MaxValX;
+int32 MinValY, MaxValY;
+int32 MinValZ, MaxValZ;
+int32 Point1, Point2;
+int32 NewPointX, NewPointY, NewPointZ;
+
+
+void
+CCullZone::FindTestPoints()
+{
+ static int CZNumber;
+
+ NumTestPoints = 0;
+ ElementsX = (maxx-minx) < 1.0f ? 2 : (maxx-minx)+1.0f;
+ ElementsY = (maxy-miny) < 1.0f ? 2 : (maxy-miny)+1.0f;
+ ElementsZ = (maxz-minz) < 1.0f ? 2 : (maxz-minz)+1.0f;
+ if(ElementsX > 32) ElementsX = 32;
+ if(ElementsY > 32) ElementsY = 32;
+ if(ElementsZ > 32) ElementsZ = 32;
+ Memsize = ElementsX * ElementsY * ElementsZ;
+ StepX = (maxx-minx)/(ElementsX-1);
+ StepY = (maxy-miny)/(ElementsY-1);
+ StepZ = (maxz-minz)/(ElementsZ-1);
+
+ pMem = new uint8[Memsize];
+ memset(pMem, 0, Memsize);
+
+ // indices of center
+ int x = ElementsX * (position.x-minx)/(maxx-minx);
+ x = clamp(x, 0, ElementsX-1);
+ int y = ElementsY * (position.y-miny)/(maxy-miny);
+ y = clamp(y, 0, ElementsY-1);
+ int z = ElementsZ * (position.z-minz)/(maxz-minz);
+ z = clamp(z, 0, ElementsZ-1);
+
+ // Mark which test points inside the zone are not occupied by buildings.
+ // To do this, mark the start point as free and do a food fill.
+
+ // NB: we just assume the start position is free here!
+ MEM(x, y, z) |= FLAG_FREE;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ NumTestPoints++;
+
+ bool notDoneYet;
+ do{
+ notDoneYet = false;
+ for(x = 0; x < ElementsX; x++){
+ for(y = 0; y < ElementsY; y++){
+ for(z = 0; z < ElementsZ; z++){
+ if(!(MEM(x, y, z) & FLAG_FREE) || MEM(x, y, z) & FLAG_PROCESSED)
+ continue;
+
+ float pX = x*StepX + minx;
+ float pY = y*StepY + miny;
+ float pZ = z*StepZ + minz;
+
+ if(x > 0 && !(MEM(x-1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX-StepX, pY, pZ)))
+ MEM(x-1, y, z) |= FLAG_FREE;
+ if(x < ElementsX-1 && !(MEM(x+1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX+StepX, pY, pZ)))
+ MEM(x+1, y, z) |= FLAG_FREE;
+
+ if(y > 0 && !(MEM(x, y-1, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY-StepY, pZ)))
+ MEM(x, y-1, z) |= FLAG_FREE;
+ if(y < ElementsY-1 && !(MEM(x, y+1, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY+StepY, pZ)))
+ MEM(x, y+1, z) |= FLAG_FREE;
+
+ if(z > 0 && !(MEM(x, y, z-1) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ-StepZ)))
+ MEM(x, y, z-1) |= FLAG_FREE;
+ if(z < ElementsZ-1 && !(MEM(x, y, z+1) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ+StepZ)))
+ MEM(x, y, z+1) |= FLAG_FREE;
+
+ notDoneYet = true;
+ MEM(x, y, z) |= FLAG_PROCESSED;
+ }
+ }
+ }
+ }while(notDoneYet);
+
+ bool done;
+
+ // Find bound planes of free space
+
+ // increase x, bounds in y and z
+ x = 0;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(y + z < minA){
+ minA = y + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(y + z > maxA){
+ maxA = y + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(y - z < minB){
+ minB = y - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(y - z > maxB){
+ maxB = y - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ x++;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // decrease x, bounds in y and z
+ x = ElementsX-1;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(y + z < minA){
+ minA = y + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(y + z > maxA){
+ maxA = y + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(y - z < minB){
+ minB = y - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(y - z > maxB){
+ maxB = y - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ x--;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // increase y, bounds in x and z
+ y = 0;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + z < minA){
+ minA = x + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + z > maxA){
+ maxA = x + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - z < minB){
+ minB = x - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - z > maxB){
+ maxB = x - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ y++;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // decrease y, bounds in x and z
+ y = ElementsY-1;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + z < minA){
+ minA = x + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + z > maxA){
+ maxA = x + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - z < minB){
+ minB = x - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - z > maxB){
+ maxB = x - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
}
+ y--;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // increase z, bounds in x and y
+ z = 0;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + y < minA){
+ minA = x + y;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + y > maxA){
+ maxA = x + y;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - y < minB){
+ minB = x - y;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - y > maxB){
+ maxB = x - y;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ z++;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // decrease z, bounds in x and y
+ z = ElementsZ-1;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + y < minA){
+ minA = x + y;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + y > maxA){
+ maxA = x + y;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - y < minB){
+ minB = x - y;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - y > maxB){
+ maxB = x - y;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ z--;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // divide the axis aligned bounding planes into 4 and place some test points
+
+ // x = 0 plane
+ MinValY = 999999;
+ MinValZ = 999999;
+ MaxValY = 0;
+ MaxValZ = 0;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(0, y, z) & FLAG_FREE){
+ if(y < MinValY) MinValY = y;
+ if(z < MinValZ) MinValZ = z;
+ if(y > MaxValY) MaxValY = y;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValY != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(0, NewPointY, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = 0;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // x = ElementsX-1 plane
+ MinValY = 999999;
+ MinValZ = 999999;
+ MaxValY = 0;
+ MaxValZ = 0;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(ElementsX-1, y, z) & FLAG_FREE){
+ if(y < MinValY) MinValY = y;
+ if(z < MinValZ) MinValZ = z;
+ if(y > MaxValY) MaxValY = y;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValY != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(ElementsX-1, NewPointY, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = ElementsX-1;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // y = 0 plane
+ MinValX = 999999;
+ MinValZ = 999999;
+ MaxValX = 0;
+ MaxValZ = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, 0, z) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(z < MinValZ) MinValZ = z;
+ if(x > MaxValX) MaxValX = x;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(NewPointX, 0, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = 0;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // y = ElementsY-1 plane
+ MinValX = 999999;
+ MinValZ = 999999;
+ MaxValX = 0;
+ MaxValZ = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, ElementsY-1, z) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(z < MinValZ) MinValZ = z;
+ if(x > MaxValX) MaxValX = x;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(NewPointX, ElementsY-1, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = ElementsY-1;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // z = 0 plane
+ MinValX = 999999;
+ MinValY = 999999;
+ MaxValX = 0;
+ MaxValY = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, 0) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(y < MinValY) MinValY = y;
+ if(x > MaxValX) MaxValX = x;
+ if(y > MaxValY) MaxValY = y;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValY != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ if(MEM(NewPointX, NewPointY, 0) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = 0;
+ NumTestPoints++;
+ }
+ }
+
+ // z = ElementsZ-1 plane
+ MinValX = 999999;
+ MinValY = 999999;
+ MaxValX = 0;
+ MaxValY = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, ElementsZ-1) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(y < MinValY) MinValY = y;
+ if(x > MaxValX) MaxValX = x;
+ if(y > MaxValY) MaxValY = y;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValY != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ if(MEM(NewPointX, NewPointY, ElementsZ-1) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = ElementsZ-1;
+ NumTestPoints++;
+ }
+ }
+
+ // add some hardcoded test points
+ for(int i = 0; i < ARRAY_SIZE(ExtraFudgePointsCoors); i++)
+ if(PointFallsWithinZone(ExtraFudgePointsCoors[i], 0.0f)){
+ x = ElementsX * (ExtraFudgePointsCoors[i].x-minx)/(maxx-minx);
+ y = ElementsY * (ExtraFudgePointsCoors[i].y-miny)/(maxy-miny);
+ z = ElementsZ * (ExtraFudgePointsCoors[i].z-minz)/(maxz-minz);
+ if(MEM(x, y, z) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ NumTestPoints++;
+ }
+ }
+
+ // remove duplicate points
+ for(int i = 0; i < NumTestPoints; i++)
+ for(int j = i+1; j < NumTestPoints; j++)
+ if(aTestPointsX[j] == aTestPointsX[i] &&
+ aTestPointsY[j] == aTestPointsY[i] &&
+ aTestPointsZ[j] == aTestPointsZ[i]){
+ // get rid of [j]
+ for(int k = j; k < NumTestPoints-1; k++){
+ aTestPointsX[k] = aTestPointsX[k+1];
+ aTestPointsY[k] = aTestPointsY[k+1];
+ aTestPointsZ[k] = aTestPointsZ[k+1];
+ }
+ NumTestPoints--;
+ }
+
+ // convert points to floating point
+ for(int i = 0; i < NumTestPoints; i++){
+ aTestPoints[i].x = aTestPointsX[i]*StepX + minx;
+ aTestPoints[i].y = aTestPointsY[i]*StepY + miny;
+ aTestPoints[i].z = aTestPointsZ[i]*StepZ + minz;
+ }
+
+ CZNumber++;
+
+ delete[] pMem;
+ pMem = nil;
+}
+
+bool
+CCullZone::TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity)
+{
+ CColModel *colmodel = entity->GetColModel();
+ float boundMaxX = colmodel->boundingBox.max.x;
+ float boundMaxY = colmodel->boundingBox.max.y;
+ float boundMaxZ = colmodel->boundingBox.max.z;
+ float boundMinX = colmodel->boundingBox.min.x;
+ float boundMinY = colmodel->boundingBox.min.y;
+ float boundMinZ = colmodel->boundingBox.min.z;
+ if(LODentity){
+ colmodel = LODentity->GetColModel();
+ boundMaxX = Max(boundMaxX, colmodel->boundingBox.max.x);
+ boundMaxY = Max(boundMaxY, colmodel->boundingBox.max.y);
+ boundMaxZ = Max(boundMaxZ, colmodel->boundingBox.max.z);
+ boundMinX = Min(boundMinX, colmodel->boundingBox.min.x);
+ boundMinY = Min(boundMinY, colmodel->boundingBox.min.y);
+ boundMinZ = Min(boundMinZ, colmodel->boundingBox.min.z);
+ }
+
+ if(boundMaxZ-boundMinZ + extraDist < 0.5f)
+ boundMaxZ = boundMinZ + 0.5f;
+ else
+ boundMaxZ += extraDist;
+
+ CVector vecMin = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMinZ);
+ CVector vecMaxX = entity->GetMatrix() * CVector(boundMaxX, boundMinY, boundMinZ);
+ CVector vecMaxY = entity->GetMatrix() * CVector(boundMinX, boundMaxY, boundMinZ);
+ CVector vecMaxZ = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMaxZ);
+ CVector dirx = vecMaxX - vecMin;
+ CVector diry = vecMaxY - vecMin;
+ CVector dirz = vecMaxZ - vecMin;
+
+ // If building intersects zone at all, it's visible
+ int x, y, z;
+ for(x = 0; x < 9; x++){
+ CVector posX = vecMin + x/8.0f*dirx;
+ for(y = 0; y < 9; y++){
+ CVector posY = posX + y/8.0f*diry;
+ for(z = 0; z < 9; z++){
+ CVector posZ = posY + z/8.0f*dirz;
+ if(PointFallsWithinZone(posZ, 2.0f))
+ return true;
}
- if (unk == 3 && ++curCount >= count)
- return true;
}
}
+
+ float distToZone = CalcDistToCullZone(entity->GetPosition().x, entity->GetPosition().y)/15.0f;
+ distToZone = Max(distToZone, 7.0f);
+ int numX = (boundMaxX - boundMinX)/distToZone + 2.0f;
+ int numY = (boundMaxY - boundMinY)/distToZone + 2.0f;
+ int numZ = (boundMaxZ - boundMinZ)/distToZone + 2.0f;
+
+ float stepX = 1.0f/(numX-1);
+ float stepY = 1.0f/(numY-1);
+ float stepZ = 1.0f/(numZ-1);
+ float midX = (boundMaxX + boundMinX)/2.0f;
+ float midY = (boundMaxY + boundMinY)/2.0f;
+ float midZ = (boundMaxZ + boundMinZ)/2.0f;
+
+ // check both xy planes
+ for(int i = 0; i < NumTestPoints; i++){
+ CVector testPoint = aTestPoints[i];
+ CVector mid = entity->GetMatrix() * CVector(midX, midY, midZ);
+ mid.z += 0.1f;
+ if(DoThoroughLineTest(testPoint, mid, entity))
+ return true;
+
+ CVector ray = entity->GetPosition() - testPoint;
+
+ float dotX = DotProduct(ray, dirx);
+ float dotY = DotProduct(ray, diry);
+ float dotZ = DotProduct(ray, dirz);
+
+ for(x = 0; x < numX; x++){
+ CVector pMinZ = vecMin + x*stepX*dirx;
+ CVector pMaxZ = vecMin + x*stepX*dirx + dirz;
+ for(y = 0; y < numY; y++)
+ if(dotZ > 0.0f){
+ if(DoThoroughLineTest(testPoint, pMinZ + y*stepY*diry, entity))
+ return true;
+ }else{
+ if(DoThoroughLineTest(testPoint, pMaxZ + y*stepY*diry, entity))
+ return true;
+ }
+ }
+
+ for(x = 0; x < numX; x++){
+ CVector pMinY = vecMin + x*stepX*dirx;
+ CVector pMaxY = vecMin + x*stepX*dirx + diry;
+ for(z = 1; z < numZ-1; z++) // edge cases already handled
+ if(dotY > 0.0f){
+ if(DoThoroughLineTest(testPoint, pMinY + z*stepZ*dirz, entity))
+ return true;
+ }else{
+ if(DoThoroughLineTest(testPoint, pMaxY + z*stepZ*dirz, entity))
+ return true;
+ }
+ }
+
+ for(y = 1; y < numY-1; y++){ // edge cases already handled
+ CVector pMinX = vecMin + y*stepY*diry;
+ CVector pMaxX = vecMin + y*stepY*diry + dirx;
+ for(z = 1; z < numZ-1; z++) // edge cases already handled
+ if(dotX > 0.0f){
+ if(DoThoroughLineTest(testPoint, pMinX + z*stepZ*dirz, entity))
+ return true;
+ }else{
+ if(DoThoroughLineTest(testPoint, pMaxX + z*stepZ*dirz, entity))
+ return true;
+ }
+ }
+ }
+
return false;
}
diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h
index 9bc07b8c..10742ffb 100644
--- a/src/core/ZoneCull.h
+++ b/src/core/ZoneCull.h
@@ -12,7 +12,7 @@ public:
float maxz;
int32 m_indexStart;
- int16 m_groupIndexCount[3];
+ int16 m_groupIndexCount[3]; // only useful during resolution stage
int16 m_numBuildings;
int16 m_numTreadablesPlus10m;
int16 m_numTreadables;
@@ -26,30 +26,35 @@ public:
static void DoStuffEnteringZone_OneTreadable(uint16 i);
- static bool TestLine(CVector a1, CVector a2);
+ static bool TestLine(CVector vec1, CVector vec2);
+ static bool DoThoroughLineTest(CVector vec1, CVector vec2, CEntity *testEntity);
float CalcDistToCullZoneSquared(float x, float y);
float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); };
bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel);
+ bool PointFallsWithinZone(CVector pos, float radius);
+ bool TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity);
+ void FindTestPoints();
void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) {
switch (groupid) {
+ case 0:
+ default:
+ // buildings
+ start = m_indexStart;
+ size = m_groupIndexCount[0];
+ break;
case 1:
+ // treadables + 10m
start = m_groupIndexCount[0] + m_indexStart;
size = m_groupIndexCount[1];
break;
case 2:
+ // treadables
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
@@ -121,5 +126,12 @@ public:
static void DoVisibilityTestCullZone(int zoneId, bool doIt);
static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set);
- static void CompressIndicesArray() {};// todo
+ static void CompressIndicesArray();
+ static bool PickRandomSetForGroup(int32 zone, int32 group, uint16 *set);
+ static void ReplaceSetForAllGroups(uint16 *set, uint16 setid);
+ static void TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices);
+
+ // debug
+ static bool LoadTempFile(void);
+ static void SaveTempFile(void);
};
diff --git a/src/core/config.h b/src/core/config.h
index a87b1850..d64cca40 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -1,27 +1,27 @@
#pragma once
enum Config {
- NUMPLAYERS = 1,
+ NUMPLAYERS = 1, // 4 on PS2
NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC)
MAX_CDIMAGES = 8, // additional cdimages
MAX_CDCHANNELS = 5,
- MODELINFOSIZE = 5500,
+ MODELINFOSIZE = 5500, // 3150 on PS2
// TXDSTORESIZE = 850,
TXDSTORESIZE = 1024, // for Xbox map
EXTRADIRSIZE = 128,
CUTSCENEDIRSIZE = 512,
- SIMPLEMODELSIZE = 5000,
+ SIMPLEMODELSIZE = 5000, // 2910 on PS2
MLOMODELSIZE = 1,
MLOINSTANCESIZE = 1,
TIMEMODELSIZE = 30,
CLUMPMODELSIZE = 5,
PEDMODELSIZE = 90,
- VEHICLEMODELSIZE = 120,
+ VEHICLEMODELSIZE = 120, // 70 on PS2
XTRACOMPSMODELSIZE = 2,
- TWODFXSIZE = 2000,
+ TWODFXSIZE = 2000, // 1210 on PS2
MAXVEHICLESLOADED = 50, // 70 on mobile
@@ -135,10 +135,6 @@ enum Config {
NUM_EXPLOSIONS = 48,
};
-// We'll use this once we're ready to become independent of the game
-// Use it to mark bugs in the code that will prevent the game from working then
-//#define STANDALONE
-
// We don't expect to compile for PS2 or Xbox
// but it might be interesting for documentation purposes
#define GTA_PC
@@ -156,30 +152,68 @@ enum Config {
// any debug stuff that is only left in mobile, is not in MASTER
//#define MASTER
+// once and for all:
+// pc: FINAL & MASTER
+// mobile: FINAL
+
+// MASTER builds must be FINAL
+#ifdef MASTER
+#define FINAL
+#endif
+
+// Version defines
+#define GTA3_PS2_140 300
+#define GTA3_PS2_160 301
+#define GTA3_PC_10 310
+#define GTA3_PC_11 311
+#define GTA3_PC_STEAM 312
+// TODO? maybe something for xbox or android?
+
+#define GTA_VERSION GTA3_PC_11
+
+// quality of life fixes that should also be in FINAL
+#define NASTY_GAME // nasty game for all languages
+#define NO_CDCHECK
+
+// those infamous texts
+#define DRAW_GAME_VERSION_TEXT
+#define DRAW_MENU_VERSION_TEXT
+
+// Memory allocation and compression
+// #define USE_CUSTOM_ALLOCATOR // use CMemoryHeap for allocation. use with care, not finished yet
+//#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices
+//#define ANIM_COMPRESSION // only keep most recently used anims uncompressed
+
#if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH
+# define USE_CUSTOM_ALLOCATOR
# define VU_COLLISION
+# define ANIM_COMPRESSION
#elif defined GTA_PC
-# define GTA3_1_1_PATCH
-//# define GTA3_STEAM_PATCH
# ifdef GTA_PS2_STUFF
# define USE_PS2_RAND
# define RANDOMSPLASH // use random splash as on PS2
# define PS2_MATFX
# endif
+# define GTA_REPLAY
+# define GTA_SCENE_EDIT
#elif defined GTA_XBOX
#endif
#ifdef VU_COLLISION
-#define COMPRESSED_COL_VECTORS // current need compressed vectors in this code
+#define COMPRESSED_COL_VECTORS // currently need compressed vectors in this code
#endif
#ifdef MASTER
// only in master builds
+ #undef DRAW_GAME_VERSION_TEXT
#else
// not in master builds
#define VALIDATE_SAVE_SIZE
+
+ #define NO_MOVIES // disable intro videos
+ #define DEBUGMENU
#endif
#ifdef FINAL
@@ -187,18 +221,19 @@ enum Config {
# define USE_MY_DOCUMENTS // use my documents directory for user files
#else
// not in any game
-# define NASTY_GAME // nasty game for all languages
-# define NO_MOVIES // disable intro videos
-# define NO_CDCHECK
# define CHATTYSPLASH // print what the game is loading
-# define DEBUGMENU
# define TIMEBARS // print debug timers
#endif
-#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more
+#define FIX_BUGS // fixes bugs that we've came across during reversing
#define MORE_LANGUAGES // Add more translations to the game
#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible
-#define LOAD_INI_SETTINGS
+#define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS
+
+// Just debug menu entries
+#ifdef DEBUGMENU
+#define MISSION_SWITCHER // from debug menu
+#endif
// Rendering/display
//#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering
@@ -209,17 +244,20 @@ enum Config {
#define USE_TXD_CDIMAGE // generate and load textures from txd.img
#define PS2_ALPHA_TEST // emulate ps2 alpha test
#define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number
-//#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time
-#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU
+#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time
+#define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync
//#define USE_TEXTURE_POOL
-#define CUTSCENE_BORDERS_SWITCH
+#ifdef LIBRW
//#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur)
//#define EXTENDED_PIPELINES // custom render pipelines (includes Neo)
-#define MULTISAMPLING // adds MSAA option
+//#define SCREEN_DROPLETS // neo water droplets
+#endif
-#ifdef LIBRW
-// these are not supported with librw yet
-# undef MULTISAMPLING
+#ifndef EXTENDED_COLOURFILTER
+#undef SCREEN_DROPLETS // we need the backbuffer for this effect
+#endif
+#ifndef EXTENDED_PIPELINES
+#undef SCREEN_DROPLETS // we need neo.txd
#endif
// Particle
@@ -239,12 +277,14 @@ enum Config {
#define ALT_DODO_CHEAT
#define REGISTER_START_BUTTON
//#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls
+#define BUTTON_ICONS // use textures to show controller buttons
// Hud, frontend and radar
#define PS2_HUD
#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better.
// #define BETA_SLIDING_TEXT
#define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC
+// #define XBOX_SUBTITLES // the infamous outlines
#define PC_MENU
#ifndef PC_MENU
@@ -258,7 +298,14 @@ enum Config {
//# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc.
//# define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box
# define CUSTOM_FRONTEND_OPTIONS
-# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full
+
+# ifdef CUSTOM_FRONTEND_OPTIONS
+# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full
+# define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU
+# define CUTSCENE_BORDERS_SWITCH
+# define MULTISAMPLING // adds MSAA option
+# define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC
+# endif
#endif
// Script
@@ -270,7 +317,7 @@ enum Config {
#endif
//#define SIMPLIER_MISSIONS // apply simplifications from mobile
#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
-#define SCRIPT_LOG_FILE_LEVEL 1 // 0 == no log, 1 == overwrite every frame, 2 == full log
+#define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log
#ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#define USE_BASIC_SCRIPT_DEBUG_OUTPUT
@@ -307,6 +354,8 @@ enum Config {
#endif
//#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS
+// IMG
+#define BIG_IMG // allows to read larger img files
//#define SQUEEZE_PERFORMANCE
#ifdef SQUEEZE_PERFORMANCE
@@ -315,3 +364,7 @@ enum Config {
#define PC_PARTICLE
#define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial
#endif
+
+#ifdef LIBRW
+// these are not supported with librw yet
+#endif
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 171d0a57..cc7f3259 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -63,7 +63,11 @@
#include "SceneEdit.h"
#include "debugmenu.h"
#include "Clock.h"
+#include "postfx.h"
#include "custompipes.h"
+#include "screendroplets.h"
+#include "frontendoption.h"
+#include "MemoryHeap.h"
GlobalScene Scene;
@@ -88,7 +92,11 @@ RwRGBA gColourTop;
bool gameAlreadyInitialised;
float NumberOfChunksLoaded;
+#ifdef GTA_PS2
+#define TOTALNUMCHUNKS 48.0f
+#else
#define TOTALNUMCHUNKS 73.0f
+#endif
bool g_SlowMode = false;
char version_name[64];
@@ -102,6 +110,18 @@ void TheGame(void);
void DebugMenuPopulate(void);
#endif
+#ifndef FINAL
+bool gbPrintMemoryUsage;
+#endif
+
+#ifdef PS2_MENU
+#define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad
+#define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad
+#else
+#define WANT_TO_LOAD FrontEndMenuManager.m_bWantToLoad
+#define FOUND_GAME_TO_LOAD b_FoundRecentSavedGameWantToLoad
+#endif
+
void
ValidateVersion()
{
@@ -404,10 +424,20 @@ Initialise3D(void *param)
DebugMenuInit();
DebugMenuPopulate();
#endif // !DEBUGMENU
+#ifdef CUSTOM_FRONTEND_OPTIONS
+ // Apparently this func. can be run multiple times at the start.
+ if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) {
+ // needs stored language and TheText to be loaded, and last TheText reload is at the start of here
+ CustomFrontendOptionsPopulate();
+ }
+#endif
bool ret = CGame::InitialiseRenderWare();
#ifdef EXTENDED_PIPELINES
CustomPipes::CustomPipeInit(); // need Scene.world for this
#endif
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::InitDraw();
+#endif
return ret;
}
@@ -417,6 +447,9 @@ Initialise3D(void *param)
static void
Terminate3D(void)
{
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Shutdown();
+#endif
#ifdef EXTENDED_PIPELINES
CustomPipes::CustomPipeShutdown();
#endif
@@ -634,18 +667,18 @@ LoadingIslandScreen(const char *levelName)
CFont::SetColor(CRGBA(243, 237, 71, 255));
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
#else
- CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
+ CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_SCALE_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
#endif
TextCopy(wstr, name);
TheText.UpperCase(wstr);
CFont::SetColor(CRGBA(243, 237, 71, 255));
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(80.0f), wstr);
#else
- CFont::PrintString(SCREEN_WIDTH-20, SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr);
+ CFont::PrintString(SCREEN_WIDTH-20, SCREEN_SCALE_FROM_BOTTOM(80.0f), wstr);
#endif
CFont::DrawFonts();
DoRWStuffEndOfFrame();
@@ -768,6 +801,170 @@ tZonePrint ZonePrint[] =
};
#ifndef MASTER
+
+void
+PrintMemoryUsage(void)
+{
+// little hack
+if(CPools::GetPtrNodePool() == nil)
+return;
+
+ // Style taken from LCS, modified for III
+// CFont::SetFontStyle(FONT_PAGER);
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetBackgroundOff();
+ CFont::SetWrapx(640.0f);
+// CFont::SetScale(0.5f, 0.75f);
+ CFont::SetScale(0.4f, 0.75f);
+ CFont::SetCentreOff();
+ CFont::SetCentreSize(640.0f);
+ CFont::SetJustifyOff();
+ CFont::SetPropOn();
+ CFont::SetColor(CRGBA(200, 200, 200, 200));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetDropShadowPosition(0);
+
+ float y;
+
+#ifdef USE_CUSTOM_ALLOCATOR
+ y = 24.0f;
+ sprintf(gString, "Total: %d blocks, %d bytes", gMainHeap.m_totalBlocksUsed, gMainHeap.m_totalMemUsed);
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Game: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME), gMainHeap.GetMemoryUsed(MEMID_GAME));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "World: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_WORLD), gMainHeap.GetMemoryUsed(MEMID_WORLD));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Render: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDER), gMainHeap.GetMemoryUsed(MEMID_RENDER));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Render List: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDERLIST), gMainHeap.GetMemoryUsed(MEMID_RENDERLIST));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Default Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_DEF_MODELS), gMainHeap.GetMemoryUsed(MEMID_DEF_MODELS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_TEXTURES), gMainHeap.GetMemoryUsed(MEMID_TEXTURES));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streaming: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM), gMainHeap.GetMemoryUsed(MEMID_STREAM));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streamed Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_MODELS), gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streamed Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_TEXUTRES), gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Animation: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_ANIMATION));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Pools: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_POOLS), gMainHeap.GetMemoryUsed(MEMID_POOLS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Collision: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_COLLISION), gMainHeap.GetMemoryUsed(MEMID_COLLISION));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Game Process: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME_PROCESS), gMainHeap.GetMemoryUsed(MEMID_GAME_PROCESS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Script: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_SCRIPT), gMainHeap.GetMemoryUsed(MEMID_SCRIPT));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Cars: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_CARS), gMainHeap.GetMemoryUsed(MEMID_CARS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Frontend: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_FRONTEND), gMainHeap.GetMemoryUsed(MEMID_FRONTEND));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+#endif
+
+ y = 132.0f;
+ AsciiToUnicode("Pools usage:", gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "PtrNode: %d/%d", CPools::GetPtrNodePool()->GetNoOfUsedSpaces(), CPools::GetPtrNodePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "EntryInfoNode: %d/%d", CPools::GetEntryInfoNodePool()->GetNoOfUsedSpaces(), CPools::GetEntryInfoNodePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Ped: %d/%d", CPools::GetPedPool()->GetNoOfUsedSpaces(), CPools::GetPedPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Vehicle: %d/%d", CPools::GetVehiclePool()->GetNoOfUsedSpaces(), CPools::GetVehiclePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Building: %d/%d", CPools::GetBuildingPool()->GetNoOfUsedSpaces(), CPools::GetBuildingPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Treadable: %d/%d", CPools::GetTreadablePool()->GetNoOfUsedSpaces(), CPools::GetTreadablePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Object: %d/%d", CPools::GetObjectPool()->GetNoOfUsedSpaces(), CPools::GetObjectPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Dummy: %d/%d", CPools::GetDummyPool()->GetNoOfUsedSpaces(), CPools::GetDummyPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "AudioScriptObjects: %d/%d", CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces(), CPools::GetAudioScriptObjectPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+}
+
void
DisplayGameDebugText()
{
@@ -779,11 +976,15 @@ DisplayGameDebugText()
TWEAKBOOL(bDisplayPosn);
TWEAKBOOL(bDisplayRate);
}
-#endif
+ if(gbPrintMemoryUsage)
+ PrintMemoryUsage();
+#endif
char str[200];
wchar ustr[200];
+
+#ifdef DRAW_GAME_VERSION_TEXT
wchar ver[200];
AsciiToUnicode(version_name, ver);
@@ -803,6 +1004,7 @@ DisplayGameDebugText()
#else
CFont::PrintString(10.0f, 10.0f, ver);
#endif
+#endif // #ifdef DRAW_GAME_VERSION_TEXT
FrameSamples++;
FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);
@@ -989,9 +1191,11 @@ Render2dStuff(void)
MusicManager.DisplayRadioStationName();
TheConsole.Display();
+#ifdef GTA_SCENE_EDIT
if(CSceneEdit::m_bEditOn)
CSceneEdit::Draw();
else
+#endif
CHud::Draw();
CUserDisplay::OnscnTimer.ProcessForDisplay();
CMessages::Display();
@@ -1010,13 +1214,9 @@ RenderMenus(void)
{
if (FrontEndMenuManager.m_bMenuActive)
{
-#ifdef PS2
- gMainHeap.PushMemId(_TODOCONST(17));
-#endif
+ PUSH_MEMID(MEMID_FRONTEND);
FrontEndMenuManager.DrawFrontEnd();
-#ifdef PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
}
}
@@ -1055,24 +1255,29 @@ Idle(void *arg)
CPad::UpdatePads();
FrontEndMenuManager.Process();
} else {
+ PUSH_MEMID(MEMID_GAME_PROCESS);
CPointLights::InitPerFrame();
tbStartTimer(0, "CGame::Process");
CGame::Process();
tbEndTimer("CGame::Process");
+ POP_MEMID();
+
tbStartTimer(0, "DMAudio.Service");
DMAudio.Service();
-
tbEndTimer("DMAudio.Service");
}
if (RsGlobal.quit)
return;
#else
+
+ PUSH_MEMID(MEMID_GAME_PROCESS);
CPointLights::InitPerFrame();
tbStartTimer(0, "CGame::Process");
CGame::Process();
tbEndTimer("CGame::Process");
+ POP_MEMID();
tbStartTimer(0, "DMAudio.Service");
DMAudio.Service();
@@ -1080,21 +1285,12 @@ Idle(void *arg)
#endif
if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
-#ifdef PS2_MENU
- TheMemoryCard.m_bWantToLoad = false;
+ WANT_TO_LOAD = false;
FrontEndMenuManager.m_bWantToRestart = true;
-#else
- FrontEndMenuManager.m_bWantToRestart = true;
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
return;
}
-#ifdef PS2_MENU
- if ( FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad )
-#else
- if(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
{
return;
}
@@ -1104,18 +1300,22 @@ Idle(void *arg)
if(arg == nil)
return;
+ PUSH_MEMID(MEMID_RENDER);
+
if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) &&
TheCamera.GetScreenFadeStatus() != FADE_2)
{
-#if defined(GTA_PC) && defined(FIX_BUGS)
+#if defined(GTA_PC) && !defined(RW_GL3) && defined(FIX_BUGS)
+ // This is from SA, but it's nice for windowed mode
if (!FrontEndMenuManager.m_bRenderGameInMenu) {
- // This is from SA, but it's nice for windowed mode
RwV2d pos;
pos.x = SCREEN_WIDTH / 2.0f;
pos.y = SCREEN_HEIGHT / 2.0f;
RsMouseSetPos(&pos);
}
#endif
+
+ PUSH_MEMID(MEMID_RENDERLIST);
tbStartTimer(0, "CnstrRenderList");
CRenderer::ConstructRenderList();
tbEndTimer("CnstrRenderList");
@@ -1123,6 +1323,7 @@ Idle(void *arg)
tbStartTimer(0, "PreRender");
CRenderer::PreRender();
tbEndTimer("PreRender");
+ POP_MEMID();
#ifdef FIX_BUGS
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this
@@ -1133,12 +1334,12 @@ Idle(void *arg)
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
- return;
+ goto popret;
}else{
if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
255))
- return;
+ goto popret;
}
DefinedState();
@@ -1159,10 +1360,17 @@ Idle(void *arg)
RenderDebugShit();
RenderEffects();
- tbStartTimer(0, "RenderMotionBlur");
if((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) &&
TheCamera.m_ScreenReductionPercentage > 0.0f)
TheCamera.SetMotionBlurAlpha(150);
+
+#ifdef SCREEN_DROPLETS
+ CPostFX::GetBackBuffer(Scene.camera);
+ ScreenDroplets::Process();
+ ScreenDroplets::Render();
+#endif
+
+ tbStartTimer(0, "RenderMotionBlur");
TheCamera.RenderMotionBlur();
tbEndTimer("RenderMotionBlur");
@@ -1178,7 +1386,7 @@ Idle(void *arg)
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))
- return;
+ goto popret;
}
#ifdef PS2_SAVE_DIALOG
@@ -1191,7 +1399,7 @@ Idle(void *arg)
#ifdef PS2_MENU
if ( TheMemoryCard.m_bWantToLoad )
- return;
+ goto popret;
#endif
tbStartTimer(0, "DoFade");
@@ -1210,8 +1418,13 @@ Idle(void *arg)
DoRWStuffEndOfFrame();
+ POP_MEMID(); // MEMID_RENDER
+
if(g_SlowMode)
ProcessSlowMode();
+ return;
+
+popret: POP_MEMID(); // MEMID_RENDER
}
void
@@ -1377,14 +1590,13 @@ TheModelViewer(void)
}
#endif
-#ifdef PS2
+
+#ifdef GTA_PS2
void TheGame(void)
{
printf("Into TheGame!!!\n");
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(1));
-#endif
+ PUSH_MEMID(MEMID_GAME); // NB: not popped
CTimer::Initialise();
@@ -1422,77 +1634,49 @@ void TheGame(void)
while (true)
{
-#ifdef PS2
- if (TheMemoryCard.m_bWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToLoad)
-#endif
+ if (WANT_TO_LOAD)
{
Const char *splash1 = GetLevelSplashScreen(CGame::currLevel);
LoadSplash(splash1);
}
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = false;
-#else
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
+ WANT_TO_LOAD = false;
CTimer::Update();
-#ifdef PS2
- while (!(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad))
-#else
- while (!(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad))
-#endif
+ while (!(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD))
{
CSprite2d::InitPerFrame();
CFont::InitPerFrame();
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(12));
-#endif
- CPointLights::NumLights = 0;
+ PUSH_MEMID(MEMID_GAME_PROCESS)
+ CPointLights::InitPerFrame();
CGame::Process();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
DMAudio.Service();
if (CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing())
{
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = false;
-#else
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
+ WANT_TO_LOAD = false;
FrontEndMenuManager.m_bWantToRestart = true;
break;
}
-#ifdef PS2
- if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
break;
SetLightsWithTimeOfDayColour(Scene.world);
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(15));
-#endif
+
+ PUSH_MEMID(MEMID_RENDER);
if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 )
{
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(11));
-#endif
+
+ PUSH_MEMID(MEMID_RENDERLIST);
CRenderer::ConstructRenderList();
CRenderer::PreRender();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
if (CWeather::LightningFlash && !CCullZones::CamNoRain())
DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255);
@@ -1528,15 +1712,9 @@ void TheGame(void)
RenderMenus();
-#ifdef PS2
- if (TheMemoryCard.m_bWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToLoad)
-#endif
+ if (WANT_TO_LOAD)
{
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID(); // MEMID_RENDER
break;
}
@@ -1553,9 +1731,7 @@ void TheGame(void)
CTimer::Update();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID(): // MEMID_RENDER
if (g_SlowMode)
ProcessSlowMode();
@@ -1567,24 +1743,12 @@ void TheGame(void)
CGame::ShutDownForRestart();
CTimer::Stop();
-#ifdef PS2
- if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
{
-#ifdef PS2
- if (TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FOUND_GAME_TO_LOAD)
{
FrontEndMenuManager.m_bWantToRestart = true;
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = true;
-#else
- FrontEndMenuManager.m_bWantToLoad = true;
-#endif
+ WANT_TO_LOAD = true;
}
CGame::InitialiseWhenRestarting();
@@ -1607,7 +1771,7 @@ void SystemInit()
mwInit();
#endif
-#ifdef GTA_PS2
+#ifdef USE_CUSTOM_ALLOCATOR
InitMemoryMgr();
#endif
@@ -1637,7 +1801,7 @@ void SystemInit()
#ifdef GTA_PS2
CFileMgr::InitCd();
- Char modulepath[256];
+ char modulepath[256];
strcpy(modulepath, "cdrom0:\\");
strcat(modulepath, "SYSTEM\\");
@@ -1724,7 +1888,7 @@ void SystemInit()
//
#endif
-#ifdef PS2
+#ifdef GTA_PS2
TheMemoryCard.Init();
#endif
}
@@ -1753,7 +1917,7 @@ void GameInit()
#endif
CdStreamInit(MAX_CDCHANNELS);
-#ifdef PS2
+#ifdef GTA_PS2
Initialise3D(); //no params
#else
//TODO
@@ -1860,21 +2024,18 @@ void GameInit()
CreateDebugFont();
#ifdef GTA_PS2
- AddIntcHandler(_TODOCONST(2), VBlankCounter, 0);
+ AddIntcHandler(INTC_VBLANK_S, VBlankCounter, 0);
#endif
CameraSize(Scene.camera, NULL, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
CSprite2d::SetRecipNearClip();
CTxdStore::Initialise();
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(9));
-#endif
+
+ PUSH_MEMID(MEMID_TEXTURES);
CFont::Initialise();
CHud::Initialise();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
ValidateVersion();
@@ -1902,11 +2063,10 @@ main(int argc, char *argv[])
SystemInit();
-#ifdef PS2
+#ifdef GTA_PS2
int32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE);
- if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT
- && r != CMemoryCard::ERR_OPENNOENTRY && r != CMemoryCard::ERR_NONE )
+ if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT )
{
GameInit();
@@ -1916,6 +2076,8 @@ main(int argc, char *argv[])
CFont::Initialise();
FrontEndMenuManager.DrawMemoryCardStartUpMenus();
+ }else if(r == CMemoryCard::ERR_OPENNOENTRY || r == CMemoryCard::ERR_NONE){
+ // eh?
}
#endif
@@ -1926,12 +2088,18 @@ main(int argc, char *argv[])
InitMPEGPlayer();
+#ifdef GTA_PAL
PlayMPEG("cdrom0:\\MOVIES\\DMAPAL.PSS;1", false);
if (CGame::frenchGame || CGame::germanGame)
PlayMPEG("cdrom0:\\MOVIES\\INTROPAF.PSS;1", true);
else
PlayMPEG("cdrom0:\\MOVIES\\INTROPAL.PSS;1", true);
+#else
+ PlayMPEG("cdrom0:\\MOVIES\\DMANTSC.PSS;1", false);
+
+ PlayMPEG("cdrom0:\\MOVIES\\INTRNTSC.PSS;1", true);
+#endif
ShutdownMPEGPlayer();
diff --git a/src/core/main.h b/src/core/main.h
index 13fff447..77fac46a 100644
--- a/src/core/main.h
+++ b/src/core/main.h
@@ -20,6 +20,10 @@ extern bool gbShowTimebars;
#define gbShowTimebars false
#endif
+#ifndef FINAL
+extern bool gbPrintMemoryUsage;
+#endif
+
class CSprite2d;
bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index a06762f5..5974175a 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -1,7 +1,6 @@
#include <csignal>
#define WITHWINDOWS
#include "common.h"
-#include "platform.h"
#include "crossplatform.h"
#include "Renderer.h"
#include "Credits.h"
@@ -16,7 +15,6 @@
#include "Boat.h"
#include "Heli.h"
#include "Automobile.h"
-#include "Ped.h"
#include "Console.h"
#include "Debug.h"
#include "Hud.h"
@@ -26,12 +24,12 @@
#include "Radar.h"
#include "debugmenu.h"
#include "Frontend.h"
-#include "Text.h"
#include "WaterLevel.h"
#include "main.h"
-#include "MBlur.h"
+#include "Script.h"
#include "postfx.h"
#include "custompipes.h"
+#include "MemoryHeap.h"
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
#include "FileMgr.h"
@@ -76,388 +74,61 @@ mysrand(unsigned int seed)
#ifdef CUSTOM_FRONTEND_OPTIONS
#include "frontendoption.h"
-#include "Font.h"
-void ReloadFrontendOptions(void)
+void
+CustomFrontendOptionsPopulate(void)
{
- CustomFrontendOptionsPopulate();
-}
-
-void RestoreDefGraphics(int8 action) {
- if (action != FEOPTION_ACTION_SELECT)
- return;
-
- #ifdef PS2_ALPHA_TEST
- gPS2alphaTest = false;
- #endif
- #ifdef MULTISAMPLING
- FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0;
- #endif
- #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
- CMenuManager::m_PrefsFrameLimiter = true;
- CMenuManager::m_PrefsVsyncDisp = true;
- CMenuManager::m_PrefsVsync = true;
- CMenuManager::m_PrefsUseWideScreen = false;
- FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode;
- #ifdef GTA3_1_1_PATCH
- if (_dwOperatingSystemVersion == OS_WIN98) {
- CMBlur::BlurOn = false;
- CMBlur::MotionBlurClose();
- } else {
- CMBlur::BlurOn = true;
- CMBlur::MotionBlurOpen(Scene.camera);
- }
- #else
- CMBlur::BlurOn = true;
- #endif
- FrontEndMenuManager.SaveSettings();
- #endif
-}
-
-void RestoreDefDisplay(int8 action) {
- if (action != FEOPTION_ACTION_SELECT)
- return;
-
- #ifdef CUTSCENE_BORDERS_SWITCH
- CMenuManager::m_PrefsCutsceneBorders = true;
- #endif
- #ifdef FREE_CAM
- TheCamera.bFreeCam = false;
- #endif
- #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
- CMenuManager::m_PrefsBrightness = 256;
- CMenuManager::m_PrefsLOD = 1.2f;
- CRenderer::ms_lodDistScale = 1.2f;
- CMenuManager::m_PrefsShowSubtitles = true;
- FrontEndMenuManager.SaveSettings();
- #endif
-}
-
-#ifdef MULTISAMPLING
-void MultiSamplingGoBack() {
- FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
-}
-
-void MultiSamplingButtonPress(int8 action) {
- if (action == FEOPTION_ACTION_SELECT) {
- if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
- FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel;
- _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode);
- FrontEndMenuManager.SetHelperText(0);
- FrontEndMenuManager.SaveSettings();
- }
- } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) {
- if (FrontEndMenuManager.m_bGameNotLoaded) {
- FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1);
-
- int i = 0;
- int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();
- while (maxAA != 1) {
- i++;
- maxAA >>= 1;
- }
-
- if (FrontEndMenuManager.m_nDisplayMSAALevel < 0)
- FrontEndMenuManager.m_nDisplayMSAALevel = i;
- else if (FrontEndMenuManager.m_nDisplayMSAALevel > i)
- FrontEndMenuManager.m_nDisplayMSAALevel = 0;
- }
- } else if (action == FEOPTION_ACTION_FOCUSLOSS) {
- if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
- FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
- FrontEndMenuManager.SetHelperText(3);
- }
- }
-}
-
-wchar* MultiSamplingDraw(bool *disabled, bool userHovering) {
- static wchar unicodeTemp[64];
- if (userHovering) {
- if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) {
- if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply
- FrontEndMenuManager.ResetHelperText();
- } else {
- FrontEndMenuManager.SetHelperText(1);
- }
- } else {
- if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
- FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
- }
- }
-
- if (!FrontEndMenuManager.m_bGameNotLoaded)
- *disabled = true;
-
- switch (FrontEndMenuManager.m_nDisplayMSAALevel) {
- case 0:
- return TheText.Get("FEM_OFF");
- default:
- sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel));
- AsciiToUnicode(gString, unicodeTemp);
- return unicodeTemp;
- }
+ // Moved to an array in MenuScreensCustom.cpp, but APIs are still available. see frontendoption.h
}
-const char* multisamplingKey = "MultiSampling";
#endif
-#ifdef MORE_LANGUAGES
-void LangPolSelect(int8 action)
-{
- if (action == FEOPTION_ACTION_SELECT) {
- FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH;
- FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
- FrontEndMenuManager.InitialiseChangedLanguageSettings();
- FrontEndMenuManager.SaveSettings();
- }
-}
-
-void LangRusSelect(int8 action)
-{
- if (action == FEOPTION_ACTION_SELECT) {
- FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN;
- FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
- FrontEndMenuManager.InitialiseChangedLanguageSettings();
- FrontEndMenuManager.SaveSettings();
- }
-}
+#ifdef LOAD_INI_SETTINGS
+#include "ini_parser.hpp"
-void LangJapSelect(int8 action)
+linb::ini cfg;
+int CheckAndReadIniInt(const char *cat, const char *key, int original)
{
- if (action == FEOPTION_ACTION_SELECT) {
- FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE;
- FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
- FrontEndMenuManager.InitialiseChangedLanguageSettings();
- FrontEndMenuManager.SaveSettings();
- }
-}
-#endif
+ std::string strval = cfg.get(cat, key, "");
+ const char *value = strval.c_str();
+ if (value && value[0] != '\0')
+ return atoi(value);
-#ifdef IMPROVED_VIDEOMODE
-void ScreenModeChange(int8 displayedValue)
-{
- if (displayedValue != FrontEndMenuManager.m_nPrefsWindowed) {
- FrontEndMenuManager.m_nPrefsWindowed = displayedValue;
- _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution
- FrontEndMenuManager.SetHelperText(0);
- FrontEndMenuManager.SaveSettings();
- }
+ return original;
}
-#endif
-#ifdef FREE_CAM
-void FreeCamChange(int8 displayedValue)
+float CheckAndReadIniFloat(const char *cat, const char *key, float original)
{
- TheCamera.bFreeCam = !!displayedValue;
- FrontEndMenuManager.SaveSettings();
-}
-const char* freeCamKey = "FreeCam";
-#endif
+ std::string strval = cfg.get(cat, key, "");
+ const char *value = strval.c_str();
+ if (value && value[0] != '\0')
+ return atof(value);
-#ifdef CUTSCENE_BORDERS_SWITCH
-void BorderModeChange(int8 displayedValue)
-{
- CMenuManager::m_PrefsCutsceneBorders = !!displayedValue;
- FrontEndMenuManager.SaveSettings();
+ return original;
}
-const char* cutsceneBordersKey = "CutsceneBorders";
-#endif
-#ifdef PS2_ALPHA_TEST
-void PS2AlphaTestChange(int8 displayedValue)
+void CheckAndSaveIniInt(const char *cat, const char *key, int val, bool &changed)
{
- gPS2alphaTest = !!displayedValue;
- FrontEndMenuManager.SaveSettings();
-}
-const char* ps2alphaKey = "PS2AlphaTest";
-#endif
-
-#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
-wchar selectedJoystickUnicode[128];
-
-wchar* DetectJoystickDraw(bool* disabled, bool userHovering) {
- int numButtons;
- int found = -1;
- const char *joyname;
- if (userHovering) {
- for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
- if ((joyname = glfwGetJoystickName(i))) {
- const uint8* buttons = glfwGetJoystickButtons(i, &numButtons);
- for (int j = 0; j < numButtons; j++) {
- if (buttons[j]) {
- found = i;
- break;
- }
- }
- if (found != -1)
- break;
- }
- }
-
- if (found != -1 && PSGLOBAL(joy1id) != found) {
- if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)
- PSGLOBAL(joy2id) = PSGLOBAL(joy1id);
- else
- PSGLOBAL(joy2id) = -1;
-
- strcpy(gSelectedJoystickName, joyname);
- PSGLOBAL(joy1id) = found;
- }
+ char temp[10];
+ if (atoi(cfg.get(cat, key, "xxx").c_str()) != val) { // if .ini doesn't have our key, compare with xxx and forcefully add it
+ changed = true;
+ sprintf(temp, "%u", val);
+ cfg.set(cat, key, temp);
}
- if (PSGLOBAL(joy1id) == -1)
- AsciiToUnicode("Not found", selectedJoystickUnicode);
- else
- AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);
-
- return selectedJoystickUnicode;
}
-#endif
-// Important: Make sure to read the warnings/informations in frontendoption.h!!
-// If you will hardcode any text, please use AllocUnicode! wchar_t size differs between platforms
-void
-CustomFrontendOptionsPopulate(void)
+void CheckAndSaveIniFloat(const char *cat, const char *key, float val, bool &changed)
{
- RemoveCustomFrontendOptions(); // if exist
-
- // -- Graphics/display seperation preperation starts - don't add options in here!
-#ifdef GRAPHICS_MENU_OPTIONS
- int graphicsMenu = FrontendScreenAdd("FET_GRA", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20,
- FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true);
-
- int newDisplayMenu = FrontendScreenAdd("FET_DIS", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20,
- FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true);
-
- FrontendOptionSetCursor(MENUPAGE_OPTIONS, 2, true);
- FrontendOptionAddRedirect(TheText.Get("FET_DIS"), newDisplayMenu, 0);
- FrontendOptionSetCursor(MENUPAGE_OPTIONS, 3);
- FrontendOptionAddRedirect(TheText.Get("FET_GRA"), graphicsMenu, 0);
-
-#define SWITCH_TO_GRAPHICS_MENU FrontendOptionSetCursor(graphicsMenu, -1);
-#define SWITCH_TO_DISPLAY_MENU FrontendOptionSetCursor(newDisplayMenu, -1);
-#define CLONE_OPTION(a, b, c, d) FrontendOptionAddBuiltinAction(a, b, c, d);
-#define ADD_BACK FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
-#define ADD_RESTORE_DEFAULTS(a) FrontendOptionAddDynamic(TheText.Get("FET_DEF"), nil, nil, a, nil);
-#else
- int advancedDisplayMenu = FrontendScreenAdd("FET_ADV", MENUSPRITE_MAINMENU, MENUPAGE_DISPLAY_SETTINGS, 50, 0, 20,
- FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true);
- bool movedToAdvMenu = false;
-
-#define SWITCH_TO_GRAPHICS_MENU \
- if (GetNumberOfMenuOptions(MENUPAGE_DISPLAY_SETTINGS) >= 12) { \
- FrontendOptionSetCursor(advancedDisplayMenu, -1); \
- movedToAdvMenu = true; \
- } else { \
- FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3); \
- }
-
-#define SWITCH_TO_DISPLAY_MENU SWITCH_TO_GRAPHICS_MENU
-#define CLONE_OPTION(a, b, c, d)
-#define ADD_BACK
-#define ADD_RESTORE_DEFAULTS(a)
-#endif
- // -- Graphics/display seperation preperation end
-
- const wchar* off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") };
-
-#ifdef MORE_LANGUAGES
- FrontendOptionSetCursor(MENUPAGE_LANGUAGE_SETTINGS, -2);
- FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, nil, LangPolSelect, nil);
- FrontendOptionAddDynamic(TheText.Get("FEL_RUS"), nil, nil, LangRusSelect, nil);
- FrontendOptionAddDynamic(TheText.Get("FEL_JAP"), nil, nil, LangJapSelect, nil);
-#endif
-
-#ifdef MENU_MAP
- FrontendOptionSetCursor(MENUPAGE_PAUSE_MENU, 2);
- FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP);
-#endif
-
- // -- Start of graphics menu - add options in display order!
-
- SWITCH_TO_GRAPHICS_MENU
- CLONE_OPTION(TheText.Get("FED_RES"), MENUACTION_SCREENRES, nil, nil);
- CLONE_OPTION(TheText.Get("FED_WIS"), MENUACTION_WIDESCREEN, nil, nil)
-
-#ifdef IMPROVED_VIDEOMODE
- const wchar* screenModes[] = { TheText.Get("FED_FLS"), TheText.Get("FED_WND") };
- // Storing isn't enabled because it's handled in Frontend
- FrontendOptionAddSelect(TheText.Get("FEM_SCF"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil);
-#endif
-
- CLONE_OPTION(TheText.Get("FEM_VSC"), MENUACTION_FRAMESYNC, nil, nil);
- CLONE_OPTION(TheText.Get("FEM_FRM"), MENUACTION_FRAMELIMIT, nil, nil);
-
-#ifdef MULTISAMPLING
- SWITCH_TO_GRAPHICS_MENU
- FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, multisamplingKey);
-#endif
-
- CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil);
-
-#ifdef PS2_ALPHA_TEST
- SWITCH_TO_GRAPHICS_MENU
- FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, ps2alphaKey);
-#endif
-
- ADD_RESTORE_DEFAULTS(RestoreDefGraphics)
- ADD_BACK
-
- // ---- End of Graphics Menu ----
-
- // -- Start of Display menu - add options in display order!
-
- SWITCH_TO_DISPLAY_MENU
- CLONE_OPTION(TheText.Get("FED_BRI"), MENUACTION_BRIGHTNESS, nil, nil);
- CLONE_OPTION(TheText.Get("FEM_LOD"), MENUACTION_DRAWDIST, nil, nil);
-
-#ifdef CUTSCENE_BORDERS_SWITCH
- SWITCH_TO_DISPLAY_MENU
- FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, cutsceneBordersKey);
-#endif
-
-#ifdef FREE_CAM
- SWITCH_TO_DISPLAY_MENU
- FrontendOptionAddSelect(TheText.Get("FEC_FRC"), off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey);
-#endif
-
- CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil);
-
- // Add link to advanced graphics menu if it's filled.
-#ifndef GRAPHICS_MENU_OPTIONS
- if (movedToAdvMenu) {
- FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3);
- FrontendOptionAddRedirect(TheText.Get("FET_ADV"), advancedDisplayMenu, 0);
-
- FrontendOptionSetCursor(advancedDisplayMenu, -1);
- FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
+ char temp[10];
+ if (atof(cfg.get(cat, key, "xxx").c_str()) != val) { // if .ini doesn't have our key, compare with xxx and forcefully add it
+ changed = true;
+ sprintf(temp, "%f", val);
+ cfg.set(cat, key, temp);
}
-#endif
-
- ADD_RESTORE_DEFAULTS(RestoreDefDisplay)
- ADD_BACK
-
-#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
- int detectJoystickMenu = FrontendScreenAdd("FEC_JOD", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 40, 60, 20,
- FONT_BANK, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, false);
-
- FrontendOptionSetCursor(detectJoystickMenu, 0);
-
- FrontendOptionAddBuiltinAction(TheText.Get("FEC_JPR"), MENUACTION_LABEL, nil, nil);
- FrontendOptionAddDynamic(TheText.Get("FEC_JDE"), DetectJoystickDraw, nil, nil, nil);
- FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
-
- FrontendOptionSetCursor(MENUPAGE_CONTROLLER_PC, 2);
- FrontendOptionAddRedirect(TheText.Get("FEC_JOD"), detectJoystickMenu, 1);
-#endif
}
-#endif
-#ifdef LOAD_INI_SETTINGS
-#include "ini_parser.hpp"
void LoadINISettings()
{
- linb::ini cfg;
cfg.load_file("re3.ini");
- char defaultStr[4];
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
// Written by assuming the codes below will run after _InputInitialiseJoys().
@@ -491,28 +162,38 @@ void LoadINISettings()
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- for (int i = 0; i < numCustomFrontendOptions; i++) {
- FrontendOption& option = customFrontendOptions[i];
- if (option.save) {
- // CFO only supports saving uint8 right now
- sprintf(defaultStr, "%u", *option.value);
- option.lastSavedValue = option.displayedValue = *option.value = atoi(cfg.get("FrontendOptions", option.save, defaultStr).c_str());
+ for (int i = 0; i < MENUPAGES; i++) {
+ for (int j = 0; j < NUM_MENUROWS; j++) {
+ CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j];
+ if (option.m_Action == MENUACTION_NOTHING)
+ break;
+
+ // CFO check
+ if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) {
+ // CFO only supports saving uint8 right now
+ *option.m_CFO->value = CheckAndReadIniInt("FrontendOptions", option.m_CFO->save, *option.m_CFO->value);
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue = *option.m_CFO->value;
+ }
+ }
}
}
#endif
-#ifdef NO_ISLAND_LOADING
- sprintf(defaultStr, "%u", CMenuManager::m_PrefsIslandLoading);
- CMenuManager::m_PrefsIslandLoading = atoi(cfg.get("FrontendOptions", "NoIslandLoading", defaultStr).c_str());
- CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading;
+#ifdef EXTENDED_COLOURFILTER
+ CPostFX::Intensity = CheckAndReadIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity);
+#endif
+#ifdef EXTENDED_PIPELINES
+ CustomPipes::VehicleShininess = CheckAndReadIniFloat("CustomPipesValues", "NeoVehicleShininess", CustomPipes::VehicleShininess);
+ CustomPipes::VehicleSpecularity = CheckAndReadIniFloat("CustomPipesValues", "NeoVehicleSpecularity", CustomPipes::VehicleSpecularity);
+ CustomPipes::RimlightMult = CheckAndReadIniFloat("CustomPipesValues", "RimlightMult", CustomPipes::RimlightMult);
+ CustomPipes::LightmapMult = CheckAndReadIniFloat("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult);
+ CustomPipes::GlossMult = CheckAndReadIniFloat("CustomPipesValues", "GlossMult", CustomPipes::GlossMult);
#endif
-
}
void SaveINISettings()
{
- linb::ini cfg;
- cfg.load_file("re3.ini");
bool changed = false;
char temp[4];
@@ -523,23 +204,29 @@ void SaveINISettings()
}
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- for (int i = 0; i < numCustomFrontendOptions; i++) {
- FrontendOption &option = customFrontendOptions[i];
- if (option.save) {
- if (atoi(cfg.get("FrontendOptions", option.save, "xxx").c_str()) != *option.value) { // if .ini doesn't have that key compare with xxx, so we can add it
- changed = true;
- sprintf(temp, "%u", *option.value);
- cfg.set("FrontendOptions", option.save, temp);
+ for (int i = 0; i < MENUPAGES; i++) {
+ for (int j = 0; j < NUM_MENUROWS; j++) {
+ CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j];
+ if (option.m_Action == MENUACTION_NOTHING)
+ break;
+
+ if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) {
+ // Beware: CFO only supports saving uint8 right now
+ CheckAndSaveIniInt("FrontendOptions", option.m_CFO->save, *option.m_CFO->value, changed);
}
}
}
#endif
-#ifdef NO_ISLAND_LOADING
- if (atoi(cfg.get("FrontendOptions", "NoIslandLoading", "xxx").c_str()) != CMenuManager::m_PrefsIslandLoading) {
- changed = true;
- sprintf(temp, "%u", CMenuManager::m_PrefsIslandLoading);
- cfg.set("FrontendOptions", "NoIslandLoading", temp);
- }
+
+#ifdef EXTENDED_COLOURFILTER
+ CheckAndSaveIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity, changed);
+#endif
+#ifdef EXTENDED_PIPELINES
+ CheckAndSaveIniFloat("CustomPipesValues", "NeoVehicleShininess", CustomPipes::VehicleShininess, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "NeoVehicleSpecularity", CustomPipes::VehicleSpecularity, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "RimlightMult", CustomPipes::RimlightMult, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "GlossMult", CustomPipes::GlossMult, changed);
#endif
if (changed)
@@ -688,6 +375,19 @@ ResetCamStatics(void)
TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;
}
+#ifdef MISSION_SWITCHER
+int8 nextMissionToSwitch = 0;
+static void
+SwitchToMission(void)
+{
+ CTheScripts::SwitchToMission(nextMissionToSwitch);
+}
+#endif
+
+#ifdef USE_CUSTOM_ALLOCATOR
+static void ParseHeap(void) { gMainHeap.ParseHeap(); }
+#endif
+
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",
@@ -870,8 +570,19 @@ DebugMenuPopulate(void)
DebugMenuAddVarBool8("Render", "Don't render Objects", &gbDontRenderObjects, nil);
DebugMenuAddVarBool8("Render", "Don't Render Water", &gbDontRenderWater, nil);
+#ifndef FINAL
+ DebugMenuAddVarBool8("Debug", "Print Memory Usage", &gbPrintMemoryUsage, nil);
+#ifdef USE_CUSTOM_ALLOCATOR
+ DebugMenuAddCmd("Debug", "Parse Heap", ParseHeap);
+#endif
+#endif
+ DebugMenuAddVarBool8("Debug", "Show cullzone debug stuff", &gbShowCullZoneDebugStuff, nil);
+ DebugMenuAddVarBool8("Debug", "Disable zone cull", &gbDisableZoneCull, nil);
+
DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil);
+#ifdef GTA_SCENE_EDIT
DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil);
+#endif
#ifdef MENU_MAP
DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint);
#endif
@@ -888,9 +599,6 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway);
DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil);
-#ifdef CUSTOM_FRONTEND_OPTIONS
- DebugMenuAddCmd("Debug", "Reload custom frontend options", ReloadFrontendOptions);
-#endif
DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil);
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop);
@@ -899,6 +607,29 @@ DebugMenuPopulate(void)
#ifdef TIMEBARS
DebugMenuAddVarBool8("Debug", "Show Timebars", &gbShowTimebars, nil);
#endif
+#ifdef MISSION_SWITCHER
+ DebugMenuEntry *missionEntry;
+ static const char* missions[] = {
+ "Intro Movie", "Hospital Info Scene", "Police Station Info Scene",
+ "RC Diablo Destruction", "RC Mafia Massacre", "RC Rumpo Rampage", "RC Casino Calamity",
+ "Patriot Playground", "A Ride In The Park", "Gripped!", "Multistorey Mayhem",
+ "Paramedic", "Firefighter", "Vigilante", "Taxi Driver",
+ "The Crook", "The Thieves", "The Wife", "Her Lover",
+ "Give Me Liberty and Luigi's Girls", "Don't Spank My Bitch Up", "Drive Misty For Me", "Pump-Action Pimp", "The Fuzz Ball",
+ "Mike Lips Last Lunch", "Farewell 'Chunky' Lee Chong", "Van Heist", "Cipriani's Chauffeur", "Dead Skunk In The Trunk", "The Getaway",
+ "Taking Out The Laundry", "The Pick-Up", "Salvatore's Called A Meeting", "Triads And Tribulations", "Blow Fish", "Chaperone", "Cutting The Grass",
+ "Bomb Da Base: Act I", "Bomb Da Base: Act II", "Last Requests", "Turismo", "I Scream, You Scream", "Trial By Fire", "Big'N'Veiny", "Sayonara Salvatore",
+ "Under Surveillance", "Paparazzi Purge", "Payday For Ray", "Two-Faced Tanner", "Kanbu Bust-Out", "Grand Theft Auto", "Deal Steal", "Shima", "Smack Down",
+ "Silence The Sneak", "Arms Shortage", "Evidence Dash", "Gone Fishing", "Plaster Blaster", "Marked Man",
+ "Liberator", "Waka-Gashira Wipeout!", "A Drop In The Ocean", "Bling-Bling Scramble", "Uzi Rider", "Gangcar Round-Up", "Kingdom Come",
+ "Grand Theft Aero", "Escort Service", "Decoy", "Love's Disappearance", "Bait", "Espresso-2-Go!", "S.A.M.",
+ "Uzi Money", "Toyminator", "Rigged To Blow", "Bullion Run", "Rumble", "The Exchange"
+ };
+
+ missionEntry = DebugMenuAddVar("Debug", "Select mission", &nextMissionToSwitch, nil, 1, 0, 79, missions);
+ DebugMenuEntrySetWrap(missionEntry, true);
+ DebugMenuAddCmd("Debug", "Start selected mission ", SwitchToMission);
+#endif
extern bool PrintDebugCode;
extern int16 DebugCamMode;
diff --git a/src/core/templates.h b/src/core/templates.h
index 4f7b8490..166f865c 100644
--- a/src/core/templates.h
+++ b/src/core/templates.h
@@ -46,8 +46,8 @@ class CPool
public:
CPool(int size){
// TODO: use new here
- m_entries = (U*)malloc(sizeof(U)*size);
- m_flags = (Flags*)malloc(sizeof(Flags)*size);
+ m_entries = (U*)new uint8[sizeof(U)*size];
+ m_flags = (Flags*)new uint8[sizeof(Flags)*size];
m_size = size;
m_allocPtr = 0;
for(int i = 0; i < size; i++){
@@ -61,8 +61,8 @@ public:
}
void Flush() {
if (m_size > 0) {
- free(m_entries);
- free(m_flags);
+ delete[] (uint8*)m_entries;
+ delete[] (uint8*)m_flags;
m_entries = nil;
m_flags = nil;
m_size = 0;
@@ -124,12 +124,18 @@ public:
(T*)&m_entries[handle >> 8] : nil;
}
int GetIndex(T *entry){
- int i = GetJustIndex(entry);
+ int i = GetJustIndex_NoFreeAssert(entry);
return m_flags[i].u + (i<<8);
}
int GetJustIndex(T *entry){
- // TODO: the cast is unsafe
- return (int)((U*)entry - m_entries);
+ int index = GetJustIndex_NoFreeAssert(entry);
+ assert(!IsFreeSlot(index));
+ return index;
+ }
+ int GetJustIndex_NoFreeAssert(T* entry){
+ int index = ((U*)entry - m_entries);
+ assert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required
+ return index;
}
int GetNoOfUsedSpaces(void) const{
int i;
@@ -141,8 +147,8 @@ public:
}
bool IsFreeSlot(int i) { return !!m_flags[i].free; }
void ClearStorage(uint8 *&flags, U *&entries){
- free(flags);
- free(entries);
+ delete[] (uint8*)flags;
+ delete[] (uint8*)entries;
flags = nil;
entries = nil;
}
@@ -156,8 +162,8 @@ public:
debug("CopyBack:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
}
void Store(uint8 *&flags, U *&entries){
- flags = (uint8*)malloc(sizeof(uint8)*m_size);
- entries = (U*)malloc(sizeof(U)*m_size);
+ flags = (uint8*)new uint8[sizeof(uint8)*m_size];
+ entries = (U*)new uint8[sizeof(U)*m_size];
memcpy(flags, m_flags, sizeof(uint8)*m_size);
memcpy(entries, m_entries, sizeof(U)*m_size);
debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 5e3204b2..476439fa 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -28,6 +28,7 @@
#include "Bones.h"
#include "Debug.h"
#include "Renderer.h"
+#include "MemoryHeap.h"
int gBuildings;
@@ -274,7 +275,11 @@ CEntity::CreateRwObject(void)
CBaseModelInfo *mi;
mi = CModelInfo::GetModelInfo(m_modelIndex);
+
+ PUSH_MEMID(MEMID_WORLD);
m_rwObject = mi->CreateInstance();
+ POP_MEMID();
+
if(m_rwObject){
if(IsBuilding())
gBuildings++;
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index a08e68f8..04cec96b 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -572,7 +572,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
if(IsGlass(B->GetModelIndex()))
CGlass::WindowRespondsToSoftCollision(B, impulseA);
if(!A->bInfiniteMass)
- A->ApplyMoveForce(colpoint.normal*(1.0f + A->m_fElasticity)*impulseA);
+ A->ApplyMoveForce(colpoint.GetNormal() * (1.0f + A->m_fElasticity) * impulseA);
return true;
}
}else if(!B->bInfiniteMass)
@@ -624,7 +624,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
}else{
if(IsGlass(B->GetModelIndex()))
CGlass::WindowRespondsToSoftCollision(B, impulseA);
- CVector f = colpoint.normal * impulseA;
+ CVector f = colpoint.GetNormal() * impulseA;
if(A->IsVehicle() && colpoint.normal.z < 0.7f)
f.z *= 0.3f;
if(!A->bInfiniteMass){
@@ -824,7 +824,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV
normalSpeed = DotProduct(speed, colpoint.normal);
if(normalSpeed < 0.0f){
float minspeed = 1.3f*GRAVITY * CTimer::GetTimeStep();
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
if ((IsObject() || IsVehicle() && (GetUp().z < -0.3f || ((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED))) &&
#else
if((IsObject() || IsVehicle() && GetUp().z < -0.3f) &&
@@ -1146,43 +1146,43 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
mostColliding = 0;
for(j = 1; j < numCollisions; j++)
- if(colpoints[j].depth > colpoints[mostColliding].depth)
+ if (colpoints[j].GetDepth() > colpoints[mostColliding].GetDepth())
mostColliding = j;
if(CWorld::bSecondShift)
for(j = 0; j < numCollisions; j++)
- shift += colpoints[j].normal * colpoints[j].depth * 1.5f/numCollisions;
+ shift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.5f / numCollisions;
else
for(j = 0; j < numCollisions; j++)
- shift += colpoints[j].normal * colpoints[j].depth * 1.2f/numCollisions;
+ shift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.2f / numCollisions;
if(A->IsVehicle() && B->IsVehicle()){
CVector dir = A->GetPosition() - B->GetPosition();
dir.Normalise();
if(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z)
dir.z = Min(0.0f, Min(A->GetForward().z, A->GetRight().z));
- shift += dir * colpoints[mostColliding].depth * 0.5f;
+ shift += dir * colpoints[mostColliding].GetDepth() * 0.5f;
}else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){
- CVector dir = colpoints[mostColliding].normal;
+ CVector dir = colpoints[mostColliding].GetNormal();
float f = Min(Abs(dir.z), 0.9f);
dir.z = 0.0f;
dir.Normalise();
- shift += dir * colpoints[mostColliding].depth / (1.0f - f);
+ shift += dir * colpoints[mostColliding].GetDepth() / (1.0f - f);
boat = B;
}else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){
- CVector dir = colpoints[mostColliding].normal * -1.0f;
+ CVector dir = colpoints[mostColliding].GetNormal() * -1.0f;
float f = Min(Abs(dir.z), 0.9f);
dir.z = 0.0f;
dir.Normalise();
- B->GetMatrix().Translate(dir * colpoints[mostColliding].depth / (1.0f - f));
+ B->GetMatrix().Translate(dir * colpoints[mostColliding].GetDepth() / (1.0f - f));
// BUG? how can that ever happen? A is a Ped
if(B->IsVehicle())
B->ProcessEntityCollision(A, colpoints);
}else{
if(CWorld::bSecondShift)
- shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.4f;
+ shift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.4f;
else
- shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.2f;
+ shift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.2f;
}
doShift = true;
diff --git a/src/extras/custompipes.cpp b/src/extras/custompipes.cpp
index 8c2b6916..bb3ebd2e 100644
--- a/src/extras/custompipes.cpp
+++ b/src/extras/custompipes.cpp
@@ -44,7 +44,7 @@ CustomMatCopy(void *dst, void *src, int32, int32)
-static rw::TexDictionary *neoTxd;
+rw::TexDictionary *neoTxd;
bool bRenderingEnvMap;
int32 EnvMapSize = 128;
diff --git a/src/extras/custompipes.h b/src/extras/custompipes.h
index 6e9c6517..ca3f0fb4 100644
--- a/src/extras/custompipes.h
+++ b/src/extras/custompipes.h
@@ -6,6 +6,7 @@
namespace CustomPipes {
+extern rw::TexDictionary *neoTxd;
struct CustomMatExt
{
diff --git a/src/extras/custompipes_d3d9.cpp b/src/extras/custompipes_d3d9.cpp
index 93973fec..b39efd47 100644
--- a/src/extras/custompipes_d3d9.cpp
+++ b/src/extras/custompipes_d3d9.cpp
@@ -131,6 +131,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
drawInst(header, inst);
inst++;
}
+ d3d::setTexture(1, nil);
SetRenderState(SRCBLEND, BLENDSRCALPHA);
}
diff --git a/src/extras/custompipes_gl.cpp b/src/extras/custompipes_gl.cpp
index 01663df5..861a831e 100644
--- a/src/extras/custompipes_gl.cpp
+++ b/src/extras/custompipes_gl.cpp
@@ -134,6 +134,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
}
SetRenderState(SRCBLEND, BLENDSRCALPHA);
+ setTexture(1, nil);
#ifndef RW_GL_USE_VAOS
disableAttribPointers(header->attribDesc, header->numAttribs);
@@ -158,13 +159,8 @@ CreateVehiclePipe(void)
{
-#ifdef RW_GLES2
-#include "gl2_shaders/neoVehicle_fs_gl2.inc"
-#include "gl2_shaders/neoVehicle_vs_gl2.inc"
-#else
-#include "shaders/neoVehicle_fs_gl3.inc"
-#include "shaders/neoVehicle_vs_gl3.inc"
-#endif
+#include "shaders/neoVehicle_fs_gl.inc"
+#include "shaders/neoVehicle_vs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoVehicle_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, neoVehicle_frag_src, nil };
neoVehicleShader = Shader::create(vs, fs);
@@ -256,6 +252,7 @@ worldRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
drawInst(header, inst);
inst++;
}
+ setTexture(1, nil);
#ifndef RW_GL_USE_VAOS
disableAttribPointers(header->attribDesc, header->numAttribs);
#endif
@@ -273,13 +270,8 @@ CreateWorldPipe(void)
ReadTweakValueTable((char*)work_buff, WorldLightmapBlend);
{
-#ifdef RW_GLES2
-#include "gl2_shaders/neoWorldIII_fs_gl2.inc"
-#include "gl2_shaders/default_UV2_gl2.inc"
-#else
-#include "shaders/neoWorldIII_fs_gl3.inc"
-#include "shaders/default_UV2_gl3.inc"
-#endif
+#include "shaders/neoWorldIII_fs_gl.inc"
+#include "shaders/default_UV2_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, default_UV2_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, neoWorldIII_frag_src, nil };
neoWorldShader = Shader::create(vs, fs);
@@ -381,13 +373,8 @@ CreateGlossPipe(void)
using namespace rw::gl3;
{
-#ifdef RW_GLES2
-#include "gl2_shaders/neoGloss_fs_gl2.inc"
-#include "gl2_shaders/neoGloss_vs_gl2.inc"
-#else
-#include "shaders/neoGloss_fs_gl3.inc"
-#include "shaders/neoGloss_vs_gl3.inc"
-#endif
+#include "shaders/neoGloss_fs_gl.inc"
+#include "shaders/neoGloss_vs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoGloss_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, neoGloss_frag_src, nil };
neoGlossShader = Shader::create(vs, fs);
@@ -558,13 +545,8 @@ CreateRimLightPipes(void)
}
{
-#ifdef RW_GLES2
-#include "gl2_shaders/simple_fs_gl2.inc"
-#include "gl2_shaders/neoRimSkin_gl2.inc"
-#else
-#include "shaders/simple_fs_gl3.inc"
-#include "shaders/neoRimSkin_gl3.inc"
-#endif
+#include "shaders/simple_fs_gl.inc"
+#include "shaders/neoRimSkin_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoRimSkin_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
neoRimSkinShader = Shader::create(vs, fs);
@@ -572,13 +554,8 @@ CreateRimLightPipes(void)
}
{
-#ifdef RW_GLES2
-#include "gl2_shaders/simple_fs_gl2.inc"
-#include "gl2_shaders/neoRim_gl2.inc"
-#else
-#include "shaders/simple_fs_gl3.inc"
-#include "shaders/neoRim_gl3.inc"
-#endif
+#include "shaders/simple_fs_gl.inc"
+#include "shaders/neoRim_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoRim_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
neoRimShader = Shader::create(vs, fs);
diff --git a/src/extras/debugmenu.cpp b/src/extras/debugmenu.cpp
index 3a4c4175..533b97f5 100644
--- a/src/extras/debugmenu.cpp
+++ b/src/extras/debugmenu.cpp
@@ -5,7 +5,7 @@
#include "ControllerConfig.h"
#include "Timer.h"
#include "rtcharse.h"
-#include "inttypes.h"
+#include "re3_inttypes.h"
#include "debugmenu.h"
#include <new>
diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp
index 88a930a9..a3c4b9e3 100644
--- a/src/extras/frontendoption.cpp
+++ b/src/extras/frontendoption.cpp
@@ -1,19 +1,13 @@
#include "common.h"
#ifdef CUSTOM_FRONTEND_OPTIONS
-#include "frontendoption.h"
+#include "Frontend.h"
#include "Text.h"
-int numCustomFrontendOptions = 0;
-FrontendOption *customFrontendOptions;
+int lastOgScreen = MENUPAGES; // means no new pages
+int numCustomFrontendOptions = 0;
int numCustomFrontendScreens = 0;
-FrontendScreen* customFrontendScreens;
-
-int numFrontendOptionReplacements = 0;
-CMenuScreen::CMenuEntry* frontendOptionReplacements;
-
-int lastOgScreen = MENUPAGES; // means no new pages
int optionCursor = -2;
int currentMenu;
@@ -32,8 +26,7 @@ void GoBack(bool fadeIn)
{
int screen = !FrontEndMenuManager.m_bGameNotLoaded ?
aScreens[FrontEndMenuManager.m_nCurrScreen].m_PreviousPage[1] : aScreens[FrontEndMenuManager.m_nCurrScreen].m_PreviousPage[0];
- int option = !FrontEndMenuManager.m_bGameNotLoaded ?
- aScreens[FrontEndMenuManager.m_nCurrScreen].m_ParentEntry[1] : aScreens[FrontEndMenuManager.m_nCurrScreen].m_ParentEntry[0];
+ int option = FrontEndMenuManager.GetPreviousPageOption();
FrontEndMenuManager.ThingsToDoBeforeGoingBack();
@@ -58,7 +51,7 @@ GetLastMenuScreen()
{
int8 page = -1;
for (int i = 0; i < MENUPAGES; i++) {
- if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].unk == 0)
+ if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].m_PreviousPage[0] == MENUPAGE_NONE)
break;
++page;
@@ -66,89 +59,23 @@ GetLastMenuScreen()
return page;
}
-// Used before populating options, but effective in InitialiseChangedLanguageSettings and debugmenu
-void
-RemoveCustomFrontendOptions()
-{
- if (numCustomFrontendOptions != 0) {
-
- for (int i = 0; i < MENUPAGES; i++) {
- for (int j = 0; j < NUM_MENUROWS; j++) {
- if (aScreens[i].m_aEntries[j].m_SaveSlot == SAVESLOT_CFO) {
- int ogOptionId = customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].ogOptionId;
-
- if (customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].type == FEOPTION_SELECT)
- free(customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].rightTexts);
-
- if (ogOptionId == -1) {
- int k;
- for (k = j; k < NUM_MENUROWS - 1; k++) {
- memcpy(&aScreens[i].m_aEntries[k], &aScreens[i].m_aEntries[k + 1], sizeof(CMenuScreen::CMenuEntry));
- }
- aScreens[i].m_aEntries[k].m_Action = MENUACTION_NOTHING;
- aScreens[i].m_aEntries[k].m_SaveSlot = SAVESLOT_NONE;
- aScreens[i].m_aEntries[k].m_EntryName[0] = '\0';
- j--;
- } else {
- memcpy(&aScreens[i].m_aEntries[j], &frontendOptionReplacements[ogOptionId], sizeof(CMenuScreen::CMenuEntry));
- }
- }
- }
- }
- free(customFrontendOptions);
- numCustomFrontendOptions = 0;
-
- if (numFrontendOptionReplacements != 0) {
- free(frontendOptionReplacements);
- numFrontendOptionReplacements = 0;
- }
- }
-
- if (numCustomFrontendScreens == 0)
- return;
-
- for (int i = 0; i < MENUPAGES; i++) {
- if (i > lastOgScreen) {
- aScreens[i].m_ScreenName[0] = '\0';
- aScreens[i].unk = 0;
- }
- }
- free(customFrontendScreens);
- numCustomFrontendScreens = 0;
- lastOgScreen = MENUPAGES;
-}
-
-int8 RegisterNewScreen(const char *name, int prevPage)
+int8 RegisterNewScreen(const char *name, int prevPage, ReturnPrevPageFunc returnPrevPageFunc)
{
if (lastOgScreen == MENUPAGES)
lastOgScreen = GetLastMenuScreen();
numCustomFrontendScreens++;
- if (numCustomFrontendScreens == 1)
- customFrontendScreens = (FrontendScreen*)malloc(5 * sizeof(FrontendScreen));
- else if (numCustomFrontendScreens % 5 == 1)
- customFrontendScreens = (FrontendScreen*)realloc(customFrontendScreens, (numCustomFrontendScreens + 4) * sizeof(FrontendScreen));
-
- assert(customFrontendScreens != nil && "Custom frontend screens can't be allocated");
-
int id = lastOgScreen + numCustomFrontendScreens;
assert(id < MENUPAGES && "No room for new custom frontend screens! Increase MENUPAGES");
strncpy(aScreens[id].m_ScreenName, name, 8);
aScreens[id].m_PreviousPage[0] = aScreens[id].m_PreviousPage[1] = prevPage;
- aScreens[id].unk = 1;
+ aScreens[id].returnPrevPageFunc = returnPrevPageFunc;
return id;
}
int8 RegisterNewOption()
{
numCustomFrontendOptions++;
- if (numCustomFrontendOptions == 1)
- customFrontendOptions = (FrontendOption*)malloc(5 * sizeof(FrontendOption));
- else if (numCustomFrontendOptions % 5 == 1)
- customFrontendOptions = (FrontendOption*)realloc(customFrontendOptions, (numCustomFrontendOptions + 4) * sizeof(FrontendOption));
-
- assert(customFrontendOptions != nil && "Custom frontend options can't be allocated");
-
uint8 numOptions = GetNumberOfMenuOptions(currentMenu);
uint8 curIdx;
if (optionCursor < 0) {
@@ -159,30 +86,11 @@ int8 RegisterNewOption()
if (!optionOverwrite) {
if (aScreens[currentMenu].m_aEntries[curIdx].m_Action != MENUACTION_NOTHING) {
for (int i = numOptions - 1; i >= curIdx; i--) {
- memcpy(&aScreens[currentMenu].m_aEntries[i + 1], &aScreens[currentMenu].m_aEntries[i], sizeof(CMenuScreen::CMenuEntry));
+ memcpy(&aScreens[currentMenu].m_aEntries[i + 1], &aScreens[currentMenu].m_aEntries[i], sizeof(CMenuScreenCustom::CMenuEntry));
}
}
}
optionCursor++;
-
- if (optionOverwrite) {
- numFrontendOptionReplacements++;
- if (numFrontendOptionReplacements == 1)
- frontendOptionReplacements = (CMenuScreen::CMenuEntry*)malloc(5 * sizeof(CMenuScreen::CMenuEntry));
- else if (numFrontendOptionReplacements % 5 == 1)
- frontendOptionReplacements = (CMenuScreen::CMenuEntry*)realloc(frontendOptionReplacements, (numFrontendOptionReplacements + 4) * sizeof(CMenuScreen::CMenuEntry));
-
- memcpy(&frontendOptionReplacements[numFrontendOptionReplacements - 1], &aScreens[currentMenu].m_aEntries[curIdx], sizeof(CMenuScreen::CMenuEntry));
- customFrontendOptions[numCustomFrontendOptions - 1].ogOptionId = numFrontendOptionReplacements - 1;
- } else {
- customFrontendOptions[numCustomFrontendOptions - 1].ogOptionId = -1;
- }
- customFrontendOptions[numCustomFrontendOptions - 1].screen = currentMenu;
-
- aScreens[currentMenu].m_aEntries[curIdx].m_Action = MENUACTION_TRIGGERFUNC;
- aScreens[currentMenu].m_aEntries[curIdx].m_SaveSlot = SAVESLOT_CFO;
- aScreens[currentMenu].m_aEntries[curIdx].m_TargetMenu = numCustomFrontendOptions - 1;
- aScreens[currentMenu].m_aEntries[curIdx].m_EntryName[0] = 1; // just something to fool it
return curIdx;
}
@@ -193,110 +101,78 @@ void FrontendOptionSetCursor(int screen, int8 option, bool overwrite)
optionOverwrite = overwrite;
}
-void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc) {
+void FrontendOptionAddBuiltinAction(const char* gxtKey, int action, int targetMenu, int saveSlot) {
int8 screenOptionOrder = RegisterNewOption();
- FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1];
+ CMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder];
- // To fool the Frontend, we will still display the text passed via first param.
+ // We can't use custom text on those :shrug:
switch (action) {
case MENUACTION_SCREENRES:
- strcpy(aScreens[currentMenu].m_aEntries[screenOptionOrder].m_EntryName, "FED_RES");
+ strcpy(option.m_EntryName, "FED_RES");
break;
case MENUACTION_AUDIOHW:
- strcpy(aScreens[currentMenu].m_aEntries[screenOptionOrder].m_EntryName, "FEA_3DH");
+ strcpy(option.m_EntryName, "FEA_3DH");
+ break;
+ default:
+ strncpy(option.m_EntryName, gxtKey, 8);
break;
}
- aScreens[currentMenu].m_aEntries[screenOptionOrder].m_Action = action;
- option.type = FEOPTION_BUILTIN_ACTION;
- option.buttonPressFunc = buttonPressFunc;
- TextCopy(option.leftText, leftText);
- option.screenOptionOrder = screenOptionOrder;
- option.returnPrevPageFunc = returnPrevPageFunc;
- option.save = nil;
-}
-
-void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName)
-{
- int8 screenOptionOrder = RegisterNewOption();
-
- FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1];
- option.type = FEOPTION_SELECT;
- TextCopy(option.leftText, leftText);
- option.rightTexts = (wchar**)malloc(numRightTexts * sizeof(wchar*));
- memcpy(option.rightTexts, rightTexts, numRightTexts * sizeof(wchar*));
- option.numRightTexts = numRightTexts;
- option.value = var;
- option.displayedValue = *var;
- option.lastSavedValue = *var;
- option.save = saveName;
- option.onlyApplyOnEnter = onlyApplyOnEnter;
- option.changeFunc = changeFunc;
- option.screenOptionOrder = screenOptionOrder;
- option.returnPrevPageFunc = returnPrevPageFunc;
+ option.m_Action = action;
+ option.m_SaveSlot = saveSlot;
+ option.m_TargetMenu = targetMenu;
}
-void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName)
-{
+void FrontendOptionAddSelect(const char* gxtKey, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName)
+{
int8 screenOptionOrder = RegisterNewOption();
- FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1];
- option.type = FEOPTION_DYNAMIC;
- option.drawFunc = drawFunc;
- option.buttonPressFunc = buttonPressFunc;
- TextCopy(option.leftText, leftText);
- option.value = var;
- option.save = saveName;
- option.screenOptionOrder = screenOptionOrder;
- option.returnPrevPageFunc = returnPrevPageFunc;
-}
-
-void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption, bool fadeIn)
-{
- int8 screenOptionOrder = RegisterNewOption();
-
- FrontendOption &option = customFrontendOptions[numCustomFrontendOptions - 1];
- option.type = FEOPTION_REDIRECT;
- option.to = to;
- option.option = selectedOption;
- option.fadeIn = fadeIn;
- TextCopy(option.leftText, text);
- option.screenOptionOrder = screenOptionOrder;
- option.returnPrevPageFunc = nil;
- option.save = nil;
+ CMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder];
+ option.m_Action = MENUACTION_CFO_SELECT;
+ strncpy(option.m_EntryName, gxtKey, 8);
+ option.m_CFOSelect = new CCFOSelect();
+ option.m_CFOSelect->rightTexts = (char**)malloc(numRightTexts * sizeof(char*));
+ memcpy(option.m_CFOSelect->rightTexts, rightTexts, numRightTexts * sizeof(char*));
+ option.m_CFOSelect->numRightTexts = numRightTexts;
+ option.m_CFOSelect->value = var;
+ if (var) {
+ option.m_CFOSelect->displayedValue = *var;
+ option.m_CFOSelect->lastSavedValue = *var;
+ }
+ option.m_CFOSelect->save = saveName;
+ option.m_CFOSelect->onlyApplyOnEnter = onlyApplyOnEnter;
+ option.m_CFOSelect->changeFunc = changeFunc;
}
-void FrontendOptionAddBackButton(const wchar* text, bool fadeIn)
+void FrontendOptionAddDynamic(const char* gxtKey, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName)
{
int8 screenOptionOrder = RegisterNewOption();
- FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1];
- option.type = FEOPTION_GOBACK;
- option.fadeIn = fadeIn;
- TextCopy(option.leftText, text);
- option.screenOptionOrder = screenOptionOrder;
- option.returnPrevPageFunc = nil;
- option.save = nil;
+ CMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder];
+ option.m_Action = MENUACTION_CFO_DYNAMIC;
+ strncpy(option.m_EntryName, gxtKey, 8);
+ option.m_CFODynamic = new CCFODynamic();
+ option.m_CFODynamic->drawFunc = drawFunc;
+ option.m_CFODynamic->buttonPressFunc = buttonPressFunc;
+ option.m_CFODynamic->value = var;
+ option.m_CFODynamic->save = saveName;
}
uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight,
int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc) {
- uint8 screenOrder = RegisterNewScreen(gxtKey, prevPage);
-
- FrontendScreen &screen = customFrontendScreens[numCustomFrontendScreens - 1];
- screen.id = screenOrder;
- screen.sprite = sprite;
- screen.prevPage = prevPage;
- strncpy(screen.name, gxtKey, 8);
- screen.columnWidth = columnWidth;
- screen.headerHeight = headerHeight;
- screen.lineHeight = lineHeight;
- screen.font = font;
- screen.fontScaleX = fontScaleX;
- screen.fontScaleY = fontScaleY;
- screen.alignment = alignment;
- screen.returnPrevPageFunc = returnPrevPageFunc;
+ uint8 screenOrder = RegisterNewScreen(gxtKey, prevPage, returnPrevPageFunc);
+
+ CCustomScreenLayout *screen = new CCustomScreenLayout();
+ aScreens[screenOrder].layout = screen;
+ screen->sprite = sprite;
+ screen->columnWidth = columnWidth;
+ screen->headerHeight = headerHeight;
+ screen->lineHeight = lineHeight;
+ screen->font = font;
+ screen->fontScaleX = fontScaleX;
+ screen->fontScaleY = fontScaleY;
+ screen->alignment = alignment;
return screenOrder;
}
diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h
index dac6be62..19340b20 100644
--- a/src/extras/frontendoption.h
+++ b/src/extras/frontendoption.h
@@ -2,47 +2,23 @@
#include "common.h"
#ifdef CUSTOM_FRONTEND_OPTIONS
-#include "Frontend.h"
-
-// Warning:
-// All of the code relies on that you won't use more then NUM_MENUROWS(18) options on one page.
-// Also congrats if you can make 18 options visible at once.
-
-// About texts:
-// All text parameters accept wchar(including hardcoded wchar* and TheText.Get)
-// except FrontendScreenAdd(it's char[8] GXT key by the design of Frontend).
-// All texts reload if custom options reloaded too, which includes language changes and via live reload feature in debug menu!
-
-// Execute direction:
-// All of the calls below eventually manipulate the aScreens array, so keep in mind to add/replace options in order,
-// i.e. don't set cursor to 8 first and then 3.
-
-// Live reload:
-// You can add/change/undo the new options in-game if you use VS. Change what you want, build the changed bits via "Edit and Continue",
-// and hit the "Reload custom frontend options" from debug menu. Or call CustomFrontendOptionsPopulate() from somewhere else.
+// ! There are 2 ways to use CFO,
+// 1st; by adding a new option to the array in MenuScreensCustom.cpp and passing attributes/CBs to it
+// 2nd; by calling the functions listed at the bottom of this file.
// -- Option types
//
// Static/select: You allocate the variable, pass it to function and game sets it from user input among the strings given to function,
-// then you can handle ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately)
-// and ReturnPrevPageFunc optionally. You can store the option in an INI file if you pass the key(as a char array) to corresponding parameter.
+// optionally you can add post-change event via ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately)
+// You can store the option in an INI file if you pass the key(as a char array) to corresponding parameter.
//
// Dynamic: Passing variable to function is only needed if you want to store it, otherwise you should do
// all the operations with ButtonPressFunc, this includes allocating the variable.
// Left-side text is passed while creating and static, but ofc right-side text is dynamic -
-// you should return it in DrawFunc, which is called on every draw. ReturnPrevPageFunc is also here if needed.
-//
-// Redirect: Redirection to another screen. selectedOption parameter is the highlighted option user will see after the redirection.
+// you should return it in DrawFunc, which is called on every draw.
//
// Built-in action: As the name suggests, any action that game has built-in. But as an extra you can set the option text,
-// and can be informed on button press/focus loss via buttonPressFunc. ReturnPrevPageFunc is also here.
-
-#define FEOPTION_SELECT 0
-#define FEOPTION_DYNAMIC 1
-#define FEOPTION_REDIRECT 2
-#define FEOPTION_GOBACK 3
-#define FEOPTION_BUILTIN_ACTION 4
// -- Returned via ButtonPressFunc() action param.
#define FEOPTION_ACTION_LEFT 0
@@ -61,7 +37,7 @@
typedef void (*ReturnPrevPageFunc)();
// for static options
-typedef void (*ChangeFunc)(int8 displayedValue); // called before updating the value.
+typedef void (*ChangeFunc)(int8 before, int8 after); // called after updating the value.
// only called on enter if onlyApplyOnEnter set, otherwise called on every value change
// for dynamic options
@@ -69,71 +45,11 @@ typedef wchar* (*DrawFunc)(bool* disabled, bool userHovering); // you must retur
// you can also set *disabled if you want to gray it out.
typedef void (*ButtonPressFunc)(int8 action); // see FEOPTION_ACTIONs above
-struct FrontendScreen
-{
- int id;
- char name[8];
- eMenuSprites sprite;
- int prevPage;
- int columnWidth;
- int headerHeight;
- int lineHeight;
- int8 font;
- float fontScaleX;
- float fontScaleY;
- int8 alignment;
- bool showLeftRightHelper;
- ReturnPrevPageFunc returnPrevPageFunc;
-};
-
-struct FrontendOption
-{
- int8 type;
- int8 screenOptionOrder;
- int32 screen;
- wchar leftText[128];
- ReturnPrevPageFunc returnPrevPageFunc;
- int8* value;
- int8 displayedValue; // only if onlyApplyOnEnter enabled for now
- const char* save;
- int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor
-
- union {
- // Only for dynamic / built-in action
- struct {
- DrawFunc drawFunc;
- ButtonPressFunc buttonPressFunc;
- };
-
- // Only for static/select
- struct {
- wchar** rightTexts;
- int8 numRightTexts;
- bool onlyApplyOnEnter;
- ChangeFunc changeFunc;
- int8 lastSavedValue; // only if onlyApplyOnEnter enabled
- };
-
- // Only for redirect
- struct {
- int to;
- int8 option;
- bool fadeIn;
- };
- };
-};
-
// -- Internal things
-void RemoveCustomFrontendOptions();
void CustomFrontendOptionsPopulate();
-
extern int lastOgScreen; // for reloading
-
extern int numCustomFrontendOptions;
-extern FrontendOption* customFrontendOptions;
-
extern int numCustomFrontendScreens;
-extern FrontendScreen* customFrontendScreens;
// -- To be used in ButtonPressFunc / ChangeFunc(this one would be weird):
void ChangeScreen(int screen, int option = 0, bool fadeIn = true);
@@ -141,6 +57,21 @@ void GoBack(bool fadeIn = true);
uint8 GetNumberOfMenuOptions(int screen);
+// !!! We're now moved to MenuScreensCustom.cpp, which houses an array that keeps all original+custom options.
+// But you can still use the APIs below, and manipulate aScreens while in game.
+
+// Limits:
+// The code relies on that you won't use more then NUM_MENUROWS(18) options on one page, and won't exceed the MENUPAGES of pages.
+// Also congrats if you can make 18 options visible at once.
+
+// Texts:
+// All text parameters accept char[8] GXT key.
+
+// Execute direction:
+// All of the calls below eventually manipulate the aScreens array, so keep in mind to add/replace options in order,
+// i.e. don't set cursor to 8 first and then 3.
+
+
// -- Placing the cursor to append/overwrite option
//
// Done via FrontendOptionSetCursor(screen, position, overwrite = false), parameters explained below:
@@ -152,11 +83,9 @@ uint8 GetNumberOfMenuOptions(int screen);
void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false);
// var is optional in AddDynamic, enables you to save them in an INI file(also needs passing char array to saveName param. obv), otherwise pass nil/0
-void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc);
-void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil);
-void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil);
-void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true);
-void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true);
+void FrontendOptionAddBuiltinAction(const char* gxtKey, int action, int targetMenu = MENUPAGE_NONE, int saveSlot = SAVESLOT_NONE);
+void FrontendOptionAddSelect(const char* gxtKey, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName = nil);
+void FrontendOptionAddDynamic(const char* gxtKey, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName = nil);
uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc = nil);
#endif
diff --git a/src/extras/postfx.cpp b/src/extras/postfx.cpp
index 6355dfb1..d3b8b8ac 100644
--- a/src/extras/postfx.cpp
+++ b/src/extras/postfx.cpp
@@ -150,13 +150,8 @@ CPostFX::Open(RwCamera *cam)
#ifdef RW_OPENGL
using namespace rw::gl3;
{
-#ifdef RW_GLES2
-#include "gl2_shaders/im2d_gl2.inc"
-#include "gl2_shaders/colourfilterIII_fs_gl2.inc"
-#else
-#include "shaders/im2d_gl3.inc"
-#include "shaders/colourfilterIII_fs_gl3.inc"
-#endif
+#include "shaders/im2d_gl.inc"
+#include "shaders/colourfilterIII_fs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, colourfilterIII_frag_src, nil };
colourFilterIII = Shader::create(vs, fs);
@@ -164,17 +159,12 @@ CPostFX::Open(RwCamera *cam)
}
{
-#ifdef RW_GLES2
-#include "gl2_shaders/im2d_gl2.inc"
-#include "gl2_shaders/contrast_fs_gl2.inc"
-#else
-#include "shaders/im2d_gl3.inc"
-#include "shaders/contrast_fs_gl3.inc"
+#include "shaders/im2d_gl.inc"
+#include "shaders/contrast_fs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil };
contrast = Shader::create(vs, fs);
assert(contrast);
-#endif
}
#endif
@@ -374,6 +364,14 @@ CPostFX::NeedFrontBuffer(int32 type)
}
void
+CPostFX::GetBackBuffer(RwCamera *cam)
+{
+ RwRasterPushContext(pBackBuffer);
+ RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
+ RwRasterPopContext();
+}
+
+void
CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)
{
switch(type)
@@ -415,11 +413,8 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu
assert(pFrontBuffer);
assert(pBackBuffer);
- if(NeedBackBuffer()){
- RwRasterPushContext(pBackBuffer);
- RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
- RwRasterPopContext();
- }
+ if(NeedBackBuffer())
+ GetBackBuffer(cam);
DefinedState();
diff --git a/src/extras/postfx.h b/src/extras/postfx.h
index 658c2d88..f8779a6d 100644
--- a/src/extras/postfx.h
+++ b/src/extras/postfx.h
@@ -29,6 +29,7 @@ public:
static void Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha);
static bool NeedBackBuffer(void);
static bool NeedFrontBuffer(int32 type);
+ static void GetBackBuffer(RwCamera *cam);
static bool UseBlurColours(void) { return EffectSwitch != POSTFX_SIMPLE; }
};
diff --git a/src/extras/inttypes.h b/src/extras/re3_inttypes.h
index bf0c53e2..bf0c53e2 100644
--- a/src/extras/inttypes.h
+++ b/src/extras/re3_inttypes.h
diff --git a/src/extras/screendroplets.cpp b/src/extras/screendroplets.cpp
new file mode 100644
index 00000000..2d34cdcb
--- /dev/null
+++ b/src/extras/screendroplets.cpp
@@ -0,0 +1,791 @@
+#define WITH_D3D
+#include "common.h"
+
+#ifdef SCREEN_DROPLETS
+
+#ifndef LIBRW
+#error "Need librw for SCREEN_DROPLETS"
+#endif
+
+#include "General.h"
+#include "Main.h"
+#include "RwHelper.h"
+#include "Main.h"
+#include "Timer.h"
+#include "Camera.h"
+#include "ZoneCull.h"
+#include "Weather.h"
+#include "ParticleObject.h"
+ #include "Pad.h"
+#include "RenderBuffer.h"
+#include "custompipes.h"
+#include "postfx.h"
+#include "screendroplets.h"
+
+// for 640
+#define MAXSIZE 15
+#define MINSIZE 4
+
+int ScreenDroplets::ms_initialised;
+RwTexture *ScreenDroplets::ms_maskTex;
+RwTexture *ScreenDroplets::ms_screenTex;
+
+bool ScreenDroplets::ms_enabled = true;
+bool ScreenDroplets::ms_movingEnabled = true;
+
+ScreenDroplets::ScreenDrop ScreenDroplets::ms_drops[ScreenDroplets::MAXDROPS];
+int ScreenDroplets::ms_numDrops;
+ScreenDroplets::ScreenDropMoving ScreenDroplets::ms_dropsMoving[ScreenDroplets::MAXDROPSMOVING];
+int ScreenDroplets::ms_numDropsMoving;
+
+CVector ScreenDroplets::ms_prevCamUp;
+CVector ScreenDroplets::ms_prevCamPos;
+CVector ScreenDroplets::ms_camMoveDelta;
+float ScreenDroplets::ms_camMoveDist;
+CVector ScreenDroplets::ms_screenMoveDelta;
+float ScreenDroplets::ms_screenMoveDist;
+float ScreenDroplets::ms_camUpAngle;
+
+int ScreenDroplets::ms_splashDuration;
+CParticleObject *ScreenDroplets::ms_splashObject;
+
+struct Im2DVertexUV2 : rw::RWDEVICE::Im2DVertex
+{
+ rw::float32 u2, v2;
+};
+
+#ifdef RW_D3D9
+static void *screenDroplet_PS;
+#endif
+#ifdef RW_GL3
+static rw::gl3::Shader *screenDroplet;
+#endif
+
+// platform specific
+static void openim2d_uv2(void);
+static void closeim2d_uv2(void);
+static void RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices);
+
+static Im2DVertexUV2 VertexBuffer[TEMPBUFFERVERTSIZE];
+
+void
+ScreenDroplets::Initialise(void)
+{
+ Clear();
+ ms_splashDuration = -1;
+ ms_splashObject = nil;
+}
+
+void
+ScreenDroplets::InitDraw(void)
+{
+ if(CustomPipes::neoTxd)
+ ms_maskTex = CustomPipes::neoTxd->find("dropmask");
+
+ ms_screenTex = RwTextureCreate(nil);
+ RwTextureSetFilterMode(ms_screenTex, rwFILTERLINEAR);
+
+ openim2d_uv2();
+#ifdef RW_D3D9
+#include "shaders/screenDroplet_PS.inc"
+ screenDroplet_PS = rw::d3d::createPixelShader(screenDroplet_PS_cso);
+#endif
+#ifdef RW_GL3
+ using namespace rw::gl3;
+ {
+#include "shaders/im2d_UV2_gl.inc"
+#include "shaders/screenDroplet_fs_gl.inc"
+ const char *vs[] = { shaderDecl, header_vert_src, im2d_UV2_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, screenDroplet_frag_src, nil };
+ screenDroplet = Shader::create(vs, fs);
+ assert(screenDroplet);
+ }
+#endif
+
+ ms_initialised = 1;
+}
+
+void
+ScreenDroplets::Shutdown(void)
+{
+ if(ms_maskTex){
+ RwTextureDestroy(ms_maskTex);
+ ms_maskTex = nil;
+ }
+ if(ms_screenTex){
+ RwTextureSetRaster(ms_screenTex, nil);
+ RwTextureDestroy(ms_screenTex);
+ ms_screenTex = nil;
+ }
+#ifdef RW_D3D9
+ if(screenDroplet_PS){
+ rw::d3d::destroyPixelShader(screenDroplet_PS);
+ screenDroplet_PS = nil;
+ }
+#endif
+#ifdef RW_GL3
+ if(screenDroplet){
+ screenDroplet->destroy();
+ screenDroplet = nil;
+ }
+#endif
+
+ closeim2d_uv2();
+}
+
+void
+ScreenDroplets::Process(void)
+{
+ ProcessCameraMovement();
+ SprayDrops();
+ ProcessMoving();
+ Fade();
+}
+
+static void
+FlushBuffer(void)
+{
+ if(TempBufferIndicesStored){
+ RenderIndexedPrimitive_UV2(rwPRIMTYPETRILIST,
+ VertexBuffer, TempBufferVerticesStored,
+ TempBufferRenderIndexList, TempBufferIndicesStored);
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+ }
+}
+
+static int
+StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, Im2DVertexUV2 **vertexStart)
+{
+ if(TempBufferIndicesStored + numIndices >= TEMPBUFFERINDEXSIZE ||
+ TempBufferVerticesStored + numVertices >= TEMPBUFFERVERTSIZE)
+ FlushBuffer();
+ *indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored];
+ *vertexStart = &VertexBuffer[TempBufferVerticesStored];
+ int vertOffset = TempBufferVerticesStored;
+ TempBufferIndicesStored += numIndices;
+ TempBufferVerticesStored += numVertices;
+ return vertOffset;
+}
+
+void
+ScreenDroplets::Render(void)
+{
+ ScreenDrop *drop;
+
+ DefinedState();
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(ms_maskTex));
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+
+ RwTextureSetRaster(ms_screenTex, CPostFX::pBackBuffer);
+#ifdef RW_D3D9
+ rw::d3d::im2dOverridePS = screenDroplet_PS;
+ rw::d3d::setTexture(1, ms_screenTex);
+#endif
+#ifdef RW_GL3
+ rw::gl3::im2dOverrideShader = screenDroplet;
+ rw::gl3::setTexture(1, ms_screenTex);
+#endif
+
+ RenderBuffer::ClearRenderBuffer();
+ for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)
+ if(drop->active)
+ AddToRenderList(drop);
+ FlushBuffer();
+
+#ifdef RW_D3D9
+ rw::d3d::im2dOverridePS = nil;
+ rw::d3d::setTexture(1, nil);
+#endif
+#ifdef RW_GL3
+ rw::gl3::im2dOverrideShader = nil;
+ rw::gl3::setTexture(1, nil);
+#endif
+
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE);
+}
+
+void
+ScreenDroplets::AddToRenderList(ScreenDroplets::ScreenDrop *drop)
+{
+ static float xy[] = {
+ -1.0f, -1.0f,
+ -1.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, -1.0f
+ };
+ static float uv[] = {
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f
+ };
+
+ int i;
+ RwImVertexIndex *indices;
+ Im2DVertexUV2 *verts;
+ int first = StartStoring(6, 4, &indices, &verts);
+
+ float scale = 0.5f*SCREEN_SCALE_X(drop->size);
+
+ float screenz = RwIm2DGetNearScreenZ();
+ float z = RwCameraGetNearClipPlane(Scene.camera);
+ float recipz = 1.0f/z;
+
+ float magSize = SCREEN_SCALE_Y(drop->magnification*(300.0f-40.0f) + 40.0f);
+ float ul = drop->x - magSize;
+ float vt = drop->y - magSize;
+ float ur = drop->x + magSize;
+ float vb = drop->y + magSize;
+ ul = Max(ul, 0.0f)/RwRasterGetWidth(CPostFX::pBackBuffer);
+ vt = Max(vt, 0.0f)/RwRasterGetHeight(CPostFX::pBackBuffer);
+ ur = Min(ur, SCREEN_WIDTH)/RwRasterGetWidth(CPostFX::pBackBuffer);
+ vb = Min(vb, SCREEN_HEIGHT)/RwRasterGetHeight(CPostFX::pBackBuffer);
+
+ for(i = 0; i < 4; i++){
+ RwIm2DVertexSetScreenX(&verts[i], drop->x + xy[i*2]*scale);
+ RwIm2DVertexSetScreenY(&verts[i], drop->y + xy[i*2+1]*scale);
+ RwIm2DVertexSetScreenZ(&verts[i], screenz);
+ RwIm2DVertexSetCameraZ(&verts[i], z);
+ RwIm2DVertexSetRecipCameraZ(&verts[i], recipz);
+ RwIm2DVertexSetIntRGBA(&verts[i], drop->color.r, drop->color.g, drop->color.b, drop->color.a);
+ RwIm2DVertexSetU(&verts[i], uv[i*2], recipz);
+ RwIm2DVertexSetV(&verts[i], uv[i*2+1], recipz);
+
+ verts[i].u2 = i < 2 ? ul : ur;
+ verts[i].v2 = i % 3 ? vt : vb;
+ }
+ indices[0] = first + 0;
+ indices[1] = first + 1;
+ indices[2] = first + 2;
+ indices[3] = first + 2;
+ indices[4] = first + 3;
+ indices[5] = first + 0;
+}
+
+void
+ScreenDroplets::Clear(void)
+{
+ ScreenDrop *drop;
+ for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)
+ drop->active = false;
+ ms_numDrops = 0;
+}
+
+ScreenDroplets::ScreenDrop*
+ScreenDroplets::NewDrop(float x, float y, float size, float lifetime, bool fades, int r, int g, int b)
+{
+ ScreenDrop *drop;
+ int i;
+
+ for(i = 0, drop = ms_drops; i < MAXDROPS; i++, drop++)
+ if(!ms_drops[i].active)
+ goto found;
+ return nil;
+found:
+ ms_numDrops++;
+ drop->x = x;
+ drop->y = y;
+ drop->size = size;
+ drop->magnification = (MAXSIZE - size + 1.0f) / (MAXSIZE - MINSIZE + 1.0f);
+ drop->fades = fades;
+ drop->active = true;
+ drop->color.r = r;
+ drop->color.g = g;
+ drop->color.b = b;
+ drop->color.a = 255;
+ drop->time = 0.0f;
+ drop->lifetime = lifetime;
+ return drop;
+}
+
+void
+ScreenDroplets::SetMoving(ScreenDroplets::ScreenDrop *drop)
+{
+ ScreenDropMoving *moving;
+ for(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++)
+ if(moving->drop == nil)
+ goto found;
+ return;
+found:
+ ms_numDropsMoving++;
+ moving->drop = drop;
+ moving->dist = 0.0f;
+}
+
+void
+ScreenDroplets::FillScreen(int n)
+{
+ float x, y, size;
+ ScreenDrop *drop;
+
+ if(!ms_initialised)
+ return;
+ ms_numDrops = 0;
+ for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++){
+ drop->active = false;
+ if(drop < &ms_drops[n]){
+ x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;
+ y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;
+ size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);
+ NewDrop(x, y, size, 2000.0f, true);
+ }
+ }
+}
+
+void
+ScreenDroplets::FillScreenMoving(float amount, bool isBlood)
+{
+ int n = (ms_screenMoveDelta.z > 5.0f ? 1.5f : 1.0f)*amount*20.0f;
+ float x, y, size;
+ ScreenDrop *drop;
+
+ while(n--)
+ if(ms_numDrops < MAXDROPS && ms_numDropsMoving < MAXDROPSMOVING){
+ x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;
+ y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;
+ size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);
+ drop = nil;
+ if(isBlood)
+ drop = NewDrop(x, y, size, 2000.0f, true, 255, 0, 0);
+ else
+ drop = NewDrop(x, y, size, 2000.0f, true);
+ if(drop)
+ SetMoving(drop);
+ }
+}
+
+void
+ScreenDroplets::RegisterSplash(CParticleObject *pobj)
+{
+ CVector dist = pobj->GetPosition() - ms_prevCamPos;
+ if(dist.MagnitudeSqr() < 20.0f){
+ ms_splashDuration = 14;
+ ms_splashObject = pobj;
+ }
+}
+
+void
+ScreenDroplets::ProcessCameraMovement(void)
+{
+ RwMatrix *camMat = RwFrameGetMatrix(RwCameraGetFrame(Scene.camera));
+ CVector camPos = camMat->pos;
+ CVector camUp = camMat->at;
+ ms_camMoveDelta = camPos - ms_prevCamPos;
+ ms_camMoveDist = ms_camMoveDelta.Magnitude();
+
+ ms_prevCamUp = camUp;
+ ms_prevCamPos = camPos;
+
+ ms_screenMoveDelta.x = -RwV3dDotProduct(&camMat->right, (RwV3d*)&ms_camMoveDelta);
+ ms_screenMoveDelta.y = RwV3dDotProduct(&camMat->up, (RwV3d*)&ms_camMoveDelta);
+ ms_screenMoveDelta.z = RwV3dDotProduct(&camMat->at, (RwV3d*)&ms_camMoveDelta);
+ ms_screenMoveDelta *= 10.0f;
+ ms_screenMoveDist = ms_screenMoveDelta.Magnitude2D();
+
+ uint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
+ bool isTopDown = mode == CCam::MODE_TOPDOWN || mode == CCam::MODE_GTACLASSIC || mode == CCam::MODE_TOP_DOWN_PED;
+ bool isLookingInDirection = CPad::GetPad(0)->GetLookBehindForCar() || CPad::GetPad(0)->GetLookLeft() || CPad::GetPad(0)->GetLookRight();
+ ms_enabled = !isTopDown && !isLookingInDirection;
+ ms_movingEnabled = !isTopDown && !isLookingInDirection;
+
+ // 0 when looking stright up, 180 when looking up or down
+ ms_camUpAngle = RADTODEG(Acos(clamp(camUp.z, -1.0f, 1.0f)));
+}
+
+void
+ScreenDroplets::SprayDrops(void)
+{
+ bool noRain = CCullZones::PlayerNoRain() || CCullZones::CamNoRain();
+ if(!noRain && CWeather::Rain > 0.0f && ms_enabled){
+ // 180 when looking stright up, 0 when looking up or down
+ float angle = 180.0f - ms_camUpAngle;
+ angle = Max(angle, 40.0f); // want at least some rain
+ FillScreenMoving((angle - 40.0f) / 150.0f * CWeather::Rain * 0.5f);
+ }
+
+ int i;
+ for(i = 0; i < MAX_AUDIOHYDRANTS; i++){
+ CAudioHydrant *hyd = CAudioHydrant::Get(i);
+ if (hyd->pParticleObject){
+ CVector dist = hyd->pParticleObject->GetPosition() - ms_prevCamPos;
+ if(dist.MagnitudeSqr() > 40.0f ||
+ DotProduct(dist, ms_prevCamUp) < 0.0f) continue;
+
+ FillScreenMoving(1.0f);
+ }
+ }
+
+ static int ndrops[] = {
+ 125, 250, 500, 1000, 1000,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ if(ms_splashDuration >= 0){
+ if(ms_numDrops < MAXDROPS) {
+ float numDropMult = 1.0f;
+ if(ms_splashObject){
+ float dist = (ms_splashObject->GetPosition() - ms_prevCamPos).Magnitude();
+ numDropMult = 1.0f - (dist - 5.0f)/15.0f;
+ if(numDropMult < 0) numDropMult = 0.0f; // fix
+ }
+ int n = ndrops[ms_splashDuration] * numDropMult;
+ while(n--)
+ if(ms_numDrops < MAXDROPS){
+ float x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;
+ float y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;
+ float size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);
+ NewDrop(x, y, size, 10000.0f, false);
+ }
+ }
+ ms_splashDuration--;
+ }
+}
+
+void
+ScreenDroplets::NewTrace(ScreenDroplets::ScreenDropMoving *moving)
+{
+ if(ms_numDrops < MAXDROPS){
+ moving->dist = 0.0f;
+ NewDrop(moving->drop->x, moving->drop->y, MINSIZE, 500.0f, true,
+ moving->drop->color.r, moving->drop->color.g, moving->drop->color.b);
+ }
+}
+
+void
+ScreenDroplets::MoveDrop(ScreenDroplets::ScreenDropMoving *moving)
+{
+ ScreenDrop *drop = moving->drop;
+ if(!ms_movingEnabled)
+ return;
+ if(!drop->active){
+ moving->drop = nil;
+ ms_numDropsMoving--;
+ return;
+ }
+ if(ms_screenMoveDelta.z > 0.0f && ms_camMoveDist > 0.3f){
+ if(ms_screenMoveDist > 0.5f && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){
+ // movement when camera turns
+ moving->dist += ms_screenMoveDist;
+ if(moving->dist > 20.0f && drop->color.a > 100)
+ NewTrace(moving);
+
+ drop->x -= ms_screenMoveDelta.x;
+ drop->y += ms_screenMoveDelta.y;
+ }else{
+ // movement out of center
+ float d = ms_screenMoveDelta.z*0.2f;
+ float dx, dy, sum;
+ dx = drop->x - SCREEN_WIDTH*0.5f + ms_screenMoveDelta.x;
+ if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON)
+ dy = drop->y - SCREEN_HEIGHT*1.2f - ms_screenMoveDelta.y;
+ else
+ dy = drop->y - SCREEN_HEIGHT*0.5f - ms_screenMoveDelta.y;
+ sum = fabs(dx) + fabs(dy);
+ if(sum > 0.001f){
+ dx /= sum;
+ dy /= sum;
+ }
+ moving->dist += d;
+ if(moving->dist > 20.0f && drop->color.a > 100)
+ NewTrace(moving);
+ drop->x += dx * d;
+ drop->y += dy * d;
+ }
+
+ if(drop->x < 0.0f || drop->y < 0.0f ||
+ drop->x > SCREEN_WIDTH || drop->y > SCREEN_HEIGHT){
+ moving->drop = nil;
+ ms_numDropsMoving--;
+ }
+ }
+}
+
+void
+ScreenDroplets::ProcessMoving(void)
+{
+ ScreenDropMoving *moving;
+ if(!ms_movingEnabled)
+ return;
+ for(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++)
+ if(moving->drop)
+ MoveDrop(moving);
+}
+
+void
+ScreenDroplets::Fade(void)
+{
+ ScreenDrop *drop;
+ for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)
+ if(drop->active)
+ drop->Fade();
+}
+
+void
+ScreenDroplets::ScreenDrop::Fade(void)
+{
+ int delta = CTimer::GetTimeStepInMilliseconds();
+ time += delta;
+ if(time < lifetime){
+ color.a = 255 - time/lifetime*255;
+ }else if(fades){
+ ScreenDroplets::ms_numDrops--;
+ active = false;
+ }
+}
+
+
+/*
+ * Im2D with two uv coors
+ */
+
+#ifdef RW_D3D9
+// stolen from RW, not in a public header
+namespace rw {
+namespace d3d {
+void addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf); // NB: don't share this pointer
+void removeDynamicVB(IDirect3DVertexBuffer9 **buf);
+void addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf); // NB: don't share this pointer
+void removeDynamicIB(IDirect3DIndexBuffer9 **buf);
+}
+}
+// different than im2d
+#define NUMINDICES 1024
+#define NUMVERTICES 1024
+
+static int primTypeMap[] = {
+ D3DPT_POINTLIST, // invalid
+ D3DPT_LINELIST,
+ D3DPT_LINESTRIP,
+ D3DPT_TRIANGLELIST,
+ D3DPT_TRIANGLESTRIP,
+ D3DPT_TRIANGLEFAN,
+ D3DPT_POINTLIST, // actually not supported!
+};
+// end of stolen stuff
+
+
+static IDirect3DVertexDeclaration9 *im2ddecl_uv2;
+static IDirect3DVertexBuffer9 *im2dvertbuf_uv2;
+static IDirect3DIndexBuffer9 *im2dindbuf_uv2;
+
+void
+openim2d_uv2(void)
+{
+ using namespace rw;
+ using namespace d3d;
+ D3DVERTEXELEMENT9 elements[5] = {
+ { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
+ { 0, offsetof(Im2DVertexUV2, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
+ { 0, offsetof(Im2DVertexUV2, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
+ { 0, offsetof(Im2DVertexUV2, u2), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
+ D3DDECL_END()
+ };
+ assert(im2ddecl_uv2 == nil);
+ im2ddecl_uv2 = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);
+ assert(im2ddecl_uv2);
+
+ assert(im2dvertbuf_uv2 == nil);
+ im2dvertbuf_uv2 = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertexUV2), 0, true);
+ assert(im2dvertbuf_uv2);
+ addDynamicVB(NUMVERTICES*sizeof(Im2DVertexUV2), 0, &im2dvertbuf_uv2);
+
+ assert(im2dindbuf_uv2 == nil);
+ im2dindbuf_uv2 = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(rw::uint16), true);
+ assert(im2dindbuf_uv2);
+ addDynamicIB(NUMINDICES*sizeof(rw::uint16), &im2dindbuf_uv2);
+}
+
+void
+closeim2d_uv2(void)
+{
+ using namespace rw;
+ using namespace d3d;
+
+ d3d9::destroyVertexDeclaration(im2ddecl_uv2);
+ im2ddecl_uv2 = nil;
+
+ removeDynamicVB(&im2dvertbuf_uv2);
+ destroyVertexBuffer(im2dvertbuf_uv2);
+ im2dvertbuf_uv2 = nil;
+
+ removeDynamicIB(&im2dindbuf_uv2);
+ destroyIndexBuffer(im2dindbuf_uv2);
+ im2dindbuf_uv2 = nil;
+}
+
+void
+RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)
+{
+ using namespace rw;
+ using namespace d3d;
+
+ if(numVertices > NUMVERTICES ||
+ numIndices > NUMINDICES){
+ // TODO: error
+ return;
+ }
+ rw::uint16 *lockedindices = lockIndices(im2dindbuf_uv2, 0, numIndices*sizeof(rw::uint16), D3DLOCK_DISCARD);
+ memcpy(lockedindices, indices, numIndices*sizeof(rw::uint16));
+ unlockIndices(im2dindbuf_uv2);
+
+ rw::uint8 *lockedvertices = lockVertices(im2dvertbuf_uv2, 0, numVertices*sizeof(Im2DVertexUV2), D3DLOCK_DISCARD);
+ memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertexUV2));
+ unlockVertices(im2dvertbuf_uv2);
+
+ setStreamSource(0, im2dvertbuf_uv2, 0, sizeof(Im2DVertexUV2));
+ setIndices(im2dindbuf_uv2);
+ setVertexDeclaration(im2ddecl_uv2);
+
+ if(im2dOverridePS)
+ setPixelShader(im2dOverridePS);
+ else if(engine->device.getRenderState(TEXTURERASTER))
+ setPixelShader(im2d_tex_PS);
+ else
+ setPixelShader(im2d_PS);
+
+ d3d::flushCache();
+
+ rw::uint32 primCount = 0;
+ switch(primType){
+ case PRIMTYPELINELIST:
+ primCount = numIndices/2;
+ break;
+ case PRIMTYPEPOLYLINE:
+ primCount = numIndices-1;
+ break;
+ case PRIMTYPETRILIST:
+ primCount = numIndices/3;
+ break;
+ case PRIMTYPETRISTRIP:
+ primCount = numIndices-2;
+ break;
+ case PRIMTYPETRIFAN:
+ primCount = numIndices-2;
+ break;
+ case PRIMTYPEPOINTLIST:
+ primCount = numIndices;
+ break;
+ }
+ d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,
+ 0, numVertices,
+ 0, primCount);
+}
+#endif
+
+#ifdef RW_GL3
+// different than im2d
+#define NUMINDICES 1024
+#define NUMVERTICES 1024
+
+static rw::gl3::AttribDesc im2d_UV2_attribDesc[4] = {
+ { rw::gl3::ATTRIB_POS, GL_FLOAT, GL_FALSE, 4,
+ sizeof(Im2DVertexUV2), 0 },
+ { rw::gl3::ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
+ sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, r) },
+ { rw::gl3::ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
+ sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u) },
+ { rw::gl3::ATTRIB_TEXCOORDS1, GL_FLOAT, GL_FALSE, 2,
+ sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u2) }
+};
+
+static int primTypeMap[] = {
+ GL_POINTS, // invalid
+ GL_LINES,
+ GL_LINE_STRIP,
+ GL_TRIANGLES,
+ GL_TRIANGLE_STRIP,
+ GL_TRIANGLE_FAN,
+ GL_POINTS
+};
+
+static int32 u_xform;
+
+uint32 im2D_UV2_Vbo, im2D_UV2_Ibo;
+#ifdef RW_GL_USE_VAOS
+uint32 im2D_UV2_Vao;
+#endif
+
+void
+openim2d_uv2(void)
+{
+ u_xform = rw::gl3::registerUniform("u_xform"); // this doesn't add a new one, so it's safe
+
+ glGenBuffers(1, &im2D_UV2_Ibo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW);
+
+ glGenBuffers(1, &im2D_UV2_Vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo);
+ glBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW);
+
+#ifdef RW_GL_USE_VAOS
+ glGenVertexArrays(1, &im2D_UV2_Vao);
+ glBindVertexArray(im2D_UV2_Vao);
+ setAttribPointers(im2d_UV2_attribDesc, 4);
+#endif
+}
+
+void
+closeim2d_uv2(void)
+{
+ glDeleteBuffers(1, &im2D_UV2_Ibo);
+ glDeleteBuffers(1, &im2D_UV2_Vbo);
+#ifdef RW_GL_USE_VAOS
+ glDeleteVertexArrays(1, &im2D_UV2_Vao);
+#endif
+}
+
+void
+RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)
+{
+ using namespace rw;
+ using namespace gl3;
+
+ GLfloat xform[4];
+ Camera *cam;
+ cam = (Camera*)engine->currentCamera;
+
+#ifdef RW_GL_USE_VAOS
+ glBindVertexArray(im2D_UV2_Vao);
+#endif
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo);
+ glBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertexUV2), vertices);
+
+ xform[0] = 2.0f/cam->frameBuffer->width;
+ xform[1] = -2.0f/cam->frameBuffer->height;
+ xform[2] = -1.0f;
+ xform[3] = 1.0f;
+
+ if(im2dOverrideShader)
+ im2dOverrideShader->use();
+ else
+ assert(0);//im2dShader->use();
+#ifndef RW_GL_USE_VAOS
+ setAttribPointers(im2d_UV2_attribDesc, 4);
+#endif
+
+ glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);
+
+ flushCache();
+ glDrawElements(primTypeMap[primType], numIndices,
+ GL_UNSIGNED_SHORT, nil);
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(im2d_UV2_attribDesc, 4);
+#endif
+}
+#endif
+
+#endif
diff --git a/src/extras/screendroplets.h b/src/extras/screendroplets.h
new file mode 100644
index 00000000..090b1923
--- /dev/null
+++ b/src/extras/screendroplets.h
@@ -0,0 +1,78 @@
+#pragma once
+
+#ifdef SCREEN_DROPLETS
+
+class CParticleObject;
+
+class ScreenDroplets
+{
+public:
+ enum {
+ MAXDROPS = 2000,
+ MAXDROPSMOVING = 700
+ };
+
+ class ScreenDrop
+ {
+ public:
+ float x, y, time; // shorts on xbox (short float?)
+ float size, magnification, lifetime; // "
+ CRGBA color;
+ bool active;
+ bool fades;
+
+ void Fade(void);
+ };
+
+ struct ScreenDropMoving
+ {
+ ScreenDrop *drop;
+ float dist;
+ };
+
+ static int ms_initialised;
+ static RwTexture *ms_maskTex;
+ static RwTexture *ms_screenTex;
+
+ static bool ms_enabled;
+ static bool ms_movingEnabled;
+
+ static ScreenDrop ms_drops[MAXDROPS];
+ static int ms_numDrops;
+ static ScreenDropMoving ms_dropsMoving[MAXDROPSMOVING];
+ static int ms_numDropsMoving;
+
+ static CVector ms_prevCamUp;
+ static CVector ms_prevCamPos;
+ static CVector ms_camMoveDelta;
+ static float ms_camMoveDist;
+ static CVector ms_screenMoveDelta;
+ static float ms_screenMoveDist;
+ static float ms_camUpAngle;
+
+ static int ms_splashDuration;
+ static CParticleObject *ms_splashObject;
+
+ static void Initialise(void);
+ static void InitDraw(void);
+ static void Shutdown(void);
+ static void Process(void);
+ static void Render(void);
+ static void AddToRenderList(ScreenDrop *drop);
+
+ static void Clear(void);
+ static ScreenDrop *NewDrop(float x, float y, float size, float lifetime, bool fades, int r = 255, int g = 255, int b = 255);
+ static void SetMoving(ScreenDroplets::ScreenDrop *drop);
+ static void FillScreen(int n);
+ static void FillScreenMoving(float amount, bool isBlood = false);
+ static void RegisterSplash(CParticleObject *pobj);
+
+ static void ProcessCameraMovement(void);
+ static void SprayDrops(void);
+ static void NewTrace(ScreenDroplets::ScreenDropMoving *moving);
+ static void MoveDrop(ScreenDropMoving *moving);
+ static void ProcessMoving(void);
+ static void Fade(void);
+};
+
+#endif
diff --git a/src/extras/shaders/Makefile b/src/extras/shaders/Makefile
index 6cbbf237..51e009d6 100644
--- a/src/extras/shaders/Makefile
+++ b/src/extras/shaders/Makefile
@@ -1,68 +1,79 @@
-all: im2d_gl3.inc simple_fs_gl3.inc default_UV2_gl3.inc \
- colourfilterIII_fs_gl3.inc contrast_fs_gl3.inc \
- neoRim_gl3.inc neoRimSkin_gl3.inc \
- neoWorldIII_fs_gl3.inc neoGloss_vs_gl3.inc neoGloss_fs_gl3.inc \
- neoVehicle_vs_gl3.inc neoVehicle_fs_gl3.inc
+all: im2d_gl.inc simple_fs_gl.inc default_UV2_gl.inc \
+ colourfilterIII_fs_gl.inc contrast_fs_gl.inc \
+ neoRim_gl.inc neoRimSkin_gl.inc \
+ neoWorldIII_fs_gl.inc neoGloss_vs_gl.inc neoGloss_fs_gl.inc \
+ neoVehicle_vs_gl.inc neoVehicle_fs_gl.inc \
+ im2d_UV2_gl.inc screenDroplet_fs_gl.inc
-im2d_gl3.inc: im2d.vert
+im2d_gl.inc: im2d.vert
(echo 'const char *im2d_vert_src =';\
sed 's/..*/"&\\n"/' im2d.vert;\
- echo ';') >im2d_gl3.inc
+ echo ';') >im2d_gl.inc
-simple_fs_gl3.inc: simple.frag
+simple_fs_gl.inc: simple.frag
(echo 'const char *simple_frag_src =';\
sed 's/..*/"&\\n"/' simple.frag;\
- echo ';') >simple_fs_gl3.inc
+ echo ';') >simple_fs_gl.inc
-default_UV2_gl3.inc: default_UV2.vert
+default_UV2_gl.inc: default_UV2.vert
(echo 'const char *default_UV2_vert_src =';\
sed 's/..*/"&\\n"/' default_UV2.vert;\
- echo ';') >default_UV2_gl3.inc
+ echo ';') >default_UV2_gl.inc
-colourfilterIII_fs_gl3.inc: colourfilterIII.frag
+colourfilterIII_fs_gl.inc: colourfilterIII.frag
(echo 'const char *colourfilterIII_frag_src =';\
sed 's/..*/"&\\n"/' colourfilterIII.frag;\
- echo ';') >colourfilterIII_fs_gl3.inc
+ echo ';') >colourfilterIII_fs_gl.inc
-contrast_fs_gl3.inc: contrast.frag
+contrast_fs_gl.inc: contrast.frag
(echo 'const char *contrast_frag_src =';\
sed 's/..*/"&\\n"/' contrast.frag;\
- echo ';') >contrast_fs_gl3.inc
+ echo ';') >contrast_fs_gl.inc
-neoRim_gl3.inc: neoRim.vert
+neoRim_gl.inc: neoRim.vert
(echo 'const char *neoRim_vert_src =';\
sed 's/..*/"&\\n"/' neoRim.vert;\
- echo ';') >neoRim_gl3.inc
+ echo ';') >neoRim_gl.inc
-neoRimSkin_gl3.inc: neoRimSkin.vert
+neoRimSkin_gl.inc: neoRimSkin.vert
(echo 'const char *neoRimSkin_vert_src =';\
sed 's/..*/"&\\n"/' neoRimSkin.vert;\
- echo ';') >neoRimSkin_gl3.inc
+ echo ';') >neoRimSkin_gl.inc
-neoWorldIII_fs_gl3.inc: neoWorldIII.frag
+neoWorldIII_fs_gl.inc: neoWorldIII.frag
(echo 'const char *neoWorldIII_frag_src =';\
sed 's/..*/"&\\n"/' neoWorldIII.frag;\
- echo ';') >neoWorldIII_fs_gl3.inc
+ echo ';') >neoWorldIII_fs_gl.inc
-neoGloss_fs_gl3.inc: neoGloss.frag
+neoGloss_fs_gl.inc: neoGloss.frag
(echo 'const char *neoGloss_frag_src =';\
sed 's/..*/"&\\n"/' neoGloss.frag;\
- echo ';') >neoGloss_fs_gl3.inc
+ echo ';') >neoGloss_fs_gl.inc
-neoGloss_vs_gl3.inc: neoGloss.vert
+neoGloss_vs_gl.inc: neoGloss.vert
(echo 'const char *neoGloss_vert_src =';\
sed 's/..*/"&\\n"/' neoGloss.vert;\
- echo ';') >neoGloss_vs_gl3.inc
+ echo ';') >neoGloss_vs_gl.inc
-neoVehicle_vs_gl3.inc: neoVehicle.vert
+neoVehicle_vs_gl.inc: neoVehicle.vert
(echo 'const char *neoVehicle_vert_src =';\
sed 's/..*/"&\\n"/' neoVehicle.vert;\
- echo ';') >neoVehicle_vs_gl3.inc
+ echo ';') >neoVehicle_vs_gl.inc
-neoVehicle_fs_gl3.inc: neoVehicle.frag
+neoVehicle_fs_gl.inc: neoVehicle.frag
(echo 'const char *neoVehicle_frag_src =';\
sed 's/..*/"&\\n"/' neoVehicle.frag;\
- echo ';') >neoVehicle_fs_gl3.inc
+ echo ';') >neoVehicle_fs_gl.inc
+
+im2d_UV2_gl.inc: im2d_UV2.vert
+ (echo 'const char *im2d_UV2_vert_src =';\
+ sed 's/..*/"&\\n"/' im2d_UV2.vert;\
+ echo ';') >im2d_UV2_gl.inc
+
+screenDroplet_fs_gl.inc: screenDroplet.frag
+ (echo 'const char *screenDroplet_frag_src =';\
+ sed 's/..*/"&\\n"/' screenDroplet.frag;\
+ echo ';') >screenDroplet_fs_gl.inc
diff --git a/src/extras/shaders/colourfilterIII.frag b/src/extras/shaders/colourfilterIII.frag
index 4c9a8400..b41cb94a 100644
--- a/src/extras/shaders/colourfilterIII.frag
+++ b/src/extras/shaders/colourfilterIII.frag
@@ -1,11 +1,9 @@
uniform sampler2D tex0;
uniform vec4 u_blurcolor;
-in vec4 v_color;
-in vec2 v_tex0;
-in float v_fog;
-
-out vec4 color;
+FSIN vec4 v_color;
+FSIN vec2 v_tex0;
+FSIN float v_fog;
void
main(void)
@@ -17,7 +15,10 @@ main(void)
vec4 tmp = dst*(1.0-a) + prev*u_blurcolor*a;
prev = clamp(tmp, 0.0, 1.0);
}
+ vec4 color;
color.rgb = prev.rgb;
color.a = 1.0f;
+
+ FRAGCOLOR(color);
}
diff --git a/src/extras/shaders/colourfilterIII_fs_gl3.inc b/src/extras/shaders/colourfilterIII_fs_gl.inc
index 5530a4fa..6fd1935b 100644
--- a/src/extras/shaders/colourfilterIII_fs_gl3.inc
+++ b/src/extras/shaders/colourfilterIII_fs_gl.inc
@@ -2,11 +2,9 @@ const char *colourfilterIII_frag_src =
"uniform sampler2D tex0;\n"
"uniform vec4 u_blurcolor;\n"
-"in vec4 v_color;\n"
-"in vec2 v_tex0;\n"
-"in float v_fog;\n"
-
-"out vec4 color;\n"
+"FSIN vec4 v_color;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
@@ -18,8 +16,11 @@ const char *colourfilterIII_frag_src =
" vec4 tmp = dst*(1.0-a) + prev*u_blurcolor*a;\n"
" prev = clamp(tmp, 0.0, 1.0);\n"
" }\n"
+" vec4 color;\n"
" color.rgb = prev.rgb;\n"
" color.a = 1.0f;\n"
+
+" FRAGCOLOR(color);\n"
"}\n"
;
diff --git a/src/extras/shaders/contrast.frag b/src/extras/shaders/contrast.frag
index d6dec478..1b93f6fe 100644
--- a/src/extras/shaders/contrast.frag
+++ b/src/extras/shaders/contrast.frag
@@ -2,17 +2,18 @@ uniform sampler2D tex0;
uniform vec3 u_contrastAdd;
uniform vec3 u_contrastMult;
-in vec4 v_color;
-in vec2 v_tex0;
-in float v_fog;
-
-out vec4 color;
+FSIN vec4 v_color;
+FSIN vec2 v_tex0;
+FSIN float v_fog;
void
main(void)
{
vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
+ vec4 color;
color.rgb = dst.rgb*u_contrastMult + u_contrastAdd;
color.a = 1.0f;
+
+ FRAGCOLOR(color);
}
diff --git a/src/extras/shaders/contrast_fs_gl3.inc b/src/extras/shaders/contrast_fs_gl.inc
index 58aaf079..97f78194 100644
--- a/src/extras/shaders/contrast_fs_gl3.inc
+++ b/src/extras/shaders/contrast_fs_gl.inc
@@ -3,18 +3,19 @@ const char *contrast_frag_src =
"uniform vec3 u_contrastAdd;\n"
"uniform vec3 u_contrastMult;\n"
-"in vec4 v_color;\n"
-"in vec2 v_tex0;\n"
-"in float v_fog;\n"
-
-"out vec4 color;\n"
+"FSIN vec4 v_color;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
+" vec4 color;\n"
" color.rgb = dst.rgb*u_contrastMult + u_contrastAdd;\n"
" color.a = 1.0f;\n"
+
+" FRAGCOLOR(color);\n"
"}\n"
;
diff --git a/src/extras/shaders/default_UV2.vert b/src/extras/shaders/default_UV2.vert
index 3dbad20f..694c012b 100644
--- a/src/extras/shaders/default_UV2.vert
+++ b/src/extras/shaders/default_UV2.vert
@@ -1,13 +1,9 @@
-layout(location = 0) in vec3 in_pos;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec4 in_color;
-layout(location = 3) in vec2 in_tex0;
-layout(location = 4) in vec2 in_tex1;
+VSIN(ATTRIB_POS) vec3 in_pos;
-out vec4 v_color;
-out vec2 v_tex0;
-out vec2 v_tex1;
-out float v_fog;
+VSOUT vec4 v_color;
+VSOUT vec2 v_tex0;
+VSOUT vec2 v_tex1;
+VSOUT float v_fog;
void
main(void)
diff --git a/src/extras/shaders/default_UV2_gl3.inc b/src/extras/shaders/default_UV2_gl.inc
index 14106b29..450f3d9a 100644
--- a/src/extras/shaders/default_UV2_gl3.inc
+++ b/src/extras/shaders/default_UV2_gl.inc
@@ -1,14 +1,10 @@
const char *default_UV2_vert_src =
-"layout(location = 0) in vec3 in_pos;\n"
-"layout(location = 1) in vec3 in_normal;\n"
-"layout(location = 2) in vec4 in_color;\n"
-"layout(location = 3) in vec2 in_tex0;\n"
-"layout(location = 4) in vec2 in_tex1;\n"
+"VSIN(ATTRIB_POS) vec3 in_pos;\n"
-"out vec4 v_color;\n"
-"out vec2 v_tex0;\n"
-"out vec2 v_tex1;\n"
-"out float v_fog;\n"
+"VSOUT vec4 v_color;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT vec2 v_tex1;\n"
+"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
diff --git a/src/extras/shaders/im2d.vert b/src/extras/shaders/im2d.vert
index 241593b1..fcd81c2c 100644
--- a/src/extras/shaders/im2d.vert
+++ b/src/extras/shaders/im2d.vert
@@ -1,12 +1,10 @@
uniform vec4 u_xform;
-layout(location = 0) in vec4 in_pos;
-layout(location = 2) in vec4 in_color;
-layout(location = 3) in vec2 in_tex0;
+VSIN(ATTRIB_POS) vec4 in_pos;
-out vec4 v_color;
-out vec2 v_tex0;
-out float v_fog;
+VSOUT vec4 v_color;
+VSOUT vec2 v_tex0;
+VSOUT float v_fog;
void
main(void)
diff --git a/src/extras/shaders/im2d_UV2.vert b/src/extras/shaders/im2d_UV2.vert
new file mode 100644
index 00000000..e5fd4d08
--- /dev/null
+++ b/src/extras/shaders/im2d_UV2.vert
@@ -0,0 +1,21 @@
+uniform vec4 u_xform;
+
+VSIN(ATTRIB_POS) vec4 in_pos;
+
+VSOUT vec4 v_color;
+VSOUT vec2 v_tex0;
+VSOUT vec2 v_tex1;
+VSOUT float v_fog;
+
+void
+main(void)
+{
+ gl_Position = in_pos;
+ gl_Position.w = 1.0;
+ gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;
+ v_fog = DoFog(gl_Position.z);
+ gl_Position.xyz *= gl_Position.w;
+ v_color = in_color;
+ v_tex0 = in_tex0;
+ v_tex1 = in_tex1;
+}
diff --git a/src/extras/shaders/im2d_UV2_gl.inc b/src/extras/shaders/im2d_UV2_gl.inc
new file mode 100644
index 00000000..3feb2bc1
--- /dev/null
+++ b/src/extras/shaders/im2d_UV2_gl.inc
@@ -0,0 +1,23 @@
+const char *im2d_UV2_vert_src =
+"uniform vec4 u_xform;\n"
+
+"VSIN(ATTRIB_POS) vec4 in_pos;\n"
+
+"VSOUT vec4 v_color;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT vec2 v_tex1;\n"
+"VSOUT float v_fog;\n"
+
+"void\n"
+"main(void)\n"
+"{\n"
+" gl_Position = in_pos;\n"
+" gl_Position.w = 1.0;\n"
+" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n"
+" v_fog = DoFog(gl_Position.z);\n"
+" gl_Position.xyz *= gl_Position.w;\n"
+" v_color = in_color;\n"
+" v_tex0 = in_tex0;\n"
+" v_tex1 = in_tex1;\n"
+"}\n"
+;
diff --git a/src/extras/shaders/im2d_gl3.inc b/src/extras/shaders/im2d_gl.inc
index 68341b39..d11f5d33 100644
--- a/src/extras/shaders/im2d_gl3.inc
+++ b/src/extras/shaders/im2d_gl.inc
@@ -1,13 +1,11 @@
const char *im2d_vert_src =
"uniform vec4 u_xform;\n"
-"layout(location = 0) in vec4 in_pos;\n"
-"layout(location = 2) in vec4 in_color;\n"
-"layout(location = 3) in vec2 in_tex0;\n"
+"VSIN(ATTRIB_POS) vec4 in_pos;\n"
-"out vec4 v_color;\n"
-"out vec2 v_tex0;\n"
-"out float v_fog;\n"
+"VSOUT vec4 v_color;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
diff --git a/src/extras/shaders/neoGloss.frag b/src/extras/shaders/neoGloss.frag
index 14ef0e15..4f097b0b 100644
--- a/src/extras/shaders/neoGloss.frag
+++ b/src/extras/shaders/neoGloss.frag
@@ -4,17 +4,15 @@ uniform vec4 u_reflProps;
#define glossMult (u_reflProps.x)
-in vec3 v_normal;
-in vec3 v_light;
-in vec2 v_tex0;
-in float v_fog;
-
-out vec4 color;
+FSIN vec3 v_normal;
+FSIN vec3 v_light;
+FSIN vec2 v_tex0;
+FSIN float v_fog;
void
main(void)
{
- color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
+ vec4 color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
vec3 n = 2.0*v_normal-1.0; // unpack
vec3 v = 2.0*v_light-1.0; //
@@ -22,5 +20,7 @@ main(void)
color = s*s*s*s*s*s*s*s*color*v_fog*glossMult;
DoAlphaTest(color.a);
+
+ FRAGCOLOR(color);
}
diff --git a/src/extras/shaders/neoGloss.vert b/src/extras/shaders/neoGloss.vert
index 78dd1b33..41102f3f 100644
--- a/src/extras/shaders/neoGloss.vert
+++ b/src/extras/shaders/neoGloss.vert
@@ -1,15 +1,11 @@
uniform vec3 u_eye;
+VSIN(ATTRIB_POS) vec3 in_pos;
-layout(location = 0) in vec3 in_pos;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec4 in_color;
-layout(location = 3) in vec2 in_tex0;
-
-out vec3 v_normal;
-out vec3 v_light;
-out vec2 v_tex0;
-out float v_fog;
+VSOUT vec3 v_normal;
+VSOUT vec3 v_light;
+VSOUT vec2 v_tex0;
+VSOUT float v_fog;
void
main(void)
diff --git a/src/extras/shaders/neoGloss_fs_gl3.inc b/src/extras/shaders/neoGloss_fs_gl.inc
index 736b0c5d..67e9724e 100644
--- a/src/extras/shaders/neoGloss_fs_gl3.inc
+++ b/src/extras/shaders/neoGloss_fs_gl.inc
@@ -5,17 +5,15 @@ const char *neoGloss_frag_src =
"#define glossMult (u_reflProps.x)\n"
-"in vec3 v_normal;\n"
-"in vec3 v_light;\n"
-"in vec2 v_tex0;\n"
-"in float v_fog;\n"
-
-"out vec4 color;\n"
+"FSIN vec3 v_normal;\n"
+"FSIN vec3 v_light;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
-" color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
+" vec4 color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
" vec3 n = 2.0*v_normal-1.0; // unpack\n"
" vec3 v = 2.0*v_light-1.0; //\n"
@@ -23,6 +21,8 @@ const char *neoGloss_frag_src =
" color = s*s*s*s*s*s*s*s*color*v_fog*glossMult;\n"
" DoAlphaTest(color.a);\n"
+
+" FRAGCOLOR(color);\n"
"}\n"
;
diff --git a/src/extras/shaders/neoGloss_vs_gl3.inc b/src/extras/shaders/neoGloss_vs_gl.inc
index 4adc9cb2..dffb423f 100644
--- a/src/extras/shaders/neoGloss_vs_gl3.inc
+++ b/src/extras/shaders/neoGloss_vs_gl.inc
@@ -1,16 +1,12 @@
const char *neoGloss_vert_src =
"uniform vec3 u_eye;\n"
+"VSIN(ATTRIB_POS) vec3 in_pos;\n"
-"layout(location = 0) in vec3 in_pos;\n"
-"layout(location = 1) in vec3 in_normal;\n"
-"layout(location = 2) in vec4 in_color;\n"
-"layout(location = 3) in vec2 in_tex0;\n"
-
-"out vec3 v_normal;\n"
-"out vec3 v_light;\n"
-"out vec2 v_tex0;\n"
-"out float v_fog;\n"
+"VSOUT vec3 v_normal;\n"
+"VSOUT vec3 v_light;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
diff --git a/src/extras/shaders/neoRim.vert b/src/extras/shaders/neoRim.vert
index 4a2b545f..81ee1090 100644
--- a/src/extras/shaders/neoRim.vert
+++ b/src/extras/shaders/neoRim.vert
@@ -3,14 +3,11 @@ uniform vec4 u_rampStart;
uniform vec4 u_rampEnd;
uniform vec3 u_rimData;
-layout(location = 0) in vec3 in_pos;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec4 in_color;
-layout(location = 3) in vec2 in_tex0;
-
-out vec4 v_color;
-out vec2 v_tex0;
-out float v_fog;
+VSIN(ATTRIB_POS) vec3 in_pos;
+
+VSOUT vec4 v_color;
+VSOUT vec2 v_tex0;
+VSOUT float v_fog;
void
main(void)
diff --git a/src/extras/shaders/neoRimSkin.vert b/src/extras/shaders/neoRimSkin.vert
index f16f2310..1515ad71 100644
--- a/src/extras/shaders/neoRimSkin.vert
+++ b/src/extras/shaders/neoRimSkin.vert
@@ -5,16 +5,11 @@ uniform vec4 u_rampStart;
uniform vec4 u_rampEnd;
uniform vec3 u_rimData;
-layout(location = 0) in vec3 in_pos;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec4 in_color;
-layout(location = 3) in vec2 in_tex0;
-layout(location = 11) in vec4 in_weights;
-layout(location = 12) in vec4 in_indices;
-
-out vec4 v_color;
-out vec2 v_tex0;
-out float v_fog;
+VSIN(ATTRIB_POS) vec3 in_pos;
+
+VSOUT vec4 v_color;
+VSOUT vec2 v_tex0;
+VSOUT float v_fog;
void
main(void)
diff --git a/src/extras/shaders/neoRimSkin_gl3.inc b/src/extras/shaders/neoRimSkin_gl.inc
index 70948e1f..01b739b2 100644
--- a/src/extras/shaders/neoRimSkin_gl3.inc
+++ b/src/extras/shaders/neoRimSkin_gl.inc
@@ -6,16 +6,11 @@ const char *neoRimSkin_vert_src =
"uniform vec4 u_rampEnd;\n"
"uniform vec3 u_rimData;\n"
-"layout(location = 0) in vec3 in_pos;\n"
-"layout(location = 1) in vec3 in_normal;\n"
-"layout(location = 2) in vec4 in_color;\n"
-"layout(location = 3) in vec2 in_tex0;\n"
-"layout(location = 11) in vec4 in_weights;\n"
-"layout(location = 12) in vec4 in_indices;\n"
-
-"out vec4 v_color;\n"
-"out vec2 v_tex0;\n"
-"out float v_fog;\n"
+"VSIN(ATTRIB_POS) vec3 in_pos;\n"
+
+"VSOUT vec4 v_color;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
diff --git a/src/extras/shaders/neoRim_gl3.inc b/src/extras/shaders/neoRim_gl.inc
index 7e36e95a..7cd199d0 100644
--- a/src/extras/shaders/neoRim_gl3.inc
+++ b/src/extras/shaders/neoRim_gl.inc
@@ -4,14 +4,11 @@ const char *neoRim_vert_src =
"uniform vec4 u_rampEnd;\n"
"uniform vec3 u_rimData;\n"
-"layout(location = 0) in vec3 in_pos;\n"
-"layout(location = 1) in vec3 in_normal;\n"
-"layout(location = 2) in vec4 in_color;\n"
-"layout(location = 3) in vec2 in_tex0;\n"
-
-"out vec4 v_color;\n"
-"out vec2 v_tex0;\n"
-"out float v_fog;\n"
+"VSIN(ATTRIB_POS) vec3 in_pos;\n"
+
+"VSOUT vec4 v_color;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
diff --git a/src/extras/shaders/neoVehicle.frag b/src/extras/shaders/neoVehicle.frag
index 96d4a632..2ac24f70 100644
--- a/src/extras/shaders/neoVehicle.frag
+++ b/src/extras/shaders/neoVehicle.frag
@@ -1,13 +1,11 @@
uniform sampler2D tex0;
uniform sampler2D tex1;
-in vec4 v_color;
-in vec4 v_reflcolor;
-in vec2 v_tex0;
-in vec2 v_tex1;
-in float v_fog;
-
-out vec4 color;
+FSIN vec4 v_color;
+FSIN vec4 v_reflcolor;
+FSIN vec2 v_tex0;
+FSIN vec2 v_tex1;
+FSIN float v_fog;
void
main(void)
@@ -20,9 +18,12 @@ main(void)
vec3 pass2 = v_reflcolor.rgb * v_fog;
+ vec4 color;
color.rgb = pass1.rgb*pass1.a + pass2;
color.a = pass1.a;
// color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);
DoAlphaTest(color.a);
+
+ FRAGCOLOR(color);
}
diff --git a/src/extras/shaders/neoVehicle.vert b/src/extras/shaders/neoVehicle.vert
index f2f54d6d..f0224ddb 100644
--- a/src/extras/shaders/neoVehicle.vert
+++ b/src/extras/shaders/neoVehicle.vert
@@ -8,16 +8,13 @@ uniform vec4 u_specColor[5];
#define shininess (u_reflProps.z)
#define specularity (u_reflProps.w)
-layout(location = 0) in vec3 in_pos;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec4 in_color;
-layout(location = 3) in vec2 in_tex0;
-
-out vec4 v_color;
-out vec4 v_reflcolor;
-out vec2 v_tex0;
-out vec2 v_tex1;
-out float v_fog;
+VSIN(ATTRIB_POS) vec3 in_pos;
+
+VSOUT vec4 v_color;
+VSOUT vec4 v_reflcolor;
+VSOUT vec2 v_tex0;
+VSOUT vec2 v_tex1;
+VSOUT float v_fog;
vec3 DoDirLightSpec(vec3 Ldir, vec3 Lcol, vec3 N, vec3 V, float power)
{
diff --git a/src/extras/shaders/neoVehicle_fs_gl3.inc b/src/extras/shaders/neoVehicle_fs_gl.inc
index c75ba717..20537440 100644
--- a/src/extras/shaders/neoVehicle_fs_gl3.inc
+++ b/src/extras/shaders/neoVehicle_fs_gl.inc
@@ -2,13 +2,11 @@ const char *neoVehicle_frag_src =
"uniform sampler2D tex0;\n"
"uniform sampler2D tex1;\n"
-"in vec4 v_color;\n"
-"in vec4 v_reflcolor;\n"
-"in vec2 v_tex0;\n"
-"in vec2 v_tex1;\n"
-"in float v_fog;\n"
-
-"out vec4 color;\n"
+"FSIN vec4 v_color;\n"
+"FSIN vec4 v_reflcolor;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN vec2 v_tex1;\n"
+"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
@@ -21,10 +19,13 @@ const char *neoVehicle_frag_src =
" vec3 pass2 = v_reflcolor.rgb * v_fog;\n"
+" vec4 color;\n"
" color.rgb = pass1.rgb*pass1.a + pass2;\n"
" color.a = pass1.a;\n"
"// color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n"
" DoAlphaTest(color.a);\n"
+
+" FRAGCOLOR(color);\n"
"}\n"
;
diff --git a/src/extras/shaders/neoVehicle_vs_gl3.inc b/src/extras/shaders/neoVehicle_vs_gl.inc
index 268180e1..b7b42622 100644
--- a/src/extras/shaders/neoVehicle_vs_gl3.inc
+++ b/src/extras/shaders/neoVehicle_vs_gl.inc
@@ -9,16 +9,13 @@ const char *neoVehicle_vert_src =
"#define shininess (u_reflProps.z)\n"
"#define specularity (u_reflProps.w)\n"
-"layout(location = 0) in vec3 in_pos;\n"
-"layout(location = 1) in vec3 in_normal;\n"
-"layout(location = 2) in vec4 in_color;\n"
-"layout(location = 3) in vec2 in_tex0;\n"
-
-"out vec4 v_color;\n"
-"out vec4 v_reflcolor;\n"
-"out vec2 v_tex0;\n"
-"out vec2 v_tex1;\n"
-"out float v_fog;\n"
+"VSIN(ATTRIB_POS) vec3 in_pos;\n"
+
+"VSOUT vec4 v_color;\n"
+"VSOUT vec4 v_reflcolor;\n"
+"VSOUT vec2 v_tex0;\n"
+"VSOUT vec2 v_tex1;\n"
+"VSOUT float v_fog;\n"
"vec3 DoDirLightSpec(vec3 Ldir, vec3 Lcol, vec3 N, vec3 V, float power)\n"
"{\n"
diff --git a/src/extras/shaders/neoWorldIII.frag b/src/extras/shaders/neoWorldIII.frag
index 4c5571ee..d8bb7159 100644
--- a/src/extras/shaders/neoWorldIII.frag
+++ b/src/extras/shaders/neoWorldIII.frag
@@ -3,12 +3,10 @@ uniform sampler2D tex1;
uniform vec4 u_lightMap;
-in vec4 v_color;
-in vec2 v_tex0;
-in vec2 v_tex1;
-in float v_fog;
-
-out vec4 color;
+FSIN vec4 v_color;
+FSIN vec2 v_tex0;
+FSIN vec2 v_tex1;
+FSIN float v_fog;
void
main(void)
@@ -16,10 +14,12 @@ main(void)
vec4 t0 = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
vec4 t1 = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));
- color = t0*v_color*(1 + u_lightMap*(2*t1-1));
+ vec4 color = t0*v_color*(1.0 + u_lightMap*(2.0*t1-1.0));
color.a = v_color.a*t0.a*u_lightMap.a;
color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);
DoAlphaTest(color.a);
+
+ FRAGCOLOR(color);
}
diff --git a/src/extras/shaders/neoWorldIII_fs_gl3.inc b/src/extras/shaders/neoWorldIII_fs_gl.inc
index 5145f9cd..afd75f57 100644
--- a/src/extras/shaders/neoWorldIII_fs_gl3.inc
+++ b/src/extras/shaders/neoWorldIII_fs_gl.inc
@@ -4,12 +4,10 @@ const char *neoWorldIII_frag_src =
"uniform vec4 u_lightMap;\n"
-"in vec4 v_color;\n"
-"in vec2 v_tex0;\n"
-"in vec2 v_tex1;\n"
-"in float v_fog;\n"
-
-"out vec4 color;\n"
+"FSIN vec4 v_color;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN vec2 v_tex1;\n"
+"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
@@ -17,11 +15,13 @@ const char *neoWorldIII_frag_src =
" vec4 t0 = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
" vec4 t1 = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n"
-" color = t0*v_color*(1 + u_lightMap*(2*t1-1));\n"
+" vec4 color = t0*v_color*(1.0 + u_lightMap*(2.0*t1-1.0));\n"
" color.a = v_color.a*t0.a*u_lightMap.a;\n"
" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n"
" DoAlphaTest(color.a);\n"
+
+" FRAGCOLOR(color);\n"
"}\n"
;
diff --git a/src/extras/shaders/screenDroplet.frag b/src/extras/shaders/screenDroplet.frag
new file mode 100644
index 00000000..84d30bd5
--- /dev/null
+++ b/src/extras/shaders/screenDroplet.frag
@@ -0,0 +1,18 @@
+uniform sampler2D tex0;
+uniform sampler2D tex1;
+
+FSIN vec4 v_color;
+FSIN vec2 v_tex0;
+FSIN vec2 v_tex1;
+FSIN float v_fog;
+
+void
+main(void)
+{
+ vec4 color;
+ color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
+ color *= texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));
+
+ FRAGCOLOR(color);
+}
+
diff --git a/src/extras/shaders/screenDroplet_PS.cso b/src/extras/shaders/screenDroplet_PS.cso
new file mode 100644
index 00000000..5508096b
--- /dev/null
+++ b/src/extras/shaders/screenDroplet_PS.cso
Binary files differ
diff --git a/src/extras/shaders/screenDroplet_PS.hlsl b/src/extras/shaders/screenDroplet_PS.hlsl
new file mode 100644
index 00000000..4d41da68
--- /dev/null
+++ b/src/extras/shaders/screenDroplet_PS.hlsl
@@ -0,0 +1,17 @@
+struct VS_out {
+ float4 Position : POSITION;
+ float2 TexCoord0 : TEXCOORD0;
+ float2 TexCoord1 : TEXCOORD1;
+ float4 Color : COLOR0;
+};
+
+sampler2D tex0 : register(s0);
+sampler2D tex1 : register(s1);
+
+float4 main(VS_out input) : COLOR
+{
+ float4 color = input.Color;
+ color *= tex2D(tex0, input.TexCoord0.xy);
+ color *= tex2D(tex1, input.TexCoord1.xy);
+ return color;
+}
diff --git a/src/extras/shaders/screenDroplet_PS.inc b/src/extras/shaders/screenDroplet_PS.inc
new file mode 100644
index 00000000..c2055188
--- /dev/null
+++ b/src/extras/shaders/screenDroplet_PS.inc
@@ -0,0 +1,29 @@
+static unsigned char screenDroplet_PS_cso[] = {
+ 0x00, 0x02, 0xff, 0xff, 0xfe, 0xff, 0x2c, 0x00, 0x43, 0x54, 0x41, 0x42,
+ 0x1c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff,
+ 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x06, 0x00,
+ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x30,
+ 0x00, 0xab, 0xab, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x31,
+ 0x00, 0xab, 0xab, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x32,
+ 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
+ 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68,
+ 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+ 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33,
+ 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
+ 0x01, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90,
+ 0x00, 0x08, 0x0f, 0xa0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90,
+ 0x01, 0x08, 0x0f, 0xa0, 0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80,
+ 0x00, 0x00, 0xe4, 0xb0, 0x00, 0x08, 0xe4, 0xa0, 0x42, 0x00, 0x00, 0x03,
+ 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0xb0, 0x01, 0x08, 0xe4, 0xa0,
+ 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80,
+ 0x00, 0x00, 0xe4, 0x90, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80,
+ 0x01, 0x00, 0xe4, 0x80, 0x00, 0x00, 0xe4, 0x80, 0x01, 0x00, 0x00, 0x02,
+ 0x00, 0x08, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80, 0xff, 0xff, 0x00, 0x00
+};
diff --git a/src/extras/shaders/screenDroplet_fs_gl.inc b/src/extras/shaders/screenDroplet_fs_gl.inc
new file mode 100644
index 00000000..dd393b02
--- /dev/null
+++ b/src/extras/shaders/screenDroplet_fs_gl.inc
@@ -0,0 +1,20 @@
+const char *screenDroplet_frag_src =
+"uniform sampler2D tex0;\n"
+"uniform sampler2D tex1;\n"
+
+"FSIN vec4 v_color;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN vec2 v_tex1;\n"
+"FSIN float v_fog;\n"
+
+"void\n"
+"main(void)\n"
+"{\n"
+" vec4 color;\n"
+" color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
+" color *= texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n"
+
+" FRAGCOLOR(color);\n"
+"}\n"
+
+;
diff --git a/src/extras/shaders/simple.frag b/src/extras/shaders/simple.frag
index 87157beb..c85bf089 100644
--- a/src/extras/shaders/simple.frag
+++ b/src/extras/shaders/simple.frag
@@ -1,16 +1,17 @@
uniform sampler2D tex0;
-in vec4 v_color;
-in vec2 v_tex0;
-in float v_fog;
-
-out vec4 color;
+FSIN vec4 v_color;
+FSIN vec2 v_tex0;
+FSIN float v_fog;
void
main(void)
{
+ vec4 color;
color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);
DoAlphaTest(color.a);
+
+ FRAGCOLOR(color);
}
diff --git a/src/extras/shaders/simple_fs_gl3.inc b/src/extras/shaders/simple_fs_gl.inc
index 47d89971..614d79a0 100644
--- a/src/extras/shaders/simple_fs_gl3.inc
+++ b/src/extras/shaders/simple_fs_gl.inc
@@ -1,18 +1,19 @@
const char *simple_frag_src =
"uniform sampler2D tex0;\n"
-"in vec4 v_color;\n"
-"in vec2 v_tex0;\n"
-"in float v_fog;\n"
-
-"out vec4 color;\n"
+"FSIN vec4 v_color;\n"
+"FSIN vec2 v_tex0;\n"
+"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
+" vec4 color;\n"
" color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n"
" DoAlphaTest(color.a);\n"
+
+" FRAGCOLOR(color);\n"
"}\n"
;
diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp
index b9ff0144..2e04aed2 100644
--- a/src/fakerw/fake.cpp
+++ b/src/fakerw/fake.cpp
@@ -16,9 +16,14 @@ using namespace rw;
RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; }
-void *RwMalloc(size_t size) { return malloc(size); }
-void *RwCalloc(size_t numObj, size_t sizeObj) { return calloc(numObj, sizeObj); }
-void RwFree(void *mem) { free(mem); }
+void *RwMalloc(size_t size) { return engine->memfuncs.rwmalloc(size, 0); }
+void *RwCalloc(size_t numObj, size_t sizeObj) {
+ void *mem = RwMalloc(numObj*sizeObj);
+ if(mem)
+ memset(mem, 0, numObj*sizeObj);
+ return mem;
+}
+void RwFree(void *mem) { engine->memfuncs.rwfree(mem); }
//RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in);
@@ -294,32 +299,12 @@ RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture);
// TODO
void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { }
-static rw::Raster*
-ConvertTexRaster(rw::Raster *ras)
-{
- using namespace rw;
-
- if(ras->platform == rw::platform)
- return ras;
- // compatible platforms
- if(ras->platform == PLATFORM_D3D8 && rw::platform == PLATFORM_D3D9 ||
- ras->platform == PLATFORM_D3D9 && rw::platform == PLATFORM_D3D8)
- return ras;
-
- Image *img = ras->toImage();
- ras->destroy();
- img->unpalettize();
- ras = Raster::createFromImage(img);
- img->destroy();
- return ras;
-}
-
// hack for reading native textures
RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size)
{
*tex = Texture::streamReadNative(stream);
#ifdef LIBRW
- (*tex)->raster = ConvertTexRaster((*tex)->raster);
+ (*tex)->raster = rw::Raster::convertTexToCurrentPlatform((*tex)->raster);
#endif
return *tex != nil;
}
@@ -462,6 +447,53 @@ RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType);
+RwBool RwRenderStateGet(RwRenderState state, void *value)
+{
+ uint32 *uival = (uint32*)value;
+ uint32 fog;
+ switch(state){
+ case rwRENDERSTATETEXTURERASTER: *(void**)value = GetRenderStatePtr(TEXTURERASTER); return true;
+ case rwRENDERSTATETEXTUREADDRESS: *uival = GetRenderState(TEXTUREADDRESS); return true;
+ case rwRENDERSTATETEXTUREADDRESSU: *uival = GetRenderState(TEXTUREADDRESSU); return true;
+ case rwRENDERSTATETEXTUREADDRESSV: *uival = GetRenderState(TEXTUREADDRESSV); return true;
+ case rwRENDERSTATETEXTUREPERSPECTIVE: *uival = 1; return true;
+ case rwRENDERSTATEZTESTENABLE: *uival = GetRenderState(ZTESTENABLE); return true;
+ case rwRENDERSTATESHADEMODE: *uival = rwSHADEMODEGOURAUD; return true;
+ case rwRENDERSTATEZWRITEENABLE: *uival = GetRenderState(ZWRITEENABLE); return true;
+ case rwRENDERSTATETEXTUREFILTER: *uival = GetRenderState(TEXTUREFILTER); return true;
+ case rwRENDERSTATESRCBLEND: *uival = GetRenderState(SRCBLEND); return true;
+ case rwRENDERSTATEDESTBLEND: *uival = GetRenderState(DESTBLEND); return true;
+ case rwRENDERSTATEVERTEXALPHAENABLE: *uival = GetRenderState(VERTEXALPHA); return true;
+ case rwRENDERSTATEBORDERCOLOR: *uival = 0; return true;
+ case rwRENDERSTATEFOGENABLE: *uival = GetRenderState(FOGENABLE); return true;
+ case rwRENDERSTATEFOGCOLOR:
+ // have to swap R and B here
+ fog = GetRenderState(FOGCOLOR);
+ *uival = (fog>>16)&0xFF;
+ *uival |= (fog&0xFF)<<16;
+ *uival |= fog&0xFF00;
+ *uival |= fog&0xFF000000;
+ return true;
+ case rwRENDERSTATEFOGTYPE: *uival = rwFOGTYPELINEAR; return true;
+ case rwRENDERSTATEFOGDENSITY: *(float*)value = 1.0f; return true;
+ case rwRENDERSTATECULLMODE: *uival = GetRenderState(CULLMODE); return true;
+
+ // all unsupported
+ case rwRENDERSTATEFOGTABLE:
+ case rwRENDERSTATEALPHAPRIMITIVEBUFFER:
+
+ case rwRENDERSTATESTENCILENABLE:
+ case rwRENDERSTATESTENCILFAIL:
+ case rwRENDERSTATESTENCILZFAIL:
+ case rwRENDERSTATESTENCILPASS:
+ case rwRENDERSTATESTENCILFUNCTION:
+ case rwRENDERSTATESTENCILFUNCTIONREF:
+ case rwRENDERSTATESTENCILFUNCTIONMASK:
+ case rwRENDERSTATESTENCILFUNCTIONWRITEMASK:
+ default:
+ return false;
+ }
+}
RwBool RwRenderStateSet(RwRenderState state, void *value)
{
uint32 uival = (uintptr)value;
@@ -509,8 +541,27 @@ RwBool RwRenderStateSet(RwRenderState state, void *value)
}
}
+static rw::MemoryFunctions gMemfuncs;
+static void *(*real_malloc)(size_t size);
+static void *(*real_realloc)(void *mem, size_t newSize);
+static void *mallocWrap(size_t sz, uint32 hint) { if(sz == 0) return nil; return real_malloc(sz); }
+static void *reallocWrap(void *p, size_t sz, uint32 hint) { return real_realloc(p, sz); }
+
+
// WARNING: unused parameters
-RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { Engine::init(); return true; }
+RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) {
+ if(memFuncs){
+ real_malloc = memFuncs->rwmalloc;
+ real_realloc = memFuncs->rwrealloc;
+ gMemfuncs.rwmalloc = mallocWrap;
+ gMemfuncs.rwrealloc = reallocWrap;
+ gMemfuncs.rwfree = memFuncs->rwfree;
+ Engine::init(&gMemfuncs);
+ }else{
+ Engine::init(nil);
+ }
+ return true;
+}
// TODO: this is platform dependent
RwBool RwEngineOpen(RwEngineOpenParams *initParams) {
static EngineOpenParams openParams;
@@ -550,6 +601,9 @@ void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) {}
RwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; }
+void RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level) { Engine::setMultiSamplingLevels(level); }
+RwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void) { return Engine::getMaxMultiSamplingLevels(); }
+
RpMaterial *RpMaterialCreate(void) { return Material::create(); }
RwBool RpMaterialDestroy(RpMaterial *material) { material->destroy(); return true; }
@@ -749,6 +803,9 @@ RwBool RpWorldPluginAttach(void) {
registerNativeDataPlugin();
registerAtomicRightsPlugin();
registerMaterialRightsPlugin();
+
+ // not sure if this goes here
+ rw::xbox::registerVertexFormatPlugin();
return true;
}
@@ -905,14 +962,3 @@ RtCharset *RtCharsetSetColors(RtCharset * charSet, const RwRGBA * foreGround,
RtCharset *RtCharsetGetDesc(RtCharset * charset, RtCharsetDesc * desc) { *desc = charset->desc; return charset; }
RtCharset *RtCharsetCreate(const RwRGBA * foreGround, const RwRGBA * backGround) { return Charset::create(foreGround, backGround); }
RwBool RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return true; }
-
-
-
-// fake shit
-RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags)
-{
-#ifdef RW_GL3
- return '3LGO';
-#endif
- return flags & 0xF00;
-}
diff --git a/src/fakerw/rwcore.h b/src/fakerw/rwcore.h
index 31bc5541..e5d21865 100644
--- a/src/fakerw/rwcore.h
+++ b/src/fakerw/rwcore.h
@@ -411,3 +411,5 @@ RwFrame *RwCameraGetFrame(const RwCamera *camera);
void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate);
RwBool RwD3D8DeviceSupportsDXTTexture(void);
+void RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level);
+RwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void);
diff --git a/src/fakerw/rwplcore.h b/src/fakerw/rwplcore.h
index 79c745b6..511f7678 100644
--- a/src/fakerw/rwplcore.h
+++ b/src/fakerw/rwplcore.h
@@ -141,15 +141,15 @@ RwUInt8 RwObjectGetType(const RwObject *obj);
***********************************************
*/
-struct RwMemoryFunctions;
-/*
+struct RwMemoryFunctions
{
+ // NB: from RW 3.6 on the allocating functions take
+ // a hint parameter!
void *(*rwmalloc)(size_t size);
void (*rwfree)(void *mem);
void *(*rwrealloc)(void *mem, size_t newSize);
void *(*rwcalloc)(size_t numObj, size_t sizeObj);
};
-*/
void *RwMalloc(size_t size);
void RwFree(void *mem);
diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h
index 2505967b..4c274aaf 100644
--- a/src/modelinfo/BaseModelInfo.h
+++ b/src/modelinfo/BaseModelInfo.h
@@ -63,9 +63,9 @@ public:
bool DoesOwnColModel(void) { return m_bOwnsColModel; }
void DeleteCollisionModel(void);
void ClearTexDictionary(void) { m_txdSlot = -1; }
- short GetObjectID(void) { return m_objectId; }
+ int16 GetObjectID(void) { return m_objectId; }
void SetObjectID(int16 id) { m_objectId = id; }
- short GetTxdSlot(void) { return m_txdSlot; }
+ int16 GetTxdSlot(void) { return m_txdSlot; }
void AddRef(void);
void RemoveRef(void);
void SetTexDictionary(const char *name);
diff --git a/src/modelinfo/ModelIndices.cpp b/src/modelinfo/ModelIndices.cpp
index 056c3733..98c7fb38 100644
--- a/src/modelinfo/ModelIndices.cpp
+++ b/src/modelinfo/ModelIndices.cpp
@@ -3,7 +3,7 @@
#include "General.h"
#include "ModelIndices.h"
-#define X(name, var) int16 var;
+#define X(name, var) int16 var = -1;
MODELINDICES
#undef X
diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h
index d73d3646..f467fe8a 100644
--- a/src/modelinfo/PedModelInfo.h
+++ b/src/modelinfo/PedModelInfo.h
@@ -2,7 +2,6 @@
#include "ClumpModelInfo.h"
#include "PedType.h"
-#include "PedStats.h"
enum PedNode {
PED_TORSO,
diff --git a/src/modelinfo/SimpleModelInfo.h b/src/modelinfo/SimpleModelInfo.h
index ee63f24b..94e55a2f 100644
--- a/src/modelinfo/SimpleModelInfo.h
+++ b/src/modelinfo/SimpleModelInfo.h
@@ -11,6 +11,18 @@ public:
float m_lodDistances[3];
uint8 m_numAtomics;
uint8 m_alpha;
+ /* // For reference, PS2 has:
+ uint8 m_firstDamaged;
+ uint8 m_normalCull : 1;
+ uint8 m_isDamaged : 1;
+ uint8 m_isBigBuilding : 1;
+ uint8 m_noFade : 1;
+ uint8 m_drawLast : 1;
+ uint8 m_additive : 1;
+ uint8 m_isSubway : 1;
+ uint8 m_ignoreLight : 1;
+ // m_noZwrite is missing because not needed
+ */
uint16 m_firstDamaged : 2; // 0: no damage model
// 1: 1 and 2 are damage models
// 2: 2 is damage model
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index a024bb40..17754211 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -536,7 +536,7 @@ CVehicleModelInfo::SetVehicleComponentFlags(RwFrame *frame, uint32 flags)
{
tHandlingData *handling;
- handling = mod_HandlingManager.GetHandlingData((eHandlingId)m_handlingId);
+ handling = mod_HandlingManager.GetHandlingData((tVehicleType)m_handlingId);
#define SETFLAGS(f) RwFrameForAllObjects(frame, SetAtomicFlagCB, (void*)(f))
@@ -962,7 +962,7 @@ CVehicleModelInfo::DeleteVehicleColourTextures(void)
for(i = 0; i < 256; i++){
if(ms_colourTextureTable[i]){
RwTextureDestroy(ms_colourTextureTable[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
ms_colourTextureTable[i] = nil;
#endif
}
@@ -998,6 +998,8 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial *material, void *data)
return material;
}
+bool initialised;
+
RpAtomic*
CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data)
{
@@ -1011,7 +1013,12 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data)
RpGeometryForAllMaterials(geo, SetEnvironmentMapCB, data);
RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR);
RpMatFXAtomicEnableEffects(atomic);
- // PS2 sets of PS2Manager lighting CB here
+#ifdef GTA_PS2
+ if(!initialised){
+ SetupPS2ManagerLightingCallback(RpAtomicGetInstancePipeline(atomic));
+ initialised = true;
+ }
+#endif
}
return atomic;
}
diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp
index 55e75807..15611c29 100644
--- a/src/objects/CutsceneHead.cpp
+++ b/src/objects/CutsceneHead.cpp
@@ -12,6 +12,10 @@
#include "CutsceneHead.h"
#include "CdStream.h"
+#ifdef GTA_PS2_STUFF
+// this is a total hack to switch between PC and PS2 code
+static bool lastLoadedSKA;
+#endif
CCutsceneHead::CCutsceneHead(CObject *obj)
{
@@ -87,6 +91,10 @@ CCutsceneHead::ProcessControl(void)
assert(RwObjectGetType(m_rwObject) == rpCLUMP);
atm = GetFirstAtomic((RpClump*)m_rwObject);
hier = RpSkinAtomicGetHAnimHierarchy(atm);
+#ifdef GTA_PS2_STUFF
+ // PS2 only plays anims in cutscene, PC always plays anims
+ if(!lastLoadedSKA || CCutsceneMgr::IsRunning())
+#endif
RpHAnimHierarchyAddAnimTime(hier, CTimer::GetTimeStepNonClipped()/50.0f);
}
@@ -168,6 +176,10 @@ CCutsceneHead::PlayAnimation(const char *animName)
uint32 offset, size;
RwStream *stream;
+#ifdef GTA_PS2_STUFF
+ lastLoadedSKA = false;
+#endif
+
assert(RwObjectGetType(m_rwObject) == rpCLUMP);
atm = GetFirstAtomic((RpClump*)m_rwObject);
hier = RpSkinAtomicGetHAnimHierarchy(atm);
@@ -191,4 +203,29 @@ CCutsceneHead::PlayAnimation(const char *animName)
RwStreamClose(stream, nil);
}
+#ifdef GTA_PS2_STUFF
+#ifdef LIBRW
+ else{
+ sprintf(gString, "%s.ska", 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);
+ anim = rw::Animation::streamReadLegacy(stream);
+ RpHAnimHierarchySetCurrentAnim(hier, anim);
+
+ CStreaming::IHaveUsedStreamingMemory();
+
+ RwStreamClose(stream, nil);
+
+ lastLoadedSKA = true;
+ }
+ }
+#endif
+#endif
}
diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp
index a8afaf6c..71f223d7 100644
--- a/src/objects/ParticleObject.cpp
+++ b/src/objects/ParticleObject.cpp
@@ -8,6 +8,7 @@
#include "Camera.h"
#include "Game.h"
#include "DMAudio.h"
+#include "screendroplets.h"
CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS];
@@ -18,6 +19,8 @@ CParticleObject *CParticleObject::pUnusedListHead;
CAudioHydrant List[MAX_AUDIOHYDRANTS];
+CAudioHydrant *CAudioHydrant::Get(int n) { return &List[n]; }
+
bool
CAudioHydrant::Add(CParticleObject *particleobject)
{
@@ -247,6 +250,9 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe
pobj->m_nSkipFrames = 3;
#endif
pobj->m_nCreationChance = 0;
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::RegisterSplash(pobj);
+#endif
break;
}
diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h
index 34a672bb..e4e7fcd2 100644
--- a/src/objects/ParticleObject.h
+++ b/src/objects/ParticleObject.h
@@ -103,4 +103,6 @@ public:
static bool Add (CParticleObject *particleobject);
static void Remove(CParticleObject *particleobject);
+
+ static CAudioHydrant *Get(int n); // for neo screen droplets
}; \ No newline at end of file
diff --git a/src/objects/Projectile.h b/src/objects/Projectile.h
index 2f2b541c..4b3eb4b8 100644
--- a/src/objects/Projectile.h
+++ b/src/objects/Projectile.h
@@ -1,7 +1,5 @@
#pragma once
-#pragma once
-
#include "Object.h"
class CProjectile : public CObject
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp
index 2d782a73..401d2e67 100644
--- a/src/peds/CivilianPed.cpp
+++ b/src/peds/CivilianPed.cpp
@@ -424,3 +424,45 @@ CCivilianPed::ProcessControl(void)
if (m_moved.Magnitude() > 0.0f)
Avoid();
}
+
+// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up.
+bool
+CPed::RunToReportCrime(eCrimeType crimeToReport)
+{
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ if (bRunningToPhone) {
+ if (!isPhoneAvailable(m_phoneId)) {
+ m_phoneId = -1;
+ bIsRunning = false;
+ ClearSeek(); // clears bRunningToPhone
+ return false;
+ }
+
+ return true;
+ }
+#else
+ // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it.
+ if (m_nPedState == PED_SEEK_POS)
+ return false;
+#endif
+
+ CVector pos = GetPosition();
+ int phoneId = gPhoneInfo.FindNearestFreePhone(&pos);
+
+ if (phoneId == -1)
+ return false;
+
+ CPhone *phone = &gPhoneInfo.m_aPhones[phoneId];
+#ifndef PEDS_REPORT_CRIMES_ON_PHONE
+ if (phone->m_nState != PHONE_STATE_FREE)
+ return false;
+#endif
+
+ bRunningToPhone = true;
+ SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f
+ SetMoveState(PEDMOVE_RUN);
+ bIsRunning = true; // not there in original
+ m_phoneId = phoneId;
+ m_crimeToReportOnPhone = crimeToReport;
+ return true;
+} \ No newline at end of file
diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp
index f289697e..d9f55559 100644
--- a/src/peds/CopPed.cpp
+++ b/src/peds/CopPed.cpp
@@ -667,7 +667,7 @@ CCopPed::ProcessControl(void)
}
if (bDuckAndCover) {
-#if !defined(GTA3_1_1_PATCH) && !defined(VC_PED_PORTS)
+#if GTA_VERSION < GTA3_PC_11 && !defined(VC_PED_PORTS)
if (!bNotAllowedToDuck && Seek()) {
SetMoveState(PEDMOVE_STILL);
SetMoveAnim();
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index fcfd9bce..c41c1f0c 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -3,111 +3,44 @@
#include "main.h"
#include "Pools.h"
#include "Particle.h"
-#include "Stats.h"
-#include "World.h"
#include "RpAnimBlend.h"
#include "Bones.h"
#include "Ped.h"
-#include "Wanted.h"
-#include "PlayerPed.h"
-#include "PedType.h"
-#include "AnimBlendClumpData.h"
#include "AnimBlendAssociation.h"
#include "Fire.h"
#include "DMAudio.h"
#include "General.h"
-#include "SurfaceTable.h"
#include "VisibilityPlugins.h"
-#include "AudioManager.h"
#include "HandlingMgr.h"
#include "Replay.h"
-#include "Camera.h"
#include "Radar.h"
#include "PedPlacement.h"
#include "Shadows.h"
#include "Weather.h"
#include "ZoneCull.h"
#include "Population.h"
-#include "Renderer.h"
-#include "Lights.h"
-#include "PointLights.h"
#include "Pad.h"
#include "Phones.h"
-#include "Darkel.h"
-#include "PathFind.h"
-#include "ModelIndices.h"
-#include "FileMgr.h"
-#include "TempColModels.h"
-#include "Pickups.h"
-#include "Train.h"
#include "TrafficLights.h"
-#include "PedRoutes.h"
-#include "Sprite.h"
-#include "RwHelper.h"
-#include "Font.h"
-#include "Text.h"
#include "CopPed.h"
#include "Script.h"
#include "CarCtrl.h"
#include "Garages.h"
#include "WaterLevel.h"
-#include "CarAI.h"
-#include "Zones.h"
-#include "Cranes.h"
#include "Timecycle.h"
#include "ParticleObject.h"
#include "Floater.h"
#include "Range2D.h"
-#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
-
CPed *gapTempPedList[50];
uint16 gnNumTempPedList;
static CColPoint aTempPedColPts[MAX_COLLISION_POINTS];
-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},
-};
uint16 CPed::nThreatReactionRangeMultiplier = 1;
uint16 CPed::nEnterCarRangeMultiplier = 1;
-CVector vecPedCarDoorAnimOffset;
-CVector vecPedCarDoorLoAnimOffset;
-CVector vecPedVanRearDoorAnimOffset;
-CVector vecPedQuickDraggedOutCarAnimOffset;
-CVector vecPedDraggedOutCarAnimOffset;
-CVector vecPedTrainDoorAnimOffset;
-
bool CPed::bNastyLimbsCheat;
bool CPed::bPedCheat2;
bool CPed::bPedCheat3;
@@ -122,53 +55,6 @@ void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((
bool CPed::bPopHeadsOnHeadshot = false;
#endif
-CPed::~CPed(void)
-{
- CWorld::Remove(this);
- CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
- if (InVehicle()){
- uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
- if (m_pMyVehicle->pDriver == this)
- m_pMyVehicle->pDriver = nil;
- else {
- // FIX: Passenger counter now decreasing after removing ourself from vehicle.
- m_pMyVehicle->RemovePassenger(this);
- }
- if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
- m_pMyVehicle->m_nGettingOutFlags &= ~door_flag;
- bInVehicle = false;
- m_pMyVehicle = nil;
- } else if (EnteringCar()) {
- QuitEnteringCar();
- }
- if (m_pFire)
- m_pFire->Extinguish();
- CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
- DMAudio.DestroyEntity(m_audioEntityId);
-}
-
-void
-CPed::FlagToDestroyWhenNextProcessed(void)
-{
- bRemoveFromWorld = true;
- if (!InVehicle())
- return;
- if (m_pMyVehicle->pDriver == this){
- m_pMyVehicle->pDriver = nil;
- if (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED)
- m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- }else{
- m_pMyVehicle->RemovePassenger(this);
- }
- bInVehicle = false;
- m_pMyVehicle = nil;
- if (CharCreatedBy == MISSION_CHAR)
- m_nPedState = PED_DEAD;
- else
- m_nPedState = PED_NONE;
- m_pVehicleAnim = nil;
-}
-
CPed::CPed(uint32 pedType) : m_pedIK(this)
{
m_type = ENTITY_TYPE_PED;
@@ -397,370 +283,135 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
CPopulation::UpdatePedCount((ePedType)m_nPedType, false);
}
-uint32
-CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo)
-{
- CWeapon &weapon = GetWeapon(weaponType);
-
- if (HasWeapon(weaponType)) {
- if (weapon.m_nAmmoTotal + ammo > 99999)
- weapon.m_nAmmoTotal = 99999;
- else
- weapon.m_nAmmoTotal += ammo;
-
- weapon.Reload();
- } 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 (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO)
- weapon.m_eWeaponState = WEAPONSTATE_READY;
-
- return weaponType;
-}
-
-static RwObject*
-RemoveAllModelCB(RwObject *object, void *data)
-{
- RpAtomic *atomic = (RpAtomic*)object;
- if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
- RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
- RpAtomicDestroy(atomic);
- }
- return object;
-}
-
-static PedOnGroundState
-CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround)
+CPed::~CPed(void)
{
- PedOnGroundState stateToReturn;
- float angleToFace;
- CPed *currentPed = nil;
- PedState currentPedState;
- CPed *pedOnTheFloor = nil;
- CPed *deadPed = nil;
- CPed *pedBelow = nil;
- bool foundDead = false;
- bool foundOnTheFloor = false;
- bool foundBelow = false;
- float angleDiff;
- float distance;
-
- if (!CGame::nastyGame)
- return NO_PED;
-
- for (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) {
-
- currentPed = attacker->m_nearPeds[currentPedId];
-
- CVector posDifference = currentPed->GetPosition() - attacker->GetPosition();
- distance = posDifference.Magnitude();
-
- if (distance < 2.0f) {
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- currentPed->GetPosition().x, currentPed->GetPosition().y,
- attacker->GetPosition().x, attacker->GetPosition().y);
-
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- attacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur);
-
- angleDiff = Abs(angleToFace - attacker->m_fRotationCur);
-
- if (angleDiff > PI)
- angleDiff = 2 * PI - angleDiff;
-
- currentPedState = currentPed->m_nPedState;
-
- if (currentPed->OnGroundOrGettingUp()) {
- if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) {
- if (currentPedState == PED_DEAD) {
- foundDead = 1;
- if (!deadPed)
- deadPed = currentPed;
- } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {
- foundOnTheFloor = 1;
- if (!pedOnTheFloor)
- pedOnTheFloor = currentPed;
- }
- }
- } else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f))
- || (distance < 1.3f && angleDiff < DEGTORAD(55.0f))
- || (distance < 1.7f && angleDiff < DEGTORAD(35.0f))
- || (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) {
-
- // Either this condition or below one was probably returning 4 early in development. See Fight().
- foundBelow = 1;
- pedBelow = currentPed;
- break;
- } else {
- if (angleDiff < DEGTORAD(75.0f)) {
- foundBelow = 1;
- if (!pedBelow)
- pedBelow = currentPed;
- }
- }
+ CWorld::Remove(this);
+ CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
+ if (InVehicle()){
+ uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
+ if (m_pMyVehicle->pDriver == this)
+ m_pMyVehicle->pDriver = nil;
+ else {
+ // FIX: Passenger counter now decreasing after removing ourself from vehicle.
+ m_pMyVehicle->RemovePassenger(this);
}
+ if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
+ m_pMyVehicle->m_nGettingOutFlags &= ~door_flag;
+ bInVehicle = false;
+ m_pMyVehicle = nil;
+ } else if (EnteringCar()) {
+ QuitEnteringCar();
}
-
- if (foundOnTheFloor) {
- currentPed = pedOnTheFloor;
- stateToReturn = PED_ON_THE_FLOOR;
- } else if (foundDead) {
- currentPed = deadPed;
- stateToReturn = PED_DEAD_ON_THE_FLOOR;
- } else if (foundBelow) {
- currentPed = pedBelow;
- stateToReturn = PED_IN_FRONT_OF_ATTACKER;
- } else {
- currentPed = nil;
- stateToReturn = NO_PED;
- }
-
- if (pedOnGround)
- *pedOnGround = currentPed;
-
- return stateToReturn;
-}
-
-bool
-CPed::IsPlayer(void)
-{
- return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 ||
- m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4;
-}
-
-bool
-CPed::UseGroundColModel(void)
-{
- return m_nPedState == PED_FALL ||
- m_nPedState == PED_DIVE_AWAY ||
- m_nPedState == PED_DIE ||
- m_nPedState == PED_DEAD;
-}
-
-bool
-CPed::CanSetPedState(void)
-{
- return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR;
-}
-
-bool
-CPed::IsPedInControl(void)
-{
- return m_nPedState <= PED_STATES_NO_AI
- && !bIsInTheAir && !bIsLanding
- && m_fHealth > 0.0f;
-}
-
-bool
-CPed::CanStrafeOrMouseControl(void)
-{
-#ifdef FREE_CAM
- if (CCamera::bFreeCam)
- return false;
-#endif
- return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY ||
- m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP;
+ if (m_pFire)
+ m_pFire->Extinguish();
+ CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
+ DMAudio.DestroyEntity(m_audioEntityId);
}
void
-CPed::AddWeaponModel(int id)
+CPed::Initialise(void)
{
- RpAtomic *atm;
-
- if (id != -1) {
-#ifdef PED_SKIN
- if (IsClumpSkinned(GetClump())) {
- if (m_pWeaponModel)
- RemoveWeaponModel(-1);
-
- m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
- } else
-#endif
- {
- atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
- RwFrameDestroy(RpAtomicGetFrame(atm));
- RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame);
- RpClumpAddAtomic(GetClump(), atm);
- }
- m_wepModelID = id;
- }
+ debug("Initialising CPed...\n");
+ CPedType::Initialise();
+ LoadFightData();
+ SetAnimOffsetForEnterOrExitVehicle();
+ debug("CPed ready\n");
}
void
-CPed::AimGun(void)
+CPed::SetModelIndex(uint32 mi)
{
- RwV3d pos;
- CVector vector;
-
- if (m_pSeekTarget) {
- if (m_pSeekTarget->IsPed()) {
- ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_MID);
- vector = pos;
- } else {
- vector = m_pSeekTarget->GetPosition();
- }
- Say(SOUND_PED_ATTACK);
+ CEntity::SetModelIndex(mi);
+ RpAnimBlendClumpInit(GetClump());
+ RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames);
+ CPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
+ SetPedStats(modelInfo->m_pedStatType);
+ m_headingRate = m_pedStats->m_headingChangeRate;
+ m_animGroup = (AssocGroupId) modelInfo->m_animGroup;
+ CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE);
- bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector);
- if (m_pLookTarget != m_pSeekTarget) {
- SetLookFlag(m_pSeekTarget, true);
- }
+ // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
+ (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
- } else {
- if (IsPlayer()) {
- bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading);
- } else {
- bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f);
- }
- }
+#ifdef PED_SKIN
+ if(modelInfo->GetHitColModel() == nil)
+ modelInfo->CreateHitColModelSkinned(GetClump());
+#endif
}
void
-CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
-{
- CVector pos2 = CVector(
- pos.x,
- pos.y,
- pos.z + 0.1f
- );
-
- if (!IsPlayer() || evenOnPlayer) {
- ++CStats::HeadsPopped;
-
- // BUG: This condition will always return true. Even fixing it won't work, because these states are unused.
- // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {
- SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- // }
-
- bBodyPartJustCameOff = true;
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150;
-
- CParticle::AddParticle(PARTICLE_TEST, pos2,
- CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0);
-
- if (CEntity::GetIsOnScreen()) {
- for(int i=0; i < 32; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
- pos2, CVector(0.0f, 0.0f, 0.03f),
- nil, 0.0f, 0, 0, 0, 0);
- }
-
- for (int i = 0; i < 16; i++) {
- CParticle::AddParticle(PARTICLE_DEBRIS2,
- pos2,
- CVector(0.0f, 0.0f, 0.01f),
- nil, 0.0f, 0, 0, 0, 0);
- }
- }
- }
-}
-
-static RwObject*
-SetPedAtomicVisibilityCB(RwObject* object, void* data)
-{
- if (data == nil)
- RpAtomicSetFlags((RpAtomic*)object, 0);
- return object;
-}
-
-static RwFrame*
-RecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data)
+CPed::SetPedStats(ePedStats pedStat)
{
- RwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data);
- RwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil);
- return frame;
+ m_pedStats = CPedStats::ms_apPedStats[pedStat];
}
void
-CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
+CPed::BuildPedLists(void)
{
- RwFrame *frame;
- CVector pos;
-
- frame = m_pFrames[nodeId]->frame;
- if (frame) {
- if (CGame::nastyGame) {
-#ifdef PED_SKIN
- if(!IsClumpSkinned(GetClump()))
-#endif
- {
-#ifdef DEBUGMENU
- if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
-#else
- if (nodeId != PED_HEAD)
-#endif
- SpawnFlyingComponent(nodeId, direction);
+ if (((CTimer::GetFrameCounter() + m_randomSeed) % 16) == 0) {
+ CVector centre = CEntity::GetBoundCentre();
+ CRect rect(centre.x - 20.0f,
+ centre.y - 20.0f,
+ centre.x + 20.0f,
+ centre.y + 20.0f);
+ int xstart = CWorld::GetSectorIndexX(rect.left);
+ int ystart = CWorld::GetSectorIndexY(rect.top);
+ int xend = CWorld::GetSectorIndexX(rect.right);
+ int yend = CWorld::GetSectorIndexY(rect.bottom);
+ gnNumTempPedList = 0;
- RecurseFrameChildrenVisibilityCB(frame, nil);
- }
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- TransformToNode(pos, PED_HEAD);
-
- if (CEntity::GetIsOnScreen()) {
- CParticle::AddParticle(PARTICLE_TEST, pos,
- CVector(0.0f, 0.0f, 0.0f),
- nil, 0.1f, 0, 0, 0, 0);
-
- for (int i = 0; i < 16; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
- pos,
- CVector(0.0f, 0.0f, 0.03f),
- nil, 0.0f, 0, 0, 0, 0);
+ for(int y = ystart; y <= yend; y++) {
+ for(int x = xstart; x <= xend; x++) {
+ for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) {
+ CPed *ped = (CPed*)pedPtrNode->item;
+ if (ped != this && !ped->bInVehicle) {
+ float dist = (ped->GetPosition() - GetPosition()).Magnitude2D();
+ if (nThreatReactionRangeMultiplier * 30.0f > dist) {
+ gapTempPedList[gnNumTempPedList] = ped;
+ gnNumTempPedList++;
+ assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList));
+ }
+ }
}
}
- bBodyPartJustCameOff = true;
- m_bodyPartBleeding = nodeId;
}
- } else {
- printf("Trying to remove ped component");
- }
-}
+ gapTempPedList[gnNumTempPedList] = nil;
+ SortPeds(gapTempPedList, 0, gnNumTempPedList - 1);
+ for (m_numNearPeds = 0; m_numNearPeds < ARRAY_SIZE(m_nearPeds); m_numNearPeds++) {
+ CPed *ped = gapTempPedList[m_numNearPeds];
+ if (!ped)
+ break;
-void
-CPed::SetLookFlag(CEntity *target, bool keepTryingToLook)
-{
- if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
- bIsLooking = true;
- bIsRestoringLook = false;
- m_pLookTarget = target;
- m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
- m_fLookDirection = 999999.0f;
- m_lookTimer = 0;
- bKeepTryingToLook = keepTryingToLook;
- if (m_nPedState != PED_DRIVING) {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ m_nearPeds[m_numNearPeds] = ped;
}
- }
-}
-
-void
-CPed::SetLookFlag(float direction, bool keepTryingToLook)
-{
- if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
- bIsLooking = true;
- bIsRestoringLook = false;
- m_pLookTarget = nil;
- m_fLookDirection = direction;
- m_lookTimer = 0;
- bKeepTryingToLook = keepTryingToLook;
- if (m_nPedState != PED_DRIVING) {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ for (int pedToClear = m_numNearPeds; pedToClear < ARRAY_SIZE(m_nearPeds); pedToClear++)
+ m_nearPeds[pedToClear] = nil;
+ } else {
+ for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) {
+ bool removePed = false;
+ if (m_nearPeds[i]) {
+ if (m_nearPeds[i]->IsPointerValid()) {
+ float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D();
+ if (distSqr > 900.0f)
+ removePed = true;
+ } else
+ removePed = true;
+ }
+ if (removePed) {
+ // If we arrive here, the ped we're checking isn't "near", so we should remove it.
+ for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) {
+ m_nearPeds[j] = m_nearPeds[j + 1];
+ m_nearPeds[j + 1] = nil;
+ }
+ // Above loop won't work on last slot, so we need to empty it.
+ m_nearPeds[ARRAY_SIZE(m_nearPeds) - 1] = nil;
+ m_numNearPeds--;
+ } else
+ i++;
}
}
}
-void
-CPed::SetLookTimer(int time)
-{
- if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- m_lookTimer = CTimer::GetTimeInMilliseconds() + time;
- }
-}
-
bool
CPed::OurPedCanSeeThisOne(CEntity *target)
{
@@ -783,1198 +434,6 @@ CPed::OurPedCanSeeThisOne(CEntity *target)
return !CWorld::ProcessLineOfSight(headPos, target->GetPosition(), colpoint, ent, true, false, false, false, false, false);
}
-void
-CPed::Avoid(void)
-{
- CPed *nearestPed;
-
- if(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50)
- return;
-
- if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-
- if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
- nearestPed = m_nearPeds[0];
-
- if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) {
-
- // Check if this ped wants to avoid the nearest one
- if (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) {
-
- // Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters.
- // If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else.
-
- // Game converts from radians to degress and back again here, doesn't make much sense
- CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
- forward.Normalise(); // this is kinda pointless
-
- // Move forward 1.25 meters
- CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f;
-
- // Get distance to ped we want to avoid
- CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition;
-
- if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) {
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds()
- + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter())
- % 1000 / 5;
-
- m_fRotationDest += DEGTORAD(45.0f);
- if (!bIsLooking) {
- SetLookFlag(nearestPed, false);
- SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800));
- }
- }
- }
- }
- }
- }
-}
-
-void
-CPed::ClearAimFlag(void)
-{
- if (bIsAimingGun) {
- bIsAimingGun = false;
- bIsRestoringGun = true;
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
-#if defined VC_PED_PORTS || defined FIX_BUGS
- m_lookTimer = 0;
-#endif
- }
-
- if (IsPlayer())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
-}
-
-void
-CPed::ClearLookFlag(void) {
- if (bIsLooking) {
- bIsLooking = false;
- bIsRestoringLook = true;
- bShakeFist = false;
-
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- if (IsPlayer())
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000;
- else
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
-
- if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) {
- ClearLook();
- }
- }
-}
-
-bool
-CPed::IsPedHeadAbovePos(float zOffset)
-{
- return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z;
-}
-
-void
-CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
-{
- CWeaponInfo *currentWeapon;
- CAnimBlendAssociation *newAnim;
- CPed *ped = (CPed*)arg;
-
- 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);
- }
-
- newAnim->SetFinishCallback(FinishedAttackCB, ped);
- return;
-
- case ANIM_FIGHT_PPUNCH:
- attackAssoc->blendDelta = -8.0f;
- attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
- ped->ClearAttack();
- return;
-
- case ANIM_WEAPON_THROW:
- case ANIM_WEAPON_THROWU:
- if (ped->GetWeapon()->m_nAmmoTotal > 0) {
- currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
- ped->AddWeaponModel(currentWeapon->m_nModelId);
- }
- break;
- default:
- break;
- }
- }
-
- if (!ped->bIsAttacking)
- ped->ClearAttack();
-}
-
-void
-CPed::Attack(void)
-{
- CAnimBlendAssociation *weaponAnimAssoc;
- int32 weaponAnim;
- float animStart;
- eWeaponType ourWeaponType;
- float weaponAnimTime;
- eWeaponFire ourWeaponFire;
- float animLoopEnd;
- CWeaponInfo *ourWeapon;
- bool attackShouldContinue;
- AnimationId reloadAnim;
- CAnimBlendAssociation *reloadAnimAssoc;
- float delayBetweenAnimAndFire;
- CVector firePos;
-
- ourWeaponType = GetWeapon()->m_eWeaponType;
- ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
- ourWeaponFire = ourWeapon->m_eWeaponFire;
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
- attackShouldContinue = bIsAttacking;
- reloadAnimAssoc = nil;
- reloadAnim = NUM_ANIMS;
- 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 (reloadAnim != NUM_ANIMS)
- reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
-
- if (bIsDucking)
- return;
-
- if (reloadAnimAssoc) {
- if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)
- ClearAttack();
-
- return;
- }
-
- if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
- attackShouldContinue = true;
-
- 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 (!weaponAnimAssoc) {
- 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);
- }
-
- weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
- weaponAnimAssoc->SetRun();
-
- if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength)
- weaponAnimAssoc->SetCurrentTime(0.0f);
-
- if (IsPlayer()) {
- ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f;
- ((CPlayerPed*)this)->m_bHaveTargetSelected = false;
- }
- }
- } else
- FinishedAttackCB(nil, this);
-
- return;
- }
- }
-
- animStart = ourWeapon->m_fAnimLoopStart;
- weaponAnimTime = weaponAnimAssoc->currentTime;
- if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
- if (ourWeapon->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
- else
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
- }
-
- 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;
-
- firePos = GetMatrix() * firePos;
- } else if (ourWeaponType != WEAPONTYPE_UNARMED) {
- TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR);
- } else {
- firePos = GetMatrix() * firePos;
- }
-
- GetWeapon()->Fire(this, &firePos);
-
- if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) {
- 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;
- }
- } 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);
- }
-
- weaponAnimAssoc->speed = 0.5f;
-
- if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
- weaponAnimAssoc->callbackType = 0;
- }
- }
-
- attackShouldContinue = false;
- }
-
- if (ourWeaponType == WEAPONTYPE_SHOTGUN) {
- weaponAnimTime = weaponAnimAssoc->currentTime;
- firePos = ourWeapon->m_vecFireOffset;
-
- if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {
- TransformToNode(firePos, PED_HANDR);
-
- CVector gunshellPos(
- firePos.x - 0.6f * GetForward().x,
- firePos.y - 0.6f * GetForward().y,
- firePos.z - 0.15f * GetUp().z
- );
-
- CVector2D gunshellRot(
- GetRight().x,
- GetRight().y
- );
-
- gunshellRot.Normalise();
- GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);
- }
- }
-#ifdef VC_PED_PORTS
- 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) {
- 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);
- }
- } 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) {
- switch (ourWeaponType) {
- case WEAPONTYPE_UZI:
- 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;
- }
- }
-
- // 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;
-}
-
-void
-CPed::RemoveWeaponModel(int modelId)
-{
- // modelId is not used!! This function just removes the current weapon.
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- if(m_pWeaponModel){
- RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel);
- RpAtomicDestroy(m_pWeaponModel);
- RwFrameDestroy(frm);
- m_pWeaponModel = nil;
- }
- }else
-#endif
- RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil);
- m_wepModelID = -1;
-}
-
-void
-CPed::SetCurrentWeapon(uint32 weaponType)
-{
- CWeaponInfo *weaponInfo;
- if (HasWeapon(weaponType)) {
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(weaponInfo->m_nModelId);
-
- m_currentWeapon = weaponType;
-
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- AddWeaponModel(weaponInfo->m_nModelId);
- }
-}
-
-// 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++) {
- if (GetWeapon(i).m_nAmmoTotal > 0) {
- eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
- if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) {
- SetCurrentWeapon(i);
- return true;
- }
- }
- }
- SetCurrentWeapon(WEAPONTYPE_UNARMED);
- return false;
-}
-
-void
-CPed::Duck(void)
-{
- if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
- ClearDuck();
-}
-
-void
-CPed::ClearDuck(void)
-{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
-
- if (!animAssoc) {
- bIsDucking = false;
- return;
- }
- }
-
- if (!bCrouchWhenShooting)
- return;
-
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN)
- return;
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
- if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
- }
-}
-
-void
-CPed::ClearPointGunAt(void)
-{
- CAnimBlendAssociation *animAssoc;
- CWeaponInfo *weaponInfo;
-
- 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) {
- 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;
- }
-#ifndef VC_PED_PORTS
- }
-#endif
-}
-
-void
-CPed::BeingDraggedFromCar(void)
-{
- CAnimBlendAssociation *animAssoc;
- AnimationId enterAnim;
- bool dontRunAnim = false;
- PedLineUpPhase lineUpType;
-
- if (!m_pVehicleAnim) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO);
- }
- }
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
- if (bWillBeQuickJacked) {
- enterAnim = ANIM_CAR_QJACKED;
- } else if (m_pMyVehicle->bLowVehicle) {
- enterAnim = ANIM_CAR_LJACKED_LHS;
- } else {
- enterAnim = ANIM_CAR_JACKED_LHS;
- }
- } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
- if (m_pMyVehicle->bLowVehicle)
- enterAnim = ANIM_CAR_LJACKED_RHS;
- else
- enterAnim = ANIM_CAR_JACKED_RHS;
- } else
- dontRunAnim = true;
-
-
- if (!dontRunAnim)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim);
-
- m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
- lineUpType = LINE_UP_TO_CAR_START;
- } else if (m_pVehicleAnim->currentTime <= 1.4f) {
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- lineUpType = LINE_UP_TO_CAR_START;
- } else {
- lineUpType = LINE_UP_TO_CAR_2;
- }
-
- LineUpPedWithCar(lineUpType);
-#ifdef VC_PED_PORTS
- if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
- if (m_pMyVehicle) {
- m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f);
- }
- }
-#endif
-}
-
-void
-CPed::RestartNonPartialAnims(void)
-{
- CAnimBlendAssociation *assoc;
-
- for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
- if (!assoc->IsPartial())
- assoc->SetRun();
- }
-}
-
-void
-CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
-{
- CAnimBlendAssociation *quickJackedAssoc;
- CVehicle *vehicle;
- CPed *ped = (CPed*)arg;
-
- quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED);
- if (ped->m_nPedState != PED_ARRESTED) {
- ped->m_nLastPedState = PED_NONE;
- if (dragAssoc)
- dragAssoc->blendDelta = -1000.0f;
- }
- ped->RestartNonPartialAnims();
- ped->m_pVehicleAnim = nil;
- ped->m_pSeekTarget = nil;
- vehicle = ped->m_pMyVehicle;
-
- if (vehicle) {
- vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
-
- if (vehicle->pDriver == ped) {
- vehicle->RemoveDriver();
- if (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- vehicle->m_nDoorLock = CARLOCK_UNLOCKED;
-
- if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle())
- vehicle->ChangeLawEnforcerState(false);
- } else {
- vehicle->RemovePassenger(ped);
- }
- }
- ped->bInVehicle = false;
- if (ped->IsPlayer())
- AudioManager.PlayerJustLeftCar();
-
-#ifdef VC_PED_PORTS
- if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
- dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
- ped->m_fHealth = 0.0f;
- ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f);
- return;
- }
-#endif
-
- if (quickJackedAssoc) {
- dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped);
- } else {
- dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
- if (ped->CanSetPedState())
- CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
- }
-
- ped->ReplaceWeaponWhenExitingVehicle();
-
- ped->m_nStoredMoveState = PEDMOVE_NONE;
- ped->bVehExitWillBeInstant = false;
-}
-
-CVector
-CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult)
-{
- CVehicleModelInfo *vehModel;
- CVector vehDoorPos;
- CVector vehDoorOffset;
- float seatOffset;
-
- vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
- if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {
- seatOffset = 0.0f;
- vehDoorOffset = vecPedVanRearDoorAnimOffset;
- } else {
- seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult;
- if (veh->bLowVehicle) {
- vehDoorOffset = vecPedCarDoorLoAnimOffset;
- } else {
- vehDoorOffset = vecPedCarDoorAnimOffset;
- }
- }
-
- switch (component) {
- case CAR_DOOR_RF:
- vehDoorPos = vehModel->GetFrontSeatPosn();
- vehDoorPos.x += seatOffset;
- vehDoorOffset.x = -vehDoorOffset.x;
- break;
-
- case CAR_DOOR_RR:
- vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
- vehDoorPos.x += seatOffset;
- vehDoorOffset.x = -vehDoorOffset.x;
- break;
-
- case CAR_DOOR_LF:
- vehDoorPos = vehModel->GetFrontSeatPosn();
- vehDoorPos.x = -(vehDoorPos.x + seatOffset);
- break;
-
- case CAR_DOOR_LR:
- vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
- vehDoorPos.x = -(vehDoorPos.x + seatOffset);
- break;
-
- default:
- vehDoorPos = vehModel->GetFrontSeatPosn();
- vehDoorOffset = CVector(0.0f, 0.0f, 0.0f);
- }
- return vehDoorPos - vehDoorOffset;
-}
-
-// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it.
-CVector
-CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
-{
- CVector localPos;
- CVector vehDoorPos;
-
- localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f);
- vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition();
-
-/*
- // Not used.
- CVector localVehDoorOffset;
-
- if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) {
- localVehDoorOffset = vecPedVanRearDoorAnimOffset;
- } else {
- if (veh->bIsLow) {
- localVehDoorOffset = vecPedCarDoorLoAnimOffset;
- } else {
- localVehDoorOffset = vecPedCarDoorAnimOffset;
- }
- }
-
- vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition();
-*/
- return vehDoorPos;
-}
-
-CVector
-CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
-{
- CVector doorPos;
- CMatrix vehMat(veh->GetMatrix());
-
- doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));
-
- return veh->GetPosition() + doorPos;
-}
-
-void
-CPed::LineUpPedWithCar(PedLineUpPhase phase)
-{
- bool vehIsUpsideDown = false;
- int vehAnim;
- float seatPosMult = 0.0f;
- float currentZ;
- float adjustedTimeStep;
-
- if (CReplay::IsPlayingBack())
- return;
-
- if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) {
- SetPedPositionInCar();
- return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) {
- SetPedPositionInCar();
- return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) {
- SetPedPositionInCar();
- return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) {
- SetPedPositionInCar();
- return;
- }
- bChangedSeat = true;
- }
- if (phase == LINE_UP_TO_CAR_START) {
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- CVehicle *veh = m_pMyVehicle;
-
- // Not quite right, IsUpsideDown func. checks for <= -0.9f.
- if (veh->GetUp().z <= -0.8f)
- vehIsUpsideDown = true;
-
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
- if (vehIsUpsideDown) {
- m_fRotationDest = -PI + veh->GetForward().Heading();
- } else if (veh->bIsBus) {
- m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
- } else {
- m_fRotationDest = veh->GetForward().Heading();
- }
- } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
- if (vehIsUpsideDown) {
- m_fRotationDest = veh->GetForward().Heading();
- } else if (veh->bIsBus) {
- m_fRotationDest = -0.5f * PI + veh->GetForward().Heading();
- } else {
- m_fRotationDest = veh->GetForward().Heading();
- }
- } else {
- // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional.
-
- if (vehIsUpsideDown) {
- m_fRotationDest = veh->GetForward().Heading();
- } else if (veh->bIsBus) {
- m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
- } else {
- m_fRotationDest = veh->GetForward().Heading();
- }
- }
-
- if (!bInVehicle)
- seatPosMult = 1.0f;
-
-#ifdef VC_PED_PORTS
- bool multExtractedFromAnim = false;
- bool multExtractedFromAnimBus = false;
- float zBlend;
-#endif
- if (m_pVehicleAnim) {
- vehAnim = m_pVehicleAnim->animId;
-
- switch (vehAnim) {
- case ANIM_CAR_JACKED_RHS:
- case ANIM_CAR_LJACKED_RHS:
- case ANIM_CAR_JACKED_LHS:
- case ANIM_CAR_LJACKED_LHS:
- case ANIM_VAN_GETIN_L:
- 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);
- // fall through
-#endif
- case ANIM_CAR_QJACKED:
- case ANIM_CAR_GETOUT_LHS:
- case ANIM_CAR_GETOUT_LOW_LHS:
- case ANIM_CAR_GETOUT_RHS:
- case ANIM_CAR_GETOUT_LOW_RHS:
-#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);
- }
- // fall through
-#endif
- case ANIM_CAR_CRAWLOUT_RHS:
- case ANIM_CAR_CRAWLOUT_RHS2:
- case ANIM_VAN_GETOUT_L:
- case ANIM_VAN_GETOUT:
- seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength;
- 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;
- }
- // fall through
-#endif
- case ANIM_CAR_QJACK:
- case ANIM_CAR_GETIN_LOW_LHS:
- case ANIM_CAR_GETIN_LOW_RHS:
- case ANIM_DRIVE_BOAT:
- seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
- break;
- case ANIM_CAR_CLOSEDOOR_LHS:
- case ANIM_CAR_CLOSEDOOR_LOW_LHS:
- case ANIM_CAR_CLOSEDOOR_RHS:
- case ANIM_CAR_CLOSEDOOR_LOW_RHS:
- case ANIM_CAR_SHUFFLE_RHS:
- case ANIM_CAR_LSHUFFLE_RHS:
- seatPosMult = 0.0f;
- break;
- case ANIM_CAR_CLOSE_LHS:
- case ANIM_CAR_CLOSE_RHS:
- case ANIM_COACH_OPEN_L:
- case ANIM_COACH_OPEN_R:
- case ANIM_COACH_IN_L:
- case ANIM_COACH_IN_R:
- case ANIM_COACH_OUT_L:
- seatPosMult = 1.0f;
- break;
- default:
- break;
- }
- }
-
- CVector neededPos;
-
- if (phase == LINE_UP_TO_CAR_2) {
- neededPos = GetPosition();
- } else {
- neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult);
- }
-
- CVector autoZPos = neededPos;
-
- if (veh->bIsInWater) {
- if (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown())
- autoZPos.z += 1.0f;
- } else {
- CPedPlacement::FindZCoorForPed(&autoZPos);
- }
-
- if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) {
- neededPos.z = GetPosition().z;
-
- // Getting out
- if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) {
- float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep();
-
- // If we're not in ground at next step, apply animation
- if (neededPos.z + nextZSpeed >= autoZPos.z) {
- m_vecMoveSpeed.z = nextZSpeed;
- ApplyMoveSpeed();
- // Removing below line breaks the animation
- neededPos.z = GetPosition().z;
- } else {
- neededPos.z = autoZPos.z;
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- if (autoZPos.z > neededPos.z) {
-#ifdef VC_PED_PORTS
- if (multExtractedFromAnim) {
- neededPos.z += (autoZPos.z - neededPos.z) * zBlend;
- } else {
-#endif
- currentZ = GetPosition().z;
- if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) {
- neededPos.z = autoZPos.z;
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) {
- adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
-
- // Smoothly change ped position
- neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep);
- }
-#ifdef VC_PED_PORTS
- }
-#endif
- } else {
- // We may need to raise up the ped
- if (phase == LINE_UP_TO_CAR_START) {
- currentZ = GetPosition().z;
-
- if (neededPos.z > currentZ) {
-#ifdef VC_PED_PORTS
- if (multExtractedFromAnimBus) {
- neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ;
- } else {
-#endif
- if (m_pVehicleAnim &&
- (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS
- || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) {
- adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
-
- // Smoothly change ped position
- neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;
- } else if (EnteringCar()) {
- neededPos.z = Max(currentZ, autoZPos.z);
- }
-#ifdef VC_PED_PORTS
- }
-#endif
- }
- }
- }
-
- bool stillGettingInOut = false;
- if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)
- stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat;
-
- if (!stillGettingInOut) {
- m_fRotationCur = m_fRotationDest;
- } else {
- float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f;
-
- if (timeUntilStateChange <= 0.0f) {
- m_vecOffsetSeek.x = 0.0f;
- m_vecOffsetSeek.y = 0.0f;
- }
- m_vecOffsetSeek.z = 0.0f;
-
- neededPos -= timeUntilStateChange * m_vecOffsetSeek;
-
- if (PI + m_fRotationCur < limitedDest) {
- limitedDest -= 2 * PI;
- } else if (m_fRotationCur - PI > limitedDest) {
- limitedDest += 2 * PI;
- }
- m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange);
- }
-
- if (seatPosMult > 0.2f || vehIsUpsideDown) {
- SetPosition(neededPos);
- SetHeading(m_fRotationCur);
- } else {
- CMatrix vehDoorMat(veh->GetMatrix());
- vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f));
- // VC couch anims are inverted, so they're fixing it here.
- GetMatrix() = vehDoorMat;
- }
-
-}
-
-static void
-particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times)
-{
- switch (ped->m_nSurfaceTouched)
- {
- case SURFACE_TARMAC:
- case SURFACE_GRAVEL:
- case SURFACE_PAVEMENT:
- case SURFACE_SAND:
- for (int i = 0; i < times; ++i) {
- CVector adjustedPos = pos;
- adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0);
- }
- break;
- default:
- break;
- }
-}
-
-static void
-particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times)
-{
-#ifdef PC_PARTICLE
- for (int i = 0; i < times; i++) {
- CVector adjustedPos = pos;
- adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
-
- CVector direction = ped->GetForward() * -0.05f;
- CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
- }
-#else
- for ( int32 i = 0; i < times; i++ )
- {
- CVector adjustedPos = pos;
- adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
- adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
-
- CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
- }
-#endif
-}
-
-void
-CPed::PlayFootSteps(void)
-{
- if (bDoBloodyFootprints) {
- if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) {
- m_bloodyFootprintCountOrDeathTime--;
-
- if (m_bloodyFootprintCountOrDeathTime == 0)
- bDoBloodyFootprints = false;
- }
- }
-
- if (!bIsStanding)
- return;
-
- CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump());
- CAnimBlendAssociation *walkRunAssoc = nil;
- float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f;
-
- for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
- if (assoc->flags & ASSOC_WALK) {
- walkRunAssoc = assoc;
- walkRunAssocBlend += assoc->blendAmount;
- } else if ((assoc->flags & ASSOC_NOWALK) == 0) {
- idleAssocBlend += assoc->blendAmount;
- }
- }
-
-#ifdef GTA_PS2_STUFF
- CAnimBlendAssociation *runStopAsoc = NULL;
-
- if ( IsPlayer() )
- {
- runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
-
- if ( runStopAsoc == NULL )
- runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
- }
-
- if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f )
- {
- {
- CVector pos(0.0f, 0.0f, 0.0f);
- TransformToNode(pos, PED_FOOTL);
-
- pos.z -= 0.1f;
- pos += GetForward()*0.2f;
- particleProduceFootDust(this, pos, 0.02f, 1);
- }
-
- {
- CVector pos(0.0f, 0.0f, 0.0f);
- TransformToNode(pos, PED_FOOTR);
-
- pos.z -= 0.1f;
- pos += GetForward()*0.2f;
- particleProduceFootDust(this, pos, 0.02f, 1);
- }
- }
-#endif
-
-
- if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) {
- float stepStart = 1 / 15.0f;
- float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart;
- float currentTime = walkRunAssoc->currentTime;
- int stepPart = 0;
-
- if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart)
- stepPart = 1;
- else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd)
- stepPart = 2;
-
- if (stepPart != 0) {
- DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f);
- CVector footPos(0.0f, 0.0f, 0.0f);
- TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR);
-
- CVector forward = GetForward();
-
- footPos.z -= 0.1f;
- footPos += 0.2f * forward;
-
- if (bDoBloodyFootprints) {
- CVector2D top(forward * 0.26f);
- CVector2D right(GetRight() * 0.14f);
-
- CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos,
- top.x, top.y,
- right.x, right.y,
- 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f);
-
- if (m_bloodyFootprintCountOrDeathTime <= 20) {
- m_bloodyFootprintCountOrDeathTime = 0;
- bDoBloodyFootprints = false;
- } else {
- m_bloodyFootprintCountOrDeathTime -= 20;
- }
- }
- if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) {
- if(IsPlayer())
- particleProduceFootDust(this, footPos, 0.0f, 4);
- }
-#ifdef PC_PARTICLE
- else if(stepPart == 2)
-#else
- else
-#endif
- {
- particleProduceFootSplash(this, footPos, 0.15f, 4);
- }
- }
- }
-
- if (m_nSurfaceTouched == SURFACE_WATER) {
- float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude();
- if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) {
-#ifdef PC_PARTICLE
- float particleSize = pedSpeed * 2.0f;
-
- if (particleSize < 0.25f)
- particleSize = 0.25f;
-
- if (particleSize > 0.75f)
- particleSize = 0.75f;
-
- CVector particlePos = GetPosition() + GetForward() * 0.3f;
- particlePos.z -= 1.2f;
-
- CVector particleDir = m_vecMoveSpeed * -0.75f;
-
- particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f);
- CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0);
-
- particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0);
-#else
- CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f;
- CVector particleDir = m_vecMoveSpeed * 0.45f;
- particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
- CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255));
-#endif
- }
- }
-}
-
-bool
-CPed::IsPointerValid(void)
-{
- int pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8;
- if (pedIndex < 0 || pedIndex >= NUMPEDS)
- return false;
-
- if (m_entryInfoList.first || FindPlayerPed() == this)
- return true;
-
- return false;
-}
-
// Some kind of binary sort
void
CPed::SortPeds(CPed **list, int min, int max)
@@ -1987,8 +446,8 @@ CPed::SortPeds(CPed **list, int min, int max)
float middleDist = middleDiff.Magnitude();
int left = max;
- int right;
- for(right = min; right <= left; ){
+ int right = min;
+ while(right <= left){
float rightDist, leftDist;
do {
rightDiff = GetPosition() - list[right]->GetPosition();
@@ -2013,1477 +472,141 @@ CPed::SortPeds(CPed **list, int min, int max)
}
void
-CPed::BuildPedLists(void)
-{
- if ((CTimer::GetFrameCounter() + m_randomSeed) % 16) {
-
- for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) {
- bool removePed = false;
- if (m_nearPeds[i]) {
- if (m_nearPeds[i]->IsPointerValid()) {
- float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D();
- if (distSqr > 900.0f)
- removePed = true;
- } else
- removePed = true;
- }
- if (removePed) {
- // If we arrive here, the ped we're checking isn't "near", so we should remove it.
- for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) {
- m_nearPeds[j] = m_nearPeds[j + 1];
- m_nearPeds[j + 1] = nil;
- }
- // Above loop won't work when it's 9, so we need to empty slot 9.
- m_nearPeds[9] = nil;
- m_numNearPeds--;
- } else
- i++;
- }
- } else {
- CVector centre = CEntity::GetBoundCentre();
- CRect rect(centre.x - 20.0f,
- centre.y - 20.0f,
- centre.x + 20.0f,
- centre.y + 20.0f);
- int xstart = CWorld::GetSectorIndexX(rect.left);
- int ystart = CWorld::GetSectorIndexY(rect.top);
- int xend = CWorld::GetSectorIndexX(rect.right);
- int yend = CWorld::GetSectorIndexY(rect.bottom);
- gnNumTempPedList = 0;
-
- for(int y = ystart; y <= yend; y++) {
- for(int x = xstart; x <= xend; x++) {
- for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) {
- CPed *ped = (CPed*)pedPtrNode->item;
- if (ped != this && !ped->bInVehicle) {
- float dist = (ped->GetPosition() - GetPosition()).Magnitude2D();
- if (nThreatReactionRangeMultiplier * 30.0f > dist) {
- gapTempPedList[gnNumTempPedList] = ped;
- gnNumTempPedList++;
- assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList));
- }
- }
- }
- }
- }
- gapTempPedList[gnNumTempPedList] = nil;
- SortPeds(gapTempPedList, 0, gnNumTempPedList - 1);
- for (m_numNearPeds = 0; m_numNearPeds < ARRAY_SIZE(m_nearPeds); m_numNearPeds++) {
- CPed *ped = gapTempPedList[m_numNearPeds];
- if (!ped)
- break;
-
- m_nearPeds[m_numNearPeds] = ped;
- }
- for (int pedToClear = m_numNearPeds; pedToClear < ARRAY_SIZE(m_nearPeds); pedToClear++)
- m_nearPeds[pedToClear] = nil;
- }
-}
-
-void
-CPed::SetPedStats(ePedStats pedStat)
-{
- m_pedStats = CPedStats::ms_apPedStats[pedStat];
-}
-
-void
-CPed::SetModelIndex(uint32 mi)
-{
- CEntity::SetModelIndex(mi);
- RpAnimBlendClumpInit(GetClump());
- RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames);
- CPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
- SetPedStats(modelInfo->m_pedStatType);
- m_headingRate = m_pedStats->m_headingChangeRate;
- m_animGroup = (AssocGroupId) modelInfo->m_animGroup;
- CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE);
-
- // 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());
-#endif
-}
-
-void
-CPed::RemoveLighting(bool reset)
-{
- CRenderer::RemoveVehiclePedLights(this, reset);
-}
-
-bool
-CPed::SetupLighting(void)
-{
- ActivateDirectional();
- SetAmbientColoursForPedsCarsAndObjects();
-
-#ifndef MASTER
- // Originally this was being called through iteration of Sectors, but putting it here is better.
- if (GetDebugDisplay() != 0 && !IsPlayer())
- DebugRenderOnePedText();
-#endif
-
- if (bRenderScorched) {
- WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
- } else {
- // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0.
- float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition());
- if (!bHasBlip && lightMult != 1.0f) {
- SetAmbientAndDirectionalColours(lightMult);
- return true;
- }
- }
- return false;
-}
-
-void
-CPed::Teleport(CVector pos)
-{
- CWorld::Remove(this);
- SetPosition(pos);
- bIsStanding = false;
- m_nPedStateTimer = 0;
- m_actionX = 0.0f;
- m_actionY = 0.0f;
- m_pDamageEntity = nil;
- CWorld::Add(this);
-}
-
-void
-CPed::CalculateNewOrientation(void)
-{
- if (CReplay::IsPlayingBack() || !IsPedInControl())
- return;
-
- SetHeading(m_fRotationCur);
-}
-
-float
-CPed::WorkOutHeadingForMovingFirstPerson(float offset)
-{
- if (!IsPlayer())
- return 0.0f;
-
- CPad *pad0 = CPad::GetPad(0);
- float leftRight = pad0->GetPedWalkLeftRight();
- float upDown = pad0->GetPedWalkUpDown();
- float &angle = ((CPlayerPed*)this)->m_fWalkAngle;
-
- if (upDown != 0.0f) {
- angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
- } else {
- if (leftRight < 0.0f)
- angle = 0.5f * PI;
- else if (leftRight > 0.0f)
- angle = -0.5f * PI;
- }
-
- return CGeneral::LimitRadianAngle(offset + angle);
-}
-
-void
-CPed::CalculateNewVelocity(void)
-{
- if (IsPedInControl()) {
- float headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep();
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- float limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest);
-
- if (m_fRotationCur - PI > limitedRotDest) {
- limitedRotDest += 2 * PI;
- } else if(PI + m_fRotationCur < limitedRotDest) {
- limitedRotDest -= 2 * PI;
- }
-
- if (IsPlayer() && m_nPedState == PED_ATTACK)
- headAmount /= 4.0f;
-
- float neededTurn = limitedRotDest - m_fRotationCur;
- if (neededTurn <= headAmount) {
- if (neededTurn > (-headAmount))
- m_fRotationCur += neededTurn;
- else
- m_fRotationCur -= headAmount;
- } else {
- m_fRotationCur += headAmount;
- }
- }
-
- CVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur));
-
- m_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y;
- m_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward); // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur));
-
- if (CTimer::GetTimeStep() >= 0.01f) {
- m_moved = m_moved * (1 / CTimer::GetTimeStep());
- } else {
- m_moved = m_moved * (1 / 100.0f);
- }
-
- if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam())
- || FindPlayerPed() != this || !CanStrafeOrMouseControl())
- return;
-
- float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur);
- float pedSpeed = m_moved.Magnitude();
- float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur);
-
- if (localWalkAngle < -0.5f * PI) {
- localWalkAngle += PI;
- } else if (localWalkAngle > 0.5f * PI) {
- localWalkAngle -= PI;
- }
-
- // Interestingly this part is responsible for diagonal walking.
- if (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) {
- TheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed;
- m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed;
- }
-
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
-#ifdef VC_PED_PORTS
- if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) {
-#else
- if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
-#endif
- LimbOrientation newUpperLegs;
- newUpperLegs.yaw = localWalkAngle;
-
- if (newUpperLegs.yaw < -DEGTORAD(100.0f)) {
- newUpperLegs.yaw += PI;
- } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) {
- newUpperLegs.yaw -= PI;
- }
-
- 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);
- }
- }
- }
-}
-
-bool
-CPed::CanBeDeleted(void)
-{
- if (bInVehicle)
- return false;
-
- switch (CharCreatedBy) {
- case RANDOM_CHAR:
- return true;
- case MISSION_CHAR:
- return false;
- default:
- return true;
- }
-}
-
-bool
-CPed::CanPedDriveOff(void)
-{
- if (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds())
- return false;
-
- for (int i = 0; i < m_numNearPeds; i++) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) {
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 1000;
- return false;
- }
- }
- return true;
-}
-
-#ifdef VC_PED_PORTS
-bool
-CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil)
-{
- if (m_nSurfaceTouched == SURFACE_WATER)
- return true;
-
- CVector pos = GetPosition();
- CVector forwardOffset = GetForward();
- if (damageNormal && damageNormal->z > 0.17f) {
- if (damageNormal->z > 0.9f)
- return false;
-
- CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
- pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z;
- pos.z = pos.z + 0.05f;
- float collPower = damageNormal->Magnitude2D();
- if (damageNormal->z <= 0.5f) {
- forwardOffset += collPower * ourCol->spheres->radius * forwardOffset;
- } else {
- CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f);
- invDamageNormal *= 1.0f / collPower;
- CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius;
- forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f);
- }
- } else {
- pos.z -= 0.15f;
- }
-
- CVector forwardPos = pos + forwardOffset;
- return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
-}
-#else
-bool
-CPed::CanPedJumpThis(CEntity *unused)
-{
- CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
- CVector pos = GetPosition();
- CVector forwardPos(
- forward.x + pos.x,
- forward.y + pos.y,
- pos.z);
-
- return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
-}
-#endif
-
-bool
-CPed::CanPedReturnToState(void)
-{
- return m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK &&
- m_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY;
-}
-
-bool
-CPed::CanSeeEntity(CEntity *entity, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD)
-{
- float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
- entity->GetPosition().x,
- entity->GetPosition().y,
- GetPosition().x,
- GetPosition().y);
-
- if (neededAngle < 0.0f)
- neededAngle += TWOPI;
- else if (neededAngle > TWOPI)
- neededAngle -= TWOPI;
-
- float ourAngle = m_fRotationCur;
- if (ourAngle < 0.0f)
- ourAngle += TWOPI;
- else if (ourAngle > TWOPI)
- ourAngle -= TWOPI;
-
- float neededTurn = Abs(neededAngle - ourAngle);
-
- return neededTurn < threshold || TWOPI - threshold < neededTurn;
-}
-
-bool
-CPed::IsTemporaryObjective(eObjective objective)
-{
- return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER ||
-#ifdef VC_PED_PORTS
- objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||
-#endif
- objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER;
-}
-
-void
CPed::SetMoveState(eMoveState state)
{
m_nMoveState = state;
}
void
-CPed::SetObjectiveTimer(int time)
-{
- if (time == 0) {
- m_objectiveTimer = 0;
- } else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
- m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;
- }
-}
-
-void
-CPed::ForceStoredObjective(eObjective objective)
-{
- if (objective != OBJECTIVE_ENTER_CAR_AS_DRIVER && objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- m_prevObjective = m_objective;
- return;
- }
-
- switch (m_objective)
- {
- case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
- return;
- default:
- m_prevObjective = m_objective;
- }
-}
-
-void
-CPed::SetStoredObjective(void)
-{
- if (m_objective == m_prevObjective)
- return;
-
- switch (m_objective)
- {
- case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
- case OBJECTIVE_LEAVE_CAR:
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
- return;
- default:
- m_prevObjective = m_objective;
- }
-}
-
-void
-CPed::RestorePreviousObjective(void)
-{
- if (m_objective == OBJECTIVE_NONE)
- return;
-
- if (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER
-#if defined VC_PED_PORTS || defined FIX_BUGS
- && m_nPedState != PED_CARJACK
-#endif
- )
- m_pedInObjective = nil;
-
- if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {
- m_objective = OBJECTIVE_NONE;
- if (m_pMyVehicle)
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
-
- } else {
- m_objective = m_prevObjective;
- m_prevObjective = OBJECTIVE_NONE;
- }
- bObjectiveCompleted = false;
-}
-
-void
-CPed::SetLeader(CEntity *leader)
-{
- m_leader = (CPed*)leader;
-
- if(m_leader)
- m_leader->RegisterReference((CEntity **)&m_leader);
-}
-
-void
-CPed::SetObjective(eObjective newObj, void *entity)
-{
- if (DyingOrDead())
- return;
-
- if (m_prevObjective == newObj) {
- // Why?
- if (m_prevObjective != OBJECTIVE_NONE)
- return;
- }
-
- if (entity == this)
- return;
-
- SetObjectiveTimer(0);
- if (m_objective == newObj) {
- switch (newObj) {
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- case OBJECTIVE_GUARD_ATTACK:
- if (m_pedInObjective == entity)
- return;
-
- break;
- case OBJECTIVE_LEAVE_CAR:
- case OBJECTIVE_FLEE_CAR:
-#ifdef VC_PED_PORTS
- case OBJECTIVE_LEAVE_CAR_AND_DIE:
-#endif
- return;
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- case OBJECTIVE_DESTROY_CAR:
- case OBJECTIVE_SOLICIT_VEHICLE:
- case OBJECTIVE_BUY_ICE_CREAM:
- if (m_carInObjective == entity)
- return;
-
- break;
- case OBJECTIVE_SET_LEADER:
- if (m_leader == entity)
- return;
-
- break;
- default:
- break;
- }
- } else {
- if ((newObj == OBJECTIVE_LEAVE_CAR
-#ifdef VC_PED_PORTS
- || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE
-#endif
- ) && !bInVehicle)
- return;
- }
-
-#ifdef VC_PED_PORTS
- ClearPointGunAt();
-#endif
- bObjectiveCompleted = false;
- if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) {
- if (m_objective != newObj) {
- if (IsTemporaryObjective(newObj))
- ForceStoredObjective(newObj);
- else
- SetStoredObjective();
- }
- m_objective = newObj;
- } else {
- m_prevObjective = newObj;
- }
-
- switch (newObj) {
- case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
-
- // In this special case, entity parameter isn't CEntity, but int.
- SetObjectiveTimer((uintptr)entity);
- break;
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_MUG_CHAR:
- m_pNextPathNode = nil;
- bUsePedNodeSeek = false;
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- m_pedInObjective = (CPed*)entity;
- m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
- m_pLookTarget = (CEntity*)entity;
- m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
- break;
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- case OBJECTIVE_GUARD_ATTACK:
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- m_pedInObjective = (CPed*)entity;
- m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
- break;
- case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
- m_pedInObjective = (CPed*)entity;
- m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
- m_pedFormation = FORMATION_REAR;
- break;
- case OBJECTIVE_LEAVE_CAR:
-#ifdef VC_PED_PORTS
- case OBJECTIVE_LEAVE_CAR_AND_DIE:
-#endif
- case OBJECTIVE_FLEE_CAR:
- m_carInObjective = (CVehicle*)entity;
- m_carInObjective->RegisterReference((CEntity **)&m_carInObjective);
- if (!m_carInObjective->bIsBus || m_leaveCarTimer)
- break;
-
- for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) {
- if (m_carInObjective->pPassengers[i] == this) {
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i;
- break;
- }
- }
-
- break;
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- if (m_nMoveState == PEDMOVE_STILL)
- SetMoveState(PEDMOVE_RUN);
-
- if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) {
- RestorePreviousObjective();
- break;
- }
- // fall through
- case OBJECTIVE_DESTROY_CAR:
- case OBJECTIVE_SOLICIT_VEHICLE:
- case OBJECTIVE_BUY_ICE_CREAM:
- m_carInObjective = (CVehicle*)entity;
- m_carInObjective->RegisterReference((CEntity**)&m_carInObjective);
- m_pSeekTarget = m_carInObjective;
- m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- if (newObj == OBJECTIVE_SOLICIT_VEHICLE) {
- m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
- } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR &&
- (m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) {
- SetObjectiveTimer(14000);
- } else {
- m_objectiveTimer = 0;
- }
- break;
- case OBJECTIVE_SET_LEADER:
- SetLeader((CEntity*)entity);
- RestorePreviousObjective();
- break;
- default:
- break;
- }
-}
-
-void
-CPed::SetIdle(void)
-{
- if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {
-#ifdef VC_PED_PORTS
- if (m_nPedState == PED_AIM_GUN)
- ClearPointGunAt();
-
- m_nLastPedState = PED_NONE;
-#endif
- m_nPedState = PED_IDLE;
- SetMoveState(PEDMOVE_STILL);
- }
- if (m_nWaitState == WAITSTATE_FALSE) {
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000);
- }
-}
-
-void
-CPed::SetObjective(eObjective newObj)
-{
- if (DyingOrDead())
- return;
-
- if (newObj == OBJECTIVE_NONE) {
- if ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER
-#ifdef VC_PED_PORTS
- || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
- && !IsPlayer()
-#else
- )
-#endif
- && !IsPedInControl()) {
-
- bStartWanderPathOnFoot = true;
- return;
- }
- // Unused code from assembly...
- /*
- else if(m_objective == OBJECTIVE_FLEE_CAR) {
-
- } else {
-
- }
- */
- m_objective = OBJECTIVE_NONE;
- m_prevObjective = OBJECTIVE_NONE;
- } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) {
- SetObjectiveTimer(0);
-
- if (m_objective == newObj)
- return;
-
- if (IsTemporaryObjective(m_objective)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj)
- SetStoredObjective();
-
- m_objective = newObj;
- }
- bObjectiveCompleted = false;
-
- switch (newObj) {
- case OBJECTIVE_NONE:
- m_prevObjective = OBJECTIVE_NONE;
- break;
- case OBJECTIVE_HAIL_TAXI:
- m_nWaitTimer = 0;
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
- break;
- default:
- break;
- }
- }
-}
-
-// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode
-// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call...
-void
-CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)
+CPed::SetMoveAnim(void)
{
- if (DyingOrDead())
- return;
-
- if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)
+ if (m_nStoredMoveState == m_nMoveState || !IsPedInControl())
return;
- SetObjectiveTimer(0);
-
- if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
+ if (m_nMoveState == PEDMOVE_NONE) {
+ m_nStoredMoveState = PEDMOVE_NONE;
return;
-
- bObjectiveCompleted = false;
- if (IsTemporaryObjective(m_objective)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj)
- SetStoredObjective();
-
- m_objective = newObj;
}
- if (newObj == OBJECTIVE_FOLLOW_ROUTE) {
- SetFollowRoute(routePoint, routeType);
- }
-}
-
-void
-CPed::ClearChat(void)
-{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- bIsTalking = false;
- ClearLookFlag();
- RestorePreviousState();
-}
-
-bool
-CPed::IsGangMember(void)
-{
- return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9;
-}
-
-void
-CPed::InformMyGangOfAttack(CEntity *attacker)
-{
- CPed *attackerPed;
-
- if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)
- return;
-
- if (attacker->IsPed()) {
- attackerPed = (CPed*)attacker;
- } else {
- if (!attacker->IsVehicle())
- return;
+ AssocGroupId animGroupToUse;
+ if (m_leader && m_leader->IsPlayer())
+ animGroupToUse = ASSOCGRP_PLAYER;
+ else
+ animGroupToUse = m_animGroup;
- attackerPed = ((CVehicle*)attacker)->pDriver;
- if (!attackerPed)
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK);
+ if (!animAssoc) {
+ CAnimBlendAssociation *fightIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+ animAssoc = fightIdleAssoc;
+ if (fightIdleAssoc && m_nPedState == PED_FIGHT)
return;
- }
-
- if (attackerPed->m_nPedType == PEDTYPE_COP)
- return;
- for (int i = 0; i < m_numNearPeds; i++) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed && nearPed != this) {
- CPed *leader = nearPed->m_leader;
- if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper)
- {
- nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed);
- nearPed->SetObjectiveTimer(30000);
+ if (fightIdleAssoc) {
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 8.0f);
}
}
}
-}
-
-void
-CPed::QuitEnteringCar(void)
-{
- CAnimBlendAssociation *animAssoc = m_pVehicleAnim;
- CVehicle *veh = m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- RestartNonPartialAnims();
-
- if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE))
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
-
- if (veh) {
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
- veh->bIsBeingCarJacked = false;
-
- if (veh->m_nNumGettingIn != 0)
- veh->m_nNumGettingIn--;
-
-#ifdef VC_PED_PORTS
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
- RestorePreviousObjective();
-#endif
-
- veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType);
- }
-
- bUsesCollision = true;
-
- ReplaceWeaponWhenExitingVehicle();
-
- if (DyingOrDead()) {
- animAssoc = m_pVehicleAnim;
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->flags &= ~ASSOC_RUNNING;
- }
- } else
- SetIdle();
-
- m_pVehicleAnim = nil;
-
- if (veh) {
-#ifdef VC_PED_PORTS
- if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE)
-#else
- if (veh->AutoPilot.m_nCruiseSpeed == 0)
-#endif
- veh->AutoPilot.m_nCruiseSpeed = 17;
- }
-}
-
-void
-CPed::ReactToAttack(CEntity *attacker)
-{
- if (IsPlayer() && attacker->IsPed()) {
- InformMyGangOfAttack(attacker);
- SetLookFlag(attacker, true);
- SetLookTimer(700);
- return;
- }
-
-#ifdef VC_PED_PORTS
- if (m_nPedState == PED_DRIVING && InVehicle()
- && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) {
-
- if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE
- && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS)
- && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) {
-
- CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
- m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- }
- } else
-#endif
- if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {
- CPed *ourLeader = m_leader;
- if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader)
- && attacker->IsPed()) {
-
- CPed *attackerPed = (CPed*)attacker;
- if (bNotAllowedToDuck) {
- if (!attackerPed->GetWeapon()->IsTypeMelee()) {
- m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds();
- return;
- }
- } else if (bCrouchWhenShooting || bKindaStayInSamePlace) {
- SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000));
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
+ if (animAssoc)
+ if (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE)
return;
- }
- if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) {
- if (m_pedStats != attackerPed->m_pedStats) {
- if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
- RegisterThreatWithGangPeds(attackerPed);
- }
- if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker);
- SetMoveState(PEDMOVE_RUN);
- } else {
- SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);
- SetObjectiveTimer(20000);
- }
- }
- } else {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed);
- SetMoveState(PEDMOVE_RUN);
- if (attackerPed->GetWeapon()->IsTypeMelee())
- Say(SOUND_PED_FLEE_RUN);
+ if (animAssoc) {
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
}
}
}
-}
-
-bool
-CPed::TurnBody(void)
-{
- float lookDir;
- bool turnDone = true;
-
- if (m_pLookTarget) {
- const CVector &lookPos = m_pLookTarget->GetPosition();
-
- lookDir = CGeneral::GetRadianAngleBetweenPoints(
- lookPos.x,
- lookPos.y,
- GetPosition().x,
- GetPosition().y);
- } else
- lookDir = m_fLookDirection;
-
- float limitedLookDir = CGeneral::LimitRadianAngle(lookDir);
- float currentRot = m_fRotationCur;
-
- if (currentRot - PI > limitedLookDir)
- limitedLookDir += 2 * PI;
- else if (PI + currentRot < limitedLookDir)
- limitedLookDir -= 2 * PI;
-
- float neededTurn = currentRot - limitedLookDir;
- m_fRotationDest = limitedLookDir;
-
- if (Abs(neededTurn) > 0.05f) {
- turnDone = false;
- currentRot -= neededTurn * 0.2f;
- }
-
- m_fRotationCur = currentRot;
- m_fLookDirection = limitedLookDir;
- return turnDone;
-}
-
-void
-CPed::Chat(void)
-{
- // We're already looking to our partner
- if (bIsLooking && TurnBody())
- ClearLookFlag();
-
- if (!m_pLookTarget || !m_pLookTarget->IsPed()) {
- ClearChat();
- return;
- }
-
- CPed *partner = (CPed*) m_pLookTarget;
+ if (!animAssoc) {
+ m_nStoredMoveState = m_nMoveState;
+ if (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) {
+ for (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);
+ assoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) {
- if (partner->m_nPedState != PED_CHAT) {
- ClearChat();
- if (partner->m_pedInObjective) {
- if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||
- partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)
- ReactToAttack(partner->m_pedInObjective);
- }
- return;
- }
- if (bIsTalking) {
- if (CGeneral::GetRandomNumber() < 512) {
- CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (chatAssoc) {
- chatAssoc->blendDelta = -4.0f;
- chatAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) {
+ assoc->blendDelta = -2.0f;
+ assoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
}
- bIsTalking = false;
- } else
- Say(SOUND_PED_CHAT);
-
- } else if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG_XPRESS)) {
-
- if (CGeneral::GetRandomNumber() < 20) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
- }
- if (!bIsTalking) {
- CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
- float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);
- chatAssoc->SetCurrentTime(chatTime);
- bIsTalking = true;
- Say(SOUND_PED_CHAT);
- }
- }
- if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
- ClearChat();
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
- }
-}
-
-void
-CPed::CheckAroundForPossibleCollisions(void)
-{
- CVector ourCentre, objCentre;
- CEntity *objects[8];
- int16 maxObject;
-
- if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)
- return;
-
- GetBoundCentre(ourCentre);
-
- CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false);
- for (int i = 0; i < maxObject; i++) {
- CEntity *object = objects[i];
- if (bRunningToPhone) {
- if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition()))
- break;
- }
- object->GetBoundCentre(objCentre);
- float radius = object->GetBoundRadius();
- if (radius > 4.5f || radius < 1.0f)
- radius = 1.0f;
-
- // Developers gave up calculating Z diff. later according to asm.
- float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D();
-
- if (sq(radius + 1.0f) > diff)
- m_fRotationDest += DEGTORAD(22.5f);
- }
-}
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-void
-ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
- ped->m_nMoveState = PEDMOVE_STILL;
- CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f);
-
- if (assoc->blendAmount > 0.5f && ped) {
- CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f);
- }
-}
-
-void
-ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg)
-{
- assoc->flags |= ASSOC_DELETEFADEDOUT;
- assoc->blendDelta = -1000.0f;
- CPed* ped = (CPed*)arg;
-
- if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) {
- crimeReporters[ped->m_phoneId] = nil;
- gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE;
- ped->m_phoneId = -1;
- }
-
- if (assoc->blendAmount > 0.5f)
- ped->bUpdateAnimHeading = true;
-
- ped->SetWanderPath(CGeneral::GetRandomNumber() & 7);
-}
-#endif
-
-bool
-CPed::MakePhonecall(void)
-{
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) {
-
- FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(),
- (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false);
-
- if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN)
- FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1);
-
- bRunningToPhone = false;
- }
-#endif
- if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer)
- return false;
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK);
- if (talkAssoc && talkAssoc->blendAmount > 0.5f) {
- CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f);
- endAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
- endAssoc->SetFinishCallback(ReportPhonePutDownCB, this);
- }
-#endif
- SetIdle();
-
- gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE;
-#ifndef PEDS_REPORT_CRIMES_ON_PHONE
- m_phoneId = -1;
-#endif
-
- // Because SetWanderPath is now done async in ReportPhonePutDownCB
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- return false;
-#else
- return true;
-#endif
-}
-
-bool
-CPed::FacePhone(void)
-{
- // This function was broken since it's left unused early in development.
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
- gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
- GetPosition().x, GetPosition().y);
-
- if (m_facePhoneStart) {
- m_lookTimer = 0;
- SetLookFlag(phoneDir, true);
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
- m_facePhoneStart = false;
- }
-
- if (bIsLooking && TurnBody()) {
- ClearLookFlag();
- SetIdle();
- m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
- CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f);
- assoc->SetFinishCallback(ReportPhonePickUpCB, this);
- return true;
- }
-
- return false;
-#else
- float currentRot = RADTODEG(m_fRotationCur);
- float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
- gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x,
- gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
- GetPosition().x,
- GetPosition().y);
-
- SetLookFlag(phoneDir, false);
- phoneDir = CGeneral::LimitAngle(phoneDir);
- m_moved = CVector2D(0.0f, 0.0f);
-
- if (currentRot - 180.0f > phoneDir)
- phoneDir += 2 * 180.0f;
- else if (180.0f + currentRot < phoneDir)
- phoneDir -= 2 * 180.0f;
-
- float neededTurn = currentRot - phoneDir;
-
- if (Abs(neededTurn) <= 0.75f) {
- SetIdle();
- ClearLookFlag();
- m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
- return true;
- } else {
- m_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f);
- return false;
- }
-#endif
-}
-
-CPed *
-CPed::CheckForDeadPeds(void)
-{
- int event;
- if (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) {
- int pedHandle = gaEvent[event].entityRef;
- if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) {
- bGonnaInvestigateEvent = true;
- return CPools::GetPed(pedHandle);
- }
- }
- bGonnaInvestigateEvent = false;
- return nil;
-}
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-// returns event id, parameter is optional
-int32
-CPed::CheckForPlayerCrimes(CPed *victim)
-{
- int i;
- float dist;
- float mindist = 60.0f;
- CPlayerPed *player = FindPlayerPed();
- int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0);
- int event = -1;
-
- for (i = 0; i < NUMEVENTS; i++) {
- if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE)
- continue;
-
- // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc.
- if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION)
- continue;
-
- if (victim && gaEvent[i].entityRef != victimRef)
- continue;
-
- if (gaEvent[i].criminal != player)
- continue;
-
- dist = (GetPosition() - gaEvent[i].posn).Magnitude();
- if (dist < mindist) {
- mindist = dist;
- event = i;
+ ClearAimFlag();
+ ClearLookFlag();
}
- }
- if (event != -1) {
- if (victim) {
- m_victimOfPlayerCrime = victim;
- } else {
- switch (gaEvent[event].entityType) {
- case EVENT_ENTITY_PED:
- m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef);
- break;
- case EVENT_ENTITY_VEHICLE:
- m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef);
- break;
- case EVENT_ENTITY_OBJECT:
- m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef);
- break;
- default:
+ switch (m_nMoveState) {
+ case PEDMOVE_STILL:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
break;
- }
- }
- }
-
- return event;
-}
-#endif
-
-bool
-CPed::CheckForExplosions(CVector2D &area)
-{
- int event = 0;
- if (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) {
- area.x = gaEvent[event].posn.x;
- area.y = gaEvent[event].posn.y;
- CEntity *actualEntity = nil;
-
- switch (gaEvent[event].entityType) {
- case EVENT_ENTITY_PED:
- actualEntity = CPools::GetPed(gaEvent[event].entityRef);
+ case PEDMOVE_WALK:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_WALK, 1.0f);
break;
- case EVENT_ENTITY_VEHICLE:
- actualEntity = CPools::GetVehicle(gaEvent[event].entityRef);
+ case PEDMOVE_RUN:
+ if (m_nPedState == PED_FLEE_ENTITY) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 3.0f);
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 1.0f);
+ }
break;
- case EVENT_ENTITY_OBJECT:
- actualEntity = CPools::GetObject(gaEvent[event].entityRef);
+ case PEDMOVE_SPRINT:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_SPRINT, 1.0f);
break;
default:
break;
}
- if (actualEntity) {
- m_pEventEntity = actualEntity;
- m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
- bGonnaInvestigateEvent = true;
- } else
- bGonnaInvestigateEvent = false;
-
- CEventList::ClearEvent(event);
- return true;
- } else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) {
- area.x = gaEvent[event].posn.x;
- area.y = gaEvent[event].posn.y;
- CEventList::ClearEvent(event);
- bGonnaInvestigateEvent = false;
- return true;
- }
-
- bGonnaInvestigateEvent = false;
- return false;
-}
-
-CPed *
-CPed::CheckForGunShots(void)
-{
- int event;
- if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) {
- if (gaEvent[event].entityType == EVENT_ENTITY_PED) {
- // Probably due to we don't want peds to go gunshot area? (same on VC)
- bGonnaInvestigateEvent = false;
- return CPools::GetPed(gaEvent[event].entityRef);
- }
- }
- bGonnaInvestigateEvent = false;
- return nil;
-}
-
-PointBlankNecessity
-CPed::CheckForPointBlankPeds(CPed *pedToVerify)
-{
- float pbDistance = 1.1f;
- if (GetWeapon()->IsType2Handed())
- pbDistance = 1.6f;
-
- for (int i = 0; i < m_numNearPeds; i++) {
- CPed *nearPed = m_nearPeds[i];
-
- if (!pedToVerify || pedToVerify == nearPed) {
-
- CVector diff = nearPed->GetPosition() - GetPosition();
- if (diff.Magnitude() < pbDistance) {
-
- float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
- nearPed->GetPosition().x, nearPed->GetPosition().y,
- GetPosition().x, GetPosition().y);
- neededAngle = CGeneral::LimitRadianAngle(neededAngle);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- float neededTurn = Abs(neededAngle - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = 2*PI - neededTurn;
+ if (animAssoc) {
+ if (m_leader) {
+ CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_WALK);
+ if (!walkAssoc)
+ walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_RUN);
- if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY)
- return NO_POINT_BLANK_PED;
+ if (!walkAssoc)
+ walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_SPRINT);
- if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {
- if (pedToVerify == nearPed)
- return POINT_BLANK_FOR_WANTED_PED;
+ if (walkAssoc) {
+ animAssoc->speed = walkAssoc->speed;
+ } else {
+ if (CharCreatedBy == MISSION_CHAR)
+ animAssoc->speed = 1.0f;
else
- return POINT_BLANK_FOR_SOMEONE_ELSE;
+ animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
+
}
+ } else {
+ if (CharCreatedBy == MISSION_CHAR)
+ animAssoc->speed = 1.0f;
+ else
+ animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
}
}
}
- return NO_POINT_BLANK_PED;
-}
-
-bool
-CPed::CheckIfInTheAir(void)
-{
- if (bInVehicle)
- return false;
-
- CVector pos = GetPosition();
- CColPoint foundColPoint;
- CEntity *foundEntity;
-
- float startZ = pos.z - 1.54f;
- bool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil);
- if (!foundGround && m_nPedState != PED_JUMP)
- {
- pos.z -= FEET_OFFSET;
- if (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false))
- foundGround = true;
- }
- return !foundGround;
-}
-
-void
-CPed::ClearAll(void)
-{
- if (!IsPedInControl() && m_nPedState != PED_DEAD)
- return;
-
- m_nPedState = PED_NONE;
- m_nMoveState = PEDMOVE_NONE;
- m_pSeekTarget = nil;
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- m_fleeFromPosX = 0.0f;
- m_fleeFromPosY = 0.0f;
- m_fleeFrom = nil;
- m_fleeTimer = 0;
- bUsesCollision = true;
-#ifdef VC_PED_PORTS
- ClearPointGunAt();
-#else
- ClearAimFlag();
- ClearLookFlag();
-#endif
- bIsPointingGunAt = false;
- bRenderPedInCar = true;
- bKnockedUpIntoAir = false;
- m_pCollidingEntity = nil;
}
void
-CPed::ClearAttack(void)
-{
- if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
- return;
-
-#ifdef VC_PED_PORTS
- // VC uses CCamera::Using1stPersonWeaponMode
- if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
- TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) {
- SetPointGunAt(nil);
- } else
-#endif
- if (bIsPointingGunAt) {
- if (m_pLookTarget)
- SetPointGunAt(m_pLookTarget);
- else
- ClearPointGunAt();
- } else if (m_objective != OBJECTIVE_NONE) {
- SetIdle();
- } else {
- RestorePreviousState();
- }
-}
-
-void
-CPed::ClearAttackByRemovingAnim(void)
+CPed::StopNonPartialAnims(void)
{
- if (m_nPedState != PED_ATTACK || bIsDucking)
- 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 *assoc;
- if (!weaponAssoc) {
- ClearAttack();
- return;
- }
+ for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
+ if (!assoc->IsPartial())
+ assoc->flags &= ~ASSOC_RUNNING;
}
- weaponAssoc->blendDelta = -8.0f;
- weaponAssoc->flags &= ~ASSOC_RUNNING;
- weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
- weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
}
void
-CPed::StopNonPartialAnims(void)
+CPed::RestartNonPartialAnims(void)
{
CAnimBlendAssociation *assoc;
for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
if (!assoc->IsPartial())
- assoc->flags &= ~ASSOC_RUNNING;
+ assoc->SetRun();
}
}
@@ -3509,775 +632,6 @@ CPed::SetStoredState(void)
}
void
-CPed::SetDie(AnimationId animId, float delta, float speed)
-{
- CPlayerPed *player = FindPlayerPed();
- if (player == this) {
- if (!player->m_bCanBeDamaged)
- return;
- }
-
- m_threatEntity = nil;
- if (DyingOrDead())
- return;
-
- if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP)
- delta *= 0.5f;
-
- SetStoredState();
- ClearAll();
- m_fHealth = 0.0f;
- if (m_nPedState == PED_DRIVING) {
- if (!IsPlayer())
- FlagToDestroyWhenNextProcessed();
- } else if (bInVehicle) {
- if (m_pVehicleAnim)
- m_pVehicleAnim->blendDelta = -1000.0f;
- } else if (EnteringCar()) {
- QuitEnteringCar();
- }
-
- m_nPedState = PED_DIE;
- if (animId == NUM_ANIMS) {
- bIsPedDieAnimPlaying = false;
- } else {
- CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta);
- if (speed > 0.0f)
- dieAssoc->speed = speed;
-
- dieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- if (dieAssoc->IsRunning()) {
- dieAssoc->SetFinishCallback(FinishDieAnimCB, this);
- bIsPedDieAnimPlaying = true;
- }
- }
-
- Say(SOUND_PED_DEATH);
- if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK)
- QuitEnteringCar();
- if (!bInVehicle)
- StopNonPartialAnims();
-
- m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
-}
-
-bool
-CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)
-{
- CPlayerPed *player = FindPlayerPed();
- float dieDelta = 4.0f;
- float dieSpeed = 0.0f;
- AnimationId dieAnim = ANIM_KO_SHOT_FRONT1;
- bool headShot = false;
- bool willLinger = false;
- int random;
-
- if (player == this) {
- if (!player->m_bCanBeDamaged)
- return false;
-
- player->AnnoyPlayerPed(false);
- }
-
- if (DyingOrDead())
- return false;
-
- if (!bUsesCollision && method != WEAPONTYPE_DROWNING)
- return false;
-
- if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() &&
- method != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION)
- return false;
-
- float healthImpact;
- if (IsPlayer())
- healthImpact = damage * 0.33f;
- else
- healthImpact = damage * m_pedStats->m_defendWeakness;
-
- bool detectDieAnim = true;
- if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) {
- if (!IsPedHeadAbovePos(-0.3f)) {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_FLOOR_HIT_F;
- else
- dieAnim = ANIM_FLOOR_HIT;
- dieDelta *= 2.0f;
- dieSpeed = 0.5f;
- detectDieAnim = false;
- } else if (m_nPedState == PED_FALL) {
- dieAnim = NUM_ANIMS;
- detectDieAnim = false;
- }
- }
- if (detectDieAnim) {
- switch (method) {
- case WEAPONTYPE_UNARMED:
- if (bMeleeProof)
- return false;
-
- if (m_nPedState == PED_FALL) {
- if (IsPedHeadAbovePos(-0.3f)) {
- dieAnim = NUM_ANIMS;
- } else {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_FLOOR_HIT_F;
- else
- dieAnim = ANIM_FLOOR_HIT;
- dieDelta = dieDelta * 2.0f;
- dieSpeed = 0.5f;
- }
- } else {
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- }
- break;
- case WEAPONTYPE_BASEBALLBAT:
- if (bMeleeProof)
- return false;
-
- if (m_nPedState == PED_FALL) {
- if (IsPedHeadAbovePos(-0.3f)) {
- dieAnim = NUM_ANIMS;
- } else {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_FLOOR_HIT_F;
- else
- dieAnim = ANIM_FLOOR_HIT;
- dieDelta = dieDelta * 2.0f;
- dieSpeed = 0.5f;
- }
- } else {
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- }
- break;
- case WEAPONTYPE_COLT45:
- case WEAPONTYPE_UZI:
- case WEAPONTYPE_SHOTGUN:
- case WEAPONTYPE_AK47:
- case WEAPONTYPE_M16:
- case WEAPONTYPE_SNIPERRIFLE:
- if (bBulletProof)
- return false;
-
- bool dontRemoveLimb;
- if (IsPlayer() || bNoCriticalHits)
- dontRemoveLimb = true;
- else {
- switch (method) {
- case WEAPONTYPE_SNIPERRIFLE:
- dontRemoveLimb = false;
- break;
- case WEAPONTYPE_M16:
- dontRemoveLimb = false;
- break;
- case WEAPONTYPE_SHOTGUN:
- dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
- break;
- default:
- dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
- break;
- }
- }
-
- if (dontRemoveLimb) {
- if (method == WEAPONTYPE_SHOTGUN) {
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- } else
- dieAnim = ANIM_KO_SHOT_FRONT1;
-
- willLinger = false;
- } else {
- switch (pedPiece) {
- case PEDPIECE_TORSO:
- willLinger = false;
- dieAnim = ANIM_KO_SHOT_FRONT1;
- break;
- case PEDPIECE_MID:
- willLinger = false;
- dieAnim = ANIM_KO_SHOT_STOM;
- break;
- case PEDPIECE_LEFTARM:
- dieAnim = ANIM_KO_SHOT_ARML;
- RemoveBodyPart(PED_UPPERARML, direction);
- willLinger = true;
- break;
- case PEDPIECE_RIGHTARM:
- dieAnim = ANIM_KO_SHOT_ARMR;
- RemoveBodyPart(PED_UPPERARMR, direction);
- willLinger = true;
- break;
- case PEDPIECE_LEFTLEG:
- dieAnim = ANIM_KO_SHOT_LEGL;
- RemoveBodyPart(PED_UPPERLEGL, direction);
- willLinger = true;
- break;
- case PEDPIECE_RIGHTLEG:
- dieAnim = ANIM_KO_SHOT_LEGR;
- RemoveBodyPart(PED_UPPERLEGR, direction);
- willLinger = true;
- break;
- case PEDPIECE_HEAD:
- dieAnim = ANIM_KO_SHOT_FACE;
- RemoveBodyPart(PED_HEAD, direction);
- headShot = true;
- willLinger = true;
- break;
- default:
- break;
- }
- }
- break;
- case WEAPONTYPE_ROCKETLAUNCHER:
- case WEAPONTYPE_GRENADE:
- case WEAPONTYPE_EXPLOSION:
- if (bExplosionProof)
- return false;
-
- if (CGame::nastyGame && !IsPlayer() && !bInVehicle &&
- 1.0f + healthImpact > m_fArmour + m_fHealth) {
-
- random = CGeneral::GetRandomNumber();
- if (random & 1)
- RemoveBodyPart(PED_UPPERARML, direction);
- if (random & 2)
- RemoveBodyPart(PED_UPPERLEGR, direction);
- if (random & 4)
- RemoveBodyPart(PED_HEAD, direction);
- if (random & 8)
- RemoveBodyPart(PED_UPPERARMR, direction);
- if (random & 0x10)
- RemoveBodyPart(PED_UPPERLEGL, direction);
- if (bBodyPartJustCameOff)
- willLinger = true;
- }
- // fall through
- case WEAPONTYPE_MOLOTOV:
- if (bExplosionProof)
- return false;
-
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- break;
- case WEAPONTYPE_FLAMETHROWER:
- if (bFireProof)
- return false;
-
- dieAnim = ANIM_KO_SHOT_FRONT1;
- break;
- case WEAPONTYPE_RAMMEDBYCAR:
- case WEAPONTYPE_RUNOVERBYCAR:
- if (bCollisionProof)
- return false;
-
- random = CGeneral::GetRandomNumber() & 3;
- switch (random) {
- case 0:
- if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
- && (pedPiece != PEDPIECE_MID || random != 1)) {
- if (pedPiece == PEDPIECE_RIGHTARM && random > 1
- || pedPiece == PEDPIECE_MID && random == 2)
-
- dieAnim = ANIM_KO_SPIN_L;
- else
- dieAnim = ANIM_KO_SKID_FRONT;
- } else
- dieAnim = ANIM_KO_SPIN_R;
-
- break;
- case 1:
- if (m_nPedState == PED_DIVE_AWAY)
- dieAnim = ANIM_KD_LEFT;
- else
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
- && (pedPiece != PEDPIECE_MID || random != 1)) {
- if ((pedPiece != PEDPIECE_RIGHTARM || random <= 1)
- && (pedPiece != PEDPIECE_MID || random != 2)) {
- dieAnim = ANIM_KO_SKID_BACK;
- } else {
- dieAnim = ANIM_KD_RIGHT;
- }
- } else
- dieAnim = ANIM_KD_LEFT;
- break;
- case 3:
- if (m_nPedState == PED_DIVE_AWAY)
- dieAnim = ANIM_KD_RIGHT;
- else
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- if (damagedBy) {
- CVehicle *vehicle = (CVehicle*)damagedBy;
- if (method == WEAPONTYPE_RAMMEDBYCAR) {
- float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
- dieDelta = 8.0f * vehSpeed + 4.0f;
- } else {
- float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
- dieDelta = 12.0f * vehSpeed + 4.0f;
- dieSpeed = 16.0f * vehSpeed + 1.0f;
- }
- }
- break;
- case WEAPONTYPE_DROWNING:
- dieAnim = ANIM_DROWN;
- break;
- case WEAPONTYPE_FALL:
- if (bCollisionProof)
- return false;
-
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
-
- if (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) {
- if (player == this)
- CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds();
-
- if (healthImpact < m_fArmour) {
- m_fArmour = m_fArmour - healthImpact;
- healthImpact = 0.0f;
- } else {
- healthImpact = healthImpact - m_fArmour;
- m_fArmour = 0.0f;
- }
- }
-
- if (healthImpact != 0.0f) {
- if (player == this)
- CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds();
-
- m_lastWepDam = method;
- }
-
- if (m_fHealth - healthImpact >= 1.0f && !willLinger) {
- m_fHealth -= healthImpact;
- return false;
- }
-
- if (bInVehicle) {
- if (method != WEAPONTYPE_DROWNING) {
-#ifdef VC_PED_PORTS
- if (m_pMyVehicle) {
- if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) {
- if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
- }
- m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
- m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
- }
- if (m_pMyVehicle->CanPedExitCar()) {
- SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
- } else {
- m_fHealth = 0.0f;
- if (m_pMyVehicle && m_pMyVehicle->pDriver == this) {
- SetRadioStation();
- m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- }
- SetDie(dieAnim, dieDelta, dieSpeed);
- /*
- if (damagedBy == FindPlayerPed() && damagedBy != this) {
- // PlayerInfo stuff
- }
- */
- }
- for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) {
- CPed* passenger = m_pMyVehicle->pPassengers[i];
- if (passenger && passenger != this && damagedBy)
- passenger->ReactToAttack(damagedBy);
- }
-
- CPed *driverOfVeh = m_pMyVehicle->pDriver;
- if (driverOfVeh && driverOfVeh != this && damagedBy)
- driverOfVeh->ReactToAttack(damagedBy);
-
- if (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) {
- CDarkel::RegisterKillByPlayer(this, method, headShot);
- m_threatEntity = FindPlayerPed();
- } else {
- CDarkel::RegisterKillNotByPlayer(this, method);
- }
- }
-#endif
- m_fHealth = 1.0f;
- return false;
- }
- m_fHealth = 0.0f;
- if (player == this)
- m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED);
-
- SetDie(NUM_ANIMS, 4.0f, 0.0f);
- return true;
- } else {
- m_fHealth = 0.0f;
- SetDie(dieAnim, dieDelta, dieSpeed);
-
- if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) {
-
- // There are PlayerInfo stuff here in VC
- CDarkel::RegisterKillByPlayer(this, method, headShot);
- m_threatEntity = player;
- } else {
- CDarkel::RegisterKillNotByPlayer(this, method);
- }
- if (method == WEAPONTYPE_DROWNING)
- bIsInTheAir = false;
-
- return true;
- }
-}
-
-void
-CPed::ClearFlee(void)
-{
- RestorePreviousState();
- bUsePedNodeSeek = false;
- m_standardTimer = 0;
- m_fleeTimer = 0;
-}
-
-void
-CPed::ClearFall(void)
-{
- SetGetUp();
-}
-
-void
-CPed::SetGetUp(void)
-{
- if (m_nPedState == PED_GETUP && bGetUpAnimStarted)
- return;
-
- if (!CanSetPedState())
- return;
-
- if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) {
- if (bUpdateAnimHeading) {
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- m_fRotationCur -= HALFPI;
- bUpdateAnimHeading = false;
- }
- if (m_nPedState != PED_GETUP) {
- SetStoredState();
- m_nPedState = PED_GETUP;
- }
-
- CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity;
- CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition());
- 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(),
- aTempPedColPts, nil, nil) > 0)) {
-
- bGetUpAnimStarted = false;
- if (IsPlayer())
- InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
- else {
- if (!CPad::GetPad(0)->ArePlayerControlsDisabled())
- return;
-
- InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0);
- }
- return;
- }
- bGetUpAnimStarted = true;
- m_pCollidingEntity = nil;
- bKnockedUpIntoAir = false;
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
- if (animAssoc) {
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f);
- } else {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- }
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f);
- else
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
-
- animAssoc->SetFinishCallback(PedGetupCB,this);
- } else {
- m_fHealth = 0.0f;
- SetDie(NUM_ANIMS, 4.0f, 0.0f);
- }
-}
-
-void
-CPed::ClearInvestigateEvent(void)
-{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- if (m_eventType > EVENT_EXPLOSION)
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 15000;
-
- bGonnaInvestigateEvent = false;
- m_pEventEntity = nil;
- ClearLookFlag();
- RestorePreviousState();
- if(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)
- SetMoveState(PEDMOVE_WALK);
-}
-
-void
-CPed::ClearLeader(void)
-{
- if (!m_leader)
- return;
-
- m_leader = nil;
- if (IsPedInControl()) {
- SetObjective(OBJECTIVE_NONE);
- if (CharCreatedBy == MISSION_CHAR) {
- SetIdle();
- } else {
- SetWanderPath(CGeneral::GetRandomNumberInRange(0,8));
- }
- } else if (m_objective != OBJECTIVE_NONE) {
- bClearObjective = true;
- }
-}
-
-void
-CPed::ClearLook(void)
-{
- RestorePreviousState();
- ClearLookFlag();
-}
-
-void
-CPed::ClearObjective(void)
-{
- if (IsPedInControl() || m_nPedState == PED_DRIVING) {
- m_objective = OBJECTIVE_NONE;
-#ifdef VC_PED_PORTS
- m_pedInObjective = nil;
- m_carInObjective = nil;
-#endif
- if (m_nPedState == PED_DRIVING && m_pMyVehicle) {
-
- if (m_pMyVehicle->pDriver != this) {
-#if defined VC_PED_PORTS || defined FIX_BUGS
- if(!IsPlayer())
-#endif
- bWanderPathAfterExitingCar = true;
-
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- }
-#ifdef VC_PED_PORTS
- m_nLastPedState = PED_NONE;
-#endif
- } else {
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
- }
- } else {
- bClearObjective = true;
- }
-}
-
-void
-CPed::ClearPause(void)
-{
- RestorePreviousState();
-}
-
-void
-CPed::ClearSeek(void)
-{
- SetIdle();
- bRunningToPhone = false;
-}
-
-bool
-CPed::SetWanderPath(int8 pathStateDest)
-{
- uint8 nextPathState;
-
- if (IsPedInControl()) {
- if (bKindaStayInSamePlace) {
- SetIdle();
- return false;
- } else {
- m_nPathDir = pathStateDest;
- if (pathStateDest == 0)
- pathStateDest = CGeneral::GetRandomNumberInRange(1, 7);
-
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &nextPathState);
-
- // Circular loop until we find a node for current m_nPathDir
- while (!m_pNextPathNode) {
- m_nPathDir = (m_nPathDir+1) % 8;
-
- // We're at where we started and couldn't find any node
- if (m_nPathDir == pathStateDest) {
- ClearAll();
- SetIdle();
- return false;
- }
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &nextPathState);
- }
-
- // We did it, save next path state and return true
- m_nPathDir = nextPathState;
- m_nPedState = PED_WANDER_PATH;
- SetMoveState(PEDMOVE_WALK);
- bIsRunning = false;
- return true;
- }
- } else {
- m_nPathDir = pathStateDest;
- bStartWanderPathOnFoot = true;
- return false;
- }
-}
-
-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;
- }
-}
-
-void
-CPed::RestoreGunPosition(void)
-{
- if (bIsLooking) {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- bIsRestoringGun = false;
- } else if (m_pedIK.RestoreGunPosn()) {
- bIsRestoringGun = false;
- } else {
- if (IsPlayer())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
- }
-}
-
-void
-CPed::RestoreHeadingRate(void)
-{
- m_headingRate = m_pedStats->m_headingChangeRate;
-}
-
-void
-CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg)
-{
- ((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate;
-}
-
-void
CPed::RestorePreviousState(void)
{
if(!CanSetPedState() || m_nPedState == PED_FALL)
@@ -4326,4791 +680,1007 @@ CPed::RestorePreviousState(void)
}
}
-void
-CPed::SetAimFlag(CEntity *to)
-{
- bIsAimingGun = true;
- bIsRestoringGun = false;
- m_pLookTarget = to;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- m_pSeekTarget = to;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- m_lookTimer = 0;
-}
-
-void
-CPed::SetAimFlag(float angle)
-{
- bIsAimingGun = true;
- bIsRestoringGun = false;
- m_fLookDirection = angle;
- m_lookTimer = 0;
- m_pLookTarget = nil;
- m_pSeekTarget = nil;
- if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
- else
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
-}
-
-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)
- return;
-
- if (m_nPedState != PED_ATTACK)
- SetStoredState();
-
- 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 (!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);
-
- aimAssoc->blendAmount = 0.0f;
- aimAssoc->blendDelta = 8.0f;
- }
- if (to)
- Say(SOUND_PED_ATTACK);
-}
-
-void
-CPed::SetAmmo(eWeaponType weaponType, uint32 ammo)
-{
- if (HasWeapon(weaponType)) {
- GetWeapon(weaponType).m_nAmmoTotal = ammo;
- } else {
- GetWeapon(weaponType).Initialise(weaponType, ammo);
- m_maxWeaponTypeAllowed++;
- }
-}
-
-void
-CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo)
-{
- if (HasWeapon(weaponType)) {
- GetWeapon(weaponType).m_nAmmoTotal += ammo;
- } else {
- GetWeapon(weaponType).Initialise(weaponType, ammo);
- m_maxWeaponTypeAllowed++;
- }
-}
-
-void
-CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
-{
- AnimationId stepAnim;
-
- if (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0))
- return;
-
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- reason->GetPosition().x, reason->GetPosition().y,
- GetPosition().x, GetPosition().y);
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- float neededTurn = Abs(angleToFace - m_fRotationCur);
- bool vehPressedHorn = false;
-
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- CVehicle *veh = (CVehicle*)reason;
- if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) {
- if (veh->m_nCarHornTimer != 0) {
- vehPressedHorn = true;
- if (!IsPlayer())
- animType = 1;
- }
- }
- if (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) {
- SetLookFlag(veh, true);
- if ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) {
- stepAnim = ANIM_IDLE_TAXI;
- } else {
-
- float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
- veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
- 0.0f, 0.0f);
-
- // Let's turn our back to the "reason"
- angleToFace += PI;
-
- if (angleToFace > PI)
- angleToFace -= TWOPI;
-
- // We don't want to run towards car's direction
- float dangerZone = angleToFace - vehDirection;
- dangerZone = CGeneral::LimitRadianAngle(dangerZone);
-
- // So, add or subtract 90deg (jump to left/right) according to that
- if (dangerZone <= 0.0f)
- angleToFace = HALFPI + vehDirection;
- else
- angleToFace = vehDirection - HALFPI;
-
- stepAnim = NUM_ANIMS;
- if (animType == 0 || animType == 1)
- stepAnim = ANIM_EV_STEP;
- else if (animType == 2)
- stepAnim = ANIM_HANDSCOWER;
- }
- if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) {
- CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f);
- stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
- stepAssoc->SetFinishCallback(PedEvadeCB, this);
-
- if (animType == 0)
- Say(SOUND_PED_EVADE);
-
- m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace);
- ClearAimFlag();
- SetStoredState();
- m_nPedState = PED_STEP_AWAY;
- }
- }
-}
-
-void
-CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)
-{
- if (!IsPedInControl() || !bRespondsToThreats)
- return;
-
- CAnimBlendAssociation *animAssoc;
- float angleToFace, neededTurn;
- bool handsUp = false;
-
- angleToFace = m_fRotationCur;
- CVehicle *veh = (CVehicle*) reason;
- if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) {
- onlyRandomJump = true;
- }
-
- if (onlyRandomJump) {
- if (reason) {
- // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly.
- // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots.
-
- float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
- veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
- 0.0f, 0.0f);
- angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection;
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- }
- } else {
- if (IsPlayer()) {
- ((CPlayerPed*)this)->m_nEvadeAmount = 5;
- ((CPlayerPed*)this)->m_pEvadingFrom = reason;
- reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom);
- return;
- }
-
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- reason->GetPosition().x, reason->GetPosition().y,
- GetPosition().x, GetPosition().y);
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted
-#ifdef FIX_BUGS
- float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
- veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
- 0.0f, 0.0f);
-
- // Let's turn our back to the "reason"
- angleToFace += PI;
-
- if (angleToFace > PI)
- angleToFace -= 2 * PI;
-
- // We don't want to dive towards car's direction
- float dangerZone = angleToFace - vehDirection;
- dangerZone = CGeneral::LimitRadianAngle(dangerZone);
-
- // So, add or subtract 90deg (jump to left/right) according to that
- if (dangerZone > 0.0f)
- angleToFace = 0.5f * PI + vehDirection;
- else
- angleToFace = vehDirection - 0.5f * PI;
-#endif
-
- neededTurn = Abs(angleToFace - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = 2 * PI - neededTurn;
-
- if (neededTurn <= 0.5f*PI) {
- if (CGeneral::GetRandomNumber() & 1)
- handsUp = true;
- } else {
- if (CGeneral::GetRandomNumber() & 7)
- return;
- }
- Say(SOUND_PED_EVADE);
- }
-
- if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) {
- m_fRotationCur = angleToFace;
- ClearLookFlag();
- ClearAimFlag();
- SetLookFlag(reason, true);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP);
- if (animAssoc)
- return;
-
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f);
- animAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
- animAssoc->SetFinishCallback(PedEvadeCB, this);
- SetStoredState();
- m_nPedState = PED_STEP_AWAY;
- } else {
- m_fRotationCur = angleToFace;
- ClearLookFlag();
- ClearAimFlag();
- SetStoredState();
- m_nPedState = PED_DIVE_AWAY;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f);
- animAssoc->SetFinishCallback(PedEvadeCB, this);
- }
-
- if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) {
- if (veh->pDriver && veh->pDriver->IsPlayer()) {
- CWanted *wanted = FindPlayerPed()->m_pWanted;
- wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
- wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false);
- }
- }
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- else if (reason->IsVehicle()) {
- if (veh->pDriver && veh->pDriver->IsPlayer()) {
- CWanted* wanted = FindPlayerPed()->m_pWanted;
- wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
- }
- }
-#endif
-}
-
-void
-CPed::SetAttack(CEntity *victim)
+uint32
+CPed::ScanForThreats(void)
{
- CPed *victimPed = nil;
- 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;
- return;
- }
-
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) {
- if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)
- bIsAttacking = false;
- else
- bIsAttacking = true;
-
- 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) {
- if (IsPlayer() ||
- (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
-
- if (m_nPedState != PED_ATTACK) {
- m_nPedState = PED_ATTACK;
- bIsAttacking = false;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
- animAssoc->SetRun();
- if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
- animAssoc->SetCurrentTime(0.0f);
-
- animAssoc->SetFinishCallback(FinishedAttackCB, this);
- }
- } else {
- StartFightAttack(CGeneral::GetRandomNumber() % 256);
- }
- return;
+ int fearFlags = m_fearFlags;
+ CVector ourPos = GetPosition();
+ float closestPedDist = 60.0f;
+ CVector2D explosionPos = GetPosition();
+ if (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) {
+ m_eventOrThreat = explosionPos;
+ return PED_FLAG_EXPLOSION;
}
-
- 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();
- CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
- if (obstacle)
- return;
-
- m_pLookTarget = victim;
- if (victim) {
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+
+ CPed *shooter = nil;
+ if ((fearFlags & PED_FLAG_GUN) && (shooter = CheckForGunShots()) && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) {
+ if (!IsGangMember()) {
+ m_threatEntity = shooter;
+ m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
+ return PED_FLAG_GUN;
}
- if (m_pLookTarget) {
- SetAimFlag(m_pLookTarget);
- } else {
- SetAimFlag(m_fRotationCur);
- if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
- }
- }
- if (m_nPedState == PED_ATTACK) {
- bIsAttacking = true;
- return;
- }
-
- if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
- if (IsPlayer())
- CPad::GetPad(0)->ResetAverageWeapon();
-
- PointBlankNecessity pointBlankStatus;
- if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER)
- && 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
- && (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) {
- ClearAimFlag();
-
- // This condition is pointless
- if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed)
- StartFightAttack(200);
- } else {
- if (!curWeapon->m_bCanAim)
- m_pSeekTarget = nil;
-
- if (m_nPedState != PED_AIM_GUN)
- SetStoredState();
-
- m_nPedState = PED_ATTACK;
- SetMoveState(PEDMOVE_NONE);
- if (bCrouchWhenShooting) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.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);
- } else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
- }
- }
-
- animAssoc->SetRun();
- if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
- animAssoc->SetCurrentTime(0.0f);
-
- animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags) {
+ m_threatEntity = shooter;
+ m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
+ return CPedType::GetFlag(shooter->m_nPedType);
}
- return;
- }
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
- SetWaitState(WAITSTATE_SURPRISE, nil);
-
- SetLookFlag(victim, false);
- SetLookTimer(100);
-}
-
-void
-CPed::StartFightAttack(uint8 buttonPressure)
-{
- if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds())
- return;
-
- if (m_nPedState == PED_FIGHT) {
- m_fightButtonPressure = buttonPressure;
- return;
- }
-
- if (m_nPedState != PED_AIM_GUN)
- SetStoredState();
-
- if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
- }
-
- m_nPedState = PED_FIGHT;
- m_fightButtonPressure = 0;
- RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
-
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -1000.0f;
}
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
-
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -1000.0f;
- RestoreHeadingRate();
- }
-
- SetMoveState(PEDMOVE_NONE);
- m_nStoredMoveState = PEDMOVE_NONE;
-
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
-
- CPed *pedOnGround = nil;
- if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) {
- m_curFightMove = FIGHTMOVE_GROUNDKICK;
- } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) {
- m_curFightMove = FIGHTMOVE_ROUNDHOUSE;
+ CPed *deadPed = nil;
+ if (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR
+ && (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)) {
+ m_pEventEntity = deadPed;
+ m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
+ return PED_FLAG_DEADPEDS;
} else {
- m_curFightMove = FIGHTMOVE_STDPUNCH;
- }
-
- if (pedOnGround && IsPlayer()) {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- pedOnGround->GetPosition().x, pedOnGround->GetPosition().y,
- GetPosition().x, GetPosition().y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(pedOnGround, true);
- SetLookTimer(1500);
- }
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightState = FIGHTSTATE_NO_MOVE;
- m_takeAStepAfterAttack = false;
- bIsAttacking = true;
-
- if (IsPlayer())
- nPlayerInComboMove = 0;
-}
-
-void
-CPed::LoadFightData(void)
-{
- float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
- int damage, flags;
- char line[256], moveName[32], animName[32], hitLevel;
- int moveId = 0;
-
- CAnimBlendAssociation *animAssoc;
-
- size_t bp, buflen;
- int lp, linelen;
-
- buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r");
-
- for (bp = 0; bp < buflen; ) {
- // read file line by line
- for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) {
- line[linelen++] = work_buff[bp];
- }
- bp++;
- line[linelen] = '\0';
-
- // skip white space
- for (lp = 0; line[lp] <= ' '; lp++);
-
- if (lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
- line[lp] == '#')
- continue;
-
- sscanf(
- &line[lp],
- "%s %f %f %f %f %c %s %d %d",
- moveName,
- &startFireTime,
- &endFireTime,
- &comboFollowOnTime,
- &strikeRadius,
- &hitLevel,
- animName,
- &damage,
- &flags);
-
- if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0)
- return;
-
- tFightMoves[moveId].startFireTime = startFireTime / 30.0f;
- tFightMoves[moveId].endFireTime = endFireTime / 30.0f;
- tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
- tFightMoves[moveId].strikeRadius = strikeRadius;
- tFightMoves[moveId].damage = damage;
- tFightMoves[moveId].flags = flags;
-
- switch (hitLevel) {
- case 'G':
- tFightMoves[moveId].hitLevel = HITLEVEL_GROUND;
- break;
- case 'H':
- tFightMoves[moveId].hitLevel = HITLEVEL_HIGH;
- break;
- case 'L':
- tFightMoves[moveId].hitLevel = HITLEVEL_LOW;
- break;
- case 'M':
- tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM;
- break;
- case 'N':
- tFightMoves[moveId].hitLevel = HITLEVEL_NULL;
- break;
- default:
- 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;
- }
- moveId++;
- }
-}
-
-// Actually GetLocalDirectionTo(Turn/Look)
-int
-CPed::GetLocalDirection(const CVector2D &posOffset)
-{
- float direction;
-
- for (direction = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); direction < 0.0f; direction += TWOPI);
-
- for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4);
-
- // 0-forward, 1-left, 2-backward, 3-right.
- return direction;
-}
-
-bool
-CPed::FightStrike(CVector &touchedNodePos)
-{
- CColModel *ourCol;
- CVector attackDistance;
- ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
- float maxDistanceToBeBeaten;
- CPed *nearPed;
- int state = m_fightState;
- bool pedFound = false;
-
- if (state == FIGHTSTATE_JUST_ATTACKED)
- return false;
-
- // Pointless code
- if (state > FIGHTSTATE_NO_MOVE)
- attackDistance = touchedNodePos - m_vecHitLastPos;
-
- for (int i = 0; i < m_numNearPeds; i++) {
- nearPed = m_nearPeds[i];
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f;
- else
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius;
+ uint32 flagsOfSomePed = 0;
- if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
- CVector nearPedCentre;
- nearPed->GetBoundCentre(nearPedCentre);
- CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
+ CPed *pedToFearFrom = nil;
+#ifndef VC_PED_PORTS
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if (CharCreatedBy != RANDOM_CHAR || m_nearPeds[i]->CharCreatedBy != MISSION_CHAR || m_nearPeds[i]->IsPlayer()) {
+ CPed *nearPed = m_nearPeds[i];
- // He can beat us
- if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
+ // BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance.
+ // Fixed at the bottom of the function.
+ flagsOfSomePed = CPedType::GetFlag(nearPed->m_nPedType);
-#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->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) {
- ourCol = &CTempColModels::ms_colModelPedGroundHit;
- } else {
-#ifdef ANIMATE_PED_COL_MODEL
- ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(),
- RpClumpGetFrame(GetClump()));
+ if (CPedType::GetFlag(nearPed->m_nPedType) & fearFlags) {
+ if (nearPed->m_fHealth > 0.0f && OurPedCanSeeThisOne(m_nearPeds[i])) {
+ // FIX: Taken from VC
+#ifdef FIX_BUGS
+ float nearPedDistSqr = (nearPed->GetPosition() - ourPos).MagnitudeSqr2D();
#else
- ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
+ float nearPedDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
#endif
- }
-
- for (int j = 0; j < ourCol->numSpheres; j++) {
- attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
- attackDistance -= touchedNodePos;
- CColSphere *ourPieces = ourCol->spheres;
- float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;
-
- // We can beat him too
- if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
- pedFound = true;
- closestPedPiece = (ePedPieceTypes) ourPieces[j].piece;
- break;
+ if (sq(closestPedDist) > nearPedDistSqr) {
+ closestPedDist = Sqrt(nearPedDistSqr);
+ pedToFearFrom = m_nearPeds[i];
+ }
}
}
}
}
- if (pedFound)
- break;
- }
-
- if (pedFound) {
- if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP)
- return false;
-
- float oldVictimHealth = nearPed->m_fHealth;
- CVector bloodPos = 0.5f * attackDistance + touchedNodePos;
- int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
-
- CVector2D diff (GetPosition() - nearPed->GetPosition());
- int direction = nearPed->GetLocalDirection(diff);
- if (IsPlayer()) {
- if (((CPlayerPed*)this)->m_bAdrenalineActive)
- damageMult = 20;
- } else {
- damageMult *= m_pedStats->m_attackStrength;
- }
-
- // Change direction if we used kick.
- if (m_curFightMove == FIGHTMOVE_KICK) {
- if (CGeneral::GetRandomNumber() & 1) {
- direction++;
- if (direction > 3)
- direction -= 4;
- }
- }
- nearPed->ReactToAttack(this);
-
- // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
- int unk2;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
- unk2 = 101;
- else
- unk2 = damageMult;
-
- nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);
- PlayHitSound(nearPed);
- m_fightState = FIGHTSTATE_JUST_ATTACKED;
- RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;
- if (!nearPed->DyingOrDead()) {
- nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
- }
-
- if (CGame::nastyGame
- && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM
- && nearPed->m_nPedState == PED_DIE
- && nearPed->GetIsOnScreen()) {
+#else
+ bool weSawOurEnemy = false;
+ bool weMaySeeOurEnemy = false;
+ float closestEnemyDist = 60.0f;
+ if ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) {
- // Just for blood particle. We will restore it below.
- attackDistance /= (10.0f * attackDistance.Magnitude());
- for(int i=0; i<4; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0);
- }
- }
- if (!nearPed->OnGround()) {
- float curVictimHealth = nearPed->m_fHealth;
- if (curVictimHealth > 0.0f
- && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer()
- || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f
- || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer()
- || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) {
-
- nearPed->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0);
- if (nearPed->m_nPedState == PED_FALL)
- nearPed->bIsStanding = false;
- }
- }
- if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) {
- attackDistance = nearPed->GetPosition() - GetPosition();
- attackDistance.Normalise();
- attackDistance.z = 1.0f;
- nearPed->bIsStanding = false;
-
- float moveMult;
- if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
- moveMult = Min(damageMult * 0.6f, 4.0f);
- } else {
- if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
- moveMult = damageMult;
- } else {
- moveMult = Min(damageMult * 2.0f, 14.0f);
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ if (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) {
+ continue;
}
- }
-
- nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance);
- }
- CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000);
- }
-
- if (m_fightState == FIGHTSTATE_NO_MOVE)
- m_fightState = FIGHTSTATE_1;
-
- m_vecHitLastPos = *touchedNodePos;
- return false;
-}
-
-void
-CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
-{
- if (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead()))
- return;
-
- ClearLookFlag();
- ClearAimFlag();
- SetStoredState();
- m_nPedState = PED_FALL;
- CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId);
-
- if (fallAssoc) {
- fallAssoc->SetCurrentTime(0.0f);
- fallAssoc->blendAmount = 0.0f;
- fallAssoc->blendDelta = 8.0f;
- fallAssoc->SetRun();
- } else {
- fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f);
- }
-
- if (extraTime == -1) {
- m_getUpTimer = UINT32_MAX;
- } else if (fallAssoc) {
- if (IsPlayer()) {
- m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
- + CTimer::GetTimeInMilliseconds()
- + 500.0f;
- } else {
- m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
- + CTimer::GetTimeInMilliseconds()
- + extraTime
- + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
- }
- } else {
- m_getUpTimer = extraTime
- + CTimer::GetTimeInMilliseconds()
- + 1000
- + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
- }
- bFallenDown = true;
-}
-
-void
-CPed::SetFlee(CEntity *fleeFrom, int time)
-{
- if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom)
- return;
-
- SetStoredState();
- m_nPedState = PED_FLEE_ENTITY;
- bUsePedNodeSeek = true;
- SetMoveState(PEDMOVE_RUN);
- m_fleeFrom = fleeFrom;
- m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
-
- if (time <= 0)
- m_fleeTimer = 0;
- else
- m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
-
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x, GetPosition().y,
- fleeFrom->GetPosition().x, fleeFrom->GetPosition().y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
- if (m_fRotationCur - PI > m_fRotationDest) {
- m_fRotationDest += 2 * PI;
- } else if (PI + m_fRotationCur < m_fRotationDest) {
- m_fRotationDest -= 2 * PI;
- }
-}
-
-void
-CPed::SetFlee(CVector2D const &from, int time)
-{
- if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace)
- return;
-
- if (m_nPedState != PED_FLEE_ENTITY) {
- SetStoredState();
- m_nPedState = PED_FLEE_POS;
- SetMoveState(PEDMOVE_RUN);
- m_fleeFromPosX = from.x;
- m_fleeFromPosY = from.y;
- }
-
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
-
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x, GetPosition().y,
- from.x, from.y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
- if (m_fRotationCur - PI > m_fRotationDest) {
- m_fRotationDest += 2 * PI;
- } else if (PI + m_fRotationCur < m_fRotationDest) {
- m_fRotationDest -= 2 * PI;
- }
-}
-
-void
-CPed::SetWaitState(eWaitState state, void *time)
-{
- AnimationId waitAnim = NUM_ANIMS;
- CAnimBlendAssociation *animAssoc;
-
- if (!IsPedInControl())
- return;
-
- if (state != m_nWaitState)
- FinishedWaitCB(nil, this);
-
- switch (state) {
- case WAITSTATE_TRAFFIC_LIGHTS:
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
- SetMoveState(PEDMOVE_STILL);
- break;
- case WAITSTATE_CROSS_ROAD:
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
- break;
- case WAITSTATE_CROSS_ROAD_LOOK:
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 8.0f);
-
- if (time)
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000);
-
- break;
- case WAITSTATE_LOOK_PED:
- case WAITSTATE_LOOK_SHOP:
- case WAITSTATE_LOOK_ACCIDENT:
- case WAITSTATE_FACEOFF_GANG:
- break;
- case WAITSTATE_DOUBLEBACK:
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
- break;
- case WAITSTATE_HITWALL:
- m_headingRate = 2.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 16.0f);
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- animAssoc->SetDeleteCallback(FinishedWaitCB, this);
-
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
- ClearObjective();
- RestorePreviousState();
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
- }
- break;
- case WAITSTATE_TURN180:
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TURN_180, 4.0f);
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
- animAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);
- break;
- case WAITSTATE_SURPRISE:
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 4.0f);
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
- break;
- case WAITSTATE_STUCK:
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
-
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
- ClearObjective();
- RestorePreviousState();
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
- }
- break;
- case WAITSTATE_LOOK_ABOUT:
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
-
- break;
- case WAITSTATE_PLAYANIM_COWER:
- waitAnim = ANIM_HANDSCOWER;
- case WAITSTATE_PLAYANIM_HANDSUP:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_HANDSUP;
- case WAITSTATE_PLAYANIM_HANDSCOWER:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_HANDSCOWER;
- m_headingRate = 0.0f;
- if (time)
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
-
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
- animAssoc->SetDeleteCallback(FinishedWaitCB, this);
- break;
- case WAITSTATE_PLAYANIM_DUCK:
- waitAnim = ANIM_DUCK_DOWN;
- case WAITSTATE_PLAYANIM_TAXI:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_IDLE_TAXI;
- case WAITSTATE_PLAYANIM_CHAT:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_IDLE_CHAT;
- if (time)
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
-
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
- animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->SetDeleteCallback(FinishedWaitCB, this);
- break;
- case WAITSTATE_FINISH_FLEE:
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
- break;
- default:
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
- return;
- }
- m_nWaitState = state;
-}
+ // BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function.
+ flagsOfSomePed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType);
-void
-CPed::PlayHitSound(CPed *hitTo)
-{
- // That was very complicated to reverse for me...
- // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10).
- enum {
- S33 = SOUND_FIGHT_PUNCH_33,
- S34 = SOUND_FIGHT_KICK_34,
- S35 = SOUND_FIGHT_HEADBUTT_35,
- S36 = SOUND_FIGHT_PUNCH_36,
- S37 = SOUND_FIGHT_PUNCH_37,
- S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
- S39 = SOUND_FIGHT_PUNCH_39,
- S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
- S41 = SOUND_FIGHT_PUNCH_41,
- S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
- S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
- S44 = SOUND_FIGHT_KICK_44,
- NO_SND = SOUND_NO_SOUND
- };
- uint16 hitSoundsByFightMoves[12][10] = {
- {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42},
- {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
- {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
- {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39},
- {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39},
- {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39},
- {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40},
- {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40},
- {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33}
- };
-
- // This is why first dimension is between FightMove 1 and 12.
- if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)
- return;
-
- uint16 soundId;
-
- // And this is why second dimension is between 13 and 22.
- if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) {
- soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT];
-
- } else {
- if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) {
- soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT];
- } else {
- soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT];
- }
- }
-
- if (soundId != NO_SND)
- DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f);
-}
-
-void
-CPed::CollideWithPed(CPed *collideWith)
-{
- CAnimBlendAssociation *animAssoc;
- AnimationId animToPlay;
-
- bool weAreMissionChar = CharCreatedBy == MISSION_CHAR;
- bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR;
- CVector posDiff = collideWith->GetPosition() - GetPosition();
- int waitTime = 0;
-
- if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {
- bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;
- bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;
-
- if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
-
- if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)
- && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT
-#ifdef VC_PED_PORTS
- || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith
- || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this
-#endif
- )) {
-
- if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
-
- if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-
- if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) {
-
- if (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) {
+ if (flagsOfSomePed & fearFlags) {
+ if (m_nearPeds[i]->m_fHealth > 0.0f) {
- if (collideWith->m_nMoveState != PEDMOVE_STILL
- && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) {
- float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
- float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
+ // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
+ if (OurPedCanSeeThisOne(m_nearPeds[i])) {
+ if (m_nearPeds[i]->m_nPedState == PED_ATTACK) {
+ if (m_nearPeds[i]->m_pedInObjective == this) {
- if (seekPosDist <= heAndSeekPosDist) {
- waitTime = 1000;
- collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
- collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
- } else {
- waitTime = 500;
- SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestEnemyDist) > enemyDistSqr) {
+ float enemyDist = Sqrt(enemyDistSqr);
+ weSawOurEnemy = true;
+ closestPedDist = enemyDist;
+ closestEnemyDist = enemyDist;
+ pedToFearFrom = m_nearPeds[i];
}
- } else if (collideWith->m_nMoveState == PEDMOVE_STILL) {
- SetDirectionToWalkAroundObject(collideWith);
}
} else {
- if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
- || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
- (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
- SetDirectionToWalkAroundObject(collideWith);
- if (!weAreMissionChar)
- Say(SOUND_PED_CHAT);
- } else {
- SetEvasiveStep(collideWith, 2);
+ float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) {
+ closestPedDist = Sqrt(nearPedDistSqr);
+ pedToFearFrom = m_nearPeds[i];
}
}
- } else {
- if (m_pedStats->m_temper <= m_pedStats->m_fear
- || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED
- || weAreMissionChar
- || collideWith->m_nPedType == PEDTYPE_CIVFEMALE
- || collideWith->m_nPedType == m_nPedType
- || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- SetDirectionToWalkAroundObject(collideWith);
- Say(SOUND_PED_CHAT);
- } else {
- TurnBody();
- SetAttack(collideWith);
-#ifdef VC_PED_PORTS
- m_fRotationCur = 0.3f + m_fRotationCur;
- m_fRotationDest = m_fRotationCur;
-#endif
- }
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);
- }
- }
- } else {
-#ifdef VC_PED_PORTS
- if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-#else
- if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-#endif
- if (heLooksToUs) {
- SetEvasiveStep(collideWith, 1);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
- }
- } else if (weDontLookToHim && IsPedInControl()) {
+ } else if (!weSawOurEnemy) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->m_nPedState == PED_ATTACK) {
+ CColPoint foundCol;
+ CEntity *foundEnt;
- if (m_pedStats != collideWith->m_pedStats) {
+ // We don't see him yet but he's behind a ped, vehicle or object
+ // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
+ if (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt,
+ true, false, false, false, false, false, false)) {
- if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper
-#ifdef VC_PED_PORTS
- || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer
-#endif
- ) {
-
- if (collideWith->IsPlayer()) {
- // He's on our right side
- if (DotProduct(posDiff,GetRight()) <= 0.0f)
- m_fRotationCur -= m_headingRate;
- else
- m_fRotationCur += m_headingRate;
- } else {
- // He's on our right side
- if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f)
- collideWith->m_fRotationCur -= collideWith->m_headingRate;
- else
- collideWith->m_fRotationCur += collideWith->m_headingRate;
- }
- } else {
- SetLookFlag(collideWith, false);
- TurnBody();
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
- animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
-#ifdef VC_PED_PORTS
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
-#endif
- if (!heIsMissionChar) {
- CVector2D posDiff2D(posDiff);
- int direction = collideWith->GetLocalDirection(posDiff2D);
- collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5);
+ if (nearPed->m_pedInObjective == this) {
+ float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestEnemyDist) > enemyDistSqr) {
+ float enemyDist = Sqrt(enemyDistSqr);
+ weMaySeeOurEnemy = true;
+ closestPedDist = enemyDist;
+ closestEnemyDist = enemyDist;
+ pedToFearFrom = m_nearPeds[i];
+ }
+ } else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) {
+ float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestPedDist) > nearPedDistSqr) {
+ weMaySeeOurEnemy = true;
+ closestPedDist = Sqrt(nearPedDistSqr);
+ pedToFearFrom = m_nearPeds[i];
+ }
+ }
}
}
}
}
}
- } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
-#ifdef VC_PED_PORTS
- || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
-#endif
- ) {
- // He looks us and we're not at his right side
- if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
- CVector moveForce = GetRight();
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToPlay = ANIM_HIT_LEFT;
- else
- animToPlay = ANIM_SHOT_LEFT_PARTIAL;
- } else if (heLooksToUs) {
- CVector moveForce = GetRight() * -1.0f;
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToPlay = ANIM_HIT_RIGHT;
- else
- animToPlay = ANIM_SHOT_RIGHT_PARTIAL;
- } else {
- if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToPlay = ANIM_HIT_BACK;
- else
- animToPlay = ANIM_SHOT_BACK_PARTIAL;
- }
-
- if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) {
- animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f);
- animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
- if (m_nPedState == PED_ATTACK)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
- }
- } else {
- // We're at his right side
- if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) {
- CVector moveForce = GetRight() * -1.0f;
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (heLooksToUs)
- animToPlay = ANIM_KO_SPIN_L;
- else
- animToPlay = ANIM_KD_RIGHT;
- } else {
- CVector moveForce = GetRight();
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (heLooksToUs)
- animToPlay = ANIM_KO_SPIN_R;
- else
- animToPlay = ANIM_KD_LEFT;
- }
-
- if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
-
- collideWith->SetFall(3000, animToPlay, 0);
- }
- } else {
- if (!IsPedInControl())
- return;
-
- if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL)
- return;
-
- if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
-
- if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) {
-
- if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){
- SetEvasiveStep(collideWith, 2);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
- } else if (collideWith->m_nMoveState > PEDMOVE_WALK) {
- waitTime = 2000;
- SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime);
- }
- }
- } else if (heLooksToUs
- && collideWith->m_nPedState != PED_STEP_AWAY
- && m_nPedState != PED_STEP_AWAY
- && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-
- SetEvasiveStep(collideWith, 1);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
}
}
-
- if (IsPlayer()) {
- SetLookFlag(collideWith, true);
- SetLookTimer(800);
- }
- } else {
- bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;
- SetFindPathAndFlee(collideWith, 5000, !isRunning);
- }
-}
-
-void
-CPed::CreateDeadPedMoney(void)
-{
- if (!CGame::nastyGame)
- return;
-
- int skin = GetModelIndex();
- if ((skin >= MI_COP && skin <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle)
- return;
-
- int money = CGeneral::GetRandomNumber() % 60;
- if (money < 10)
- return;
-
- if (money == 43)
- money = 700;
-
- int pickupCount = money / 40 + 1;
- 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;
- if (found) {
- CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
- }
- }
-}
-
-void
-CPed::CreateDeadPedWeaponPickups(void)
-{
- bool found = false;
- float angleToPed;
- CVector pickupPos;
-
- if (bInVehicle)
- return;
-
- 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.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
-
- CVector pedPos = GetPosition();
- pedPos.z += 0.3f;
-
- CVector pedToPickup = pickupPos - pedPos;
- float distance = pedToPickup.Magnitude();
-
- // outer edge of pickup
- distance = (distance + 0.3f) / 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 (found)
- CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon]));
- }
- ClearWeapons();
-}
-
-void
-CPed::SetAttackTimer(uint32 time)
-{
- if (CTimer::GetTimeInMilliseconds() > m_attackTimer)
- m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;
-}
-
-void
-CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)
-{
- if (m_nPedState == PED_DRAG_FROM_CAR)
- return;
-
- bUsesCollision = false;
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_nLastPedState = PED_IDLE;
- SetMoveState(PEDMOVE_STILL);
- m_pSeekTarget = veh;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- m_vehEnterType = vehEnterType;
- if (m_vehEnterType == CAR_DOOR_LF) {
- if (veh->pDriver && veh->pDriver->IsPlayer())
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- else
- veh->SetStatus(STATUS_ABANDONED);
- }
- RemoveInCarAnims();
- SetMoveState(PEDMOVE_NONE);
- LineUpPedWithCar(LINE_UP_TO_CAR_START);
- m_pVehicleAnim = nil;
- m_nPedState = PED_DRAG_FROM_CAR;
- bChangedSeat = false;
- bWillBeQuickJacked = quickJack;
-
- SetHeading(m_fRotationCur);
-
- Say(SOUND_PED_CAR_JACKED);
- SetRadioStation();
- veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType);
-}
-
-void
-CPed::SetBuyIceCream(void)
-{
- if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl())
- return;
-
- if (!m_carInObjective)
- return;
-
-#ifdef FIX_ICECREAM
-
- // Simulating BuyIceCream
- CPed* driver = m_carInObjective->pDriver;
- if (driver) {
- m_nPedState = PED_BUY_ICECREAM;
- bFindNewNodeAfterStateRestore = true;
- SetObjectiveTimer(8000);
- SetChat(driver, 8000);
- driver->SetChat(this, 8000);
- return;
- }
-#endif
-
- // Side of the Ice Cream van
- m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
-
- if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000;
- m_nPedState = PED_BUY_ICECREAM;
- }
-}
-
-void
-CPed::SetChat(CEntity *chatWith, uint32 time)
-{
- if(m_nPedState != PED_CHAT)
- SetStoredState();
-
- m_nPedState = PED_CHAT;
- SetMoveState(PEDMOVE_STILL);
-#if defined VC_PED_PORTS || defined FIX_BUGS
- m_lookTimer = 0;
#endif
- SetLookFlag(chatWith, true);
- m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
-}
-
-void
-CPed::SetDead(void)
-{
- bUsesCollision = false;
-
- m_fHealth = 0.0f;
- if (m_nPedState == PED_DRIVING)
- bIsVisible = false;
-
- m_nPedState = PED_DEAD;
- m_pVehicleAnim = nil;
- m_pCollidingEntity = nil;
-
- CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(weapon->m_nModelId);
-
- m_currentWeapon = WEAPONTYPE_UNARMED;
- CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250);
- if (this != FindPlayerPed()) {
- CreateDeadPedWeaponPickups();
- CreateDeadPedMoney();
- }
-
- m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
- m_deadBleeding = false;
- bDoBloodyFootprints = false;
- bVehExitWillBeInstant = false;
- CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
-}
-
-void
-CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
-{
- if (!IsPedInControl())
- return;
-
- if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)
- return;
-
- if (!seeking)
- return;
-
- if (m_nPedState != PED_SEEK_ENTITY)
- SetStoredState();
-
- m_nPedState = PED_SEEK_ENTITY;
- m_distanceToCountSeekDone = distanceToCountDone;
- m_pSeekTarget = seeking;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- SetMoveState(PEDMOVE_STILL);
-}
-
-void
-CPed::SetSeek(CVector pos, float distanceToCountDone)
-{
- if (!IsPedInControl()
- || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
- return;
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) {
- ClearPointGunAt();
- }
-
- if (m_nPedState != PED_SEEK_POS)
- SetStoredState();
-
- m_nPedState = PED_SEEK_POS;
- m_distanceToCountSeekDone = distanceToCountDone;
- m_vecSeekPos = pos;
-}
-
-void
-CPed::DeadPedMakesTyresBloody(void)
-{
- int minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f);
- if (minX < 0) minX = 0;
- int minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f);
- if (minY < 0) minY = 0;
- int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);
- if (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1;
- int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);
- if (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1;
-
- CWorld::AdvanceCurrentScanCode();
-
- for (int curY = minY; curY <= maxY; curY++) {
- for (int curX = minX; curX <= maxX; curX++) {
- CSector *sector = CWorld::GetSector(curX, curY);
- MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]);
- MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
- }
- }
-}
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(ourPos, 20.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ CVehicle* foundVeh = nil;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* nearVeh = (CVehicle*)vehicles[i];
-void
-CPed::Die(void)
-{
- // UNUSED: This is a perfectly empty function.
-}
+ CPed *driver = nearVeh->pDriver;
+ if (driver) {
-uint8
-CPed::DoesLOSBulletHitPed(CColPoint &colPoint)
-{
+ // BUG: Same bug as above. Fixed at the bottom of function.
+ flagsOfSomePed = CPedType::GetFlag(driver->m_nPedType);
+ if (CPedType::GetFlag(driver->m_nPedType) & fearFlags) {
+ if (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) {
+ // FIX: Taken from VC
#ifdef FIX_BUGS
- return 1;
+ float driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D();
#else
- uint8 retVal = 2;
-
- float headZ = GetNodePosition(PED_HEAD).z;
-
- if (m_nPedState == PED_FALL)
- retVal = 1;
-
- float colZ = colPoint.point.z;
- if (colZ < headZ)
- retVal = 1;
-
- if (headZ + 0.2f <= colZ)
- retVal = 0;
-
- return retVal;
+ float driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
#endif
-}
-
-bool
-CPed::DuckAndCover(void)
-{
- if (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer)
- return false;
-
- if (bKindaStayInSamePlace){
-
- if (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) {
- if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- }
- if (!bIsAimingGun)
- SetAimFlag(m_pedInObjective);
-
- } else {
- bCrouchWhenShooting = false;
- bKindaStayInSamePlace = false;
- bIsDucking = false;
- bDuckAndCover = false;
- m_headingRate = 10.0f;
- m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000);
- if (m_pSeekTarget && m_pSeekTarget->IsVehicle())
- ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--;
- }
- return false;
- }
-
- bool justDucked = false;
- CVehicle *foundVeh = nil;
- float maxDist = 225.0f;
- bIsDucking = false;
- bCrouchWhenShooting = false;
- if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
- CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
-
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle *veh = (CVehicle*) vehicles[i];
- if (veh->m_vecMoveSpeed.Magnitude() <= 0.02f
- && !veh->bIsBus
- && !veh->bIsVan
- && !veh->bIsBig
- && veh->m_numPedsUseItAsCover < 3) {
- float dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr();
- if (dist < maxDist) {
- maxDist = dist;
- foundVeh = veh;
+ if (sq(closestPedDist) > driverDistSqr) {
+ closestPedDist = Sqrt(driverDistSqr);
+ pedToFearFrom = nearVeh->pDriver;
+ }
+ }
}
}
}
- if (foundVeh) {
- // Unused.
- // CVector lfWheelPos, rfWheelPos;
- // foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos);
- // foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos);
- CVector rightSide, leftSide;
-
- // 3 persons can use the car as cover. Found the correct position for us.
- if (foundVeh->m_numPedsUseItAsCover == 2) {
- rightSide = CVector(1.5f, -0.5f, 0.0f);
- leftSide = CVector(-1.5f, -0.5f, 0.0f);
- } else if (foundVeh->m_numPedsUseItAsCover == 1) {
- rightSide = CVector(1.5f, 0.5f, 0.0f);
- leftSide = CVector(-1.5f, 0.5f, 0.0f);
- } else if (foundVeh->m_numPedsUseItAsCover == 0) {
- rightSide = CVector(1.5f, 0.0f, 0.0f);
- leftSide = CVector(-1.5f, 0.0f, 0.0f);
- }
-
- CMatrix vehMatrix(foundVeh->GetMatrix());
- CVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition();
-
- CVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition();
-
- CVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide;
- CVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide;
-
- CVector duckPos;
- if (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr())
- duckPos = duckAtLeftSide;
- else
- duckPos = duckAtRightSide;
-
- if (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false)
- && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) {
- SetSeek(duckPos, 1.0f);
- m_headingRate = 15.0f;
- bIsRunning = true;
- bDuckAndCover = true;
- justDucked = true;
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500;
- if (foundVeh->bIsLawEnforcer)
- m_carInObjective = foundVeh;
-
- // BUG? Shouldn't we register the reference?
- m_pSeekTarget = foundVeh;
- ClearPointGunAt();
- } else {
- m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000);
- bDuckAndCover = false;
- }
- } else {
- bDuckAndCover = false;
- }
- }
-
- if (!justDucked && !bDuckAndCover)
- return false;
-
- if (!Seek())
- return true;
-
- bKindaStayInSamePlace = true;
- bDuckAndCover = false;
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- if (m_pSeekTarget && m_pSeekTarget->IsVehicle())
- ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++;
-
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- }
-
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000);
- return false;
-}
-
-void
-CPed::EndFight(uint8 endType)
-{
- if (m_nPedState != PED_FIGHT)
- return;
+ m_threatEntity = pedToFearFrom;
+ if (m_threatEntity)
+ m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
- m_curFightMove = FIGHTMOVE_NULL;
- RestorePreviousState();
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
- if (animAssoc)
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+#ifdef FIX_BUGS
+ if (pedToFearFrom)
+ flagsOfSomePed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType);
+ else
+ flagsOfSomePed = 0;
+#endif
- switch (endType) {
- case ENDFIGHT_NORMAL:
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f);
- break;
- case ENDFIGHT_WITH_A_STEP:
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1.0f);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WALK_START, 8.0f);
- break;
- case ENDFIGHT_FAST:
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f)->speed = 2.0f;
- break;
- default:
- break;
+ return flagsOfSomePed;
}
- m_nWaitTimer = 0;
}
void
-CPed::EnterCar(void)
-{
- if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {
- CVehicle *veh = (CVehicle*)m_pSeekTarget;
-
- // Not used.
- // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType);
-
- if (veh->CanPedOpenLocks(this)) {
- if (m_vehEnterType) {
- CAnimBlendAssociation *enterAssoc = m_pVehicleAnim;
- if (enterAssoc)
- veh->ProcessOpenDoor(m_vehEnterType, enterAssoc->animId, enterAssoc->currentTime);
- }
- }
- bIsInTheAir = false;
- LineUpPedWithCar(LINE_UP_TO_CAR_START);
- } else {
- QuitEnteringCar();
- SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
-}
-
-uint8
-CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos)
+CPed::SetLookFlag(float direction, bool keepTryingToLook)
{
- CVector enterStepOffset;
- CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex());
- CMatrix trainMat = CMatrix(train->GetMatrix());
- CVector leftEntryPos, rightEntryPos, midEntryPos;
- float distLeftEntry, distRightEntry, distMidEntry;
-
- // enterStepOffset = vecPedCarDoorAnimOffset;
- enterStepOffset = CVector(1.5f, 0.0f, 0.0f);
-
- if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) {
- distLeftEntry = 999.0f;
- } else {
- leftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset;
- leftEntryPos = Multiply3x3(trainMat, leftEntryPos);
- leftEntryPos += train->GetPosition();
- distLeftEntry = (leftEntryPos - GetPosition()).Magnitude();
- }
-
- if (train->pPassengers[TRAIN_POS_MID_ENTRY]) {
- distMidEntry = 999.0f;
- } else {
- midEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset;
- midEntryPos = Multiply3x3(trainMat, midEntryPos);
- midEntryPos += train->GetPosition();
- distMidEntry = (midEntryPos - GetPosition()).Magnitude();
- }
-
- if (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) {
- distRightEntry = 999.0f;
- } else {
- rightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset;
- rightEntryPos = Multiply3x3(trainMat, rightEntryPos);
- rightEntryPos += train->GetPosition();
- distRightEntry = (rightEntryPos - GetPosition()).Magnitude();
- }
-
- if (distMidEntry < distLeftEntry) {
- if (distMidEntry < distRightEntry) {
- enterPos = midEntryPos;
- m_vehEnterType = TRAIN_POS_MID_ENTRY;
- } else {
- enterPos = rightEntryPos;
- m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ bIsLooking = true;
+ bIsRestoringLook = false;
+ m_pLookTarget = nil;
+ m_fLookDirection = direction;
+ m_lookTimer = 0;
+ bKeepTryingToLook = keepTryingToLook;
+ if (m_nPedState != PED_DRIVING) {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
}
- } else if (distRightEntry < distLeftEntry) {
- enterPos = rightEntryPos;
- m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
- } else {
- enterPos = leftEntryPos;
- m_vehEnterType = TRAIN_POS_LEFT_ENTRY;
}
-
- return 1;
-}
-
-uint8
-CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos)
-{
- GetNearestTrainPedPosition(train, doorPos);
-/*
- // Not used.
- CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex);
- CMatrix trainMat = CMatrix(train->GetMatrix());
-
- doorPos = trainModel->m_positions[m_vehEnterType];
- doorPos.x -= 1.5f;
- doorPos = Multiply3x3(trainMat, doorPos);
- doorPos += train->GetPosition();
-*/
- return 1;
}
void
-CPed::LineUpPedWithTrain(void)
+CPed::SetLookFlag(CEntity *target, bool keepTryingToLook)
{
- CVector lineUpPos;
- CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex());
- CVector enterOffset(1.5f, 0.0f, -0.2f);
-
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;
- m_fRotationDest = m_fRotationCur;
-
- if (!bInVehicle) {
- GetNearestTrainDoor(m_pMyVehicle, lineUpPos);
- lineUpPos.z += 0.2f;
- } else {
- if (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) {
-
- lineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset;
-
- } else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) {
-
- lineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset;
-
- } else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) {
-
- lineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset;
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ bIsLooking = true;
+ bIsRestoringLook = false;
+ m_pLookTarget = target;
+ m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
+ m_fLookDirection = 999999.0f;
+ m_lookTimer = 0;
+ bKeepTryingToLook = keepTryingToLook;
+ if (m_nPedState != PED_DRIVING) {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
}
- lineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos);
- lineUpPos += m_pMyVehicle->GetPosition();
}
-
- if (m_pVehicleAnim) {
- float percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
- lineUpPos += (GetPosition() - lineUpPos) * percentageLeft;
- }
-
- SetPosition(lineUpPos);
- SetHeading(m_fRotationCur);
-}
-
-void
-CPed::EnterTrain(void)
-{
- LineUpPedWithTrain();
-}
-
-void
-CPed::ExitTrain(void)
-{
- LineUpPedWithTrain();
}
void
-CPed::ExitCar(void)
-{
- if (!m_pVehicleAnim)
- return;
-
- AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId;
- float animTime = m_pVehicleAnim->currentTime;
-
- m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime);
+CPed::ClearLookFlag(void) {
+ if (bIsLooking) {
+ bIsLooking = false;
+ bIsRestoringLook = true;
+ bShakeFist = false;
- if (m_pSeekTarget) {
- // Car is upside down
- if (m_pMyVehicle->GetUp().z > -0.8f) {
- if (exitAnim != ANIM_CAR_CLOSE_RHS && exitAnim != ANIM_CAR_CLOSE_LHS && animTime <= 0.3f)
- LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START));
- else
- LineUpPedWithCar(LINE_UP_TO_CAR_END);
- } else {
- LineUpPedWithCar(LINE_UP_TO_CAR_END);
- }
- }
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ if (IsPlayer())
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ else
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
- // If there is someone in front of the door, make him fall while we exit.
- if (m_nPedState == PED_EXIT_CAR) {
- CPed *foundPed = nil;
- for (int i = 0; i < m_numNearPeds; i++) {
- if ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < 0.04f) {
- foundPed = m_nearPeds[i];
- break;
- }
+ if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) {
+ ClearLook();
}
- if (foundPed && animTime > 0.4f && foundPed->IsPedInControl())
- foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1);
}
}
void
-CPed::Fall(void)
+FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer
-#ifdef VC_PED_PORTS
- && bIsStanding
-#endif
- )
- ClearFall();
+ CPed *ped = (CPed*)arg;
- // VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III.
+ if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
+ ped->RemoveWeaponModel(0);
}
void
-CPed::Fight(void)
+CPed::MoveHeadToLook(void)
{
- CAnimBlendAssociation *currentAssoc, *animAssoc;
- bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse;
- float angleToFace, nextAngle;
- bool goForward = false;
- int nextFightMove;
-
- switch (m_curFightMove) {
- case FIGHTMOVE_NULL:
- return;
- case FIGHTMOVE_IDLE2NORM:
- m_curFightMove = FIGHTMOVE_NULL;
- RestorePreviousState();
+ CVector lookPos;
- // FIX: Uninitialized
- currentAssoc = nil;
- break;
- case FIGHTMOVE_IDLE:
- currentAssoc = nil;
- break;
- default:
- currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
- break;
+ if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ ClearLookFlag();
+ } else if (m_nPedState == PED_DRIVING) {
+ m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;
}
- if (!bIsAttacking && IsPlayer()) {
- if (currentAssoc) {
- currentAssoc->blendDelta = -1000.0f;
- currentAssoc->flags |= ASSOC_DELETEFADEDOUT;
- currentAssoc->flags &= ~ASSOC_RUNNING;
- }
- if (m_takeAStepAfterAttack)
- EndFight(ENDFIGHT_WITH_A_STEP);
- else
- EndFight(ENDFIGHT_FAST);
-
- } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) {
- float animTime = currentAssoc->currentTime;
- FightMove &curMove = tFightMoves[m_curFightMove];
- if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
-
- CVector touchingNodePos(0.0f, 0.0f, 0.0f);
-
- switch (m_curFightMove) {
- case FIGHTMOVE_STDPUNCH:
- case FIGHTMOVE_PUNCHHOOK:
- case FIGHTMOVE_BODYBLOW:
- TransformToNode(touchingNodePos, PED_HANDR);
- break;
- case FIGHTMOVE_IDLE:
- case FIGHTMOVE_SHUFFLE_F:
- break;
- 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:
- TransformToNode(touchingNodePos, PED_FOOTR);
- break;
- }
-
- if (m_curFightMove == FIGHTMOVE_PUNCHJAB) {
- touchingNodePos += 0.1f * GetForward();
- } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) {
- touchingNodePos += 0.22f * GetForward();
- }
- FightStrike(touchingNodePos);
- m_fightButtonPressure = 0;
- return;
- }
-
- if (curMove.hitLevel != HITLEVEL_NULL) {
- if (animTime > curMove.endFireTime) {
- if (IsPlayer())
- currentAssoc->speed = 1.0f;
- else
- currentAssoc->speed = 0.8f;
- }
-
- if (IsPlayer() && !nPlayerInComboMove) {
- if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) {
-
- // Notice that it increases fight move index, because we're in combo!
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f);
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength);
- m_fightButtonPressure = 0;
- nPlayerInComboMove = 1;
- }
- }
- } else {
- if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) {
- if (IsPlayer())
- currentAssoc->speed = 1.3f;
- else
- currentAssoc->speed = 0.8f;
- }
- }
- } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- EndFight(ENDFIGHT_FAST);
-
- } else if (m_fightButtonPressure != 0) {
- bool canAffectMultiplePeople = true;
- nextAngle = m_fRotationCur;
- bool kickGround = false;
- float angleForGroundKick = 0.0f;
- CPed *pedOnGround = nil;
-
- Say(SOUND_PED_ATTACK);
-
- if (IsPlayer()) {
- canRoundhouse = false;
- punchOnly = false;
- canKick = true;
- nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
- hasShoppingBags = false;
- canKneeHead = true;
- nPlayerInComboMove = 0;
- } else {
- nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
- uint16 pedFeatures = m_pedStats->m_flags;
- punchOnly = pedFeatures & STAT_PUNCH_ONLY;
- canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE;
- canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD;
- canKick = pedFeatures & STAT_CAN_KICK;
- hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS;
- }
-
- // Attack isn't scripted, find the victim
- if (IsPlayer() || !m_pedInObjective) {
-
- for (int i = 0; i < m_numNearPeds; i++) {
-
- CPed *nearPed = m_nearPeds[i];
- float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude();
- if (nearPedDist < 3.0f) {
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- nearPed->GetPosition().x, nearPed->GetPosition().y,
- GetPosition().x, GetPosition().y);
-
- nextAngle = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- float neededTurn = Abs(nextAngle - m_fRotationCur);
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- if (!nearPed->OnGroundOrGettingUp()) {
-
- if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) {
- canAffectMultiplePeople = false;
- } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) {
-
- if (nearPedDist < 1.7f
- && neededTurn < DEGTORAD(35.0f)
- && (canKick || hasShoppingBags)) {
+ if (m_pLookTarget) {
- nextFightMove = FIGHTMOVE_KICK;
- if (hasShoppingBags) {
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
- } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) {
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
- }
- canAffectMultiplePeople = false;
- } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) {
- canAffectMultiplePeople = false;
- nextFightMove = FIGHTMOVE_LONGKICK;
- } else if (neededTurn < DEGTORAD(30.0f)) {
- goForward = true;
- }
- } else {
- nextFightMove += 2; // Makes it 6 or 7
- if (punchOnly)
- nextFightMove = FIGHTMOVE_PUNCHJAB;
+ if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
- canAffectMultiplePeople = false;
- }
- } else if (!CGame::nastyGame
- || nearPedDist >= 1.3f
- || neededTurn >= DEGTORAD(55.0f)
- || punchOnly) {
-
- if (nearPedDist > 0.8f
- && nearPedDist < 3.0f
- && neededTurn < DEGTORAD(30.0f)) {
- goForward = true;
- }
+ CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
+ if (fuckUAssoc) {
- } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) {
- if (!nearPed->IsPedHeadAbovePos(-0.3f)) {
- canAffectMultiplePeople = false;
- nextFightMove = FIGHTMOVE_GROUNDKICK;
- }
+ float animTime = fuckUAssoc->currentTime;
+ if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) {
- } else {
- pedOnGround = nearPed;
- kickGround = true;
- angleForGroundKick = nextAngle;
- }
- }
+ bool lookingToCop = false;
+ if (m_pLookTarget->GetModelIndex() == MI_POLICE
+ || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) {
- if (!canAffectMultiplePeople) {
- m_fRotationDest = nextAngle;
- if (IsPlayer()) {
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(nearPed, true);
- SetLookTimer(1500);
+ lookingToCop = true;
}
- break;
- }
- }
- } else {
- // Because we're in a scripted fight with some particular ped.
- canAffectMultiplePeople = false;
-
- float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude();
- if (hasShoppingBags) {
- if (fightingPedDist >= 1.7f)
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- else
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
-
- } else if (punchOnly) {
- if (fightingPedDist >= 1.3f)
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- else
- nextFightMove = FIGHTMOVE_PUNCHJAB;
-
- } else if (fightingPedDist >= 3.0f) {
- nextFightMove = FIGHTMOVE_STDPUNCH;
-
- } else {
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- m_pedInObjective->GetPosition().x,
- m_pedInObjective->GetPosition().y,
- GetPosition().x,
- GetPosition().y);
-
- nextAngle = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationDest = nextAngle;
- m_fRotationCur = m_fRotationDest;
- if (!m_pedInObjective->OnGroundOrGettingUp()) {
-
- if (fightingPedDist >= 0.8f || !canKneeHead) {
-
- if (fightingPedDist >= 1.3f) {
- if (fightingPedDist < 1.7f && canKick) {
- nextFightMove = FIGHTMOVE_KICK;
- if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
-
- } else if (fightingPedDist < 2.0f && canKick) {
- nextFightMove += 5; // Makes it 9 or 10
-
- } else {
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) {
+ AddWeaponModel(MI_FINGERS);
+ ((CPlayerPed*)this)->AnnoyPlayerPed(true);
- }
- } else {
- nextFightMove += 2; // Makes it 6 or 7
- }
+ } else if ((CGeneral::GetRandomNumber() & 3) == 0) {
+ AddWeaponModel(MI_FINGERS);
}
- } else if (!CGame::nastyGame
- || fightingPedDist >= 1.3f
- || m_pedInObjective->IsPlayer()
- || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) {
- nextFightMove = FIGHTMOVE_IDLE;
- } else {
- nextFightMove = FIGHTMOVE_GROUNDKICK;
}
}
}
- if (canAffectMultiplePeople) {
- if (kickGround && IsPlayer()) {
- m_fRotationDest = angleForGroundKick;
- nextFightMove = FIGHTMOVE_GROUNDKICK;
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(pedOnGround, true);
- SetLookTimer(1500);
- } else if (goForward) {
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- } else {
- nextFightMove = FIGHTMOVE_STDPUNCH;
- }
+ if (m_pLookTarget->IsPed()) {
+ ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID);
+ } else {
+ lookPos = m_pLookTarget->GetPosition();
}
- if (nextFightMove != FIGHTMOVE_IDLE) {
- m_curFightMove = nextFightMove;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
-
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {
- animAssoc->SetCurrentTime(0.0f);
- animAssoc->SetRun();
+ if (!m_pedIK.LookAtPosition(lookPos)) {
+ if (!bKeepTryingToLook) {
+ ClearLookFlag();
}
- m_fightButtonPressure = 0;
+ return;
}
- m_fightState = FIGHTSTATE_NO_MOVE;
- } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F
-#ifndef FIX_BUGS
- && CheckForPedsOnGroundToAttack(this, nil) == 4) {
-#else
- && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) {
-#endif
- m_curFightMove = FIGHTMOVE_SHUFFLE_F;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
- if (animAssoc) {
- animAssoc->SetCurrentTime(0.0f);
- animAssoc->blendDelta = 4.0f;
- animAssoc->SetRun();
- } else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f);
- }
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightState = FIGHTSTATE_NO_MOVE;
- m_fightButtonPressure = 0;
- m_takeAStepAfterAttack = false;
+ if (!bShakeFist || bIsAimingGun || bIsRestoringGun)
+ return;
- } else if (m_takeAStepAfterAttack) {
- EndFight(ENDFIGHT_FAST);
+ if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000)
+ return;
- } else if (m_curFightMove == FIGHTMOVE_IDLE) {
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- EndFight(ENDFIGHT_NORMAL);
- }
+ bool notRocketLauncher = false;
+ bool notTwoHanded = false;
+ AnimationId animToPlay = NUM_ANIMS;
- } else {
- m_curFightMove = FIGHTMOVE_IDLE;
- if (IsPlayer())
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
- }
-}
+ if (!GetWeapon()->IsType2Handed())
+ notTwoHanded = true;
-// Some helper function which doesn't exist in og game.
-inline void
-SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3)
-{
- for (int i = 0; i < node->numLinks; i++) {
+ if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER)
+ notRocketLauncher = true;
- CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];
+ if (IsPlayer() && notRocketLauncher) {
- if (testNode && testNode != closeNode && testNode != closeNode2) {
- CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());
- float dist = posDiff.MagnitudeSqr();
+ if (m_pLookTarget->IsPed()) {
- if (farDist.MagnitudeSqr() > dist) {
+ if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) {
- if (closeDist.MagnitudeSqr() <= dist) {
- ped->m_pNextPathNode = closeNode;
- closeDist = posDiff;
+ // FIX: Unreachable and meaningless condition
+#ifndef FIX_BUGS
+ if (m_pedStats->m_temper < 47)
+#endif
+ animToPlay = ANIM_FIGHT_PPUNCH;
} else {
- ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode);
- farDist = posDiff;
+ animToPlay = ANIM_FUCKU;
}
+ } else if (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE) {
+ animToPlay = ANIM_FUCKU;
}
-
- if (--runCount > 0)
- SelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount);
+ } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) {
+ animToPlay = ANIM_FUCKU;
}
- }
-}
-
-bool
-CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
-{
- if (m_pNextPathNode || !bUsePedNodeSeek)
- return false;
-
- CVector ourPos = GetPosition();
-
- int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f, false, false);
- CVector seekObjPos = m_vecSeekPos;
- seekObjPos.z += 1.0f;
-
- if (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false))
- return false;
-
- m_pNextPathNode = nil;
-
- CVector2D seekPosDist (m_vecSeekPos - ourPos);
-
- CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId];
- CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition());
-
- SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil);
-
- // Above function decided that going to the next node is more logical than seeking the object.
- if (m_pNextPathNode) {
+ if (animToPlay != NUM_ANIMS) {
+ CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos;
- if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
- *bestCoords = m_pNextPathNode->GetPosition();
- return true;
+ if (newAssoc) {
+ newAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ newAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (newAssoc->animId == ANIM_FUCKU)
+ newAssoc->SetDeleteCallback(FinishFuckUCB, this);
+ }
}
- m_pNextPathNode = nil;
+ bShakeFist = false;
+ return;
+ } else if (999999.0f == m_fLookDirection) {
+ ClearLookFlag();
+ } else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) {
+ if (!bKeepTryingToLook)
+ ClearLookFlag();
}
-
- return false;
}
void
-CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::RestoreHeadPosition(void)
{
- CPed *ped = (CPed*)arg;
-
- if (ped->bIsPedDieAnimPlaying)
- ped->bIsPedDieAnimPlaying = false;
+ if (m_pedIK.RestoreLookAt()) {
+ bIsRestoringLook = false;
+ }
}
void
-CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::SetAimFlag(float angle)
{
- CPed *ped = (CPed*)arg;
-
- if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) {
- ped->m_fightState = FIGHTSTATE_MOVE_FINISHED;
- animAssoc->blendDelta = -1000.0f;
- }
+ bIsAimingGun = true;
+ bIsRestoringGun = false;
+ m_fLookDirection = angle;
+ m_lookTimer = 0;
+ m_pLookTarget = nil;
+ m_pSeekTarget = nil;
+ if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
void
-CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::SetAimFlag(CEntity *to)
{
- CPed *ped = (CPed*)arg;
-
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (ped->m_nPedState == PED_JUMP)
- ped->RestorePreviousState();
-
- ped->bIsLanding = false;
+ bIsAimingGun = true;
+ bIsRestoringGun = false;
+ m_pLookTarget = to;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ m_pSeekTarget = to;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ m_lookTimer = 0;
}
void
-CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::ClearAimFlag(void)
{
- CPed *ped = (CPed*)arg;
-
- ped->bResetWalkAnims = true;
- ped->bIsLanding = false;
+ if (bIsAimingGun) {
+ bIsAimingGun = false;
+ bIsRestoringGun = true;
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ m_lookTimer = 0;
+#endif
+ }
- animAssoc->blendDelta = -1000.0f;
+ if (IsPlayer())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
}
void
-CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::AimGun(void)
{
- CPed *ped = (CPed*)arg;
-
- if (ped->m_nPedState != PED_JUMP)
- return;
-
- CVector forward(0.15f * ped->GetForward() + ped->GetPosition());
- forward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres->center.z + 0.25f;
-
- CEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
- if (!obstacle) {
- // Forward of forward
- forward += 0.15f * ped->GetForward();
- forward.z += 0.15f;
- obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
- }
-
- 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);
- handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped);
- ped->bIsLanding = true;
- return;
- }
-
- float velocityFromAnim = 0.1f;
- CAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_SPRINT);
-
- if (sprintAssoc) {
- velocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f;
- } else {
- CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_RUN);
- if (runAssoc) {
- velocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f;
- }
- }
-
- if (ped->IsPlayer()
-#ifdef VC_PED_PORTS
- || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer()
-#endif
- )
- ped->ApplyMoveForce(0.0f, 0.0f, 8.5f);
- else
- ped->ApplyMoveForce(0.0f, 0.0f, 4.5f);
-
- if (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D()
-#ifdef VC_PED_PORTS
- || ped->m_pCurrentPhysSurface
-#endif
- ) {
+ CVector vector;
-#ifdef FREE_CAM
- if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) {
-#else
- if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
-#endif
- float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur);
- ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle);
- ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle);
+ if (m_pSeekTarget) {
+ if (m_pSeekTarget->IsPed()) {
+ ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID);
} else {
- ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur);
- ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur);
- }
-#ifdef VC_PED_PORTS
- if (ped->m_pCurrentPhysSurface) {
- ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;
- ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;
+ vector = m_pSeekTarget->GetPosition();
}
-#endif
- }
-
- ped->bIsStanding = false;
- ped->bIsInTheAir = true;
- animAssoc->blendDelta = -1000.0f;
- CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_JUMP_GLIDE);
-
- if (ped->bDoBloodyFootprints) {
- CVector bloodPos(0.0f, 0.0f, 0.0f);
- ped->TransformToNode(bloodPos, PED_FOOTL);
-
- bloodPos.z -= 0.1f;
- bloodPos += 0.2f * ped->GetForward();
-
- CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
- 0.26f * ped->GetForward().x,
- 0.26f * ped->GetForward().y,
- 0.14f * ped->GetRight().x,
- 0.14f * ped->GetRight().y,
- 255, 255, 0, 0, 4.0f, 3000, 1.0f);
-
- bloodPos = CVector(0.0f, 0.0f, 0.0f);
- ped->TransformToNode(bloodPos, PED_FOOTR);
+ Say(SOUND_PED_ATTACK);
- bloodPos.z -= 0.1f;
- bloodPos += 0.2f * ped->GetForward();
- CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
- 0.26f * ped->GetForward().x,
- 0.26f * ped->GetForward().y,
- 0.14f * ped->GetRight().x,
- 0.14f * ped->GetRight().y,
- 255, 255, 0, 0, 4.0f, 3000, 1.0f);
+ bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector);
+ if (m_pLookTarget != m_pSeekTarget) {
+ SetLookFlag(m_pSeekTarget, true);
+ }
- if (ped->m_bloodyFootprintCountOrDeathTime <= 40) {
- ped->m_bloodyFootprintCountOrDeathTime = 0;
- ped->bDoBloodyFootprints = false;
+ } else {
+ if (IsPlayer()) {
+ bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading);
} else {
- ped->m_bloodyFootprintCountOrDeathTime -= 40;
+ bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f);
}
}
}
void
-CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::RestoreGunPosition(void)
{
- CPed *ped = (CPed*)arg;
-
- ped->m_nWaitTimer = 0;
- ped->RestoreHeadingRate();
- ped->Wait();
+ if (bIsLooking) {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ bIsRestoringGun = false;
+ } else if (m_pedIK.RestoreGunPosn()) {
+ bIsRestoringGun = false;
+ } else {
+ if (IsPlayer())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
+ }
}
void
-CPed::Wait(void)
+CPed::ScanForInterestingStuff(void)
{
- AnimationId mustHaveAnim = NUM_ANIMS;
- CAnimBlendAssociation *animAssoc;
- CPed *pedWeLook;
-
- if (DyingOrDead()) {
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
+ if (!IsPedInControl())
return;
- }
-
- switch (m_nWaitState) {
- case WAITSTATE_TRAFFIC_LIGHTS:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- }
- }
- break;
-
- case WAITSTATE_CROSS_ROAD:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
- m_nWaitState = WAITSTATE_FALSE;
- else
- SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
+ if (m_objective != OBJECTIVE_NONE)
+ return;
- case WAITSTATE_CROSS_ROAD_LOOK:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
+ if (CharCreatedBy == MISSION_CHAR)
+ return;
- case WAITSTATE_DOUBLEBACK:
- if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
- uint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds();
- if (timeLeft < 2500 && timeLeft > 2000) {
- m_nWaitTimer -= 500;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
- }
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- }
- break;
+ LookForSexyPeds();
+ LookForSexyCars();
+ if (LookForInterestingNodes())
+ return;
- case WAITSTATE_HITWALL:
- if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
- if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
- m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
- }
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- }
- break;
+ if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
+ if (CGeneral::GetRandomNumber() % 100 < 10) {
+ int mostExpensiveVehAround = -1;
+ int bestMonetaryValue = 0;
- case WAITSTATE_TURN180:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- m_fRotationCur = m_fRotationCur + PI;
- if (m_nPedState == PED_INVESTIGATE)
- ClearInvestigateEvent();
- }
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
- m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
- }
- break;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* veh = (CVehicle*)vehicles[i];
- case WAITSTATE_SURPRISE:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HIT_WALL)) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- } else {
- m_nWaitState = WAITSTATE_FALSE;
+ if (veh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal()
+ && veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) {
+ mostExpensiveVehAround = i;
+ bestMonetaryValue = veh->pHandling->nMonetaryValue;
+ }
}
}
- break;
-
- case WAITSTATE_STUCK:
- if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer)
- break;
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
-
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_TURN_180);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
-
- if (animAssoc) {
- if (animAssoc->IsPartial()) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- } else {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- }
-
- if (animAssoc->animId == ANIM_TURN_180) {
- m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- m_nStoredMoveState = PEDMOVE_NONE;
- m_panicCounter = 0;
- return;
- }
+ if (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]);
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ return;
}
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ } else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) {
+ CPed *charToMug = nil;
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
- AnimationId animToPlay;
-
- switch (CGeneral::GetRandomNumber() & 3) {
- case 0:
- animToPlay = ANIM_ROAD_CROSS;
+ if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f))
break;
- case 1:
- animToPlay = ANIM_IDLE_TIRED;
- break;
- case 2:
- animToPlay = ANIM_XPRESS_SCRATCH;
- break;
- case 3:
- animToPlay = ANIM_TURN_180;
- break;
- default:
- break;
- }
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
-
- if (animToPlay == ANIM_TURN_180)
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
-
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000);
- break;
-
- case WAITSTATE_LOOK_ABOUT:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
-
- case WAITSTATE_PLAYANIM_HANDSUP:
- mustHaveAnim = ANIM_HANDSUP;
-
- case WAITSTATE_PLAYANIM_HANDSCOWER:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_HANDSCOWER;
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
- pedWeLook = (CPed*) m_pLookTarget;
-
- if ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt)
- && m_nPedState != PED_FLEE_ENTITY
- && m_nPedState != PED_ATTACK
- && CTimer::GetTimeInMilliseconds() <= m_nWaitTimer
- && animAssoc) {
-
- TurnBody();
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- m_nWaitTimer = 0;
- if (m_pLookTarget && m_pLookTarget->IsPed()) {
-
- if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) {
-
- if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) {
-
- if (GetWeapon()->IsTypeMelee()) {
-#ifdef VC_PED_PORTS
- if(m_pedStats->m_flags & STAT_GUN_PANIC) {
-#endif
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
- if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) {
-
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- }
- if (m_nMoveState != PEDMOVE_RUN)
- SetMoveState(PEDMOVE_WALK);
-
- if (m_nPedType != PEDTYPE_COP) {
- ProcessObjective();
- SetMoveState(PEDMOVE_WALK);
- }
-#ifdef VC_PED_PORTS
- } else {
- SetObjective(OBJECTIVE_NONE);
- SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- }
-#endif
- } else {
- SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget);
- SetObjectiveTimer(20000);
- }
- } else {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
- if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS)
- {
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- }
- SetMoveState(PEDMOVE_RUN);
- Say(SOUND_PED_FLEE_RUN);
- }
- }
- }
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
- case WAITSTATE_PLAYANIM_COWER:
- mustHaveAnim = ANIM_HANDSCOWER;
-
- case WAITSTATE_PLAYANIM_DUCK:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_DUCK_DOWN;
-
- case WAITSTATE_PLAYANIM_TAXI:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_IDLE_TAXI;
-
- case WAITSTATE_PLAYANIM_CHAT:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_IDLE_CHAT;
-
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- m_nWaitState = WAITSTATE_FALSE;
- }
-#ifdef VC_PED_PORTS
- else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
- if (m_pedInObjective) {
- if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {
-
- // VC also calls CleanUpOldReference here for old LookTarget.
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- }
+ if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE
+ || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1
+ || nearPed->m_nPedType == PEDTYPE_PROSTITUTE)
+ && nearPed->CharCreatedBy != MISSION_CHAR
+ && nearPed->IsPedShootable()
+ && nearPed->m_objective != OBJECTIVE_MUG_CHAR) {
+ charToMug = nearPed;
+ break;
}
}
-#endif
- break;
+ if (charToMug)
+ SetObjective(OBJECTIVE_MUG_CHAR, charToMug);
- case WAITSTATE_FINISH_FLEE:
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (animAssoc) {
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- int timer = 2000;
- m_nWaitState = WAITSTATE_FALSE;
- SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
- }
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- }
- break;
- default:
- break;
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ }
}
- if(!m_nWaitState)
- RestoreHeadingRate();
-}
-
-bool
-CPed::Seek(void)
-{
- float distanceToCountItDone = m_distanceToCountSeekDone;
- eMoveState nextMove = PEDMOVE_NONE;
-
- if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
-
- if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT &&
- m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) {
-
- if ((!m_pedInObjective || !m_pedInObjective->bInVehicle)
- && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) {
-
- CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil,
- false, true, false, false, false, false);
+ if (m_nPedState == PED_WANDER_PATH) {
+#ifndef VC_PED_PORTS
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
- if (obstacle) {
- if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) {
- distanceToCountItDone = 2.5f;
- } else {
- CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());
- float yLength = vehModel->GetColModel()->boundingBox.max.y
- - vehModel->GetColModel()->boundingBox.min.y;
- distanceToCountItDone = yLength * 0.55f;
+ // += 2 is weird
+ for (int i = 0; i < m_numNearPeds; i += 2) {
+ if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH && WillChat(m_nearPeds[i])) {
+ if (CGeneral::GetRandomNumberInRange(0, 100) >= 100)
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ else {
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ } else if (CanSeeEntity(m_nearPeds[i])) {
+ int time = CGeneral::GetRandomNumber() % 4000 + 10000;
+ SetChat(m_nearPeds[i], time);
+ m_nearPeds[i]->SetChat(this, time);
+ return;
+ }
}
}
}
}
- }
-
- if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)
- ClearSeek();
-
- float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();
- if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {
-
- if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
-
- if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
- nextMove = m_pedInObjective->m_nMoveState;
- } else
- nextMove = PEDMOVE_WALK;
-
- } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
-
- if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning)
- nextMove = PEDMOVE_RUN;
- else
- nextMove = PEDMOVE_WALK;
-
- } else if (seekPosDist <= 2.0f) {
-
- if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
- nextMove = m_pedInObjective->m_nMoveState;
-
- } else {
- nextMove = PEDMOVE_RUN;
- }
-
- if (m_nPedState == PED_SEEK_ENTITY) {
- if (m_pSeekTarget->IsPed()) {
- if (((CPed*)m_pSeekTarget)->bInVehicle)
- distanceToCountItDone += 2.0f;
- }
- }
-
- if (seekPosDist >= distanceToCountItDone) {
- if (bIsRunning)
- nextMove = PEDMOVE_RUN;
-
- if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) {
-
- if (m_actionX != 0.0f && m_actionY != 0.0f) {
-
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_actionX, m_actionY,
- GetPosition().x, GetPosition().y);
-
- float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
+#else
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) {
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+ for (int i = 0; i < m_numNearPeds; i ++) {
+ if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) {
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f
+ && CanSeeEntity(m_nearPeds[i])
+ && m_nearPeds[i]->CanSeeEntity(this)
+ && WillChat(m_nearPeds[i])) {
- if (neededTurn > HALFPI) {
- if (seekPosDist >= 1.0f) {
- if (seekPosDist < 2.0f) {
- if (bIsRunning)
- nextMove = PEDMOVE_RUN;
- else
- nextMove = PEDMOVE_WALK;
+ int time = CGeneral::GetRandomNumber() % 4000 + 10000;
+ SetChat(m_nearPeds[i], time);
+ m_nearPeds[i]->SetChat(this, time);
+ return;
}
- } else {
- nextMove = PEDMOVE_STILL;
}
}
-
- CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY);
- if (moveDist.Magnitude() < 0.5f) {
- m_nPedStateTimer = 0;
- m_actionX = 0;
- m_actionY = 0;
- }
}
} else {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_vecSeekPos.x, m_vecSeekPos.y,
- GetPosition().x, GetPosition().y);
-
- float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- if (neededTurn > HALFPI) {
- if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) {
- if (seekPosDist < 2.0f)
- nextMove = PEDMOVE_WALK;
- } else {
- nextMove = PEDMOVE_STILL;
- }
- }
- }
-
- if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove)
- || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) {
-
- SetMoveState(nextMove);
- }
-
- SetMoveAnim();
- return false;
- }
-
- if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) {
- m_nPedStateTimer = 0;
- m_actionX = 0;
- m_actionY = 0;
- }
-
- if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) {
- if (m_pNextPathNode)
- m_pNextPathNode = nil;
- else
- bScriptObjectiveCompleted = true;
-
- bUsePedNodeSeek = true;
- }
-
- if (SeekFollowingPath(nil))
- m_nCurPathNode++;
-
- return true;
-}
-
-bool
-CPed::SeekFollowingPath(CVector *unused)
-{
- return m_nCurPathNode <= m_nPathNodes && m_nPathNodes;
-}
-
-void
-CPed::Flee(void)
-{
- if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) {
- bool mayFinishFleeing = true;
- if (m_nPedState == PED_FLEE_ENTITY) {
- if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f))
- mayFinishFleeing = false;
- }
-
- if (mayFinishFleeing) {
- eMoveState moveState = m_nMoveState;
- ClearFlee();
-
- if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
- RestorePreviousObjective();
-
- if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) {
- SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil);
- }
- return;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 200;
}
- m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000;
+#endif
}
- if (bUsePedNodeSeek) {
- CPathNode *realLastNode = nil;
- uint8 nextDirection = 0;
- uint8 curDirectionShouldBe = 9; // means not defined yet
-
- if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()
- && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) {
-
- if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
-
- curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
- if (m_nPathDir < curDirectionShouldBe)
- m_nPathDir += 8;
+ // Parts below aren't there in VC, they're in somewhere else.
+ if (!CGame::noProstitutes && m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy != MISSION_CHAR
+ && m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) {
- int dirDiff = m_nPathDir - curDirectionShouldBe;
- if (dirDiff > 2 && dirDiff < 6) {
- realLastNode = nil;
- m_pLastPathNode = m_pNextPathNode;
- m_pNextPathNode = nil;
- }
- }
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- if (m_pNextPathNode) {
- m_vecSeekPos = m_pNextPathNode->GetPosition();
- if (m_nMoveState == PEDMOVE_RUN)
- bIsRunning = true;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* veh = (CVehicle*)vehicles[i];
- eMoveState moveState = m_nMoveState;
- if (Seek()) {
- realLastNode = m_pLastPathNode;
- m_pLastPathNode = m_pNextPathNode;
- m_pNextPathNode = nil;
+ if (veh->IsVehicleNormal()) {
+ if (veh->IsCar()) {
+ if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) {
+ SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh);
+ Say(SOUND_PED_SOLICIT);
+ return;
+ }
}
- bIsRunning = false;
- SetMoveState(moveState);
}
}
-
- if (!m_pNextPathNode) {
- if (curDirectionShouldBe == 9) {
- curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
- }
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- curDirectionShouldBe,
- &nextDirection);
-
- if (curDirectionShouldBe < nextDirection)
- curDirectionShouldBe += 8;
-
- if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {
- m_nPathDir = nextDirection;
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
- } else {
- bUsePedNodeSeek = false;
- SetMoveState(PEDMOVE_RUN);
- Flee();
- }
- }
- return;
- }
-
- if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
-
- float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x,
- GetPosition().y,
- ms_vec2DFleePosition.x,
- ms_vec2DFleePosition.y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos);
-
- if (m_fRotationCur - PI > m_fRotationDest)
- m_fRotationDest += TWOPI;
- else if (PI + m_fRotationCur < m_fRotationDest)
- m_fRotationDest -= TWOPI;
- }
-
- if (CTimer::GetTimeInMilliseconds() & 0x20) {
- //CVector forwardPos = GetPosition();
- CMatrix forwardMat(GetMatrix());
- forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f));
- CVector forwardPos = forwardMat.GetPosition();
-
- CEntity *foundEnt;
- CColPoint foundCol;
- bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0);
-
- if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) {
- m_fRotationDest += DEGTORAD(112.5f);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
- }
- }
-
- if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer)
- return;
-
- if (!m_collidingEntityWhileFleeing)
- return;
-
- double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500;
-
- if (collidingThingPriorityMult <= 1.5) {
-
- double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x,
- GetPosition().y,
- m_collidingEntityWhileFleeing->GetPosition().x,
- m_collidingEntityWhileFleeing->GetPosition().y);
- angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity);
-
- double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints(
- m_vecDamageNormal.x,
- m_vecDamageNormal.y,
- 0.0f,
- 0.0f);
- angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing);
-
- if (angleToFleeEntity - PI > angleToFleeCollidingThing)
- angleToFleeCollidingThing += TWOPI;
- else if (PI + angleToFleeEntity < angleToFleeCollidingThing)
- angleToFleeCollidingThing -= TWOPI;
-
- if (collidingThingPriorityMult <= 1.0f) {
- // Range [0.0, 1.0]
-
- float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f;
-
- if (m_fRotationDest - PI > angleToFleeBoth)
- angleToFleeBoth += TWOPI;
- else if (PI + m_fRotationDest < angleToFleeBoth)
- angleToFleeBoth -= TWOPI;
-
- m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth;
- } else {
- // Range (1.0, 1.5]
-
- double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f;
- m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing;
- }
- } else {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_vecDamageNormal.x,
- m_vecDamageNormal.y,
- 0.0f,
- 0.0f);
- m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- }
-
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- if (m_fRotationCur - PI > m_fRotationDest)
- m_fRotationDest += TWOPI;
- else if (PI + m_fRotationCur < m_fRotationDest)
- m_fRotationDest -= TWOPI;
-
-}
-
-void
-CPed::FollowPath(void)
-{
- m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x;
- m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y;
- m_vecSeekPos.z = GetPosition().z;
-
- // Mysterious code
-/* int v4 = 0;
- int maxNodeIndex = m_nPathNodes - 1;
- if (maxNodeIndex > 0) {
- if (maxNodeIndex > 8) {
- while (v4 < maxNodeIndex - 8)
- v4 += 8;
- }
-
- while (v4 < maxNodeIndex)
- v4++;
-
- }
-*/
- if (Seek()) {
- m_nCurPathNode++;
- if (m_nCurPathNode == m_nPathNodes)
- RestorePreviousState();
- }
-}
-
-CVector
-CPed::GetFormationPosition(void)
-{
- CPed *referencePed = m_pedInObjective;
-
- if (referencePed->m_nPedState == PED_DEAD) {
- CPed *referencePedOfReference = referencePed->m_pedInObjective;
- if (!referencePedOfReference) {
- m_pedInObjective = nil;
- return GetPosition();
- }
- m_pedInObjective = referencePed = referencePedOfReference;
- }
-
- CVector formationOffset;
- switch (m_pedFormation) {
- case FORMATION_REAR:
- formationOffset = CVector(0.0f, -1.5f, 0.0f);
- break;
- case FORMATION_REAR_LEFT:
- formationOffset = CVector(-1.5f, -1.5f, 0.0f);
- break;
- case FORMATION_REAR_RIGHT:
- formationOffset = CVector(1.5f, -1.5f, 0.0f);
- break;
- case FORMATION_FRONT_LEFT:
- formationOffset = CVector(-1.5f, 1.5f, 0.0f);
- break;
- case FORMATION_FRONT_RIGHT:
- formationOffset = CVector(1.5f, 1.5f, 0.0f);
- break;
- case FORMATION_LEFT:
- formationOffset = CVector(-1.5f, 0.0f, 0.0f);
- break;
- case FORMATION_RIGHT:
- formationOffset = CVector(1.5f, 0.0f, 0.0f);
- break;
- case FORMATION_FRONT:
- formationOffset = CVector(0.0f, 1.5f, 0.0f);
- break;
- default:
- formationOffset = CVector(0.0f, 0.0f, 0.0f);
- break;
}
- return formationOffset + referencePed->GetPosition();
-}
-
-void
-CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)
-{
- CVector *enterOffset = nil;
- if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver
- || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0]
- || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1]
- || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2])
- {
- enterOffset = &vecPedQuickDraggedOutCarAnimOffset;
- }
-
- CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF);
- CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
-
- // Right front door is closer
- if ((lfPos - GetPosition()).MagnitudeSqr2D() >= (rfPos - GetPosition()).MagnitudeSqr2D()) {
-
- if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+ if (m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- CPed *rfPassenger = veh->pPassengers[0];
- if (!rfPassenger
- || rfPassenger->m_leader != this && !rfPassenger->bDontDragMeOutCar && (veh->VehicleCreatedBy != MISSION_VEHICLE || m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER)
- || veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) {
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* veh = (CVehicle*)vehicles[i];
- if ((veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) == 0
- || veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) {
- m_vehEnterType = CAR_DOOR_RF;
- posToOpen = rfPos;
- return;
+ if (veh->GetModelIndex() == MI_MRWHOOP) {
+ if (veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED) {
+ if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f) {
+ SetObjective(OBJECTIVE_BUY_ICE_CREAM, veh);
+ return;
+ }
}
}
- } else {
- if (!veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset))
- return;
}
- m_vehEnterType = CAR_DOOR_LF;
- posToOpen = lfPos;
- return;
- }
-
- if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
- m_vehEnterType = CAR_DOOR_LF;
- posToOpen = lfPos;
- return;
- }
-
- if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
- m_vehEnterType = CAR_DOOR_RF;
- posToOpen = rfPos;
}
}
bool
-CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen)
-{
- CVector rfPos, lrPos, rrPos;
- bool canEnter = false;
-
- CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
-
- switch (veh->GetModelIndex()) {
- case MI_BUS:
- m_vehEnterType = CAR_DOOR_RF;
- posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
- return true;
- case MI_RHINO:
- default:
- break;
- }
-
- CVector2D rfPosDist(999.0f, 999.0f);
- CVector2D lrPosDist(999.0f, 999.0f);
- CVector2D rrPosDist(999.0f, 999.0f);
-
- if (!veh->pPassengers[0]
- && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
- && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {
-
- rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
- canEnter = true;
- rfPosDist = rfPos - GetPosition();
- }
- if (vehModel->m_numDoors == 4) {
- if (!veh->pPassengers[1]
- && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
- && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {
- lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);
- canEnter = true;
- lrPosDist = lrPos - GetPosition();
- }
- if (!veh->pPassengers[2]
- && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
- && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {
- rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);
- canEnter = true;
- rrPosDist = rrPos - GetPosition();
- }
-
- // When the door we should enter is blocked by some object.
- if (!canEnter)
- veh->ShufflePassengersToMakeSpace();
- }
-
- CVector2D nextToCompare = rfPosDist;
- posToOpen = rfPos;
- m_vehEnterType = CAR_DOOR_RF;
- if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
- m_vehEnterType = CAR_DOOR_LR;
- posToOpen = lrPos;
- nextToCompare = lrPosDist;
- }
-
- if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
- m_vehEnterType = CAR_DOOR_RR;
- posToOpen = rrPos;
- }
- return canEnter;
-}
-
-int
-CPed::GetNextPointOnRoute(void)
+CPed::WillChat(CPed *stranger)
{
- int16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
-
- // Route is complete
- if (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) {
-
- switch (m_routeType) {
- case PEDROUTE_STOP_WHEN_DONE:
- nextPoint = -1;
- break;
- case PEDROUTE_GO_BACKWARD_WHEN_DONE:
- m_routePointsBeingPassed = -m_routePointsBeingPassed;
- nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
- break;
- case PEDROUTE_GO_TO_START_WHEN_DONE:
- m_routePointsPassed = -1;
- nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
- break;
- default:
- break;
+ if (m_pNextPathNode && m_pLastPathNode) {
+ if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) {
+ return false;
}
}
- 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;
- }
-}
-
-// Some kind of VC leftover I think
-int
-CPed::GetWeaponSlot(eWeaponType weaponType)
-{
- if (HasWeapon(weaponType))
- return weaponType;
- else
- return -1;
-}
-
-void
-CPed::GoToNearestDoor(CVehicle *veh)
-{
- CVector posToOpen;
- GetNearestDoor(veh, posToOpen);
- SetSeek(posToOpen, 0.5f);
- SetMoveState(PEDMOVE_RUN);
-}
-
-bool
-CPed::HaveReachedNextPointOnRoute(float distToCountReached)
-{
- if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() >= distToCountReached)
+ if (m_nSurfaceTouched == SURFACE_TARMAC)
+ return false;
+ if (stranger == this)
+ return false;
+ if (m_nPedType == stranger->m_nPedType)
+ return true;
+ if (m_nPedType == PEDTYPE_CRIMINAL)
+ return false;
+ if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType)
return false;
-
- m_routePointsPassed += m_routePointsBeingPassed;
return true;
}
void
-CPed::Idle(void)
+CPed::CalculateNewVelocity(void)
{
- CVehicle *veh = m_pMyVehicle;
- if (veh && veh->m_nGettingOutFlags && m_vehEnterType) {
-
- if (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehEnterType)) {
-
- if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
-
- CVector doorPos = GetPositionToOpenCarDoor(veh, m_vehEnterType);
- CVector doorDist = GetPosition() - doorPos;
+ if (IsPedInControl()) {
+ float headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep();
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ float limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- if (doorDist.MagnitudeSqr() < sq(0.5f)) {
- SetMoveState(PEDMOVE_WALK);
- return;
- }
- }
+ if (m_fRotationCur - PI > limitedRotDest) {
+ limitedRotDest += 2 * PI;
+ } else if(PI + m_fRotationCur < limitedRotDest) {
+ limitedRotDest -= 2 * PI;
}
- }
-
- CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
- CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- int waitTime;
-
- if (m_nMoveState == PEDMOVE_STILL) {
-
- eWeaponType curWeapon = GetWeapon()->m_eWeaponType;
- if (!armedIdleAssoc ||
- CTimer::GetTimeInMilliseconds() <= m_nWaitTimer && curWeapon != WEAPONTYPE_UNARMED && curWeapon != WEAPONTYPE_MOLOTOV && curWeapon != WEAPONTYPE_GRENADE) {
- if ((!GetWeapon()->IsType2Handed() || curWeapon == WEAPONTYPE_SHOTGUN) && curWeapon != WEAPONTYPE_BASEBALLBAT
- || !unarmedIdleAssoc || unarmedIdleAssoc->blendAmount <= 0.95f || m_nWaitState != WAITSTATE_FALSE || CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ if (IsPlayer() && m_nPedState == PED_ATTACK)
+ headAmount /= 4.0f;
- m_moved = CVector2D(0.0f, 0.0f);
- return;
- }
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_ARMED, 3.0f);
- waitTime = CGeneral::GetRandomNumberInRange(4000, 7500);
+ float neededTurn = limitedRotDest - m_fRotationCur;
+ if (neededTurn <= headAmount) {
+ if (neededTurn > (-headAmount))
+ m_fRotationCur += neededTurn;
+ else
+ m_fRotationCur -= headAmount;
} else {
- armedIdleAssoc->blendDelta = -2.0f;
- armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
- waitTime = CGeneral::GetRandomNumberInRange(3000, 8500);
- }
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + waitTime;
- } else {
- if (armedIdleAssoc) {
- armedIdleAssoc->blendDelta = -8.0f;
- armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
- m_nWaitTimer = 0;
- }
- if (!IsPlayer())
- SetMoveState(PEDMOVE_STILL);
- }
- m_moved = CVector2D(0.0f, 0.0f);
-}
-
-void
-CPed::InTheAir(void)
-{
- CColPoint foundCol;
- CEntity *foundEnt;
-
- CVector ourPos = GetPosition();
- CVector bitBelow = GetPosition();
- bitBelow.z -= 4.04f;
-
- if (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) {
- if (!DyingOrDead()) {
- if (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) {
- if (GetPosition().z - foundCol.point.z < 1.3f
-#ifdef VC_PED_PORTS
- || bIsStanding
-#endif
- )
- SetLanding();
- } else {
- if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)) {
- if (m_vecMoveSpeed.z < -0.1f)
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_FALL, 4.0f);
- }
- }
+ m_fRotationCur += headAmount;
}
}
-}
-
-void
-CPed::SetLanding(void)
-{
- if (DyingOrDead())
- return;
- CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
- CAnimBlendAssociation *landAssoc;
-
- RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
- if (fallAssoc) {
- landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f);
+ CVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur));
- if (IsPlayer())
- Say(SOUND_PED_LAND);
+ m_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y;
+ m_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward); // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur));
+ if (CTimer::GetTimeStep() >= 0.01f) {
+ m_moved = m_moved * (1 / CTimer::GetTimeStep());
} else {
- landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f);
- }
-
- landAssoc->SetFinishCallback(PedLandCB, this);
- bIsInTheAir = false;
- bIsLanding = true;
-}
-
-void
-CPed::Initialise(void)
-{
- debug("Initialising CPed...\n");
- CPedType::Initialise();
- LoadFightData();
- SetAnimOffsetForEnterOrExitVehicle();
- debug("CPed ready\n");
-}
-
-void
-CPed::SetAnimOffsetForEnterOrExitVehicle(void)
-{
- // FIX: If there were no translations on enter anims, there were overflows all over this function.
-
- CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy;
- CAnimBlendSequence *seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedDraggedOutCarAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedCarDoorAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedCarDoorLoAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedVanRearDoorAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_TRAIN_GETOUT)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedTrainDoorAnimOffset = lastFrame->translation;
- }
+ m_moved = m_moved * (1 / 100.0f);
}
-}
-void
-CPed::InvestigateEvent(void)
-{
- CAnimBlendAssociation *animAssoc;
- AnimationId animToPlay;
- AssocGroupId animGroup;
-
- if (m_nWaitState == WAITSTATE_TURN180)
+ if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam())
+ || FindPlayerPed() != this || !CanStrafeOrMouseControl())
return;
- if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
-
- if (m_standardTimer) {
- if (m_eventType < EVENT_ASSAULT_NASTYWEAPON)
- SetWaitState(WAITSTATE_TURN180, nil);
+ float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur);
+ float pedSpeed = m_moved.Magnitude();
+ float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur);
- m_standardTimer = 0;
- } else {
- ClearInvestigateEvent();
- }
- return;
+ if (localWalkAngle < -0.5f * PI) {
+ localWalkAngle += PI;
+ } else if (localWalkAngle > 0.5f * PI) {
+ localWalkAngle -= PI;
}
- CVector2D vecDist = m_eventOrThreat - GetPosition();
- float distSqr = vecDist.MagnitudeSqr();
- if (sq(m_distanceToCountSeekDone) >= distSqr) {
-
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f);
- SetMoveState(PEDMOVE_STILL);
-
- switch (m_eventType) {
- case EVENT_DEAD_PED:
- case EVENT_HIT_AND_RUN:
- case EVENT_HIT_AND_RUN_COP:
-
- if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
-
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (m_pEventEntity)
- SetLookFlag(m_pEventEntity, true);
-
- SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
-
- } else if (CGeneral::GetRandomNumber() & 3) {
- ClearLookFlag();
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
-
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
- Say(SOUND_PED_CHAT_EVENT);
-
- } else {
- ClearInvestigateEvent();
- }
- }
- break;
- case EVENT_FIRE:
- case EVENT_EXPLOSION:
-
- if (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
-
- if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
-
- } else if (CGeneral::GetRandomNumber() & 3) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));
- Say(SOUND_PED_CHAT_EVENT);
-
- } else {
- m_standardTimer = 0;
- }
-
- } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
-
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
-
- if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) {
- if (CGeneral::GetRandomNumber() & 1)
- animToPlay = ANIM_IDLE_HBHB;
- else
- animToPlay = ANIM_XPRESS_SCRATCH;
-
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
-
- } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (CGeneral::GetRandomNumber() & 1) {
- animToPlay = ANIM_IDLE_STANCE;
- animGroup = m_animGroup;
- } else {
- animToPlay = ANIM_XPRESS_SCRATCH;
- animGroup = ASSOCGRP_STD;
- }
-
- CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
-
- } else {
- if (CGeneral::GetRandomNumber() & 1) {
- animToPlay = ANIM_IDLE_STANCE;
- animGroup = m_animGroup;
- } else {
- animToPlay = ANIM_IDLE_HBHB;
- animGroup = ASSOCGRP_STD;
- }
-
- CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
- }
- Say(SOUND_PED_CHAT_EVENT);
- }
- break;
- case EVENT_ICECREAM:
- case EVENT_SHOPSTALL:
-
- m_fRotationDest = m_fAngleToEvent;
- if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
-
- if (m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+ // Interestingly this part is responsible for diagonal walking.
+ if (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) {
+ TheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed;
+ m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed;
+ }
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (m_eventType == EVENT_ICECREAM)
- animToPlay = ANIM_IDLE_CHAT;
- else
- animToPlay = ANIM_XPRESS_SCRATCH;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+#ifdef VC_PED_PORTS
+ if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) {
+#else
+ if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
+#endif
+ LimbOrientation newUpperLegs;
+ newUpperLegs.yaw = localWalkAngle;
- } else {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- ClearInvestigateEvent();
- } else {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- ClearInvestigateEvent();
- }
- }
- } else {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
- }
- }
- break;
- default:
- return;
+ if (newUpperLegs.yaw < -DEGTORAD(100.0f)) {
+ newUpperLegs.yaw += PI;
+ } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) {
+ newUpperLegs.yaw -= PI;
}
- } else {
- m_vecSeekPos.x = m_eventOrThreat.x;
- m_vecSeekPos.y = m_eventOrThreat.y;
- m_vecSeekPos.z = GetPosition().z;
- Seek();
- if (m_eventType < EVENT_ICECREAM) {
- if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {
- SetMoveState(PEDMOVE_RUN);
- return;
- }
- }
- if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) {
- SetMoveState(PEDMOVE_WALK);
- return;
- }
- if (distSqr > sq(1.2f)) {
- SetMoveState(PEDMOVE_WALK);
- return;
- }
+ 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);
- for (int i = 0; i < m_numNearPeds; i++) {
- if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) {
- SetMoveState(PEDMOVE_STILL);
- return;
+ 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);
}
}
-
- SetMoveState(PEDMOVE_WALK);
}
}
-bool
-CPed::IsPedDoingDriveByShooting(void)
-{
- if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
- if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
- return true;
- }
- return false;
-}
-
-bool
-CPed::IsPedShootable(void)
+float
+CPed::WorkOutHeadingForMovingFirstPerson(float offset)
{
- return m_nPedState <= PED_STATES_NO_ST;
-}
+ if (!IsPlayer())
+ return 0.0f;
-bool
-CPed::IsRoomToBeCarJacked(void)
-{
- if (!m_pMyVehicle)
- return false;
+ CPad *pad0 = CPad::GetPad(0);
+ float leftRight = pad0->GetPedWalkLeftRight();
+ float upDown = pad0->GetPedWalkUpDown();
+ float &angle = ((CPlayerPed*)this)->m_fWalkAngle;
- CVector offset;
- if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) {
- offset = vecPedDraggedOutCarAnimOffset;
+ if (upDown != 0.0f) {
+ angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
} else {
- offset = vecPedQuickDraggedOutCarAnimOffset;
- }
-
- offset.z = 0.0f;
- if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) {
- return true;
+ if (leftRight < 0.0f)
+ angle = 0.5f * PI;
+ else if (leftRight > 0.0f)
+ angle = -0.5f * PI;
}
- return false;
+ return CGeneral::LimitRadianAngle(offset + angle);
}
void
-CPed::KillPedWithCar(CVehicle *car, float impulse)
+CPed::UpdatePosition(void)
{
- CVehicleModelInfo *vehModel;
- CColModel *vehColModel;
- uint8 damageDir;
- PedNode nodeToDamage;
- eWeaponType killMethod;
-
- if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {
- if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)
- this->m_pCollidingEntity = car;
- return;
- }
-
- if (m_nPedState == PED_DEAD)
+ if (CReplay::IsPlayingBack() || !bIsStanding)
return;
- if (m_pCurSurface) {
- if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer()))
- return;
- }
-
- CVector distVec = GetPosition() - car->GetPosition();
-
- if ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) {
- nodeToDamage = PED_TORSO;
- killMethod = WEAPONTYPE_RAMMEDBYCAR;
- uint8 randVal = CGeneral::GetRandomNumber() & 3;
-
- if (car == FindPlayerVehicle()) {
- float carSpeed = car->m_vecMoveSpeed.Magnitude();
- uint8 shakeFreq;
- if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) {
- shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f;
- } else {
- shakeFreq = 250.0f;
- }
- CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);
- }
- bIsStanding = false;
- damageDir = GetLocalDirection(-m_vecMoveSpeed);
- vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex());
- vehColModel = vehModel->GetColModel();
- float carRightAndDistDotProd = DotProduct(distVec, car->GetRight());
-
- if (car->GetModelIndex() == MI_TRAIN) {
- killMethod = WEAPONTYPE_RUNOVERBYCAR;
- nodeToDamage = PED_HEAD;
- m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0f;
- if (damageDir == 1 || damageDir == 3)
- damageDir = 2;
- if (CGame::nastyGame)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
-
- // Car doesn't look to us
- } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){
-
- if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) {
-
- // We're at the right of the car
- if (carRightAndDistDotProd <= 0.0f)
- nodeToDamage = PED_UPPERARML;
- else
- nodeToDamage = PED_UPPERARMR;
-
- if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
- killMethod = WEAPONTYPE_RUNOVERBYCAR;
- m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0f;
- if (damageDir == 1 || damageDir == 3)
- damageDir = 2;
- if (CGame::nastyGame)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
-
- }
- } else {
- float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());
-
- // carFrontAndDistDotProd <= 0.0 car looks to us
- if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) {
- killMethod = WEAPONTYPE_RUNOVERBYCAR;
- nodeToDamage = PED_HEAD;
- m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0f;
- if (damageDir == 1 || damageDir == 3)
- damageDir = 2;
-
- if (CGame::nastyGame)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
-
- } else {
- nodeToDamage = PED_MID;
- float vehColMaxY = vehColModel->boundingBox.max.y;
- float vehColMinY = vehColModel->boundingBox.min.y;
- float vehColMaxZ = vehColModel->boundingBox.max.z;
- float carFrontZ = car->GetForward().z;
- float carHighestZ, carLength;
-
- if (carFrontZ < -0.2f) {
- // Highest point of car's back
- carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
- carLength = vehColMaxY - vehColMinY;
-
- } else if (carFrontZ > 0.1f) {
- // Highest point of car's front
- carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
- float highestZDist = carHighestZ - GetPosition().z;
- if (highestZDist > 0.0f) {
- GetMatrix().GetPosition().z += 0.5f * highestZDist;
- carHighestZ += highestZDist * 0.25f;
- }
- carLength = vehColMaxY;
-
- } else {
- // Highest point of car's front
- carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
- carLength = vehColMaxY;
- }
-
- float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude());
-
- // TODO: What are we doing down here?
- float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;
-
- // After this point, distVec isn't distVec anymore.
- distVec = car->m_vecMoveSpeed;
- distVec.Normalise();
- distVec *= 0.2 * unknown;
-
- if (damageDir != 1 && damageDir != 3)
- distVec.z += unknown;
- else
- distVec.z += 1.5f * unknown;
+ CVector2D velocityChange;
- m_vecMoveSpeed = distVec;
- damageDir += 2;
- if (damageDir > 3)
- damageDir = damageDir - 4;
+ SetHeading(m_fRotationCur);
+ if (m_pCurrentPhysSurface) {
+ CVector2D velocityOfSurface;
+ if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
- if (car->m_vehType == VEHICLE_TYPE_CAR) {
- CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
+ // It seems R* didn't like m_vecOffsetFromPhysSurface for boats
+ CVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition();
+ offsetToSurface.z -= FEET_OFFSET;
- if (bonnet) {
- if (CGeneral::GetRandomNumber() & 1) {
- bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));
- } else {
- bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));
- }
- CVector forceDir = car->GetUp() * 10.0f;
- bonnet->ApplyTurnForce(forceDir, car->GetForward());
- }
- }
- }
- }
- }
+ CVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed;
+ CVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface);
- if (car->pDriver) {
- CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000);
+ // Also we use that weird formula instead of friction if it's boat
+ float slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr();
+ velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);
+ m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);
+ } else {
+ velocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface);
}
+ // Reminder: m_moved is displacement from walking/running.
+ velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;
+ m_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ m_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ } else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) {
+ // Ped got damaged by steep slope
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
+ // some kind of
+ CVector2D reactionForce = m_vecDamageNormal;
+ reactionForce.Normalise();
- ePedPieceTypes pieceToDamage;
- switch (nodeToDamage) {
- case PED_HEAD:
- pieceToDamage = PEDPIECE_HEAD;
- break;
- case PED_UPPERARML:
- pieceToDamage = PEDPIECE_LEFTARM;
- break;
- case PED_UPPERARMR:
- pieceToDamage = PEDPIECE_RIGHTARM;
- break;
- default:
- pieceToDamage = PEDPIECE_MID;
- break;
- }
- InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);
+ velocityChange = 0.02f * reactionForce + m_moved;
- if (DyingOrDead()
- && bIsPedDieAnimPlaying && !m_pCollidingEntity) {
- m_pCollidingEntity = car;
+ float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);
+ // they're in same direction
+ if (reactionAndVelocityDotProd < 0.0f) {
+ velocityChange -= reactionAndVelocityDotProd * reactionForce;
}
- if (nodeToDamage == PED_MID)
- bKnockedUpIntoAir = true;
- else
- bKnockedUpIntoAir = false;
-
- distVec.Normalise();
-
-#ifdef VC_PED_PORTS
- distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
-#endif
- car->ApplyMoveForce(distVec * -100.0f);
- Say(SOUND_PED_DEFEND);
-
- } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f
- || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {
-
- bIsStanding = false;
- uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed);
- float damage;
- if (IsPlayer() && car->GetModelIndex() == MI_TRAIN)
- damage = 150.0f;
- else
- damage = 30.0f;
+ } else {
+ velocityChange = m_moved - m_vecMoveSpeed;
+ }
- InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);
- SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true);
-
- if (OnGround() && !m_pCollidingEntity &&
- (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
-
- m_pCollidingEntity = car;
- }
-
- bKnockedUpIntoAir = false;
- if (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) {
- m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f;
+ // Take time step into account
+ if (m_pCurrentPhysSurface) {
+ float speedChange = velocityChange.Magnitude();
+ float changeMult = speedChange;
+ if (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) {
+ changeMult = 0.002f * CTimer::GetTimeStep();
+ } else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) {
+ changeMult = 0.01f * CTimer::GetTimeStep();
}
- m_vecMoveSpeed.z = 0.0f;
- distVec.Normalise();
-#ifdef VC_PED_PORTS
- distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
-#endif
- car->ApplyMoveForce(distVec * -60.0f);
- Say(SOUND_PED_DEFEND);
- }
-#ifdef VC_PED_PORTS
- // Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
- if (IsGangMember()) {
- CPed *driver = car->pDriver;
- if (driver && driver->IsPlayer()
-#ifdef FIX_BUGS
- && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver)
-#endif
- ) {
- RegisterThreatWithGangPeds(driver);
+ if (speedChange > changeMult) {
+ velocityChange = velocityChange * (changeMult / speedChange);
}
}
-#endif
+ m_vecMoveSpeed.x += velocityChange.x;
+ m_vecMoveSpeed.y += velocityChange.y;
}
void
-CPed::Look(void)
-{
- // UNUSED: This is a perfectly empty function.
-}
-
-bool
-CPed::LookForInterestingNodes(void)
+CPed::CalculateNewOrientation(void)
{
- CBaseModelInfo *model;
- CPtrNode *ptrNode;
- CVector effectDist;
- C2dEffect *effect;
- CMatrix *objMat;
-
- if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) {
- return false;
- }
- bool found = false;
- uint8 randVal = CGeneral::GetRandomNumber() % 256;
-
- int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST);
- if (minX < 0) minX = 0;
- int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST);
- if (minY < 0) minY = 0;
- int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST);
-#ifdef FIX_BUGS
- if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
-#else
- if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
-#endif
-
- int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST);
-#ifdef FIX_BUGS
- if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
-#else
- if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
-#endif
-
- for (int curY = minY; curY <= maxY && !found; curY++) {
- for (int curX = minX; curX <= maxX && !found; curX++) {
- CSector *sector = CWorld::GetSector(curX, curY);
-
- for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CVehicle *veh = (CVehicle*)ptrNode->item;
- model = veh->GetModelInfo();
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &veh->GetMatrix();
- CVector effectPos = veh->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CObject *obj = (CObject*)ptrNode->item;
- model = CModelInfo::GetModelInfo(obj->GetModelIndex());
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &obj->GetMatrix();
- CVector effectPos = obj->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CBuilding *building = (CBuilding*)ptrNode->item;
- model = CModelInfo::GetModelInfo(building->GetModelIndex());
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &building->GetMatrix();
- CVector effectPos = building->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CBuilding *building = (CBuilding*)ptrNode->item;
- model = CModelInfo::GetModelInfo(building->GetModelIndex());
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &building->GetMatrix();
- CVector effectPos = building->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- }
- }
-
- if (!found)
- return false;
-
- CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir);
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f);
- randVal = CGeneral::GetRandomNumber() % 256;
- if (randVal <= m_randomSeed % 256) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
- SetLookFlag(angleToFace, true);
- SetLookTimer(1000);
- return false;
- }
+ if (CReplay::IsPlayingBack() || !IsPedInControl())
+ return;
- CVector2D effectPos = *objMat * effect->pos;
- switch (effect->attractor.type) {
- case ATTRACTORTYPE_ICECREAM:
- SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace);
- break;
- case ATTRACTORTYPE_STARE:
- SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f,
- CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500),
- angleToFace);
- break;
- default:
- return true;
- }
- return true;
+ SetHeading(m_fRotationCur);
}
void
-CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle)
+CPed::ClearAll(void)
{
- if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR)
+ if (!IsPedInControl() && m_nPedState != PED_DEAD)
return;
- SetStoredState();
- bFindNewNodeAfterStateRestore = false;
- m_nPedState = PED_INVESTIGATE;
- m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
- m_eventType = event;
- m_eventOrThreat = pos;
- m_distanceToCountSeekDone = distanceToCountDone;
- m_fAngleToEvent = angle;
-
- if (m_eventType >= EVENT_ICECREAM)
- m_lookTimer = 0;
- else
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f);
-
+ m_nPedState = PED_NONE;
+ m_nMoveState = PEDMOVE_NONE;
+ m_pSeekTarget = nil;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_fleeFromPosX = 0.0f;
+ m_fleeFromPosY = 0.0f;
+ m_fleeFrom = nil;
+ m_fleeTimer = 0;
+ bUsesCollision = true;
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#else
+ ClearAimFlag();
+ ClearLookFlag();
+#endif
+ bIsPointingGunAt = false;
+ bRenderPedInCar = true;
+ bKnockedUpIntoAir = false;
+ m_pCollidingEntity = nil;
}
void
-CPed::LookForSexyCars(void)
+CPed::ProcessBuoyancy(void)
{
- CEntity *vehicles[8];
- CVehicle *veh;
- int foundVehId = 0;
- int bestPriceYet = 0;
- int16 lastVehicle;
+ static uint32 nGenerateRaindrops = 0;
+ static uint32 nGenerateWaterCircles = 0;
+ CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f),
+ ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f),
+ ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f),
+ (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48);
- if (!IsPedInControl() && m_nPedState != PED_DRIVING)
+ if (bInVehicle)
return;
- if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
- CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
-
- for (int vehId = 0; vehId < lastVehicle; vehId++) {
- veh = (CVehicle*)vehicles[vehId];
- if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) {
- foundVehId = vehId;
- bestPriceYet = veh->pHandling->nMonetaryValue;
- }
- }
- if (lastVehicle > 0 && bestPriceYet > 40000)
- SetLookFlag(vehicles[foundVehId], false);
-
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
-}
-
-void
-CPed::LookForSexyPeds(void)
-{
- if ((!IsPedInControl() && m_nPedState != PED_DRIVING)
- || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE)
- return;
+ CVector buoyancyPoint;
+ CVector buoyancyImpulse;
- for (int i = 0; i < m_numNearPeds; i++) {
- if (CanSeeEntity(m_nearPeds[i])) {
- if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {
- CPed *nearPed = m_nearPeds[i];
- if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)
- && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {
+#ifndef VC_PED_PORTS
+ float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f);
+#else
+ float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f);
+#endif
- SetLookFlag(nearPed, true);
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
- Say(SOUND_PED_CHAT_SEXY);
- return;
- }
- }
+ if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
+ bTouchingWater = true;
+ CEntity *entity;
+ CColPoint point;
+ if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil)
+ && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) {
+ bIsInWater = false;
+ return;
}
- }
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
-}
-
-void
-CPed::MakeTyresMuddySectorList(CPtrList &list)
-{
- for (CPtrNode *node = list.first; node; node = node->next) {
- CVehicle *veh = (CVehicle*)node->item;
- if (veh->IsCar() && veh->m_scanCode != CWorld::GetCurrentScanCode()) {
- veh->m_scanCode = CWorld::GetCurrentScanCode();
-
- if (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f) {
-
- if (Abs(GetPosition().y - veh->GetPosition().y) < 10.0f
- && veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) {
-
- for(int wheel = 0; wheel < 4; wheel++) {
-
- if (!((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel]
- && ((CAutomobile*)veh)->m_aSuspensionSpringRatio[wheel] < 1.0f) {
-
- CColModel *vehCol = veh->GetModelInfo()->GetColModel();
- CVector approxWheelOffset;
- switch (wheel) {
- case 0:
- approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
- break;
- case 1:
- approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
- break;
- case 2:
- approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
- break;
- case 3:
- approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
- break;
- default:
- break;
- }
-
- // I hope so
- CVector wheelPos = veh->GetMatrix() * approxWheelOffset;
- if (Abs(wheelPos.z - GetPosition().z) < 2.0f) {
-
- if ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) {
- if (CGame::nastyGame) {
- ((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] = true;
- DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_SPLATTER, 0.0f);
- }
- veh->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f));
-
- CVector vehAndWheelDist = wheelPos - veh->GetPosition();
- veh->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f), vehAndWheelDist);
+ bIsInWater = true;
+ ApplyMoveForce(buoyancyImpulse);
+ if (!DyingOrDead()) {
+ if (bTryingToReachDryLand) {
+ if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) {
+ bTryingToReachDryLand = false;
+ CVector pos = GetPosition();
+ if (PlacePedOnDryLand()) {
+ if (m_fHealth > 20.0f)
+ InflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false);
- if (veh == FindPlayerVehicle()) {
- CPad::GetPad(0)->StartShake(300, 70);
- }
- }
- }
+ if (bIsInTheAir) {
+ RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
+ bIsInTheAir = false;
}
+ pos.z = pos.z - 0.8f;
+#ifdef PC_PARTICLE
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true);
+#else
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true);
+#endif
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_nPedState = PED_IDLE;
+ return;
}
}
}
- }
- }
-}
-
-void
-CPed::Mug(void)
-{
- if (m_pSeekTarget && m_pSeekTarget->IsPed()) {
-
- if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) {
- if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f)
- m_wepSkills = 50;
-
- Say(SOUND_PED_MUGGING);
- ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED);
- } else {
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- SetFlee(m_pSeekTarget, 20000);
- }
-
- } else {
- SetIdle();
- }
-}
-
-void
-CPed::MoveHeadToLook(void)
-{
- CVector lookPos;
-
- if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- ClearLookFlag();
- } else if (m_nPedState == PED_DRIVING) {
- m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;
- }
-
- if (m_pLookTarget) {
-
- if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
-
- CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
- if (fuckUAssoc) {
-
- float animTime = fuckUAssoc->currentTime;
- if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) {
-
- bool lookingToCop = false;
- if (m_pLookTarget->GetModelIndex() == MI_POLICE
- || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) {
-
- lookingToCop = true;
- }
-
- if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) {
- AddWeaponModel(MI_FINGERS);
- ((CPlayerPed*)this)->AnnoyPlayerPed(true);
-
- } else if ((CGeneral::GetRandomNumber() & 3) == 0) {
- AddWeaponModel(MI_FINGERS);
- }
- }
- }
- }
-
- if (m_pLookTarget->IsPed()) {
- ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID);
- } else {
- lookPos = m_pLookTarget->GetPosition();
- }
-
- if (!m_pedIK.LookAtPosition(lookPos)) {
- if (!bKeepTryingToLook) {
- ClearLookFlag();
+ float speedMult = 0.0f;
+ if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.75f * CTimer::GetTimeStep()
+ || mod_Buoyancy.m_waterlevel > GetPosition().z) {
+ speedMult = pow(0.9f, CTimer::GetTimeStep());
+ m_vecMoveSpeed.x *= speedMult;
+ m_vecMoveSpeed.y *= speedMult;
+ m_vecMoveSpeed.z *= speedMult;
+ bIsStanding = false;
+ InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
}
- return;
- }
-
- if (!bShakeFist || bIsAimingGun || bIsRestoringGun)
- return;
-
- if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000)
- return;
-
- bool notRocketLauncher = false;
- bool notTwoHanded = false;
- AnimationId animToPlay = NUM_ANIMS;
-
- if (!GetWeapon()->IsType2Handed())
- notTwoHanded = true;
-
- if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER)
- notRocketLauncher = true;
-
- if (IsPlayer() && notRocketLauncher) {
-
- if (m_pLookTarget->IsPed()) {
-
- if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) {
+ if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) {
+ if (speedMult == 0.0f) {
+ speedMult = pow(0.9f, CTimer::GetTimeStep());
+ }
+ m_vecMoveSpeed.x *= speedMult;
+ m_vecMoveSpeed.y *= speedMult;
+ if (m_vecMoveSpeed.z >= -0.1f) {
+ if (m_vecMoveSpeed.z < -0.04f)
+ m_vecMoveSpeed.z = -0.02f;
+ } else {
+ m_vecMoveSpeed.z = -0.01f;
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f);
+#ifdef PC_PARTICLE
+ CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
+ aBitForward.z = level;
- // FIX: Unreachable and meaningless condition
-#ifndef FIX_BUGS
- if (m_pedStats->m_temper < 47)
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true);
+ nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80;
+ nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100;
+#else
+ CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
+ aBitForward.z = level + 0.5f;
+
+ CVector vel = m_vecMoveSpeed * 0.1f;
+ vel.z = 0.18f;
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true);
+ nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300;
+ nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60;
#endif
- animToPlay = ANIM_FIGHT_PPUNCH;
- } else {
- animToPlay = ANIM_FUCKU;
}
- } else if (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE) {
- animToPlay = ANIM_FUCKU;
- }
- } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) {
- animToPlay = ANIM_FUCKU;
- }
-
- if (animToPlay != NUM_ANIMS) {
- CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
-
- if (newAssoc) {
- newAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- newAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (newAssoc->animId == ANIM_FUCKU)
- newAssoc->SetDeleteCallback(FinishFuckUCB, this);
}
- }
- bShakeFist = false;
- return;
- }
-
- if (999999.0f == m_fLookDirection) {
- ClearLookFlag();
- return;
- }
-
- if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) {
- if (!bKeepTryingToLook) {
- ClearLookFlag();
+ } else
return;
- }
- }
-}
-
-void
-FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
- ped->RemoveWeaponModel(0);
-}
-
-void
-CPed::Pause(void)
-{
- m_moved = CVector2D(0.0f, 0.0f);
- if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)
- ClearPause();
-}
-
-void
-CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (!ped->IsNotInWreckedVehicle())
- return;
+ } else
+ bTouchingWater = false;
- if (!ped->EnteringCar()) {
-#ifdef VC_PED_PORTS
- if (ped->m_nPedState != PED_DRIVING)
-#endif
- ped->QuitEnteringCar();
+ if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) {
+ CVector pos = GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(pos, &level, false))
+ pos.z = level;
- return;
- }
- if (ped->m_fHealth == 0.0f) {
- ped->QuitEnteringCar();
- return;
- }
- bool itsVan = !!veh->bIsVan;
- bool itsBus = !!veh->bIsBus;
-#ifdef FIX_BUGS
- bool itsLow = !!veh->bLowVehicle;
+ if (pos.z != 0.0f) {
+ nGenerateWaterCircles = 0;
+ for(int i = 0; i < 4; i++) {
+#ifdef PC_PARTICLE
+ pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
+ pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0);
+#else
+ pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
+ pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f));
#endif
- eDoors enterDoor;
- AnimationId enterAnim;
-
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- itsVan = false;
- enterDoor = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- enterDoor = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- itsVan = false;
- enterDoor = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- enterDoor = DOOR_REAR_LEFT;
- break;
- default:
- break;
+ }
+ }
}
- if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {
+ if (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) {
+ CVector pos = GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(pos, &level, false))
+ pos.z = level;
- veh->AutoPilot.m_nCruiseSpeed = 0;
- if (ped->m_nPedState == PED_CARJACK) {
- ped->PedAnimDoorOpenCB(nil, ped);
- return;
- }
- if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
- if (itsVan) {
- enterAnim = ANIM_VAN_GETIN;
- } else if (itsBus) {
- enterAnim = ANIM_COACH_IN_R;
-#ifdef FIX_BUGS
- } else if (itsLow) {
- enterAnim = ANIM_CAR_GETIN_LOW_RHS;
+ if (pos.z >= 0.0f) {
+#ifdef PC_PARTICLE
+ pos.z += 0.25f;
+#else
+ pos.z += 0.5f;
#endif
- } else {
- enterAnim = ANIM_CAR_GETIN_RHS;
- }
- } else if (itsVan) {
- enterAnim = ANIM_VAN_GETIN_L;
- } else if (itsBus) {
- enterAnim = ANIM_COACH_IN_L;
-#ifdef FIX_BUGS
- } else if (itsLow) {
- enterAnim = ANIM_CAR_GETIN_LOW_LHS;
+ nGenerateRaindrops = 0;
+#ifdef PC_PARTICLE
+ CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true);
+#else
+ CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true);
#endif
- } else {
- enterAnim = 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)) {
-
- 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);
- } else if (itsBus) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, 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);
- } else if (itsBus) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L);
- } else {
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {
-
- if (!veh->bLowVehicle
- && veh->pDriver->CharCreatedBy != MISSION_CHAR
- && veh->pDriver->m_nPedState == PED_DRIVING) {
-
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true);
-
- if (veh->pDriver->IsGangMember())
- veh->pDriver->RegisterThreatWithGangPeds(ped);
- return;
- }
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS);
- }
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
-
- } else {
- if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS);
-
- ped->bCancelEnteringCar = true;
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
}
}
@@ -10455,3351 +3025,458 @@ CPed::ProcessControl(void)
}
}
-void
-CPed::SetInTheAir(void)
-{
- if (bIsInTheAir)
- return;
-
- bIsInTheAir = true;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f);
-
- if (m_nPedState == PED_ATTACK) {
- ClearAttack();
- ClearPointGunAt();
- } else if (m_nPedState == PED_FIGHT) {
- EndFight(ENDFIGHT_FAST);
- }
-
-}
-
-void
-CPed::RestoreHeadPosition(void)
-{
- if (m_pedIK.RestoreLookAt()) {
- bIsRestoringLook = false;
- }
-}
-
-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);
-
- if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
- weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
- weaponAssoc->flags &= ~ASSOC_RUNNING;
-
- if (weaponInfo->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
- else
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
- }
-}
-
-void
-CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)
+int32
+CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
{
- CPed *ped = (CPed*)arg;
-
- CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle);
-
- if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
- return;
-
- if (ped->EnteringCar()) {
- bool isLow = !!veh->bLowVehicle;
-
- if (!veh->bIsBus)
- veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f);
-
- eDoors door;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;
- case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;
- case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;
- case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;
- default: assert(0);
- }
-
- if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SMASHED)
- veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK);
-
- if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) {
- PedSetInCarCB(nil, ped);
- } else if (ped->m_vehEnterType == CAR_DOOR_RF
- && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF ||
- (veh->pDriver != nil &&
- (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR
-#ifdef VC_PED_PORTS
- && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE
-#endif
- || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) {
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
-#if defined VC_PED_PORTS || defined FIX_BUGS
- || ped->m_nPedState == PED_CARJACK
-#endif
- )
- veh->bIsBeingCarJacked = false;
-
- ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
- PedSetInCarCB(nil, ped);
-
- ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- if (!ped->IsPlayer())
- ped->bFleeAfterExitingCar = true;
+ bool collidedWithBoat = false;
+ bool belowTorsoCollided = false;
+ float gravityEffect = -0.15f * CTimer::GetTimeStep();
+ CColPoint intersectionPoint;
+ CColLine ourLine;
- ped->bUsePedNodeSeek = true;
- ped->m_pNextPathNode = nil;
+ CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();
+ CColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel();
- } else {
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
+ if (!bUsesCollision)
+ return false;
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS);
+ if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat())
+ collidedWithBoat = true;
- ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);
- }
- } else {
+ // ofc we're not vehicle
+ if (!m_bIsVehicleBeingShifted && !bSkipLineCol
#ifdef VC_PED_PORTS
- if (ped->m_nPedState != PED_DRIVING)
+ && !collidingEnt->IsPed()
#endif
- ped->QuitEnteringCar();
- }
-}
-
-void
-CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- CAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle);
-
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (veh->bLowVehicle) {
- veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR_LOW, 1.0f);
- } else {
- veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f);
- }
-
- veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF;
-
- if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING)
- veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK);
-}
-
-void
-CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- CVehicle* veh = ped->m_pMyVehicle;
-
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (!ped->IsNotInWreckedVehicle())
- return;
-
- if (!ped->EnteringCar()) {
+ ) {
+ if (!bCollisionProcessed) {
#ifdef VC_PED_PORTS
- if (ped->m_nPedState != PED_DRIVING)
-#endif
- ped->QuitEnteringCar();
-
- return;
- }
-
- eDoors door;
- CPed *pedInSeat = nil;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; pedInSeat = veh->pPassengers[0]; break;
- case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; pedInSeat = veh->pPassengers[2]; break;
- case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; pedInSeat = veh->pDriver; break;
- case CAR_DOOR_LR: door = DOOR_REAR_LEFT; pedInSeat = veh->pPassengers[1]; break;
- default: assert(0);
- }
-
- if (ped->m_fHealth == 0.0f || CPad::GetPad(0)->ArePlayerControlsDisabled() && pedInSeat && pedInSeat->IsPlayer()) {
- ped->QuitEnteringCar();
- return;
- }
-
- bool isVan = veh->bIsVan;
- bool isBus = veh->bIsBus;
- bool isLow = veh->bLowVehicle;
- bool vehUpsideDown = veh->IsUpsideDown();
- if (ped->bCancelEnteringCar) {
- if (ped->IsPlayer()) {
- if (veh->pDriver) {
- if (veh->pDriver->m_nPedType == PEDTYPE_COP) {
- FindPlayerPed()->SetWantedLevelNoDrop(1);
- }
- }
- }
-#ifdef CANCELLABLE_CAR_ENTER
- if (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) {
- ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
- }
+ m_pCurrentPhysSurface = nil;
#endif
- ped->QuitEnteringCar();
- ped->RestorePreviousObjective();
- ped->bCancelEnteringCar = false;
- return;
- }
- if (!veh->IsDoorMissing(door) && veh->IsCar()) {
- ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
- }
-
- if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {
- ped->QuitEnteringCar();
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR)
- ped->SetFall(1000, ANIM_KO_SPIN_R, false);
- else
- ped->SetFall(1000, ANIM_KO_SPIN_L, false);
-
- return;
- }
- veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f);
-
- if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF)
- 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;
- } else if (isBus) {
- animToPlay = ANIM_COACH_IN_R;
- } else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_RHS;
- } else {
- animToPlay = ANIM_CAR_GETIN_RHS;
+ if (bIsStanding) {
+ bIsStanding = false;
+ bWasStanding = true;
}
- } else if (isVan) {
- animToPlay = ANIM_VAN_GETIN_L;
- } else if (isBus) {
- animToPlay = ANIM_COACH_IN_L;
- } else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_LHS;
- } else {
- animToPlay = ANIM_CAR_GETIN_LHS;
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- } else {
- CPed *pedToDragOut = nil;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break;
- case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break;
- case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break;
- case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break;
- default: assert(0);
- }
-
- if (vehUpsideDown) {
- ped->QuitEnteringCar();
- if (ped->m_nPedType == PEDTYPE_COP)
- ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
- }
-
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
- if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {
- if (pedToDragOut->m_nPedState != PED_DRIVING) {
- ped->QuitEnteringCar();
- pedToDragOut = nil;
- } else {
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
- }
- } else if (ped->m_nPedType == PEDTYPE_COP) {
- ped->QuitEnteringCar();
- if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) {
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
- } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) {
- ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);
- }
+ bCollisionProcessed = true;
+ m_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep();
+ bStillOnValidPoly = false;
+ if (IsPlayer() || m_fCollisionSpeed >= 1.0f
+ && (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) {
+ m_collPoly.valid = false;
+ m_fCollisionSpeed = 0.0f;
+ bHitSteepSlope = false;
} else {
- // BUG: Probably we will sit on top of the passenger if his m_ped_flagF4 is true.
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- }
- } else {
- if (pedToDragOut) {
- if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {
-
- // BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC.
- ped->QuitEnteringCar();
- pedToDragOut = nil;
- } else {
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ CVector pos = GetPosition();
+ float potentialGroundZ = GetPosition().z - FEET_OFFSET;
+ if (bWasStanding) {
+ pos.z += -0.25f;
+ potentialGroundZ += gravityEffect;
}
- } else {
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- }
- }
-
- if (pedToDragOut) {
- pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false);
- if (pedToDragOut->IsGangMember())
- pedToDragOut->RegisterThreatWithGangPeds(ped);
- }
- }
-
- if (veh->pDriver && ped) {
- veh->pDriver->SetLookFlag(ped, true);
- veh->pDriver->SetLookTimer(1000);
- }
- return;
-}
-
-void
-CPed::SetJump(void)
-{
- if (!bInVehicle &&
-#if defined VC_PED_PORTS || defined FIX_BUGS
- m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) &&
-#endif
- (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) {
- SetStoredState();
- m_nPedState = PED_JUMP;
- CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f);
- jumpAssoc->SetFinishCallback(FinishLaunchCB, this);
- m_fRotationDest = m_fRotationCur;
- }
-}
-
-void
-CPed::RemoveInCarAnims(void)
-{
- if (!IsPlayer())
- return;
-
- 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;
- }
-
-#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
-CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*) arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
- return;
-
- if (!ped->EnteringCar()) {
+ if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) {
+ bStillOnValidPoly = true;
#ifdef VC_PED_PORTS
- if(ped->m_nPedState != PED_DRIVING)
+ if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ if (bSomeVCflag1)
+ bSomeVCflag1 = false;
+ }
+#else
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
#endif
- ped->QuitEnteringCar();
- return;
- }
-
- if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) {
- PedSetInCarCB(nil, ped);
- ped->m_nLastPedState = ped->m_nPedState;
- ped->m_nPedState = PED_ARRESTED;
- ped->bGonnaKillTheCarJacker = false;
- if (veh) {
- veh->m_nNumGettingIn = 0;
- veh->m_nGettingInFlags = 0;
- veh->bIsHandbrakeOn = true;
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- }
- return;
- }
- if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF
- && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)
- && veh->IsCar()) {
- if (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING)
- ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
- PedSetInCarCB(nil, ped);
- return;
- }
- bool isVan = !!veh->bIsVan;
- bool isBus = !!veh->bIsBus;
- bool isLow = !!veh->bLowVehicle;
- eDoors enterDoor;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- isVan = false;
- enterDoor = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- enterDoor = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- isVan = false;
- enterDoor = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- enterDoor = DOOR_REAR_LEFT;
- break;
- default:
- break;
- }
- if (!veh->IsDoorMissing(enterDoor)) {
- if (veh->IsCar())
- ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING);
- }
- CPed *driver = veh->pDriver;
- if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
- if (veh->bIsBus) {
- driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- if (driver->IsPlayer()) {
- veh->bIsHandbrakeOn = true;
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- }
- driver->bBusJacked = true;
- veh->bIsBeingCarJacked = false;
- PedSetInCarCB(nil, ped);
- if (ped->m_nPedType == PEDTYPE_COP
- || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT
- || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
- ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- }
- ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400;
- return;
- }
- if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) {
- if (!driver->IsPlayer()) {
- driver->bUsePedNodeSeek = true;
- driver->m_pLastPathNode = nil;
- if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear
- || driver->CharCreatedBy == MISSION_CHAR
- || veh->VehicleCreatedBy == MISSION_VEHICLE) {
- driver->bFleeAfterExitingCar = true;
+ m_vecMoveSpeed.z = 0.0f;
+ bIsStanding = true;
} else {
- driver->bGonnaKillTheCarJacker = true;
- veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped);
-
- if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) {
- FindPlayerPed()->SetWantedLevelNoDrop(1);
- }
+ m_collPoly.valid = false;
+ m_fCollisionSpeed = 0.0f;
+ bHitSteepSlope = false;
}
}
- if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY)
- && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) {
- veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- veh->pDriver->Say(SOUND_PED_CAR_JACKED);
-#ifdef VC_PED_PORTS
- veh->pDriver->SetRadioStation();
-#endif
- } else {
- ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
- }
- }
- }
- 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;
- } else if (isLow) {
- animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS;
- } else {
- animToPlay = ANIM_CAR_CLOSEDOOR_RHS;
- }
- } else if (isVan) {
- animToPlay = ANIM_VAN_CLOSE_L;
- } else if (isLow) {
- animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS;
- } else {
- animToPlay = ANIM_CAR_CLOSEDOOR_LHS;
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
- }
-}
-
-void
-CPed::SetPedPositionInTrain(void)
-{
- LineUpPedWithTrain();
-}
-
-void
-CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- CVehicle* veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (ped->EnteringCar()) {
- if (!ped->IsNotInWreckedVehicle())
- return;
-
-#ifdef CANCELLABLE_CAR_ENTER
- if (ped->bCancelEnteringCar) {
- ped->QuitEnteringCar();
- ped->RestorePreviousObjective();
- ped->bCancelEnteringCar = false;
- return;
}
-#endif
- bool isLow = !!veh->bLowVehicle;
-
- int padNo;
- if (ped->IsPlayer()) {
+ if (!bStillOnValidPoly) {
+ CVector potentialCenter = GetPosition();
+ potentialCenter.z = GetPosition().z - 0.52f;
- // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
- switch (ped->m_nPedType) {
- case PEDTYPE_PLAYER1:
- padNo = 0;
- break;
- case PEDTYPE_PLAYER2:
- padNo = 1;
- break;
- case PEDTYPE_PLAYER3:
- padNo = 2;
- break;
- case PEDTYPE_PLAYER4:
- padNo = 3;
- break;
- }
- CPad *pad = CPad::GetPad(padNo);
-
- if (!pad->ArePlayerControlsDisabled()) {
-
- if (pad->GetTarget()
- || pad->NewState.LeftStickX
- || pad->NewState.LeftStickY
- || pad->NewState.DPadUp
- || pad->NewState.DPadDown
- || pad->NewState.DPadLeft
- || pad->NewState.DPadRight) {
- ped->QuitEnteringCar();
- ped->RestorePreviousObjective();
- return;
+ // 0.52f should be a ped's approx. radius
+ float totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect;
+ if (bWasStanding) {
+ if (collidedWithBoat) {
+ potentialCenter.z += 2.0f * gravityEffect;
+ totalRadiusWhenCollided += Abs(gravityEffect);
+ } else {
+ potentialCenter.z += gravityEffect;
}
}
- }
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- AnimationId animToPlay;
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
- if (isLow)
- animToPlay = ANIM_CAR_GETIN_LOW_RHS;
- else
- animToPlay = ANIM_CAR_GETIN_RHS;
- } else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_LHS;
- } else {
- animToPlay = ANIM_CAR_GETIN_LHS;
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- } else {
- ped->QuitEnteringCar();
- }
- } else {
- ped->QuitEnteringCar();
- }
-}
-
-void
-CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- CVehicle* veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (!veh) {
- PedSetOutCarCB(nil, ped);
- return;
- }
-#ifdef VC_PED_PORTS
- CVector posForZ = ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&posForZ);
- if (ped->GetPosition().z - 0.5f > posForZ.z) {
- PedSetOutCarCB(nil, ped);
- return;
- }
-#endif
- veh->m_nStaticFrames = 0;
- veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f);
- veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f);
- if (!veh->bIsBus)
- veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f);
-
- /*
- // Duplicate and only in PC for some reason
- if (!veh) {
- PedSetOutCarCB(nil, ped);
- return;
- }
- */
- eDoors door;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- door = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- door = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- door = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- door = DOOR_REAR_LEFT;
- break;
- default:
- break;
- }
- bool closeDoor = false;
- if (!veh->IsDoorMissing(door))
- closeDoor = true;
-
- int padNo;
- if (ped->IsPlayer()) {
-
- // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
- switch (ped->m_nPedType) {
- case PEDTYPE_PLAYER1:
- padNo = 0;
- break;
- case PEDTYPE_PLAYER2:
- padNo = 1;
- break;
- case PEDTYPE_PLAYER3:
- padNo = 2;
- break;
- case PEDTYPE_PLAYER4:
- padNo = 3;
- break;
- }
- CPad* pad = CPad::GetPad(padNo);
- bool engineIsIntact = false;
- if (veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225) {
- engineIsIntact = true;
- }
- if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS
- && (pad->GetTarget()
- || pad->NewState.LeftStickX
- || pad->NewState.LeftStickY
- || pad->NewState.DPadUp
- || pad->NewState.DPadDown
- || pad->NewState.DPadLeft
- || pad->NewState.DPadRight)
- || veh->bIsBus
- || veh->m_pCarFire
- || engineIsIntact) {
- closeDoor = false;
- }
- }
-
-#ifdef VC_PED_PORTS
- if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
- closeDoor = false;
-#endif
-
- if (!closeDoor) {
- if (!veh->IsDoorMissing(door) && !veh->bIsBus) {
- ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
- }
- PedSetOutCarCB(nil, ped);
- return;
- }
-
- if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) {
- // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa?
- if (!veh->IsDoorMissing(door))
- ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
- } else {
- switch (door) {
- case DOOR_FRONT_LEFT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
- break;
- case DOOR_FRONT_RIGHT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
- break;
- case DOOR_REAR_LEFT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
- break;
- case DOOR_REAR_RIGHT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
- break;
- default:
- break;
- }
- }
-
- if (ped->m_pVehicleAnim)
- ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);
- return;
-}
-
-void
-CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- if (!animAssoc) {
- ped->ClearLookFlag();
- if (ped->m_nPedState != PED_DIVE_AWAY && ped->m_nPedState != PED_STEP_AWAY)
- return;
-
- ped->RestorePreviousState();
- } else if (animAssoc->animId == ANIM_EV_DIVE) {
- ped->bUpdateAnimHeading = true;
- ped->ClearLookFlag();
- if (ped->m_nPedState == PED_DIVE_AWAY)
- {
- ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1;
- ped->m_nPedState = PED_FALL;
- }
- animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) {
- ped->ClearLookFlag();
- if (ped->m_nPedState != PED_DIVE_AWAY && ped->m_nPedState != PED_STEP_AWAY)
- return;
-
- ped->RestorePreviousState();
- } else if (ped->m_nPedState != PED_ARRESTED) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (animAssoc->blendDelta >= 0.0f)
- animAssoc->blendDelta = -4.0f;
-
- ped->ClearLookFlag();
- if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) {
- ped->RestorePreviousState();
- }
- }
-}
-
-void
-CPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- if (ped->m_nPedState == PED_GETUP)
- RpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f);
-
- ped->bFallenDown = false;
- animAssoc->blendDelta = -1000.0f;
- if (ped->m_nPedState == PED_GETUP)
- ped->RestorePreviousState();
-
- if (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY)
- ped->SetMoveState(PEDMOVE_STILL);
- else
- ped->SetMoveState(PEDMOVE_RUN);
-
- ped->SetMoveAnim();
- ped->bGetUpAnimStarted = false;
-}
-
-void
-CPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- animAssoc->blendDelta = -1000.0f;
- ped->bIsLanding = false;
-
- if (ped->m_nPedState == PED_JUMP)
- ped->RestorePreviousState();
-}
-
-void
-CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed *ped = (CPed*)arg;
-
- ped->bUsesCollision = true;
- ped->RestartNonPartialAnims();
- bool itsRearDoor = false;
-
- if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
- itsRearDoor = true;
-
- CMatrix pedMat(ped->GetMatrix());
- CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset));
- posAfterBeingDragged += ped->GetPosition();
-#ifndef VC_PED_PORTS
- posAfterBeingDragged.z += 1.0f;
-#endif
- CPedPlacement::FindZCoorForPed(&posAfterBeingDragged);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(posAfterBeingDragged);
-
- if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) {
- ped->PositionPedOutOfCollision();
- }
-
- if (!ped->CanSetPedState())
- return;
-
- if (!ped->m_pMyVehicle) {
- ped->SetIdle();
- ped->SetGetUp();
- return;
- }
-
- CPed *driver = ped->m_pMyVehicle->pDriver;
-
- if (ped->IsPlayer()) {
- ped->SetIdle();
-
- } else if (ped->bFleeAfterExitingCar) {
- ped->bFleeAfterExitingCar = false;
- ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
-
- } else if (ped->bWanderPathAfterExitingCar) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- ped->bWanderPathAfterExitingCar = false;
-
- } else if (ped->bGonnaKillTheCarJacker) {
- // Kill objective is already set at this point.
-
- ped->bGonnaKillTheCarJacker = false;
- if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) {
- if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
- ped->m_nPedState = PED_NONE;
- ped->m_nLastPedState = PED_NONE;
- ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
- } else {
- ped->ClearObjective();
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
- }
- }
-
- } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
- && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver
- && driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) {
+ if (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) {
+ ourLine.p0 = GetPosition();
+ ourLine.p1 = GetPosition();
+ ourLine.p1.z = GetPosition().z - FEET_OFFSET;
+ if (bWasStanding) {
+ ourLine.p1.z = ourLine.p1.z + gravityEffect;
+ ourLine.p0.z = ourLine.p0.z + -0.25f;
+ }
+ float minDist = 1.0f;
+ belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
+ intersectionPoint, minDist, false, &m_collPoly);
+ if (collidedWithBoat && bWasStanding && !belowTorsoCollided) {
+ ourLine.p0.z = ourLine.p1.z;
+ ourLine.p1.z = ourLine.p1.z + gravityEffect;
+ belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
+ intersectionPoint, minDist, false, &m_collPoly);
+ }
+ if (belowTorsoCollided) {
#ifndef VC_PED_PORTS
- if (CGeneral::GetRandomNumber() & 1)
- ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver);
- else
-#endif
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
-
- } else {
-#ifdef VC_PED_PORTS
- if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
- && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver
- && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission())
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
- else
-#endif
- {
- ped->m_nPedState = PED_NONE;
- ped->m_nLastPedState = PED_NONE;
- ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000);
- }
- }
- ped->SetGetUp();
-}
-
-void
-CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- // Pointless code
- if (!veh)
- return;
-
-#ifdef VC_PED_PORTS
- // Situation of entering car as a driver while there is already a driver exiting atm.
- CPed *driver = veh->pDriver;
- if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR
- && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
-
- if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) {
- ped->QuitEnteringCar();
- return;
- }
- if (driver->CharCreatedBy == MISSION_CHAR) {
- PedSetOutCarCB(nil, veh->pDriver);
- if (driver->m_pMyVehicle) {
- driver->PositionPedOutOfCollision();
- } else {
- driver->m_pMyVehicle = veh;
- driver->PositionPedOutOfCollision();
- driver->m_pMyVehicle = nil;
- }
- veh->pDriver = nil;
- } else {
- driver->SetDead();
- driver->FlagToDestroyWhenNextProcessed();
- veh->pDriver = nil;
- }
- }
-#endif
-
- if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
- return;
-
- ped->bInVehicle = true;
- if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
- if (veh->pDriver) {
- if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
- CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000;
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
- CWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped;
- }
- }
- }
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
-#if defined VC_PED_PORTS || defined FIX_BUGS
- || ped->m_nPedState == PED_CARJACK
-#endif
- )
- veh->bIsBeingCarJacked = false;
-
- if (veh->m_nNumGettingIn)
- --veh->m_nNumGettingIn;
-
- if (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive)
- ((CPlayerPed*)ped)->ClearAdrenaline();
-
- if (veh->IsBoat()) {
- if (ped->IsPlayer()) {
-#if defined VC_PED_PORTS || defined FIX_BUGS
- CCarCtrl::RegisterVehicleOfInterest(veh);
-#endif
- if (veh->GetStatus() == STATUS_SIMPLE) {
- veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f);
- veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- veh->SetStatus(STATUS_PLAYER);
- AudioManager.PlayerJustGotInCar();
- }
- veh->SetDriver(ped);
- if (!veh->bEngineOn)
- veh->bEngineOn = true;
-
- ped->m_nPedState = PED_DRIVING;
- ped->StopNonPartialAnims();
- return;
- }
-
- if (ped->m_pVehicleAnim)
- ped->m_pVehicleAnim->blendDelta = -1000.0f;
-
- ped->bDoBloodyFootprints = false;
- if (veh->m_nAlarmState == -1)
- veh->m_nAlarmState = 15000;
-
- if (ped->IsPlayer()) {
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (veh->GetStatus() == STATUS_SIMPLE) {
- veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- veh->SetStatus(STATUS_PLAYER);
- }
- AudioManager.PlayerJustGotInCar();
- } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (veh->GetStatus() == STATUS_SIMPLE) {
- veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- veh->SetStatus(STATUS_PHYSICS);
- }
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) {
- CPed *passenger = veh->pPassengers[i];
- if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) {
- passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
-#ifdef VC_PED_PORTS
- passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds();
-#endif
- }
- }
- }
- // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below.
-#if !defined VC_PED_PORTS && !defined FIX_BUGS
- else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- if (ped->m_nPedState == PED_CARJACK) {
- veh->AddPassenger(ped, 0);
- ped->m_nPedState = PED_DRIVING;
- ped->RestorePreviousObjective();
- ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) {
- veh->AutoPilot.m_nCruiseSpeed = 17;
- }
- }
+ if (!collidingEnt->IsPed()) {
#endif
+ if (!bIsStanding
+ || FEET_OFFSET + intersectionPoint.point.z > GetPosition().z
+ || collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) {
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) {
- veh->SetDriver(ped);
- if (veh->VehicleCreatedBy == PARKED_VEHICLE) {
- veh->VehicleCreatedBy = RANDOM_VEHICLE;
- ++CCarCtrl::NumRandomCars;
- --CCarCtrl::NumParkedCars;
- }
- if (veh->bIsAmbulanceOnDuty) {
- veh->bIsAmbulanceOnDuty = false;
- --CCarCtrl::NumAmbulancesOnDuty;
- }
- if (veh->bIsFireTruckOnDuty) {
- veh->bIsFireTruckOnDuty = false;
- --CCarCtrl::NumFiretrucksOnDuty;
- }
- if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
- veh->ChangeLawEnforcerState(true);
-
- if (!veh->bEngineOn) {
- veh->bEngineOn = true;
- DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
- }
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR
- && ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) {
-
- CCarCtrl::JoinCarWithRoadSystem(veh);
- veh->AutoPilot.m_nCarMission = MISSION_CRUISE;
- veh->AutoPilot.m_nTempAction = TEMPACT_NONE;
- veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- veh->AutoPilot.m_nCruiseSpeed = 25;
- }
- ped->m_nPedState = PED_DRIVING;
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
-
- if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
- ped->m_prevObjective = OBJECTIVE_NONE;
-
- ped->RestorePreviousObjective();
- }
-
- } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- if (veh->bIsBus) {
- veh->AddPassenger(ped);
- } else {
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- veh->AddPassenger(ped, 0);
- break;
- case CAR_DOOR_RR:
- veh->AddPassenger(ped, 2);
- break;
- case CAR_DOOR_LR:
- veh->AddPassenger(ped, 1);
- break;
- default:
- veh->AddPassenger(ped);
- break;
- }
- }
- ped->m_nPedState = PED_DRIVING;
- if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
- ped->m_prevObjective = OBJECTIVE_NONE;
-
- ped->RestorePreviousObjective();
+ if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) {
+ m_pCurSurface = collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
+ bTryingToReachDryLand = false;
+ bOnBoat = false;
+ } else {
+ m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);
+ m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();
+ m_pCurSurface = collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
+ m_collPoly.valid = false;
+ if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) {
+ bOnBoat = true;
+ } else {
+ bOnBoat = false;
+ }
+ }
#ifdef VC_PED_PORTS
- if(veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR)
- veh->AutoPilot.m_nCruiseSpeed = 17;
-#endif
- }
-
- veh->m_nGettingInFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
-
- if (veh->bIsBus && !veh->m_nGettingInFlags)
- ((CAutomobile*)veh)->SetBusDoorTimer(1000, 1);
-
- switch (ped->m_objective) {
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_LEAVE_CAR:
- case OBJECTIVE_FOLLOW_CAR_IN_CAR:
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
- break;
- default:
- 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();
- if (veh->bIsBus)
- ped->bRenderPedInCar = false;
-
- // FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check.
-#ifndef FIX_BUGS
- if (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ if (bSomeVCflag1)
+ bSomeVCflag1 = false;
+ }
#else
- if (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) {
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
#endif
- CCarCtrl::RegisterVehicleOfInterest(veh);
-
- if (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE)
- CEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500);
-
- veh->bHasBeenOwnedByPlayer = true;
- }
- ped->bChangedSeat = true;
-}
-
-void
-CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed *ped = (CPed*)arg;
- CTrain *veh = (CTrain*)ped->m_pMyVehicle;
-
- if (!veh)
- return;
-
- ped->bInVehicle = true;
- ped->m_nPedState = PED_DRIVING;
- ped->RestorePreviousObjective();
- ped->SetMoveState(PEDMOVE_STILL);
- veh->AddPassenger(ped);
-}
+ m_nSurfaceTouched = intersectionPoint.surfaceB;
+ if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) {
+ bHitSteepSlope = true;
+ m_vecDamageNormal = intersectionPoint.normal;
+ }
+ }
+#ifdef VC_PED_PORTS
+ float upperSpeedLimit = 0.33f;
+ float lowerSpeedLimit = -0.25f;
+ float speed = m_vecMoveSpeed.Magnitude2D();
+ if (m_nPedState == PED_IDLE) {
+ upperSpeedLimit *= 2.0f;
+ lowerSpeedLimit *= 1.5f;
+ }
+ CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
+ if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit)
+ && m_pCollidingEntity != collidingEnt) {
-void
-CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- /*
- CPed *ped = (CPed*)arg;
+ float damage = 100.0f * Max(speed - 0.25f, 0.0f);
+ float damage2 = damage;
+ if (m_vecMoveSpeed.z < -0.25f)
+ damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;
- if (ped->m_nPedState == PED_STAGGER)
- // nothing
- */
-}
+ 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);
+ }
-// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up.
-bool
-CPed::RunToReportCrime(eCrimeType crimeToReport)
-{
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- if (bRunningToPhone) {
- if (!isPhoneAvailable(m_phoneId)) {
- m_phoneId = -1;
- bIsRunning = false;
- ClearSeek(); // clears bRunningToPhone
- return false;
- }
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir);
+ if (IsPlayer() && damage2 > 5.0f)
+ Say(SOUND_PED_LAND);
- return true;
- }
+ } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
+ }
#else
- // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it.
- if (m_nPedState == PED_SEEK_POS)
- return false;
-#endif
-
- CVector pos = GetPosition();
- int phoneId = gPhoneInfo.FindNearestFreePhone(&pos);
-
- if (phoneId == -1)
- return false;
-
- CPhone *phone = &gPhoneInfo.m_aPhones[phoneId];
-#ifndef PEDS_REPORT_CRIMES_ON_PHONE
- if (phone->m_nState != PHONE_STATE_FREE)
- return false;
-#endif
-
- bRunningToPhone = true;
- SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f
- SetMoveState(PEDMOVE_RUN);
- bIsRunning = true; // not there in original
- m_phoneId = phoneId;
- m_crimeToReportOnPhone = crimeToReport;
- return true;
-}
-
-void
-CPed::RegisterThreatWithGangPeds(CEntity *attacker)
-{
- CPed *attackerPed = nil;
- if (attacker) {
- if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) {
- if (attacker->IsPed()) {
- attackerPed = (CPed*)attacker;
- } else {
- if (!attacker->IsVehicle())
- return;
-
- attackerPed = ((CVehicle*)attacker)->pDriver;
- if (!attackerPed)
- return;
- }
-
- if (attackerPed && (attackerPed->IsPlayer() || attackerPed->IsGangMember())) {
- for (int i = 0; i < m_numNearPeds; ++i) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed->IsPointerValid()) {
- if (nearPed != this && nearPed->m_nPedType == m_nPedType)
- nearPed->m_fearFlags |= CPedType::GetFlag(attackerPed->m_nPedType);
- }
- }
- }
- }
- }
-
- if (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) {
- if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOYZ) {
- int16 lastVehicle;
- CEntity *vehicles[8];
- CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
-
- if (lastVehicle > 8)
- lastVehicle = 8;
-
- for (int j = 0; j < lastVehicle; ++j) {
- CVehicle *nearVeh = (CVehicle*) vehicles[j];
-
- if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
- CPed *nearVehDriver = nearVeh->pDriver;
+ float speedSqr = 0.0f;
+ CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
+ if (!bWasStanding && (m_vecMoveSpeed.z < -0.25f || (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) > sq(0.5f))) {
+ if (speedSqr == 0.0f)
+ speedSqr = sq(m_vecMoveSpeed.z);
- if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType) {
+ 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);
- if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
- nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
- nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
- nearVeh->SetStatus(STATUS_PHYSICS);
- nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;
- nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
}
+#endif
+ m_vecMoveSpeed.z = 0.0f;
+ bIsStanding = true;
+#ifndef VC_PED_PORTS
+ } else {
+ bOnBoat = false;
}
+#endif
+ } else {
+ bOnBoat = false;
}
}
}
}
-}
-
-void
-CPed::ReactToPointGun(CEntity *entWithGun)
-{
- CPed *pedWithGun = (CPed*)entWithGun;
- int waitTime;
-
- if (IsPlayer() || !IsPedInControl() || CharCreatedBy == MISSION_CHAR)
- return;
-
- if (m_leader == pedWithGun)
- return;
-
- if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER ||
- (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f)
- return;
- if (m_leader) {
- if (FindPlayerPed() == m_leader)
- return;
-
- ClearLeader();
- }
- if (m_pedStats->m_flags & STAT_GUN_PANIC
- && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())
- && m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_AIM_GUN) {
-
- waitTime = CGeneral::GetRandomNumberInRange(3000, 6000);
- SetWaitState(WAITSTATE_PLAYANIM_HANDSCOWER, &waitTime);
- Say(SOUND_PED_HANDS_COWER);
- m_pLookTarget = pedWithGun;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- SetMoveState(PEDMOVE_NONE);
-
- } else if (m_nPedType != pedWithGun->m_nPedType) {
- if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
- RegisterThreatWithGangPeds(pedWithGun);
- }
-
- if (m_nPedType == PEDTYPE_COP) {
- if (pedWithGun->IsPlayer()) {
- ((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2);
- }
- if (bCrouchWhenShooting || bKindaStayInSamePlace) {
- SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000));
- }
-
- } else if (m_nPedType != PEDTYPE_COP
- && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())
- && (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun)
- && m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
-
- waitTime = CGeneral::GetRandomNumberInRange(3000, 6000);
- SetWaitState(WAITSTATE_PLAYANIM_HANDSUP, &waitTime);
- Say(SOUND_PED_HANDS_UP);
- m_pLookTarget = pedWithGun;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- SetMoveState(PEDMOVE_NONE);
- if (m_nPedState == PED_FLEE_ENTITY) {
- m_fleeFrom = pedWithGun;
- m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
- }
+ int ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil);
+ if (ourCollidedSpheres > 0 || belowTorsoCollided) {
+ AddCollisionRecord(collidingEnt);
+ if (!collidingEnt->IsBuilding())
+ ((CPhysical*)collidingEnt)->AddCollisionRecord(this);
- if (FindPlayerPed() == pedWithGun && bRichFromMugging) {
- int money = CGeneral::GetRandomNumberInRange(100, 300);
- int pickupCount = money / 40 + 1;
- 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;
- if (found) {
- CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
- }
- }
- bRichFromMugging = false;
- }
+ if (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) {
+ bHasHitWall = true;
}
}
-}
-
-void
-CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- bool startedToRun = false;
- ped->bUsesCollision = true;
- ped->m_actionX = 0.0f;
- ped->m_actionY = 0.0f;
- ped->bVehExitWillBeInstant = false;
- if (veh && veh->IsBoat())
- ped->ApplyMoveSpeed();
+ if (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) {
- if (ped->m_objective == OBJECTIVE_LEAVE_CAR)
- ped->RestorePreviousObjective();
+ if (bWasStanding) {
+ CVector sphereNormal;
+ float normalLength;
+ for(int sphere = 0; sphere < ourCollidedSpheres; sphere++) {
+ sphereNormal = collidingPoints[sphere].normal;
#ifdef VC_PED_PORTS
- else if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
- ped->m_fHealth = 0.0f;
- ped->SetDie(ANIM_FLOOR_HIT, 4.0f, 0.5f);
- }
+ if (sphereNormal.z >= -1.0f || !IsPlayer()) {
#endif
-
- ped->bInVehicle = false;
- if (veh && veh->IsCar() && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) {
- ped->PositionPedOutOfCollision();
- }
-
- if (ped->m_nPedState == PED_EXIT_CAR) {
- if (ped->m_nPedType == PEDTYPE_COP)
- ped->SetIdle();
- else
- ped->RestorePreviousState();
-
- veh = ped->m_pMyVehicle;
- if (ped->bFleeAfterExitingCar && veh) {
- ped->bFleeAfterExitingCar = false;
- ped->SetFlee(veh->GetPosition(), 12000);
- ped->bUsePedNodeSeek = true;
- ped->m_pNextPathNode = nil;
- if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
- ped->SetMoveState(PEDMOVE_SPRINT);
- ped->Say(SOUND_PED_FLEE_SPRINT);
- } else {
- ped->SetMoveState(PEDMOVE_RUN);
- ped->Say(SOUND_PED_FLEE_RUN);
- }
- startedToRun = true;
-
- // This is not a good way to do this...
- ped->m_nLastPedState = PED_WANDER_PATH;
-
- } else if (ped->bWanderPathAfterExitingCar) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- ped->bWanderPathAfterExitingCar = false;
- if (ped->m_nPedType == PEDTYPE_PROSTITUTE)
- ped->SetObjectiveTimer(30000);
- ped->m_nLastPedState = PED_NONE;
-
- } else if (ped->bGonnaKillTheCarJacker) {
-
- // Kill objective is already given at this point.
- ped->bGonnaKillTheCarJacker = false;
- if (ped->m_pedInObjective) {
- if (!(CGeneral::GetRandomNumber() & 1)
- && ped->m_nPedType != PEDTYPE_COP
- && (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) {
- ped->ClearObjective();
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
- }
- ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500;
- }
- int waitTime = 1500;
- ped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime);
- ped->SetMoveState(PEDMOVE_RUN);
- startedToRun = true;
- } else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- }
- }
+ normalLength = sphereNormal.Magnitude2D();
+ if (normalLength != 0.0f) {
+ sphereNormal.x = sphereNormal.x / normalLength;
+ sphereNormal.y = sphereNormal.y / normalLength;
+ }
#ifdef VC_PED_PORTS
- else {
- ped->m_nPedState = PED_IDLE;
- }
-#endif
-
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- ped->RestartNonPartialAnims();
- ped->m_pVehicleAnim = nil;
- CVector posFromZ = ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&posFromZ);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(posFromZ);
- veh = ped->m_pMyVehicle;
- if (veh) {
- if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
- if (veh->pDriver) {
- if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0;
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0;
- CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100;
- if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0)
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0;
- }
- }
- }
- veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
- if (veh->pDriver == ped) {
- veh->RemoveDriver();
- veh->SetStatus(STATUS_ABANDONED);
- if (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- veh->m_nDoorLock = CARLOCK_UNLOCKED;
- if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
- veh->ChangeLawEnforcerState(false);
- } else {
- veh->RemovePassenger(ped);
- }
-
- if (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) {
- float angleAfterExit;
- if (ped->m_vehEnterType == CAR_DOOR_LF) {
- angleAfterExit = HALFPI + veh->GetForward().Heading();
- } else {
- angleAfterExit = veh->GetForward().Heading() - HALFPI;
- }
- ped->SetHeading(angleAfterExit);
- ped->m_fRotationDest = angleAfterExit;
- ped->m_fRotationCur = angleAfterExit;
- if (!ped->bBusJacked)
- ped->SetMoveState(PEDMOVE_WALK);
- }
- if (CGarages::IsPointWithinAnyGarage(ped->GetPosition()))
- veh->bLightsOn = false;
- }
-
- if (ped->IsPlayer())
- AudioManager.PlayerJustLeftCar();
-
- ped->ReplaceWeaponWhenExitingVehicle();
-
- ped->bOnBoat = false;
- if (ped->bBusJacked) {
- ped->SetFall(1500, ANIM_KO_SKID_BACK, false);
- ped->bBusJacked = false;
- }
- ped->m_nStoredMoveState = PEDMOVE_NONE;
- if (!ped->IsPlayer()) {
- // It's a shame...
-#ifdef FIX_BUGS
- int createdBy = ped->CharCreatedBy;
-#else
- int createdBy = !ped->CharCreatedBy;
-#endif
-
- if (createdBy == MISSION_CHAR && !startedToRun)
- ped->SetMoveState(PEDMOVE_WALK);
- }
-}
-
-// It was inlined in III but not in VC.
-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() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {
- SetCurrentWeapon(m_storedWeapon);
- m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
- }
- } else {
- AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);
- }
-}
-
-// Same, it's inlined in III.
-inline void
-CPed::RemoveWeaponWhenEnteringVehicle(void)
-{
- if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
- if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
- m_storedWeapon = GetWeapon()->m_eWeaponType;
- SetCurrentWeapon(WEAPONTYPE_UZI);
- } else {
- CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(ourWeapon->m_nModelId);
- }
-}
-
-void
-CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- if (ped->m_pVehicleAnim)
- ped->m_pVehicleAnim->blendDelta = -1000.0f;
-
- ped->bUsesCollision = true;
- ped->m_pVehicleAnim = nil;
- ped->bInVehicle = false;
- ped->m_nPedState = PED_IDLE;
- ped->RestorePreviousObjective();
- ped->SetMoveState(PEDMOVE_STILL);
-
- CMatrix pedMat(ped->GetMatrix());
- ped->m_fRotationCur = HALFPI + veh->GetForward().Heading();
- ped->m_fRotationDest = ped->m_fRotationCur;
- CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset);
- posAfterExit += ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&posAfterExit);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(posAfterExit);
- ped->SetHeading(ped->m_fRotationCur);
- veh->RemovePassenger(ped);
-}
-
-bool
-CPed::PlacePedOnDryLand(void)
-{
- float waterLevel = 0.0f;
- CEntity *foundEnt = nil;
- CColPoint foundCol;
- float foundColZ;
-
- CWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel);
-
- CVector potentialGround = GetPosition();
- potentialGround.z = waterLevel;
-
- if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
- return false;
-
- CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
- potentialGroundDist.z = 0.0f;
- potentialGroundDist.Normalise();
-
- CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;
- posToCheck.z = 3.0f + waterLevel;
-
- if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) {
- foundColZ = foundCol.point.z;
- if (foundColZ >= waterLevel) {
- posToCheck.z = 0.8f + foundColZ;
- SetPosition(posToCheck);
- bIsStanding = true;
- bWasStanding = true;
- return true;
- }
- }
-
- posToCheck = 5.0f * potentialGroundDist + GetPosition();
- posToCheck.z = 3.0f + waterLevel;
-
- if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil))
- return false;
-
- foundColZ = foundCol.point.z;
- if (foundColZ < waterLevel)
- return false;
-
- posToCheck.z = 0.8f + foundColZ;
- SetPosition(posToCheck);
- bIsStanding = true;
- bWasStanding = true;
- return true;
-}
-
-void
-CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- CVector finalPos;
- CVector draggedOutOffset;
- CVector finalLocalPos;
-
- CMatrix pedMat(ped->GetMatrix());
- ped->bUsesCollision = true;
- ped->RestartNonPartialAnims();
- draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset;
- if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
- draggedOutOffset.x = -draggedOutOffset.x;
-
- finalLocalPos = Multiply3x3(pedMat, draggedOutOffset);
- finalPos = finalLocalPos + ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&finalPos);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(finalPos);
-
- if (veh) {
- ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI;
- ped->m_fRotationCur = ped->m_fRotationDest;
- ped->CalculateNewOrientation();
-
- if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset))
- ped->PositionPedOutOfCollision();
- }
-
- if (!ped->CanSetPedState())
- return;
-
- ped->SetIdle();
- if (veh) {
- if (ped->bFleeAfterExitingCar) {
- ped->bFleeAfterExitingCar = false;
- ped->SetFlee(veh->GetPosition(), 14000);
-
- } else if (ped->bWanderPathAfterExitingCar) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- ped->bWanderPathAfterExitingCar = false;
-
- } else if (ped->bGonnaKillTheCarJacker) {
- ped->bGonnaKillTheCarJacker = false;
- if (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) {
- if (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT)
- ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective);
-
- } else {
- CPed *driver = veh->pDriver;
- if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
- ped->SetFlee(veh->GetPosition(), 14000);
} else {
- ped->ClearObjective();
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+ float speed = m_vecMoveSpeed.Magnitude2D();
+ 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;
}
- ped->bUsePedNodeSeek = true;
- ped->m_pNextPathNode = nil;
- ped->Say(SOUND_PED_FLEE_RUN);
- }
- } else {
- if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear
- && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE
- && veh->pDriver && veh->pDriver->IsPlayer()
- && !CTheScripts::IsPlayerOnAMission()) {
-
-#ifndef VC_PED_PORTS
- if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) {
- ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver);
- } else
#endif
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
-
- } else {
-#ifdef VC_PED_PORTS
- if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
- && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !veh->pDriver
- && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission())
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
- else
-#endif
- {
- ped->SetFindPathAndFlee(veh->GetPosition(), 10000);
- if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
- ped->SetMoveState(PEDMOVE_SPRINT);
- ped->Say(SOUND_PED_FLEE_SPRINT);
- } else {
- ped->Say(SOUND_PED_FLEE_RUN);
- }
- }
+ sphereNormal.Normalise();
+ collidingPoints[sphere].normal = sphereNormal;
+ if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF)
+ bHitSteepSlope = true;
}
}
}
- if (ped->m_nLastPedState == PED_IDLE)
- ped->m_nLastPedState = PED_WANDER_PATH;
+ return ourCollidedSpheres;
}
-bool
-CPed::PositionPedOutOfCollision(void)
+static void
+particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times)
{
- CVehicle *veh;
- CVector posNearVeh;
- CVector posSomewhereClose;
- bool putNearVeh = false;
- bool putSomewhereClose = false;
- int smallestDistNearVeh = 999;
- int smallestDistSomewhereClose = 999;
-
- if (!m_pMyVehicle)
- return false;
+#ifdef PC_PARTICLE
+ for (int i = 0; i < times; i++) {
+ CVector adjustedPos = pos;
+ adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- CVector vehPos = m_pMyVehicle->GetPosition();
- CVector potentialPos;
- potentialPos.y = GetPosition().y - 3.5f;
- potentialPos.z = GetPosition().z;
-
- for (int yTry = 0; yTry < 15; yTry++) {
- potentialPos.x = GetPosition().x - 3.5f;
-
- for (int xTry = 0; xTry < 15; xTry++) {
- CPedPlacement::FindZCoorForPed(&potentialPos);
- CVector distVec = potentialPos - vehPos;
- float dist = distVec.Magnitude();
-
- // Makes close distances bigger for some reason.
- float mult = (0.6f + dist) / dist;
- CVector adjustedPotentialPos = distVec * mult + vehPos;
- if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false)
- && !CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) {
-
- float potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr();
- veh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false);
- if (veh) {
- if (potentialChangeSqr < smallestDistNearVeh) {
- posNearVeh = potentialPos;
- putNearVeh = true;
- smallestDistNearVeh = potentialChangeSqr;
- }
- } else if (potentialChangeSqr < smallestDistSomewhereClose) {
- smallestDistSomewhereClose = potentialChangeSqr;
- posSomewhereClose = potentialPos;
- putSomewhereClose = true;
- }
- }
- potentialPos.x += 0.5f;
- }
- potentialPos.y += 0.5f;
+ CVector direction = ped->GetForward() * -0.05f;
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
}
-
- if (!putSomewhereClose && !putNearVeh)
- return false;
-
- // We refrain from using posNearVeh, probably because of it may be top of the vehicle.
- if (putSomewhereClose) {
- SetPosition(posSomewhereClose);
- } else {
- CVector vehSize = veh->GetModelInfo()->GetColModel()->boundingBox.max;
- posNearVeh.z += vehSize.z;
- SetPosition(posNearVeh);
+#else
+ for ( int32 i = 0; i < times; i++ )
+ {
+ CVector adjustedPos = pos;
+ adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
+ adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
+
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
}
- return true;
+#endif
}
-bool
-CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh)
+static void
+particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times)
{
- bool foundIt = false;
-
- CVector helperPos = GetPosition();
- helperPos.z = pos->z - 0.5f;
-
- CVector foundPos = *pos;
- foundPos.z -= 0.5f;
-
- // If there is another car between target car and us.
- if (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) {
-
- CColModel *vehCol = veh->GetModelInfo()->GetColModel();
- CVector *colMin = &vehCol->boundingBox.min;
- CVector *colMax = &vehCol->boundingBox.max;
-
- CVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f);
- CVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f);
- CVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f);
- CVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f);
-
- leftRearPos = veh->GetMatrix() * leftRearPos;
- rightRearPos = veh->GetMatrix() * rightRearPos;
- leftFrontPos = veh->GetMatrix() * leftFrontPos;
- rightFrontPos = veh->GetMatrix() * rightFrontPos;
-
- // Makes helperPos veh-ped distance vector.
- helperPos -= veh->GetPosition();
-
- // ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour.
- // On every run it returns another pos. for ped, with same distance to the veh.
- // Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't)
- helperPos = veh->GetMatrix() * helperPos;
-
- float vehForwardHeading = veh->GetForward().Heading();
-
- // I'm absolutely not sure about these namings.
- // NTVF = needed turn if we're looking to vehicle front and wanna look to...
-
- float potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y);
- float NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading);
-
- float potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y);
- float NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading);
-
- float potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y);
- float NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading);
-
- float potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y);
- float NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading);
-
- bool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI;
-
- bool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI;
-
- bool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI;
-
- bool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI;
-
- // Only order of conditions are different among enterTypes.
- if (m_vehEnterType == CAR_DOOR_RR) {
- if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- } else if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
- } else if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- } else if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- }
- } else if(m_vehEnterType == CAR_DOOR_RF) {
- if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
- } else if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- } else if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- } else if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- }
- } else if (m_vehEnterType == CAR_DOOR_LF) {
- if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- } else if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- } else if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
- } else if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- }
- } else if (m_vehEnterType == CAR_DOOR_LR) {
- if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- } else if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- } else if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- } else if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
+ switch (ped->m_nSurfaceTouched)
+ {
+ case SURFACE_TARMAC:
+ case SURFACE_GRAVEL:
+ case SURFACE_PAVEMENT:
+ case SURFACE_SAND:
+ for (int i = 0; i < times; ++i) {
+ CVector adjustedPos = pos;
+ adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0);
}
- }
+ break;
+ default:
+ break;
}
- if (!foundIt)
- return false;
-
- helperPos = GetPosition() - foundPos;
- helperPos.z = 0.0f;
- if (helperPos.MagnitudeSqr() <= sq(0.5f))
- return false;
-
- pos->x = foundPos.x;
- pos->y = foundPos.y;
- return true;
}
void
-CPed::Render(void)
+CPed::PlayFootSteps(void)
{
- if (!bInVehicle || m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR ||
- bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) {
- CEntity::Render();
+ if (bDoBloodyFootprints) {
+ if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) {
+ m_bloodyFootprintCountOrDeathTime--;
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- renderLimb(PED_HEAD);
- renderLimb(PED_HANDL);
- renderLimb(PED_HANDR);
- }
- if(m_pWeaponModel && IsClumpSkinned(GetClump())){
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel);
- *RwFrameGetMatrix(frame) = *mat;
- RwFrameUpdateObjects(frame);
- RpAtomicRender(m_pWeaponModel);
+ if (m_bloodyFootprintCountOrDeathTime == 0)
+ bDoBloodyFootprints = false;
}
-#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)
+ if (!bIsStanding)
return;
- RwFrame *frame = RpAtomicGetFrame(atomic);
- *RwFrameGetMatrix(frame) = *mat;
- RwFrameUpdateObjects(frame);
- int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
- RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha);
- RpAtomicRender(atomic);
-}
-#endif
+ CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump());
+ CAnimBlendAssociation *walkRunAssoc = nil;
+ float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f;
-void
-CPed::ProcessObjective(void)
-{
- if (bClearObjective && (IsPedInControl() || m_nPedState == PED_DRIVING)) {
- ClearObjective();
- bClearObjective = false;
+ for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
+ if (assoc->flags & ASSOC_WALK) {
+ walkRunAssoc = assoc;
+ walkRunAssocBlend += assoc->blendAmount;
+ } else if ((assoc->flags & ASSOC_NOWALK) == 0) {
+ idleAssocBlend += assoc->blendAmount;
+ }
}
- UpdateFromLeader();
- CVector carOrOurPos;
- CVector targetCarOrHisPos;
- CVector distWithTarget;
-
- if (m_objective != OBJECTIVE_NONE && (IsPedInControl() || m_nPedState == PED_DRIVING)) {
- if (bInVehicle) {
- if (!m_pMyVehicle) {
- bInVehicle = false;
- return;
- }
- carOrOurPos = m_pMyVehicle->GetPosition();
- } else {
- carOrOurPos = GetPosition();
+#ifdef GTA_PS2_STUFF
+ CAnimBlendAssociation *runStopAsoc = NULL;
+
+ if ( IsPlayer() )
+ {
+ runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+
+ if ( runStopAsoc == NULL )
+ runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+ }
+
+ if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f )
+ {
+ {
+ CVector pos(0.0f, 0.0f, 0.0f);
+ TransformToNode(pos, PED_FOOTL);
+
+ pos.z -= 0.1f;
+ pos += GetForward()*0.2f;
+ particleProduceFootDust(this, pos, 0.02f, 1);
}
- if (m_pedInObjective) {
- if (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
- targetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition();
- } else {
- targetCarOrHisPos = m_pedInObjective->GetPosition();
- }
- distWithTarget = targetCarOrHisPos - carOrOurPos;
- } else if (m_carInObjective) {
- targetCarOrHisPos = m_carInObjective->GetPosition();
- distWithTarget = targetCarOrHisPos - carOrOurPos;
+ {
+ CVector pos(0.0f, 0.0f, 0.0f);
+ TransformToNode(pos, PED_FOOTR);
+
+ pos.z -= 0.1f;
+ pos += GetForward()*0.2f;
+ particleProduceFootDust(this, pos, 0.02f, 1);
}
+ }
+#endif
+
- switch (m_objective) {
- case OBJECTIVE_NONE:
- case OBJECTIVE_GUARD_AREA:
- case OBJECTIVE_FOLLOW_CAR_IN_CAR:
- case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
- case OBJECTIVE_DESTROY_OBJECT:
- case OBJECTIVE_GOTO_AREA_IN_CAR:
- case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
- case OBJECTIVE_SET_LEADER:
- break;
- case OBJECTIVE_WAIT_ON_FOOT:
- SetIdle();
- m_objective = OBJECTIVE_NONE;
- SetMoveState(PEDMOVE_STILL);
- break;
- case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
- if (InVehicle()) {
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- bFleeAfterExitingCar = true;
- } else if (m_nPedState != PED_FLEE_POS) {
- CVector2D fleePos = GetPosition();
- SetFlee(fleePos, 10000);
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- }
- break;
- case OBJECTIVE_GUARD_SPOT:
- {
- distWithTarget = m_vecSeekPosEx - GetPosition();
- if (m_pedInObjective) {
- SetLookFlag(m_pedInObjective, true);
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- }
- float distWithTargetSc = distWithTarget.Magnitude();
- if (2.0f * m_distanceToCountSeekDoneEx >= distWithTargetSc) {
- if (m_pedInObjective) {
- if (distWithTargetSc <= m_distanceToCountSeekDoneEx)
- SetIdle();
- else
- SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
- } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- int threatType = ScanForThreats();
- SetLookTimer(CGeneral::GetRandomNumberInRange(500, 1500));
-
- // Second condition is pointless and isn't there in Mobile.
- if (threatType == PED_FLAG_GUN || (threatType == PED_FLAG_EXPLOSION && m_threatEntity) || m_threatEntity) {
- if (m_threatEntity->IsPed())
- SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
- }
- }
- } else {
- SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
- }
- break;
- }
- case OBJECTIVE_WAIT_IN_CAR:
- m_nPedState = PED_DRIVING;
- break;
- case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
- m_nPedState = PED_DRIVING;
- break;
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- {
- if (m_pedInObjective) {
- if (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR
- && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0
- && !bKindaStayInSamePlace) {
-
- SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
- break;
- }
- if (InVehicle()) {
- if (distWithTarget.Magnitude() >= 20.0f
- || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) {
- if (m_pMyVehicle->pDriver == this
- && !m_pMyVehicle->m_nGettingInFlags) {
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- m_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;
- if (m_nPedType == PEDTYPE_COP) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity);
- m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
- } else {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
- m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
- }
- m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- }
- } else {
- bool targetHasVeh = m_pedInObjective->bInVehicle;
- if (!targetHasVeh
- || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- }
- }
- break;
- }
- if (distWithTarget.Magnitude() > 30.0f && !bKindaStayInSamePlace) {
- if (m_pMyVehicle) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
- } else {
- float closestVehDist = 60.0f;
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- CVehicle *foundVeh = nil;
- for(int i = 0; i < lastVehicle; i++) {
- CVehicle *nearVeh = (CVehicle*)vehicles[i];
- /*
- Not used.
- CVector vehSpeed = nearVeh->GetSpeed();
- CVector ourSpeed = GetSpeed();
- */
- CVector vehDistVec = nearVeh->GetPosition() - GetPosition();
- if (vehDistVec.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh
- && nearVeh->CanPedOpenLocks(this)) {
-
- foundVeh = nearVeh;
- closestVehDist = vehDistVec.Magnitude();
- }
- }
- m_pMyVehicle = foundVeh;
- if (m_pMyVehicle) {
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
- } else if (!GetIsOnScreen()) {
- CVector ourPos = GetPosition();
- int closestNode = ThePaths.FindNodeClosestToCoors(ourPos, PATH_CAR, 20.0f);
- if (closestNode >= 0) {
- int16 colliding;
- CWorld::FindObjectsKindaColliding(
- ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
- if (!colliding) {
- CZoneInfo zoneInfo;
- int chosenCarClass;
- CTheZones::GetZoneInfoForTimeOfDay(&ourPos, &zoneInfo);
- 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->SetHeading(DEGTORAD(200.0f));
- newVeh->SetStatus(STATUS_ABANDONED);
- newVeh->m_nDoorLock = CARLOCK_UNLOCKED;
- CWorld::Add(newVeh);
- m_pMyVehicle = newVeh;
- if (m_pMyVehicle) {
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
- }
- }
- }
- }
- }
- }
- break;
- }
- } else {
- ClearLookFlag();
- bObjectiveCompleted = true;
- }
- }
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- {
- bool killPlayerInNoPoliceZone = false;
- if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) {
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- break;
- }
- if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {
- ClearLookFlag();
- bObjectiveCompleted = true;
- SetMoveAnim();
- break;
- }
- if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice())
- killPlayerInNoPoliceZone = true;
-
- if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) {
- if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee())
- bNotAllowedToDuck = true;
- } else {
- if (!m_pedInObjective->bInVehicle) {
- if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) {
- bNotAllowedToDuck = false;
- bCrouchWhenShooting = false;
- } else if (DuckAndCover()) {
- break;
- }
- } else {
- bNotAllowedToDuck = false;
- bCrouchWhenShooting = false;
- }
- }
- if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {
- SetMoveState(PEDMOVE_STILL);
- break;
- }
- if (m_pedInObjective->IsPlayer()) {
- CPlayerPed *player = FindPlayerPed();
- if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops
- || player->m_pWanted->m_bIgnoredByEveryone
- || m_pedInObjective->bIsInWater
- || m_pedInObjective->m_nPedState == PED_ARRESTED) {
-
- if (m_nPedState != PED_ARREST_PLAYER)
- SetIdle();
-
- break;
- }
- }
- CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- float wepRange = wepInfo->m_fRange;
- float wepRangeAdjusted;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- wepRangeAdjusted = wepRange / 3.0f;
- } else {
- if (m_nPedState == PED_FIGHT) {
- if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))
- wepRange = 2.0f;
- } else {
- wepRange = 1.3f;
- }
- wepRangeAdjusted = wepRange;
- }
- if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) {
- wepRangeAdjusted = 2.5f;
- }
- if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP
- && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) {
- SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
- break;
- }
- if (m_pedInObjective->m_fHealth <= 0.0f) {
- bObjectiveCompleted = true;
- bScriptObjectiveCompleted = true;
- SetMoveAnim();
- break;
- }
- float distWithTargetSc = distWithTarget.Magnitude();
- if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
- CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle;
- if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED
- || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) {
- SetIdle();
- return;
- }
- SetLookFlag(vehOfTarget, false);
- if (m_nPedState != PED_CARJACK) {
- if (m_pedInObjective->m_nPedState != PED_ARRESTED) {
- if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
- && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) {
-
- // I hope so
- CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
- CVector maxShotPos = vehOfTarget->GetPosition() - ourHead;
- maxShotPos.Normalise();
- maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
-
- CWorld::bIncludeDeadPeds = true;
- CColPoint foundCol;
- CEntity *foundEnt;
- CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
- true, true, true, true, false, true, false);
- CWorld::bIncludeDeadPeds = false;
- if (foundEnt == vehOfTarget) {
- SetAttack(vehOfTarget);
- m_pPointGunAt = vehOfTarget;
- if (vehOfTarget)
- vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt);
-
- SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
- if (distWithTargetSc <= m_distanceToCountSeekDone) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));
- SetMoveState(PEDMOVE_STILL);
- } else {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
- }
- }
- }
- else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {
- if (vehOfTarget) {
- if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {
- GoToNearestDoor(vehOfTarget);
- } else {
- m_vehEnterType = 0;
- if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
- m_vehEnterType = CAR_DOOR_LF;
- } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
- m_vehEnterType = CAR_DOOR_RF;
- } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
- m_vehEnterType = CAR_DOOR_LR;
- } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
- m_vehEnterType = CAR_DOOR_RR;
- }
- // Unused
- // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType);
- SetSeekCar(vehOfTarget, m_vehEnterType);
- SetMoveState(PEDMOVE_RUN);
- }
- }
- }
- }
- }
- SetMoveAnim();
- break;
- }
- if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
- SetLookFlag(m_pedInObjective, false);
- TurnBody();
- }
- if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) {
- if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
- || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {
-
- ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);
- return;
- }
- }
- if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) {
- if (distWithTargetSc > wepRange
- || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
- || m_pedInObjective->m_nPedState == PED_ARRESTED
- || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f
- || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) {
-
- if (m_pedInObjective->EnteringCar())
- wepRangeAdjusted = 2.0f;
-
- if (bUsePedNodeSeek) {
- CVector bestCoords(0.0f, 0.0f, 0.0f);
- m_vecSeekPos = m_pedInObjective->GetPosition();
-
- if (!m_pNextPathNode)
- FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
-
- if (m_pNextPathNode)
- m_vecSeekPos = m_pNextPathNode->GetPosition();
-
- SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
- } else {
- SetSeek(m_pedInObjective, wepRangeAdjusted);
- }
- bCrouchWhenShooting = false;
- if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) {
- if (wepRange <= 5.0f) {
- if (m_pedInObjective->IsPlayer()
- && FindPlayerPed()->m_bSpeedTimerFlag
- && (IsGangMember() || m_nPedType == PEDTYPE_COP)
- && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
- GiveWeapon(WEAPONTYPE_COLT45, 1000);
- SetCurrentWeapon(WEAPONTYPE_COLT45);
- }
- } else {
- bStopAndShoot = true;
- }
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- break;
- }
- bStopAndShoot = false;
- SetMoveAnim();
- break;
- }
- }
- if (m_attackTimer < CTimer::GetTimeInMilliseconds()
- && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
- if (bIsDucking) {
- CAnimBlendAssociation *duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (duckAnim) {
- duckAnim->blendDelta = -2.0f;
- break;
- }
- bIsDucking = false;
- } else if (wepRange <= 5.0f) {
- SetMoveState(PEDMOVE_STILL);
- SetAttack(m_pedInObjective);
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,
- GetPosition().x, GetPosition().y);
- SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f));
- SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f));
- bObstacleShowedUpDuringKillObjective = false;
+ if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) {
+ float stepStart = 1 / 15.0f;
+ float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart;
+ float currentTime = walkRunAssoc->currentTime;
+ int stepPart = 0;
- } else {
- CVector target;
- CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
- if (m_pedInObjective->IsPed())
- m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID);
- else
- target = m_pedInObjective->GetPosition();
-
- target -= ourHead;
- target.Normalise();
- target = target * wepInfo->m_fRange + ourHead;
-
- CWorld::bIncludeDeadPeds = true;
- CEntity *foundEnt = nil;
- CColPoint foundCol;
-
- CWorld::ProcessLineOfSight(
- ourHead, target, foundCol, foundEnt,
- true, true, true, false, true, false);
- CWorld::bIncludeDeadPeds = 0;
- if (foundEnt == m_pedInObjective) {
- SetAttack(m_pedInObjective);
- m_pPointGunAt = m_pedInObjective;
- if (m_pedInObjective)
- m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt);
-
- SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f));
-
- int time;
- if (distWithTargetSc <= wepRangeAdjusted)
- time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f);
- else
- time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);
+ if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart)
+ stepPart = 1;
+ else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd)
+ stepPart = 2;
- SetAttackTimer(time);
- bObstacleShowedUpDuringKillObjective = false;
+ if (stepPart != 0) {
+ DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f);
+ CVector footPos(0.0f, 0.0f, 0.0f);
+ TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR);
- } else if (foundEnt) {
- if (foundEnt->IsPed()) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f));
- bObstacleShowedUpDuringKillObjective = false;
- } else {
- if (foundEnt->IsObject()) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f));
- bObstacleShowedUpDuringKillObjective = true;
- } else if (foundEnt->IsVehicle()) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f));
- bObstacleShowedUpDuringKillObjective = true;
- } else {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f));
- bObstacleShowedUpDuringKillObjective = true;
- }
- }
+ CVector forward = GetForward();
- m_fleeFrom = foundEnt;
- m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom);
- SetPointGunAt(m_pedInObjective);
- }
- }
- } else {
- if (!m_pedInObjective->m_pCurrentPhysSurface)
- bStopAndShoot = false;
-
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
-
- // This is weird...
- if (bNotAllowedToDuck && bKindaStayInSamePlace) {
- if (!bIsDucking) {
- CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!duckAnim || duckAnim->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
- bIsDucking = true;
- }
- break;
- } else {
- CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!duckAnim || duckAnim->blendDelta < 0.0f) {
- bIsDucking = false;
- } else {
- break;
- }
- }
- }
- if (bObstacleShowedUpDuringKillObjective) {
- if (m_nPedType == PEDTYPE_COP) {
- if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45
- || m_fleeFrom && m_fleeFrom->IsObject()) {
- wepRangeAdjusted = 6.0f;
- } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) {
- wepRangeAdjusted = 4.0f;
- } else {
- wepRangeAdjusted = 2.0f;
- }
- } else {
- wepRangeAdjusted = 2.0f;
- }
- }
- if (distWithTargetSc <= wepRangeAdjusted) {
- SetMoveState(PEDMOVE_STILL);
- bIsPointingGunAt = true;
- if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) {
- m_attackTimer = CTimer::GetTimeInMilliseconds();
- SetIdle();
- }
- } else {
- if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS
- && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) {
- Say(SOUND_PED_ATTACK);
- SetSeek(m_pedInObjective, wepRangeAdjusted);
- bIsRunning = true;
- }
- }
- }
- }
+ footPos.z -= 0.1f;
+ footPos += 0.2f * forward;
- if (distWithTargetSc < 2.5f && wepRange > 5.0f
- && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) {
+ if (bDoBloodyFootprints) {
+ CVector2D top(forward * 0.26f);
+ CVector2D right(GetRight() * 0.14f);
- SetAttack(m_pedInObjective);
- if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
- int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f);
- SetAttackTimer(time);
- SetShootTimer(time - 500);
- }
- SetMoveState(PEDMOVE_STILL);
- }
- if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y);
-
- SetMoveAnim();
- break;
- }
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
- {
- if (InVehicle()) {
- if (m_nPedState == PED_DRIVING)
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- } else if (m_nPedState != PED_FLEE_ENTITY) {
- int time;
- if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
- time = 0;
- else
- time = 6000;
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos,
+ top.x, top.y,
+ right.x, right.y,
+ 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f);
- SetFindPathAndFlee(m_pedInObjective, time);
- }
- break;
- }
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- {
- if (m_pedInObjective) {
- float safeDistance = 2.0f;
- if (m_pedInObjective->bInVehicle)
- safeDistance = 3.0f;
-
- float distWithTargetSc = distWithTarget.Magnitude();
- if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
- if (distWithTargetSc <= safeDistance) {
- bScriptObjectiveCompleted = true;
- if (m_nPedState != PED_ATTACK) {
- SetIdle();
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- }
- if (distWithTargetSc > 2.0f)
- SetMoveState(m_pedInObjective->m_nMoveState);
- else
- SetMoveState(PEDMOVE_STILL);
- } else {
- SetSeek(m_pedInObjective, safeDistance);
- if (distWithTargetSc >= 5.0f) {
- if (m_leader && m_leader->m_nMoveState == PEDMOVE_SPRINT)
- SetMoveState(PEDMOVE_SPRINT);
- else
- SetMoveState(PEDMOVE_RUN);
- } else {
- if (m_leader && m_leader->m_nMoveState != PEDMOVE_STILL
- && m_leader->m_nMoveState != PEDMOVE_NONE) {
- if (m_leader->IsPlayer()) {
- if (distWithTargetSc >= 3.0f && FindPlayerPed()->m_fMoveSpeed >= 1.3f)
- SetMoveState(PEDMOVE_RUN);
- else
- SetMoveState(PEDMOVE_WALK);
- } else {
- SetMoveState(m_leader->m_nMoveState);
- }
- } else if (distWithTargetSc <= 3.0f) {
- SetMoveState(PEDMOVE_WALK);
- } else {
- SetMoveState(PEDMOVE_RUN);
- }
- }
- }
- }
- } else {
- SetObjective(OBJECTIVE_NONE);
- }
- break;
- }
- case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
- {
- if (m_pedInObjective) {
- CVector posToGo = GetFormationPosition();
- distWithTarget = posToGo - carOrOurPos;
- SetSeek(posToGo, 1.0f);
- if (distWithTarget.Magnitude() <= 3.0f) {
- SetSeek(posToGo, 1.0f);
- if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
- SetMoveState(m_pedInObjective->m_nMoveState);
- } else {
- SetSeek(posToGo, 1.0f);
- SetMoveState(PEDMOVE_RUN);
- }
+ if (m_bloodyFootprintCountOrDeathTime <= 20) {
+ m_bloodyFootprintCountOrDeathTime = 0;
+ bDoBloodyFootprints = false;
} else {
- SetObjective(OBJECTIVE_NONE);
+ m_bloodyFootprintCountOrDeathTime -= 20;
}
- break;
}
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- {
- if (m_carInObjective) {
- if (!bInVehicle && m_carInObjective->m_nNumPassengers >= m_carInObjective->m_nNumMaxPassengers) {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
-
- break;
- }
-
- if (m_prevObjective == OBJECTIVE_HAIL_TAXI && !((CAutomobile*)m_carInObjective)->bTaxiLight) {
- RestorePreviousObjective();
- ClearObjective();
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- bIsRunning = false;
- break;
- }
- if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) {
- if (!EnteringCar()) {
- bool foundSeat = false;
- if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
- if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
- if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
- foundSeat = false;
- } else {
- m_vehEnterType = CAR_DOOR_RR;
- foundSeat = true;
- }
- } else {
- m_vehEnterType = CAR_DOOR_LR;
- foundSeat = true;
- }
- } else {
- m_vehEnterType = CAR_DOOR_RF;
- foundSeat = true;
- }
- for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) {
- if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
- m_vehEnterType = CAR_DOOR_RF;
- foundSeat = true;
- }
- }
- if (foundSeat) {
- SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType));
- SetEnterCar(m_carInObjective, m_vehEnterType);
- }
- }
- m_objectiveTimer = 0;
- }
- }
- // fall through
+ if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) {
+ if(IsPlayer())
+ particleProduceFootDust(this, footPos, 0.0f, 4);
}
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- {
- if (!m_carInObjective || bInVehicle) {
-#ifdef VC_PED_PORTS
- if (bInVehicle && m_pMyVehicle != m_carInObjective) {
- SetExitCar(m_pMyVehicle, 0);
- } else
-#endif
- {
- bObjectiveCompleted = true;
- bScriptObjectiveCompleted = true;
- RestorePreviousState();
- }
- } else {
- if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) {
- SetMoveState(PEDMOVE_STILL);
- break;
- }
- if (IsPedInControl()) {
- if (m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
- if (distWithTarget.Magnitude() < 20.0f) {
- RestorePreviousObjective();
- RestorePreviousState();
- return;
- }
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (m_carInObjective->pDriver
-#ifdef VC_PED_PORTS
- && !IsPlayer()
-#endif
- ) {
- if (m_carInObjective->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS && m_carInObjective->pDriver != m_pedInObjective) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
- m_carInObjective->bIsBeingCarJacked = false;
- }
- }
- }
- } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- if (m_carInObjective->pDriver
-#ifdef VC_PED_PORTS
- && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR)
-#endif
- ) {
- if (m_carInObjective->pDriver->m_nPedType == m_nPedType) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
- m_carInObjective->bIsBeingCarJacked = false;
- }
- }
- }
- if (m_carInObjective->IsUpsideDown() && m_carInObjective->m_vehType != VEHICLE_TYPE_BIKE) {
- RestorePreviousObjective();
- RestorePreviousState();
- return;
- }
- if (!m_carInObjective->IsBoat() || m_nPedState == PED_SEEK_IN_BOAT) {
- if (m_nPedState != PED_SEEK_CAR)
- SetSeekCar(m_carInObjective, 0);
- } else {
- SetSeekBoatPosition(m_carInObjective);
- }
- if (m_nMoveState == PEDMOVE_STILL && !bVehEnterDoorIsBlocked)
- SetMoveState(PEDMOVE_RUN);
-
- if (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) {
- distWithTarget = m_carInObjective->GetPosition() - GetPosition();
- if (!bInVehicle) {
- if (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) {
- if (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen())
- WarpPedToNearEntityOffScreen(m_carInObjective);
-
- if (CharCreatedBy != MISSION_CHAR || m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS
-#ifdef VC_PED_PORTS
- || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled()
+#ifdef PC_PARTICLE
+ else if(stepPart == 2)
+#else
+ else
#endif
- ) {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- } else {
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
- }
- }
- }
- } else if (!bInVehicle) {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- }
- }
- break;
- }
- case OBJECTIVE_DESTROY_CAR:
{
- if (!m_carInObjective) {
- ClearLookFlag();
- bObjectiveCompleted = true;
- break;
- }
- float distWithTargetSc = distWithTarget.Magnitude();
- CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- float wepRange = wepInfo->m_fRange;
- m_pLookTarget = m_carInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
-
- m_pSeekTarget = m_carInObjective;
- m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
-
- TurnBody();
- if (m_carInObjective->m_fHealth <= 0.0f) {
- ClearLookFlag();
- bScriptObjectiveCompleted = true;
- break;
- }
-
- if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
- && distWithTargetSc < wepRange) {
-
- // I hope so
- CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
- CVector maxShotPos = m_carInObjective->GetPosition() - ourHead;
- maxShotPos.Normalise();
- maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
-
- CWorld::bIncludeDeadPeds = true;
- CColPoint foundCol;
- CEntity *foundEnt;
- CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
- true, true, true, true, false, true, false);
- CWorld::bIncludeDeadPeds = false;
- if (foundEnt == m_carInObjective) {
- SetAttack(m_carInObjective);
- m_pPointGunAt = m_carInObjective;
- if (m_pPointGunAt)
- m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt);
-
- SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
- if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
- } else {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300));
- SetMoveState(PEDMOVE_STILL);
- }
- }
- } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) {
+ particleProduceFootSplash(this, footPos, 0.15f, 4);
+ }
+ }
+ }
- float safeDistance;
- if (wepRange <= 5.0f)
- safeDistance = 3.0f;
- else
- safeDistance = wepRange * 0.25f;
+ if (m_nSurfaceTouched == SURFACE_WATER) {
+ float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude();
+ if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) {
+#ifdef PC_PARTICLE
+ float particleSize = pedSpeed * 2.0f;
- SetSeek(m_carInObjective, safeDistance);
- SetMoveState(PEDMOVE_RUN);
- }
- SetLookFlag(m_carInObjective, false);
- TurnBody();
- break;
- }
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- {
- distWithTarget = m_nextRoutePointPos - GetPosition();
- distWithTarget.z = 0.0f;
- if (InVehicle()) {
- CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos);
- CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle);
- if (distWithTarget.MagnitudeSqr() < sq(20.0f)) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS);
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- }
- break;
- }
- if (distWithTarget.Magnitude() > 30.0f) {
- if (m_pMyVehicle) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- } else {
- float closestVehDist = SQR(60.0f);
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- CVehicle* foundVeh = nil;
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* nearVeh = (CVehicle*)vehicles[i];
- /*
- Not used.
- CVector vehSpeed = nearVeh->GetSpeed();
- CVector ourSpeed = GetSpeed();
- */
- CVector vehDistVec = nearVeh->GetPosition() - GetPosition();
- if (vehDistVec.MagnitudeSqr() < closestVehDist
- && m_pedInObjective->m_pMyVehicle != nearVeh)
- {
- foundVeh = nearVeh;
- closestVehDist = vehDistVec.MagnitudeSqr();
- }
- }
- m_pMyVehicle = foundVeh;
- if (m_pMyVehicle) {
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
- }
- }
- break;
- }
- // fall through
- }
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
- {
- if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA)
- && InVehicle()) {
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- } else {
- distWithTarget = m_nextRoutePointPos - GetPosition();
- distWithTarget.z = 0.0f;
- if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) {
- bObjectiveCompleted = true;
- bScriptObjectiveCompleted = true;
- SetMoveState(PEDMOVE_STILL);
- } else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) {
- if (bUsePedNodeSeek) {
- CVector bestCoords(0.0f, 0.0f, 0.0f);
- m_vecSeekPos = m_nextRoutePointPos;
+ if (particleSize < 0.25f)
+ particleSize = 0.25f;
- if (!m_pNextPathNode)
- FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+ if (particleSize > 0.75f)
+ particleSize = 0.75f;
- if (m_pNextPathNode)
- m_vecSeekPos = m_pNextPathNode->GetPosition();
- }
- SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
- }
- }
+ CVector particlePos = GetPosition() + GetForward() * 0.3f;
+ particlePos.z -= 1.2f;
- break;
- }
- case OBJECTIVE_GUARD_ATTACK:
- {
- if (m_pedInObjective) {
- SetLookFlag(m_pedInObjective, true);
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- m_lookTimer = m_attackTimer;
- TurnBody();
- float distWithTargetSc = distWithTarget.Magnitude();
- if (distWithTargetSc >= 20.0f) {
- RestorePreviousObjective();
- } else if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
- if (m_nPedState != PED_SEEK_ENTITY && distWithTargetSc >= 2.0f) {
- SetSeek(m_pedInObjective, 1.0f);
- } else {
- SetAttack(m_pedInObjective);
- SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1500.0f));
- }
- SetAttackTimer(1000);
- }
- } else {
- RestorePreviousObjective();
- }
- break;
- }
- case OBJECTIVE_FOLLOW_ROUTE:
- if (HaveReachedNextPointOnRoute(1.0f)) {
- int nextPoint = GetNextPointOnRoute();
- m_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint);
- } else {
- SetSeek(m_nextRoutePointPos, 0.8f);
- }
- break;
- case OBJECTIVE_SOLICIT_VEHICLE:
- if (m_carInObjective) {
- if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) {
- if (!bInVehicle) {
- SetObjective(OBJECTIVE_NONE);
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- } else {
- if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT)
- SetSeekCar(m_carInObjective, 0);
- }
- } else {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- break;
- case OBJECTIVE_HAIL_TAXI:
- if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- Say(SOUND_PED_TAXI_WAIT);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f);
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
- }
- break;
- case OBJECTIVE_CATCH_TRAIN:
- {
- if (m_carInObjective) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
- } else {
- CVehicle* trainToEnter = nil;
- float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity* vehicles[8];
-
- CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* nearVeh = (CVehicle*)vehicles[i];
- if (nearVeh->IsTrain()) {
- CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
- float vehDist = vehDistVec.Magnitude();
- if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh)
- {
- trainToEnter = nearVeh;
- closestCarDist = vehDist;
- }
- }
- }
- if (trainToEnter) {
- m_carInObjective = trainToEnter;
- m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
- }
- }
- break;
- }
- case OBJECTIVE_BUY_ICE_CREAM:
- if (m_carInObjective) {
- if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM)
- SetSeekCar(m_carInObjective, 0);
- } else {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- break;
- case OBJECTIVE_STEAL_ANY_CAR:
- {
- if (bInVehicle) {
- bScriptObjectiveCompleted = true;
- RestorePreviousObjective();
- } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
- CVehicle *carToSteal = nil;
- float closestCarDist = ENTER_CAR_MAX_DIST;
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
-
- // NB: This should've been ENTER_CAR_MAX_DIST actually, and is fixed in VC.
- CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- for(int i = 0; i < lastVehicle; i++) {
- CVehicle *nearVeh = (CVehicle*)vehicles[i];
- if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
- if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) {
- if (nearVeh->CanPedOpenLocks(this)) {
- CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
- float vehDist = vehDistVec.Magnitude();
- if (vehDist < closestCarDist) {
- carToSteal = nearVeh;
- closestCarDist = vehDist;
- }
- }
- }
- }
- }
- if (carToSteal) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal);
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
- } else {
- RestorePreviousObjective();
- RestorePreviousState();
- }
- }
- break;
- }
- case OBJECTIVE_MUG_CHAR:
- {
- if (m_pedInObjective) {
- if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) {
- ClearObjective();
- return;
- }
- if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) {
- ClearObjective();
- return;
- }
- if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective);
- SetMoveState(PEDMOVE_SPRINT);
- return;
- }
- if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this
- || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) {
- ClearObjective();
- SetFindPathAndFlee(m_pedInObjective, 15000, true);
- return;
- }
- float distWithTargetScSqr = distWithTarget.MagnitudeSqr();
- if (distWithTargetScSqr <= sq(10.0f)) {
- if (distWithTargetScSqr <= sq(1.4f)) {
- CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD);
- 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)) {
- CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
- punchAssoc->flags |= ASSOC_DELETEFADEDOUT;
- punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- CVector2D offset(distWithTarget.x, distWithTarget.y);
- int dir = m_pedInObjective->GetLocalDirection(offset);
- m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);
- m_pedInObjective->ReactToAttack(this);
- m_pedInObjective->Say(SOUND_PED_ROBBED);
- Say(SOUND_PED_MUGGING);
- bRichFromMugging = true;
-
- // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call
- CPed *victim = m_pedInObjective;
- ClearObjective();
- if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
- || victim->m_pedInObjective != this) {
- SetFindPathAndFlee(victim, 15000, true);
- m_nLastPedState = PED_WANDER_PATH;
- } else {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim);
- SetMoveState(PEDMOVE_SPRINT);
- m_nLastPedState = PED_WANDER_PATH;
- }
- }
- } else {
- eWeaponType weaponType = GetWeapon()->m_eWeaponType;
- if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)
- SetCurrentWeapon(WEAPONTYPE_UNARMED);
+ CVector particleDir = m_vecMoveSpeed * -0.75f;
- CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f);
- newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
- newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- }
- } else {
- SetSeek(m_pedInObjective, 1.0f);
- CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
+ particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f);
+ CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0);
- if (walkAssoc)
- walkAssoc->speed = 1.3f;
- }
- } else {
- ClearObjective();
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- }
- } else {
-#ifdef VC_PED_PORTS
- m_objective = OBJECTIVE_NONE;
-#endif
- ClearObjective();
- }
- break;
- }
- case OBJECTIVE_FLEE_CAR:
- if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) {
- RestorePreviousObjective();
- SetFlee(m_pMyVehicle, 6000);
- break;
- }
- // fall through
- case OBJECTIVE_LEAVE_CAR:
- 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))) {
- if (m_pMyVehicle->IsTrain())
- SetExitTrain(m_pMyVehicle);
-#ifdef VC_PED_PORTS
- else if (m_pMyVehicle->IsBoat())
- SetExitBoat(m_pMyVehicle);
-#endif
- else
- SetExitCar(m_pMyVehicle, 0);
- }
- } else {
- RestorePreviousObjective();
- }
- }
- break;
-#ifdef VC_PED_PORTS
- case OBJECTIVE_LEAVE_CAR_AND_DIE:
- {
- if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
- if (InVehicle()) {
- if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) {
- if (m_pMyVehicle->IsBoat())
- SetExitBoat(m_pMyVehicle);
- else if (m_pMyVehicle->bIsBus)
- SetExitCar(m_pMyVehicle, 0);
- else {
- eCarNodes doorNode = CAR_DOOR_LF;
- if (m_pMyVehicle->pDriver != this) {
- if (m_pMyVehicle->pPassengers[0] == this) {
- doorNode = CAR_DOOR_RF;
- } else if (m_pMyVehicle->pPassengers[1] == this) {
- doorNode = CAR_DOOR_LR;
- } else if (m_pMyVehicle->pPassengers[2] == this) {
- doorNode = CAR_DOOR_RR;
- }
- }
- SetBeingDraggedFromCar(m_pMyVehicle, doorNode, false);
- }
- }
- }
- }
- break;
- }
+ particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
+ CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0);
+#else
+ CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f;
+ CVector particleDir = m_vecMoveSpeed * 0.45f;
+ particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
+ CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255));
#endif
}
- if (bObjectiveCompleted
- || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
- RestorePreviousObjective();
- if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer)
- m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1;
-
- if (CharCreatedBy != RANDOM_CHAR || bInVehicle) {
- if (IsPedInControl())
- RestorePreviousState();
- } else {
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- }
- ClearAimFlag();
- ClearLookFlag();
- }
}
}
-void
-CPed::SetShootTimer(uint32 time)
-{
- if (CTimer::GetTimeInMilliseconds() > m_shootTimer) {
- m_shootTimer = CTimer::GetTimeInMilliseconds() + time;
- }
-}
-
-void
-CPed::SetSeekCar(CVehicle *car, uint32 doorNode)
-{
- if (m_nPedState == PED_SEEK_CAR)
- return;
-
-#ifdef VC_PED_PORTS
- if (!CanSetPedState() || m_nPedState == PED_DRIVING)
- return;
-#endif
-
- SetStoredState();
- m_pSeekTarget = car;
- m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
- m_carInObjective = car;
- m_carInObjective->RegisterReference((CEntity**) &m_carInObjective);
- m_pMyVehicle = car;
- m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
- // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
- m_vehEnterType = doorNode;
- m_distanceToCountSeekDone = 0.5f;
- m_nPedState = PED_SEEK_CAR;
-
-}
-
-void
-CPed::SetSeekBoatPosition(CVehicle *boat)
+// Actually GetLocalDirectionTo(Turn/Look)
+int
+CPed::GetLocalDirection(const CVector2D &posOffset)
{
- if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver
-#if defined VC_PED_PORTS || defined FIX_BUGS
- || !IsPedInControl()
-#endif
- )
- return;
+ int direction;
+ float angle;
- SetStoredState();
- m_carInObjective = boat;
- m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
- m_pMyVehicle = boat;
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_distanceToCountSeekDone = 0.5f;
- m_nPedState = PED_SEEK_IN_BOAT;
-}
+ for (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI);
-void
-CPed::SetExitTrain(CVehicle* train)
-{
- if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())
- return;
+ for (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4);
- /*
- // Not used
- CVector exitPos;
- GetNearestTrainPedPosition(train, exitPos);
- */
- m_nPedState = PED_EXIT_TRAIN;
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
- m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
- bUsesCollision = false;
- LineUpPedWithTrain();
+ // 0-forward, 1-left, 2-backward, 3-right.
+ return direction;
}
#ifdef NEW_WALK_AROUND_ALGORITHM
@@ -14394,486 +4071,734 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime;
}
-int32
-CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
+bool
+CPed::IsPedInControl(void)
{
- bool collidedWithBoat = false;
- bool belowTorsoCollided = false;
- float gravityEffect = -0.15f * CTimer::GetTimeStep();
- CColPoint intersectionPoint;
- CColLine ourLine;
+ return m_nPedState <= PED_STATES_NO_AI
+ && !bIsInTheAir && !bIsLanding
+ && m_fHealth > 0.0f;
+}
- CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();
- CColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel();
+bool
+CPed::IsPedShootable(void)
+{
+ return m_nPedState <= PED_STATES_NO_ST;
+}
- if (!bUsesCollision)
- return false;
+bool
+CPed::UseGroundColModel(void)
+{
+ return m_nPedState == PED_FALL ||
+ m_nPedState == PED_DIVE_AWAY ||
+ m_nPedState == PED_DIE ||
+ m_nPedState == PED_DEAD;
+}
- if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat())
- collidedWithBoat = true;
+bool
+CPed::CanPedReturnToState(void)
+{
+ return m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK &&
+ m_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY;
+}
- // ofc we're not vehicle
- if (!m_bIsVehicleBeingShifted && !bSkipLineCol
-#ifdef VC_PED_PORTS
- && !collidingEnt->IsPed()
+bool
+CPed::CanSetPedState(void)
+{
+ return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR;
+}
+
+bool
+CPed::CanStrafeOrMouseControl(void)
+{
+#ifdef FREE_CAM
+ if (CCamera::bFreeCam)
+ return false;
#endif
- ) {
- if (!bCollisionProcessed) {
+ return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY ||
+ m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP;
+}
+
+void
+CPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ if (ped->m_nPedState == PED_GETUP)
+ RpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f);
+
+ ped->bFallenDown = false;
+ animAssoc->blendDelta = -1000.0f;
+ if (ped->m_nPedState == PED_GETUP)
+ ped->RestorePreviousState();
+
+ if (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY)
+ ped->SetMoveState(PEDMOVE_STILL);
+ else
+ ped->SetMoveState(PEDMOVE_RUN);
+
+ ped->SetMoveAnim();
+ ped->bGetUpAnimStarted = false;
+}
+
+void
+CPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ animAssoc->blendDelta = -1000.0f;
+ ped->bIsLanding = false;
+
+ if (ped->m_nPedState == PED_JUMP)
+ ped->RestorePreviousState();
+}
+
+void
+CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ /*
+ CPed *ped = (CPed*)arg;
+
+ if (ped->m_nPedState == PED_STAGGER)
+ // nothing
+ */
+}
+
+void
+CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ bool startedToRun = false;
+ ped->bUsesCollision = true;
+ ped->m_actionX = 0.0f;
+ ped->m_actionY = 0.0f;
+ ped->bVehExitWillBeInstant = false;
+ if (veh && veh->IsBoat())
+ ped->ApplyMoveSpeed();
+
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR)
+ ped->RestorePreviousObjective();
#ifdef VC_PED_PORTS
- m_pCurrentPhysSurface = nil;
+ else if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ ped->m_fHealth = 0.0f;
+ ped->SetDie(ANIM_FLOOR_HIT, 4.0f, 0.5f);
+ }
#endif
- if (bIsStanding) {
- bIsStanding = false;
- bWasStanding = true;
- }
- bCollisionProcessed = true;
- m_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep();
- bStillOnValidPoly = false;
- if (IsPlayer() || m_fCollisionSpeed >= 1.0f
- && (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) {
- m_collPoly.valid = false;
- m_fCollisionSpeed = 0.0f;
- bHitSteepSlope = false;
+
+ ped->bInVehicle = false;
+ if (veh && veh->IsCar() && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) {
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (ped->m_nPedState == PED_EXIT_CAR) {
+ if (ped->m_nPedType == PEDTYPE_COP)
+ ped->SetIdle();
+ else
+ ped->RestorePreviousState();
+
+ veh = ped->m_pMyVehicle;
+ if (ped->bFleeAfterExitingCar && veh) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(veh->GetPosition(), 12000);
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+ if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
+ ped->SetMoveState(PEDMOVE_SPRINT);
+ ped->Say(SOUND_PED_FLEE_SPRINT);
} else {
- CVector pos = GetPosition();
- float potentialGroundZ = GetPosition().z - FEET_OFFSET;
- if (bWasStanding) {
- pos.z += -0.25f;
- potentialGroundZ += gravityEffect;
+ ped->SetMoveState(PEDMOVE_RUN);
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ startedToRun = true;
+
+ // This is not a good way to do this...
+ ped->m_nLastPedState = PED_WANDER_PATH;
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+ if (ped->m_nPedType == PEDTYPE_PROSTITUTE)
+ ped->SetObjectiveTimer(30000);
+ ped->m_nLastPedState = PED_NONE;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+
+ // Kill objective is already given at this point.
+ ped->bGonnaKillTheCarJacker = false;
+ if (ped->m_pedInObjective) {
+ if (!(CGeneral::GetRandomNumber() & 1)
+ && ped->m_nPedType != PEDTYPE_COP
+ && (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
}
- if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) {
- bStillOnValidPoly = true;
+ ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ }
+ int waitTime = 1500;
+ ped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime);
+ ped->SetMoveState(PEDMOVE_RUN);
+ startedToRun = true;
+ } else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ }
+ }
#ifdef VC_PED_PORTS
- if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
- }
-#else
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ else {
+ ped->m_nPedState = PED_IDLE;
+ }
#endif
- m_vecMoveSpeed.z = 0.0f;
- bIsStanding = true;
- } else {
- m_collPoly.valid = false;
- m_fCollisionSpeed = 0.0f;
- bHitSteepSlope = false;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ ped->RestartNonPartialAnims();
+ ped->m_pVehicleAnim = nil;
+ CVector posFromZ = ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posFromZ);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posFromZ);
+ veh = ped->m_pMyVehicle;
+ if (veh) {
+ if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
+ if (veh->pDriver) {
+ if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0;
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0;
+ CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100;
+ if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0)
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0;
}
}
}
+ veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
+ if (veh->pDriver == ped) {
+ veh->RemoveDriver();
+ veh->SetStatus(STATUS_ABANDONED);
+ if (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+ veh->m_nDoorLock = CARLOCK_UNLOCKED;
+ if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
+ veh->ChangeLawEnforcerState(false);
+ } else {
+ veh->RemovePassenger(ped);
+ }
- if (!bStillOnValidPoly) {
- CVector potentialCenter = GetPosition();
- potentialCenter.z = GetPosition().z - 0.52f;
-
- // 0.52f should be a ped's approx. radius
- float totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect;
- if (bWasStanding) {
- if (collidedWithBoat) {
- potentialCenter.z += 2.0f * gravityEffect;
- totalRadiusWhenCollided += Abs(gravityEffect);
- } else {
- potentialCenter.z += gravityEffect;
- }
+ if (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) {
+ float angleAfterExit;
+ if (ped->m_vehEnterType == CAR_DOOR_LF) {
+ angleAfterExit = HALFPI + veh->GetForward().Heading();
+ } else {
+ angleAfterExit = veh->GetForward().Heading() - HALFPI;
}
- if (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) {
- ourLine.p0 = GetPosition();
- ourLine.p1 = GetPosition();
- ourLine.p1.z = GetPosition().z - FEET_OFFSET;
- if (bWasStanding) {
- ourLine.p1.z = ourLine.p1.z + gravityEffect;
- ourLine.p0.z = ourLine.p0.z + -0.25f;
- }
- float minDist = 1.0f;
- belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
- intersectionPoint, minDist, false, &m_collPoly);
+ ped->SetHeading(angleAfterExit);
+ ped->m_fRotationDest = angleAfterExit;
+ ped->m_fRotationCur = angleAfterExit;
+ if (!ped->bBusJacked)
+ ped->SetMoveState(PEDMOVE_WALK);
+ }
+ if (CGarages::IsPointWithinAnyGarage(ped->GetPosition()))
+ veh->bLightsOn = false;
+ }
- if (collidedWithBoat && bWasStanding && !belowTorsoCollided) {
- ourLine.p0.z = ourLine.p1.z;
- ourLine.p1.z = ourLine.p1.z + gravityEffect;
- belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
- intersectionPoint, minDist, false, &m_collPoly);
- }
- if (belowTorsoCollided) {
-#ifndef VC_PED_PORTS
- if (!collidingEnt->IsPed()) {
-#endif
- if (!bIsStanding
- || FEET_OFFSET + intersectionPoint.point.z > GetPosition().z
- || collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) {
+ if (ped->IsPlayer())
+ AudioManager.PlayerJustLeftCar();
- if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) {
- m_pCurSurface = collidingEnt;
- collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
- bTryingToReachDryLand = false;
- bOnBoat = false;
- } else {
- m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
- collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);
- m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();
- m_pCurSurface = collidingEnt;
- collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
- m_collPoly.valid = false;
- if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) {
- bOnBoat = true;
- } else {
- bOnBoat = false;
- }
- }
-#ifdef VC_PED_PORTS
- if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
- }
+ ped->ReplaceWeaponWhenExitingVehicle();
+
+ ped->bOnBoat = false;
+ if (ped->bBusJacked) {
+ ped->SetFall(1500, ANIM_KO_SKID_BACK, false);
+ ped->bBusJacked = false;
+ }
+ ped->m_nStoredMoveState = PEDMOVE_NONE;
+ if (!ped->IsPlayer()) {
+ // It's a shame...
+#ifdef FIX_BUGS
+ int createdBy = ped->CharCreatedBy;
#else
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ int createdBy = !ped->CharCreatedBy;
#endif
- m_nSurfaceTouched = intersectionPoint.surfaceB;
- if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) {
- bHitSteepSlope = true;
- m_vecDamageNormal = intersectionPoint.normal;
- }
- }
-#ifdef VC_PED_PORTS
- float upperSpeedLimit = 0.33f;
- float lowerSpeedLimit = -0.25f;
- float speed = m_vecMoveSpeed.Magnitude2D();
- if (m_nPedState == PED_IDLE) {
- upperSpeedLimit *= 2.0f;
- lowerSpeedLimit *= 1.5f;
- }
- CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
- if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit)
- && m_pCollidingEntity != collidingEnt) {
- float damage = 100.0f * Max(speed - 0.25f, 0.0f);
- float damage2 = damage;
- if (m_vecMoveSpeed.z < -0.25f)
- damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;
+ if (createdBy == MISSION_CHAR && !startedToRun)
+ ped->SetMoveState(PEDMOVE_WALK);
+ }
+}
- 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);
- }
+void
+CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
+{
+ CAnimBlendAssociation *quickJackedAssoc;
+ CVehicle *vehicle;
+ CPed *ped = (CPed*)arg;
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir);
- if (IsPlayer() && damage2 > 5.0f)
- Say(SOUND_PED_LAND);
+ quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED);
+ if (ped->m_nPedState != PED_ARRESTED) {
+ ped->m_nLastPedState = PED_NONE;
+ if (dragAssoc)
+ dragAssoc->blendDelta = -1000.0f;
+ }
+ ped->RestartNonPartialAnims();
+ ped->m_pVehicleAnim = nil;
+ ped->m_pSeekTarget = nil;
+ vehicle = ped->m_pMyVehicle;
- } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
- }
-#else
- float speedSqr = 0.0f;
- CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
- if (!bWasStanding && (m_vecMoveSpeed.z < -0.25f || (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) > sq(0.5f))) {
- if (speedSqr == 0.0f)
- speedSqr = sq(m_vecMoveSpeed.z);
+ if (vehicle) {
+ vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
- 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);
+ if (vehicle->pDriver == ped) {
+ vehicle->RemoveDriver();
+ if (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+ vehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
- }
+ if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle())
+ vehicle->ChangeLawEnforcerState(false);
+ } else {
+ vehicle->RemovePassenger(ped);
+ }
+ }
+ ped->bInVehicle = false;
+ if (ped->IsPlayer())
+ AudioManager.PlayerJustLeftCar();
+
+#ifdef VC_PED_PORTS
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
+ ped->m_fHealth = 0.0f;
+ ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f);
+ return;
+ }
#endif
- m_vecMoveSpeed.z = 0.0f;
- bIsStanding = true;
-#ifndef VC_PED_PORTS
- } else {
- bOnBoat = false;
- }
+
+ if (quickJackedAssoc) {
+ dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped);
+ } else {
+ dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
+ if (ped->CanSetPedState())
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
+ }
+
+ ped->ReplaceWeaponWhenExitingVehicle();
+
+ ped->m_nStoredMoveState = PEDMOVE_NONE;
+ ped->bVehExitWillBeInstant = false;
+}
+
+void
+CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ // Pointless code
+ if (!veh)
+ return;
+
+#ifdef VC_PED_PORTS
+ // Situation of entering car as a driver while there is already a driver exiting atm.
+ CPed *driver = veh->pDriver;
+ if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR
+ && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
+
+ if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ if (driver->CharCreatedBy == MISSION_CHAR) {
+ PedSetOutCarCB(nil, veh->pDriver);
+ if (driver->m_pMyVehicle) {
+ driver->PositionPedOutOfCollision();
+ } else {
+ driver->m_pMyVehicle = veh;
+ driver->PositionPedOutOfCollision();
+ driver->m_pMyVehicle = nil;
+ }
+ veh->pDriver = nil;
+ } else {
+ driver->SetDead();
+ driver->FlagToDestroyWhenNextProcessed();
+ veh->pDriver = nil;
+ }
+ }
#endif
- } else {
- bOnBoat = false;
- }
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ ped->bInVehicle = true;
+ if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
+ if (veh->pDriver) {
+ if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000;
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
+ CWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped;
}
}
}
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ || ped->m_nPedState == PED_CARJACK
+#endif
+ )
+ veh->bIsBeingCarJacked = false;
- int ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil);
- if (ourCollidedSpheres > 0 || belowTorsoCollided) {
- AddCollisionRecord(collidingEnt);
- if (!collidingEnt->IsBuilding())
- ((CPhysical*)collidingEnt)->AddCollisionRecord(this);
+ if (veh->m_nNumGettingIn)
+ --veh->m_nNumGettingIn;
- if (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) {
- bHasHitWall = true;
+ if (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive)
+ ((CPlayerPed*)ped)->ClearAdrenaline();
+
+ if (veh->IsBoat()) {
+ if (ped->IsPlayer()) {
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ CCarCtrl::RegisterVehicleOfInterest(veh);
+#endif
+ if (veh->GetStatus() == STATUS_SIMPLE) {
+ veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f);
+ veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ veh->SetStatus(STATUS_PLAYER);
+ AudioManager.PlayerJustGotInCar();
}
+ veh->SetDriver(ped);
+ if (!veh->bEngineOn)
+ veh->bEngineOn = true;
+
+ ped->m_nPedState = PED_DRIVING;
+ ped->StopNonPartialAnims();
+ return;
}
- if (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) {
- if (bWasStanding) {
- CVector sphereNormal;
- float normalLength;
- for(int sphere = 0; sphere < ourCollidedSpheres; sphere++) {
- sphereNormal = collidingPoints[sphere].normal;
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->blendDelta = -1000.0f;
+
+ ped->bDoBloodyFootprints = false;
+ if (veh->m_nAlarmState == -1)
+ veh->m_nAlarmState = 15000;
+
+ if (ped->IsPlayer()) {
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (veh->GetStatus() == STATUS_SIMPLE) {
+ veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ veh->SetStatus(STATUS_PLAYER);
+ }
+ AudioManager.PlayerJustGotInCar();
+ } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (veh->GetStatus() == STATUS_SIMPLE) {
+ veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ veh->SetStatus(STATUS_PHYSICS);
+ }
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) {
+ CPed *passenger = veh->pPassengers[i];
+ if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) {
+ passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
#ifdef VC_PED_PORTS
- if (sphereNormal.z >= -1.0f || !IsPlayer()) {
+ passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds();
#endif
- normalLength = sphereNormal.Magnitude2D();
- if (normalLength != 0.0f) {
- sphereNormal.x = sphereNormal.x / normalLength;
- sphereNormal.y = sphereNormal.y / normalLength;
- }
-#ifdef VC_PED_PORTS
- } else {
- float speed = m_vecMoveSpeed.Magnitude2D();
- 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;
- }
+ }
+ }
+ }
+ // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below.
+#if !defined VC_PED_PORTS && !defined FIX_BUGS
+ else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ if (ped->m_nPedState == PED_CARJACK) {
+ veh->AddPassenger(ped, 0);
+ ped->m_nPedState = PED_DRIVING;
+ ped->RestorePreviousObjective();
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) {
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+ }
+ }
#endif
- sphereNormal.Normalise();
- collidingPoints[sphere].normal = sphereNormal;
- if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF)
- bHitSteepSlope = true;
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) {
+ veh->SetDriver(ped);
+ if (veh->VehicleCreatedBy == PARKED_VEHICLE) {
+ veh->VehicleCreatedBy = RANDOM_VEHICLE;
+ ++CCarCtrl::NumRandomCars;
+ --CCarCtrl::NumParkedCars;
+ }
+ if (veh->bIsAmbulanceOnDuty) {
+ veh->bIsAmbulanceOnDuty = false;
+ --CCarCtrl::NumAmbulancesOnDuty;
+ }
+ if (veh->bIsFireTruckOnDuty) {
+ veh->bIsFireTruckOnDuty = false;
+ --CCarCtrl::NumFiretrucksOnDuty;
+ }
+ if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
+ veh->ChangeLawEnforcerState(true);
+
+ if (!veh->bEngineOn) {
+ veh->bEngineOn = true;
+ DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
+ }
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR
+ && ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) {
+
+ CCarCtrl::JoinCarWithRoadSystem(veh);
+ veh->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ veh->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ veh->AutoPilot.m_nCruiseSpeed = 25;
+ }
+ ped->m_nPedState = PED_DRIVING;
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+
+ if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->m_prevObjective = OBJECTIVE_NONE;
+
+ ped->RestorePreviousObjective();
+ }
+
+ } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ if (veh->bIsBus) {
+ veh->AddPassenger(ped);
+ } else {
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ veh->AddPassenger(ped, 0);
+ break;
+ case CAR_DOOR_RR:
+ veh->AddPassenger(ped, 2);
+ break;
+ case CAR_DOOR_LR:
+ veh->AddPassenger(ped, 1);
+ break;
+ default:
+ veh->AddPassenger(ped);
+ break;
}
}
+ ped->m_nPedState = PED_DRIVING;
+ if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->m_prevObjective = OBJECTIVE_NONE;
+
+ ped->RestorePreviousObjective();
+#ifdef VC_PED_PORTS
+ if(veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR)
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+#endif
}
- return ourCollidedSpheres;
-}
-void
-CPed::SetFormation(eFormation type)
-{
- // FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7.
- // To not change the behaviour, range in here tweaked by 1 with the use of enum.
-
- switch (m_pedFormation) {
- case FORMATION_REAR:
- case FORMATION_REAR_LEFT:
- case FORMATION_REAR_RIGHT:
- case FORMATION_FRONT_LEFT:
- case FORMATION_FRONT_RIGHT:
- case FORMATION_LEFT:
- case FORMATION_RIGHT:
- case FORMATION_FRONT:
+ veh->m_nGettingInFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
+
+ if (veh->bIsBus && !veh->m_nGettingInFlags)
+ ((CAutomobile*)veh)->SetBusDoorTimer(1000, 1);
+
+ switch (ped->m_objective) {
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_FOLLOW_CAR_IN_CAR:
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
break;
default:
- Error("Unknown formation type, PedAI.cpp");
- break;
+ ped->SetObjective(OBJECTIVE_NONE);
}
- m_pedFormation = type;
-}
-
-void
-CPed::SetFollowRoute(int16 currentPoint, int16 routeType)
-{
- m_routeLastPoint = currentPoint;
- m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);
- m_routePointsPassed = 0;
- m_routeType = routeType;
- m_routePointsBeingPassed = 1;
- m_objective = OBJECTIVE_FOLLOW_ROUTE;
- m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute());
-}
-// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway
-void
-CPed::WanderRange(void)
-{
- bool arrived = Seek();
- if (arrived) {
- Idle();
- if ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) {
- CVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange();
- SetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f);
+ 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();
+ if (veh->bIsBus)
+ ped->bRenderPedInCar = false;
+
+ // FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check.
+#ifndef FIX_BUGS
+ if (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) {
+#else
+ if (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) {
+#endif
+ CCarCtrl::RegisterVehicleOfInterest(veh);
+
+ if (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE)
+ CEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500);
+
+ veh->bHasBeenOwnedByPlayer = true;
+ }
+ ped->bChangedSeat = true;
}
bool
-CPed::WillChat(CPed *stranger)
+CPed::CanBeDeleted(void)
{
- if (m_pNextPathNode && m_pLastPathNode) {
- if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) {
+ if (bInVehicle)
+ return false;
+
+ switch (CharCreatedBy) {
+ case RANDOM_CHAR:
+ return true;
+ case MISSION_CHAR:
return false;
- }
+ default:
+ return true;
}
- if (m_nSurfaceTouched == SURFACE_TARMAC)
- return false;
- if (stranger == this)
- return false;
- if (m_nPedType == stranger->m_nPedType)
- return true;
- if (m_nPedType == PEDTYPE_CRIMINAL)
- return false;
- if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType)
- return false;
- return true;
}
void
-CPed::SetEnterTrain(CVehicle *train, uint32 unused)
+CPed::AddWeaponModel(int id)
{
- if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())
- return;
+ RpAtomic *atm;
- /*
- // Not used
- CVector enterPos;
- GetNearestTrainPedPosition(train, enterPos);
- */
- m_fRotationCur = train->GetForward().Heading() - HALFPI;
- m_pMyVehicle = train;
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ if (id != -1) {
+#ifdef PED_SKIN
+ if (IsClumpSkinned(GetClump())) {
+ if (m_pWeaponModel)
+ RemoveWeaponModel(-1);
- m_nPedState = PED_ENTER_TRAIN;
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f);
- m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);
- bUsesCollision = false;
- LineUpPedWithTrain();
- if (IsPlayer()) {
- if (((CPlayerPed*)this)->m_bAdrenalineActive)
- ((CPlayerPed*)this)->ClearAdrenaline();
+ m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
+ } else
+#endif
+ {
+ atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
+ RwFrameDestroy(RpAtomicGetFrame(atm));
+ RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame);
+ RpClumpAddAtomic(GetClump(), atm);
+ }
+ m_wepModelID = id;
}
}
-void
-CPed::SetDuck(uint32 time)
+static RwObject*
+RemoveAllModelCB(RwObject *object, void *data)
{
- if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer)
- return;
+ RpAtomic *atomic = (RpAtomic*)object;
+ if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
+ RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
+ RpAtomicDestroy(atomic);
+ }
+ return object;
+}
- 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;
+void
+CPed::RemoveWeaponModel(int modelId)
+{
+ // modelId is not used!! This function just removes the current weapon.
+#ifdef PED_SKIN
+ if(IsClumpSkinned(GetClump())){
+ if(m_pWeaponModel){
+ RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel);
+ RpAtomicDestroy(m_pWeaponModel);
+ RwFrameDestroy(frm);
+ m_pWeaponModel = nil;
}
+ }else
+#endif
+ RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil);
+ m_wepModelID = -1;
+}
+
+uint32
+CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo)
+{
+ CWeapon &weapon = GetWeapon(weaponType);
+
+ if (HasWeapon(weaponType)) {
+ if (weapon.m_nAmmoTotal + ammo > 99999)
+ weapon.m_nAmmoTotal = 99999;
+ else
+ weapon.m_nAmmoTotal += ammo;
+
+ weapon.Reload();
} else {
- CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
- bIsDucking = true;
- m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
- }
+ 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 (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO)
+ weapon.m_eWeaponState = WEAPONSTATE_READY;
+
+ return weaponType;
+}
+
+// Some kind of VC leftover I think
+int
+CPed::GetWeaponSlot(eWeaponType weaponType)
+{
+ if (HasWeapon(weaponType))
+ return weaponType;
+ else
+ return -1;
}
void
-CPed::SeekBoatPosition(void)
+CPed::SetCurrentWeapon(uint32 weaponType)
{
- if (m_carInObjective && !m_carInObjective->pDriver) {
- CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo();
+ CWeaponInfo *weaponInfo;
+ if (HasWeapon(weaponType)) {
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(weaponInfo->m_nModelId);
- CVector enterOffset;
- enterOffset = boatModel->GetFrontSeatPosn();
- enterOffset.x = 0.0f;
- CMatrix boatMat(m_carInObjective->GetMatrix());
- SetMoveState(PEDMOVE_WALK);
- m_vecSeekPos = boatMat * enterOffset;
- if (Seek()) {
- // We arrived to the boat
- m_vehEnterType = 0;
- SetEnterCar(m_carInObjective, 0);
- }
- } else
- RestorePreviousState();
+ m_currentWeapon = weaponType;
+
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ AddWeaponModel(weaponInfo->m_nModelId);
+ }
}
void
-CPed::SetEnterCar(CVehicle *car, uint32 unused)
+CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo)
{
- if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
- RestorePreviousState();
- RestorePreviousObjective();
+ if (HasWeapon(weaponType)) {
+ GetWeapon(weaponType).m_nAmmoTotal += ammo;
} else {
- uint8 doorFlag;
- eDoors door;
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- doorFlag = CAR_DOOR_FLAG_RF;
- door = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- doorFlag = CAR_DOOR_FLAG_RR;
- door = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- doorFlag = CAR_DOOR_FLAG_LF;
- door = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- doorFlag = CAR_DOOR_FLAG_LR;
- door = DOOR_REAR_LEFT;
- break;
- default:
- doorFlag = CAR_DOOR_FLAG_UNKNOWN;
- break;
- }
- if (!IsPedInControl() || m_fHealth <= 0.0f
- || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags
- || car->bIsBeingCarJacked || m_pVehicleAnim
- || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))
- SetMoveState(PEDMOVE_STILL);
- else
- SetEnterCar_AllClear(car, m_vehEnterType, doorFlag);
+ GetWeapon(weaponType).Initialise(weaponType, ammo);
+ m_maxWeaponTypeAllowed++;
}
}
void
-CPed::SetRadioStation(void)
+CPed::SetAmmo(eWeaponType weaponType, uint32 ammo)
{
- static const uint8 radiosPerRadioCategories[10][4] = {
- {JAH_RADIO, RISE_FM, GAME_FM, MSX_FM},
- {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
- {RISE_FM, GAME_FM, MSX_FM, FLASHBACK},
- {HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM},
- {HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK},
- {JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK},
- {HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK},
- {HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK},
- {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
- {CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM}
- };
- uint8 orderInCat = 0; // BUG: this wasn't initialized
-
- if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this)
- return;
-
- uint8 category = GetPedRadioCategory(GetModelIndex());
- if (DMAudio.IsMP3RadioChannelAvailable()) {
- if (CGeneral::GetRandomNumber() & 15) {
- for (orderInCat = 0; orderInCat < 4; orderInCat++) {
- if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
- break;
- }
- } else {
- m_pMyVehicle->m_nRadioStation = USERTRACK;
- }
+ if (HasWeapon(weaponType)) {
+ GetWeapon(weaponType).m_nAmmoTotal = ammo;
} else {
- for (orderInCat = 0; orderInCat < 4; orderInCat++) {
- if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
- break;
- }
- }
- if (orderInCat == 4) {
- if (DMAudio.IsMP3RadioChannelAvailable()) {
- if (CGeneral::GetRandomNumber() & 15)
- m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
- else
- m_pMyVehicle->m_nRadioStation = USERTRACK;
- } else {
- m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
- }
+ GetWeapon(weaponType).Initialise(weaponType, ammo);
+ m_maxWeaponTypeAllowed++;
}
}
-inline bool
-CPed::IsNotInWreckedVehicle()
+void
+CPed::ClearWeapons(void)
{
- return m_pMyVehicle != nil && m_pMyVehicle->GetStatus() != STATUS_WRECKED;
+ 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;
+ }
}
void
@@ -14969,693 +4894,1120 @@ CPed::PreRender(void)
}
void
-CPed::ProcessBuoyancy(void)
+CPed::Render(void)
{
- static uint32 nGenerateRaindrops = 0;
- static uint32 nGenerateWaterCircles = 0;
- CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f),
- ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f),
- ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f),
- (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48);
+ if (bInVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) {
+ if (!bRenderPedInCar)
+ return;
- if (bInVehicle)
- return;
+ float camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr();
+ if (camDistSq > SQR(25.0f * TheCamera.LODDistMultiplier))
+ return;
+ }
- CVector buoyancyPoint;
- CVector buoyancyImpulse;
+ CEntity::Render();
-#ifndef VC_PED_PORTS
- float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f);
-#else
- float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f);
+#ifdef PED_SKIN
+ if(IsClumpSkinned(GetClump())){
+ renderLimb(PED_HEAD);
+ renderLimb(PED_HANDL);
+ renderLimb(PED_HANDR);
+ }
+ if(m_pWeaponModel && IsClumpSkinned(GetClump())){
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);
+ RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
+ RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel);
+ *RwFrameGetMatrix(frame) = *mat;
+ RwFrameUpdateObjects(frame);
+ RpAtomicRender(m_pWeaponModel);
+ }
#endif
+}
- if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
- bTouchingWater = true;
- CEntity *entity;
- CColPoint point;
- if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil)
- && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) {
- bIsInWater = false;
- return;
+void
+CPed::CheckAroundForPossibleCollisions(void)
+{
+ CVector ourCentre, objCentre;
+ CEntity *objects[8];
+ int16 maxObject;
+
+ if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)
+ return;
+
+ GetBoundCentre(ourCentre);
+
+ CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false);
+ for (int i = 0; i < maxObject; i++) {
+ CEntity *object = objects[i];
+ if (bRunningToPhone) {
+ if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition()))
+ break;
}
- bIsInWater = true;
- ApplyMoveForce(buoyancyImpulse);
- if (!DyingOrDead()) {
- if (bTryingToReachDryLand) {
- if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) {
- bTryingToReachDryLand = false;
- CVector pos = GetPosition();
- if (PlacePedOnDryLand()) {
- if (m_fHealth > 20.0f)
- InflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false);
+ object->GetBoundCentre(objCentre);
+ float radius = object->GetBoundRadius();
+ if (radius > 4.5f || radius < 1.0f)
+ radius = 1.0f;
- if (bIsInTheAir) {
- RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
- bIsInTheAir = false;
- }
- pos.z = pos.z - 0.8f;
-#ifdef PC_PARTICLE
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true);
-#else
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true);
-#endif
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_nPedState = PED_IDLE;
- return;
- }
- }
- }
- float speedMult = 0.0f;
- if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.75f * CTimer::GetTimeStep()
- || mod_Buoyancy.m_waterlevel > GetPosition().z) {
- speedMult = pow(0.9f, CTimer::GetTimeStep());
- m_vecMoveSpeed.x *= speedMult;
- m_vecMoveSpeed.y *= speedMult;
- m_vecMoveSpeed.z *= speedMult;
- bIsStanding = false;
- InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
- }
- if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) {
- if (speedMult == 0.0f) {
- speedMult = pow(0.9f, CTimer::GetTimeStep());
- }
- m_vecMoveSpeed.x *= speedMult;
- m_vecMoveSpeed.y *= speedMult;
- if (m_vecMoveSpeed.z >= -0.1f) {
- if (m_vecMoveSpeed.z < -0.04f)
- m_vecMoveSpeed.z = -0.02f;
- } else {
- m_vecMoveSpeed.z = -0.01f;
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f);
-#ifdef PC_PARTICLE
- CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
- aBitForward.z = level;
+ // Developers gave up calculating Z diff. later according to asm.
+ float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D();
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true);
- nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80;
- nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100;
-#else
- CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
- aBitForward.z = level + 0.5f;
-
- CVector vel = m_vecMoveSpeed * 0.1f;
- vel.z = 0.18f;
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true);
- nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300;
- nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60;
+ if (sq(radius + 1.0f) > diff)
+ m_fRotationDest += DEGTORAD(22.5f);
+ }
+}
+
+void
+CPed::SetIdle(void)
+{
+ if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {
+#ifdef VC_PED_PORTS
+ if (m_nPedState == PED_AIM_GUN)
+ ClearPointGunAt();
+
+ m_nLastPedState = PED_NONE;
#endif
+ m_nPedState = PED_IDLE;
+ SetMoveState(PEDMOVE_STILL);
+ }
+ if (m_nWaitState == WAITSTATE_FALSE) {
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000);
+ }
+}
+
+void
+CPed::Idle(void)
+{
+ CVehicle *veh = m_pMyVehicle;
+ if (veh && veh->m_nGettingOutFlags && m_vehEnterType) {
+
+ if (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehEnterType)) {
+
+ if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
+
+ CVector doorPos = GetPositionToOpenCarDoor(veh, m_vehEnterType);
+ CVector doorDist = GetPosition() - doorPos;
+
+ if (doorDist.MagnitudeSqr() < sq(0.5f)) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
}
}
- } else
- return;
- } else
- bTouchingWater = false;
+ }
+ }
- if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) {
- CVector pos = GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(pos, &level, false))
- pos.z = level;
+ CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
+ CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ int waitTime;
- if (pos.z != 0.0f) {
- nGenerateWaterCircles = 0;
- for(int i = 0; i < 4; i++) {
-#ifdef PC_PARTICLE
- pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
- pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
- CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0);
-#else
- pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
- pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
- CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f));
-#endif
+ if (m_nMoveState == PEDMOVE_STILL) {
+
+ eWeaponType curWeapon = GetWeapon()->m_eWeaponType;
+ if (!armedIdleAssoc ||
+ CTimer::GetTimeInMilliseconds() <= m_nWaitTimer && curWeapon != WEAPONTYPE_UNARMED && curWeapon != WEAPONTYPE_MOLOTOV && curWeapon != WEAPONTYPE_GRENADE) {
+
+ if ((!GetWeapon()->IsType2Handed() || curWeapon == WEAPONTYPE_SHOTGUN) && curWeapon != WEAPONTYPE_BASEBALLBAT
+ || !unarmedIdleAssoc || unarmedIdleAssoc->blendAmount <= 0.95f || m_nWaitState != WAITSTATE_FALSE || CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+
+ m_moved = CVector2D(0.0f, 0.0f);
+ return;
}
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_ARMED, 3.0f);
+ waitTime = CGeneral::GetRandomNumberInRange(4000, 7500);
+ } else {
+ armedIdleAssoc->blendDelta = -2.0f;
+ armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ waitTime = CGeneral::GetRandomNumberInRange(3000, 8500);
}
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ } else {
+ if (armedIdleAssoc) {
+ armedIdleAssoc->blendDelta = -8.0f;
+ armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ m_nWaitTimer = 0;
+ }
+ if (!IsPlayer())
+ SetMoveState(PEDMOVE_STILL);
}
+ m_moved = CVector2D(0.0f, 0.0f);
+}
- if (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) {
- CVector pos = GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(pos, &level, false))
- pos.z = level;
+void
+CPed::ClearPause(void)
+{
+ RestorePreviousState();
+}
- if (pos.z >= 0.0f) {
-#ifdef PC_PARTICLE
- pos.z += 0.25f;
-#else
- pos.z += 0.5f;
+void
+CPed::Pause(void)
+{
+ m_moved = CVector2D(0.0f, 0.0f);
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)
+ ClearPause();
+}
+
+void
+CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
+{
+ if (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead()))
+ return;
+
+ ClearLookFlag();
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_FALL;
+ CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId);
+
+ if (fallAssoc) {
+ fallAssoc->SetCurrentTime(0.0f);
+ fallAssoc->blendAmount = 0.0f;
+ fallAssoc->blendDelta = 8.0f;
+ fallAssoc->SetRun();
+ } else {
+ fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f);
+ }
+
+ if (extraTime == -1) {
+ m_getUpTimer = UINT32_MAX;
+ } else if (fallAssoc) {
+ if (IsPlayer()) {
+ m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
+ + CTimer::GetTimeInMilliseconds()
+ + 500.0f;
+ } else {
+ m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
+ + CTimer::GetTimeInMilliseconds()
+ + extraTime
+ + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
+ }
+ } else {
+ m_getUpTimer = extraTime
+ + CTimer::GetTimeInMilliseconds()
+ + 1000
+ + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
+ }
+ bFallenDown = true;
+}
+
+void
+CPed::ClearFall(void)
+{
+ SetGetUp();
+}
+
+void
+CPed::Fall(void)
+{
+ if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer
+#ifdef VC_PED_PORTS
+ && bIsStanding
#endif
- nGenerateRaindrops = 0;
-#ifdef PC_PARTICLE
- CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true);
-#else
- CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true);
+ )
+ ClearFall();
+
+ // VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III.
+}
+
+bool
+CPed::CheckIfInTheAir(void)
+{
+ if (bInVehicle)
+ return false;
+
+ CVector pos = GetPosition();
+ CColPoint foundColPoint;
+ CEntity *foundEntity;
+
+ float startZ = pos.z - 1.54f;
+ bool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil);
+ if (!foundGround && m_nPedState != PED_JUMP)
+ {
+ pos.z -= FEET_OFFSET;
+ if (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false))
+ foundGround = true;
+ }
+ return !foundGround;
+}
+
+void
+CPed::SetInTheAir(void)
+{
+ if (bIsInTheAir)
+ return;
+
+ bIsInTheAir = true;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f);
+
+ if (m_nPedState == PED_ATTACK) {
+ ClearAttack();
+ ClearPointGunAt();
+ } else if (m_nPedState == PED_FIGHT) {
+ EndFight(ENDFIGHT_FAST);
+ }
+
+}
+
+void
+CPed::InTheAir(void)
+{
+ CColPoint foundCol;
+ CEntity *foundEnt;
+
+ CVector ourPos = GetPosition();
+ CVector bitBelow = GetPosition();
+ bitBelow.z -= 4.04f;
+
+ if (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) {
+ if (!DyingOrDead()) {
+ if (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) {
+ if (GetPosition().z - foundCol.point.z < 1.3f
+#ifdef VC_PED_PORTS
+ || bIsStanding
#endif
+ )
+ SetLanding();
+ } else {
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)) {
+ if (m_vecMoveSpeed.z < -0.1f)
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_FALL, 4.0f);
+ }
+ }
}
}
}
void
-CPed::SetSolicit(uint32 time)
+CPed::SetLanding(void)
{
- if (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective)
+ if (DyingOrDead())
return;
- if (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0
- && CTimer::GetTimeInMilliseconds() < m_objectiveTimer) {
- if (m_vehEnterType == CAR_DOOR_LF) {
- m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
- } else {
- m_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI;
+ CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
+ CAnimBlendAssociation *landAssoc;
+
+ RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
+ if (fallAssoc) {
+ landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f);
+
+ if (IsPlayer())
+ Say(SOUND_PED_LAND);
+
+ } else {
+ landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f);
+ }
+
+ landAssoc->SetFinishCallback(PedLandCB, this);
+ bIsInTheAir = false;
+ bIsLanding = true;
+}
+
+void
+CPed::SetGetUp(void)
+{
+ if (m_nPedState == PED_GETUP && bGetUpAnimStarted)
+ return;
+
+ if (!CanSetPedState())
+ return;
+
+ if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) {
+ if (bUpdateAnimHeading) {
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ m_fRotationCur -= HALFPI;
+ bUpdateAnimHeading = false;
+ }
+ if (m_nPedState != PED_GETUP) {
+ SetStoredState();
+ m_nPedState = PED_GETUP;
}
- if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity;
+ CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition());
+ 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(),
+ aTempPedColPts, nil, nil) > 0)) {
- if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f);
+ bGetUpAnimStarted = false;
+ if (IsPlayer())
+ InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
+ else {
+ if (!CPad::GetPad(0)->ArePlayerControlsDisabled())
+ return;
- m_nPedState = PED_SOLICIT;
+ InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0);
+ }
+ return;
}
+ bGetUpAnimStarted = true;
+ m_pCollidingEntity = nil;
+ bKnockedUpIntoAir = false;
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
+ if (animAssoc) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f);
+ } else {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ }
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f);
+ else
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
+
+ animAssoc->SetFinishCallback(PedGetupCB,this);
+ } else {
+ m_fHealth = 0.0f;
+ SetDie(NUM_ANIMS, 4.0f, 0.0f);
}
}
-bool
-CPed::SetFollowPath(CVector dest)
+void
+CPed::Mug(void)
{
- if (m_nPedState == PED_FOLLOW_PATH)
- return false;
+ if (m_pSeekTarget && m_pSeekTarget->IsPed()) {
- if (FindPlayerPed() != this)
- return false;
+ if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) {
+ if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f)
+ m_wepSkills = 50;
- if ((dest - GetPosition()).Magnitude() <= 2.0f)
- return false;
+ Say(SOUND_PED_MUGGING);
+ ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED);
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ SetFlee(m_pSeekTarget, 20000);
+ }
- CVector pointPoses[7];
- int16 pointsFound;
- CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7);
- for(int i = 0; i < pointsFound; i++) {
- m_stPathNodeStates[i].x = pointPoses[i].x;
- m_stPathNodeStates[i].y = pointPoses[i].y;
+ } else {
+ SetIdle();
}
+}
- m_nCurPathNode = 0;
- m_nPathNodes = pointsFound;
- if (m_nPathNodes < 1)
- return false;
+void
+CPed::SetLookTimer(int time)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+}
- SetStoredState();
- m_nPedState = PED_FOLLOW_PATH;
- SetMoveState(PEDMOVE_WALK);
- return true;
+void
+CPed::SetAttackTimer(uint32 time)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_attackTimer)
+ m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;
}
void
-AddYardieDoorSmoke(CVehicle *veh, uint32 doorNode)
+CPed::SetShootTimer(uint32 time)
{
- eDoors door;
- switch (doorNode) {
- case CAR_DOOR_RF:
- door = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_LF:
- door = DOOR_FRONT_LEFT;
- break;
- default:
- break;
+ if (CTimer::GetTimeInMilliseconds() > m_shootTimer) {
+ m_shootTimer = CTimer::GetTimeInMilliseconds() + time;
}
+}
- if (!veh->IsDoorMissing(door) && veh->IsComponentPresent(doorNode)) {
- CVector pos;
-#ifdef FIX_BUGS
- veh->GetComponentWorldPosition(doorNode, pos);
-#else
- veh->GetComponentWorldPosition(CAR_DOOR_LF, pos);
-#endif
- CParticle::AddYardieDoorSmoke(pos, veh->GetMatrix());
+void
+CPed::ClearLook(void)
+{
+ RestorePreviousState();
+ ClearLookFlag();
+}
+
+void
+CPed::Look(void)
+{
+ // UNUSED: This is a perfectly empty function.
+}
+
+bool
+CPed::TurnBody(void)
+{
+ bool turnDone = true;
+
+ if (m_pLookTarget)
+ m_fLookDirection = CGeneral::GetRadianAngleBetweenPoints(
+ m_pLookTarget->GetPosition().x,
+ m_pLookTarget->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ float limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection);
+ float currentRot = m_fRotationCur;
+
+ if (currentRot - PI > limitedLookDir)
+ limitedLookDir += 2 * PI;
+ else if (PI + currentRot < limitedLookDir)
+ limitedLookDir -= 2 * PI;
+
+ float neededTurn = currentRot - limitedLookDir;
+ m_fRotationDest = limitedLookDir;
+
+ if (Abs(neededTurn) > 0.05f) {
+ turnDone = false;
+ currentRot -= neededTurn * 0.2f;
}
+
+ m_fRotationCur = currentRot;
+ m_fLookDirection = limitedLookDir;
+ return turnDone;
}
-// wantedDoorNode = 0 means that func. will determine it
void
-CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
+CPed::SetSeek(CVector pos, float distanceToCountDone)
{
- uint32 optedDoorNode = wantedDoorNode;
- bool teleportNeeded = false;
- bool isLow = !!veh->bLowVehicle;
- if (!veh->CanPedExitCar()) {
- if (veh->pDriver && !veh->pDriver->IsPlayer()) {
- veh->AutoPilot.m_nCruiseSpeed = 0;
- veh->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ if (!IsPedInControl()
+ || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
return;
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) {
+ ClearPointGunAt();
}
- if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
+ if (m_nPedState != PED_SEEK_POS)
+ SetStoredState();
+
+ m_nPedState = PED_SEEK_POS;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_vecSeekPos = pos;
+}
+
+void
+CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
+{
+ if (!IsPedInControl())
return;
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- if (wantedDoorNode == 0) {
- optedDoorNode = CAR_DOOR_LF;
- if (!veh->bIsBus) {
- if (veh->pDriver == this) {
- optedDoorNode = CAR_DOOR_LF;
- } else if (veh->pPassengers[0] == this) {
- optedDoorNode = CAR_DOOR_RF;
- } else if (veh->pPassengers[1] == this) {
- optedDoorNode = CAR_DOOR_LR;
- } else if (veh->pPassengers[2] == this) {
- optedDoorNode = CAR_DOOR_RR;
- } else {
- for (int i = 3; i < veh->m_nNumMaxPassengers; ++i) {
- if (veh->pPassengers[i] == this) {
- if (i & 1)
- optedDoorNode = CAR_DOOR_RR;
- else
- optedDoorNode = CAR_DOOR_LR;
+ if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)
+ return;
- break;
+ if (!seeking)
+ return;
+
+ if (m_nPedState != PED_SEEK_ENTITY)
+ SetStoredState();
+
+ m_nPedState = PED_SEEK_ENTITY;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_pSeekTarget = seeking;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ SetMoveState(PEDMOVE_STILL);
+}
+
+void
+CPed::ClearSeek(void)
+{
+ SetIdle();
+ bRunningToPhone = false;
+}
+
+bool
+CPed::Seek(void)
+{
+ float distanceToCountItDone = m_distanceToCountSeekDone;
+ eMoveState nextMove = PEDMOVE_NONE;
+
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+
+ if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT &&
+ m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) {
+
+ if ((!m_pedInObjective || !m_pedInObjective->bInVehicle)
+ && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) {
+
+ CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil,
+ false, true, false, false, false, false);
+
+ if (obstacle) {
+ if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) {
+ distanceToCountItDone = 2.5f;
+ } else {
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());
+ float yLength = vehModel->GetColModel()->boundingBox.max.y
+ - vehModel->GetColModel()->boundingBox.min.y;
+ distanceToCountItDone = yLength * 0.55f;
}
}
}
}
}
- bool someoneExitsFromOurExitDoor = false;
- bool someoneEntersFromOurExitDoor = false;
- switch (optedDoorNode) {
- case CAR_DOOR_RF:
- if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
- someoneEntersFromOurExitDoor = true;
- if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RF)
- someoneExitsFromOurExitDoor = true;
- break;
- case CAR_DOOR_RR:
- if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
- someoneEntersFromOurExitDoor = true;
- if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RR)
- someoneExitsFromOurExitDoor = true;
- break;
- case CAR_DOOR_LF:
- if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF)
- someoneEntersFromOurExitDoor = true;
- if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LF)
- someoneExitsFromOurExitDoor = true;
- break;
- case CAR_DOOR_LR:
- if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
- someoneEntersFromOurExitDoor = true;
- if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LR)
- someoneExitsFromOurExitDoor = true;
- break;
- default:
- break;
+
+ if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)
+ ClearSeek();
+
+ float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();
+ if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {
+
+ if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
+
+ if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
+ nextMove = m_pedInObjective->m_nMoveState;
+ } else
+ nextMove = PEDMOVE_WALK;
+
+ } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
+
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning)
+ nextMove = PEDMOVE_RUN;
+ else
+ nextMove = PEDMOVE_WALK;
+
+ } else if (seekPosDist <= 2.0f) {
+
+ if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
+ nextMove = m_pedInObjective->m_nMoveState;
+
+ } else {
+ nextMove = PEDMOVE_RUN;
}
- if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) {
- RestorePreviousObjective();
- return;
+
+ if (m_nPedState == PED_SEEK_ENTITY) {
+ if (m_pSeekTarget->IsPed()) {
+ if (((CPed*)m_pSeekTarget)->bInVehicle)
+ distanceToCountItDone += 2.0f;
+ }
}
- if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) {
- // Again, unused...
- // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
- bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);
- if (veh->IsOnItsSide()) {
- teleportNeeded = true;
- } else if (!thereIsRoom) {
- bool trySideSeat = false;
- CPed *pedOnSideSeat = nil;
- switch (optedDoorNode) {
- case CAR_DOOR_RF:
- if (veh->pDriver || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) {
- pedOnSideSeat = veh->pDriver;
- trySideSeat = true;
- } else
- optedDoorNode = CAR_DOOR_LF;
- break;
- case CAR_DOOR_RR:
- if (veh->pPassengers[1] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
- pedOnSideSeat = veh->pPassengers[1];
- trySideSeat = true;
- } else
- optedDoorNode = CAR_DOOR_LR;
+ if (seekPosDist >= distanceToCountItDone) {
+ if (bIsRunning)
+ nextMove = PEDMOVE_RUN;
- break;
- case CAR_DOOR_LF:
- if (veh->pPassengers[0] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
- pedOnSideSeat = veh->pPassengers[0];
- trySideSeat = true;
- } else
- optedDoorNode = CAR_DOOR_RF;
+ if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) {
- break;
- case CAR_DOOR_LR:
- if (veh->pPassengers[2] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
- pedOnSideSeat = (CPed*)veh->pPassengers[2];
- trySideSeat = true;
- } else
- optedDoorNode = CAR_DOOR_RR;
+ if (m_actionX != 0.0f && m_actionY != 0.0f) {
- break;
- default:
- break;
- }
- if (trySideSeat) {
- if (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR)
- return;
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_actionX, m_actionY,
+ GetPosition().x, GetPosition().y);
- switch (optedDoorNode) {
- case CAR_DOOR_RF:
- optedDoorNode = CAR_DOOR_LF;
- break;
- case CAR_DOOR_RR:
- optedDoorNode = CAR_DOOR_LR;
- break;
- case CAR_DOOR_LF:
- optedDoorNode = CAR_DOOR_RF;
- break;
- case CAR_DOOR_LR:
- optedDoorNode = CAR_DOOR_RR;
- break;
- default:
- break;
+ float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ if (neededTurn > HALFPI) {
+ if (seekPosDist >= 1.0f) {
+ if (seekPosDist < 2.0f) {
+ if (bIsRunning)
+ nextMove = PEDMOVE_RUN;
+ else
+ nextMove = PEDMOVE_WALK;
+ }
+ } else {
+ nextMove = PEDMOVE_STILL;
+ }
}
- }
- // ...
- // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
- if (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) {
- if (!IsPlayer() && CharCreatedBy != MISSION_CHAR)
- return;
- teleportNeeded = true;
+ CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY);
+ if (moveDist.Magnitude() < 0.5f) {
+ m_nPedStateTimer = 0;
+ m_actionX = 0;
+ m_actionY = 0;
+ }
}
- }
- if (m_nPedState == PED_FLEE_POS) {
- m_nLastPedState = PED_FLEE_POS;
- m_nPrevMoveState = PEDMOVE_RUN;
- SetMoveState(PEDMOVE_SPRINT);
} else {
- m_nLastPedState = PED_IDLE;
- m_nPrevMoveState = PEDMOVE_STILL;
- SetMoveState(PEDMOVE_STILL);
- }
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecSeekPos.x, m_vecSeekPos.y,
+ GetPosition().x, GetPosition().y);
- ReplaceWeaponWhenExitingVehicle();
- bUsesCollision = false;
- m_pSeekTarget = veh;
- m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
- m_vehEnterType = optedDoorNode;
- m_nPedState = PED_EXIT_CAR;
- if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL)
- m_pVehicleAnim->blendDelta = -1000.0f;
- SetMoveState(PEDMOVE_NONE);
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- RemoveInCarAnims();
- veh->AutoPilot.m_nCruiseSpeed = 0;
- if (teleportNeeded) {
- PedSetOutCarCB(nil, this);
-
- // This is same code with CPedPlacement::FindZCoorForPed, except we start from z + 1.5 and also check vehicles.
- float zForPed;
- float startZ = GetPosition().z - 100.0f;
- float foundColZ = -100.0f;
- float foundColZ2 = -100.0f;
- CColPoint foundCol;
- CEntity* foundEnt;
-
- CVector vec = GetPosition();
- vec.z += 1.5f;
-
- if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
- foundColZ = foundCol.point.z;
-
- // Adjust coords and do a second test
- vec.x += 0.1f;
- vec.y += 0.1f;
-
- if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
- foundColZ2 = foundCol.point.z;
-
- zForPed = Max(foundColZ, foundColZ2);
-
- if (zForPed > -99.0f)
- GetMatrix().GetPosition().z = FEET_OFFSET + zForPed;
- } else {
- if (veh->GetUp().z > -0.8f) {
- bool addDoorSmoke = false;
- if (veh->GetModelIndex() == MI_YARDIE)
- addDoorSmoke = true;
-
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- if (veh->bIsBus) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
- } else {
- if (isLow)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
- else
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+ float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
- if (addDoorSmoke)
- AddYardieDoorSmoke(veh, CAR_DOOR_RF);
- }
- break;
- case CAR_DOOR_RR:
- if (veh->bIsVan) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT);
- } else if (isLow) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
- } else {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
- }
- break;
- case CAR_DOOR_LF:
- if (veh->bIsBus) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
- } else {
- if (isLow)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
- else
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
- if (addDoorSmoke)
- AddYardieDoorSmoke(veh, CAR_DOOR_LF);
- }
- break;
- case CAR_DOOR_LR:
- if (veh->bIsVan) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L);
- } else if (isLow) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
- } else {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
- }
- break;
- default:
- break;
- }
- if (!bBusJacked) {
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RF;
- break;
- case CAR_DOOR_RR:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RR;
- break;
- case CAR_DOOR_LF:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;
- break;
- case CAR_DOOR_LR:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LR;
- break;
- default:
- break;
- }
- }
- m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);
- } else {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2);
- } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS);
+ if (neededTurn > HALFPI) {
+ if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) {
+ if (seekPosDist < 2.0f)
+ nextMove = PEDMOVE_WALK;
+ } else {
+ nextMove = PEDMOVE_STILL;
}
- m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
}
}
- bChangedSeat = false;
- if (veh->bIsBus)
- bRenderPedInCar = true;
- SetRadioStation();
- if (veh->pDriver == this) {
- if (IsPlayer())
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- else
- veh->SetStatus(STATUS_ABANDONED);
+ if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove)
+ || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) {
+
+ SetMoveState(nextMove);
}
+
+ SetMoveAnim();
+ return false;
+ }
+
+ if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) {
+ m_nPedStateTimer = 0;
+ m_actionX = 0;
+ m_actionY = 0;
+ }
+
+ if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) {
+ if (m_pNextPathNode)
+ m_pNextPathNode = nil;
+ else
+ bScriptObjectiveCompleted = true;
+
+ bUsePedNodeSeek = true;
}
+
+ if (SeekFollowingPath(nil))
+ m_nCurPathNode++;
+
+ return true;
}
void
-CPed::ScanForInterestingStuff(void)
+CPed::SetFlee(CVector2D const &from, int time)
{
- if (!IsPedInControl())
+ if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace)
return;
- if (m_objective != OBJECTIVE_NONE)
- return;
+ if (m_nPedState != PED_FLEE_ENTITY) {
+ SetStoredState();
+ m_nPedState = PED_FLEE_POS;
+ SetMoveState(PEDMOVE_RUN);
+ m_fleeFromPosX = from.x;
+ m_fleeFromPosY = from.y;
+ }
- if (CharCreatedBy == MISSION_CHAR)
- return;
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
- LookForSexyPeds();
- LookForSexyCars();
- if (LookForInterestingNodes())
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x, GetPosition().y,
+ from.x, from.y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
+ if (m_fRotationCur - PI > m_fRotationDest) {
+ m_fRotationDest += 2 * PI;
+ } else if (PI + m_fRotationCur < m_fRotationDest) {
+ m_fRotationDest -= 2 * PI;
+ }
+}
+
+void
+CPed::SetFlee(CEntity *fleeFrom, int time)
+{
+ if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom)
return;
- if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
- if (CGeneral::GetRandomNumber() % 100 >= 10) {
- if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) {
- CPed *charToMug = nil;
- for (int i = 0; i < m_numNearPeds; ++i) {
- CPed *nearPed = m_nearPeds[i];
+ SetStoredState();
+ m_nPedState = PED_FLEE_ENTITY;
+ bUsePedNodeSeek = true;
+ SetMoveState(PEDMOVE_RUN);
+ m_fleeFrom = fleeFrom;
+ m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
- if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f))
- break;
+ if (time <= 0)
+ m_fleeTimer = 0;
+ else
+ m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
- if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE
- || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1
- || nearPed->m_nPedType == PEDTYPE_PROSTITUTE)
- && nearPed->CharCreatedBy != MISSION_CHAR
- && nearPed->IsPedShootable()
- && nearPed->m_objective != OBJECTIVE_MUG_CHAR) {
- charToMug = nearPed;
- break;
- }
- }
- if (charToMug)
- SetObjective(OBJECTIVE_MUG_CHAR, charToMug);
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x, GetPosition().y,
+ fleeFrom->GetPosition().x, fleeFrom->GetPosition().y);
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
+ if (m_fRotationCur - PI > m_fRotationDest) {
+ m_fRotationDest += 2 * PI;
+ } else if (PI + m_fRotationCur < m_fRotationDest) {
+ m_fRotationDest -= 2 * PI;
+ }
+}
+
+void
+CPed::ClearFlee(void)
+{
+ RestorePreviousState();
+ bUsePedNodeSeek = false;
+ m_standardTimer = 0;
+ m_fleeTimer = 0;
+}
+
+void
+CPed::Flee(void)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) {
+ bool mayFinishFleeing = true;
+ if (m_nPedState == PED_FLEE_ENTITY) {
+ if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f))
+ mayFinishFleeing = false;
+ }
+
+ if (mayFinishFleeing) {
+ eMoveState moveState = m_nMoveState;
+ ClearFlee();
+
+ if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
+ RestorePreviousObjective();
+
+ if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) {
+ SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil);
}
- } else {
- int mostExpensiveVehAround = -1;
- int bestMonetaryValue = 0;
+ return;
+ }
+ m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ }
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
- CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ if (bUsePedNodeSeek) {
+ CPathNode *realLastNode = nil;
+ uint8 nextDirection = 0;
+ uint8 curDirectionShouldBe = 9; // means not defined yet
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* veh = (CVehicle*)vehicles[i];
+ if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()
+ && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) {
- if (veh->VehicleCreatedBy != MISSION_VEHICLE) {
- if (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal()
- && veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) {
- mostExpensiveVehAround = i;
- bestMonetaryValue = veh->pHandling->nMonetaryValue;
- }
+ if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+
+ curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
+ if (m_nPathDir < curDirectionShouldBe)
+ m_nPathDir += 8;
+
+ int dirDiff = m_nPathDir - curDirectionShouldBe;
+ if (dirDiff > 2 && dirDiff < 6) {
+ realLastNode = nil;
+ m_pLastPathNode = m_pNextPathNode;
+ m_pNextPathNode = nil;
}
}
- if (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]);
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
- return;
+
+ if (m_pNextPathNode) {
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+ if (m_nMoveState == PEDMOVE_RUN)
+ bIsRunning = true;
+
+ eMoveState moveState = m_nMoveState;
+ if (Seek()) {
+ realLastNode = m_pLastPathNode;
+ m_pLastPathNode = m_pNextPathNode;
+ m_pNextPathNode = nil;
+ }
+ bIsRunning = false;
+ SetMoveState(moveState);
}
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
}
- }
- if (m_nPedState == PED_WANDER_PATH) {
-#ifndef VC_PED_PORTS
- if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+ if (!m_pNextPathNode) {
+ if (curDirectionShouldBe == 9) {
+ curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
+ }
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ curDirectionShouldBe,
+ &nextDirection);
- // += 2 is weird
- for (int i = 0; i < m_numNearPeds; i += 2) {
- if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH && WillChat(m_nearPeds[i])) {
- if (CGeneral::GetRandomNumberInRange(0, 100) >= 100)
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
- else {
- if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
- } else if (CanSeeEntity(m_nearPeds[i])) {
- int time = CGeneral::GetRandomNumber() % 4000 + 10000;
- SetChat(m_nearPeds[i], time);
- m_nearPeds[i]->SetChat(this, time);
- return;
- }
- }
- }
+ if (curDirectionShouldBe < nextDirection)
+ curDirectionShouldBe += 8;
+
+ if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {
+ m_nPathDir = nextDirection;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ } else {
+ bUsePedNodeSeek = false;
+ SetMoveState(PEDMOVE_RUN);
+ Flee();
}
}
-#else
- if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= 0.5f) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 200;
+ return;
+ }
+
+ if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
+
+ float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x,
+ GetPosition().y,
+ ms_vec2DFleePosition.x,
+ ms_vec2DFleePosition.y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos);
+
+ if (m_fRotationCur - PI > m_fRotationDest)
+ m_fRotationDest += TWOPI;
+ else if (PI + m_fRotationCur < m_fRotationDest)
+ m_fRotationDest -= TWOPI;
+ }
+
+ if (CTimer::GetTimeInMilliseconds() & 0x20) {
+ //CVector forwardPos = GetPosition();
+ CMatrix forwardMat(GetMatrix());
+ forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f));
+ CVector forwardPos = forwardMat.GetPosition();
+
+ CEntity *foundEnt;
+ CColPoint foundCol;
+ bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0);
+
+ if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) {
+ m_fRotationDest += DEGTORAD(112.5f);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ }
+
+ if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer)
+ return;
+
+ if (!m_collidingEntityWhileFleeing)
+ return;
+
+ double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500;
+
+ if (collidingThingPriorityMult <= 1.5) {
+
+ double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x,
+ GetPosition().y,
+ m_collidingEntityWhileFleeing->GetPosition().x,
+ m_collidingEntityWhileFleeing->GetPosition().y);
+ angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity);
+
+ double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecDamageNormal.x,
+ m_vecDamageNormal.y,
+ 0.0f,
+ 0.0f);
+ angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing);
+
+ if (angleToFleeEntity - PI > angleToFleeCollidingThing)
+ angleToFleeCollidingThing += TWOPI;
+ else if (PI + angleToFleeEntity < angleToFleeCollidingThing)
+ angleToFleeCollidingThing -= TWOPI;
+
+ if (collidingThingPriorityMult <= 1.0f) {
+ // Range [0.0, 1.0]
+
+ float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f;
+
+ if (m_fRotationDest - PI > angleToFleeBoth)
+ angleToFleeBoth += TWOPI;
+ else if (PI + m_fRotationDest < angleToFleeBoth)
+ angleToFleeBoth -= TWOPI;
+
+ m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth;
} else {
- if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
- for (int i = 0; i < m_numNearPeds; i ++) {
- if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) {
- if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f
- && CanSeeEntity(m_nearPeds[i])
- && m_nearPeds[i]->CanSeeEntity(this)
- && WillChat(m_nearPeds[i])) {
+ // Range (1.0, 1.5]
- int time = CGeneral::GetRandomNumber() % 4000 + 10000;
- SetChat(m_nearPeds[i], time);
- m_nearPeds[i]->SetChat(this, time);
- return;
- }
- }
+ double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f;
+ m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing;
+ }
+ } else {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecDamageNormal.x,
+ m_vecDamageNormal.y,
+ 0.0f,
+ 0.0f);
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ }
+
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ if (m_fRotationCur - PI > m_fRotationDest)
+ m_fRotationDest += TWOPI;
+ else if (PI + m_fRotationCur < m_fRotationDest)
+ m_fRotationDest -= TWOPI;
+
+}
+
+// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway
+void
+CPed::WanderRange(void)
+{
+ bool arrived = Seek();
+ if (arrived) {
+ Idle();
+ if ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) {
+ CVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange();
+ SetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f);
+ }
+ }
+}
+
+bool
+CPed::SetWanderPath(int8 pathStateDest)
+{
+ uint8 nextPathState;
+
+ if (IsPedInControl()) {
+ if (bKindaStayInSamePlace) {
+ SetIdle();
+ return false;
+ } else {
+ m_nPathDir = pathStateDest;
+ if (pathStateDest == 0)
+ pathStateDest = CGeneral::GetRandomNumberInRange(1, 7);
+
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &nextPathState);
+
+ // Circular loop until we find a node for current m_nPathDir
+ while (!m_pNextPathNode) {
+ m_nPathDir = (m_nPathDir+1) % 8;
+
+ // We're at where we started and couldn't find any node
+ if (m_nPathDir == pathStateDest) {
+ ClearAll();
+ SetIdle();
+ return false;
}
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &nextPathState);
}
+
+ // We did it, save next path state and return true
+ m_nPathDir = nextPathState;
+ m_nPedState = PED_WANDER_PATH;
+ SetMoveState(PEDMOVE_WALK);
+ bIsRunning = false;
+ return true;
}
-#endif
+ } else {
+ m_nPathDir = pathStateDest;
+ bStartWanderPathOnFoot = true;
+ return false;
}
+}
- // Parts below aren't there in VC, they're in somewhere else.
- if (!CGame::noProstitutes && m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy != MISSION_CHAR
- && m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) {
+void
+CPed::WanderPath(void)
+{
+ if (!m_pNextPathNode) {
+ printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n");
+ SetIdle();
+ return;
+ }
+ if (m_nWaitState == WAITSTATE_FALSE) {
+ if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
+ SetMoveState(PEDMOVE_WALK);
+ }
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+ m_vecSeekPos.z += 1.0f;
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
+ if (!Seek())
+ return;
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* veh = (CVehicle*)vehicles[i];
+ CPathNode *previousLastNode = m_pLastPathNode;
+ uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;
- if (veh->IsVehicleNormal()) {
- if (veh->IsCar()) {
- if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) {
- SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh);
- Say(SOUND_PED_SOLICIT);
- return;
- }
+ // We don't prefer 180-degree turns in normal situations
+ uint8 dirWeWouldntPrefer = m_nPathDir;
+ if (dirWeWouldntPrefer <= 3)
+ dirWeWouldntPrefer += 4;
+ else
+ dirWeWouldntPrefer -= 4;
+
+ CPathNode *nodeWeWouldntPrefer = nil;
+ uint8 dirToSet = 9; // means undefined
+ uint8 dirWeWouldntPrefer2 = 9; // means undefined
+ if (randVal <= 90) {
+ if (randVal > 80) {
+ m_nPathDir += 2;
+ m_nPathDir %= 8;
+ }
+ } else {
+ m_nPathDir -= 2;
+ if (m_nPathDir < 0)
+ m_nPathDir += 8;
+ }
+
+ m_pLastPathNode = m_pNextPathNode;
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &dirToSet);
+
+ uint8 tryCount = 0;
+
+ // NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7
+ while (!m_pNextPathNode) {
+ tryCount++;
+ m_nPathDir = (m_nPathDir + 1) % 8;
+
+ // We're at where we started and couldn't find any node
+ if (tryCount > 7) {
+ if (!nodeWeWouldntPrefer) {
+ ClearAll();
+ SetIdle();
+ // Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.
+ Error("Can't find valid path node, SetWanderPath, Ped.cpp");
+ return;
+ }
+ m_pNextPathNode = nodeWeWouldntPrefer;
+ dirToSet = dirWeWouldntPrefer2;
+ } else {
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &dirToSet);
+ if (m_pNextPathNode) {
+ if (dirToSet == dirWeWouldntPrefer) {
+ nodeWeWouldntPrefer = m_pNextPathNode;
+ dirWeWouldntPrefer2 = dirToSet;
+ m_pNextPathNode = nil;
}
}
}
}
- if (m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* veh = (CVehicle*)vehicles[i];
+ m_nPathDir = dirToSet;
+ if (m_pLastPathNode == m_pNextPathNode) {
+ m_pNextPathNode = previousLastNode;
+ SetWaitState(WAITSTATE_DOUBLEBACK, nil);
+ Say(SOUND_PED_WAIT_DOUBLEBACK);
+ } else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) {
+ SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil);
+ } else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) {
+ SetWaitState(WAITSTATE_CROSS_ROAD, nil);
+ } else if (m_pNextPathNode == previousLastNode) {
+ SetWaitState(WAITSTATE_DOUBLEBACK, nil);
+ Say(SOUND_PED_WAIT_DOUBLEBACK);
+ }
+}
- if (veh->GetModelIndex() == MI_MRWHOOP) {
- if (veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED) {
- if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f) {
- SetObjective(OBJECTIVE_BUY_ICE_CREAM, veh);
- return;
+void
+CPed::Avoid(void)
+{
+ CPed *nearestPed;
+
+ if(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50)
+ return;
+
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+
+ if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
+ nearestPed = m_nearPeds[0];
+
+ if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) {
+
+ // Check if this ped wants to avoid the nearest one
+ if (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) {
+
+ // Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters.
+ // If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else.
+
+ // Game converts from radians to degress and back again here, doesn't make much sense
+ CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
+ forward.Normalise(); // this is kinda pointless
+
+ // Move forward 1.25 meters
+ CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f;
+
+ // Get distance to ped we want to avoid
+ CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition;
+
+ if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) {
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds()
+ + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter())
+ % 1000 / 5;
+
+ m_fRotationDest += DEGTORAD(45.0f);
+ if (!bIsLooking) {
+ SetLookFlag(nearestPed, false);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800));
+ }
}
}
}
@@ -15663,183 +6015,651 @@ CPed::ScanForInterestingStuff(void)
}
}
-uint32
-CPed::ScanForThreats(void)
+bool
+CPed::SeekFollowingPath(CVector *unused)
{
- int fearFlags = m_fearFlags;
- CVector ourPos = GetPosition();
- float closestPedDist = 60.0f;
- CVector2D explosionPos = GetPosition();
- if (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) {
- m_eventOrThreat = explosionPos;
- return PED_FLAG_EXPLOSION;
+ return m_nCurPathNode <= m_nPathNodes && m_nPathNodes;
+}
+
+bool
+CPed::SetFollowPath(CVector dest)
+{
+ if (m_nPedState == PED_FOLLOW_PATH)
+ return false;
+
+ if (FindPlayerPed() != this)
+ return false;
+
+ if ((dest - GetPosition()).Magnitude() <= 2.0f)
+ return false;
+
+ CVector pointPoses[7];
+ int16 pointsFound;
+ CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7);
+ for(int i = 0; i < pointsFound; i++) {
+ m_stPathNodeStates[i].x = pointPoses[i].x;
+ m_stPathNodeStates[i].y = pointPoses[i].y;
}
+
+ m_nCurPathNode = 0;
+ m_nPathNodes = pointsFound;
+ if (m_nPathNodes < 1)
+ return false;
+
+ SetStoredState();
+ m_nPedState = PED_FOLLOW_PATH;
+ SetMoveState(PEDMOVE_WALK);
+ return true;
+}
+
+void
+CPed::FollowPath(void)
+{
+ m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x;
+ m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y;
+ m_vecSeekPos.z = GetPosition().z;
- CPed *shooter = nil;
- if ((fearFlags & PED_FLAG_GUN) && (shooter = CheckForGunShots()) && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) {
- if (!IsGangMember()) {
- m_threatEntity = shooter;
- m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
- return PED_FLAG_GUN;
+ // Mysterious code
+/* int v4 = 0;
+ int maxNodeIndex = m_nPathNodes - 1;
+ if (maxNodeIndex > 0) {
+ if (maxNodeIndex > 8) {
+ while (v4 < maxNodeIndex - 8)
+ v4 += 8;
}
- if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags) {
- m_threatEntity = shooter;
- m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
- return CPedType::GetFlag(shooter->m_nPedType);
+ while (v4 < maxNodeIndex)
+ v4++;
+
+ }
+*/
+ if (Seek()) {
+ m_nCurPathNode++;
+ if (m_nCurPathNode == m_nPathNodes)
+ RestorePreviousState();
+ }
+}
+
+void
+CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
+{
+ AnimationId stepAnim;
+
+ if (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0))
+ return;
+
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ reason->GetPosition().x, reason->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ float neededTurn = Abs(angleToFace - m_fRotationCur);
+ bool vehPressedHorn = false;
+
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ CVehicle *veh = (CVehicle*)reason;
+ if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) {
+ if (veh->m_nCarHornTimer != 0) {
+ vehPressedHorn = true;
+ if (!IsPlayer())
+ animType = 1;
}
}
+ if (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) {
+ SetLookFlag(veh, true);
+ if ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) {
+ stepAnim = ANIM_IDLE_TAXI;
+ } else {
- CPed *deadPed = nil;
- if (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR
- && (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)) {
- m_pEventEntity = deadPed;
- m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
- return PED_FLAG_DEADPEDS;
- } else {
- uint32 flagsOfSomePed = 0;
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
- CPed *pedToFearFrom = nil;
-#ifndef VC_PED_PORTS
- for (int i = 0; i < m_numNearPeds; i++) {
- if (CharCreatedBy != RANDOM_CHAR || m_nearPeds[i]->CharCreatedBy != MISSION_CHAR || m_nearPeds[i]->IsPlayer()) {
- CPed *nearPed = m_nearPeds[i];
+ // Let's turn our back to the "reason"
+ angleToFace += PI;
- // BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance.
- // Fixed at the bottom of the function.
- flagsOfSomePed = CPedType::GetFlag(nearPed->m_nPedType);
+ if (angleToFace > PI)
+ angleToFace -= TWOPI;
- if (CPedType::GetFlag(nearPed->m_nPedType) & fearFlags) {
- if (nearPed->m_fHealth > 0.0f && OurPedCanSeeThisOne(m_nearPeds[i])) {
- // FIX: Taken from VC
+ // We don't want to run towards car's direction
+ float dangerZone = angleToFace - vehDirection;
+ dangerZone = CGeneral::LimitRadianAngle(dangerZone);
+
+ // So, add or subtract 90deg (jump to left/right) according to that
+ if (dangerZone > 0.0f)
+ angleToFace = vehDirection - HALFPI;
+ else
+ angleToFace = vehDirection + HALFPI;
+
+ stepAnim = NUM_ANIMS;
+ if (animType == 0 || animType == 1)
+ stepAnim = ANIM_EV_STEP;
+ else if (animType == 2)
+ stepAnim = ANIM_HANDSCOWER;
+ }
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) {
+ CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f);
+ stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ stepAssoc->SetFinishCallback(PedEvadeCB, this);
+
+ if (animType == 0)
+ Say(SOUND_PED_EVADE);
+
+ m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace);
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_STEP_AWAY;
+ }
+ }
+}
+
+void
+CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)
+{
+ if (!IsPedInControl() || !bRespondsToThreats)
+ return;
+
+ CAnimBlendAssociation *animAssoc;
+ float angleToFace, neededTurn;
+ bool handsUp = false;
+
+ angleToFace = m_fRotationCur;
+ CVehicle *veh = (CVehicle*) reason;
+ if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) {
+ onlyRandomJump = true;
+ }
+
+ if (onlyRandomJump) {
+ if (reason) {
+ // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly.
+ // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots.
+
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
+ angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection;
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ }
+ } else {
+ if (IsPlayer()) {
+ ((CPlayerPed*)this)->m_nEvadeAmount = 5;
+ ((CPlayerPed*)this)->m_pEvadingFrom = reason;
+ reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom);
+ return;
+ }
+
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ reason->GetPosition().x, reason->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted
#ifdef FIX_BUGS
- float nearPedDistSqr = (nearPed->GetPosition() - ourPos).MagnitudeSqr2D();
-#else
- float nearPedDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
+
+ // Let's turn our back to the "reason"
+ angleToFace += PI;
+
+ if (angleToFace > PI)
+ angleToFace -= 2 * PI;
+
+ // We don't want to dive towards car's direction
+ float dangerZone = angleToFace - vehDirection;
+ dangerZone = CGeneral::LimitRadianAngle(dangerZone);
+
+ // So, add or subtract 90deg (jump to left/right) according to that
+ if (dangerZone > 0.0f)
+ angleToFace = 0.5f * PI + vehDirection;
+ else
+ angleToFace = vehDirection - 0.5f * PI;
#endif
- if (sq(closestPedDist) > nearPedDistSqr) {
- closestPedDist = Sqrt(nearPedDistSqr);
- pedToFearFrom = m_nearPeds[i];
- }
- }
- }
- }
+
+ neededTurn = Abs(angleToFace - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = 2 * PI - neededTurn;
+
+ if (neededTurn <= 0.5f*PI) {
+ if (CGeneral::GetRandomNumber() & 1)
+ handsUp = true;
+ } else {
+ if (CGeneral::GetRandomNumber() & 7)
+ return;
}
-#else
- bool weSawOurEnemy = false;
- bool weMaySeeOurEnemy = false;
- float closestEnemyDist = 60.0f;
- if ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) {
+ Say(SOUND_PED_EVADE);
+ }
- for (int i = 0; i < m_numNearPeds; ++i) {
- if (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) {
- continue;
- }
+ if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) {
+ m_fRotationCur = angleToFace;
+ ClearLookFlag();
+ ClearAimFlag();
+ SetLookFlag(reason, true);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP);
+ if (animAssoc)
+ return;
- // BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function.
- flagsOfSomePed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType);
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f);
+ animAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ animAssoc->SetFinishCallback(PedEvadeCB, this);
+ SetStoredState();
+ m_nPedState = PED_STEP_AWAY;
+ } else {
+ m_fRotationCur = angleToFace;
+ ClearLookFlag();
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_DIVE_AWAY;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f);
+ animAssoc->SetFinishCallback(PedEvadeCB, this);
+ }
- if (flagsOfSomePed & fearFlags) {
- if (m_nearPeds[i]->m_fHealth > 0.0f) {
+ if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) {
+ if (veh->pDriver && veh->pDriver->IsPlayer()) {
+ CWanted *wanted = FindPlayerPed()->m_pWanted;
+ wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
+ wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false);
+ }
+ }
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ else if (reason->IsVehicle()) {
+ if (veh->pDriver && veh->pDriver->IsPlayer()) {
+ CWanted* wanted = FindPlayerPed()->m_pWanted;
+ wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
+ }
+ }
+#endif
+}
- // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
- if (OurPedCanSeeThisOne(m_nearPeds[i])) {
- if (m_nearPeds[i]->m_nPedState == PED_ATTACK) {
- if (m_nearPeds[i]->m_pedInObjective == this) {
+void
+CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
- float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestEnemyDist) > enemyDistSqr) {
- float enemyDist = Sqrt(enemyDistSqr);
- weSawOurEnemy = true;
- closestPedDist = enemyDist;
- closestEnemyDist = enemyDist;
- pedToFearFrom = m_nearPeds[i];
- }
- }
- } else {
- float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) {
- closestPedDist = Sqrt(nearPedDistSqr);
- pedToFearFrom = m_nearPeds[i];
- }
- }
- } else if (!weSawOurEnemy) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed->m_nPedState == PED_ATTACK) {
- CColPoint foundCol;
- CEntity *foundEnt;
+ if (!animAssoc) {
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)
+ ped->RestorePreviousState();
+
+ } else if (animAssoc->animId == ANIM_EV_DIVE) {
+ ped->bUpdateAnimHeading = true;
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY)
+ {
+ ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1;
+ ped->m_nPedState = PED_FALL;
+ }
+ animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- // We don't see him yet but he's behind a ped, vehicle or object
- // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
- if (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt,
- true, false, false, false, false, false, false)) {
+ } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) {
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)
+ ped->RestorePreviousState();
- if (nearPed->m_pedInObjective == this) {
- float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestEnemyDist) > enemyDistSqr) {
- float enemyDist = Sqrt(enemyDistSqr);
- weMaySeeOurEnemy = true;
- closestPedDist = enemyDist;
- closestEnemyDist = enemyDist;
- pedToFearFrom = m_nearPeds[i];
- }
- } else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) {
- float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestPedDist) > nearPedDistSqr) {
- weMaySeeOurEnemy = true;
- closestPedDist = Sqrt(nearPedDistSqr);
- pedToFearFrom = m_nearPeds[i];
- }
- }
- }
- }
- }
- }
- }
+ } else if (ped->m_nPedState != PED_ARRESTED) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (animAssoc->blendDelta >= 0.0f)
+ animAssoc->blendDelta = -4.0f;
+
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) {
+ ped->RestorePreviousState();
+ }
+ }
+}
+
+void
+CPed::SetDie(AnimationId animId, float delta, float speed)
+{
+ CPlayerPed *player = FindPlayerPed();
+ if (player == this) {
+ if (!player->m_bCanBeDamaged)
+ return;
+ }
+
+ m_threatEntity = nil;
+ if (DyingOrDead())
+ return;
+
+ if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP)
+ delta *= 0.5f;
+
+ SetStoredState();
+ ClearAll();
+ m_fHealth = 0.0f;
+ if (m_nPedState == PED_DRIVING) {
+ if (!IsPlayer())
+ FlagToDestroyWhenNextProcessed();
+ } else if (bInVehicle) {
+ if (m_pVehicleAnim)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+ } else if (EnteringCar()) {
+ QuitEnteringCar();
+ }
+
+ m_nPedState = PED_DIE;
+ if (animId == NUM_ANIMS) {
+ bIsPedDieAnimPlaying = false;
+ } else {
+ CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta);
+ if (speed > 0.0f)
+ dieAssoc->speed = speed;
+
+ dieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ if (dieAssoc->IsRunning()) {
+ dieAssoc->SetFinishCallback(FinishDieAnimCB, this);
+ bIsPedDieAnimPlaying = true;
+ }
+ }
+
+ Say(SOUND_PED_DEATH);
+ if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK)
+ QuitEnteringCar();
+ if (!bInVehicle)
+ StopNonPartialAnims();
+
+ m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
+}
+
+void
+CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (ped->bIsPedDieAnimPlaying)
+ ped->bIsPedDieAnimPlaying = false;
+}
+
+void
+CPed::SetDead(void)
+{
+ bUsesCollision = false;
+
+ m_fHealth = 0.0f;
+ if (m_nPedState == PED_DRIVING)
+ bIsVisible = false;
+
+ m_nPedState = PED_DEAD;
+ m_pVehicleAnim = nil;
+ m_pCollidingEntity = nil;
+
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(weapon->m_nModelId);
+
+ m_currentWeapon = WEAPONTYPE_UNARMED;
+ CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250);
+ if (this != FindPlayerPed()) {
+ CreateDeadPedWeaponPickups();
+ CreateDeadPedMoney();
+ }
+
+ m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
+ m_deadBleeding = false;
+ bDoBloodyFootprints = false;
+ bVehExitWillBeInstant = false;
+ CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
+}
+
+void
+CPed::Die(void)
+{
+ // UNUSED: This is a perfectly empty function.
+}
+
+void
+CPed::SetChat(CEntity *chatWith, uint32 time)
+{
+ if(m_nPedState != PED_CHAT)
+ SetStoredState();
+
+ m_nPedState = PED_CHAT;
+ SetMoveState(PEDMOVE_STILL);
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ m_lookTimer = 0;
+#endif
+ SetLookFlag(chatWith, true);
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
+}
+
+void
+CPed::Chat(void)
+{
+ // We're already looking to our partner
+ if (bIsLooking && TurnBody())
+ ClearLookFlag();
+
+ if (!m_pLookTarget || !m_pLookTarget->IsPed()) {
+ ClearChat();
+ return;
+ }
+
+ CPed *partner = (CPed*) m_pLookTarget;
+
+ if (partner->m_nPedState != PED_CHAT) {
+ ClearChat();
+ if (partner->m_pedInObjective) {
+ if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||
+ partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)
+ ReactToAttack(partner->m_pedInObjective);
+ }
+ return;
+ }
+ if (bIsTalking) {
+ if (CGeneral::GetRandomNumber() < 512) {
+ CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (chatAssoc) {
+ chatAssoc->blendDelta = -4.0f;
+ chatAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
+ bIsTalking = false;
+ } else
+ Say(SOUND_PED_CHAT);
+
+ } else {
+
+ if (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
}
+ if (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {
+ CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
+ float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);
+ chatAssoc->SetCurrentTime(chatTime);
+
+ bIsTalking = true;
+ Say(SOUND_PED_CHAT);
+ }
+ }
+ if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+ ClearChat();
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ }
+}
+
+void
+CPed::ClearChat(void)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ bIsTalking = false;
+ ClearLookFlag();
+ RestorePreviousState();
+}
+
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+void
+ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+ ped->m_nMoveState = PEDMOVE_STILL;
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f);
+
+ if (assoc->blendAmount > 0.5f && ped) {
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f);
+ }
+}
+
+void
+ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg)
+{
+ assoc->flags |= ASSOC_DELETEFADEDOUT;
+ assoc->blendDelta = -1000.0f;
+ CPed* ped = (CPed*)arg;
+
+ if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) {
+ crimeReporters[ped->m_phoneId] = nil;
+ gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE;
+ ped->m_phoneId = -1;
+ }
+
+ if (assoc->blendAmount > 0.5f)
+ ped->bUpdateAnimHeading = true;
+
+ ped->SetWanderPath(CGeneral::GetRandomNumber() & 7);
+}
#endif
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(ourPos, 20.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- CVehicle* foundVeh = nil;
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* nearVeh = (CVehicle*)vehicles[i];
- CPed *driver = nearVeh->pDriver;
- if (driver) {
+bool
+CPed::FacePhone(void)
+{
+ // This function was broken since it's left unused early in development.
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
+ gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
+ GetPosition().x, GetPosition().y);
- // BUG: Same bug as above. Fixed at the bottom of function.
- flagsOfSomePed = CPedType::GetFlag(driver->m_nPedType);
- if (CPedType::GetFlag(driver->m_nPedType) & fearFlags) {
- if (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) {
- // FIX: Taken from VC
-#ifdef FIX_BUGS
- float driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (m_facePhoneStart) {
+ m_lookTimer = 0;
+ SetLookFlag(phoneDir, true);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ m_facePhoneStart = false;
+ }
+
+ if (bIsLooking && TurnBody()) {
+ ClearLookFlag();
+ SetIdle();
+ m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f);
+ assoc->SetFinishCallback(ReportPhonePickUpCB, this);
+ return true;
+ }
+
+ return false;
#else
- float driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
+ float currentRot = RADTODEG(m_fRotationCur);
+ float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
+ gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x,
+ gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
+ GetPosition().x,
+ GetPosition().y);
+
+ SetLookFlag(phoneDir, false);
+ phoneDir = CGeneral::LimitAngle(phoneDir);
+ m_moved = CVector2D(0.0f, 0.0f);
+
+ if (currentRot - 180.0f > phoneDir)
+ phoneDir += 2 * 180.0f;
+ else if (180.0f + currentRot < phoneDir)
+ phoneDir -= 2 * 180.0f;
+
+ float neededTurn = currentRot - phoneDir;
+
+ if (Abs(neededTurn) <= 0.75f) {
+ SetIdle();
+ ClearLookFlag();
+ m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ return true;
+ } else {
+ m_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f);
+ return false;
+ }
#endif
- if (sq(closestPedDist) > driverDistSqr) {
- closestPedDist = Sqrt(driverDistSqr);
- pedToFearFrom = nearVeh->pDriver;
- }
- }
- }
- }
- }
- m_threatEntity = pedToFearFrom;
- if (m_threatEntity)
- m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
+}
+bool
+CPed::MakePhonecall(void)
+{
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) {
-#ifdef FIX_BUGS
- if (pedToFearFrom)
- flagsOfSomePed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType);
- else
- flagsOfSomePed = 0;
+ FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(),
+ (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false);
+
+ if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN)
+ FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1);
+
+ bRunningToPhone = false;
+ }
#endif
+ if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer)
+ return false;
- return flagsOfSomePed;
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK);
+ if (talkAssoc && talkAssoc->blendAmount > 0.5f) {
+ CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f);
+ endAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ endAssoc->SetFinishCallback(ReportPhonePutDownCB, this);
}
+#endif
+ SetIdle();
+
+ gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE;
+#ifndef PEDS_REPORT_CRIMES_ON_PHONE
+ m_phoneId = -1;
+#endif
+
+ // Because SetWanderPath is now done async in ReportPhonePutDownCB
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ return false;
+#else
+ return true;
+#endif
+}
+
+void
+CPed::Teleport(CVector pos)
+{
+ CWorld::Remove(this);
+ SetPosition(pos);
+ bIsStanding = false;
+ m_nPedStateTimer = 0;
+ m_actionX = 0.0f;
+ m_actionY = 0.0f;
+ m_pDamageEntity = nil;
+ CWorld::Add(this);
+}
+
+void
+CPed::SetSeekCar(CVehicle *car, uint32 doorNode)
+{
+ if (m_nPedState == PED_SEEK_CAR)
+ return;
+
+#ifdef VC_PED_PORTS
+ if (!CanSetPedState() || m_nPedState == PED_DRIVING)
+ return;
+#endif
+
+ SetStoredState();
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_carInObjective = car;
+ m_carInObjective->RegisterReference((CEntity**) &m_carInObjective);
+ m_pMyVehicle = car;
+ m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
+ // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_vehEnterType = doorNode;
+ m_distanceToCountSeekDone = 0.5f;
+ m_nPedState = PED_SEEK_CAR;
+
}
void
@@ -16006,488 +6826,104 @@ CPed::SeekCar(void)
}
}
-void
-CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
+bool
+CPed::CheckForExplosions(CVector2D &area)
{
- if (m_nPedState == PED_DEAD) {
- if (CGame::nastyGame) {
- if (hitLevel == HITLEVEL_GROUND) {
- CAnimBlendAssociation *floorHitAssoc;
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) {
- floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f);
- } else {
- floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f);
- }
- if (floorHitAssoc) {
- floorHitAssoc->SetCurrentTime(0.0f);
- floorHitAssoc->SetRun();
- floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- }
- }
- if (CGame::nastyGame) {
- CVector headPos = GetNodePosition(PED_HEAD);
- for(int i = 0; i < 4; ++i) {
- CVector bloodDir(0.0f, 0.0f, 0.1f);
- CVector bloodPos = headPos - 0.2f * GetForward();
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);
- }
- }
- }
- } else if (m_nPedState == PED_FALL) {
- if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) {
- CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ?
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) :
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f);
- if (floorHitAssoc) {
- floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- } else if (IsPedInControl()) {
- if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)
- || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {
-#ifndef VC_PED_PORTS
- if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) {
- if (IsPlayer() || CGeneral::GetRandomNumber() & 3) {
-#else
- if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {
- if (IsPlayer() || CGeneral::GetRandomNumber() & 1) {
-#endif
- AnimationId shotAnim;
- switch (direction) {
- case 1:
- shotAnim = ANIM_SHOT_LEFT_PARTIAL;
- break;
- case 2:
- shotAnim = ANIM_SHOT_BACK_PARTIAL;
- break;
- case 3:
- shotAnim = ANIM_SHOT_RIGHT_PARTIAL;
- break;
- default:
- shotAnim = ANIM_SHOT_FRONT_PARTIAL;
- break;
- }
- CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim);
- if (!shotAssoc || shotAssoc->blendDelta < 0.0f)
- shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f);
+ int event = 0;
+ if (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) {
+ area.x = gaEvent[event].posn.x;
+ area.y = gaEvent[event].posn.y;
+ CEntity *actualEntity = nil;
- shotAssoc->SetCurrentTime(0.0f);
- shotAssoc->SetRun();
- shotAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- } else {
- int time = CGeneral::GetRandomNumberInRange(1000, 3000);
- SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);
- }
- } else {
-#ifndef VC_PED_PORTS
- switch (direction) {
- case 1:
- SetFall(500, ANIM_KO_SPIN_R, false);
- break;
- case 2:
- SetFall(500, ANIM_KO_SKID_BACK, false);
- break;
- case 3:
- SetFall(500, ANIM_KO_SPIN_L, false);
- break;
- default:
- SetFall(500, ANIM_KO_SHOT_STOM, false);
- break;
- }
-#else
- bool fall = true;
- AnimationId hitAnim;
- switch (direction) {
- case 1:
- hitAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- if (CGeneral::GetRandomNumber() & 1) {
- fall = false;
- hitAnim = ANIM_HIT_BACK;
- } else {
- hitAnim = ANIM_KO_SKID_BACK;
- }
- break;
- case 3:
- hitAnim = ANIM_KO_SPIN_L;
- break;
- default:
- if (hitLevel == HITLEVEL_LOW) {
- hitAnim = ANIM_KO_SHOT_STOM;
- } else if (CGeneral::GetRandomNumber() & 1) {
- fall = false;
- hitAnim = ANIM_HIT_WALK;
- } else if (CGeneral::GetRandomNumber() & 1) {
- fall = false;
- hitAnim = ANIM_HIT_HEAD;
- } else {
- hitAnim = ANIM_KO_SHOT_FACE;
- }
- break;
- }
- if (fall) {
- SetFall(500, hitAnim, false);
- } else {
- CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim);
- if (!hitAssoc || hitAssoc->blendDelta < 0.0f)
- hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f);
+ switch (gaEvent[event].entityType) {
+ case EVENT_ENTITY_PED:
+ actualEntity = CPools::GetPed(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_VEHICLE:
+ actualEntity = CPools::GetVehicle(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_OBJECT:
+ actualEntity = CPools::GetObject(gaEvent[event].entityRef);
+ break;
+ default:
+ break;
+ }
- hitAssoc->SetCurrentTime(0.0f);
- hitAssoc->SetRun();
- hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- }
-#endif
- }
- Say(SOUND_PED_DEFEND);
- } else {
- Say(SOUND_PED_DEFEND);
- switch (hitLevel) {
- case HITLEVEL_GROUND:
- m_curFightMove = FIGHTMOVE_HITONFLOOR;
- break;
- case HITLEVEL_LOW:
-#ifndef VC_PED_PORTS
- if (direction == 2) {
- SetFall(1000, ANIM_KO_SKID_BACK, false);
- return;
- }
-#else
- if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
- SetFall(1000, ANIM_KO_SKID_BACK, false);
- return;
- } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
- SetFall(1000, ANIM_KO_SHOT_STOM, false);
- return;
- }
-#endif
- m_curFightMove = FIGHTMOVE_HITBODY;
- break;
- case HITLEVEL_HIGH:
- switch (direction) {
- case 1:
- m_curFightMove = FIGHTMOVE_HITLEFT;
- break;
- case 2:
- m_curFightMove = FIGHTMOVE_HITBACK;
- break;
- case 3:
- m_curFightMove = FIGHTMOVE_HITRIGHT;
- break;
- default:
- if (unk <= 5)
- m_curFightMove = FIGHTMOVE_HITHEAD;
- else
- m_curFightMove = FIGHTMOVE_HITBIGSTEP;
- break;
- }
- break;
- default:
- switch (direction) {
- case 1:
- m_curFightMove = FIGHTMOVE_HITLEFT;
- break;
- case 2:
- m_curFightMove = FIGHTMOVE_HITBACK;
- break;
- case 3:
- m_curFightMove = FIGHTMOVE_HITRIGHT;
- break;
- default:
- if (unk <= 5)
- m_curFightMove = FIGHTMOVE_HITCHEST;
- else
- m_curFightMove = FIGHTMOVE_HITBIGSTEP;
- break;
- }
- break;
- }
- if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f))
- m_curFightMove = FIGHTMOVE_HITONFLOOR;
-
- if (m_nPedState == PED_FIGHT) {
- CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
- moveAssoc->SetCurrentTime(0.0f);
- moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
- if (IsPlayer())
- moveAssoc->speed = 1.3f;
-
- m_takeAStepAfterAttack = 0;
- m_fightButtonPressure = 0;
- } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
- CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
- moveAssoc->SetCurrentTime(0.0f);
- moveAssoc->speed = 1.3f;
- } else {
- if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
- SetStoredState();
+ if (actualEntity) {
+ m_pEventEntity = actualEntity;
+ m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
+ bGonnaInvestigateEvent = true;
+ } else
+ bGonnaInvestigateEvent = false;
- if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
- }
- m_nPedState = PED_FIGHT;
- m_fightButtonPressure = 0;
- RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
- CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
- if (walkStartAssoc) {
- walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT;
- walkStartAssoc->blendDelta = -1000.0f;
- }
- CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
- if (!walkStopAssoc)
- walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
- if (walkStopAssoc) {
- walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
- walkStopAssoc->blendDelta = -1000.0f;
- RestoreHeadingRate();
- }
- SetMoveState(PEDMOVE_NONE);
- m_nStoredMoveState = PEDMOVE_NONE;
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
- CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
- moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightState = FIGHTSTATE_NO_MOVE;
- m_takeAStepAfterAttack = false;
- bIsAttacking = true;
- }
- }
+ CEventList::ClearEvent(event);
+ return true;
+ } else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) {
+ area.x = gaEvent[event].posn.x;
+ area.y = gaEvent[event].posn.y;
+ CEventList::ClearEvent(event);
+ bGonnaInvestigateEvent = false;
+ return true;
}
+
+ bGonnaInvestigateEvent = false;
+ return false;
}
-void
-CPed::UpdateFromLeader(void)
+CPed *
+CPed::CheckForGunShots(void)
{
- if (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer)
- return;
-
- if (!m_leader)
- return;
-
- CVector leaderDist;
- if (m_leader->InVehicle())
- leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition();
- else
- leaderDist = m_leader->GetPosition() - GetPosition();
-
- if (leaderDist.Magnitude() > 30.0f) {
- if (IsPedInControl()) {
- SetObjective(OBJECTIVE_NONE);
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
+ int event;
+ if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) {
+ if (gaEvent[event].entityType == EVENT_ENTITY_PED) {
+ // Probably due to we don't want peds to go gunshot area? (same on VC)
+ bGonnaInvestigateEvent = false;
+ return CPools::GetPed(gaEvent[event].entityRef);
}
- SetLeader(nil);
- return;
}
+ bGonnaInvestigateEvent = false;
+ return nil;
+}
- if (IsPedInControl()) {
- if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI)
- WarpPedToNearLeaderOffScreen();
-
- if (m_leader->m_nPedState == PED_DEAD) {
- SetLeader(nil);
- SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
- return;
- }
- if (!m_leader->bInVehicle) {
- if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (bInVehicle) {
- if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR)
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
-
- return;
- }
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- RestorePreviousObjective();
- RestorePreviousState();
- }
- }
- if (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) {
- SetLeader(nil);
- return;
- }
- }
- if (bInVehicle || !m_leader->bInVehicle || m_leader->m_nPedState != PED_DRIVING) {
- if (m_leader->m_objective != OBJECTIVE_NONE && (!m_leader->IsPlayer() || m_leader->m_objective != OBJECTIVE_WAIT_ON_FOOT)
- && m_objective != m_leader->m_objective) {
-
- switch (m_leader->m_objective) {
- case OBJECTIVE_WAIT_ON_FOOT:
- case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_WAIT_IN_CAR:
- case OBJECTIVE_FOLLOW_ROUTE:
- SetObjective(m_leader->m_objective);
- m_objectiveTimer = m_leader->m_objectiveTimer;
- break;
- case OBJECTIVE_GUARD_SPOT:
- SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx);
- m_objectiveTimer = m_leader->m_objectiveTimer;
- break;
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- if (m_leader->m_pedInObjective) {
- SetObjective(m_leader->m_objective, m_leader->m_pedInObjective);
- m_objectiveTimer = m_leader->m_objectiveTimer;
- }
- break;
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- if (m_leader->m_carInObjective) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective);
- return;
- }
- break;
- case OBJECTIVE_GUARD_ATTACK:
- return;
- case OBJECTIVE_HAIL_TAXI:
- m_leader = nil;
- SetObjective(OBJECTIVE_NONE);
- break;
- default:
- SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
- SetObjectiveTimer(0);
- break;
- }
- } else {
- if (m_leader->m_nPedState == PED_ATTACK) {
- CEntity *lookTargetOfLeader = m_leader->m_pLookTarget;
- if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
- && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) {
-
- SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader);
- SetObjectiveTimer(8000);
- SetLookFlag(m_leader->m_pLookTarget, false);
- SetLookTimer(500);
- }
- } else {
- if (IsPedInControl() && m_nPedState != PED_ATTACK) {
-#ifndef VC_PED_PORTS
- SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
- SetObjectiveTimer(0);
-#else
- if (m_leader->m_objective != OBJECTIVE_NONE || m_objective != OBJECTIVE_NONE
- || m_leader->m_nPedState != PED_CHAT || m_nPedState != PED_CHAT) {
-
- SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
- SetObjectiveTimer(0);
- } else {
- SetObjective(OBJECTIVE_NONE);
- }
-#endif
- }
- if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) {
- if (ScanForThreats() && m_threatEntity) {
- m_pLookTarget = m_threatEntity;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {
- m_pPointGunAt = m_threatEntity;
- if (m_threatEntity)
- m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt);
- SetAttack(m_threatEntity);
- }
- }
- }
- }
- }
- } else {
- if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers)
- SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle);
- }
- }
- } else if (bInVehicle) {
- if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {
-
- switch (m_leader->m_objective) {
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- if (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective)
- break;
-
- // fall through
- default:
- if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) {
-#ifdef VC_PED_PORTS
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;
-#endif
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- }
-
- break;
- }
+CPed *
+CPed::CheckForDeadPeds(void)
+{
+ int event;
+ if (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) {
+ int pedHandle = gaEvent[event].entityRef;
+ if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) {
+ bGonnaInvestigateEvent = true;
+ return CPools::GetPed(pedHandle);
}
}
+ bGonnaInvestigateEvent = false;
+ return nil;
}
-void
-CPed::UpdatePosition(void)
+bool
+CPed::IsPlayer(void) const
{
- if (CReplay::IsPlayingBack() || !bIsStanding)
- return;
-
- CVector2D velocityChange;
-
- SetHeading(m_fRotationCur);
- if (m_pCurrentPhysSurface) {
- CVector2D velocityOfSurface;
- CPhysical *curSurface = m_pCurrentPhysSurface;
- if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
-
- // It seems R* didn't like m_vecOffsetFromPhysSurface for boats
- CVector offsetToSurface = GetPosition() - curSurface->GetPosition();
- offsetToSurface.z -= FEET_OFFSET;
-
- CVector surfaceMoveVelocity = curSurface->m_vecMoveSpeed;
- CVector surfaceTurnVelocity = CrossProduct(curSurface->m_vecTurnSpeed, offsetToSurface);
+ return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 ||
+ m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4;
+}
- // Also we use that weird formula instead of friction if it's boat
- float slideMult = -curSurface->m_vecTurnSpeed.MagnitudeSqr();
- velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);
- m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);
- } else {
- velocityOfSurface = curSurface->GetSpeed(m_vecOffsetFromPhysSurface);
- }
- // Reminder: m_moved is displacement from walking/running.
- velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;
- m_fRotationCur += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
- m_fRotationDest += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
- } else if (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) {
- velocityChange = m_moved - m_vecMoveSpeed;
- } else {
- // Ped got damaged by steep slope
- m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
- // some kind of
- CVector2D reactionForce = m_vecDamageNormal * (1.0f / m_vecDamageNormal.Magnitude2D());
+bool
+CPed::IsGangMember(void) const
+{
+ return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9;
+}
- velocityChange = 0.02f * reactionForce + m_moved;
+bool
+CPed::IsPointerValid(void)
+{
+ int pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8;
+ if (pedIndex < 0 || pedIndex >= NUMPEDS)
+ return false;
- float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);
- // they're in same direction
- if (reactionAndVelocityDotProd < 0.0f) {
- velocityChange -= reactionAndVelocityDotProd * reactionForce;
- }
- }
-
- // Take time step into account
- if (m_pCurrentPhysSurface) {
- float speedChange = velocityChange.Magnitude();
- float changeMult = speedChange;
- if (m_nPedState != PED_DIE || !m_pCurrentPhysSurface->IsVehicle()) {
- if (!m_pCurrentPhysSurface->IsVehicle() || !((CVehicle*)m_pCurrentPhysSurface)->IsBoat())
- changeMult = 0.01f * CTimer::GetTimeStep();
- } else {
- changeMult = 0.002f * CTimer::GetTimeStep();
- }
+ if (m_entryInfoList.first || FindPlayerPed() == this)
+ return true;
- if (speedChange > changeMult) {
- velocityChange = velocityChange * (changeMult / speedChange);
- }
- }
- m_vecMoveSpeed.x += velocityChange.x;
- m_vecMoveSpeed.y += velocityChange.y;
+ return false;
}
void
@@ -16551,7 +6987,7 @@ CPed::SetPedPositionInCar(void)
tempMat.RotateZ(-HALFPI);
newMat = newMat * tempMat;
} else if (m_pMyVehicle->pPassengers[2] == this) {
- m_fRotationCur = HALFPI + m_pMyVehicle->GetForward().Heading();
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading() + HALFPI;
tempMat.SetTranslate(0.0f, 0.0f, 0.0f);
tempMat.RotateZ(HALFPI);
newMat = newMat * tempMat;
@@ -16564,879 +7000,1469 @@ CPed::SetPedPositionInCar(void)
GetMatrix() = newMat;
}
-static RwObject*
-CloneAtomicToFrameCB(RwObject *frame, void *data)
-{
- RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);
- RpAtomicSetFrame(newAtomic, (RwFrame*)data);
- RpClumpAddAtomic(flyingClumpTemp, newAtomic);
- CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);
- return frame;
-}
-
-static RwFrame*
-RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)
-{
- RwFrame *newFrame = RwFrameCreate();
- RwFrameAddChild((RwFrame*)data, newFrame);
- RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);
- RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);
- RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);
- return newFrame;
-}
-
-CObject*
-CPed::SpawnFlyingComponent(int pedNode, int8 direction)
+void
+CPed::LookForSexyPeds(void)
{
- if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
- return nil;
-
-#ifdef PED_SKIN
- assert(!IsClumpSkinned(GetClump()));
-#endif
-
- CObject *obj = new CObject();
- if (!obj)
- return nil;
-
- RwFrame *frame = RwFrameCreate();
- RpClump *clump = RpClumpCreate();
- RpClumpSetFrame(clump, frame);
- RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame);
- *RwFrameGetMatrix(frame) = *matrix;
-
- flyingClumpTemp = clump;
- RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame);
- RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame);
- flyingClumpTemp = nil;
- switch (pedNode) {
- case PED_HEAD:
- // So popping head would have wheel collision. They disabled it anyway
- obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
- break;
- case PED_UPPERARML:
- case PED_UPPERARMR:
- obj->SetModelIndexNoCreate(MI_BODYPARTB);
- obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
- break;
- case PED_UPPERLEGL:
- case PED_UPPERLEGR:
- obj->SetModelIndexNoCreate(MI_BODYPARTA);
- obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
- break;
- default:
- break;
- }
- obj->RefModelInfo(GetModelIndex());
- obj->AttachToRwObject((RwObject*)clump);
- obj->m_fMass = 15.0f;
- obj->m_fTurnMass = 5.0f;
- obj->m_fAirResistance = 0.99f;
- obj->m_fElasticity = 0.03f;
- obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
- obj->ObjectCreatedBy = TEMP_OBJECT;
- obj->SetIsStatic(false);
- obj->bIsPickup = false;
- obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX;
-
- // life time - the more objects the are, the shorter this one will live
- CObject::nNoTempObjects++;
- if (CObject::nNoTempObjects > 20)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
- else if (CObject::nNoTempObjects > 10)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
- else
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
+ if ((!IsPedInControl() && m_nPedState != PED_DRIVING)
+ || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE)
+ return;
- CVector localForcePos, forceDir;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if (CanSeeEntity(m_nearPeds[i])) {
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {
+ CPed *nearPed = m_nearPeds[i];
+ if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)
+ && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {
- if (direction == 2) {
- obj->m_vecMoveSpeed = 0.03f * GetForward();
- obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
- obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- localForcePos = CVector(0.0f, 0.0f, 0.0f);
- forceDir = GetForward();
- } else {
- obj->m_vecMoveSpeed = -0.03f * GetForward();
- obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
- obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- localForcePos = CVector(0.0f, 0.0f, 0.0f);
- forceDir = -GetForward();
+ SetLookFlag(nearPed, true);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
+ Say(SOUND_PED_CHAT_SEXY);
+ return;
+ }
+ }
+ }
}
- obj->ApplyTurnForce(forceDir, localForcePos);
- CWorld::Add(obj);
-
- return obj;
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
}
void
-CPed::WarpPedIntoCar(CVehicle *car)
+CPed::LookForSexyCars(void)
{
- bInVehicle = true;
- m_pMyVehicle = car;
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_carInObjective = car;
- m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
- m_nPedState = PED_DRIVING;
- bUsesCollision = false;
- bIsInTheAir = false;
- bVehExitWillBeInstant = true;
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- car->SetDriver(this);
- car->pDriver->RegisterReference((CEntity **) &car->pDriver);
+ CEntity *vehicles[8];
+ CVehicle *veh;
+ int foundVehId = 0;
+ int bestPriceYet = 0;
+ int16 lastVehicle;
- } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- for (int i = 0; i < 4; i++) {
- if (!car->pPassengers[i]) {
- car->pPassengers[i] = this;
- car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]);
- break;
+ if (!IsPedInControl() && m_nPedState != PED_DRIVING)
+ return;
+
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ for (int vehId = 0; vehId < lastVehicle; vehId++) {
+ veh = (CVehicle*)vehicles[vehId];
+ if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) {
+ foundVehId = vehId;
+ bestPriceYet = veh->pHandling->nMonetaryValue;
}
}
- } else
- return;
+ if (lastVehicle > 0 && bestPriceYet > 40000)
+ SetLookFlag(vehicles[foundVehId], false);
- if (IsPlayer()) {
- car->SetStatus(STATUS_PLAYER);
- AudioManager.PlayerJustGotInCar();
- CCarCtrl::RegisterVehicleOfInterest(car);
- } else {
- car->SetStatus(STATUS_PHYSICS);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
}
+}
- CWorld::Remove(this);
- SetPosition(car->GetPosition());
- CWorld::Add(this);
+bool
+CPed::LookForInterestingNodes(void)
+{
+ CBaseModelInfo *model;
+ CPtrNode *ptrNode;
+ CVector effectDist;
+ C2dEffect *effect;
+ CMatrix *objMat;
- if (car->bIsAmbulanceOnDuty) {
- car->bIsAmbulanceOnDuty = false;
- --CCarCtrl::NumAmbulancesOnDuty;
- }
- if (car->bIsFireTruckOnDuty) {
- car->bIsFireTruckOnDuty = false;
- --CCarCtrl::NumFiretrucksOnDuty;
- }
- if (!car->bEngineOn) {
- car->bEngineOn = true;
- DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
+ if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) {
+ return false;
}
+ bool found = false;
+ uint8 randVal = CGeneral::GetRandomNumber() % 256;
-#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);
- RemoveWeaponWhenEnteringVehicle();
+ int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST);
+ if (minX < 0) minX = 0;
+ int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST);
+ if (minY < 0) minY = 0;
+ int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST);
+#ifdef FIX_BUGS
+ if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
- if (car->IsBoat()) {
-#ifndef FIX_BUGS
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+ if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
+#endif
+
+ int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST);
+#ifdef FIX_BUGS
+ if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+ if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
#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);
+ for (int curY = minY; curY <= maxY && !found; curY++) {
+ for (int curX = minX; curX <= maxX && !found; curX++) {
+ CSector *sector = CWorld::GetSector(curX, curY);
+
+ for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CVehicle *veh = (CVehicle*)ptrNode->item;
+ model = veh->GetModelInfo();
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &veh->GetMatrix();
+ CVector effectPos = veh->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CObject *obj = (CObject*)ptrNode->item;
+ model = CModelInfo::GetModelInfo(obj->GetModelIndex());
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &obj->GetMatrix();
+ CVector effectPos = obj->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CBuilding *building = (CBuilding*)ptrNode->item;
+ model = CModelInfo::GetModelInfo(building->GetModelIndex());
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &building->GetMatrix();
+ CVector effectPos = building->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CBuilding *building = (CBuilding*)ptrNode->item;
+ model = CModelInfo::GetModelInfo(building->GetModelIndex());
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &building->GetMatrix();
+ CVector effectPos = building->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
-#endif
- StopNonPartialAnims();
- if (car->bIsBus)
- bRenderPedInCar = false;
+ if (!found)
+ return false;
- bChangedSeat = true;
+ CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir);
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f);
+ randVal = CGeneral::GetRandomNumber() % 256;
+ if (randVal <= m_randomSeed % 256) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ SetLookFlag(angleToFace, true);
+ SetLookTimer(1000);
+ return false;
+ }
+
+ CVector2D effectPos = *objMat * effect->pos;
+ switch (effect->attractor.type) {
+ case ATTRACTORTYPE_ICECREAM:
+ SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace);
+ break;
+ case ATTRACTORTYPE_STARE:
+ SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f,
+ CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500),
+ angleToFace);
+ break;
+ default:
+ return true;
+ }
+ return true;
}
void
-CPed::SetObjective(eObjective newObj, CVector dest)
+CPed::SetWaitState(eWaitState state, void *time)
{
- if (DyingOrDead())
- return;
+ AnimationId waitAnim = NUM_ANIMS;
+ CAnimBlendAssociation *animAssoc;
- if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ if (!IsPedInControl())
return;
- SetObjectiveTimer(0);
- if (m_objective == newObj) {
- if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
- if (m_nextRoutePointPos == dest)
- return;
- } else if (newObj == OBJECTIVE_GUARD_SPOT) {
- if (m_vecSeekPosEx == dest)
- return;
- }
- }
+ if (state != m_nWaitState)
+ FinishedWaitCB(nil, this);
-#ifdef VC_PED_PORTS
- ClearPointGunAt();
-#endif
- bObjectiveCompleted = false;
- switch (newObj) {
- case OBJECTIVE_GUARD_SPOT:
- m_vecSeekPosEx = dest;
- m_distanceToCountSeekDoneEx = 5.0f;
+ switch (state) {
+ case WAITSTATE_TRAFFIC_LIGHTS:
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
SetMoveState(PEDMOVE_STILL);
break;
- case OBJECTIVE_GUARD_AREA:
- case OBJECTIVE_WAIT_IN_CAR:
- case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
- case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
- case OBJECTIVE_LEAVE_CAR:
- case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- case OBJECTIVE_FOLLOW_CAR_IN_CAR:
- case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
- case OBJECTIVE_DESTROY_OBJECT:
- case OBJECTIVE_DESTROY_CAR:
+ case WAITSTATE_CROSS_ROAD:
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
break;
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- 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;
+ case WAITSTATE_CROSS_ROAD_LOOK:
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 8.0f);
+
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000);
+
break;
- case OBJECTIVE_RUN_TO_AREA:
- bIsRunning = true;
- 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;
+ case WAITSTATE_LOOK_PED:
+ case WAITSTATE_LOOK_SHOP:
+ case WAITSTATE_LOOK_ACCIDENT:
+ case WAITSTATE_FACEOFF_GANG:
break;
- default: break;
- }
+ case WAITSTATE_DOUBLEBACK:
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+ break;
+ case WAITSTATE_HITWALL:
+ m_headingRate = 2.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 16.0f);
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ animAssoc->SetDeleteCallback(FinishedWaitCB, this);
- if (IsTemporaryObjective(m_objective)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj)
- SetStoredObjective();
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
+ ClearObjective();
+ RestorePreviousState();
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ }
+ break;
+ case WAITSTATE_TURN180:
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TURN_180, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ animAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);
+ break;
+ case WAITSTATE_SURPRISE:
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ break;
+ case WAITSTATE_STUCK:
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
+ ClearObjective();
+ RestorePreviousState();
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ }
+ break;
+ case WAITSTATE_LOOK_ABOUT:
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+
+ break;
+ case WAITSTATE_PLAYANIM_COWER:
+ waitAnim = ANIM_HANDSCOWER;
+ case WAITSTATE_PLAYANIM_HANDSUP:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_HANDSUP;
+ case WAITSTATE_PLAYANIM_HANDSCOWER:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_HANDSCOWER;
+ m_headingRate = 0.0f;
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
- m_objective = newObj;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
+ animAssoc->SetDeleteCallback(FinishedWaitCB, this);
+ break;
+ case WAITSTATE_PLAYANIM_DUCK:
+ waitAnim = ANIM_DUCK_DOWN;
+ case WAITSTATE_PLAYANIM_TAXI:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_IDLE_TAXI;
+ case WAITSTATE_PLAYANIM_CHAT:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_IDLE_CHAT;
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
+
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
+ animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->SetDeleteCallback(FinishedWaitCB, this);
+ break;
+ case WAITSTATE_FINISH_FLEE:
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+ break;
+ default:
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ return;
}
+ m_nWaitState = state;
}
void
-CPed::SetMoveAnim(void)
+CPed::Wait(void)
{
- if (m_nStoredMoveState == m_nMoveState || !IsPedInControl())
- return;
+ AnimationId mustHaveAnim = NUM_ANIMS;
+ CAnimBlendAssociation *animAssoc;
+ CPed *pedWeLook;
- if (m_nMoveState == PEDMOVE_NONE) {
- m_nStoredMoveState = PEDMOVE_NONE;
+ if (DyingOrDead()) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
return;
}
- AssocGroupId animGroupToUse;
- if (m_leader && m_leader->IsPlayer())
- animGroupToUse = ASSOCGRP_PLAYER;
- else
- animGroupToUse = m_animGroup;
+ switch (m_nWaitState) {
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK);
- if (!animAssoc) {
- CAnimBlendAssociation *fightIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
- animAssoc = fightIdleAssoc;
- if (fightIdleAssoc && m_nPedState == PED_FIGHT)
- return;
+ case WAITSTATE_TRAFFIC_LIGHTS:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
+ }
+ }
+ break;
- if (fightIdleAssoc) {
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 8.0f);
+ case WAITSTATE_CROSS_ROAD:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
+ m_nWaitState = WAITSTATE_FALSE;
+ else
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
}
- }
- }
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (animAssoc)
- if (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE)
- return;
+ break;
- if (animAssoc) {
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
+ case WAITSTATE_CROSS_ROAD_LOOK:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ m_nWaitState = WAITSTATE_FALSE;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
}
- }
- }
- if (!animAssoc) {
- m_nStoredMoveState = m_nMoveState;
- if (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) {
- for (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);
- assoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) {
+ break;
- if (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) {
- assoc->blendDelta = -2.0f;
- assoc->flags |= ASSOC_DELETEFADEDOUT;
+ case WAITSTATE_DOUBLEBACK:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ uint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds();
+ if (timeLeft < 2500 && timeLeft > 2000) {
+ m_nWaitTimer -= 500;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
}
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
}
+ break;
- ClearAimFlag();
- ClearLookFlag();
- }
+ case WAITSTATE_HITWALL:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
+ m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ }
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ }
+ break;
- switch (m_nMoveState) {
- case PEDMOVE_STILL:
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
- break;
- case PEDMOVE_WALK:
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_WALK, 1.0f);
- break;
- case PEDMOVE_RUN:
- if (m_nPedState == PED_FLEE_ENTITY) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 3.0f);
+ case WAITSTATE_TURN180:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
+ m_fRotationCur = m_fRotationCur + PI;
+ if (m_nPedState == PED_INVESTIGATE)
+ ClearInvestigateEvent();
+ }
+
+ if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
+ m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ }
+ break;
+
+ case WAITSTATE_SURPRISE:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HIT_WALL)) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
} else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 1.0f);
+ m_nWaitState = WAITSTATE_FALSE;
}
+ }
+ break;
+
+ case WAITSTATE_STUCK:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer)
break;
- case PEDMOVE_SPRINT:
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_SPRINT, 1.0f);
- break;
- default:
- break;
- }
- if (animAssoc) {
- if (m_leader) {
- CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_WALK);
- if (!walkAssoc)
- walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_RUN);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (!walkAssoc)
- walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_SPRINT);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_TURN_180);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
- if (walkAssoc) {
- animAssoc->speed = walkAssoc->speed;
+ if (animAssoc) {
+ if (animAssoc->IsPartial()) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
} else {
- if (CharCreatedBy == MISSION_CHAR)
- animAssoc->speed = 1.0f;
- else
- animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
-
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ }
+
+ if (animAssoc->animId == ANIM_TURN_180) {
+ m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
+ m_nStoredMoveState = PEDMOVE_NONE;
+ m_panicCounter = 0;
+ return;
}
- } else {
- if (CharCreatedBy == MISSION_CHAR)
- animAssoc->speed = 1.0f;
- else
- animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
}
- }
- }
-}
-void
-CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
-{
- float zDiff = 0.0f;
- RemoveWeaponWhenEnteringVehicle();
- car->m_nGettingInFlags |= doorFlag;
- bVehEnterDoorIsBlocked = false;
- if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)
- SetStoredState();
+ AnimationId animToPlay;
- m_pSeekTarget = car;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- m_vehEnterType = doorNode;
- m_nPedState = PED_ENTER_CAR;
- if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) {
- car->bIsBeingCarJacked = true;
- }
+ switch (CGeneral::GetRandomNumber() & 3) {
+ case 0:
+ animToPlay = ANIM_ROAD_CROSS;
+ break;
+ case 1:
+ animToPlay = ANIM_IDLE_TIRED;
+ break;
+ case 2:
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ break;
+ case 3:
+ animToPlay = ANIM_TURN_180;
+ break;
+ default:
+ break;
+ }
- m_pMyVehicle = (CVehicle*)m_pSeekTarget;
- m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
- ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
- bUsesCollision = false;
- CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- // Because buses have stairs
- if (!m_pMyVehicle->bIsBus)
- zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z);
+ if (animToPlay == ANIM_TURN_180)
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
- m_vecOffsetSeek = doorOpenPos - GetPosition();
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
- if (car->IsBoat()) {
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000);
+ break;
+
+ case WAITSTATE_LOOK_ABOUT:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ m_nWaitState = WAITSTATE_FALSE;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ break;
+
+ case WAITSTATE_PLAYANIM_HANDSUP:
+ mustHaveAnim = ANIM_HANDSUP;
+
+ case WAITSTATE_PLAYANIM_HANDSCOWER:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_HANDSCOWER;
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
+ pedWeLook = (CPed*) m_pLookTarget;
+
+ if ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt)
+ && m_nPedState != PED_FLEE_ENTITY
+ && m_nPedState != PED_ATTACK
+ && CTimer::GetTimeInMilliseconds() <= m_nWaitTimer
+ && animAssoc) {
+
+ TurnBody();
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ m_nWaitTimer = 0;
+ if (m_pLookTarget && m_pLookTarget->IsPed()) {
+
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) {
+
+ if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) {
+
+ if (GetWeapon()->IsTypeMelee()) {
#ifdef VC_PED_PORTS
- // VC checks for handling flag, but we can't do that
- if(car->GetModelIndex() == MI_SPEEDER)
- 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);
+ if(m_pedStats->m_flags & STAT_GUN_PANIC) {
+#endif
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
+ if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) {
- PedSetInCarCB(nil, this);
- bVehExitWillBeInstant = true;
-#else
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ }
+ if (m_nMoveState != PEDMOVE_RUN)
+ SetMoveState(PEDMOVE_WALK);
-#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);
+ if (m_nPedType != PEDTYPE_COP) {
+ ProcessObjective();
+ SetMoveState(PEDMOVE_WALK);
+ }
+#ifdef VC_PED_PORTS
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ }
#endif
+ } else {
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget);
+ SetObjectiveTimer(20000);
+ }
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
+ if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS)
+ {
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ }
+ SetMoveState(PEDMOVE_RUN);
+ Say(SOUND_PED_FLEE_RUN);
+ }
+ }
+ }
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
+ if (animAssoc) {
+ animAssoc->blendDelta = -4.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ break;
+ case WAITSTATE_PLAYANIM_COWER:
+ mustHaveAnim = ANIM_HANDSCOWER;
- m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
+ case WAITSTATE_PLAYANIM_DUCK:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_DUCK_DOWN;
+
+ case WAITSTATE_PLAYANIM_TAXI:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_IDLE_TAXI;
+
+ case WAITSTATE_PLAYANIM_CHAT:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_IDLE_CHAT;
+
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
+ if (animAssoc) {
+ animAssoc->blendDelta = -4.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ m_nWaitState = WAITSTATE_FALSE;
+ }
+#ifdef VC_PED_PORTS
+ else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
+ if (m_pedInObjective) {
+ if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {
+
+ // VC also calls CleanUpOldReference here for old LookTarget.
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ }
+ }
#endif
- if (IsPlayer())
- CWaterLevel::AllocateBoatWakeArray();
- } else {
- if (zDiff > 4.4f) {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
+ break;
- } else {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
- }
- m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
- car->AutoPilot.m_nCruiseSpeed = 0;
+ case WAITSTATE_FINISH_FLEE:
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
+ if (animAssoc) {
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ int timer = 2000;
+ m_nWaitState = WAITSTATE_FALSE;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
+ }
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ }
+ break;
+ default:
+ break;
}
+
+ if(!m_nWaitState)
+ RestoreHeadingRate();
}
void
-CPed::WanderPath(void)
+CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- if (!m_pNextPathNode) {
- printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n");
- SetIdle();
+ CPed *ped = (CPed*)arg;
+
+ ped->m_nWaitTimer = 0;
+ ped->RestoreHeadingRate();
+ ped->Wait();
+}
+
+void
+CPed::RestoreHeadingRate(void)
+{
+ m_headingRate = m_pedStats->m_headingChangeRate;
+}
+
+void
+CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg)
+{
+ ((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate;
+}
+
+void
+CPed::FlagToDestroyWhenNextProcessed(void)
+{
+ bRemoveFromWorld = true;
+ if (!InVehicle())
return;
+ if (m_pMyVehicle->pDriver == this){
+ m_pMyVehicle->pDriver = nil;
+ if (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED)
+ m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ }else{
+ m_pMyVehicle->RemovePassenger(this);
}
- if (m_nWaitState == WAITSTATE_FALSE) {
- if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
- SetMoveState(PEDMOVE_WALK);
- }
- m_vecSeekPos = m_pNextPathNode->GetPosition();
- m_vecSeekPos.z += 1.0f;
+ bInVehicle = false;
+ m_pMyVehicle = nil;
+ if (CharCreatedBy == MISSION_CHAR)
+ m_nPedState = PED_DEAD;
+ else
+ m_nPedState = PED_NONE;
+ m_pVehicleAnim = nil;
+}
- // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
- if (!Seek())
+void
+CPed::SetSolicit(uint32 time)
+{
+ if (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective)
return;
- CPathNode *previousLastNode = m_pLastPathNode;
- uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;
+ if (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0
+ && CTimer::GetTimeInMilliseconds() < m_objectiveTimer) {
+ if (m_vehEnterType == CAR_DOOR_LF) {
+ m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
+ } else {
+ m_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI;
+ }
- // We don't prefer 180-degree turns in normal situations
- uint8 dirWeWouldntPrefer = m_nPathDir;
- if (dirWeWouldntPrefer <= 3)
- dirWeWouldntPrefer += 4;
- else
- dirWeWouldntPrefer -= 4;
+ if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
- CPathNode *nodeWeWouldntPrefer = nil;
- uint8 dirToSet = 9; // means undefined
- uint8 dirWeWouldntPrefer2 = 9; // means undefined
- if (randVal <= 90) {
- if (randVal > 80) {
- m_nPathDir += 2;
- m_nPathDir %= 8;
+ if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f);
+
+ m_nPedState = PED_SOLICIT;
}
- } else {
- m_nPathDir -= 2;
- if (m_nPathDir < 0)
- m_nPathDir += 8;
}
+}
- m_pLastPathNode = m_pNextPathNode;
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &dirToSet);
-
- uint8 tryCount = 0;
+void
+CPed::Solicit(void)
+{
+ if (m_standardTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) {
+ CVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType, 0.0f);
+ SetMoveState(PEDMOVE_STILL);
- // NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7
- while (!m_pNextPathNode) {
- tryCount++;
- m_nPathDir = (m_nPathDir + 1) % 8;
+ // Game uses GetAngleBetweenPoints and converts it to radian
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ doorPos.x, doorPos.y,
+ GetPosition().x, GetPosition().y);
- // We're at where we started and couldn't find any node
- if (tryCount > 7) {
- if (!nodeWeWouldntPrefer) {
- ClearAll();
- SetIdle();
- // Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.
- Error("Can't find valid path node, SetWanderPath, Ped.cpp");
- return;
- }
- m_pNextPathNode = nodeWeWouldntPrefer;
- dirToSet = dirWeWouldntPrefer2;
- } else {
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &dirToSet);
- if (m_pNextPathNode) {
- if (dirToSet == dirWeWouldntPrefer) {
- nodeWeWouldntPrefer = m_pNextPathNode;
- dirWeWouldntPrefer2 = dirToSet;
- m_pNextPathNode = nil;
- }
- }
+ if (m_fRotationDest < 0.0f) {
+ m_fRotationDest = m_fRotationDest + TWOPI;
+ } else if (m_fRotationDest > TWOPI) {
+ m_fRotationDest = m_fRotationDest - TWOPI;
}
- }
- m_nPathDir = dirToSet;
- if (m_pLastPathNode == m_pNextPathNode) {
- m_pNextPathNode = previousLastNode;
- SetWaitState(WAITSTATE_DOUBLEBACK, nil);
- Say(SOUND_PED_WAIT_DOUBLEBACK);
- } else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) {
- SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil);
- } else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) {
- SetWaitState(WAITSTATE_CROSS_ROAD, nil);
- } else if (m_pNextPathNode == previousLastNode) {
- SetWaitState(WAITSTATE_DOUBLEBACK, nil);
- Say(SOUND_PED_WAIT_DOUBLEBACK);
+ if ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f)
+ return;
+ CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_HOOKERTALK);
+ if (talkAssoc) {
+ talkAssoc->blendDelta = -1000.0f;
+ talkAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ RestorePreviousState();
+ RestorePreviousObjective();
+ SetObjectiveTimer(10000);
+ } else if (!m_carInObjective) {
+ RestorePreviousState();
+ RestorePreviousObjective();
+ SetObjectiveTimer(10000);
+ } else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) {
+ m_carInObjective = nil;
+ } else {
+ m_pVehicleAnim = nil;
+ SetLeader(m_carInObjective->pDriver);
}
}
-bool
-CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo)
+void
+CPed::SetBuyIceCream(void)
{
- bool teleported = false;
- if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
- return false;
+ if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl())
+ return;
+
+ if (!m_carInObjective)
+ return;
- CVector warpToPos = warpTo->GetPosition();
- CVector distVec = warpToPos - GetPosition();
- float halfOfDist = distVec.Magnitude() * 0.5f;
- CVector halfNormalizedDist = distVec / halfOfDist;
+#ifdef FIX_ICECREAM
- CVector appropriatePos = GetPosition();
- CVector zCorrectedPos = appropriatePos;
- int tryCount = Min(10, halfOfDist);
- for (int i = 0; i < tryCount; ++i) {
- appropriatePos += halfNormalizedDist;
- CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+ // Simulating BuyIceCream
+ CPed* driver = m_carInObjective->pDriver;
+ if (driver) {
+ m_nPedState = PED_BUY_ICECREAM;
+ bFindNewNodeAfterStateRestore = true;
+ SetObjectiveTimer(8000);
+ SetChat(driver, 8000);
+ driver->SetChat(this, 8000);
+ return;
+ }
+#endif
- if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
- continue;
+ // Side of the Ice Cream van
+ m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
- appropriatePos.z = zCorrectedPos.z;
- if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
- && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
- && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
- teleported = true;
- Teleport(appropriatePos);
- }
+ if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ m_nPedState = PED_BUY_ICECREAM;
}
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
- return teleported;
}
bool
-CPed::WarpPedToNearLeaderOffScreen(void)
+CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh)
{
- bool teleported = false;
- if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
- return false;
+ bool foundIt = false;
- CVector warpToPos = m_leader->GetPosition();
- CVector distVec = warpToPos - GetPosition();
- float halfOfDist = distVec.Magnitude() * 0.5f;
- CVector halfNormalizedDist = distVec / halfOfDist;
+ CVector helperPos = GetPosition();
+ helperPos.z = pos->z - 0.5f;
- CVector appropriatePos = GetPosition();
- CVector zCorrectedPos = appropriatePos;
- int tryCount = Min(10, halfOfDist);
- for (int i = 0; i < tryCount; ++i) {
- appropriatePos += halfNormalizedDist;
- CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+ CVector foundPos = *pos;
+ foundPos.z -= 0.5f;
- if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
- continue;
+ // If there is another car between target car and us.
+ if (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) {
+
+ CColModel *vehCol = veh->GetModelInfo()->GetColModel();
+ CVector *colMin = &vehCol->boundingBox.min;
+ CVector *colMax = &vehCol->boundingBox.max;
+
+ CVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f);
+ CVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f);
+ CVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f);
+ CVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f);
+
+ leftRearPos = veh->GetMatrix() * leftRearPos;
+ rightRearPos = veh->GetMatrix() * rightRearPos;
+ leftFrontPos = veh->GetMatrix() * leftFrontPos;
+ rightFrontPos = veh->GetMatrix() * rightFrontPos;
+
+ // Makes helperPos veh-ped distance vector.
+ helperPos -= veh->GetPosition();
- appropriatePos.z = zCorrectedPos.z;
- if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
- && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
- && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
- teleported = true;
- Teleport(appropriatePos);
+ // ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour.
+ // On every run it returns another pos. for ped, with same distance to the veh.
+ // Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't)
+ helperPos = veh->GetMatrix() * helperPos;
+
+ float vehForwardHeading = veh->GetForward().Heading();
+
+ // I'm absolutely not sure about these namings.
+ // NTVF = needed turn if we're looking to vehicle front and wanna look to...
+
+ float potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y);
+ float NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading);
+
+ float potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y);
+ float NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading);
+
+ float potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y);
+ float NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading);
+
+ float potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y);
+ float NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading);
+
+ bool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI;
+
+ bool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI;
+
+ bool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI;
+
+ bool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI;
+
+ // Only order of conditions are different among enterTypes.
+ if (m_vehEnterType == CAR_DOOR_RR) {
+ if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ } else if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ } else if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ } else if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ }
+ } else if(m_vehEnterType == CAR_DOOR_RF) {
+ if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ } else if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ } else if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ } else if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LF) {
+ if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ } else if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ } else if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ } else if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LR) {
+ if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ } else if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ } else if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ } else if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ }
}
}
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
- return teleported;
+ if (!foundIt)
+ return false;
+
+ helperPos = GetPosition() - foundPos;
+ helperPos.z = 0.0f;
+ if (helperPos.MagnitudeSqr() <= sq(0.5f))
+ return false;
+
+ pos->x = foundPos.x;
+ pos->y = foundPos.y;
+ return true;
}
void
-CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+CPed::SetLeader(CEntity *leader)
{
- RemoveWeaponWhenEnteringVehicle();
- if (m_nPedState != PED_SEEK_CAR)
- SetStoredState();
+ m_leader = (CPed*)leader;
- m_pSeekTarget = car;
- m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
- m_nPedState = PED_CARJACK;
- car->bIsBeingCarJacked = true;
- m_pMyVehicle = (CVehicle*)m_pSeekTarget;
- m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);
- ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
-
- Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING);
- CVector carEnterPos;
- carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
-
- car->m_nGettingInFlags |= doorFlag;
- m_vecOffsetSeek = carEnterPos - GetPosition();
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
- float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z);
- bUsesCollision = false;
+ if(m_leader)
+ m_leader->RegisterReference((CEntity **)&m_leader);
+}
- if (zDiff > 4.4f) {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
+#ifdef VC_PED_PORTS
+bool
+CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal)
+{
+ if (m_nSurfaceTouched == SURFACE_WATER)
+ return true;
+ CVector pos = GetPosition();
+ CVector forwardOffset = GetForward();
+ if (damageNormal && damageNormal->z > 0.17f) {
+ if (damageNormal->z > 0.9f)
+ return false;
+
+ CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
+ pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z;
+ pos.z = pos.z + 0.05f;
+ float collPower = damageNormal->Magnitude2D();
+ if (damageNormal->z > 0.5f) {
+ CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f);
+ invDamageNormal *= 1.0f / collPower;
+ CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius;
+ forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f);
+ } else {
+ forwardOffset += collPower * ourCol->spheres->radius * forwardOffset;
+ }
} else {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
+ pos.z -= 0.15f;
}
- m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+ CVector forwardPos = pos + forwardOffset;
+ return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
}
+#else
+bool
+CPed::CanPedJumpThis(CEntity *unused)
+{
+ CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
+ CVector pos = GetPosition();
+ CVector forwardPos(
+ forward.x + pos.x,
+ forward.y + pos.y,
+ pos.z);
+
+ return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
+}
+#endif
void
-CPed::SetObjective(eObjective newObj, CVector dest, float safeDist)
+CPed::SetJump(void)
{
- if (DyingOrDead())
+ if (!bInVehicle &&
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) &&
+#endif
+ (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) {
+ SetStoredState();
+ m_nPedState = PED_JUMP;
+ CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f);
+ jumpAssoc->SetFinishCallback(FinishLaunchCB, this);
+ m_fRotationDest = m_fRotationCur;
+ }
+}
+
+void
+CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (ped->m_nPedState != PED_JUMP)
return;
- if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ CVector forward(0.15f * ped->GetForward() + ped->GetPosition());
+ forward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres->center.z + 0.25f;
+
+ CEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
+ if (!obstacle) {
+ // Forward of forward
+ forward += 0.15f * ped->GetForward();
+ forward.z += 0.15f;
+ obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
+ }
+
+ 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);
+ handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped);
+ ped->bIsLanding = true;
return;
+ }
- SetObjectiveTimer(0);
- if (m_objective == newObj) {
- if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
- if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist)
- return;
- } else if (newObj == OBJECTIVE_GUARD_SPOT) {
- if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist)
- return;
+ float velocityFromAnim = 0.1f;
+ CAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_SPRINT);
+
+ if (sprintAssoc) {
+ velocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f;
+ } else {
+ CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_RUN);
+ if (runAssoc) {
+ velocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f;
}
}
+ if (ped->IsPlayer()
#ifdef VC_PED_PORTS
- ClearPointGunAt();
+ || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer()
#endif
- bObjectiveCompleted = false;
- if (IsTemporaryObjective(m_objective)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj)
- SetStoredObjective();
+ )
+ ped->ApplyMoveForce(0.0f, 0.0f, 8.5f);
+ else
+ ped->ApplyMoveForce(0.0f, 0.0f, 4.5f);
+
+ if (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D()
+#ifdef VC_PED_PORTS
+ || ped->m_pCurrentPhysSurface
+#endif
+ ) {
- m_objective = newObj;
+#ifdef FREE_CAM
+ if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) {
+#else
+ if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
+#endif
+ float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur);
+ ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle);
+ ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle);
+ } else {
+ ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur);
+ ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur);
+ }
+#ifdef VC_PED_PORTS
+ if (ped->m_pCurrentPhysSurface) {
+ ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;
+ ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;
+ }
+#endif
}
-
- if (newObj == OBJECTIVE_GUARD_SPOT) {
- m_vecSeekPosEx = dest;
- m_distanceToCountSeekDoneEx = safeDist;
- } else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
- m_pNextPathNode = nil;
- m_nextRoutePointPos = dest;
- m_vecSeekPos = m_nextRoutePointPos;
- bUsePedNodeSeek = true;
+
+ ped->bIsStanding = false;
+ ped->bIsInTheAir = true;
+ animAssoc->blendDelta = -1000.0f;
+ CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_JUMP_GLIDE);
+
+ if (ped->bDoBloodyFootprints) {
+ CVector bloodPos(0.0f, 0.0f, 0.0f);
+ ped->TransformToNode(bloodPos, PED_FOOTL);
+
+ bloodPos.z -= 0.1f;
+ bloodPos += 0.2f * ped->GetForward();
+
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
+ 0.26f * ped->GetForward().x,
+ 0.26f * ped->GetForward().y,
+ 0.14f * ped->GetRight().x,
+ 0.14f * ped->GetRight().y,
+ 255, 255, 0, 0, 4.0f, 3000, 1.0f);
+
+ bloodPos = CVector(0.0f, 0.0f, 0.0f);
+ ped->TransformToNode(bloodPos, PED_FOOTR);
+
+ bloodPos.z -= 0.1f;
+ bloodPos += 0.2f * ped->GetForward();
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
+ 0.26f * ped->GetForward().x,
+ 0.26f * ped->GetForward().y,
+ 0.14f * ped->GetRight().x,
+ 0.14f * ped->GetRight().y,
+ 255, 255, 0, 0, 4.0f, 3000, 1.0f);
+
+ if (ped->m_bloodyFootprintCountOrDeathTime <= 40) {
+ ped->m_bloodyFootprintCountOrDeathTime = 0;
+ ped->bDoBloodyFootprints = false;
+ } else {
+ ped->m_bloodyFootprintCountOrDeathTime -= 40;
+ }
}
}
void
-CPed::SetCarJack(CVehicle* car)
+CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- uint8 doorFlag;
- eDoors door;
- CPed *pedInSeat = nil;
+ CPed *ped = (CPed*)arg;
- if (car->IsBoat())
- return;
+ ped->bResetWalkAnims = true;
+ ped->bIsLanding = false;
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- doorFlag = CAR_DOOR_FLAG_RF;
- door = DOOR_FRONT_RIGHT;
- if (car->pPassengers[0]) {
- pedInSeat = car->pPassengers[0];
- } else if (m_nPedType == PEDTYPE_COP) {
- pedInSeat = car->pDriver;
- }
- break;
- case CAR_DOOR_RR:
- doorFlag = CAR_DOOR_FLAG_RR;
- door = DOOR_REAR_RIGHT;
- pedInSeat = car->pPassengers[2];
- break;
- case CAR_DOOR_LF:
- doorFlag = CAR_DOOR_FLAG_LF;
- door = DOOR_FRONT_LEFT;
- pedInSeat = car->pDriver;
- break;
- case CAR_DOOR_LR:
- doorFlag = CAR_DOOR_FLAG_LR;
- door = DOOR_REAR_LEFT;
- pedInSeat = car->pPassengers[1];
- break;
- default:
- doorFlag = CAR_DOOR_FLAG_UNKNOWN;
- break;
+ animAssoc->blendDelta = -1000.0f;
+}
+
+void
+CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -4.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
- if(car->bIsBus)
- pedInSeat = car->pDriver;
+ if (ped->m_nPedState == PED_JUMP)
+ ped->RestorePreviousState();
- 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)))
- if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
- if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
- if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
- if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))
- SetCarJack_AllClear(car, m_vehEnterType, doorFlag);
+ ped->bIsLanding = false;
}
-void
-CPed::Solicit(void)
+bool
+CPed::CanPedDriveOff(void)
{
- if (m_standardTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) {
- CVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType, 0.0f);
- SetMoveState(PEDMOVE_STILL);
-
- // Game uses GetAngleBetweenPoints and converts it to radian
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- doorPos.x, doorPos.y,
- GetPosition().x, GetPosition().y);
+ if (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds())
+ return false;
- if (m_fRotationDest < 0.0f) {
- m_fRotationDest = m_fRotationDest + TWOPI;
- } else if (m_fRotationDest > TWOPI) {
- m_fRotationDest = m_fRotationDest - TWOPI;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) {
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ return false;
}
+ }
+ return true;
+}
- if ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f)
- return;
- CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_HOOKERTALK);
- if (talkAssoc) {
- talkAssoc->blendDelta = -1000.0f;
- talkAssoc->flags |= ASSOC_DELETEFADEDOUT;
+// 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;
+ }
+}
+
+void
+CPed::SetRadioStation(void)
+{
+ static const uint8 radiosPerRadioCategories[10][4] = {
+ {JAH_RADIO, RISE_FM, GAME_FM, MSX_FM},
+ {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
+ {RISE_FM, GAME_FM, MSX_FM, FLASHBACK},
+ {HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM},
+ {HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK},
+ {JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK},
+ {HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK},
+ {HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK},
+ {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
+ {CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM}
+ };
+ uint8 orderInCat = 0; // BUG: this wasn't initialized
+
+ if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this)
+ return;
+
+ uint8 category = GetPedRadioCategory(GetModelIndex());
+ if (DMAudio.IsMP3RadioChannelAvailable()) {
+ if (CGeneral::GetRandomNumber() & 15) {
+ for (orderInCat = 0; orderInCat < 4; orderInCat++) {
+ if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
+ break;
+ }
+ } else {
+ m_pMyVehicle->m_nRadioStation = USERTRACK;
}
- RestorePreviousState();
- RestorePreviousObjective();
- SetObjectiveTimer(10000);
- } else if (!m_carInObjective) {
- RestorePreviousState();
- RestorePreviousObjective();
- SetObjectiveTimer(10000);
- } else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) {
- m_carInObjective = nil;
} else {
- m_pVehicleAnim = nil;
- SetLeader(m_carInObjective->pDriver);
+ for (orderInCat = 0; orderInCat < 4; orderInCat++) {
+ if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
+ break;
+ }
+ }
+ if (orderInCat == 4) {
+ if (DMAudio.IsMP3RadioChannelAvailable()) {
+ if (CGeneral::GetRandomNumber() & 15)
+ m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
+ else
+ m_pMyVehicle->m_nRadioStation = USERTRACK;
+ } else {
+ m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
+ }
}
}
-// Seperate function in VC, more logical. Not sure is it inlined in III.
void
-CPed::SetExitBoat(CVehicle *boat)
+CPed::WarpPedIntoCar(CVehicle *car)
{
-#ifndef VC_PED_PORTS
- m_nPedState = PED_IDLE;
- CVector firstPos = GetPosition();
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) {
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f);
- m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
- m_vehEnterType = CAR_DOOR_RF;
- m_nPedState = PED_EXIT_CAR;
+ bInVehicle = true;
+ m_pMyVehicle = car;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_carInObjective = car;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_nPedState = PED_DRIVING;
+ bUsesCollision = false;
+ bIsInTheAir = false;
+ bVehExitWillBeInstant = true;
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ car->SetDriver(this);
+ car->pDriver->RegisterReference((CEntity **) &car->pDriver);
+
+ } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ for (int i = 0; i < 4; i++) {
+ if (!car->pPassengers[i]) {
+ car->pPassengers[i] = this;
+ car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]);
+ break;
+ }
+ }
+ } else
+ return;
+
+ if (IsPlayer()) {
+ car->SetStatus(STATUS_PLAYER);
+ AudioManager.PlayerJustGotInCar();
+ CCarCtrl::RegisterVehicleOfInterest(car);
} else {
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- m_pCurSurface = boat;
- m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ car->SetStatus(STATUS_PHYSICS);
}
- SetPosition(firstPos);
- SetMoveState(PEDMOVE_STILL);
- m_vecMoveSpeed = boat->m_vecMoveSpeed;
- bTryingToReachDryLand = true;
+
+ CWorld::Remove(this);
+ SetPosition(car->GetPosition());
+ CWorld::Add(this);
+
+ if (car->bIsAmbulanceOnDuty) {
+ car->bIsAmbulanceOnDuty = false;
+ --CCarCtrl::NumAmbulancesOnDuty;
+ }
+ if (car->bIsFireTruckOnDuty) {
+ car->bIsFireTruckOnDuty = false;
+ --CCarCtrl::NumFiretrucksOnDuty;
+ }
+ if (!car->bEngineOn) {
+ car->bEngineOn = true;
+ 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);
+ RemoveWeaponWhenEnteringVehicle();
#else
- m_nPedState = PED_IDLE;
- CVector newPos = GetPosition();
- RemoveInCarAnims();
- CColModel* boatCol = boat->GetColModel();
- if (boat->IsUpsideDown()) {
- newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z };
- newPos = boat->GetMatrix() * newPos;
- newPos.z += 1.0f;
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- m_pCurSurface = boat;
- m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
- m_pCurrentPhysSurface = boat;
+ 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 {
-/* if (boat->m_modelIndex != MI_SKIMMER || boat->bIsInWater) {
- if (boat->m_modelIndex == MI_SKIMMER)
- newPos.z += 2.0f
-*/
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- m_pCurSurface = boat;
- m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
- m_pCurrentPhysSurface = boat;
- CColPoint foundCol;
- CEntity *foundEnt = nil;
- if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil))
- newPos.z = FEET_OFFSET + foundCol.point.z;
-/* // VC specific
+ // 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;
+
+ bChangedSeat = true;
+}
+
+
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+// returns event id, parameter is optional
+int32
+CPed::CheckForPlayerCrimes(CPed *victim)
+{
+ int i;
+ float dist;
+ float mindist = 60.0f;
+ CPlayerPed *player = FindPlayerPed();
+ int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0);
+ int event = -1;
+
+ for (i = 0; i < NUMEVENTS; i++) {
+ if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE)
+ continue;
+
+ // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc.
+ if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION)
+ continue;
+
+ if (victim && gaEvent[i].entityRef != victimRef)
+ continue;
+
+ if (gaEvent[i].criminal != player)
+ continue;
+
+ dist = (GetPosition() - gaEvent[i].posn).Magnitude();
+ if (dist < mindist) {
+ mindist = dist;
+ event = i;
+ }
+ }
+
+ if (event != -1) {
+ if (victim) {
+ m_victimOfPlayerCrime = victim;
} else {
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- SetMoveState(PEDMOVE_STILL);
- bTryingToReachDryLand = true;
- float upMult = 1.04f + boatCol->boundingBox.min.z;
- float rightMult = 0.6f * boatCol->boundingBox.max.x;
- newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition();
- GetPosition() = newPos;
- if (m_pMyVehicle) {
- PositionPedOutOfCollision();
- } else {
- m_pMyVehicle = boat;
- PositionPedOutOfCollision();
- m_pMyVehicle = nil;
+ switch (gaEvent[event].entityType) {
+ case EVENT_ENTITY_PED:
+ m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_VEHICLE:
+ m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_OBJECT:
+ m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef);
+ break;
+ default:
+ break;
}
- return;
}
-*/ }
- SetPosition(newPos);
- SetMoveState(PEDMOVE_STILL);
- m_vecMoveSpeed = boat->m_vecMoveSpeed;
+ }
+
+ return event;
+}
#endif
- // Not there in VC.
- CWaterLevel::FreeBoatWakeArray();
+
+#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
+
#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));
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index dbe61572..a3d4997d 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -5,7 +5,7 @@
#include "Crime.h"
#include "EventList.h"
#include "PedIK.h"
-#include "PedStats.h"
+#include "PedType.h"
#include "Physical.h"
#include "Weapon.h"
#include "WeaponInfo.h"
@@ -13,6 +13,7 @@
#define FEET_OFFSET 1.04f
#define CHECK_NEARBY_THINGS_MAX_DIST 15.0f
#define ENTER_CAR_MAX_DIST 30.0f
+#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
struct CPathNode;
class CAccident;
@@ -568,7 +569,7 @@ public:
void CalculateNewOrientation(void);
float WorkOutHeadingForMovingFirstPerson(float);
void CalculateNewVelocity(void);
- bool CanSeeEntity(CEntity*, float);
+ bool CanSeeEntity(CEntity*, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD);
void RestorePreviousObjective(void);
void SetIdle(void);
#ifdef _MSC_VER
@@ -747,7 +748,7 @@ public:
static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
- bool IsPlayer(void);
+ bool IsPlayer(void) const;
bool UseGroundColModel(void);
bool CanSetPedState(void);
bool IsPedInControl(void);
@@ -765,7 +766,7 @@ public:
void SetStoredObjective(void);
void SetLeader(CEntity* leader);
void SetPedStats(ePedStats);
- bool IsGangMember(void);
+ bool IsGangMember(void) const;
void Die(void);
void EnterTrain(void);
void ExitTrain(void);
@@ -788,7 +789,7 @@ public:
CObject *SpawnFlyingComponent(int, int8);
void SetCarJack_AllClear(CVehicle*, uint32, uint32);
#ifdef VC_PED_PORTS
- bool CanPedJumpThis(CEntity*, CVector*);
+ bool CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil);
#else
bool CanPedJumpThis(CEntity*);
#endif
@@ -809,9 +810,40 @@ public:
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; }
- void ReplaceWeaponWhenExitingVehicle(void);
- void RemoveWeaponWhenEnteringVehicle(void);
- bool IsNotInWreckedVehicle();
+ // It was inlined in III but not in VC.
+ inline void
+ 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() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {
+ SetCurrentWeapon(m_storedWeapon);
+ m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
+ }
+ } else {
+ AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);
+ }
+ }
+
+ // It was inlined in III but not in VC.
+ inline void
+ RemoveWeaponWhenEnteringVehicle(void)
+ {
+ if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
+ if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
+ m_storedWeapon = GetWeapon()->m_eWeaponType;
+ SetCurrentWeapon(WEAPONTYPE_UZI);
+ } else {
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ }
+ }
+ bool IsNotInWreckedVehicle()
+ {
+ return m_pMyVehicle != nil && ((CEntity*)m_pMyVehicle)->GetStatus() != STATUS_WRECKED;
+ }
// My additions, because there were many, many instances of that.
inline void SetFindPathAndFlee(CEntity *fleeFrom, int time, bool walk = false)
{
diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp
new file mode 100644
index 00000000..38303473
--- /dev/null
+++ b/src/peds/PedAI.cpp
@@ -0,0 +1,5413 @@
+#include "common.h"
+
+#include "main.h"
+#include "Particle.h"
+#include "RpAnimBlend.h"
+#include "Ped.h"
+#include "Wanted.h"
+#include "AnimBlendAssociation.h"
+#include "DMAudio.h"
+#include "General.h"
+#include "HandlingMgr.h"
+#include "Replay.h"
+#include "Camera.h"
+#include "PedPlacement.h"
+#include "ZoneCull.h"
+#include "Pad.h"
+#include "Pickups.h"
+#include "Train.h"
+#include "PedRoutes.h"
+#include "CopPed.h"
+#include "Script.h"
+#include "CarCtrl.h"
+#include "WaterLevel.h"
+#include "CarAI.h"
+#include "Zones.h"
+#include "Cranes.h"
+
+CVector vecPedCarDoorAnimOffset;
+CVector vecPedCarDoorLoAnimOffset;
+CVector vecPedVanRearDoorAnimOffset;
+CVector vecPedQuickDraggedOutCarAnimOffset;
+CVector vecPedDraggedOutCarAnimOffset;
+CVector vecPedTrainDoorAnimOffset;
+
+void
+CPed::SetObjectiveTimer(int time)
+{
+ if (time == 0) {
+ m_objectiveTimer = 0;
+ } else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+}
+
+void
+CPed::SetStoredObjective(void)
+{
+ if (m_objective == m_prevObjective)
+ return;
+
+ switch (m_objective)
+ {
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ return;
+ default:
+ m_prevObjective = m_objective;
+ }
+}
+
+void
+CPed::ForceStoredObjective(eObjective objective)
+{
+ if (objective != OBJECTIVE_ENTER_CAR_AS_DRIVER && objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ m_prevObjective = m_objective;
+ return;
+ }
+
+ switch (m_objective)
+ {
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ return;
+ default:
+ m_prevObjective = m_objective;
+ }
+}
+
+bool
+CPed::IsTemporaryObjective(eObjective objective)
+{
+ return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER ||
+#ifdef VC_PED_PORTS
+ objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||
+#endif
+ objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+}
+
+void
+CPed::SetObjective(eObjective newObj)
+{
+ if (DyingOrDead())
+ return;
+
+ if (newObj == OBJECTIVE_NONE) {
+ if ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER
+#ifdef VC_PED_PORTS
+ || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
+ && !IsPlayer()
+#else
+ )
+#endif
+ && !IsPedInControl()) {
+
+ bStartWanderPathOnFoot = true;
+ return;
+ }
+ // Unused code from assembly...
+ /*
+ else if(m_objective == OBJECTIVE_FLEE_CAR) {
+
+ } else {
+
+ }
+ */
+ m_objective = OBJECTIVE_NONE;
+ m_prevObjective = OBJECTIVE_NONE;
+ } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) {
+ SetObjectiveTimer(0);
+
+ if (m_objective == newObj)
+ return;
+
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+ bObjectiveCompleted = false;
+
+ switch (newObj) {
+ case OBJECTIVE_NONE:
+ m_prevObjective = OBJECTIVE_NONE;
+ break;
+ case OBJECTIVE_HAIL_TAXI:
+ m_nWaitTimer = 0;
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void
+CPed::SetObjective(eObjective newObj, void *entity)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective == newObj) {
+ // Why?
+ if (m_prevObjective != OBJECTIVE_NONE)
+ return;
+ }
+
+ if (entity == this)
+ return;
+
+ SetObjectiveTimer(0);
+ if (m_objective == newObj) {
+ switch (newObj) {
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GUARD_ATTACK:
+ if (m_pedInObjective == entity)
+ return;
+
+ break;
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_FLEE_CAR:
+#ifdef VC_PED_PORTS
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+#endif
+ return;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_DESTROY_CAR:
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ case OBJECTIVE_BUY_ICE_CREAM:
+ if (m_carInObjective == entity)
+ return;
+
+ break;
+ case OBJECTIVE_SET_LEADER:
+ if (m_leader == entity)
+ return;
+
+ break;
+ default:
+ break;
+ }
+ } else {
+ if ((newObj == OBJECTIVE_LEAVE_CAR
+#ifdef VC_PED_PORTS
+ || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE
+#endif
+ ) && !bInVehicle)
+ return;
+ }
+
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#endif
+ bObjectiveCompleted = false;
+ if (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj) {
+ if (IsTemporaryObjective(newObj))
+ ForceStoredObjective(newObj);
+ else
+ SetStoredObjective();
+ }
+ m_objective = newObj;
+ }
+
+ switch (newObj) {
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+
+ // In this special case, entity parameter isn't CEntity, but int.
+ SetObjectiveTimer((uintptr)entity);
+ break;
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_MUG_CHAR:
+ m_pNextPathNode = nil;
+ bUsePedNodeSeek = false;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ m_pLookTarget = (CEntity*)entity;
+ m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
+ break;
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GUARD_ATTACK:
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ break;
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ m_pedFormation = FORMATION_REAR;
+ break;
+ case OBJECTIVE_LEAVE_CAR:
+#ifdef VC_PED_PORTS
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+#endif
+ case OBJECTIVE_FLEE_CAR:
+ m_carInObjective = (CVehicle*)entity;
+ m_carInObjective->RegisterReference((CEntity **)&m_carInObjective);
+ if (m_carInObjective->bIsBus && m_leaveCarTimer == 0) {
+ for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) {
+ if (m_carInObjective->pPassengers[i] == this) {
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i;
+ break;
+ }
+ }
+ }
+
+ break;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_nMoveState == PEDMOVE_STILL)
+ SetMoveState(PEDMOVE_RUN);
+
+ if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) {
+ RestorePreviousObjective();
+ break;
+ }
+ // fall through
+ case OBJECTIVE_DESTROY_CAR:
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ case OBJECTIVE_BUY_ICE_CREAM:
+ m_carInObjective = (CVehicle*)entity;
+ m_carInObjective->RegisterReference((CEntity**)&m_carInObjective);
+ m_pSeekTarget = m_carInObjective;
+ m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ if (newObj == OBJECTIVE_SOLICIT_VEHICLE) {
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR &&
+ (m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) {
+ SetObjectiveTimer(14000);
+ } else {
+ m_objectiveTimer = 0;
+ }
+ break;
+ case OBJECTIVE_SET_LEADER:
+ SetLeader((CEntity*)entity);
+ RestorePreviousObjective();
+ break;
+ default:
+ break;
+ }
+}
+
+void
+CPed::SetObjective(eObjective newObj, CVector dest, float safeDist)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ return;
+
+ SetObjectiveTimer(0);
+ if (m_objective == newObj) {
+ if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
+ if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist)
+ return;
+ } else if (newObj == OBJECTIVE_GUARD_SPOT) {
+ if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist)
+ return;
+ }
+ }
+
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#endif
+ bObjectiveCompleted = false;
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+
+ if (newObj == OBJECTIVE_GUARD_SPOT) {
+ m_vecSeekPosEx = dest;
+ m_distanceToCountSeekDoneEx = safeDist;
+ } else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
+ m_pNextPathNode = nil;
+ m_nextRoutePointPos = dest;
+ m_vecSeekPos = m_nextRoutePointPos;
+ bUsePedNodeSeek = true;
+ }
+}
+
+// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode
+// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call...
+void
+CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)
+ return;
+
+ SetObjectiveTimer(0);
+
+ if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
+ return;
+
+ bObjectiveCompleted = false;
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+
+ if (newObj == OBJECTIVE_FOLLOW_ROUTE) {
+ SetFollowRoute(routePoint, routeType);
+ }
+}
+
+void
+CPed::SetObjective(eObjective newObj, CVector dest)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ return;
+
+ SetObjectiveTimer(0);
+ if (m_objective == newObj) {
+ if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
+ if (m_nextRoutePointPos == dest)
+ return;
+ } else if (newObj == OBJECTIVE_GUARD_SPOT) {
+ if (m_vecSeekPosEx == dest)
+ return;
+ }
+ }
+
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#endif
+ bObjectiveCompleted = false;
+ switch (newObj) {
+ case OBJECTIVE_GUARD_SPOT:
+ m_vecSeekPosEx = dest;
+ m_distanceToCountSeekDoneEx = 5.0f;
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ case OBJECTIVE_GUARD_AREA:
+ case OBJECTIVE_WAIT_IN_CAR:
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_FOLLOW_CAR_IN_CAR:
+ case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
+ case OBJECTIVE_DESTROY_OBJECT:
+ case OBJECTIVE_DESTROY_CAR:
+ break;
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ 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;
+ break;
+ case OBJECTIVE_RUN_TO_AREA:
+ bIsRunning = true;
+ 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;
+ break;
+ default: break;
+ }
+
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+}
+
+void
+CPed::ClearObjective(void)
+{
+ if (IsPedInControl() || m_nPedState == PED_DRIVING) {
+ m_objective = OBJECTIVE_NONE;
+#ifdef VC_PED_PORTS
+ m_pedInObjective = nil;
+ m_carInObjective = nil;
+#endif
+ if (m_nPedState == PED_DRIVING && m_pMyVehicle) {
+
+ if (m_pMyVehicle->pDriver != this) {
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ if(!IsPlayer())
+#endif
+ bWanderPathAfterExitingCar = true;
+
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+#ifdef VC_PED_PORTS
+ m_nLastPedState = PED_NONE;
+#endif
+ } else {
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ } else {
+ bClearObjective = true;
+ }
+}
+
+void
+CPed::ClearLeader(void)
+{
+ if (!m_leader)
+ return;
+
+ m_leader = nil;
+ if (IsPedInControl()) {
+ SetObjective(OBJECTIVE_NONE);
+ if (CharCreatedBy == MISSION_CHAR) {
+ SetIdle();
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumberInRange(0,8));
+ }
+ } else if (m_objective != OBJECTIVE_NONE) {
+ bClearObjective = true;
+ }
+}
+
+void
+CPed::UpdateFromLeader(void)
+{
+ if (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer)
+ return;
+
+ if (!m_leader)
+ return;
+
+ CVector leaderDist;
+ if (m_leader->InVehicle())
+ leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition();
+ else
+ leaderDist = m_leader->GetPosition() - GetPosition();
+
+ if (leaderDist.Magnitude() > 30.0f) {
+ if (IsPedInControl()) {
+ SetObjective(OBJECTIVE_NONE);
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ SetLeader(nil);
+ return;
+ }
+
+ if (IsPedInControl()) {
+ if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI)
+ WarpPedToNearLeaderOffScreen();
+
+ if (m_leader->m_nPedState == PED_DEAD) {
+ SetLeader(nil);
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+ return;
+ }
+ if (!m_leader->bInVehicle) {
+ if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (bInVehicle) {
+ if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR)
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+
+ return;
+ }
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ }
+ }
+ if (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) {
+ SetLeader(nil);
+ return;
+ }
+ }
+ if (!bInVehicle && m_leader->bInVehicle && m_leader->m_nPedState == PED_DRIVING) {
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers)
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle);
+ }
+ } else if (m_leader->m_objective == OBJECTIVE_NONE || (m_leader->IsPlayer() && m_leader->m_objective == OBJECTIVE_WAIT_ON_FOOT)
+ || m_objective == m_leader->m_objective) {
+
+ if (m_leader->m_nPedState == PED_ATTACK) {
+ CEntity *lookTargetOfLeader = m_leader->m_pLookTarget;
+ if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) {
+
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader);
+ SetObjectiveTimer(8000);
+ SetLookFlag(m_leader->m_pLookTarget, false);
+ SetLookTimer(500);
+ }
+ } else {
+ if (IsPedInControl() && m_nPedState != PED_ATTACK) {
+#ifndef VC_PED_PORTS
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+#else
+ if (m_leader->m_objective == OBJECTIVE_NONE && m_objective == OBJECTIVE_NONE
+ && m_leader->m_nPedState == PED_CHAT && m_nPedState == PED_CHAT) {
+
+ SetObjective(OBJECTIVE_NONE);
+ } else {
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+ }
+#endif
+ }
+ if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) {
+ if (ScanForThreats() && m_threatEntity) {
+ m_pLookTarget = m_threatEntity;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {
+ m_pPointGunAt = m_threatEntity;
+ if (m_threatEntity)
+ m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt);
+ SetAttack(m_threatEntity);
+ }
+ }
+ }
+ }
+ } else {
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_WAIT_ON_FOOT:
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_WAIT_IN_CAR:
+ case OBJECTIVE_FOLLOW_ROUTE:
+ SetObjective(m_leader->m_objective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_GUARD_SPOT:
+ SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ if (m_leader->m_pedInObjective) {
+ SetObjective(m_leader->m_objective, m_leader->m_pedInObjective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ }
+ break;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_leader->m_carInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective);
+ return;
+ }
+ break;
+ case OBJECTIVE_GUARD_ATTACK:
+ return;
+ case OBJECTIVE_HAIL_TAXI:
+ m_leader = nil;
+ SetObjective(OBJECTIVE_NONE);
+ break;
+ default:
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+ break;
+ }
+ }
+ } else if (bInVehicle) {
+ if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {
+
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective)
+ break;
+
+ // fall through
+ default:
+ if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) {
+#ifdef VC_PED_PORTS
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;
+#endif
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+void
+CPed::RestorePreviousObjective(void)
+{
+ if (m_objective == OBJECTIVE_NONE)
+ return;
+
+ if (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ && m_nPedState != PED_CARJACK
+#endif
+ )
+ m_pedInObjective = nil;
+
+ if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {
+ m_objective = OBJECTIVE_NONE;
+ if (m_pMyVehicle)
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+
+ } else {
+ m_objective = m_prevObjective;
+ m_prevObjective = OBJECTIVE_NONE;
+ }
+ bObjectiveCompleted = false;
+}
+
+void
+CPed::ProcessObjective(void)
+{
+ if (bClearObjective && (IsPedInControl() || m_nPedState == PED_DRIVING)) {
+ ClearObjective();
+ bClearObjective = false;
+ }
+ UpdateFromLeader();
+
+ CVector carOrOurPos;
+ CVector targetCarOrHisPos;
+ CVector distWithTarget;
+
+ if (m_objective != OBJECTIVE_NONE && (IsPedInControl() || m_nPedState == PED_DRIVING)) {
+ if (bInVehicle) {
+ if (!m_pMyVehicle) {
+ bInVehicle = false;
+ return;
+ }
+ carOrOurPos = m_pMyVehicle->GetPosition();
+ } else {
+ carOrOurPos = GetPosition();
+ }
+
+ if (m_pedInObjective) {
+ if (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+ targetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition();
+ } else {
+ targetCarOrHisPos = m_pedInObjective->GetPosition();
+ }
+ distWithTarget = targetCarOrHisPos - carOrOurPos;
+ } else if (m_carInObjective) {
+ targetCarOrHisPos = m_carInObjective->GetPosition();
+ distWithTarget = targetCarOrHisPos - carOrOurPos;
+ }
+
+ switch (m_objective) {
+ case OBJECTIVE_NONE:
+ case OBJECTIVE_GUARD_AREA:
+ case OBJECTIVE_FOLLOW_CAR_IN_CAR:
+ case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
+ case OBJECTIVE_DESTROY_OBJECT:
+ case OBJECTIVE_GOTO_AREA_IN_CAR:
+ case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+ case OBJECTIVE_SET_LEADER:
+ break;
+ case OBJECTIVE_WAIT_ON_FOOT:
+ SetIdle();
+ m_objective = OBJECTIVE_NONE;
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ if (InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ bFleeAfterExitingCar = true;
+ } else if (m_nPedState != PED_FLEE_POS) {
+ CVector2D fleePos = GetPosition();
+ SetFlee(fleePos, 10000);
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ }
+ break;
+ case OBJECTIVE_GUARD_SPOT:
+ {
+ distWithTarget = m_vecSeekPosEx - GetPosition();
+ if (m_pedInObjective) {
+ SetLookFlag(m_pedInObjective, true);
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (2.0f * m_distanceToCountSeekDoneEx >= distWithTargetSc) {
+ if (m_pedInObjective) {
+ if (distWithTargetSc <= m_distanceToCountSeekDoneEx)
+ SetIdle();
+ else
+ SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
+ } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ int threatType = ScanForThreats();
+ SetLookTimer(CGeneral::GetRandomNumberInRange(500, 1500));
+
+ // Second condition is pointless and isn't there in Mobile.
+ if (threatType == PED_FLAG_GUN || (threatType == PED_FLAG_EXPLOSION && m_threatEntity) || m_threatEntity) {
+ if (m_threatEntity->IsPed())
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
+ }
+ }
+ } else {
+ SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
+ }
+ break;
+ }
+ case OBJECTIVE_WAIT_IN_CAR:
+ m_nPedState = PED_DRIVING;
+ break;
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+ m_nPedState = PED_DRIVING;
+ break;
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ {
+ if (m_pedInObjective) {
+ if (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR
+ && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0
+ && !bKindaStayInSamePlace) {
+
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+ break;
+ }
+ if (InVehicle()) {
+ if (distWithTarget.Magnitude() >= 20.0f
+ || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) {
+ if (m_pMyVehicle->pDriver == this
+ && !m_pMyVehicle->m_nGettingInFlags) {
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ m_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;
+ if (m_nPedType == PEDTYPE_COP) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity);
+ m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
+ } else {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
+ }
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ } else {
+ bool targetHasVeh = m_pedInObjective->bInVehicle;
+ if (!targetHasVeh
+ || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+ }
+ break;
+ }
+ if (distWithTarget.Magnitude() > 30.0f && !bKindaStayInSamePlace) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ } else {
+ float closestVehDist = 60.0f;
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ CVehicle *foundVeh = nil;
+ for(int i = 0; i < lastVehicle; i++) {
+ CVehicle *nearVeh = (CVehicle*)vehicles[i];
+ /*
+ Not used.
+ CVector vehSpeed = nearVeh->GetSpeed();
+ CVector ourSpeed = GetSpeed();
+ */
+ CVector vehDistVec = nearVeh->GetPosition() - GetPosition();
+ if (vehDistVec.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh
+ && nearVeh->CanPedOpenLocks(this)) {
+
+ foundVeh = nearVeh;
+ closestVehDist = vehDistVec.Magnitude();
+ }
+ }
+ m_pMyVehicle = foundVeh;
+ if (m_pMyVehicle) {
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ } else if (!GetIsOnScreen()) {
+ CVector ourPos = GetPosition();
+ int closestNode = ThePaths.FindNodeClosestToCoors(ourPos, PATH_CAR, 20.0f);
+ if (closestNode >= 0) {
+ int16 colliding;
+ CWorld::FindObjectsKindaColliding(
+ ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+ if (!colliding) {
+ CZoneInfo zoneInfo;
+ int chosenCarClass;
+ CTheZones::GetZoneInfoForTimeOfDay(&ourPos, &zoneInfo);
+ 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->SetHeading(DEGTORAD(200.0f));
+ newVeh->SetStatus(STATUS_ABANDONED);
+ newVeh->m_nDoorLock = CARLOCK_UNLOCKED;
+ CWorld::Add(newVeh);
+ m_pMyVehicle = newVeh;
+ if (m_pMyVehicle) {
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ } else {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ }
+ }
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ {
+ bool killPlayerInNoPoliceZone = false;
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ break;
+ }
+ if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ SetMoveAnim();
+ break;
+ }
+ if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice())
+ killPlayerInNoPoliceZone = true;
+
+ if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) {
+ if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee())
+ bNotAllowedToDuck = true;
+ } else {
+ if (!m_pedInObjective->bInVehicle) {
+ if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) {
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ } else if (DuckAndCover()) {
+ break;
+ }
+ } else {
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ }
+ }
+ if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ }
+ if (m_pedInObjective->IsPlayer()) {
+ CPlayerPed *player = FindPlayerPed();
+ if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops
+ || player->m_pWanted->m_bIgnoredByEveryone
+ || m_pedInObjective->bIsInWater
+ || m_pedInObjective->m_nPedState == PED_ARRESTED) {
+
+ if (m_nPedState != PED_ARREST_PLAYER)
+ SetIdle();
+
+ break;
+ }
+ }
+ CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float wepRange = wepInfo->m_fRange;
+ float wepRangeAdjusted;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ wepRangeAdjusted = wepRange / 3.0f;
+ } else {
+ if (m_nPedState == PED_FIGHT) {
+ if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))
+ wepRange = 2.0f;
+ } else {
+ wepRange = 1.3f;
+ }
+ wepRangeAdjusted = wepRange;
+ }
+ if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) {
+ wepRangeAdjusted = 2.5f;
+ }
+ if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP
+ && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) {
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+ break;
+ }
+ if (m_pedInObjective->m_fHealth <= 0.0f) {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ SetMoveAnim();
+ break;
+ }
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+ CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle;
+ if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED
+ || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) {
+ SetIdle();
+ return;
+ }
+ SetLookFlag(vehOfTarget, false);
+ if (m_nPedState != PED_CARJACK) {
+ if (m_pedInObjective->m_nPedState != PED_ARRESTED) {
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
+ && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) {
+
+ // I hope so
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ CVector maxShotPos = vehOfTarget->GetPosition() - ourHead;
+ maxShotPos.Normalise();
+ maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CColPoint foundCol;
+ CEntity *foundEnt;
+ CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
+ true, true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = false;
+ if (foundEnt == vehOfTarget) {
+ SetAttack(vehOfTarget);
+ m_pPointGunAt = vehOfTarget;
+ if (vehOfTarget)
+ vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
+ if (distWithTargetSc <= m_distanceToCountSeekDone) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));
+ SetMoveState(PEDMOVE_STILL);
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ }
+ }
+ }
+ else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {
+ if (vehOfTarget) {
+ if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {
+ GoToNearestDoor(vehOfTarget);
+ } else {
+ m_vehEnterType = 0;
+ if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
+ m_vehEnterType = CAR_DOOR_LF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
+ m_vehEnterType = CAR_DOOR_RF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
+ m_vehEnterType = CAR_DOOR_LR;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
+ m_vehEnterType = CAR_DOOR_RR;
+ }
+ // Unused
+ // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType);
+ SetSeekCar(vehOfTarget, m_vehEnterType);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ }
+ }
+ }
+ SetMoveAnim();
+ break;
+ }
+ if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
+ SetLookFlag(m_pedInObjective, false);
+ TurnBody();
+ }
+ if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) {
+ if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {
+
+ ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);
+ return;
+ }
+ }
+ if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) {
+ if (distWithTargetSc > wepRange
+ || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_ARRESTED
+ || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f
+ || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) {
+
+ if (m_pedInObjective->EnteringCar())
+ wepRangeAdjusted = 2.0f;
+
+ if (bUsePedNodeSeek) {
+ CVector bestCoords(0.0f, 0.0f, 0.0f);
+ m_vecSeekPos = m_pedInObjective->GetPosition();
+
+ if (!m_pNextPathNode)
+ FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+
+ if (m_pNextPathNode)
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ } else {
+ SetSeek(m_pedInObjective, wepRangeAdjusted);
+ }
+ bCrouchWhenShooting = false;
+ if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) {
+ if (wepRange <= 5.0f) {
+ if (m_pedInObjective->IsPlayer()
+ && FindPlayerPed()->m_bSpeedTimerFlag
+ && (IsGangMember() || m_nPedType == PEDTYPE_COP)
+ && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
+ GiveWeapon(WEAPONTYPE_COLT45, 1000);
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+ }
+ } else {
+ bStopAndShoot = true;
+ }
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ break;
+ }
+ bStopAndShoot = false;
+ SetMoveAnim();
+ break;
+ }
+ }
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds()
+ && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+ if (bIsDucking) {
+ CAnimBlendAssociation *duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (duckAnim) {
+ duckAnim->blendDelta = -2.0f;
+ break;
+ }
+ bIsDucking = false;
+ } else if (wepRange <= 5.0f) {
+ SetMoveState(PEDMOVE_STILL);
+ SetAttack(m_pedInObjective);
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f));
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f));
+ bObstacleShowedUpDuringKillObjective = false;
+
+ } else {
+ CVector target;
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ if (m_pedInObjective->IsPed())
+ m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID);
+ else
+ target = m_pedInObjective->GetPosition();
+
+ target -= ourHead;
+ target.Normalise();
+ target = target * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CEntity *foundEnt = nil;
+ CColPoint foundCol;
+
+ CWorld::ProcessLineOfSight(
+ ourHead, target, foundCol, foundEnt,
+ true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = 0;
+ if (foundEnt == m_pedInObjective) {
+ SetAttack(m_pedInObjective);
+ m_pPointGunAt = m_pedInObjective;
+ if (m_pedInObjective)
+ m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f));
+
+ int time;
+ if (distWithTargetSc <= wepRangeAdjusted)
+ time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f);
+ else
+ time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);
+
+ SetAttackTimer(time);
+ bObstacleShowedUpDuringKillObjective = false;
+
+ } else if (foundEnt) {
+ if (foundEnt->IsPed()) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f));
+ bObstacleShowedUpDuringKillObjective = false;
+ } else {
+ if (foundEnt->IsObject()) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f));
+ bObstacleShowedUpDuringKillObjective = true;
+ } else if (foundEnt->IsVehicle()) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f));
+ bObstacleShowedUpDuringKillObjective = true;
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f));
+ bObstacleShowedUpDuringKillObjective = true;
+ }
+ }
+
+ m_fleeFrom = foundEnt;
+ m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom);
+ SetPointGunAt(m_pedInObjective);
+ }
+ }
+ } else {
+ if (!m_pedInObjective->m_pCurrentPhysSurface)
+ bStopAndShoot = false;
+
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
+
+ // This is weird...
+ if (bNotAllowedToDuck && bKindaStayInSamePlace) {
+ if (!bIsDucking) {
+ CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAnim || duckAnim->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
+ bIsDucking = true;
+ }
+ break;
+ } else {
+ CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAnim || duckAnim->blendDelta < 0.0f) {
+ bIsDucking = false;
+ } else {
+ break;
+ }
+ }
+ }
+ if (bObstacleShowedUpDuringKillObjective) {
+ if (m_nPedType == PEDTYPE_COP) {
+ if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45
+ || m_fleeFrom && m_fleeFrom->IsObject()) {
+ wepRangeAdjusted = 6.0f;
+ } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) {
+ wepRangeAdjusted = 4.0f;
+ } else {
+ wepRangeAdjusted = 2.0f;
+ }
+ } else {
+ wepRangeAdjusted = 2.0f;
+ }
+ }
+ if (distWithTargetSc <= wepRangeAdjusted) {
+ SetMoveState(PEDMOVE_STILL);
+ bIsPointingGunAt = true;
+ if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) {
+ m_attackTimer = CTimer::GetTimeInMilliseconds();
+ SetIdle();
+ }
+ } else {
+ if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS
+ && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) {
+ Say(SOUND_PED_ATTACK);
+ SetSeek(m_pedInObjective, wepRangeAdjusted);
+ bIsRunning = true;
+ }
+ }
+ }
+ }
+
+ if (distWithTargetSc < 2.5f && wepRange > 5.0f
+ && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) {
+
+ SetAttack(m_pedInObjective);
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
+ int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f);
+ SetAttackTimer(time);
+ SetShootTimer(time - 500);
+ }
+ SetMoveState(PEDMOVE_STILL);
+ }
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y);
+
+ SetMoveAnim();
+ break;
+ }
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ {
+ if (InVehicle()) {
+ if (m_nPedState == PED_DRIVING)
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ } else if (m_nPedState != PED_FLEE_ENTITY) {
+ int time;
+ if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
+ time = 0;
+ else
+ time = 6000;
+
+ SetFindPathAndFlee(m_pedInObjective, time);
+ }
+ break;
+ }
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ {
+ if (m_pedInObjective) {
+ float safeDistance = 2.0f;
+ if (m_pedInObjective->bInVehicle)
+ safeDistance = 3.0f;
+
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
+ if (distWithTargetSc <= safeDistance) {
+ bScriptObjectiveCompleted = true;
+ if (m_nPedState != PED_ATTACK) {
+ SetIdle();
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ if (distWithTargetSc > 2.0f)
+ SetMoveState(m_pedInObjective->m_nMoveState);
+ else
+ SetMoveState(PEDMOVE_STILL);
+ } else {
+ SetSeek(m_pedInObjective, safeDistance);
+ if (distWithTargetSc >= 5.0f) {
+ if (m_leader && m_leader->m_nMoveState == PEDMOVE_SPRINT)
+ SetMoveState(PEDMOVE_SPRINT);
+ else
+ SetMoveState(PEDMOVE_RUN);
+ } else {
+ if (m_leader && m_leader->m_nMoveState != PEDMOVE_STILL
+ && m_leader->m_nMoveState != PEDMOVE_NONE) {
+ if (m_leader->IsPlayer()) {
+ if (distWithTargetSc >= 3.0f && FindPlayerPed()->m_fMoveSpeed >= 1.3f)
+ SetMoveState(PEDMOVE_RUN);
+ else
+ SetMoveState(PEDMOVE_WALK);
+ } else {
+ SetMoveState(m_leader->m_nMoveState);
+ }
+ } else if (distWithTargetSc <= 3.0f) {
+ SetMoveState(PEDMOVE_WALK);
+ } else {
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ }
+ }
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ }
+ break;
+ }
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ {
+ if (m_pedInObjective) {
+ CVector posToGo = GetFormationPosition();
+ distWithTarget = posToGo - carOrOurPos;
+ SetSeek(posToGo, 1.0f);
+ if (distWithTarget.Magnitude() <= 3.0f) {
+ SetSeek(posToGo, 1.0f);
+ if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
+ SetMoveState(m_pedInObjective->m_nMoveState);
+ } else {
+ SetSeek(posToGo, 1.0f);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ }
+ break;
+ }
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ {
+ if (m_carInObjective) {
+ if (!bInVehicle && m_carInObjective->m_nNumPassengers >= m_carInObjective->m_nNumMaxPassengers) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+
+ break;
+ }
+
+ if (m_prevObjective == OBJECTIVE_HAIL_TAXI && !((CAutomobile*)m_carInObjective)->bTaxiLight) {
+ RestorePreviousObjective();
+ ClearObjective();
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ bIsRunning = false;
+ break;
+ }
+ if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) {
+ if (!EnteringCar()) {
+ bool foundSeat = false;
+ if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
+ if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
+ if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
+ foundSeat = false;
+ } else {
+ m_vehEnterType = CAR_DOOR_RR;
+ foundSeat = true;
+ }
+ } else {
+ m_vehEnterType = CAR_DOOR_LR;
+ foundSeat = true;
+ }
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ foundSeat = true;
+ }
+ for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) {
+ if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
+ m_vehEnterType = CAR_DOOR_RF;
+ foundSeat = true;
+ }
+ }
+ if (foundSeat) {
+ SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType));
+ SetEnterCar(m_carInObjective, m_vehEnterType);
+ }
+ }
+ m_objectiveTimer = 0;
+ }
+ }
+ // fall through
+ }
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ {
+ if (!m_carInObjective || bInVehicle) {
+#ifdef VC_PED_PORTS
+ if (bInVehicle && m_pMyVehicle != m_carInObjective) {
+ SetExitCar(m_pMyVehicle, 0);
+ } else
+#endif
+ {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ RestorePreviousState();
+ }
+ } else {
+ if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) {
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ }
+ if (IsPedInControl()) {
+ if (m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ if (distWithTarget.Magnitude() < 20.0f) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ return;
+ }
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (m_carInObjective->pDriver
+#ifdef VC_PED_PORTS
+ && !IsPlayer()
+#endif
+ ) {
+ if (m_carInObjective->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS && m_carInObjective->pDriver != m_pedInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ m_carInObjective->bIsBeingCarJacked = false;
+ }
+ }
+ }
+ } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ if (m_carInObjective->pDriver
+#ifdef VC_PED_PORTS
+ && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR)
+#endif
+ ) {
+ if (m_carInObjective->pDriver->m_nPedType == m_nPedType) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ m_carInObjective->bIsBeingCarJacked = false;
+ }
+ }
+ }
+ if (m_carInObjective->IsUpsideDown() && m_carInObjective->m_vehType != VEHICLE_TYPE_BIKE) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ return;
+ }
+ if (!m_carInObjective->IsBoat() || m_nPedState == PED_SEEK_IN_BOAT) {
+ if (m_nPedState != PED_SEEK_CAR)
+ SetSeekCar(m_carInObjective, 0);
+ } else {
+ SetSeekBoatPosition(m_carInObjective);
+ }
+ if (m_nMoveState == PEDMOVE_STILL && !bVehEnterDoorIsBlocked)
+ SetMoveState(PEDMOVE_RUN);
+
+ if (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) {
+ distWithTarget = m_carInObjective->GetPosition() - GetPosition();
+ if (!bInVehicle) {
+ if (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) {
+ if (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen())
+ WarpPedToNearEntityOffScreen(m_carInObjective);
+
+ if (CharCreatedBy != MISSION_CHAR || m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS
+#ifdef VC_PED_PORTS
+ || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled()
+#endif
+ ) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ } else {
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ }
+ } else if (!bInVehicle) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_DESTROY_CAR:
+ {
+ if (!m_carInObjective) {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ break;
+ }
+ float distWithTargetSc = distWithTarget.Magnitude();
+ CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float wepRange = wepInfo->m_fRange;
+ m_pLookTarget = m_carInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+
+ m_pSeekTarget = m_carInObjective;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+
+ TurnBody();
+ if (m_carInObjective->m_fHealth <= 0.0f) {
+ ClearLookFlag();
+ bScriptObjectiveCompleted = true;
+ break;
+ }
+
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
+ && distWithTargetSc < wepRange) {
+
+ // I hope so
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ CVector maxShotPos = m_carInObjective->GetPosition() - ourHead;
+ maxShotPos.Normalise();
+ maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CColPoint foundCol;
+ CEntity *foundEnt;
+ CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
+ true, true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = false;
+ if (foundEnt == m_carInObjective) {
+ SetAttack(m_carInObjective);
+ m_pPointGunAt = m_carInObjective;
+ if (m_pPointGunAt)
+ m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
+ if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300));
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) {
+
+ float safeDistance;
+ if (wepRange <= 5.0f)
+ safeDistance = 3.0f;
+ else
+ safeDistance = wepRange * 0.25f;
+
+ SetSeek(m_carInObjective, safeDistance);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ SetLookFlag(m_carInObjective, false);
+ TurnBody();
+ break;
+ }
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ {
+ distWithTarget = m_nextRoutePointPos - GetPosition();
+ distWithTarget.z = 0.0f;
+ if (InVehicle()) {
+ CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos);
+ CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle);
+ if (distWithTarget.MagnitudeSqr() < sq(20.0f)) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS);
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+ break;
+ }
+ if (distWithTarget.Magnitude() > 30.0f) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ } else {
+ float closestVehDist = SQR(60.0f);
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ CVehicle* foundVeh = nil;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* nearVeh = (CVehicle*)vehicles[i];
+ /*
+ Not used.
+ CVector vehSpeed = nearVeh->GetSpeed();
+ CVector ourSpeed = GetSpeed();
+ */
+ CVector vehDistVec = nearVeh->GetPosition() - GetPosition();
+ if (vehDistVec.MagnitudeSqr() < closestVehDist
+ && m_pedInObjective->m_pMyVehicle != nearVeh)
+ {
+ foundVeh = nearVeh;
+ closestVehDist = vehDistVec.MagnitudeSqr();
+ }
+ }
+ m_pMyVehicle = foundVeh;
+ if (m_pMyVehicle) {
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ }
+ break;
+ }
+ // fall through
+ }
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ {
+ if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA)
+ && InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ } else {
+ distWithTarget = m_nextRoutePointPos - GetPosition();
+ distWithTarget.z = 0.0f;
+ if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ SetMoveState(PEDMOVE_STILL);
+ } else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) {
+ if (bUsePedNodeSeek) {
+ CVector bestCoords(0.0f, 0.0f, 0.0f);
+ m_vecSeekPos = m_nextRoutePointPos;
+
+ if (!m_pNextPathNode)
+ FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+
+ if (m_pNextPathNode)
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+ }
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ }
+ }
+
+ break;
+ }
+ case OBJECTIVE_GUARD_ATTACK:
+ {
+ if (m_pedInObjective) {
+ SetLookFlag(m_pedInObjective, true);
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ m_lookTimer = m_attackTimer;
+ TurnBody();
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (distWithTargetSc >= 20.0f) {
+ RestorePreviousObjective();
+ } else if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
+ if (m_nPedState != PED_SEEK_ENTITY && distWithTargetSc >= 2.0f) {
+ SetSeek(m_pedInObjective, 1.0f);
+ } else {
+ SetAttack(m_pedInObjective);
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1500.0f));
+ }
+ SetAttackTimer(1000);
+ }
+ } else {
+ RestorePreviousObjective();
+ }
+ break;
+ }
+ case OBJECTIVE_FOLLOW_ROUTE:
+ if (HaveReachedNextPointOnRoute(1.0f)) {
+ int nextPoint = GetNextPointOnRoute();
+ m_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint);
+ } else {
+ SetSeek(m_nextRoutePointPos, 0.8f);
+ }
+ break;
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ if (m_carInObjective) {
+ if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) {
+ if (!bInVehicle) {
+ SetObjective(OBJECTIVE_NONE);
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ } else {
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT)
+ SetSeekCar(m_carInObjective, 0);
+ }
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ break;
+ case OBJECTIVE_HAIL_TAXI:
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ Say(SOUND_PED_TAXI_WAIT);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ break;
+ case OBJECTIVE_CATCH_TRAIN:
+ {
+ if (m_carInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ } else {
+ CVehicle* trainToEnter = nil;
+ float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+
+ CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* nearVeh = (CVehicle*)vehicles[i];
+ if (nearVeh->IsTrain()) {
+ CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
+ float vehDist = vehDistVec.Magnitude();
+ if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh)
+ {
+ trainToEnter = nearVeh;
+ closestCarDist = vehDist;
+ }
+ }
+ }
+ if (trainToEnter) {
+ m_carInObjective = trainToEnter;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_BUY_ICE_CREAM:
+ if (m_carInObjective) {
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM)
+ SetSeekCar(m_carInObjective, 0);
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ break;
+ case OBJECTIVE_STEAL_ANY_CAR:
+ {
+ if (bInVehicle) {
+ bScriptObjectiveCompleted = true;
+ RestorePreviousObjective();
+ } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
+ CVehicle *carToSteal = nil;
+ float closestCarDist = ENTER_CAR_MAX_DIST;
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+
+ // NB: This should've been ENTER_CAR_MAX_DIST actually, and is fixed in VC.
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ for(int i = 0; i < lastVehicle; i++) {
+ CVehicle *nearVeh = (CVehicle*)vehicles[i];
+ if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) {
+ if (nearVeh->CanPedOpenLocks(this)) {
+ CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
+ float vehDist = vehDistVec.Magnitude();
+ if (vehDist < closestCarDist) {
+ carToSteal = nearVeh;
+ closestCarDist = vehDist;
+ }
+ }
+ }
+ }
+ }
+ if (carToSteal) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal);
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_MUG_CHAR:
+ {
+ if (m_pedInObjective) {
+ if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) {
+ ClearObjective();
+ return;
+ }
+ if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) {
+ ClearObjective();
+ return;
+ }
+ if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective);
+ SetMoveState(PEDMOVE_SPRINT);
+ return;
+ }
+ if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this
+ || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) {
+ ClearObjective();
+ SetFindPathAndFlee(m_pedInObjective, 15000, true);
+ return;
+ }
+ float distWithTargetScSqr = distWithTarget.MagnitudeSqr();
+ if (distWithTargetScSqr <= sq(10.0f)) {
+ if (distWithTargetScSqr <= sq(1.4f)) {
+ CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD);
+ 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)) {
+ CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
+ punchAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ CVector2D offset(distWithTarget.x, distWithTarget.y);
+ int dir = m_pedInObjective->GetLocalDirection(offset);
+ m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);
+ m_pedInObjective->ReactToAttack(this);
+ m_pedInObjective->Say(SOUND_PED_ROBBED);
+ Say(SOUND_PED_MUGGING);
+ bRichFromMugging = true;
+
+ // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call
+ CPed *victim = m_pedInObjective;
+ ClearObjective();
+ if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ || victim->m_pedInObjective != this) {
+ SetFindPathAndFlee(victim, 15000, true);
+ m_nLastPedState = PED_WANDER_PATH;
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim);
+ SetMoveState(PEDMOVE_SPRINT);
+ m_nLastPedState = PED_WANDER_PATH;
+ }
+ }
+ } else {
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+ if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
+
+ CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f);
+ newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+ } else {
+ SetSeek(m_pedInObjective, 1.0f);
+ CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
+
+ if (walkAssoc)
+ walkAssoc->speed = 1.3f;
+ }
+ } else {
+ ClearObjective();
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ }
+ } else {
+#ifdef VC_PED_PORTS
+ m_objective = OBJECTIVE_NONE;
+#endif
+ ClearObjective();
+ }
+ break;
+ }
+ case OBJECTIVE_FLEE_CAR:
+ if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) {
+ RestorePreviousObjective();
+ SetFlee(m_pMyVehicle, 6000);
+ break;
+ }
+ // fall through
+ case OBJECTIVE_LEAVE_CAR:
+ 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))) {
+ if (m_pMyVehicle->IsTrain())
+ SetExitTrain(m_pMyVehicle);
+#ifdef VC_PED_PORTS
+ else if (m_pMyVehicle->IsBoat())
+ SetExitBoat(m_pMyVehicle);
+#endif
+ else
+ SetExitCar(m_pMyVehicle, 0);
+ }
+ } else {
+ RestorePreviousObjective();
+ }
+ }
+ break;
+#ifdef VC_PED_PORTS
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+ {
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
+ if (InVehicle()) {
+ if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) {
+ if (m_pMyVehicle->IsBoat())
+ SetExitBoat(m_pMyVehicle);
+ else if (m_pMyVehicle->bIsBus)
+ SetExitCar(m_pMyVehicle, 0);
+ else {
+ eCarNodes doorNode = CAR_DOOR_LF;
+ if (m_pMyVehicle->pDriver != this) {
+ if (m_pMyVehicle->pPassengers[0] == this) {
+ doorNode = CAR_DOOR_RF;
+ } else if (m_pMyVehicle->pPassengers[1] == this) {
+ doorNode = CAR_DOOR_LR;
+ } else if (m_pMyVehicle->pPassengers[2] == this) {
+ doorNode = CAR_DOOR_RR;
+ }
+ }
+ SetBeingDraggedFromCar(m_pMyVehicle, doorNode, false);
+ }
+ }
+ }
+ }
+ break;
+ }
+#endif
+ }
+ if (bObjectiveCompleted
+ || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
+ RestorePreviousObjective();
+ if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer)
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1;
+
+ if (CharCreatedBy != RANDOM_CHAR || bInVehicle) {
+ if (IsPedInControl())
+ RestorePreviousState();
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ }
+ ClearAimFlag();
+ ClearLookFlag();
+ }
+ }
+}
+
+void
+CPed::SetFollowRoute(int16 currentPoint, int16 routeType)
+{
+ m_routeLastPoint = currentPoint;
+ m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);
+ m_routePointsPassed = 0;
+ m_routeType = routeType;
+ m_routePointsBeingPassed = 1;
+ m_objective = OBJECTIVE_FOLLOW_ROUTE;
+ m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute());
+}
+
+int
+CPed::GetNextPointOnRoute(void)
+{
+ int16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
+
+ // Route is complete
+ if (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) {
+
+ switch (m_routeType) {
+ case PEDROUTE_STOP_WHEN_DONE:
+ nextPoint = -1;
+ break;
+ case PEDROUTE_GO_BACKWARD_WHEN_DONE:
+ m_routePointsBeingPassed = -m_routePointsBeingPassed;
+ nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
+ break;
+ case PEDROUTE_GO_TO_START_WHEN_DONE:
+ m_routePointsPassed = -1;
+ nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
+ break;
+ default:
+ break;
+ }
+ }
+ return nextPoint;
+}
+
+bool
+CPed::HaveReachedNextPointOnRoute(float distToCountReached)
+{
+ if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() >= distToCountReached)
+ return false;
+
+ m_routePointsPassed += m_routePointsBeingPassed;
+ return true;
+}
+
+bool
+CPed::CanSeeEntity(CEntity *entity, float threshold)
+{
+ float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
+ entity->GetPosition().x,
+ entity->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ if (neededAngle < 0.0f)
+ neededAngle += TWOPI;
+ else if (neededAngle > TWOPI)
+ neededAngle -= TWOPI;
+
+ float ourAngle = m_fRotationCur;
+ if (ourAngle < 0.0f)
+ ourAngle += TWOPI;
+ else if (ourAngle > TWOPI)
+ ourAngle -= TWOPI;
+
+ float neededTurn = Abs(neededAngle - ourAngle);
+
+ return neededTurn < threshold || TWOPI - threshold < neededTurn;
+}
+
+// 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++) {
+ if (GetWeapon(i).m_nAmmoTotal > 0) {
+ eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
+ if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) {
+ SetCurrentWeapon(i);
+ return true;
+ }
+ }
+ }
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
+ return false;
+}
+
+void
+CPed::ReactToPointGun(CEntity *entWithGun)
+{
+ CPed *pedWithGun = (CPed*)entWithGun;
+ int waitTime;
+
+ if (IsPlayer() || !IsPedInControl() || CharCreatedBy == MISSION_CHAR)
+ return;
+
+ if (m_leader == pedWithGun)
+ return;
+
+ if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER ||
+ (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f)
+ return;
+
+ if (m_leader) {
+ if (FindPlayerPed() == m_leader)
+ return;
+
+ ClearLeader();
+ }
+ if (m_pedStats->m_flags & STAT_GUN_PANIC
+ && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())
+ && m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_AIM_GUN) {
+
+ waitTime = CGeneral::GetRandomNumberInRange(3000, 6000);
+ SetWaitState(WAITSTATE_PLAYANIM_HANDSCOWER, &waitTime);
+ Say(SOUND_PED_HANDS_COWER);
+ m_pLookTarget = pedWithGun;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ SetMoveState(PEDMOVE_NONE);
+
+ } else if (m_nPedType != pedWithGun->m_nPedType) {
+ if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
+ RegisterThreatWithGangPeds(pedWithGun);
+ }
+
+ if (m_nPedType == PEDTYPE_COP) {
+ if (pedWithGun->IsPlayer()) {
+ ((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2);
+ if (bCrouchWhenShooting || bKindaStayInSamePlace) {
+ SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000));
+ return;
+ }
+ }
+ }
+
+ if (m_nPedType != PEDTYPE_COP
+ && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())
+ && (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun)
+ && m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
+
+ waitTime = CGeneral::GetRandomNumberInRange(3000, 6000);
+ SetWaitState(WAITSTATE_PLAYANIM_HANDSUP, &waitTime);
+ Say(SOUND_PED_HANDS_UP);
+ m_pLookTarget = pedWithGun;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ SetMoveState(PEDMOVE_NONE);
+ if (m_nPedState == PED_FLEE_ENTITY) {
+ m_fleeFrom = pedWithGun;
+ m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
+ }
+
+ if (FindPlayerPed() == pedWithGun && bRichFromMugging) {
+ int money = CGeneral::GetRandomNumberInRange(100, 300);
+ int pickupCount = money / 40 + 1;
+ int moneyPerPickup = money / pickupCount;
+
+ for (int i = 0; i < pickupCount; i++) {
+ float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x;
+ float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y;
+ bool found = false;
+ float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f;
+ if (found) {
+ CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
+ }
+ }
+ bRichFromMugging = false;
+ }
+ }
+ }
+}
+
+void
+CPed::ReactToAttack(CEntity *attacker)
+{
+ if (IsPlayer() && attacker->IsPed()) {
+ InformMyGangOfAttack(attacker);
+ SetLookFlag(attacker, true);
+ SetLookTimer(700);
+ return;
+ }
+
+#ifdef VC_PED_PORTS
+ if (m_nPedState == PED_DRIVING && InVehicle()
+ && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) {
+
+ if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE
+ && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS)
+ && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) {
+
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ }
+ } else
+#endif
+ if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {
+ CPed *ourLeader = m_leader;
+ if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader)
+ && attacker->IsPed()) {
+
+ CPed *attackerPed = (CPed*)attacker;
+ if (bNotAllowedToDuck) {
+ if (!attackerPed->GetWeapon()->IsTypeMelee()) {
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ } else if (bCrouchWhenShooting || bKindaStayInSamePlace) {
+ SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000));
+ return;
+ }
+
+ if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) {
+ if (m_pedStats != attackerPed->m_pedStats) {
+ if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
+ RegisterThreatWithGangPeds(attackerPed);
+ }
+ if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker);
+ SetMoveState(PEDMOVE_RUN);
+ } else {
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);
+ SetObjectiveTimer(20000);
+ }
+ }
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed);
+ SetMoveState(PEDMOVE_RUN);
+ if (attackerPed->GetWeapon()->IsTypeMelee())
+ Say(SOUND_PED_FLEE_RUN);
+ }
+ }
+ }
+}
+
+void
+CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!ped->IsNotInWreckedVehicle())
+ return;
+
+ if (!ped->EnteringCar()) {
+#ifdef VC_PED_PORTS
+ if (ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+
+ return;
+ }
+ if (ped->m_fHealth == 0.0f) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ bool itsVan = !!veh->bIsVan;
+ bool itsBus = !!veh->bIsBus;
+#ifdef FIX_BUGS
+ bool itsLow = !!veh->bLowVehicle;
+#endif
+ eDoors enterDoor;
+ AnimationId enterAnim;
+
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ itsVan = false;
+ enterDoor = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ enterDoor = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ itsVan = false;
+ enterDoor = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ enterDoor = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+
+ if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {
+
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (ped->m_nPedState == PED_CARJACK) {
+ ped->PedAnimDoorOpenCB(nil, ped);
+ return;
+ }
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (itsVan) {
+ enterAnim = ANIM_VAN_GETIN;
+ } else if (itsBus) {
+ enterAnim = ANIM_COACH_IN_R;
+#ifdef FIX_BUGS
+ } else if (itsLow) {
+ enterAnim = ANIM_CAR_GETIN_LOW_RHS;
+#endif
+ } else {
+ enterAnim = ANIM_CAR_GETIN_RHS;
+ }
+ } else if (itsVan) {
+ enterAnim = ANIM_VAN_GETIN_L;
+ } else if (itsBus) {
+ enterAnim = ANIM_COACH_IN_L;
+#ifdef FIX_BUGS
+ } else if (itsLow) {
+ enterAnim = ANIM_CAR_GETIN_LOW_LHS;
+#endif
+ } else {
+ enterAnim = 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)) {
+
+ 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);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, 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);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L);
+ } else {
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {
+
+ if (!veh->bLowVehicle
+ && veh->pDriver->CharCreatedBy != MISSION_CHAR
+ && veh->pDriver->m_nPedState == PED_DRIVING) {
+
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true);
+
+ if (veh->pDriver->IsGangMember())
+ veh->pDriver->RegisterThreatWithGangPeds(ped);
+ return;
+ }
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+
+ } else {
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS);
+
+ ped->bCancelEnteringCar = true;
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+ }
+}
+
+void
+CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!ped->IsNotInWreckedVehicle())
+ return;
+
+ if (!ped->EnteringCar()) {
+#ifdef VC_PED_PORTS
+ if (ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+
+ return;
+ }
+
+ eDoors door;
+ CPed *pedInSeat = nil;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; pedInSeat = veh->pPassengers[0]; break;
+ case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; pedInSeat = veh->pPassengers[2]; break;
+ case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; pedInSeat = veh->pDriver; break;
+ case CAR_DOOR_LR: door = DOOR_REAR_LEFT; pedInSeat = veh->pPassengers[1]; break;
+ default: assert(0);
+ }
+
+ if (ped->m_fHealth == 0.0f || CPad::GetPad(0)->ArePlayerControlsDisabled() && pedInSeat && pedInSeat->IsPlayer()) {
+ ped->QuitEnteringCar();
+ return;
+ }
+
+ bool isVan = veh->bIsVan;
+ bool isBus = veh->bIsBus;
+ bool isLow = veh->bLowVehicle;
+ bool vehUpsideDown = veh->IsUpsideDown();
+ if (ped->bCancelEnteringCar) {
+ if (ped->IsPlayer()) {
+ if (veh->pDriver) {
+ if (veh->pDriver->m_nPedType == PEDTYPE_COP) {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ }
+ }
+#ifdef CANCELLABLE_CAR_ENTER
+ if (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+#endif
+ ped->QuitEnteringCar();
+ ped->RestorePreviousObjective();
+ ped->bCancelEnteringCar = false;
+ return;
+ }
+ if (!veh->IsDoorMissing(door) && veh->IsCar()) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+
+ if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {
+ ped->QuitEnteringCar();
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR)
+ ped->SetFall(1000, ANIM_KO_SPIN_R, false);
+ else
+ ped->SetFall(1000, ANIM_KO_SPIN_L, false);
+
+ return;
+ }
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f);
+
+ if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF)
+ 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;
+ } else if (isBus) {
+ animToPlay = ANIM_COACH_IN_R;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_GETIN_LOW_RHS;
+ } else {
+ animToPlay = ANIM_CAR_GETIN_RHS;
+ }
+ } else if (isVan) {
+ animToPlay = ANIM_VAN_GETIN_L;
+ } else if (isBus) {
+ animToPlay = ANIM_COACH_IN_L;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_GETIN_LOW_LHS;
+ } else {
+ animToPlay = ANIM_CAR_GETIN_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ } else {
+ CPed *pedToDragOut = nil;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break;
+ case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break;
+ case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break;
+ case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break;
+ default: assert(0);
+ }
+
+ if (vehUpsideDown) {
+ ped->QuitEnteringCar();
+ if (ped->m_nPedType == PEDTYPE_COP)
+ ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
+ }
+
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
+ if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {
+ if (pedToDragOut->m_nPedState != PED_DRIVING) {
+ ped->QuitEnteringCar();
+ pedToDragOut = nil;
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ }
+ } else if (ped->m_nPedType == PEDTYPE_COP) {
+ ped->QuitEnteringCar();
+ if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) {
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
+ } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);
+ }
+ } else {
+ // BUG: Probably we will sit on top of the passenger if his m_ped_flagF4 is true.
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ }
+ } else {
+ if (pedToDragOut) {
+ if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {
+
+ // BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC.
+ ped->QuitEnteringCar();
+ pedToDragOut = nil;
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ }
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ }
+ }
+
+ if (pedToDragOut) {
+ pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false);
+ if (pedToDragOut->IsGangMember())
+ pedToDragOut->RegisterThreatWithGangPeds(ped);
+ }
+ }
+
+ if (veh->pDriver && ped) {
+ veh->pDriver->SetLookFlag(ped, true);
+ veh->pDriver->SetLookTimer(1000);
+ }
+ return;
+}
+
+void
+CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (ped->EnteringCar()) {
+ if (!ped->IsNotInWreckedVehicle())
+ return;
+
+#ifdef CANCELLABLE_CAR_ENTER
+ if (ped->bCancelEnteringCar) {
+ ped->QuitEnteringCar();
+ ped->RestorePreviousObjective();
+ ped->bCancelEnteringCar = false;
+ return;
+ }
+#endif
+
+ bool isLow = !!veh->bLowVehicle;
+
+ int padNo;
+ if (ped->IsPlayer()) {
+
+ // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
+ switch (ped->m_nPedType) {
+ case PEDTYPE_PLAYER1:
+ padNo = 0;
+ break;
+ case PEDTYPE_PLAYER2:
+ padNo = 1;
+ break;
+ case PEDTYPE_PLAYER3:
+ padNo = 2;
+ break;
+ case PEDTYPE_PLAYER4:
+ padNo = 3;
+ break;
+ }
+ CPad *pad = CPad::GetPad(padNo);
+
+ if (!pad->ArePlayerControlsDisabled()) {
+
+ if (pad->GetTarget()
+ || pad->NewState.LeftStickX
+ || pad->NewState.LeftStickY
+ || pad->NewState.DPadUp
+ || pad->NewState.DPadDown
+ || pad->NewState.DPadLeft
+ || pad->NewState.DPadRight) {
+ ped->QuitEnteringCar();
+ ped->RestorePreviousObjective();
+ return;
+ }
+ }
+ }
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ AnimationId animToPlay;
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
+ if (isLow)
+ animToPlay = ANIM_CAR_GETIN_LOW_RHS;
+ else
+ animToPlay = ANIM_CAR_GETIN_RHS;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_GETIN_LOW_LHS;
+ } else {
+ animToPlay = ANIM_CAR_GETIN_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ } else {
+ ped->QuitEnteringCar();
+ }
+ } else {
+ ped->QuitEnteringCar();
+ }
+}
+
+void
+CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*) arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ if (!ped->EnteringCar()) {
+#ifdef VC_PED_PORTS
+ if(ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+ return;
+ }
+
+ if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) {
+ PedSetInCarCB(nil, ped);
+ ped->m_nLastPedState = ped->m_nPedState;
+ ped->m_nPedState = PED_ARRESTED;
+ ped->bGonnaKillTheCarJacker = false;
+ if (veh) {
+ veh->m_nNumGettingIn = 0;
+ veh->m_nGettingInFlags = 0;
+ veh->bIsHandbrakeOn = true;
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ }
+ return;
+ }
+ if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF
+ && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)
+ && veh->IsCar()) {
+ if (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING)
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
+
+ PedSetInCarCB(nil, ped);
+ return;
+ }
+ bool isVan = !!veh->bIsVan;
+ bool isBus = !!veh->bIsBus;
+ bool isLow = !!veh->bLowVehicle;
+ eDoors enterDoor;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ isVan = false;
+ enterDoor = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ enterDoor = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ isVan = false;
+ enterDoor = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ enterDoor = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+ if (!veh->IsDoorMissing(enterDoor)) {
+ if (veh->IsCar())
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING);
+ }
+ CPed *driver = veh->pDriver;
+ if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
+ if (veh->bIsBus) {
+ driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ if (driver->IsPlayer()) {
+ veh->bIsHandbrakeOn = true;
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ }
+ driver->bBusJacked = true;
+ veh->bIsBeingCarJacked = false;
+ PedSetInCarCB(nil, ped);
+ if (ped->m_nPedType == PEDTYPE_COP
+ || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT
+ || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ }
+ ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400;
+ return;
+ }
+ if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) {
+ if (!driver->IsPlayer()) {
+ driver->bUsePedNodeSeek = true;
+ driver->m_pLastPathNode = nil;
+ if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear
+ || driver->CharCreatedBy == MISSION_CHAR
+ || veh->VehicleCreatedBy == MISSION_VEHICLE) {
+ driver->bFleeAfterExitingCar = true;
+ } else {
+ driver->bGonnaKillTheCarJacker = true;
+ veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped);
+
+ if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ }
+ }
+ if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY)
+ && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) {
+ veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ veh->pDriver->Say(SOUND_PED_CAR_JACKED);
+#ifdef VC_PED_PORTS
+ veh->pDriver->SetRadioStation();
+#endif
+ } else {
+ ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+ }
+ }
+ }
+ 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;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS;
+ } else {
+ animToPlay = ANIM_CAR_CLOSEDOOR_RHS;
+ }
+ } else if (isVan) {
+ animToPlay = ANIM_VAN_CLOSE_L;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS;
+ } else {
+ animToPlay = ANIM_CAR_CLOSEDOOR_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
+ }
+}
+
+void
+CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle);
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ if (ped->EnteringCar()) {
+ bool isLow = !!veh->bLowVehicle;
+
+ if (!veh->bIsBus)
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f);
+
+ eDoors door;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;
+ case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;
+ case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;
+ case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;
+ default: assert(0);
+ }
+
+ if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)
+ veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK);
+
+ if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) {
+ PedSetInCarCB(nil, ped);
+ } else if (ped->m_vehEnterType == CAR_DOOR_RF
+ && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF ||
+ (veh->pDriver != nil &&
+ (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR
+#ifdef VC_PED_PORTS
+ && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE
+#endif
+ || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) {
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ || ped->m_nPedState == PED_CARJACK
+#endif
+ )
+ veh->bIsBeingCarJacked = false;
+
+ ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+ PedSetInCarCB(nil, ped);
+
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ if (!ped->IsPlayer())
+ ped->bFleeAfterExitingCar = true;
+
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+
+ } else {
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);
+ }
+ } else {
+#ifdef VC_PED_PORTS
+ if (ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+ }
+}
+
+void
+CPed::SetFormation(eFormation type)
+{
+ // FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7.
+ // To not change the behaviour, range in here tweaked by 1 with the use of enum.
+
+ switch (m_pedFormation) {
+ case FORMATION_REAR:
+ case FORMATION_REAR_LEFT:
+ case FORMATION_REAR_RIGHT:
+ case FORMATION_FRONT_LEFT:
+ case FORMATION_FRONT_RIGHT:
+ case FORMATION_LEFT:
+ case FORMATION_RIGHT:
+ case FORMATION_FRONT:
+ break;
+ default:
+ Error("Unknown formation type, PedAI.cpp");
+ break;
+ }
+ m_pedFormation = type;
+}
+
+CVector
+CPed::GetFormationPosition(void)
+{
+ if (m_pedInObjective->m_nPedState == PED_DEAD) {
+ if (!m_pedInObjective->m_pedInObjective) {
+ m_pedInObjective = nil;
+ return GetPosition();
+ }
+ m_pedInObjective = m_pedInObjective->m_pedInObjective;
+ }
+
+ CVector formationOffset;
+ switch (m_pedFormation) {
+ case FORMATION_REAR:
+ formationOffset = CVector(0.0f, -1.5f, 0.0f);
+ break;
+ case FORMATION_REAR_LEFT:
+ formationOffset = CVector(-1.5f, -1.5f, 0.0f);
+ break;
+ case FORMATION_REAR_RIGHT:
+ formationOffset = CVector(1.5f, -1.5f, 0.0f);
+ break;
+ case FORMATION_FRONT_LEFT:
+ formationOffset = CVector(-1.5f, 1.5f, 0.0f);
+ break;
+ case FORMATION_FRONT_RIGHT:
+ formationOffset = CVector(1.5f, 1.5f, 0.0f);
+ break;
+ case FORMATION_LEFT:
+ formationOffset = CVector(-1.5f, 0.0f, 0.0f);
+ break;
+ case FORMATION_RIGHT:
+ formationOffset = CVector(1.5f, 0.0f, 0.0f);
+ break;
+ case FORMATION_FRONT:
+ formationOffset = CVector(0.0f, 1.5f, 0.0f);
+ break;
+ default:
+ formationOffset = CVector(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ return formationOffset + m_pedInObjective->GetPosition();
+}
+
+void
+CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!veh) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+#ifdef VC_PED_PORTS
+ CVector posForZ = ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posForZ);
+ if (ped->GetPosition().z - 0.5f > posForZ.z) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+#endif
+ veh->m_nStaticFrames = 0;
+ veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f);
+ veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f);
+ if (!veh->bIsBus)
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f);
+
+ /*
+ // Duplicate and only in PC for some reason
+ if (!veh) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+ */
+ eDoors door;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ door = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+ bool closeDoor = !veh->IsDoorMissing(door);
+
+ int padNo;
+ if (ped->IsPlayer()) {
+
+ // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
+ switch (ped->m_nPedType) {
+ case PEDTYPE_PLAYER1:
+ padNo = 0;
+ break;
+ case PEDTYPE_PLAYER2:
+ padNo = 1;
+ break;
+ case PEDTYPE_PLAYER3:
+ padNo = 2;
+ break;
+ case PEDTYPE_PLAYER4:
+ padNo = 3;
+ break;
+ }
+ CPad* pad = CPad::GetPad(padNo);
+ bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225;
+ if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS
+ && (pad->GetTarget()
+ || pad->NewState.LeftStickX
+ || pad->NewState.LeftStickY
+ || pad->NewState.DPadUp
+ || pad->NewState.DPadDown
+ || pad->NewState.DPadLeft
+ || pad->NewState.DPadRight)
+ || veh->bIsBus
+ || veh->m_pCarFire
+ || engineIsIntact) {
+ closeDoor = false;
+ }
+ }
+
+#ifdef VC_PED_PORTS
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
+ closeDoor = false;
+#endif
+
+ if (!closeDoor) {
+ if (!veh->IsDoorMissing(door) && !veh->bIsBus) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+
+ if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) {
+ // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa?
+ if (!veh->IsDoorMissing(door))
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
+ } else {
+ switch (door) {
+ case DOOR_FRONT_LEFT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
+ break;
+ case DOOR_FRONT_RIGHT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
+ break;
+ case DOOR_REAR_LEFT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
+ break;
+ case DOOR_REAR_RIGHT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);
+ return;
+}
+
+void
+CPed::LineUpPedWithCar(PedLineUpPhase phase)
+{
+ bool vehIsUpsideDown = false;
+ int vehAnim;
+ float seatPosMult = 0.0f;
+ float currentZ;
+ float adjustedTimeStep;
+
+ if (CReplay::IsPlayingBack())
+ return;
+
+ if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) {
+ SetPedPositionInCar();
+ return;
+ }
+ bChangedSeat = true;
+ }
+ if (phase == LINE_UP_TO_CAR_START) {
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ CVehicle *veh = m_pMyVehicle;
+
+ // Not quite right, IsUpsideDown func. checks for <= -0.9f.
+ if (veh->GetUp().z <= -0.8f)
+ vehIsUpsideDown = true;
+
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (vehIsUpsideDown) {
+ m_fRotationDest = -PI + veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (vehIsUpsideDown) {
+ m_fRotationDest = veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = -0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ } else {
+ // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional.
+
+ if (vehIsUpsideDown) {
+ m_fRotationDest = veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ }
+
+ if (!bInVehicle)
+ seatPosMult = 1.0f;
+
+#ifdef VC_PED_PORTS
+ bool multExtractedFromAnim = false;
+ bool multExtractedFromAnimBus = false;
+ float zBlend;
+#endif
+ if (m_pVehicleAnim) {
+ vehAnim = m_pVehicleAnim->animId;
+
+ switch (vehAnim) {
+ case ANIM_CAR_JACKED_RHS:
+ case ANIM_CAR_LJACKED_RHS:
+ case ANIM_CAR_JACKED_LHS:
+ case ANIM_CAR_LJACKED_LHS:
+ case ANIM_VAN_GETIN_L:
+ 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);
+ // fall through
+#endif
+ case ANIM_CAR_QJACKED:
+ case ANIM_CAR_GETOUT_LHS:
+ case ANIM_CAR_GETOUT_LOW_LHS:
+ case ANIM_CAR_GETOUT_RHS:
+ case ANIM_CAR_GETOUT_LOW_RHS:
+#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);
+ }
+ // fall through
+#endif
+ case ANIM_CAR_CRAWLOUT_RHS:
+ case ANIM_CAR_CRAWLOUT_RHS2:
+ case ANIM_VAN_GETOUT_L:
+ case ANIM_VAN_GETOUT:
+ seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength;
+ 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;
+ }
+ // fall through
+#endif
+ case ANIM_CAR_QJACK:
+ case ANIM_CAR_GETIN_LOW_LHS:
+ case ANIM_CAR_GETIN_LOW_RHS:
+ case ANIM_DRIVE_BOAT:
+ seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
+ break;
+ case ANIM_CAR_CLOSEDOOR_LHS:
+ case ANIM_CAR_CLOSEDOOR_LOW_LHS:
+ case ANIM_CAR_CLOSEDOOR_RHS:
+ case ANIM_CAR_CLOSEDOOR_LOW_RHS:
+ case ANIM_CAR_SHUFFLE_RHS:
+ case ANIM_CAR_LSHUFFLE_RHS:
+ seatPosMult = 0.0f;
+ break;
+ case ANIM_CAR_CLOSE_LHS:
+ case ANIM_CAR_CLOSE_RHS:
+ case ANIM_COACH_OPEN_L:
+ case ANIM_COACH_OPEN_R:
+ case ANIM_COACH_IN_L:
+ case ANIM_COACH_IN_R:
+ case ANIM_COACH_OUT_L:
+ seatPosMult = 1.0f;
+ break;
+ default:
+ break;
+ }
+ }
+
+ CVector neededPos;
+
+ if (phase == LINE_UP_TO_CAR_2) {
+ neededPos = GetPosition();
+ } else {
+ neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult);
+ }
+
+ CVector autoZPos = neededPos;
+
+ if (veh->bIsInWater) {
+ if (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown())
+ autoZPos.z += 1.0f;
+ } else {
+ CPedPlacement::FindZCoorForPed(&autoZPos);
+ }
+
+ if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) {
+ neededPos.z = GetPosition().z;
+
+ // Getting out
+ if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) {
+ float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep();
+
+ // If we're not in ground at next step, apply animation
+ if (neededPos.z + nextZSpeed >= autoZPos.z) {
+ m_vecMoveSpeed.z = nextZSpeed;
+ ApplyMoveSpeed();
+ // Removing below line breaks the animation
+ neededPos.z = GetPosition().z;
+ } else {
+ neededPos.z = autoZPos.z;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ if (autoZPos.z > neededPos.z) {
+#ifdef VC_PED_PORTS
+ if (multExtractedFromAnim) {
+ neededPos.z += (autoZPos.z - neededPos.z) * zBlend;
+ } else {
+#endif
+ currentZ = GetPosition().z;
+ if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) {
+ neededPos.z = autoZPos.z;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) {
+ adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
+
+ // Smoothly change ped position
+ neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep);
+ }
+#ifdef VC_PED_PORTS
+ }
+#endif
+ } else {
+ // We may need to raise up the ped
+ if (phase == LINE_UP_TO_CAR_START) {
+ currentZ = GetPosition().z;
+
+ if (neededPos.z > currentZ) {
+#ifdef VC_PED_PORTS
+ if (multExtractedFromAnimBus) {
+ neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ;
+ } else {
+#endif
+ if (m_pVehicleAnim &&
+ (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS
+ || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) {
+ adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
+
+ // Smoothly change ped position
+ neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;
+ } else if (EnteringCar()) {
+ neededPos.z = Max(currentZ, autoZPos.z);
+ }
+#ifdef VC_PED_PORTS
+ }
+#endif
+ }
+ }
+ }
+
+ bool stillGettingInOut = false;
+ if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)
+ stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat;
+
+ if (!stillGettingInOut) {
+ m_fRotationCur = m_fRotationDest;
+ } else {
+ float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f;
+
+ if (timeUntilStateChange <= 0.0f) {
+ m_vecOffsetSeek.x = 0.0f;
+ m_vecOffsetSeek.y = 0.0f;
+ }
+ m_vecOffsetSeek.z = 0.0f;
+
+ neededPos -= timeUntilStateChange * m_vecOffsetSeek;
+
+ if (PI + m_fRotationCur < limitedDest) {
+ limitedDest -= 2 * PI;
+ } else if (m_fRotationCur - PI > limitedDest) {
+ limitedDest += 2 * PI;
+ }
+ m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange);
+ }
+
+ if (seatPosMult > 0.2f || vehIsUpsideDown) {
+ SetPosition(neededPos);
+ SetHeading(m_fRotationCur);
+ } else {
+ CMatrix vehDoorMat(veh->GetMatrix());
+ vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f));
+ // VC couch anims are inverted, so they're fixing it here.
+ GetMatrix() = vehDoorMat;
+ }
+
+}
+
+void
+CPed::SetCarJack(CVehicle* car)
+{
+ uint8 doorFlag;
+ eDoors door;
+ CPed *pedInSeat = nil;
+
+ if (car->IsBoat())
+ return;
+
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ if (car->pPassengers[0]) {
+ pedInSeat = car->pPassengers[0];
+ } else if (m_nPedType == PEDTYPE_COP) {
+ pedInSeat = car->pDriver;
+ }
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ pedInSeat = car->pPassengers[2];
+ break;
+ case CAR_DOOR_LF:
+ doorFlag = CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_LEFT;
+ pedInSeat = car->pDriver;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_LEFT;
+ pedInSeat = car->pPassengers[1];
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+
+ if(car->bIsBus)
+ 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)))
+ if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
+ if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
+ if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
+ if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))
+ SetCarJack_AllClear(car, m_vehEnterType, doorFlag);
+}
+
+void
+CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+{
+ RemoveWeaponWhenEnteringVehicle();
+ if (m_nPedState != PED_SEEK_CAR)
+ SetStoredState();
+
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
+ m_nPedState = PED_CARJACK;
+ car->bIsBeingCarJacked = true;
+ m_pMyVehicle = (CVehicle*)m_pSeekTarget;
+ m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);
+ ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
+
+ Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING);
+ CVector carEnterPos;
+ carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+
+ car->m_nGettingInFlags |= doorFlag;
+ m_vecOffsetSeek = carEnterPos - GetPosition();
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
+ float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z);
+ bUsesCollision = false;
+
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f);
+
+ m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+}
+
+void
+CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)
+{
+ if (m_nPedState == PED_DRAG_FROM_CAR)
+ return;
+
+ bUsesCollision = false;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_nLastPedState = PED_IDLE;
+ SetMoveState(PEDMOVE_STILL);
+ m_pSeekTarget = veh;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ m_vehEnterType = vehEnterType;
+ if (m_vehEnterType == CAR_DOOR_LF) {
+ if (veh->pDriver && veh->pDriver->IsPlayer())
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ else
+ veh->SetStatus(STATUS_ABANDONED);
+ }
+ RemoveInCarAnims();
+ SetMoveState(PEDMOVE_NONE);
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ m_pVehicleAnim = nil;
+ m_nPedState = PED_DRAG_FROM_CAR;
+ bChangedSeat = false;
+ bWillBeQuickJacked = quickJack;
+
+ SetHeading(m_fRotationCur);
+
+ Say(SOUND_PED_CAR_JACKED);
+ SetRadioStation();
+ veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType);
+}
+
+void
+CPed::BeingDraggedFromCar(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId enterAnim;
+ bool dontRunAnim = false;
+ PedLineUpPhase lineUpType;
+
+ if (!m_pVehicleAnim) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO);
+ }
+ }
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (bWillBeQuickJacked) {
+ enterAnim = ANIM_CAR_QJACKED;
+ } else if (m_pMyVehicle->bLowVehicle) {
+ enterAnim = ANIM_CAR_LJACKED_LHS;
+ } else {
+ enterAnim = ANIM_CAR_JACKED_LHS;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (m_pMyVehicle->bLowVehicle)
+ enterAnim = ANIM_CAR_LJACKED_RHS;
+ else
+ enterAnim = ANIM_CAR_JACKED_RHS;
+ } else
+ dontRunAnim = true;
+
+
+ if (!dontRunAnim)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim);
+
+ m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
+ lineUpType = LINE_UP_TO_CAR_START;
+ } else if (m_pVehicleAnim->currentTime <= 1.4f) {
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ lineUpType = LINE_UP_TO_CAR_START;
+ } else {
+ lineUpType = LINE_UP_TO_CAR_2;
+ }
+
+ LineUpPedWithCar(lineUpType);
+#ifdef VC_PED_PORTS
+ if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f);
+ }
+ }
+#endif
+}
+
+void
+CPed::SetEnterCar(CVehicle *car, uint32 unused)
+{
+ if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
+ RestorePreviousState();
+ RestorePreviousObjective();
+ } else {
+ uint8 doorFlag;
+ eDoors door;
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ doorFlag = CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_LEFT;
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+ if (!IsPedInControl() || m_fHealth <= 0.0f
+ || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags
+ || car->bIsBeingCarJacked || m_pVehicleAnim
+ || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))
+ SetMoveState(PEDMOVE_STILL);
+ else
+ SetEnterCar_AllClear(car, m_vehEnterType, doorFlag);
+ }
+}
+
+void
+CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+{
+ float zDiff = 0.0f;
+ RemoveWeaponWhenEnteringVehicle();
+ car->m_nGettingInFlags |= doorFlag;
+ bVehEnterDoorIsBlocked = false;
+ if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)
+ SetStoredState();
+
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ m_vehEnterType = doorNode;
+ m_nPedState = PED_ENTER_CAR;
+ if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) {
+ car->bIsBeingCarJacked = true;
+ }
+
+ m_pMyVehicle = (CVehicle*)m_pSeekTarget;
+ m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
+ ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
+ bUsesCollision = false;
+ CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+
+ // Because buses have stairs
+ if (!m_pMyVehicle->bIsBus)
+ zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z);
+
+ 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)
+ 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 {
+ if (zDiff > 4.4f) {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
+
+ } else {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
+ }
+ m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+ car->AutoPilot.m_nCruiseSpeed = 0;
+ }
+}
+
+void
+CPed::EnterCar(void)
+{
+ if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {
+ CVehicle *veh = (CVehicle*)m_pSeekTarget;
+
+ // Not used.
+ // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType);
+
+ if (veh->CanPedOpenLocks(this)) {
+ if (m_vehEnterType && m_pVehicleAnim) {
+ veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime);
+ }
+ }
+ bIsInTheAir = false;
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ } else {
+ QuitEnteringCar();
+ SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ }
+}
+
+void
+CPed::QuitEnteringCar(void)
+{
+ CVehicle *veh = m_pMyVehicle;
+ if (m_pVehicleAnim)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+
+ RestartNonPartialAnims();
+
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE))
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+
+ if (veh) {
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
+ veh->bIsBeingCarJacked = false;
+
+ if (veh->m_nNumGettingIn != 0)
+ veh->m_nNumGettingIn--;
+
+#ifdef VC_PED_PORTS
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+ RestorePreviousObjective();
+#endif
+
+ veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType);
+ }
+
+ bUsesCollision = true;
+
+ ReplaceWeaponWhenExitingVehicle();
+
+ if (DyingOrDead()) {
+ if (m_pVehicleAnim) {
+ m_pVehicleAnim->blendDelta = -4.0f;
+ m_pVehicleAnim->flags |= ASSOC_DELETEFADEDOUT;
+ m_pVehicleAnim->flags &= ~ASSOC_RUNNING;
+ }
+ } else
+ SetIdle();
+
+ m_pVehicleAnim = nil;
+
+ if (veh) {
+#ifdef VC_PED_PORTS
+ if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE)
+#else
+ if (veh->AutoPilot.m_nCruiseSpeed == 0)
+#endif
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+ }
+}
+
+void
+AddYardieDoorSmoke(CVehicle *veh, uint32 doorNode)
+{
+ eDoors door;
+ switch (doorNode) {
+ case CAR_DOOR_RF:
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ door = DOOR_FRONT_LEFT;
+ break;
+ default:
+ break;
+ }
+
+ if (!veh->IsDoorMissing(door) && veh->IsComponentPresent(doorNode)) {
+ CVector pos;
+#ifdef FIX_BUGS
+ veh->GetComponentWorldPosition(doorNode, pos);
+#else
+ veh->GetComponentWorldPosition(CAR_DOOR_LF, pos);
+#endif
+ CParticle::AddYardieDoorSmoke(pos, veh->GetMatrix());
+ }
+}
+
+// Seperate function in VC, more logical. Not sure is it inlined in III.
+void
+CPed::SetExitBoat(CVehicle *boat)
+{
+#ifndef VC_PED_PORTS
+ m_nPedState = PED_IDLE;
+ CVector firstPos = GetPosition();
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
+ m_vehEnterType = CAR_DOOR_RF;
+ m_nPedState = PED_EXIT_CAR;
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ }
+ SetPosition(firstPos);
+ SetMoveState(PEDMOVE_STILL);
+ m_vecMoveSpeed = boat->m_vecMoveSpeed;
+ bTryingToReachDryLand = true;
+#else
+ m_nPedState = PED_IDLE;
+ CVector newPos = GetPosition();
+ RemoveInCarAnims();
+ CColModel* boatCol = boat->GetColModel();
+ if (boat->IsUpsideDown()) {
+ newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z };
+ newPos = boat->GetMatrix() * newPos;
+ newPos.z += 1.0f;
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ m_pCurrentPhysSurface = boat;
+ } else {
+/* if (boat->m_modelIndex != MI_SKIMMER || boat->bIsInWater) {
+ if (boat->m_modelIndex == MI_SKIMMER)
+ newPos.z += 2.0f
+*/
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ m_pCurrentPhysSurface = boat;
+ CColPoint foundCol;
+ CEntity *foundEnt = nil;
+ if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil))
+ newPos.z = FEET_OFFSET + foundCol.point.z;
+/* // VC specific
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ SetMoveState(PEDMOVE_STILL);
+ bTryingToReachDryLand = true;
+ float upMult = 1.04f + boatCol->boundingBox.min.z;
+ float rightMult = 0.6f * boatCol->boundingBox.max.x;
+ newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition();
+ GetPosition() = newPos;
+ if (m_pMyVehicle) {
+ PositionPedOutOfCollision();
+ } else {
+ m_pMyVehicle = boat;
+ PositionPedOutOfCollision();
+ m_pMyVehicle = nil;
+ }
+ return;
+ }
+*/ }
+ SetPosition(newPos);
+ SetMoveState(PEDMOVE_STILL);
+ m_vecMoveSpeed = boat->m_vecMoveSpeed;
+#endif
+ // Not there in VC.
+ CWaterLevel::FreeBoatWakeArray();
+}
+
+// wantedDoorNode = 0 means that func. will determine it
+void
+CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
+{
+ uint32 optedDoorNode = wantedDoorNode;
+ bool teleportNeeded = false;
+ bool isLow = !!veh->bLowVehicle;
+ if (!veh->CanPedExitCar()) {
+ if (veh->pDriver && !veh->pDriver->IsPlayer()) {
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ veh->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
+ return;
+ }
+
+ if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
+ return;
+
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ if (wantedDoorNode == 0) {
+ optedDoorNode = CAR_DOOR_LF;
+ if (!veh->bIsBus) {
+ if (veh->pDriver == this) {
+ optedDoorNode = CAR_DOOR_LF;
+ } else if (veh->pPassengers[0] == this) {
+ optedDoorNode = CAR_DOOR_RF;
+ } else if (veh->pPassengers[1] == this) {
+ optedDoorNode = CAR_DOOR_LR;
+ } else if (veh->pPassengers[2] == this) {
+ optedDoorNode = CAR_DOOR_RR;
+ } else {
+ for (int i = 3; i < veh->m_nNumMaxPassengers; ++i) {
+ if (veh->pPassengers[i] == this) {
+ if (i & 1)
+ optedDoorNode = CAR_DOOR_RR;
+ else
+ optedDoorNode = CAR_DOOR_LR;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ bool someoneExitsFromOurExitDoor = false;
+ bool someoneEntersFromOurExitDoor = false;
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RF)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_RR:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RR)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_LF:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LF)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_LR:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LR)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ default:
+ break;
+ }
+ if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) {
+ RestorePreviousObjective();
+ return;
+ }
+ if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) {
+ // Again, unused...
+ // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
+ bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);
+ if (veh->IsOnItsSide()) {
+ teleportNeeded = true;
+ } else if (!thereIsRoom) {
+ bool trySideSeat = false;
+ CPed *pedOnSideSeat = nil;
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ if (veh->pDriver || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) {
+ pedOnSideSeat = veh->pDriver;
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_LF;
+
+ break;
+ case CAR_DOOR_RR:
+ if (veh->pPassengers[1] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
+ pedOnSideSeat = veh->pPassengers[1];
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_LR;
+
+ break;
+ case CAR_DOOR_LF:
+ if (veh->pPassengers[0] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
+ pedOnSideSeat = veh->pPassengers[0];
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_RF;
+
+ break;
+ case CAR_DOOR_LR:
+ if (veh->pPassengers[2] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
+ pedOnSideSeat = (CPed*)veh->pPassengers[2];
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_RR;
+
+ break;
+ default:
+ break;
+ }
+ if (trySideSeat) {
+ if (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR)
+ return;
+
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ optedDoorNode = CAR_DOOR_LF;
+ break;
+ case CAR_DOOR_RR:
+ optedDoorNode = CAR_DOOR_LR;
+ break;
+ case CAR_DOOR_LF:
+ optedDoorNode = CAR_DOOR_RF;
+ break;
+ case CAR_DOOR_LR:
+ optedDoorNode = CAR_DOOR_RR;
+ break;
+ default:
+ break;
+ }
+ }
+ // ...
+ // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
+ if (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) {
+ if (!IsPlayer() && CharCreatedBy != MISSION_CHAR)
+ return;
+
+ teleportNeeded = true;
+ }
+ }
+ if (m_nPedState == PED_FLEE_POS) {
+ m_nLastPedState = PED_FLEE_POS;
+ m_nPrevMoveState = PEDMOVE_RUN;
+ SetMoveState(PEDMOVE_SPRINT);
+ } else {
+ m_nLastPedState = PED_IDLE;
+ m_nPrevMoveState = PEDMOVE_STILL;
+ SetMoveState(PEDMOVE_STILL);
+ }
+
+ ReplaceWeaponWhenExitingVehicle();
+ bUsesCollision = false;
+ m_pSeekTarget = veh;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_vehEnterType = optedDoorNode;
+ m_nPedState = PED_EXIT_CAR;
+ if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+ SetMoveState(PEDMOVE_NONE);
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ RemoveInCarAnims();
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (teleportNeeded) {
+ PedSetOutCarCB(nil, this);
+
+ // This is same code with CPedPlacement::FindZCoorForPed, except we start from z + 1.5 and also check vehicles.
+ float zForPed;
+ float startZ = GetPosition().z - 100.0f;
+ float foundColZ = -100.0f;
+ float foundColZ2 = -100.0f;
+ CColPoint foundCol;
+ CEntity* foundEnt;
+
+ CVector vec = GetPosition();
+ vec.z += 1.5f;
+
+ if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
+ foundColZ = foundCol.point.z;
+
+ // Adjust coords and do a second test
+ vec.x += 0.1f;
+ vec.y += 0.1f;
+
+ if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
+ foundColZ2 = foundCol.point.z;
+
+ zForPed = Max(foundColZ, foundColZ2);
+
+ if (zForPed > -99.0f)
+ GetMatrix().GetPosition().z = FEET_OFFSET + zForPed;
+ } else {
+ if (veh->GetUp().z > -0.8f) {
+ bool addDoorSmoke = false;
+ if (veh->GetModelIndex() == MI_YARDIE)
+ addDoorSmoke = true;
+
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ if (veh->bIsBus) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
+ } else {
+ if (isLow)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
+ else
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+
+ if (addDoorSmoke)
+ AddYardieDoorSmoke(veh, CAR_DOOR_RF);
+ }
+ break;
+ case CAR_DOOR_RR:
+ if (veh->bIsVan) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT);
+ } else if (isLow) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
+ } else {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+ }
+ break;
+ case CAR_DOOR_LF:
+ if (veh->bIsBus) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
+ } else {
+ if (isLow)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
+ else
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+
+ if (addDoorSmoke)
+ AddYardieDoorSmoke(veh, CAR_DOOR_LF);
+ }
+ break;
+ case CAR_DOOR_LR:
+ if (veh->bIsVan) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L);
+ } else if (isLow) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
+ } else {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+ }
+ break;
+ default:
+ break;
+ }
+ if (!bBusJacked) {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RF;
+ break;
+ case CAR_DOOR_RR:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RR;
+ break;
+ case CAR_DOOR_LF:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;
+ break;
+ case CAR_DOOR_LR:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LR;
+ break;
+ default:
+ break;
+ }
+ }
+ m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);
+ } else {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2);
+ } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS);
+ }
+ m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
+ }
+ }
+ bChangedSeat = false;
+ if (veh->bIsBus)
+ bRenderPedInCar = true;
+
+ SetRadioStation();
+ if (veh->pDriver == this) {
+ if (IsPlayer())
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ else
+ veh->SetStatus(STATUS_ABANDONED);
+ }
+ }
+}
+
+void
+CPed::ExitCar(void)
+{
+ if (!m_pVehicleAnim)
+ return;
+
+ AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId;
+ float animTime = m_pVehicleAnim->currentTime;
+
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime);
+
+ if (m_pSeekTarget) {
+ // Car is upside down
+ if (m_pMyVehicle->GetUp().z > -0.8f) {
+ if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f)
+ LineUpPedWithCar(LINE_UP_TO_CAR_END);
+ else
+ LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START));
+ } else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_END);
+ }
+ }
+
+ // If there is someone in front of the door, make him fall while we exit.
+ if (m_nPedState == PED_EXIT_CAR) {
+ CPed *foundPed = nil;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < 0.04f) {
+ foundPed = m_nearPeds[i];
+ break;
+ }
+ }
+ if (foundPed && animTime > 0.4f && foundPed->IsPedInControl())
+ foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1);
+ }
+}
+
+// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it.
+CVector
+CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
+{
+ CVector localPos;
+ CVector vehDoorPos;
+
+ localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f);
+ vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition();
+
+/*
+ // Not used.
+ CVector localVehDoorOffset;
+
+ if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) {
+ localVehDoorOffset = vecPedVanRearDoorAnimOffset;
+ } else {
+ if (veh->bIsLow) {
+ localVehDoorOffset = vecPedCarDoorLoAnimOffset;
+ } else {
+ localVehDoorOffset = vecPedCarDoorAnimOffset;
+ }
+ }
+
+ vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition();
+*/
+ return vehDoorPos;
+}
+
+void
+CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)
+{
+ CVector *enterOffset = nil;
+ if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver
+ || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0]
+ || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1]
+ || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2])
+ {
+ enterOffset = &vecPedQuickDraggedOutCarAnimOffset;
+ }
+
+ CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF);
+ CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+
+ // Left front door is closer
+ if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) {
+
+ if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = rfPos;
+ }
+ } else {
+
+ if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+
+ CPed *rfPassenger = veh->pPassengers[0];
+ if (rfPassenger && (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar ||
+ veh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)
+ || (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = rfPos;
+ }
+ } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ }
+ }
+}
+
+bool
+CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen)
+{
+ CVector rfPos, lrPos, rrPos;
+ bool canEnter = false;
+
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
+
+ switch (veh->GetModelIndex()) {
+ case MI_BUS:
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+ return true;
+ case MI_RHINO:
+ default:
+ break;
+ }
+
+ CVector2D rfPosDist(999.0f, 999.0f);
+ CVector2D lrPosDist(999.0f, 999.0f);
+ CVector2D rrPosDist(999.0f, 999.0f);
+
+ if (!veh->pPassengers[0]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {
+
+ rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+ canEnter = true;
+ rfPosDist = rfPos - GetPosition();
+ }
+ if (vehModel->m_numDoors == 4) {
+ if (!veh->pPassengers[1]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {
+ lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);
+ canEnter = true;
+ lrPosDist = lrPos - GetPosition();
+ }
+ if (!veh->pPassengers[2]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {
+ rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);
+ canEnter = true;
+ rrPosDist = rrPos - GetPosition();
+ }
+
+ // When the door we should enter is blocked by some object.
+ if (!canEnter)
+ veh->ShufflePassengersToMakeSpace();
+ }
+
+ CVector2D nextToCompare = rfPosDist;
+ posToOpen = rfPos;
+ m_vehEnterType = CAR_DOOR_RF;
+ if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
+ m_vehEnterType = CAR_DOOR_LR;
+ posToOpen = lrPos;
+ nextToCompare = lrPosDist;
+ }
+
+ if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
+ m_vehEnterType = CAR_DOOR_RR;
+ posToOpen = rrPos;
+ }
+ return canEnter;
+}
+
+void
+CPed::GoToNearestDoor(CVehicle *veh)
+{
+ CVector posToOpen;
+ GetNearestDoor(veh, posToOpen);
+ SetSeek(posToOpen, 0.5f);
+ SetMoveState(PEDMOVE_RUN);
+}
+
+void
+CPed::SetAnimOffsetForEnterOrExitVehicle(void)
+{
+ // FIX: If there were no translations on enter anims, there were overflows all over this function.
+
+ CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy;
+ CAnimBlendSequence *seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedDraggedOutCarAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedCarDoorAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedCarDoorLoAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedVanRearDoorAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_TRAIN_GETOUT)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedTrainDoorAnimOffset = lastFrame->translation;
+ }
+ }
+}
+
+void
+CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ CVector finalPos;
+ CVector draggedOutOffset;
+
+ CMatrix pedMat(ped->GetMatrix());
+ ped->bUsesCollision = true;
+ ped->RestartNonPartialAnims();
+ draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset;
+ if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
+ draggedOutOffset.x = -draggedOutOffset.x;
+
+ finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&finalPos);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(finalPos);
+
+ if (veh) {
+ ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI;
+ ped->m_fRotationCur = ped->m_fRotationDest;
+ ped->CalculateNewOrientation();
+
+ if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset))
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (!ped->CanSetPedState())
+ return;
+
+ ped->SetIdle();
+ if (veh) {
+ if (ped->bFleeAfterExitingCar) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(veh->GetPosition(), 14000);
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+ ped->bGonnaKillTheCarJacker = false;
+ if (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) {
+ if (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective);
+
+ } else {
+ CPed *driver = veh->pDriver;
+ if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
+ ped->SetFlee(veh->GetPosition(), 14000);
+ } else {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+ }
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear
+ && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE
+ && veh->pDriver && veh->pDriver->IsPlayer()
+ && !CTheScripts::IsPlayerOnAMission()) {
+
+#ifndef VC_PED_PORTS
+ if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) {
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver);
+ } else
+#endif
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+
+#ifdef VC_PED_PORTS
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear
+ && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE
+ && !veh->pDriver && FindPlayerPed()->m_carInObjective == veh
+ && !CTheScripts::IsPlayerOnAMission()) {
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+#endif
+ } else {
+ ped->SetFindPathAndFlee(veh->GetPosition(), 10000);
+ if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
+ ped->SetMoveState(PEDMOVE_SPRINT);
+ ped->Say(SOUND_PED_FLEE_SPRINT);
+ } else {
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ }
+ }
+ if (ped->m_nLastPedState == PED_IDLE)
+ ped->m_nLastPedState = PED_WANDER_PATH;
+}
+
+void
+CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ ped->bUsesCollision = true;
+ ped->RestartNonPartialAnims();
+ bool itsRearDoor = false;
+
+ if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
+ itsRearDoor = true;
+
+ CMatrix pedMat(ped->GetMatrix());
+ CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset));
+ posAfterBeingDragged += ped->GetPosition();
+#ifndef VC_PED_PORTS
+ posAfterBeingDragged.z += 1.0f;
+#endif
+ CPedPlacement::FindZCoorForPed(&posAfterBeingDragged);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posAfterBeingDragged);
+
+ if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) {
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (!ped->CanSetPedState())
+ return;
+
+ if (!ped->m_pMyVehicle) {
+ ped->SetIdle();
+ ped->SetGetUp();
+ return;
+ }
+
+ CPed *driver = ped->m_pMyVehicle->pDriver;
+
+ if (ped->IsPlayer()) {
+ ped->SetIdle();
+
+ } else if (ped->bFleeAfterExitingCar) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+ // Kill objective is already set at this point.
+
+ ped->bGonnaKillTheCarJacker = false;
+ if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) {
+ if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
+ ped->m_nPedState = PED_NONE;
+ ped->m_nLastPedState = PED_NONE;
+ ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
+ } else {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+ }
+ }
+
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
+ && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver
+ && driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) {
+
+#ifndef VC_PED_PORTS
+ if (CGeneral::GetRandomNumber() & 1)
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver);
+ else
+#endif
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+
+ } else {
+#ifdef VC_PED_PORTS
+ if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
+ && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver
+ && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission())
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+ else
+#endif
+ {
+ ped->m_nPedState = PED_NONE;
+ ped->m_nLastPedState = PED_NONE;
+ ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000);
+ }
+ }
+ ped->SetGetUp();
+}
+
+uint8
+CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos)
+{
+ GetNearestTrainPedPosition(train, doorPos);
+/*
+ // Not used.
+ CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex);
+ CMatrix trainMat = CMatrix(train->GetMatrix());
+
+ doorPos = trainModel->m_positions[m_vehEnterType];
+ doorPos.x -= 1.5f;
+ doorPos = Multiply3x3(trainMat, doorPos);
+ doorPos += train->GetPosition();
+*/
+ return 1;
+}
+
+uint8
+CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos)
+{
+ CVector enterStepOffset;
+ CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex());
+ CMatrix trainMat = CMatrix(train->GetMatrix());
+ CVector leftEntryPos, rightEntryPos, midEntryPos;
+ float distLeftEntry, distRightEntry, distMidEntry;
+
+ // enterStepOffset = vecPedCarDoorAnimOffset;
+ enterStepOffset = CVector(1.5f, 0.0f, 0.0f);
+
+ if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) {
+ distLeftEntry = 999.0f;
+ } else {
+ leftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset;
+ leftEntryPos = Multiply3x3(trainMat, leftEntryPos);
+ leftEntryPos += train->GetPosition();
+ distLeftEntry = (leftEntryPos - GetPosition()).Magnitude();
+ }
+
+ if (train->pPassengers[TRAIN_POS_MID_ENTRY]) {
+ distMidEntry = 999.0f;
+ } else {
+ midEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset;
+ midEntryPos = Multiply3x3(trainMat, midEntryPos);
+ midEntryPos += train->GetPosition();
+ distMidEntry = (midEntryPos - GetPosition()).Magnitude();
+ }
+
+ if (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) {
+ distRightEntry = 999.0f;
+ } else {
+ rightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset;
+ rightEntryPos = Multiply3x3(trainMat, rightEntryPos);
+ rightEntryPos += train->GetPosition();
+ distRightEntry = (rightEntryPos - GetPosition()).Magnitude();
+ }
+
+ if (distMidEntry < distLeftEntry) {
+ if (distMidEntry < distRightEntry) {
+ enterPos = midEntryPos;
+ m_vehEnterType = TRAIN_POS_MID_ENTRY;
+ } else {
+ enterPos = rightEntryPos;
+ m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ }
+ } else if (distRightEntry < distLeftEntry) {
+ enterPos = rightEntryPos;
+ m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ } else {
+ enterPos = leftEntryPos;
+ m_vehEnterType = TRAIN_POS_LEFT_ENTRY;
+ }
+
+ return 1;
+}
+
+void
+CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed *ped = (CPed*)arg;
+ CTrain *veh = (CTrain*)ped->m_pMyVehicle;
+
+ if (!veh)
+ return;
+
+ ped->bInVehicle = true;
+ ped->m_nPedState = PED_DRIVING;
+ ped->RestorePreviousObjective();
+ ped->SetMoveState(PEDMOVE_STILL);
+ veh->AddPassenger(ped);
+}
+
+void
+CPed::SetEnterTrain(CVehicle *train, uint32 unused)
+{
+ if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())
+ return;
+
+ /*
+ // Not used
+ CVector enterPos;
+ GetNearestTrainPedPosition(train, enterPos);
+ */
+ m_fRotationCur = train->GetForward().Heading() - HALFPI;
+ m_pMyVehicle = train;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+
+ m_nPedState = PED_ENTER_TRAIN;
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);
+ bUsesCollision = false;
+ LineUpPedWithTrain();
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ ((CPlayerPed*)this)->ClearAdrenaline();
+ }
+}
+
+void
+CPed::EnterTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::SetPedPositionInTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::LineUpPedWithTrain(void)
+{
+ CVector lineUpPos;
+ CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex());
+ CVector enterOffset(1.5f, 0.0f, -0.2f);
+
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;
+ m_fRotationDest = m_fRotationCur;
+
+ if (!bInVehicle) {
+ GetNearestTrainDoor(m_pMyVehicle, lineUpPos);
+ lineUpPos.z += 0.2f;
+ } else {
+ if (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset;
+
+ } else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset;
+
+ } else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset;
+ }
+ lineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos);
+ lineUpPos += m_pMyVehicle->GetPosition();
+ }
+
+ if (m_pVehicleAnim) {
+ float percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
+ lineUpPos += (GetPosition() - lineUpPos) * percentageLeft;
+ }
+
+ SetPosition(lineUpPos);
+ SetHeading(m_fRotationCur);
+}
+
+void
+CPed::SetExitTrain(CVehicle* train)
+{
+ if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())
+ return;
+
+ /*
+ // Not used
+ CVector exitPos;
+ GetNearestTrainPedPosition(train, exitPos);
+ */
+ m_nPedState = PED_EXIT_TRAIN;
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
+ bUsesCollision = false;
+ LineUpPedWithTrain();
+}
+
+void
+CPed::ExitTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->blendDelta = -1000.0f;
+
+ ped->bUsesCollision = true;
+ ped->m_pVehicleAnim = nil;
+ ped->bInVehicle = false;
+ ped->m_nPedState = PED_IDLE;
+ ped->RestorePreviousObjective();
+ ped->SetMoveState(PEDMOVE_STILL);
+
+ CMatrix pedMat(ped->GetMatrix());
+ ped->m_fRotationCur = HALFPI + veh->GetForward().Heading();
+ ped->m_fRotationDest = ped->m_fRotationCur;
+ CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset);
+ posAfterExit += ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posAfterExit);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posAfterExit);
+ ped->SetHeading(ped->m_fRotationCur);
+ veh->RemovePassenger(ped);
+}
+
+void
+CPed::RegisterThreatWithGangPeds(CEntity *attacker)
+{
+ CPed *attackerPed = nil;
+ if (attacker) {
+ if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ if (attacker->IsPed()) {
+ attackerPed = (CPed*)attacker;
+ } else {
+ if (!attacker->IsVehicle())
+ return;
+
+ attackerPed = ((CVehicle*)attacker)->pDriver;
+ if (!attackerPed)
+ return;
+ }
+
+ if (attackerPed && (attackerPed->IsPlayer() || attackerPed->IsGangMember())) {
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->IsPointerValid()) {
+ if (nearPed != this && nearPed->m_nPedType == m_nPedType)
+ nearPed->m_fearFlags |= CPedType::GetFlag(attackerPed->m_nPedType);
+ }
+ }
+ }
+ }
+ }
+
+ if (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) {
+ if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOYZ) {
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ if (lastVehicle > 8)
+ lastVehicle = 8;
+
+ for (int j = 0; j < lastVehicle; ++j) {
+ CVehicle *nearVeh = (CVehicle*) vehicles[j];
+
+ if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
+ CPed *nearVehDriver = nearVeh->pDriver;
+
+ if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType) {
+
+ if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
+ nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
+ nearVeh->SetStatus(STATUS_PHYSICS);
+ nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Some helper function which doesn't exist in og game.
+inline void
+SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3)
+{
+ for (int i = 0; i < node->numLinks; i++) {
+
+ CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];
+
+ if (testNode && testNode != closeNode && testNode != closeNode2) {
+ CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());
+ float dist = posDiff.MagnitudeSqr();
+
+ if (farDist.MagnitudeSqr() > dist) {
+
+ if (closeDist.MagnitudeSqr() <= dist) {
+ ped->m_pNextPathNode = closeNode;
+ closeDist = posDiff;
+ } else {
+ ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode);
+ farDist = posDiff;
+ }
+ }
+
+ if (--runCount > 0)
+ SelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount);
+ }
+ }
+}
+
+bool
+CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
+{
+ if (m_pNextPathNode || !bUsePedNodeSeek)
+ return false;
+
+ CVector ourPos = GetPosition();
+
+ int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f);
+
+ CVector seekObjPos = m_vecSeekPos;
+ seekObjPos.z += 1.0f;
+
+ if (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false))
+ return false;
+
+ m_pNextPathNode = nil;
+
+ CVector2D seekPosDist (m_vecSeekPos - ourPos);
+
+ CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId];
+ CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition());
+
+ SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil);
+
+ // Above function decided that going to the next node is more logical than seeking the object.
+ if (m_pNextPathNode) {
+
+ CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos;
+ if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
+ *bestCoords = m_pNextPathNode->GetPosition();
+ return true;
+ }
+ m_pNextPathNode = nil;
+ }
+
+ return false;
+}
+
+bool
+CPed::DuckAndCover(void)
+{
+ if (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer)
+ return false;
+
+ if (bKindaStayInSamePlace){
+
+ if (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) {
+ if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ }
+ if (!bIsAimingGun)
+ SetAimFlag(m_pedInObjective);
+
+ } else {
+ bCrouchWhenShooting = false;
+ bKindaStayInSamePlace = false;
+ bIsDucking = false;
+ bDuckAndCover = false;
+ m_headingRate = 10.0f;
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000);
+ if (m_pSeekTarget && m_pSeekTarget->IsVehicle())
+ ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--;
+ }
+ return false;
+ }
+
+ bool justDucked = false;
+ CVehicle *foundVeh = nil;
+ float maxDist = 225.0f;
+ bIsDucking = false;
+ bCrouchWhenShooting = false;
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle *veh = (CVehicle*) vehicles[i];
+ if (veh->m_vecMoveSpeed.Magnitude() <= 0.02f
+ && !veh->bIsBus
+ && !veh->bIsVan
+ && !veh->bIsBig
+ && veh->m_numPedsUseItAsCover < 3) {
+ float dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr();
+ if (dist < maxDist) {
+ maxDist = dist;
+ foundVeh = veh;
+ }
+ }
+ }
+ if (foundVeh) {
+ // Unused.
+ // CVector lfWheelPos, rfWheelPos;
+ // foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos);
+ // foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos);
+ CVector rightSide, leftSide;
+
+ // 3 persons can use the car as cover. Found the correct position for us.
+ if (foundVeh->m_numPedsUseItAsCover == 2) {
+ rightSide = CVector(1.5f, -0.5f, 0.0f);
+ leftSide = CVector(-1.5f, -0.5f, 0.0f);
+ } else if (foundVeh->m_numPedsUseItAsCover == 1) {
+ rightSide = CVector(1.5f, 0.5f, 0.0f);
+ leftSide = CVector(-1.5f, 0.5f, 0.0f);
+ } else if (foundVeh->m_numPedsUseItAsCover == 0) {
+ rightSide = CVector(1.5f, 0.0f, 0.0f);
+ leftSide = CVector(-1.5f, 0.0f, 0.0f);
+ }
+
+ CMatrix vehMatrix(foundVeh->GetMatrix());
+ CVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition();
+
+ CVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition();
+
+ CVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide;
+ CVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide;
+
+ CVector duckPos;
+ if (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr())
+ duckPos = duckAtLeftSide;
+ else
+ duckPos = duckAtRightSide;
+
+ if (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false)
+ && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) {
+ SetSeek(duckPos, 1.0f);
+ m_headingRate = 15.0f;
+ bIsRunning = true;
+ bDuckAndCover = true;
+ justDucked = true;
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500;
+ if (foundVeh->bIsLawEnforcer)
+ m_carInObjective = foundVeh;
+
+ // BUG? Shouldn't we register the reference?
+ m_pSeekTarget = foundVeh;
+ ClearPointGunAt();
+ } else {
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000);
+ bDuckAndCover = false;
+ }
+ } else {
+ bDuckAndCover = false;
+ }
+ }
+
+ if (!justDucked && !bDuckAndCover)
+ return false;
+
+ if (!Seek())
+ return true;
+
+ bKindaStayInSamePlace = true;
+ bDuckAndCover = false;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ if (m_pSeekTarget && m_pSeekTarget->IsVehicle())
+ ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++;
+
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ }
+
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000);
+ return false;
+}
+
+CVector
+CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
+{
+ CVector doorPos;
+ CMatrix vehMat(veh->GetMatrix());
+
+ doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));
+
+ return veh->GetPosition() + doorPos;
+}
+
+CVector
+CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult)
+{
+ CVehicleModelInfo *vehModel;
+ CVector vehDoorPos;
+ CVector vehDoorOffset;
+ float seatOffset;
+
+ vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
+ if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {
+ seatOffset = 0.0f;
+ vehDoorOffset = vecPedVanRearDoorAnimOffset;
+ } else {
+ seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult;
+ if (veh->bLowVehicle) {
+ vehDoorOffset = vecPedCarDoorLoAnimOffset;
+ } else {
+ vehDoorOffset = vecPedCarDoorAnimOffset;
+ }
+ }
+
+ switch (component) {
+ case CAR_DOOR_RF:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorPos.x += seatOffset;
+ vehDoorOffset.x = -vehDoorOffset.x;
+ break;
+
+ case CAR_DOOR_RR:
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ vehDoorPos.x += seatOffset;
+ vehDoorOffset.x = -vehDoorOffset.x;
+ break;
+
+ case CAR_DOOR_LF:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorPos.x = -(vehDoorPos.x + seatOffset);
+ break;
+
+ case CAR_DOOR_LR:
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ vehDoorPos.x = -(vehDoorPos.x + seatOffset);
+ break;
+
+ default:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorOffset = CVector(0.0f, 0.0f, 0.0f);
+ }
+ return vehDoorPos - vehDoorOffset;
+}
+
+void
+CPed::SetDuck(uint32 time)
+{
+ if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer)
+ 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;
+ }
+ } else {
+ CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
+ bIsDucking = true;
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ }
+}
+
+void
+CPed::Duck(void)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
+ ClearDuck();
+}
+
+void
+CPed::ClearDuck(void)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
+
+ if (!animAssoc) {
+ bIsDucking = false;
+ return;
+ }
+ }
+
+ if (!bCrouchWhenShooting)
+ return;
+
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN)
+ return;
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
+ if (!animAssoc || animAssoc->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ }
+}
+
+void
+CPed::InformMyGangOfAttack(CEntity *attacker)
+{
+ CPed *attackerPed;
+
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)
+ return;
+
+ if (attacker->IsPed()) {
+ attackerPed = (CPed*)attacker;
+ } else {
+ if (!attacker->IsVehicle())
+ return;
+
+ attackerPed = ((CVehicle*)attacker)->pDriver;
+ if (!attackerPed)
+ return;
+ }
+
+ if (attackerPed->m_nPedType == PEDTYPE_COP)
+ return;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed && nearPed != this) {
+ CPed *leader = nearPed->m_leader;
+ if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper)
+ {
+ nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed);
+ nearPed->SetObjectiveTimer(30000);
+ }
+ }
+ }
+}
+
+void
+CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle);
+
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (veh->bLowVehicle) {
+ veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR_LOW, 1.0f);
+ } else {
+ veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f);
+ }
+
+ veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF;
+
+ if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING)
+ veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK);
+}
+
+void
+CPed::SetSeekBoatPosition(CVehicle *boat)
+{
+ if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ || !IsPedInControl()
+#endif
+ )
+ return;
+
+ SetStoredState();
+ m_carInObjective = boat;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_pMyVehicle = boat;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_distanceToCountSeekDone = 0.5f;
+ m_nPedState = PED_SEEK_IN_BOAT;
+}
+
+void
+CPed::SeekBoatPosition(void)
+{
+ if (m_carInObjective && !m_carInObjective->pDriver) {
+ CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo();
+
+ CVector enterOffset;
+ enterOffset = boatModel->GetFrontSeatPosn();
+ enterOffset.x = 0.0f;
+ CMatrix boatMat(m_carInObjective->GetMatrix());
+ SetMoveState(PEDMOVE_WALK);
+ m_vecSeekPos = boatMat * enterOffset;
+ if (Seek()) {
+ // We arrived to the boat
+ m_vehEnterType = 0;
+ SetEnterCar(m_carInObjective, 0);
+ }
+ } else
+ RestorePreviousState();
+}
+
+bool
+CPed::IsRoomToBeCarJacked(void)
+{
+ if (!m_pMyVehicle)
+ return false;
+
+ CVector offset;
+ if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) {
+ offset = vecPedDraggedOutCarAnimOffset;
+ } else {
+ offset = vecPedQuickDraggedOutCarAnimOffset;
+ }
+
+ offset.z = 0.0f;
+ if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) {
+ return true;
+ }
+
+ return false;
+}
+
+void
+CPed::RemoveInCarAnims(void)
+{
+ if (!IsPlayer())
+ return;
+
+ 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;
+ }
+
+#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;
+}
+
+bool
+CPed::PositionPedOutOfCollision(void)
+{
+ CVehicle *veh;
+ CVector posNearVeh;
+ CVector posSomewhereClose;
+ bool putNearVeh = false;
+ bool putSomewhereClose = false;
+ int smallestDistNearVeh = 999;
+ int smallestDistSomewhereClose = 999;
+
+ if (!m_pMyVehicle)
+ return false;
+
+ CVector vehPos = m_pMyVehicle->GetPosition();
+ CVector potentialPos;
+ potentialPos.y = GetPosition().y - 3.5f;
+ potentialPos.z = GetPosition().z;
+
+ for (int yTry = 0; yTry < 15; yTry++) {
+ potentialPos.x = GetPosition().x - 3.5f;
+
+ for (int xTry = 0; xTry < 15; xTry++) {
+ CPedPlacement::FindZCoorForPed(&potentialPos);
+ CVector distVec = potentialPos - vehPos;
+ float dist = distVec.Magnitude();
+
+ // Makes close distances bigger for some reason.
+ float mult = (0.6f + dist) / dist;
+ CVector adjustedPotentialPos = distVec * mult + vehPos;
+ if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false)
+ && !CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) {
+
+ float potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr();
+ veh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false);
+ if (veh) {
+ if (potentialChangeSqr < smallestDistNearVeh) {
+ posNearVeh = potentialPos;
+ putNearVeh = true;
+ smallestDistNearVeh = potentialChangeSqr;
+ }
+ } else if (potentialChangeSqr < smallestDistSomewhereClose) {
+ smallestDistSomewhereClose = potentialChangeSqr;
+ posSomewhereClose = potentialPos;
+ putSomewhereClose = true;
+ }
+ }
+ potentialPos.x += 0.5f;
+ }
+ potentialPos.y += 0.5f;
+ }
+
+ if (!putSomewhereClose && !putNearVeh)
+ return false;
+
+ // We refrain from using posNearVeh, probably because of it may be top of the vehicle.
+ if (putSomewhereClose) {
+ SetPosition(posSomewhereClose);
+ } else {
+ CVector vehSize = veh->GetModelInfo()->GetColModel()->boundingBox.max;
+ posNearVeh.z += vehSize.z;
+ SetPosition(posNearVeh);
+ }
+ return true;
+}
+
+bool
+CPed::WarpPedToNearLeaderOffScreen(void)
+{
+ bool teleported = false;
+ if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
+ return false;
+
+ CVector warpToPos = m_leader->GetPosition();
+ CVector distVec = warpToPos - GetPosition();
+ float halfOfDist = distVec.Magnitude() * 0.5f;
+ CVector halfNormalizedDist = distVec / halfOfDist;
+
+ CVector appropriatePos = GetPosition();
+ CVector zCorrectedPos = appropriatePos;
+ int tryCount = Min(10, halfOfDist);
+ for (int i = 0; i < tryCount; ++i) {
+ appropriatePos += halfNormalizedDist;
+ CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+
+ if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
+ continue;
+
+ appropriatePos.z = zCorrectedPos.z;
+ if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
+ && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
+ && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
+ teleported = true;
+ Teleport(appropriatePos);
+ }
+ }
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ return teleported;
+}
+
+bool
+CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo)
+{
+ bool teleported = false;
+ if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
+ return false;
+
+ CVector warpToPos = warpTo->GetPosition();
+ CVector distVec = warpToPos - GetPosition();
+ float halfOfDist = distVec.Magnitude() * 0.5f;
+ CVector halfNormalizedDist = distVec / halfOfDist;
+
+ CVector appropriatePos = GetPosition();
+ CVector zCorrectedPos = appropriatePos;
+ int tryCount = Min(10, halfOfDist);
+ for (int i = 0; i < tryCount; ++i) {
+ appropriatePos += halfNormalizedDist;
+ CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+
+ if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
+ continue;
+
+ appropriatePos.z = zCorrectedPos.z;
+ if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
+ && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
+ && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
+ teleported = true;
+ Teleport(appropriatePos);
+ }
+ }
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ return teleported;
+} \ No newline at end of file
diff --git a/src/peds/PedChat.cpp b/src/peds/PedChat.cpp
index 65ed67a5..81e295c6 100644
--- a/src/peds/PedChat.cpp
+++ b/src/peds/PedChat.cpp
@@ -56,26 +56,27 @@ CPed::ServiceTalkingWhenDead(void)
void
CPed::ServiceTalking(void)
{
- if (!bBodyPartJustCameOff || m_bodyPartBleeding != PED_HEAD) {
- if (!CGeneral::faststricmp(CModelInfo::GetModelInfo(GetModelIndex())->GetName(), "bomber"))
- m_queuedSound = SOUND_PED_BOMBER;
- else if (m_nPedState == PED_ON_FIRE)
- m_queuedSound = SOUND_PED_BURNING;
+ if (bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD)
+ return;
- if (m_queuedSound != SOUND_NO_SOUND) {
- if (m_queuedSound == SOUND_PED_DEATH)
- m_soundStart = CTimer::GetTimeInMilliseconds() - 1;
+ if (!CGeneral::faststricmp(CModelInfo::GetModelInfo(GetModelIndex())->GetName(), "bomber"))
+ m_queuedSound = SOUND_PED_BOMBER;
+ else if (m_nPedState == PED_ON_FIRE)
+ m_queuedSound = SOUND_PED_BURNING;
- if (CTimer::GetTimeInMilliseconds() > m_soundStart) {
- DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f);
- m_lastSoundStart = CTimer::GetTimeInMilliseconds();
- m_soundStart =
- CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime
- + CTimer::GetTimeInMilliseconds()
- + CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime);
- m_lastQueuedSound = m_queuedSound;
- m_queuedSound = SOUND_NO_SOUND;
- }
+ if (m_queuedSound != SOUND_NO_SOUND) {
+ if (m_queuedSound == SOUND_PED_DEATH)
+ m_soundStart = CTimer::GetTimeInMilliseconds() - 1;
+
+ if (CTimer::GetTimeInMilliseconds() > m_soundStart) {
+ DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f);
+ m_lastSoundStart = CTimer::GetTimeInMilliseconds();
+ m_soundStart =
+ CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime
+ + CTimer::GetTimeInMilliseconds()
+ + CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime);
+ m_lastQueuedSound = m_queuedSound;
+ m_queuedSound = SOUND_NO_SOUND;
}
}
}
@@ -83,14 +84,12 @@ CPed::ServiceTalking(void)
void
CPed::Say(uint16 audio)
{
- uint16 audioToPlay = audio;
-
if (IsPlayer()) {
// Ofc this part isn't in VC.
switch (audio) {
case SOUND_PED_DEATH:
- audioToPlay = SOUND_PED_DAMAGE;
+ audio = SOUND_PED_DAMAGE;
break;
case SOUND_PED_DAMAGE:
case SOUND_PED_HIT:
@@ -99,7 +98,7 @@ CPed::Say(uint16 audio)
case SOUND_PED_BULLET_HIT:
case SOUND_PED_CAR_JACKED:
case SOUND_PED_DEFEND:
- audioToPlay = SOUND_PED_HIT;
+ audio = SOUND_PED_HIT;
break;
default:
return;
@@ -142,12 +141,12 @@ CPed::Say(uint16 audio)
}
}
- if (audioToPlay < m_queuedSound) {
- if (audioToPlay != m_lastQueuedSound || audioToPlay == SOUND_PED_DEATH
- || CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime
+ if (audio < m_queuedSound) {
+ if (audio != m_lastQueuedSound || audio == SOUND_PED_DEATH
+ || CommentWaitTime[audio - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime
+ m_lastSoundStart
- + (uint32) CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) {
- m_queuedSound = audioToPlay;
+ + (uint32) CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audio - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) {
+ m_queuedSound = audio;
}
}
} \ No newline at end of file
diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp
new file mode 100644
index 00000000..21310aaa
--- /dev/null
+++ b/src/peds/PedFight.cpp
@@ -0,0 +1,3250 @@
+#include "common.h"
+
+#include "main.h"
+#include "RpAnimBlend.h"
+#include "AnimBlendClumpData.h"
+#include "AnimBlendAssociation.h"
+#include "Camera.h"
+#include "CarCtrl.h"
+#include "Darkel.h"
+#include "DMAudio.h"
+#include "FileMgr.h"
+#include "General.h"
+#include "Object.h"
+#include "Pad.h"
+#include "Particle.h"
+#include "Ped.h"
+#include "PlayerPed.h"
+#include "Stats.h"
+#include "TempColModels.h"
+#include "VisibilityPlugins.h"
+#include "Vehicle.h"
+#include "Automobile.h"
+#include "WaterLevel.h"
+#include "World.h"
+
+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},
+};
+
+static PedOnGroundState
+CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround)
+{
+ PedOnGroundState stateToReturn;
+ float angleToFace;
+ CPed *currentPed = nil;
+ PedState currentPedState;
+ CPed *pedOnTheFloor = nil;
+ CPed *deadPed = nil;
+ CPed *pedBelow = nil;
+ bool foundDead = false;
+ bool foundOnTheFloor = false;
+ bool foundBelow = false;
+ float angleDiff;
+ float distance;
+
+ if (!CGame::nastyGame)
+ return NO_PED;
+
+ for (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) {
+
+ currentPed = attacker->m_nearPeds[currentPedId];
+
+ CVector posDifference = currentPed->GetPosition() - attacker->GetPosition();
+ distance = posDifference.Magnitude();
+
+ if (distance < 2.0f) {
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ currentPed->GetPosition().x, currentPed->GetPosition().y,
+ attacker->GetPosition().x, attacker->GetPosition().y);
+
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ attacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur);
+
+ angleDiff = Abs(angleToFace - attacker->m_fRotationCur);
+
+ if (angleDiff > PI)
+ angleDiff = 2 * PI - angleDiff;
+
+ currentPedState = currentPed->m_nPedState;
+
+ if (currentPed->OnGroundOrGettingUp()) {
+ if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) {
+ if (currentPedState == PED_DEAD) {
+ foundDead = 1;
+ if (!deadPed)
+ deadPed = currentPed;
+ } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {
+ foundOnTheFloor = 1;
+ if (!pedOnTheFloor)
+ pedOnTheFloor = currentPed;
+ }
+ }
+ } else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f))
+ || (distance < 1.3f && angleDiff < DEGTORAD(55.0f))
+ || (distance < 1.7f && angleDiff < DEGTORAD(35.0f))
+ || (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) {
+
+ // Either this condition or below one was probably returning 4 early in development. See Fight().
+ foundBelow = 1;
+ pedBelow = currentPed;
+ break;
+ } else {
+ if (angleDiff < DEGTORAD(75.0f)) {
+ foundBelow = 1;
+ if (!pedBelow)
+ pedBelow = currentPed;
+ }
+ }
+ }
+ }
+
+ if (foundOnTheFloor) {
+ currentPed = pedOnTheFloor;
+ stateToReturn = PED_ON_THE_FLOOR;
+ } else if (foundDead) {
+ currentPed = deadPed;
+ stateToReturn = PED_DEAD_ON_THE_FLOOR;
+ } else if (foundBelow) {
+ currentPed = pedBelow;
+ stateToReturn = PED_IN_FRONT_OF_ATTACKER;
+ } else {
+ currentPed = nil;
+ stateToReturn = NO_PED;
+ }
+
+ if (pedOnGround)
+ *pedOnGround = currentPed;
+
+ return stateToReturn;
+}
+
+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)
+ return;
+
+ if (m_nPedState != PED_ATTACK)
+ SetStoredState();
+
+ 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 (!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);
+
+ aimAssoc->blendAmount = 0.0f;
+ aimAssoc->blendDelta = 8.0f;
+ }
+ if (to)
+ Say(SOUND_PED_ATTACK);
+}
+
+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);
+
+ if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
+ weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+
+ if (weaponInfo->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+ }
+}
+
+void
+CPed::ClearPointGunAt(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ CWeaponInfo *weaponInfo;
+
+ 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) {
+ 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;
+ }
+#ifndef VC_PED_PORTS
+ }
+#endif
+}
+
+void
+CPed::SetAttack(CEntity *victim)
+{
+ CPed *victimPed = nil;
+ 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;
+ return;
+ }
+
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) {
+ if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)
+ bIsAttacking = false;
+ else
+ bIsAttacking = true;
+
+ 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) {
+ if (IsPlayer() ||
+ (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
+
+ if (m_nPedState != PED_ATTACK) {
+ m_nPedState = PED_ATTACK;
+ bIsAttacking = false;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
+ animAssoc->SetRun();
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ } else {
+ StartFightAttack(CGeneral::GetRandomNumber() % 256);
+ }
+ return;
+ }
+
+ 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();
+ CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
+ if (obstacle)
+ 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 {
+ SetAimFlag(m_fRotationCur);
+
+ if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
+ }
+ }
+ if (m_nPedState == PED_ATTACK) {
+ bIsAttacking = true;
+ return;
+ }
+
+ if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
+ if (IsPlayer())
+ CPad::GetPad(0)->ResetAverageWeapon();
+
+ PointBlankNecessity pointBlankStatus;
+ if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER)
+ && 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
+ && (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) {
+ ClearAimFlag();
+
+ // This condition is pointless
+ if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed)
+ StartFightAttack(200);
+ } else {
+ if (!curWeapon->m_bCanAim)
+ m_pSeekTarget = nil;
+
+ if (m_nPedState != PED_AIM_GUN)
+ SetStoredState();
+
+ m_nPedState = PED_ATTACK;
+ SetMoveState(PEDMOVE_NONE);
+ if (bCrouchWhenShooting) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.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);
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
+ }
+ }
+
+ animAssoc->SetRun();
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ return;
+ }
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
+ SetWaitState(WAITSTATE_SURPRISE, nil);
+
+ SetLookFlag(victim, false);
+ SetLookTimer(100);
+}
+
+void
+CPed::ClearAttack(void)
+{
+ if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
+ return;
+
+#ifdef VC_PED_PORTS
+ // VC uses CCamera::Using1stPersonWeaponMode
+ if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
+ TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) {
+ SetPointGunAt(nil);
+ } else
+#endif
+ if (bIsPointingGunAt) {
+ if (m_pLookTarget)
+ SetPointGunAt(m_pLookTarget);
+ else
+ ClearPointGunAt();
+ } else if (m_objective != OBJECTIVE_NONE) {
+ SetIdle();
+ } else {
+ RestorePreviousState();
+ }
+}
+
+void
+CPed::ClearAttackByRemovingAnim(void)
+{
+ if (m_nPedState != PED_ATTACK || bIsDucking)
+ 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);
+
+ if (!weaponAssoc) {
+ ClearAttack();
+ return;
+ }
+ }
+ weaponAssoc->blendDelta = -8.0f;
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
+}
+
+void
+CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
+{
+ CWeaponInfo *currentWeapon;
+ CAnimBlendAssociation *newAnim;
+ CPed *ped = (CPed*)arg;
+
+ 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);
+ }
+
+ newAnim->SetFinishCallback(FinishedAttackCB, ped);
+ return;
+
+ case ANIM_FIGHT_PPUNCH:
+ attackAssoc->blendDelta = -8.0f;
+ attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ped->ClearAttack();
+ return;
+
+ case ANIM_WEAPON_THROW:
+ case ANIM_WEAPON_THROWU:
+ if (ped->GetWeapon()->m_nAmmoTotal > 0) {
+ currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
+ ped->AddWeaponModel(currentWeapon->m_nModelId);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!ped->bIsAttacking)
+ ped->ClearAttack();
+}
+
+PointBlankNecessity
+CPed::CheckForPointBlankPeds(CPed *pedToVerify)
+{
+ float pbDistance = 1.1f;
+ if (GetWeapon()->IsType2Handed())
+ pbDistance = 1.6f;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+
+ if (!pedToVerify || pedToVerify == nearPed) {
+
+ CVector diff = nearPed->GetPosition() - GetPosition();
+ if (diff.Magnitude() < pbDistance) {
+
+ float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
+ nearPed->GetPosition().x, nearPed->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ neededAngle = CGeneral::LimitRadianAngle(neededAngle);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ float neededTurn = Abs(neededAngle - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = 2*PI - neededTurn;
+
+ if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY)
+ return NO_POINT_BLANK_PED;
+
+ if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {
+ if (pedToVerify == nearPed)
+ return POINT_BLANK_FOR_WANTED_PED;
+ else
+ return POINT_BLANK_FOR_SOMEONE_ELSE;
+ }
+ }
+ }
+ }
+ return NO_POINT_BLANK_PED;
+}
+
+void
+CPed::Attack(void)
+{
+ CAnimBlendAssociation *weaponAnimAssoc;
+ int32 weaponAnim;
+ float animStart;
+ eWeaponType ourWeaponType;
+ float weaponAnimTime;
+ eWeaponFire ourWeaponFire;
+ float animLoopEnd;
+ CWeaponInfo *ourWeapon;
+ bool attackShouldContinue;
+ AnimationId reloadAnim;
+ CAnimBlendAssociation *reloadAnimAssoc;
+ float delayBetweenAnimAndFire;
+ CVector firePos;
+
+ ourWeaponType = GetWeapon()->m_eWeaponType;
+ ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
+ ourWeaponFire = ourWeapon->m_eWeaponFire;
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
+ attackShouldContinue = bIsAttacking;
+ reloadAnimAssoc = nil;
+ reloadAnim = NUM_ANIMS;
+ 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 (reloadAnim != NUM_ANIMS)
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
+
+ if (bIsDucking)
+ return;
+
+ if (reloadAnimAssoc) {
+ if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)
+ ClearAttack();
+
+ return;
+ }
+
+ if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ attackShouldContinue = true;
+
+ 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 (!weaponAnimAssoc) {
+ 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);
+ }
+
+ weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
+ weaponAnimAssoc->SetRun();
+
+ if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength)
+ weaponAnimAssoc->SetCurrentTime(0.0f);
+
+ if (IsPlayer()) {
+ ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f;
+ ((CPlayerPed*)this)->m_bHaveTargetSelected = false;
+ }
+ }
+ } else
+ FinishedAttackCB(nil, this);
+
+ return;
+ }
+ }
+
+ animStart = ourWeapon->m_fAnimLoopStart;
+ weaponAnimTime = weaponAnimAssoc->currentTime;
+ if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
+ if (ourWeapon->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+ }
+
+ 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;
+
+ firePos = GetMatrix() * firePos;
+ } else if (ourWeaponType != WEAPONTYPE_UNARMED) {
+ TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR);
+ } else {
+ firePos = GetMatrix() * firePos;
+ }
+
+ GetWeapon()->Fire(this, &firePos);
+
+ if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) {
+ 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;
+ }
+ } 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);
+ }
+
+ weaponAnimAssoc->speed = 0.5f;
+
+ if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
+ weaponAnimAssoc->callbackType = 0;
+ }
+ }
+
+ attackShouldContinue = false;
+ }
+
+ if (ourWeaponType == WEAPONTYPE_SHOTGUN) {
+ weaponAnimTime = weaponAnimAssoc->currentTime;
+ firePos = ourWeapon->m_vecFireOffset;
+
+ if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {
+ TransformToNode(firePos, PED_HANDR);
+
+ CVector gunshellPos(
+ firePos.x - 0.6f * GetForward().x,
+ firePos.y - 0.6f * GetForward().y,
+ firePos.z - 0.15f * GetUp().z
+ );
+
+ CVector2D gunshellRot(
+ GetRight().x,
+ GetRight().y
+ );
+
+ gunshellRot.Normalise();
+ GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);
+ }
+ }
+#ifdef VC_PED_PORTS
+ 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) {
+ 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);
+ }
+ } 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) {
+ switch (ourWeaponType) {
+ case WEAPONTYPE_UZI:
+ 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;
+ }
+ }
+
+ // 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;
+}
+
+void
+CPed::StartFightAttack(uint8 buttonPressure)
+{
+ if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds())
+ return;
+
+ if (m_nPedState == PED_FIGHT) {
+ m_fightButtonPressure = buttonPressure;
+ return;
+ }
+
+ if (m_nPedState != PED_AIM_GUN)
+ SetStoredState();
+
+ if (m_nWaitState != WAITSTATE_FALSE) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ }
+
+ m_nPedState = PED_FIGHT;
+ m_fightButtonPressure = 0;
+ RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -1000.0f;
+ }
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -1000.0f;
+ RestoreHeadingRate();
+ }
+
+ SetMoveState(PEDMOVE_NONE);
+ m_nStoredMoveState = PEDMOVE_NONE;
+
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+
+ CPed *pedOnGround = nil;
+ if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) {
+ m_curFightMove = FIGHTMOVE_GROUNDKICK;
+ } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) {
+ m_curFightMove = FIGHTMOVE_ROUNDHOUSE;
+ } else {
+ m_curFightMove = FIGHTMOVE_STDPUNCH;
+ }
+
+ if (pedOnGround && IsPlayer()) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ pedOnGround->GetPosition().x, pedOnGround->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(pedOnGround, true);
+ SetLookTimer(1500);
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_takeAStepAfterAttack = false;
+ bIsAttacking = true;
+
+ if (IsPlayer())
+ nPlayerInComboMove = 0;
+}
+
+void
+CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
+{
+ if (m_nPedState == PED_DEAD) {
+ if (CGame::nastyGame) {
+ if (hitLevel == HITLEVEL_GROUND) {
+ CAnimBlendAssociation *floorHitAssoc;
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) {
+ floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f);
+ } else {
+ floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f);
+ }
+ if (floorHitAssoc) {
+ floorHitAssoc->SetCurrentTime(0.0f);
+ floorHitAssoc->SetRun();
+ floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ }
+ }
+ if (CGame::nastyGame) {
+ CVector headPos = GetNodePosition(PED_HEAD);
+ for(int i = 0; i < 4; ++i) {
+ CVector bloodDir(0.0f, 0.0f, 0.1f);
+ CVector bloodPos = headPos - 0.2f * GetForward();
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+ } else if (m_nPedState == PED_FALL) {
+ if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) {
+ CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ?
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) :
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f);
+ if (floorHitAssoc) {
+ floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ } else if (IsPedInControl()) {
+ if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)
+ || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {
+#ifndef VC_PED_PORTS
+ if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) {
+ if (IsPlayer() || CGeneral::GetRandomNumber() & 3) {
+#else
+ if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {
+ if (IsPlayer() || CGeneral::GetRandomNumber() & 1) {
+#endif
+ AnimationId shotAnim;
+ switch (direction) {
+ case 1:
+ shotAnim = ANIM_SHOT_LEFT_PARTIAL;
+ break;
+ case 2:
+ shotAnim = ANIM_SHOT_BACK_PARTIAL;
+ break;
+ case 3:
+ shotAnim = ANIM_SHOT_RIGHT_PARTIAL;
+ break;
+ default:
+ shotAnim = ANIM_SHOT_FRONT_PARTIAL;
+ break;
+ }
+ CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim);
+ if (!shotAssoc || shotAssoc->blendDelta < 0.0f)
+ shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f);
+
+ shotAssoc->SetCurrentTime(0.0f);
+ shotAssoc->SetRun();
+ shotAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ } else {
+ int time = CGeneral::GetRandomNumberInRange(1000, 3000);
+ SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);
+ }
+ } else {
+#ifndef VC_PED_PORTS
+ switch (direction) {
+ case 1:
+ SetFall(500, ANIM_KO_SPIN_R, false);
+ break;
+ case 2:
+ SetFall(500, ANIM_KO_SKID_BACK, false);
+ break;
+ case 3:
+ SetFall(500, ANIM_KO_SPIN_L, false);
+ break;
+ default:
+ SetFall(500, ANIM_KO_SHOT_STOM, false);
+ break;
+ }
+#else
+ bool fall = true;
+ AnimationId hitAnim;
+ switch (direction) {
+ case 1:
+ hitAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_BACK;
+ } else {
+ hitAnim = ANIM_KO_SKID_BACK;
+ }
+ break;
+ case 3:
+ hitAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ if (hitLevel == HITLEVEL_LOW) {
+ hitAnim = ANIM_KO_SHOT_STOM;
+ } else if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_WALK;
+ } else if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_HEAD;
+ } else {
+ hitAnim = ANIM_KO_SHOT_FACE;
+ }
+ break;
+ }
+ if (fall) {
+ SetFall(500, hitAnim, false);
+ } else {
+ CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim);
+ if (!hitAssoc || hitAssoc->blendDelta < 0.0f)
+ hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f);
+
+ hitAssoc->SetCurrentTime(0.0f);
+ hitAssoc->SetRun();
+ hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+#endif
+ }
+ Say(SOUND_PED_DEFEND);
+ } else {
+ Say(SOUND_PED_DEFEND);
+ switch (hitLevel) {
+ case HITLEVEL_GROUND:
+ m_curFightMove = FIGHTMOVE_HITONFLOOR;
+ break;
+ case HITLEVEL_LOW:
+#ifndef VC_PED_PORTS
+ if (direction == 2) {
+ SetFall(1000, ANIM_KO_SKID_BACK, false);
+ return;
+ }
+#else
+ if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
+ SetFall(1000, ANIM_KO_SKID_BACK, false);
+ return;
+ } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
+ SetFall(1000, ANIM_KO_SHOT_STOM, false);
+ return;
+ }
+#endif
+ m_curFightMove = FIGHTMOVE_HITBODY;
+ break;
+ case HITLEVEL_HIGH:
+ switch (direction) {
+ case 1:
+ m_curFightMove = FIGHTMOVE_HITLEFT;
+ break;
+ case 2:
+ m_curFightMove = FIGHTMOVE_HITBACK;
+ break;
+ case 3:
+ m_curFightMove = FIGHTMOVE_HITRIGHT;
+ break;
+ default:
+ if (unk <= 5)
+ m_curFightMove = FIGHTMOVE_HITHEAD;
+ else
+ m_curFightMove = FIGHTMOVE_HITBIGSTEP;
+ break;
+ }
+ break;
+ default:
+ switch (direction) {
+ case 1:
+ m_curFightMove = FIGHTMOVE_HITLEFT;
+ break;
+ case 2:
+ m_curFightMove = FIGHTMOVE_HITBACK;
+ break;
+ case 3:
+ m_curFightMove = FIGHTMOVE_HITRIGHT;
+ break;
+ default:
+ if (unk <= 5)
+ m_curFightMove = FIGHTMOVE_HITCHEST;
+ else
+ m_curFightMove = FIGHTMOVE_HITBIGSTEP;
+ break;
+ }
+ break;
+ }
+ if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f))
+ m_curFightMove = FIGHTMOVE_HITONFLOOR;
+
+ if (m_nPedState == PED_FIGHT) {
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
+ moveAssoc->SetCurrentTime(0.0f);
+ moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ if (IsPlayer())
+ moveAssoc->speed = 1.3f;
+
+ m_takeAStepAfterAttack = 0;
+ m_fightButtonPressure = 0;
+ } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
+ moveAssoc->SetCurrentTime(0.0f);
+ moveAssoc->speed = 1.3f;
+ } else {
+ if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
+ SetStoredState();
+
+ if (m_nWaitState != WAITSTATE_FALSE) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ }
+ m_nPedState = PED_FIGHT;
+ m_fightButtonPressure = 0;
+ RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
+ CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+ if (walkStartAssoc) {
+ walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ walkStartAssoc->blendDelta = -1000.0f;
+ }
+ CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ if (!walkStopAssoc)
+ walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+ if (walkStopAssoc) {
+ walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ walkStopAssoc->blendDelta = -1000.0f;
+ RestoreHeadingRate();
+ }
+ SetMoveState(PEDMOVE_NONE);
+ m_nStoredMoveState = PEDMOVE_NONE;
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
+ moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_takeAStepAfterAttack = false;
+ bIsAttacking = true;
+ }
+ }
+ }
+}
+
+void
+CPed::Fight(void)
+{
+ CAnimBlendAssociation *currentAssoc, *animAssoc;
+ bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse;
+ float angleToFace, nextAngle;
+ bool goForward = false;
+ int nextFightMove;
+
+ switch (m_curFightMove) {
+ case FIGHTMOVE_NULL:
+ return;
+ case FIGHTMOVE_IDLE2NORM:
+ m_curFightMove = FIGHTMOVE_NULL;
+ RestorePreviousState();
+
+ // FIX: Uninitialized
+ currentAssoc = nil;
+ break;
+ case FIGHTMOVE_IDLE:
+ currentAssoc = nil;
+ break;
+ default:
+ currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
+ break;
+ }
+
+ if (!bIsAttacking && IsPlayer()) {
+ if (currentAssoc) {
+ currentAssoc->blendDelta = -1000.0f;
+ currentAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ currentAssoc->flags &= ~ASSOC_RUNNING;
+ }
+ if (m_takeAStepAfterAttack)
+ EndFight(ENDFIGHT_WITH_A_STEP);
+ else
+ EndFight(ENDFIGHT_FAST);
+
+ } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) {
+ float animTime = currentAssoc->currentTime;
+ FightMove &curMove = tFightMoves[m_curFightMove];
+ if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
+
+ CVector touchingNodePos(0.0f, 0.0f, 0.0f);
+
+ switch (m_curFightMove) {
+ case FIGHTMOVE_STDPUNCH:
+ case FIGHTMOVE_PUNCHHOOK:
+ case FIGHTMOVE_BODYBLOW:
+ TransformToNode(touchingNodePos, PED_HANDR);
+ break;
+ case FIGHTMOVE_IDLE:
+ case FIGHTMOVE_SHUFFLE_F:
+ break;
+ 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:
+ TransformToNode(touchingNodePos, PED_FOOTR);
+ break;
+ }
+
+ if (m_curFightMove == FIGHTMOVE_PUNCHJAB) {
+ touchingNodePos += 0.1f * GetForward();
+ } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) {
+ touchingNodePos += 0.22f * GetForward();
+ }
+ FightStrike(touchingNodePos);
+ m_fightButtonPressure = 0;
+ return;
+ }
+
+ if (curMove.hitLevel != HITLEVEL_NULL) {
+ if (animTime > curMove.endFireTime) {
+ if (IsPlayer())
+ currentAssoc->speed = 1.0f;
+ else
+ currentAssoc->speed = 0.8f;
+ }
+
+ if (IsPlayer() && !nPlayerInComboMove) {
+ if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) {
+
+ // Notice that it increases fight move index, because we're in combo!
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f);
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength);
+ m_fightButtonPressure = 0;
+ nPlayerInComboMove = 1;
+ }
+ }
+ } else {
+ if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) {
+ if (IsPlayer())
+ currentAssoc->speed = 1.3f;
+ else
+ currentAssoc->speed = 0.8f;
+ }
+ }
+ } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ EndFight(ENDFIGHT_FAST);
+
+ } else if (m_fightButtonPressure != 0) {
+ bool canAffectMultiplePeople = true;
+ nextAngle = m_fRotationCur;
+ bool kickGround = false;
+ float angleForGroundKick = 0.0f;
+ CPed *pedOnGround = nil;
+
+ Say(SOUND_PED_ATTACK);
+
+ if (IsPlayer()) {
+ canRoundhouse = false;
+ punchOnly = false;
+ canKick = true;
+ nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
+ hasShoppingBags = false;
+ canKneeHead = true;
+ nPlayerInComboMove = 0;
+ } else {
+ nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
+ uint16 pedFeatures = m_pedStats->m_flags;
+ punchOnly = pedFeatures & STAT_PUNCH_ONLY;
+ canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE;
+ canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD;
+ canKick = pedFeatures & STAT_CAN_KICK;
+ hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS;
+ }
+
+ // Attack isn't scripted, find the victim
+ if (IsPlayer() || !m_pedInObjective) {
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+
+ CPed *nearPed = m_nearPeds[i];
+ float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude();
+ if (nearPedDist < 3.0f) {
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ nearPed->GetPosition().x, nearPed->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+
+ nextAngle = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ float neededTurn = Abs(nextAngle - m_fRotationCur);
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ if (!nearPed->OnGroundOrGettingUp()) {
+
+ if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) {
+ canAffectMultiplePeople = false;
+ } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) {
+
+ if (nearPedDist < 1.7f
+ && neededTurn < DEGTORAD(35.0f)
+ && (canKick || hasShoppingBags)) {
+
+ nextFightMove = FIGHTMOVE_KICK;
+ if (hasShoppingBags) {
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+ } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) {
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+ }
+ canAffectMultiplePeople = false;
+ } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) {
+ canAffectMultiplePeople = false;
+ nextFightMove = FIGHTMOVE_LONGKICK;
+ } else if (neededTurn < DEGTORAD(30.0f)) {
+ goForward = true;
+ }
+ } else {
+ nextFightMove += 2; // Makes it 6 or 7
+ if (punchOnly)
+ nextFightMove = FIGHTMOVE_PUNCHJAB;
+
+ canAffectMultiplePeople = false;
+ }
+ } else if (!CGame::nastyGame
+ || nearPedDist >= 1.3f
+ || neededTurn >= DEGTORAD(55.0f)
+ || punchOnly) {
+
+ if (nearPedDist > 0.8f
+ && nearPedDist < 3.0f
+ && neededTurn < DEGTORAD(30.0f)) {
+ goForward = true;
+ }
+
+ } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) {
+ if (!nearPed->IsPedHeadAbovePos(-0.3f)) {
+ canAffectMultiplePeople = false;
+ nextFightMove = FIGHTMOVE_GROUNDKICK;
+ }
+
+ } else {
+ pedOnGround = nearPed;
+ kickGround = true;
+ angleForGroundKick = nextAngle;
+ }
+ }
+
+ if (!canAffectMultiplePeople) {
+ m_fRotationDest = nextAngle;
+ if (IsPlayer()) {
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(nearPed, true);
+ SetLookTimer(1500);
+ }
+ break;
+ }
+ }
+ } else {
+ // Because we're in a scripted fight with some particular ped.
+ canAffectMultiplePeople = false;
+
+ float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude();
+ if (hasShoppingBags) {
+ if (fightingPedDist >= 1.7f)
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ else
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+
+ } else if (punchOnly) {
+ if (fightingPedDist >= 1.3f)
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ else
+ nextFightMove = FIGHTMOVE_PUNCHJAB;
+
+ } else if (fightingPedDist >= 3.0f) {
+ nextFightMove = FIGHTMOVE_STDPUNCH;
+
+ } else {
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ m_pedInObjective->GetPosition().x,
+ m_pedInObjective->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ nextAngle = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationDest = nextAngle;
+ m_fRotationCur = m_fRotationDest;
+ if (!m_pedInObjective->OnGroundOrGettingUp()) {
+
+ if (fightingPedDist >= 0.8f || !canKneeHead) {
+
+ if (fightingPedDist >= 1.3f) {
+
+ if (fightingPedDist < 1.7f && canKick) {
+ nextFightMove = FIGHTMOVE_KICK;
+ if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+
+ } else if (fightingPedDist < 2.0f && canKick) {
+ nextFightMove += 5; // Makes it 9 or 10
+
+ } else {
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+
+ }
+ } else {
+ nextFightMove += 2; // Makes it 6 or 7
+ }
+ }
+ } else if (!CGame::nastyGame
+ || fightingPedDist >= 1.3f
+ || m_pedInObjective->IsPlayer()
+ || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) {
+ nextFightMove = FIGHTMOVE_IDLE;
+ } else {
+ nextFightMove = FIGHTMOVE_GROUNDKICK;
+ }
+ }
+ }
+
+ if (canAffectMultiplePeople) {
+ if (kickGround && IsPlayer()) {
+ m_fRotationDest = angleForGroundKick;
+ nextFightMove = FIGHTMOVE_GROUNDKICK;
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(pedOnGround, true);
+ SetLookTimer(1500);
+ } else if (goForward) {
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ } else {
+ nextFightMove = FIGHTMOVE_STDPUNCH;
+ }
+ }
+
+ if (nextFightMove != FIGHTMOVE_IDLE) {
+ m_curFightMove = nextFightMove;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
+
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {
+ animAssoc->SetCurrentTime(0.0f);
+ animAssoc->SetRun();
+ }
+ m_fightButtonPressure = 0;
+ }
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F
+#ifndef FIX_BUGS
+ && CheckForPedsOnGroundToAttack(this, nil) == 4) {
+#else
+ && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) {
+#endif
+ m_curFightMove = FIGHTMOVE_SHUFFLE_F;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
+
+ if (animAssoc) {
+ animAssoc->SetCurrentTime(0.0f);
+ animAssoc->blendDelta = 4.0f;
+ animAssoc->SetRun();
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f);
+ }
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_fightButtonPressure = 0;
+ m_takeAStepAfterAttack = false;
+
+ } else if (m_takeAStepAfterAttack) {
+ EndFight(ENDFIGHT_FAST);
+
+ } else if (m_curFightMove == FIGHTMOVE_IDLE) {
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ EndFight(ENDFIGHT_NORMAL);
+ }
+
+ } else {
+ m_curFightMove = FIGHTMOVE_IDLE;
+ if (IsPlayer())
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+}
+
+void
+CPed::EndFight(uint8 endType)
+{
+ if (m_nPedState != PED_FIGHT)
+ return;
+
+ m_curFightMove = FIGHTMOVE_NULL;
+ RestorePreviousState();
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+ if (animAssoc)
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+
+ switch (endType) {
+ case ENDFIGHT_NORMAL:
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f);
+ break;
+ case ENDFIGHT_WITH_A_STEP:
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WALK_START, 8.0f);
+ break;
+ case ENDFIGHT_FAST:
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f)->speed = 2.0f;
+ break;
+ default:
+ break;
+ }
+ m_nWaitTimer = 0;
+}
+
+
+void
+CPed::PlayHitSound(CPed *hitTo)
+{
+ // That was very complicated to reverse for me...
+ // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10).
+ enum {
+ S33 = SOUND_FIGHT_PUNCH_33,
+ S34 = SOUND_FIGHT_KICK_34,
+ S35 = SOUND_FIGHT_HEADBUTT_35,
+ S36 = SOUND_FIGHT_PUNCH_36,
+ S37 = SOUND_FIGHT_PUNCH_37,
+ S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
+ S39 = SOUND_FIGHT_PUNCH_39,
+ S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
+ S41 = SOUND_FIGHT_PUNCH_41,
+ S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
+ S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
+ S44 = SOUND_FIGHT_KICK_44,
+ NO_SND = SOUND_NO_SOUND
+ };
+ uint16 hitSoundsByFightMoves[12][10] = {
+ {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42},
+ {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
+ {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
+ {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39},
+ {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39},
+ {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39},
+ {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39},
+ {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
+ {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
+ {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40},
+ {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40},
+ {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33}
+ };
+
+ // This is why first dimension is between FightMove 1 and 12.
+ if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)
+ return;
+
+ uint16 soundId;
+
+ // And this is why second dimension is between 13 and 22.
+ if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) {
+ soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT];
+
+ } else {
+ if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) {
+ soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT];
+ } else {
+ soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT];
+ }
+ }
+
+ if (soundId != NO_SND)
+ DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f);
+}
+
+bool
+CPed::FightStrike(CVector &touchedNodePos)
+{
+ CColModel *ourCol;
+ CVector attackDistance;
+ ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
+ float maxDistanceToBeBeaten;
+ CPed *nearPed;
+ int state = m_fightState;
+ bool pedFound = false;
+
+ if (state == FIGHTSTATE_JUST_ATTACKED)
+ return false;
+
+ // Pointless code
+ if (state > FIGHTSTATE_NO_MOVE)
+ attackDistance = touchedNodePos - m_vecHitLastPos;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ nearPed = m_nearPeds[i];
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
+ maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f;
+ else
+ maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius;
+
+ if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
+ CVector nearPedCentre;
+ 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->OnGround() || !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;
+ attackDistance -= touchedNodePos;
+ CColSphere *ourPieces = ourCol->spheres;
+ float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;
+
+ // We can beat him too
+ if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
+ pedFound = true;
+ closestPedPiece = (ePedPieceTypes) ourPieces[j].piece;
+ break;
+ }
+ }
+ }
+ }
+ if (pedFound)
+ break;
+ }
+
+ if (pedFound) {
+ if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP)
+ return false;
+
+ float oldVictimHealth = nearPed->m_fHealth;
+ CVector bloodPos = 0.5f * attackDistance + touchedNodePos;
+ int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
+
+ CVector2D diff (GetPosition() - nearPed->GetPosition());
+ int direction = nearPed->GetLocalDirection(diff);
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ damageMult = 20;
+ } else {
+ damageMult *= m_pedStats->m_attackStrength;
+ }
+
+ // Change direction if we used kick.
+ if (m_curFightMove == FIGHTMOVE_KICK) {
+ if (CGeneral::GetRandomNumber() & 1) {
+ direction++;
+ if (direction > 3)
+ direction -= 4;
+ }
+ }
+ nearPed->ReactToAttack(this);
+
+ // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
+ int unk2;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
+ unk2 = 101;
+ else
+ unk2 = damageMult;
+
+ nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);
+ PlayHitSound(nearPed);
+ m_fightState = FIGHTSTATE_JUST_ATTACKED;
+ RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;
+ if (!nearPed->DyingOrDead()) {
+ nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
+ }
+
+ if (CGame::nastyGame
+ && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM
+ && nearPed->m_nPedState == PED_DIE
+ && nearPed->GetIsOnScreen()) {
+
+ // Just for blood particle. We will restore it below.
+ attackDistance /= (10.0f * attackDistance.Magnitude());
+ for(int i=0; i<4; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ if (!nearPed->OnGround()) {
+ float curVictimHealth = nearPed->m_fHealth;
+ if (curVictimHealth > 0.0f
+ && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer()
+ || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f
+ || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer()
+ || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) {
+
+ nearPed->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0);
+ if (nearPed->m_nPedState == PED_FALL)
+ nearPed->bIsStanding = false;
+ }
+ }
+ if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) {
+ attackDistance = nearPed->GetPosition() - GetPosition();
+ attackDistance.Normalise();
+ attackDistance.z = 1.0f;
+ nearPed->bIsStanding = false;
+
+ float moveMult;
+ if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
+ moveMult = Min(damageMult * 0.6f, 4.0f);
+ } else {
+ if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
+ moveMult = damageMult;
+ } else {
+ moveMult = Min(damageMult * 2.0f, 14.0f);
+ }
+ }
+
+ nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance);
+ }
+ CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000);
+ }
+
+ if (m_fightState == FIGHTSTATE_NO_MOVE)
+ m_fightState = FIGHTSTATE_1;
+
+ m_vecHitLastPos = *touchedNodePos;
+ return false;
+}
+
+void
+CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) {
+ ped->m_fightState = FIGHTSTATE_MOVE_FINISHED;
+ animAssoc->blendDelta = -1000.0f;
+ }
+}
+
+void
+CPed::LoadFightData(void)
+{
+ float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
+ int damage, flags;
+ char line[256], moveName[32], animName[32], hitLevel;
+ int moveId = 0;
+
+ CAnimBlendAssociation *animAssoc;
+
+ size_t bp, buflen;
+ int lp, linelen;
+
+ buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r");
+
+ for (bp = 0; bp < buflen; ) {
+ // read file line by line
+ for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) {
+ line[linelen++] = work_buff[bp];
+ }
+ bp++;
+ line[linelen] = '\0';
+
+ // skip white space
+ for (lp = 0; line[lp] <= ' ' && line[lp] != '\0'; lp++);
+
+ if (line[lp] == '\0' ||
+ line[lp] == '#')
+ continue;
+
+ sscanf(
+ &line[lp],
+ "%s %f %f %f %f %c %s %d %d",
+ moveName,
+ &startFireTime,
+ &endFireTime,
+ &comboFollowOnTime,
+ &strikeRadius,
+ &hitLevel,
+ animName,
+ &damage,
+ &flags);
+
+ if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0)
+ return;
+
+ tFightMoves[moveId].startFireTime = startFireTime / 30.0f;
+ tFightMoves[moveId].endFireTime = endFireTime / 30.0f;
+ tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
+ tFightMoves[moveId].strikeRadius = strikeRadius;
+ tFightMoves[moveId].damage = damage;
+ tFightMoves[moveId].flags = flags;
+
+ switch (hitLevel) {
+ case 'G':
+ tFightMoves[moveId].hitLevel = HITLEVEL_GROUND;
+ break;
+ case 'H':
+ tFightMoves[moveId].hitLevel = HITLEVEL_HIGH;
+ break;
+ case 'L':
+ tFightMoves[moveId].hitLevel = HITLEVEL_LOW;
+ break;
+ case 'M':
+ tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM;
+ break;
+ case 'N':
+ tFightMoves[moveId].hitLevel = HITLEVEL_NULL;
+ break;
+ default:
+ 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;
+ }
+ moveId++;
+ }
+}
+
+void
+CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle)
+{
+ if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR)
+ return;
+
+ SetStoredState();
+ bFindNewNodeAfterStateRestore = false;
+ m_nPedState = PED_INVESTIGATE;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ m_eventType = event;
+ m_eventOrThreat = pos;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_fAngleToEvent = angle;
+
+ if (m_eventType >= EVENT_ICECREAM)
+ m_lookTimer = 0;
+ else
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f);
+
+}
+
+void
+CPed::InvestigateEvent(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId animToPlay;
+ AssocGroupId animGroup;
+
+ if (m_nWaitState == WAITSTATE_TURN180)
+ return;
+
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+
+ if (m_standardTimer) {
+ if (m_eventType < EVENT_ASSAULT_NASTYWEAPON)
+ SetWaitState(WAITSTATE_TURN180, nil);
+
+ m_standardTimer = 0;
+ } else {
+ ClearInvestigateEvent();
+ }
+ return;
+ }
+
+ CVector2D vecDist = m_eventOrThreat - GetPosition();
+ float distSqr = vecDist.MagnitudeSqr();
+ if (sq(m_distanceToCountSeekDone) >= distSqr) {
+
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f);
+ SetMoveState(PEDMOVE_STILL);
+
+ switch (m_eventType) {
+ case EVENT_DEAD_PED:
+ case EVENT_HIT_AND_RUN:
+ case EVENT_HIT_AND_RUN_COP:
+
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (m_pEventEntity)
+ SetLookFlag(m_pEventEntity, true);
+
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
+
+ } else if (CGeneral::GetRandomNumber() & 3) {
+ ClearLookFlag();
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
+
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ Say(SOUND_PED_CHAT_EVENT);
+
+ } else {
+ ClearInvestigateEvent();
+ }
+ }
+ break;
+ case EVENT_FIRE:
+ case EVENT_EXPLOSION:
+
+ if (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+
+ if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else if (CGeneral::GetRandomNumber() & 3) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));
+ Say(SOUND_PED_CHAT_EVENT);
+
+ } else {
+ m_standardTimer = 0;
+ }
+
+ } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+
+ if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) {
+ if (CGeneral::GetRandomNumber() & 1)
+ animToPlay = ANIM_IDLE_HBHB;
+ else
+ animToPlay = ANIM_XPRESS_SCRATCH;
+
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
+
+ } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (CGeneral::GetRandomNumber() & 1) {
+ animToPlay = ANIM_IDLE_STANCE;
+ animGroup = m_animGroup;
+ } else {
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ animGroup = ASSOCGRP_STD;
+ }
+
+ CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else {
+ if (CGeneral::GetRandomNumber() & 1) {
+ animToPlay = ANIM_IDLE_STANCE;
+ animGroup = m_animGroup;
+ } else {
+ animToPlay = ANIM_IDLE_HBHB;
+ animGroup = ASSOCGRP_STD;
+ }
+
+ CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ }
+ Say(SOUND_PED_CHAT_EVENT);
+ }
+ break;
+ case EVENT_ICECREAM:
+ case EVENT_SHOPSTALL:
+
+ m_fRotationDest = m_fAngleToEvent;
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+
+ if (m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (m_eventType == EVENT_ICECREAM)
+ animToPlay = ANIM_IDLE_CHAT;
+ else
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ClearInvestigateEvent();
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ ClearInvestigateEvent();
+ }
+ }
+ } else {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ } else {
+ m_vecSeekPos.x = m_eventOrThreat.x;
+ m_vecSeekPos.y = m_eventOrThreat.y;
+ m_vecSeekPos.z = GetPosition().z;
+ Seek();
+
+ if (m_eventType < EVENT_ICECREAM) {
+ if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {
+ SetMoveState(PEDMOVE_RUN);
+ return;
+ }
+ }
+ if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+ if (distSqr > sq(1.2f)) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) {
+ SetMoveState(PEDMOVE_STILL);
+ return;
+ }
+ }
+
+ SetMoveState(PEDMOVE_WALK);
+ }
+}
+
+void
+CPed::ClearInvestigateEvent(void)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ if (m_eventType > EVENT_EXPLOSION)
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 15000;
+
+ bGonnaInvestigateEvent = false;
+ m_pEventEntity = nil;
+ ClearLookFlag();
+ RestorePreviousState();
+ if(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)
+ SetMoveState(PEDMOVE_WALK);
+}
+
+bool
+CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)
+{
+ CPlayerPed *player = FindPlayerPed();
+ float dieDelta = 4.0f;
+ float dieSpeed = 0.0f;
+ AnimationId dieAnim = ANIM_KO_SHOT_FRONT1;
+ bool headShot = false;
+ bool willLinger = false;
+ int random;
+
+ if (player == this) {
+ if (!player->m_bCanBeDamaged)
+ return false;
+
+ player->AnnoyPlayerPed(false);
+ }
+
+ if (DyingOrDead())
+ return false;
+
+ if (!bUsesCollision && method != WEAPONTYPE_DROWNING)
+ return false;
+
+ if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() &&
+ method != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION)
+ return false;
+
+ float healthImpact;
+ if (IsPlayer())
+ healthImpact = damage * 0.33f;
+ else
+ healthImpact = damage * m_pedStats->m_defendWeakness;
+
+ bool detectDieAnim = true;
+ if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) {
+ if (!IsPedHeadAbovePos(-0.3f)) {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_FLOOR_HIT_F;
+ else
+ dieAnim = ANIM_FLOOR_HIT;
+ dieDelta *= 2.0f;
+ dieSpeed = 0.5f;
+ detectDieAnim = false;
+ } else if (m_nPedState == PED_FALL) {
+ dieAnim = NUM_ANIMS;
+ detectDieAnim = false;
+ }
+ }
+ if (detectDieAnim) {
+ switch (method) {
+ case WEAPONTYPE_UNARMED:
+ if (bMeleeProof)
+ return false;
+
+ if (m_nPedState == PED_FALL) {
+ if (IsPedHeadAbovePos(-0.3f)) {
+ dieAnim = NUM_ANIMS;
+ } else {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_FLOOR_HIT_F;
+ else
+ dieAnim = ANIM_FLOOR_HIT;
+ dieDelta = dieDelta * 2.0f;
+ dieSpeed = 0.5f;
+ }
+ } else {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WEAPONTYPE_BASEBALLBAT:
+ if (bMeleeProof)
+ return false;
+
+ if (m_nPedState == PED_FALL) {
+ if (IsPedHeadAbovePos(-0.3f)) {
+ dieAnim = NUM_ANIMS;
+ } else {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_FLOOR_HIT_F;
+ else
+ dieAnim = ANIM_FLOOR_HIT;
+ dieDelta = dieDelta * 2.0f;
+ dieSpeed = 0.5f;
+ }
+ } else {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WEAPONTYPE_COLT45:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SHOTGUN:
+ case WEAPONTYPE_AK47:
+ case WEAPONTYPE_M16:
+ case WEAPONTYPE_SNIPERRIFLE:
+ if (bBulletProof)
+ return false;
+
+ bool dontRemoveLimb;
+ if (IsPlayer() || bNoCriticalHits)
+ dontRemoveLimb = true;
+ else {
+ switch (method) {
+ case WEAPONTYPE_SNIPERRIFLE:
+ dontRemoveLimb = false;
+ break;
+ case WEAPONTYPE_M16:
+ dontRemoveLimb = false;
+ break;
+ case WEAPONTYPE_SHOTGUN:
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
+ break;
+ default:
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
+ break;
+ }
+ }
+
+ if (dontRemoveLimb) {
+ if (method == WEAPONTYPE_SHOTGUN) {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ } else
+ dieAnim = ANIM_KO_SHOT_FRONT1;
+
+ willLinger = false;
+ } else {
+ switch (pedPiece) {
+ case PEDPIECE_TORSO:
+ willLinger = false;
+ dieAnim = ANIM_KO_SHOT_FRONT1;
+ break;
+ case PEDPIECE_MID:
+ willLinger = false;
+ dieAnim = ANIM_KO_SHOT_STOM;
+ break;
+ case PEDPIECE_LEFTARM:
+ dieAnim = ANIM_KO_SHOT_ARML;
+ RemoveBodyPart(PED_UPPERARML, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_RIGHTARM:
+ dieAnim = ANIM_KO_SHOT_ARMR;
+ RemoveBodyPart(PED_UPPERARMR, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_LEFTLEG:
+ dieAnim = ANIM_KO_SHOT_LEGL;
+ RemoveBodyPart(PED_UPPERLEGL, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_RIGHTLEG:
+ dieAnim = ANIM_KO_SHOT_LEGR;
+ RemoveBodyPart(PED_UPPERLEGR, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_HEAD:
+ dieAnim = ANIM_KO_SHOT_FACE;
+ RemoveBodyPart(PED_HEAD, direction);
+ headShot = true;
+ willLinger = true;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_EXPLOSION:
+ if (bExplosionProof)
+ return false;
+
+ if (CGame::nastyGame && !IsPlayer() && !bInVehicle &&
+ 1.0f + healthImpact > m_fArmour + m_fHealth) {
+
+ random = CGeneral::GetRandomNumber();
+ if (random & 1)
+ RemoveBodyPart(PED_UPPERARML, direction);
+ if (random & 2)
+ RemoveBodyPart(PED_UPPERLEGR, direction);
+ if (random & 4)
+ RemoveBodyPart(PED_HEAD, direction);
+ if (random & 8)
+ RemoveBodyPart(PED_UPPERARMR, direction);
+ if (random & 0x10)
+ RemoveBodyPart(PED_UPPERLEGL, direction);
+ if (bBodyPartJustCameOff)
+ willLinger = true;
+ }
+ // fall through
+ case WEAPONTYPE_MOLOTOV:
+ if (bExplosionProof)
+ return false;
+
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ break;
+ case WEAPONTYPE_FLAMETHROWER:
+ if (bFireProof)
+ return false;
+
+ dieAnim = ANIM_KO_SHOT_FRONT1;
+ break;
+ case WEAPONTYPE_RAMMEDBYCAR:
+ case WEAPONTYPE_RUNOVERBYCAR:
+ if (bCollisionProof)
+ return false;
+
+ random = CGeneral::GetRandomNumber() & 3;
+ switch (random) {
+ case 0:
+ if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
+ && (pedPiece != PEDPIECE_MID || random != 1)) {
+ if (pedPiece == PEDPIECE_RIGHTARM && random > 1
+ || pedPiece == PEDPIECE_MID && random == 2)
+
+ dieAnim = ANIM_KO_SPIN_L;
+ else
+ dieAnim = ANIM_KO_SKID_FRONT;
+ } else
+ dieAnim = ANIM_KO_SPIN_R;
+
+ break;
+ case 1:
+ if (m_nPedState == PED_DIVE_AWAY)
+ dieAnim = ANIM_KD_LEFT;
+ else
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
+ && (pedPiece != PEDPIECE_MID || random != 1)) {
+ if ((pedPiece != PEDPIECE_RIGHTARM || random <= 1)
+ && (pedPiece != PEDPIECE_MID || random != 2)) {
+ dieAnim = ANIM_KO_SKID_BACK;
+ } else {
+ dieAnim = ANIM_KD_RIGHT;
+ }
+ } else
+ dieAnim = ANIM_KD_LEFT;
+ break;
+ case 3:
+ if (m_nPedState == PED_DIVE_AWAY)
+ dieAnim = ANIM_KD_RIGHT;
+ else
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ if (damagedBy) {
+ CVehicle *vehicle = (CVehicle*)damagedBy;
+ if (method == WEAPONTYPE_RAMMEDBYCAR) {
+ float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
+ dieDelta = 8.0f * vehSpeed + 4.0f;
+ } else {
+ float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
+ dieDelta = 12.0f * vehSpeed + 4.0f;
+ dieSpeed = 16.0f * vehSpeed + 1.0f;
+ }
+ }
+ break;
+ case WEAPONTYPE_DROWNING:
+ dieAnim = ANIM_DROWN;
+ break;
+ case WEAPONTYPE_FALL:
+ if (bCollisionProof)
+ return false;
+
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) {
+ if (player == this)
+ CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds();
+
+ if (healthImpact < m_fArmour) {
+ m_fArmour = m_fArmour - healthImpact;
+ healthImpact = 0.0f;
+ } else {
+ healthImpact = healthImpact - m_fArmour;
+ m_fArmour = 0.0f;
+ }
+ }
+
+ if (healthImpact != 0.0f) {
+ if (player == this)
+ CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds();
+
+ m_lastWepDam = method;
+ }
+
+ if (m_fHealth - healthImpact >= 1.0f && !willLinger) {
+ m_fHealth -= healthImpact;
+ return false;
+ }
+
+ if (bInVehicle) {
+ if (method != WEAPONTYPE_DROWNING) {
+#ifdef VC_PED_PORTS
+ if (m_pMyVehicle) {
+ if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) {
+ if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ }
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
+ m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ if (m_pMyVehicle->CanPedExitCar()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
+ } else {
+ m_fHealth = 0.0f;
+ if (m_pMyVehicle && m_pMyVehicle->pDriver == this) {
+ SetRadioStation();
+ m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ }
+ SetDie(dieAnim, dieDelta, dieSpeed);
+ /*
+ if (damagedBy == FindPlayerPed() && damagedBy != this) {
+ // PlayerInfo stuff
+ }
+ */
+ }
+ for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) {
+ CPed* passenger = m_pMyVehicle->pPassengers[i];
+ if (passenger && passenger != this && damagedBy)
+ passenger->ReactToAttack(damagedBy);
+ }
+
+ CPed *driverOfVeh = m_pMyVehicle->pDriver;
+ if (driverOfVeh && driverOfVeh != this && damagedBy)
+ driverOfVeh->ReactToAttack(damagedBy);
+
+ if (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) {
+ CDarkel::RegisterKillByPlayer(this, method, headShot);
+ m_threatEntity = FindPlayerPed();
+ } else {
+ CDarkel::RegisterKillNotByPlayer(this, method);
+ }
+ }
+#endif
+ m_fHealth = 1.0f;
+ return false;
+ }
+ m_fHealth = 0.0f;
+ if (player == this)
+ m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED);
+
+ SetDie(NUM_ANIMS, 4.0f, 0.0f);
+ return true;
+ } else {
+ m_fHealth = 0.0f;
+ SetDie(dieAnim, dieDelta, dieSpeed);
+
+ if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) {
+
+ // There are PlayerInfo stuff here in VC
+ CDarkel::RegisterKillByPlayer(this, method, headShot);
+ m_threatEntity = player;
+ } else {
+ CDarkel::RegisterKillNotByPlayer(this, method);
+ }
+ if (method == WEAPONTYPE_DROWNING)
+ bIsInTheAir = false;
+
+ return true;
+ }
+}
+
+static RwObject*
+SetPedAtomicVisibilityCB(RwObject* object, void* data)
+{
+ if (data == nil)
+ RpAtomicSetFlags((RpAtomic*)object, 0);
+ return object;
+}
+
+static RwFrame*
+RecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data)
+{
+ RwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data);
+ RwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil);
+ return frame;
+}
+
+static RwObject*
+CloneAtomicToFrameCB(RwObject *frame, void *data)
+{
+ RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);
+ RpAtomicSetFrame(newAtomic, (RwFrame*)data);
+ RpClumpAddAtomic(flyingClumpTemp, newAtomic);
+ CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);
+ return frame;
+}
+
+static RwFrame*
+RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)
+{
+ RwFrame *newFrame = RwFrameCreate();
+ RwFrameAddChild((RwFrame*)data, newFrame);
+ RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);
+ RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);
+ RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);
+ return newFrame;
+}
+
+void
+CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
+{
+ RwFrame *frame;
+ CVector pos;
+
+ frame = m_pFrames[nodeId]->frame;
+ if (frame) {
+ if (CGame::nastyGame) {
+#ifdef PED_SKIN
+ if(!IsClumpSkinned(GetClump()))
+#endif
+ {
+#ifdef DEBUGMENU
+ if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
+#else
+ if (nodeId != PED_HEAD)
+#endif
+ SpawnFlyingComponent(nodeId, direction);
+
+ RecurseFrameChildrenVisibilityCB(frame, nil);
+ }
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ TransformToNode(pos, PED_HEAD);
+
+ if (CEntity::GetIsOnScreen()) {
+ CParticle::AddParticle(PARTICLE_TEST, pos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil, 0.1f, 0, 0, 0, 0);
+
+ for (int i = 0; i < 16; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
+ pos,
+ CVector(0.0f, 0.0f, 0.03f),
+ nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ bBodyPartJustCameOff = true;
+ m_bodyPartBleeding = nodeId;
+ }
+ } else {
+ printf("Trying to remove ped component");
+ }
+}
+
+CObject*
+CPed::SpawnFlyingComponent(int pedNode, int8 direction)
+{
+ if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
+ return nil;
+
+#ifdef PED_SKIN
+ assert(!IsClumpSkinned(GetClump()));
+#endif
+
+ CObject *obj = new CObject();
+ if (!obj)
+ return nil;
+
+ RwFrame *frame = RwFrameCreate();
+ RpClump *clump = RpClumpCreate();
+ RpClumpSetFrame(clump, frame);
+ RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame);
+ *RwFrameGetMatrix(frame) = *matrix;
+
+ flyingClumpTemp = clump;
+ RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame);
+ RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame);
+ flyingClumpTemp = nil;
+ switch (pedNode) {
+ case PED_HEAD:
+ // So popping head would have wheel collision. They disabled it anyway
+ obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
+ break;
+ case PED_UPPERARML:
+ case PED_UPPERARMR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTB);
+ obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
+ break;
+ case PED_UPPERLEGL:
+ case PED_UPPERLEGR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTA);
+ obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
+ break;
+ default:
+ break;
+ }
+ obj->RefModelInfo(GetModelIndex());
+ obj->AttachToRwObject((RwObject*)clump);
+ obj->m_fMass = 15.0f;
+ obj->m_fTurnMass = 5.0f;
+ obj->m_fAirResistance = 0.99f;
+ obj->m_fElasticity = 0.03f;
+ obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
+ obj->ObjectCreatedBy = TEMP_OBJECT;
+ obj->SetIsStatic(false);
+ obj->bIsPickup = false;
+ obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX;
+
+ // life time - the more objects the are, the shorter this one will live
+ CObject::nNoTempObjects++;
+ if (CObject::nNoTempObjects > 20)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
+ else if (CObject::nNoTempObjects > 10)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
+ else
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
+
+ CVector localForcePos, forceDir;
+
+ if (direction == 2) {
+ obj->m_vecMoveSpeed = 0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = GetForward();
+ } else {
+ obj->m_vecMoveSpeed = -0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = -GetForward();
+ }
+ obj->ApplyTurnForce(forceDir, localForcePos);
+ CWorld::Add(obj);
+
+ return obj;
+}
+
+void
+CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
+{
+ CVector pos2 = CVector(
+ pos.x,
+ pos.y,
+ pos.z + 0.1f
+ );
+
+ if (!IsPlayer() || evenOnPlayer) {
+ ++CStats::HeadsPopped;
+
+ // BUG: This condition will always return true. Even fixing it won't work, because these states are unused.
+ // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {
+ SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ // }
+
+ bBodyPartJustCameOff = true;
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150;
+
+ CParticle::AddParticle(PARTICLE_TEST, pos2,
+ CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0);
+
+ if (CEntity::GetIsOnScreen()) {
+ for(int i=0; i < 32; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
+ pos2, CVector(0.0f, 0.0f, 0.03f),
+ nil, 0.0f, 0, 0, 0, 0);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ CParticle::AddParticle(PARTICLE_DEBRIS2,
+ pos2,
+ CVector(0.0f, 0.0f, 0.01f),
+ nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+}
+
+uint8
+CPed::DoesLOSBulletHitPed(CColPoint &colPoint)
+{
+#ifdef FIX_BUGS
+ return 1;
+#else
+ uint8 retVal = 2;
+
+ float headZ = GetNodePosition(PED_HEAD).z;
+
+ if (m_nPedState == PED_FALL)
+ retVal = 1;
+
+ float colZ = colPoint.point.z;
+ if (colZ < headZ)
+ retVal = 1;
+
+ if (headZ + 0.2f <= colZ)
+ retVal = 0;
+
+ return retVal;
+#endif
+}
+
+bool
+CPed::IsPedHeadAbovePos(float zOffset)
+{
+ return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z;
+}
+
+bool
+CPed::PlacePedOnDryLand(void)
+{
+ float waterLevel = 0.0f;
+ CEntity *foundEnt = nil;
+ CColPoint foundCol;
+ float foundColZ;
+
+ CWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel);
+
+ CVector potentialGround = GetPosition();
+ potentialGround.z = waterLevel;
+
+ if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
+ return false;
+
+ CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
+ potentialGroundDist.z = 0.0f;
+ potentialGroundDist.Normalise();
+
+ CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;
+ posToCheck.z = 3.0f + waterLevel;
+
+ if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) {
+ foundColZ = foundCol.point.z;
+ if (foundColZ >= waterLevel) {
+ posToCheck.z = 0.8f + foundColZ;
+ SetPosition(posToCheck);
+ bIsStanding = true;
+ bWasStanding = true;
+ return true;
+ }
+ }
+
+ posToCheck = 5.0f * potentialGroundDist + GetPosition();
+ posToCheck.z = 3.0f + waterLevel;
+
+ if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil))
+ return false;
+
+ foundColZ = foundCol.point.z;
+ if (foundColZ < waterLevel)
+ return false;
+
+ posToCheck.z = 0.8f + foundColZ;
+ SetPosition(posToCheck);
+ bIsStanding = true;
+ bWasStanding = true;
+ return true;
+}
+
+void
+CPed::CollideWithPed(CPed *collideWith)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId animToPlay;
+
+ bool weAreMissionChar = CharCreatedBy == MISSION_CHAR;
+ bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR;
+ CVector posDiff = collideWith->GetPosition() - GetPosition();
+ int waitTime = 0;
+
+ if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {
+ bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;
+ bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;
+
+ if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
+
+ if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)
+ && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT
+#ifdef VC_PED_PORTS
+ || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith
+ || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this
+#endif
+ )) {
+
+ if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
+
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+
+ if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) {
+
+ if (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) {
+
+ if (collideWith->m_nMoveState != PEDMOVE_STILL
+ && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) {
+ float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
+ float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
+
+ if (seekPosDist <= heAndSeekPosDist) {
+ waitTime = 1000;
+ collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
+ collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ } else {
+ waitTime = 500;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ }
+ } else if (collideWith->m_nMoveState == PEDMOVE_STILL) {
+ SetDirectionToWalkAroundObject(collideWith);
+ }
+ } else {
+ if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
+ || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
+ (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
+ SetDirectionToWalkAroundObject(collideWith);
+ if (!weAreMissionChar)
+ Say(SOUND_PED_CHAT);
+ } else {
+ SetEvasiveStep(collideWith, 2);
+ }
+ }
+ } else {
+ if (m_pedStats->m_temper <= m_pedStats->m_fear
+ || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED
+ || weAreMissionChar
+ || collideWith->m_nPedType == PEDTYPE_CIVFEMALE
+ || collideWith->m_nPedType == m_nPedType
+ || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ SetDirectionToWalkAroundObject(collideWith);
+ Say(SOUND_PED_CHAT);
+ } else {
+ TurnBody();
+ SetAttack(collideWith);
+#ifdef VC_PED_PORTS
+ m_fRotationCur = 0.3f + m_fRotationCur;
+ m_fRotationDest = m_fRotationCur;
+#endif
+ }
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);
+ }
+ }
+ } else {
+#ifdef VC_PED_PORTS
+ if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+#else
+ if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+#endif
+ if (heLooksToUs) {
+ SetEvasiveStep(collideWith, 1);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ }
+ } else if (weDontLookToHim && IsPedInControl()) {
+
+ if (m_pedStats != collideWith->m_pedStats) {
+
+ if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper
+#ifdef VC_PED_PORTS
+ || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer
+#endif
+ ) {
+
+ if (collideWith->IsPlayer()) {
+ // He's on our right side
+ if (DotProduct(posDiff,GetRight()) <= 0.0f)
+ m_fRotationCur -= m_headingRate;
+ else
+ m_fRotationCur += m_headingRate;
+ } else {
+ // He's on our right side
+ if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f)
+ collideWith->m_fRotationCur -= collideWith->m_headingRate;
+ else
+ collideWith->m_fRotationCur += collideWith->m_headingRate;
+ }
+ } else {
+ SetLookFlag(collideWith, false);
+ TurnBody();
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
+ animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+#ifdef VC_PED_PORTS
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
+#endif
+ if (!heIsMissionChar) {
+ CVector2D posDiff2D(posDiff);
+ int direction = collideWith->GetLocalDirection(posDiff2D);
+ collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5);
+ }
+ }
+ }
+ }
+ }
+ } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
+#ifdef VC_PED_PORTS
+ || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
+#endif
+ ) {
+ // He looks us and we're not at his right side
+ if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
+ CVector moveForce = GetRight();
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
+ animToPlay = ANIM_HIT_LEFT;
+ else
+ animToPlay = ANIM_SHOT_LEFT_PARTIAL;
+ } else if (heLooksToUs) {
+ CVector moveForce = GetRight() * -1.0f;
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
+ animToPlay = ANIM_HIT_RIGHT;
+ else
+ animToPlay = ANIM_SHOT_RIGHT_PARTIAL;
+ } else {
+ if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
+ animToPlay = ANIM_HIT_BACK;
+ else
+ animToPlay = ANIM_SHOT_BACK_PARTIAL;
+ }
+
+ if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) {
+ animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f);
+ animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ if (m_nPedState == PED_ATTACK)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ }
+ } else {
+ // We're at his right side
+ if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) {
+ CVector moveForce = GetRight() * -1.0f;
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (heLooksToUs)
+ animToPlay = ANIM_KO_SPIN_L;
+ else
+ animToPlay = ANIM_KD_RIGHT;
+ } else {
+ CVector moveForce = GetRight();
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (heLooksToUs)
+ animToPlay = ANIM_KO_SPIN_R;
+ else
+ animToPlay = ANIM_KD_LEFT;
+ }
+
+ if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+
+ collideWith->SetFall(3000, animToPlay, 0);
+ }
+ } else {
+ if (!IsPedInControl())
+ return;
+
+ if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL)
+ return;
+
+ if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
+
+ if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) {
+
+ if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){
+ SetEvasiveStep(collideWith, 2);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ } else if (collideWith->m_nMoveState > PEDMOVE_WALK) {
+ waitTime = 2000;
+ SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime);
+ }
+ }
+ } else if (heLooksToUs
+ && collideWith->m_nPedState != PED_STEP_AWAY
+ && m_nPedState != PED_STEP_AWAY
+ && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+
+ SetEvasiveStep(collideWith, 1);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ }
+ }
+
+ if (IsPlayer()) {
+ SetLookFlag(collideWith, true);
+ SetLookTimer(800);
+ }
+ } else {
+ bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;
+ SetFindPathAndFlee(collideWith, 5000, !isRunning);
+ }
+}
+
+void
+CPed::KillPedWithCar(CVehicle *car, float impulse)
+{
+ CVehicleModelInfo *vehModel;
+ CColModel *vehColModel;
+ uint8 damageDir;
+ PedNode nodeToDamage;
+ eWeaponType killMethod;
+
+ if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {
+ if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)
+ this->m_pCollidingEntity = car;
+ return;
+ }
+
+ if (m_nPedState == PED_DEAD)
+ return;
+
+ if (m_pCurSurface) {
+ if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer()))
+ return;
+ }
+
+ CVector distVec = GetPosition() - car->GetPosition();
+
+ if ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) {
+ nodeToDamage = PED_TORSO;
+ killMethod = WEAPONTYPE_RAMMEDBYCAR;
+ uint8 randVal = CGeneral::GetRandomNumber() & 3;
+
+ if (car == FindPlayerVehicle()) {
+ float carSpeed = car->m_vecMoveSpeed.Magnitude();
+ uint8 shakeFreq;
+ if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) {
+ shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f;
+ } else {
+ shakeFreq = 250.0f;
+ }
+ CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);
+ }
+ bIsStanding = false;
+ damageDir = GetLocalDirection(-m_vecMoveSpeed);
+ vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex());
+ vehColModel = vehModel->GetColModel();
+ float carRightAndDistDotProd = DotProduct(distVec, car->GetRight());
+
+ if (car->GetModelIndex() == MI_TRAIN) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ nodeToDamage = PED_HEAD;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0f;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ // Car doesn't look to us
+ } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){
+
+ if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) {
+
+ // We're at the right of the car
+ if (carRightAndDistDotProd <= 0.0f)
+ nodeToDamage = PED_UPPERARML;
+ else
+ nodeToDamage = PED_UPPERARMR;
+
+ if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0f;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ }
+ } else {
+ float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());
+
+ // carFrontAndDistDotProd <= 0.0 car looks to us
+ if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ nodeToDamage = PED_HEAD;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0f;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ } else {
+ nodeToDamage = PED_MID;
+ float vehColMaxY = vehColModel->boundingBox.max.y;
+ float vehColMinY = vehColModel->boundingBox.min.y;
+ float vehColMaxZ = vehColModel->boundingBox.max.z;
+ float carFrontZ = car->GetForward().z;
+ float carHighestZ, carLength;
+
+ if (carFrontZ < -0.2f) {
+ // Highest point of car's back
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
+ carLength = vehColMaxY - vehColMinY;
+
+ } else if (carFrontZ > 0.1f) {
+ // Highest point of car's front
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ float highestZDist = carHighestZ - GetPosition().z;
+ if (highestZDist > 0.0f) {
+ GetMatrix().GetPosition().z += 0.5f * highestZDist;
+ carHighestZ += highestZDist * 0.25f;
+ }
+ carLength = vehColMaxY;
+
+ } else {
+ // Highest point of car's front
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ carLength = vehColMaxY;
+ }
+
+ float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude());
+
+ // TODO: What are we doing down here?
+ float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;
+
+ // After this point, distVec isn't distVec anymore.
+ distVec = car->m_vecMoveSpeed;
+ distVec.Normalise();
+ distVec *= 0.2 * unknown;
+
+ if (damageDir != 1 && damageDir != 3)
+ distVec.z += unknown;
+ else
+ distVec.z += 1.5f * unknown;
+
+ m_vecMoveSpeed = distVec;
+ damageDir += 2;
+ if (damageDir > 3)
+ damageDir = damageDir - 4;
+
+ if (car->m_vehType == VEHICLE_TYPE_CAR) {
+ CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
+
+ if (bonnet) {
+ if (CGeneral::GetRandomNumber() & 1) {
+ bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));
+ } else {
+ bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));
+ }
+ CVector forceDir = car->GetUp() * 10.0f;
+ bonnet->ApplyTurnForce(forceDir, car->GetForward());
+ }
+ }
+ }
+ }
+ }
+
+ if (car->pDriver) {
+ CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000);
+ }
+
+ ePedPieceTypes pieceToDamage;
+ switch (nodeToDamage) {
+ case PED_HEAD:
+ pieceToDamage = PEDPIECE_HEAD;
+ break;
+ case PED_UPPERARML:
+ pieceToDamage = PEDPIECE_LEFTARM;
+ break;
+ case PED_UPPERARMR:
+ pieceToDamage = PEDPIECE_RIGHTARM;
+ break;
+ default:
+ pieceToDamage = PEDPIECE_MID;
+ break;
+ }
+ InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);
+
+ if (DyingOrDead()
+ && bIsPedDieAnimPlaying && !m_pCollidingEntity) {
+ m_pCollidingEntity = car;
+ }
+ if (nodeToDamage == PED_MID)
+ bKnockedUpIntoAir = true;
+ else
+ bKnockedUpIntoAir = false;
+
+ distVec.Normalise();
+
+#ifdef VC_PED_PORTS
+ distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
+#endif
+ car->ApplyMoveForce(distVec * -100.0f);
+ Say(SOUND_PED_DEFEND);
+
+ } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f
+ || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {
+
+ bIsStanding = false;
+ uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed);
+ float damage;
+ if (IsPlayer() && car->GetModelIndex() == MI_TRAIN)
+ damage = 150.0f;
+ else
+ damage = 30.0f;
+
+ InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);
+ SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true);
+
+ if (OnGround() && !m_pCollidingEntity &&
+ (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
+
+ m_pCollidingEntity = car;
+ }
+
+ bKnockedUpIntoAir = false;
+ if (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) {
+ m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f;
+ }
+ m_vecMoveSpeed.z = 0.0f;
+ distVec.Normalise();
+#ifdef VC_PED_PORTS
+ distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
+#endif
+ car->ApplyMoveForce(distVec * -60.0f);
+ Say(SOUND_PED_DEFEND);
+ }
+
+#ifdef VC_PED_PORTS
+ // Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
+ if (IsGangMember()) {
+ CPed *driver = car->pDriver;
+ if (driver && driver->IsPlayer()
+#ifdef FIX_BUGS
+ && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver)
+#endif
+ ) {
+ RegisterThreatWithGangPeds(driver);
+ }
+ }
+#endif
+} \ No newline at end of file
diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp
deleted file mode 100644
index 1f7a95b4..00000000
--- a/src/peds/PedStats.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "common.h"
-
-#include "General.h"
-#include "FileMgr.h"
-#include "PedStats.h"
-
-CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS];
-
-void
-CPedStats::Initialise(void)
-{
- int i;
-
- debug("Initialising CPedStats...\n");
- for(i = 0; i < NUM_PEDSTATS; i++){
- ms_apPedStats[i] = new CPedStats;
- ms_apPedStats[i]->m_type = PEDSTAT_PLAYER;
- ms_apPedStats[i]->m_name[8] = 'R'; // WHAT?
- ms_apPedStats[i]->m_fleeDistance = 20.0f;
- ms_apPedStats[i]->m_headingChangeRate = 15.0f;
- ms_apPedStats[i]->m_fear = 50;
- ms_apPedStats[i]->m_temper = 50;
- ms_apPedStats[i]->m_lawfulness = 50;
- ms_apPedStats[i]->m_sexiness = 50;
- ms_apPedStats[i]->m_attackStrength = 1.0f;
- ms_apPedStats[i]->m_defendWeakness = 1.0f;
- ms_apPedStats[i]->m_flags = 0;
- }
- debug("Loading pedstats data...\n");
- CPedStats::LoadPedStats();
- debug("CPedStats ready\n");
-}
-
-void
-CPedStats::Shutdown(void)
-{
- int i;
- debug("Shutting down CPedStats...\n");
- for(i = 0; i < NUM_PEDSTATS; i++)
- delete ms_apPedStats[i];
- debug("CPedStats shut down\n");
-}
-
-void
-CPedStats::LoadPedStats(void)
-{
- char *buf;
- char line[256];
- char name[32];
- size_t bp, buflen;
- int lp, linelen;
- int type;
- float fleeDist, headingChangeRate, attackStrength, defendWeakness;
- int fear, temper, lawfullness, sexiness, flags;
-
-
- type = 0;
- buf = new char[16 * 1024];
-
- CFileMgr::SetDir("DATA");
- buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r");
- CFileMgr::SetDir("");
-
- for(bp = 0; bp < buflen; ){
- // read file line by line
- for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){
- if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t')
- line[linelen++] = ' ';
- else
- line[linelen++] = buf[bp];
- }
- bp++;
- line[linelen] = '\0';
-
- // skip white space
- for(lp = 0; line[lp] <= ' '; lp++);
-
- if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
- line[lp] == '#')
- continue;
-
- sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d",
- name,
- &fleeDist,
- &headingChangeRate,
- &fear,
- &temper,
- &lawfullness,
- &sexiness,
- &attackStrength,
- &defendWeakness,
- &flags);
- ms_apPedStats[type]->m_type = (ePedStats)type;
- strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy
- ms_apPedStats[type]->m_fleeDistance = fleeDist;
- ms_apPedStats[type]->m_headingChangeRate = headingChangeRate;
- ms_apPedStats[type]->m_fear = fear;
- ms_apPedStats[type]->m_temper = temper;
- ms_apPedStats[type]->m_lawfulness = lawfullness;
- ms_apPedStats[type]->m_sexiness = sexiness;
- ms_apPedStats[type]->m_attackStrength = attackStrength;
- ms_apPedStats[type]->m_defendWeakness = defendWeakness;
- ms_apPedStats[type]->m_flags = flags;
- type++;
- }
-
- delete[] buf;
-}
-
-ePedStats
-CPedStats::GetPedStatType(char *name)
-{
- for(uint16 type = 0; type < NUM_PEDSTATS; type++)
- if(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name))
- return (ePedStats) type;
-
- return NUM_PEDSTATS;
-}
diff --git a/src/peds/PedStats.h b/src/peds/PedStats.h
deleted file mode 100644
index df97bdb8..00000000
--- a/src/peds/PedStats.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#pragma once
-
-enum ePedStats
-{
- PEDSTAT_PLAYER,
- PEDSTAT_COP,
- PEDSTAT_MEDIC,
- PEDSTAT_FIREMAN,
- PEDSTAT_GANG1,
- PEDSTAT_GANG2,
- PEDSTAT_GANG3,
- PEDSTAT_GANG4,
- PEDSTAT_GANG5,
- PEDSTAT_GANG6,
- PEDSTAT_GANG7,
- PEDSTAT_STREET_GUY,
- PEDSTAT_SUIT_GUY,
- PEDSTAT_SENSIBLE_GUY,
- PEDSTAT_GEEK_GUY,
- PEDSTAT_OLD_GUY,
- PEDSTAT_TOUGH_GUY,
- PEDSTAT_STREET_GIRL,
- PEDSTAT_SUIT_GIRL,
- PEDSTAT_SENSIBLE_GIRL,
- PEDSTAT_GEEK_GIRL,
- PEDSTAT_OLD_GIRL,
- PEDSTAT_TOUGH_GIRL,
- PEDSTAT_TRAMP_MALE,
- PEDSTAT_TRAMP_FEMALE,
- PEDSTAT_TOURIST,
- PEDSTAT_PROSTITUTE,
- PEDSTAT_CRIMINAL,
- PEDSTAT_BUSKER,
- PEDSTAT_TAXIDRIVER,
- PEDSTAT_PSYCHO,
- PEDSTAT_STEWARD,
- PEDSTAT_SPORTSFAN,
- PEDSTAT_SHOPPER,
- PEDSTAT_OLDSHOPPER,
-
- NUM_PEDSTATS
-};
-
-// flags
-enum
-{
- STAT_PUNCH_ONLY = 1,
- STAT_CAN_KNEE_HEAD = 2,
- STAT_CAN_KICK = 4,
- STAT_CAN_ROUNDHOUSE = 8,
- STAT_NO_DIVE = 0x10,
- STAT_ONE_HIT_KNOCKDOWN = 0x20,
- STAT_SHOPPING_BAGS = 0x40,
- STAT_GUN_PANIC = 0x80
-};
-
-class CPedStats
-{
-public:
- ePedStats m_type;
- char m_name[24];
- float m_fleeDistance;
- float m_headingChangeRate;
- int8 m_fear;
- int8 m_temper;
- int8 m_lawfulness;
- int8 m_sexiness;
- float m_attackStrength;
- float m_defendWeakness;
- int16 m_flags;
-
- static CPedStats *ms_apPedStats[NUM_PEDSTATS];
-
- static void Initialise(void);
- static void Shutdown(void);
- static void LoadPedStats(void);
- static ePedStats GetPedStatType(char *name);
-};
-
-VALIDATE_SIZE(CPedStats, 0x34);
diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp
index 397cd71d..6e745bd7 100644
--- a/src/peds/PedType.cpp
+++ b/src/peds/PedType.cpp
@@ -1,9 +1,11 @@
#include "common.h"
+#include "General.h"
#include "FileMgr.h"
#include "PedType.h"
CPedType *CPedType::ms_apPedType[NUM_PEDTYPES];
+CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS];
void
CPedType::Initialise(void)
@@ -202,3 +204,114 @@ INITSAVEBUF
*ms_apPedType[i] = ReadSaveBuf<CPedType>(buf);
VALIDATESAVEBUF(size)
}
+
+void
+CPedStats::Initialise(void)
+{
+ int i;
+
+ debug("Initialising CPedStats...\n");
+ for(i = 0; i < NUM_PEDSTATS; i++){
+ ms_apPedStats[i] = new CPedStats;
+ ms_apPedStats[i]->m_type = PEDSTAT_PLAYER;
+ ms_apPedStats[i]->m_name[8] = 'R'; // WHAT?
+ ms_apPedStats[i]->m_fleeDistance = 20.0f;
+ ms_apPedStats[i]->m_headingChangeRate = 15.0f;
+ ms_apPedStats[i]->m_fear = 50;
+ ms_apPedStats[i]->m_temper = 50;
+ ms_apPedStats[i]->m_lawfulness = 50;
+ ms_apPedStats[i]->m_sexiness = 50;
+ ms_apPedStats[i]->m_attackStrength = 1.0f;
+ ms_apPedStats[i]->m_defendWeakness = 1.0f;
+ ms_apPedStats[i]->m_flags = 0;
+ }
+ debug("Loading pedstats data...\n");
+ CPedStats::LoadPedStats();
+ debug("CPedStats ready\n");
+}
+
+void
+CPedStats::Shutdown(void)
+{
+ int i;
+ debug("Shutting down CPedStats...\n");
+ for(i = 0; i < NUM_PEDSTATS; i++)
+ delete ms_apPedStats[i];
+ debug("CPedStats shut down\n");
+}
+
+void
+CPedStats::LoadPedStats(void)
+{
+ char *buf;
+ char line[256];
+ char name[32];
+ size_t bp, buflen;
+ int lp, linelen;
+ int type;
+ float fleeDist, headingChangeRate, attackStrength, defendWeakness;
+ int fear, temper, lawfullness, sexiness, flags;
+
+
+ type = 0;
+ buf = new char[16 * 1024];
+
+ CFileMgr::SetDir("DATA");
+ buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r");
+ CFileMgr::SetDir("");
+
+ for(bp = 0; bp < buflen; ){
+ // read file line by line
+ for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){
+ if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t')
+ line[linelen++] = ' ';
+ else
+ line[linelen++] = buf[bp];
+ }
+ bp++;
+ line[linelen] = '\0';
+
+ // skip white space
+ for(lp = 0; line[lp] <= ' '; lp++);
+
+ if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
+ line[lp] == '#')
+ continue;
+
+ sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d",
+ name,
+ &fleeDist,
+ &headingChangeRate,
+ &fear,
+ &temper,
+ &lawfullness,
+ &sexiness,
+ &attackStrength,
+ &defendWeakness,
+ &flags);
+ ms_apPedStats[type]->m_type = (ePedStats)type;
+ strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy
+ ms_apPedStats[type]->m_fleeDistance = fleeDist;
+ ms_apPedStats[type]->m_headingChangeRate = headingChangeRate;
+ ms_apPedStats[type]->m_fear = fear;
+ ms_apPedStats[type]->m_temper = temper;
+ ms_apPedStats[type]->m_lawfulness = lawfullness;
+ ms_apPedStats[type]->m_sexiness = sexiness;
+ ms_apPedStats[type]->m_attackStrength = attackStrength;
+ ms_apPedStats[type]->m_defendWeakness = defendWeakness;
+ ms_apPedStats[type]->m_flags = flags;
+ type++;
+ }
+
+ delete[] buf;
+}
+
+ePedStats
+CPedStats::GetPedStatType(char *name)
+{
+ for(uint16 type = 0; type < NUM_PEDSTATS; type++)
+ if(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name))
+ return (ePedStats) type;
+
+ return NUM_PEDSTATS;
+}
diff --git a/src/peds/PedType.h b/src/peds/PedType.h
index 3a765da1..3e23c249 100644
--- a/src/peds/PedType.h
+++ b/src/peds/PedType.h
@@ -92,3 +92,82 @@ public:
};
VALIDATE_SIZE(CPedType, 0x20);
+
+enum ePedStats
+{
+ PEDSTAT_PLAYER,
+ PEDSTAT_COP,
+ PEDSTAT_MEDIC,
+ PEDSTAT_FIREMAN,
+ PEDSTAT_GANG1,
+ PEDSTAT_GANG2,
+ PEDSTAT_GANG3,
+ PEDSTAT_GANG4,
+ PEDSTAT_GANG5,
+ PEDSTAT_GANG6,
+ PEDSTAT_GANG7,
+ PEDSTAT_STREET_GUY,
+ PEDSTAT_SUIT_GUY,
+ PEDSTAT_SENSIBLE_GUY,
+ PEDSTAT_GEEK_GUY,
+ PEDSTAT_OLD_GUY,
+ PEDSTAT_TOUGH_GUY,
+ PEDSTAT_STREET_GIRL,
+ PEDSTAT_SUIT_GIRL,
+ PEDSTAT_SENSIBLE_GIRL,
+ PEDSTAT_GEEK_GIRL,
+ PEDSTAT_OLD_GIRL,
+ PEDSTAT_TOUGH_GIRL,
+ PEDSTAT_TRAMP_MALE,
+ PEDSTAT_TRAMP_FEMALE,
+ PEDSTAT_TOURIST,
+ PEDSTAT_PROSTITUTE,
+ PEDSTAT_CRIMINAL,
+ PEDSTAT_BUSKER,
+ PEDSTAT_TAXIDRIVER,
+ PEDSTAT_PSYCHO,
+ PEDSTAT_STEWARD,
+ PEDSTAT_SPORTSFAN,
+ PEDSTAT_SHOPPER,
+ PEDSTAT_OLDSHOPPER,
+
+ NUM_PEDSTATS
+};
+
+// flags
+enum
+{
+ STAT_PUNCH_ONLY = 1,
+ STAT_CAN_KNEE_HEAD = 2,
+ STAT_CAN_KICK = 4,
+ STAT_CAN_ROUNDHOUSE = 8,
+ STAT_NO_DIVE = 0x10,
+ STAT_ONE_HIT_KNOCKDOWN = 0x20,
+ STAT_SHOPPING_BAGS = 0x40,
+ STAT_GUN_PANIC = 0x80
+};
+
+class CPedStats
+{
+public:
+ ePedStats m_type;
+ char m_name[24];
+ float m_fleeDistance;
+ float m_headingChangeRate;
+ int8 m_fear;
+ int8 m_temper;
+ int8 m_lawfulness;
+ int8 m_sexiness;
+ float m_attackStrength;
+ float m_defendWeakness;
+ int16 m_flags;
+
+ static CPedStats *ms_apPedStats[NUM_PEDSTATS];
+
+ static void Initialise(void);
+ static void Shutdown(void);
+ static void LoadPedStats(void);
+ static ePedStats GetPedStatType(char *name);
+};
+
+VALIDATE_SIZE(CPedStats, 0x34); \ No newline at end of file
diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h
index 628d64c2..a8013b34 100644
--- a/src/render/2dEffect.h
+++ b/src/render/2dEffect.h
@@ -78,12 +78,12 @@ public:
if(type == EFFECT_LIGHT){
if(light.corona)
RwTextureDestroy(light.corona);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
light.corona = nil;
#endif
if(light.shadow)
RwTextureDestroy(light.shadow);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
light.shadow = nil;
#endif
}
diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp
index 05ddbcdc..161418b9 100644
--- a/src/render/Clouds.cpp
+++ b/src/render/Clouds.cpp
@@ -44,23 +44,23 @@ void
CClouds::Shutdown(void)
{
RwTextureDestroy(gpCloudTex[0]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex[0] = nil;
#endif
RwTextureDestroy(gpCloudTex[1]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex[1] = nil;
#endif
RwTextureDestroy(gpCloudTex[2]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex[2] = nil;
#endif
RwTextureDestroy(gpCloudTex[3]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex[3] = nil;
#endif
RwTextureDestroy(gpCloudTex[4]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex[4] = nil;
#endif
}
diff --git a/src/render/Font.cpp b/src/render/Font.cpp
index f7f5fafc..65ab42ff 100644
--- a/src/render/Font.cpp
+++ b/src/render/Font.cpp
@@ -3,6 +3,9 @@
#include "Sprite2d.h"
#include "TxdStore.h"
#include "Font.h"
+#ifdef BUTTON_ICONS
+#include "FileMgr.h"
+#endif
void
AsciiToUnicode(const char *src, wchar *dst)
@@ -224,6 +227,12 @@ wchar foreign_table[128] = {
0, 174, 165, 166, 167, 0, 168, 0, 0, 169, 170, 171, 172, 0, 0, 0,
};
+#ifdef BUTTON_ICONS
+CSprite2d CFont::ButtonSprite[MAX_BUTTON_ICONS];
+int CFont::PS2Symbol = BUTTON_NONE;
+int CFont::ButtonsSlot = -1;
+#endif // BUTTON_ICONS
+
void
CFont::Initialise(void)
{
@@ -286,6 +295,34 @@ CFont::Initialise(void)
SetAlphaFade(255.0f);
SetDropShadowPosition(0);
CTxdStore::PopCurrentTxd();
+
+#ifdef BUTTON_ICONS
+ if (int file = CFileMgr::OpenFile("MODELS/X360BTNS.TXD")) {
+ CFileMgr::CloseFile(file);
+ ButtonsSlot = CTxdStore::AddTxdSlot("buttons");
+ CTxdStore::LoadTxd(ButtonsSlot, "MODELS/X360BTNS.TXD");
+ CTxdStore::AddRef(ButtonsSlot);
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(ButtonsSlot);
+#if 0 // unused
+ ButtonSprite[BUTTON_UP].SetTexture("up");
+ ButtonSprite[BUTTON_DOWN].SetTexture("down");
+ ButtonSprite[BUTTON_LEFT].SetTexture("left");
+ ButtonSprite[BUTTON_RIGHT].SetTexture("right");
+#endif
+ ButtonSprite[BUTTON_CROSS].SetTexture("cross");
+ ButtonSprite[BUTTON_CIRCLE].SetTexture("circle");
+ ButtonSprite[BUTTON_SQUARE].SetTexture("square");
+ ButtonSprite[BUTTON_TRIANGLE].SetTexture("triangle");
+ ButtonSprite[BUTTON_L1].SetTexture("l1");
+ ButtonSprite[BUTTON_L2].SetTexture("l2");
+ ButtonSprite[BUTTON_L3].SetTexture("l3");
+ ButtonSprite[BUTTON_R1].SetTexture("r1");
+ ButtonSprite[BUTTON_R2].SetTexture("r2");
+ ButtonSprite[BUTTON_R3].SetTexture("r3");
+ CTxdStore::PopCurrentTxd();
+ }
+#endif // BUTTON_ICONS
}
#ifdef MORE_LANGUAGES
@@ -334,6 +371,13 @@ CFont::ReloadFonts(uint8 set)
void
CFont::Shutdown(void)
{
+#ifdef BUTTON_ICONS
+ if (ButtonsSlot != -1) {
+ for (int i = 0; i < MAX_BUTTON_ICONS; i++)
+ ButtonSprite[i].Delete();
+ CTxdStore::RemoveTxdSlot(ButtonsSlot);
+ }
+#endif
Sprite[0].Delete();
Sprite[1].Delete();
Sprite[2].Delete();
@@ -359,7 +403,33 @@ CFont::InitPerFrame(void)
#endif
SetDropShadowPosition(0);
NewLine = 0;
+#ifdef BUTTON_ICONS
+ PS2Symbol = BUTTON_NONE;
+#endif
+}
+
+#ifdef BUTTON_ICONS
+void
+CFont::DrawButton(float x, float y)
+{
+ if (x <= 0.0f || x > SCREEN_WIDTH || y <= 0.0f || y > SCREEN_HEIGHT)
+ return;
+
+ if (PS2Symbol != BUTTON_NONE) {
+ CRect rect;
+ rect.left = x;
+ rect.top = Details.scaleY + Details.scaleY + y;
+ rect.right = Details.scaleY * 17.0f + x;
+ rect.bottom = Details.scaleY * 19.0f + y;
+
+ int vertexAlphaState;
+ RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+ ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, Details.color.a));
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState);
+ }
}
+#endif
void
CFont::PrintChar(float x, float y, wchar c)
@@ -642,7 +712,14 @@ CFont::GetNumberLines(float xstart, float ystart, wchar *s)
y = ystart;
while(*s){
+#ifdef FIX_BUGS
+ float f = Details.centre ? Details.centreSize :
+ Details.rightJustify ? xstart - Details.rightJustifyWrap :
+ Details.wrapX;
+#else
float f = (Details.centre ? Details.centreSize : Details.wrapX);
+#endif
+
#ifdef MORE_LANGUAGES
if (IsJapaneseFont())
f -= SCREEN_SCALE_X(21.0f * 2.0f);
@@ -722,8 +799,15 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s)
x = xstart;
y = ystart;
+#ifdef FIX_BUGS
+ float xEnd = Details.centre ? Details.centreSize :
+ Details.rightJustify ? xstart - Details.rightJustifyWrap :
+ Details.wrapX;
+#else
+ float xEnd = (Details.centre ? Details.centreSize : Details.wrapX);
+#endif
while(*s){
- if(x + GetStringWidth(s) > (Details.centre ? Details.centreSize : Details.wrapX)){
+ if(x + GetStringWidth(s) > xEnd){
// reached end of line
if(x > maxlength)
maxlength = x;
@@ -833,6 +917,15 @@ CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, f
c = *s - ' ';
if (Details.slant != 0.0f && !IsJapanese())
y = (Details.slantRefX - x) * Details.slant + Details.slantRefY;
+
+#ifdef BUTTON_ICONS
+ if (PS2Symbol != BUTTON_NONE) {
+ DrawButton(x, y);
+ x += Details.scaleY * 17.0f;
+ PS2Symbol = BUTTON_NONE;
+ }
+#endif
+
PrintChar(x, y, c);
x += GetCharacterSize(c);
if (c == 0 && (!NewLine || !IsJapanese())) // space
@@ -860,6 +953,40 @@ CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth)
}
#endif
+#ifdef XBOX_SUBTITLES
+void
+CFont::PrintStringFromBottom(float x, float y, wchar *str)
+{
+#ifdef MORE_LANGUAGES
+ if (IsJapaneseFont())
+ y -= (32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY) * GetNumberLines(x, y, str);
+ else
+#endif
+ y -= (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * GetNumberLines(x, y, str);
+ PrintString(x, y, str);
+}
+
+void
+CFont::PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor)
+{
+ CRGBA textColor = Details.color;
+ SetColor(outlineColor);
+ CVector2D offsets[] = { {1.f, 1.f}, {1.f, -1.f}, {-1.f, 1.f}, {-1.f, -1.f} };
+ for(int i = 0; i < ARRAY_SIZE(offsets); i++){
+ if (fromBottom)
+ PrintStringFromBottom(x + SCREEN_SCALE_X(offsets[i].x * outlineStrength), y + SCREEN_SCALE_Y(offsets[i].y * outlineStrength), str);
+ else
+ PrintString(x + SCREEN_SCALE_X(offsets[i].x * outlineStrength), y + SCREEN_SCALE_Y(offsets[i].y * outlineStrength), str);
+ }
+ SetColor(textColor);
+
+ if (fromBottom)
+ PrintStringFromBottom(x, y, str);
+ else
+ PrintString(x, y, str);
+}
+#endif
+
float
CFont::GetCharacterWidth(wchar c)
{
@@ -964,6 +1091,30 @@ CFont::GetStringWidth(wchar *s, bool spaces)
do {
while (*s == '~' || *s == JAP_TERMINATION) {
s++;
+#ifdef BUTTON_ICONS
+ switch (*s) {
+#if 0 // unused
+ case 'U':
+ case 'D':
+ case '<':
+ case '>':
+#endif
+ case 'X':
+ case 'O':
+ case 'Q':
+ case 'T':
+ case 'K':
+ case 'M':
+ case 'A':
+ case 'J':
+ case 'V':
+ case 'C':
+ w += 17.0f * Details.scaleY;
+ break;
+ default:
+ break;
+ }
+#endif
while (!(*s == '~' || *s == JAP_TERMINATION)) s++;
s++;
}
@@ -978,12 +1129,40 @@ CFont::GetStringWidth(wchar *s, bool spaces)
for (; (*s != ' ' || spaces) && *s != '\0'; s++) {
if (*s == '~') {
s++;
+#ifdef BUTTON_ICONS
+ switch (*s) {
+#if 0 // unused
+ case 'U':
+ case 'D':
+ case '<':
+ case '>':
+#endif
+ case 'X':
+ case 'O':
+ case 'Q':
+ case 'T':
+ case 'K':
+ case 'M':
+ case 'A':
+ case 'J':
+ case 'V':
+ case 'C':
+ w += 17.0f * Details.scaleY;
+ break;
+ default:
+ break;
+ }
+#endif
while (*s != '~') s++;
+#ifndef FIX_BUGS
s++;
if (*s == ' ' && !spaces)
break;
- }
- w += GetCharacterSize(*s - ' ');
+ }
+#else
+ } else
+#endif
+ w += GetCharacterSize(*s - ' ');
}
}
return w;
@@ -1037,9 +1216,11 @@ CFont::GetNextSpace(wchar *s)
if(*s == '~'){
s++;
while(*s != '~') s++;
+#ifndef FIX_BUGS
s++;
if(*s == ' ')
break;
+#endif
}
}
return s;
@@ -1047,7 +1228,7 @@ CFont::GetNextSpace(wchar *s)
#ifdef MORE_LANGUAGES
wchar*
-CFont::ParseToken(wchar *s, wchar*, bool japShit)
+CFont::ParseToken(wchar *s, wchar* ss, bool japShit)
{
s++;
if ((Details.color.r || Details.color.g || Details.color.b) && !japShit) {
@@ -1067,13 +1248,37 @@ CFont::ParseToken(wchar *s, wchar*, bool japShit)
case 'r': SetColor(CRGBA(113, 43, 73, 255)); break;
case 'w': SetColor(CRGBA(175, 175, 175, 255)); break;
case 'y': SetColor(CRGBA(210, 196, 106, 255)); break;
+#ifdef BUTTON_ICONS
+#if 0 // unused
+ case 'U': PS2Symbol = BUTTON_UP; break;
+ case 'D': PS2Symbol = BUTTON_DOWN; break;
+ case '<': PS2Symbol = BUTTON_LEFT; break;
+ case '>': PS2Symbol = BUTTON_RIGHT; break;
+#endif
+ case 'X': PS2Symbol = BUTTON_CROSS; break;
+ case 'O': PS2Symbol = BUTTON_CIRCLE; break;
+ case 'Q': PS2Symbol = BUTTON_SQUARE; break;
+ case 'T': PS2Symbol = BUTTON_TRIANGLE; break;
+ case 'K': PS2Symbol = BUTTON_L1; break;
+ case 'M': PS2Symbol = BUTTON_L2; break;
+ case 'A': PS2Symbol = BUTTON_L3; break;
+ case 'J': PS2Symbol = BUTTON_R1; break;
+ case 'V': PS2Symbol = BUTTON_R2; break;
+ case 'C': PS2Symbol = BUTTON_R3; break;
+#endif
}
} else if (IsJapanese()) {
if ((*s & 0x7FFF) == 'N' || (*s & 0x7FFF) == 'n')
NewLine = true;
}
while ((!IsJapanese() || (*s != JAP_TERMINATION)) && *s != '~') s++;
+#ifdef FIX_BUGS
+ if (*(++s) == '~')
+ s = ParseToken(s, ss, japShit);
+ return s;
+#else
return s + 1;
+#endif
}
#else
wchar*
@@ -1094,6 +1299,24 @@ CFont::ParseToken(wchar *s, wchar*)
case 'r': SetColor(CRGBA(0x71, 0x2B, 0x49, 0xFF)); break;
case 'w': SetColor(CRGBA(0xAF, 0xAF, 0xAF, 0xFF)); break;
case 'y': SetColor(CRGBA(0xD2, 0xC4, 0x6A, 0xFF)); break;
+#ifdef BUTTON_ICONS
+#if 0 // unused
+ case 'U': PS2Symbol = BUTTON_UP; break;
+ case 'D': PS2Symbol = BUTTON_DOWN; break;
+ case '<': PS2Symbol = BUTTON_LEFT; break;
+ case '>': PS2Symbol = BUTTON_RIGHT; break;
+#endif
+ case 'X': PS2Symbol = BUTTON_CROSS; break;
+ case 'O': PS2Symbol = BUTTON_CIRCLE; break;
+ case 'Q': PS2Symbol = BUTTON_SQUARE; break;
+ case 'T': PS2Symbol = BUTTON_TRIANGLE; break;
+ case 'K': PS2Symbol = BUTTON_L1; break;
+ case 'M': PS2Symbol = BUTTON_L2; break;
+ case 'A': PS2Symbol = BUTTON_L3; break;
+ case 'J': PS2Symbol = BUTTON_R1; break;
+ case 'V': PS2Symbol = BUTTON_R2; break;
+ case 'C': PS2Symbol = BUTTON_R3; break;
+#endif
}
while(*s != '~') s++;
return s+1;
diff --git a/src/render/Font.h b/src/render/Font.h
index 51035601..7b67e310 100644
--- a/src/render/Font.h
+++ b/src/render/Font.h
@@ -63,6 +63,31 @@ enum
#define FONT_LOCALE(style) (style)
#endif
+#ifdef BUTTON_ICONS
+enum
+{
+ BUTTON_NONE = -1,
+#if 0 // unused
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_LEFT,
+ BUTTON_RIGHT,
+#endif
+ BUTTON_CROSS,
+ BUTTON_CIRCLE,
+ BUTTON_SQUARE,
+ BUTTON_TRIANGLE,
+ BUTTON_L1,
+ BUTTON_L2,
+ BUTTON_L3,
+ BUTTON_R1,
+ BUTTON_R2,
+ BUTTON_R3,
+ MAX_BUTTON_ICONS
+};
+#endif // BUTTON_ICONS
+
+
class CFont
{
#ifdef MORE_LANGUAGES
@@ -77,11 +102,24 @@ public:
static CSprite2d Sprite[MAX_FONTS];
static CFontDetails Details;
+#ifdef BUTTON_ICONS
+ static int32 ButtonsSlot;
+ static CSprite2d ButtonSprite[MAX_BUTTON_ICONS];
+ static int PS2Symbol;
+
+ static void DrawButton(float x, float y);
+#endif // BUTTON_ICONS
+
+
static void Initialise(void);
static void Shutdown(void);
static void InitPerFrame(void);
static void PrintChar(float x, float y, wchar c);
static void PrintString(float x, float y, wchar *s);
+#ifdef XBOX_SUBTITLES
+ static void PrintStringFromBottom(float x, float y, wchar *str);
+ static void PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor);
+#endif
static int GetNumberLines(float xstart, float ystart, wchar *s);
static void GetTextRect(CRect *rect, float xstart, float ystart, wchar *s);
#ifdef MORE_LANGUAGES
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index e42242b6..d54f1c05 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -534,7 +534,7 @@ void CHud::Draw()
CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f));
CFont::SetJustifyOff();
CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+ CFont::SetCentreSize(SCREEN_WIDTH);
CFont::SetPropOn();
CFont::SetFontStyle(FONT_BANK);
@@ -1029,7 +1029,7 @@ void CHud::Draw()
CFont::SetRightJustifyWrap(0.0f);
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
CFont::SetColor(CRGBA(244, 20, 20, 255));
- CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+ CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));
CFont::SetPropOff();
CFont::SetBackGroundOnlyTextOn();
@@ -1342,9 +1342,9 @@ void CHud::Draw()
CFont::PrintOutlinedString(rectWidth / 2.0f + radarBulge, SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(48.0f) - SCREEN_SCALE_Y(1), m_Message,
2.0f, true, CRGBA(0, 0, 0, 255));
#else
-
float radarBulge = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f);
float rectWidth = SCREEN_SCALE_FROM_RIGHT(50.0f) - SCREEN_SCALE_X(8.0f) - radarBulge;
+
CFont::SetCentreSize(rectWidth);
const int16 shadow = 1;
@@ -1856,8 +1856,7 @@ void CHud::DrawAfterFade()
CFont::SetPropOn();
#ifdef FIX_BUGS
- //CFont::SetRightJustifyWrap(SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 500.0f));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(-500.0f));
+ CFont::SetRightJustifyWrap(SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 500.0f));
#else
CFont::SetRightJustifyWrap(-500.0f);
#endif
diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp
index acce946b..2b19486e 100644
--- a/src/render/Particle.cpp
+++ b/src/render/Particle.cpp
@@ -590,7 +590,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_SMOKE_FILES; i++ )
{
RwTextureDestroy(gpSmokeTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpSmokeTex[i] = nil;
#endif
}
@@ -598,7 +598,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ )
{
RwTextureDestroy(gpSmoke2Tex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpSmoke2Tex[i] = nil;
#endif
}
@@ -606,7 +606,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ )
{
RwTextureDestroy(gpRubberTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRubberTex[i] = nil;
#endif
}
@@ -614,7 +614,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ )
{
RwTextureDestroy(gpRainSplashTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRainSplashTex[i] = nil;
#endif
}
@@ -622,7 +622,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ )
{
RwTextureDestroy(gpWatersprayTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpWatersprayTex[i] = nil;
#endif
}
@@ -630,7 +630,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ )
{
RwTextureDestroy(gpExplosionMediumTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpExplosionMediumTex[i] = nil;
#endif
}
@@ -638,7 +638,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ )
{
RwTextureDestroy(gpGunFlashTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpGunFlashTex[i] = nil;
#endif
}
@@ -646,7 +646,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ )
{
RwTextureDestroy(gpRainDropTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRainDropTex[i] = nil;
#endif
}
@@ -654,7 +654,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ )
{
RwTextureDestroy(gpRainSplashupTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRainSplashupTex[i] = nil;
#endif
}
@@ -662,7 +662,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ )
{
RwTextureDestroy(gpBirdfrontTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpBirdfrontTex[i] = nil;
#endif
}
@@ -670,7 +670,7 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ )
{
RwTextureDestroy(gpCarDebrisTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCarDebrisTex[i] = nil;
#endif
}
@@ -678,78 +678,78 @@ void CParticle::Shutdown()
for ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ )
{
RwTextureDestroy(gpCarSplashTex[i]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCarSplashTex[i] = nil;
#endif
}
RwTextureDestroy(gpFlame1Tex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpFlame1Tex = nil;
#endif
RwTextureDestroy(gpFlame5Tex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpFlame5Tex = nil;
#endif
RwTextureDestroy(gpRainDropSmallTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRainDropSmallTex = nil;
#endif
RwTextureDestroy(gpBloodTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpBloodTex = nil;
#endif
RwTextureDestroy(gpLeafTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpLeafTex = nil;
#endif
RwTextureDestroy(gpCloudTex1);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex1 = nil;
#endif
RwTextureDestroy(gpCloudTex4);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCloudTex4 = nil;
#endif
RwTextureDestroy(gpBloodSmallTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpBloodSmallTex = nil;
#endif
RwTextureDestroy(gpGungeTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpGungeTex = nil;
#endif
RwTextureDestroy(gpCollisionSmokeTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCollisionSmokeTex = nil;
#endif
RwTextureDestroy(gpBulletHitTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpBulletHitTex = nil;
#endif
RwTextureDestroy(gpGunShellTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpGunShellTex = nil;
#endif
RwTextureDestroy(gpWakeOldTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpWakeOldTex = nil;
#endif
RwTextureDestroy(gpPointlightTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpPointlightTex = nil;
#endif
diff --git a/src/render/PlayerSkin.cpp b/src/render/PlayerSkin.cpp
index d66f7ce4..f0fae45a 100644
--- a/src/render/PlayerSkin.cpp
+++ b/src/render/PlayerSkin.cpp
@@ -14,6 +14,7 @@
#include "RwHelper.h"
#include "Timer.h"
#include "Lights.h"
+#include "MemoryMgr.h"
RpClump *gpPlayerClump;
float gOldFov;
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 4ad1d3b9..a0f66819 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -21,12 +21,14 @@
#include "Renderer.h"
#include "Frontend.h"
#include "custompipes.h"
+#include "Debug.h"
bool gbShowPedRoadGroups;
bool gbShowCarRoadGroups;
bool gbShowCollisionPolys;
bool gbShowCollisionLines;
bool gbShowCullZoneDebugStuff;
+bool gbDisableZoneCull; // not original
bool gbBigWhiteDebugLightSwitchedOn;
bool gbDontRenderBuildings;
@@ -35,6 +37,25 @@ bool gbDontRenderPeds;
bool gbDontRenderObjects;
bool gbDontRenderVehicles;
+int32 EntitiesRendered;
+int32 EntitiesNotRendered;
+int32 RenderedBigBuildings;
+int32 RenderedBuildings;
+int32 RenderedCars;
+int32 RenderedPeds;
+int32 RenderedObjects;
+int32 RenderedDummies;
+int32 TestedBigBuildings;
+int32 TestedBuildings;
+int32 TestedCars;
+int32 TestedPeds;
+int32 TestedObjects;
+int32 TestedDummies;
+
+// unused
+int16 TestCloseThings;
+int16 TestBigThings;
+
struct EntityInfo
{
CEntity *ent;
@@ -61,6 +82,11 @@ float CRenderer::ms_lodDistScale = 1.2f;
#define BACKFACE_CULLING_OFF
#endif
+// unused
+BlockedRange CRenderer::aBlockedRanges[16];
+BlockedRange *CRenderer::pFullBlockedRanges;
+BlockedRange *CRenderer::pEmptyBlockedRanges;
+
void
CRenderer::Init(void)
{
@@ -111,7 +137,7 @@ CRenderer::RenderOneRoad(CEntity *e)
CustomPipes::AttachGlossPipe(e->GetAtomic());
#endif
#ifdef EXTRA_MODEL_FLAGS
- if(CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){
+ if(!e->IsBuilding() || CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){
BACKFACE_CULLING_OFF;
e->Render();
BACKFACE_CULLING_ON;
@@ -181,7 +207,7 @@ CRenderer::RenderOneNonRoad(CEntity *e)
BACKFACE_CULLING_OFF;
}
#ifdef EXTRA_MODEL_FLAGS
- if(CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){
+ if(!e->IsBuilding() || CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){
BACKFACE_CULLING_OFF;
e->Render();
BACKFACE_CULLING_ON;
@@ -190,6 +216,7 @@ CRenderer::RenderOneNonRoad(CEntity *e)
e->Render();
if(e->IsVehicle()){
+ BACKFACE_CULLING_OFF;
e->bImBeingRendered = true;
CVisibilityPlugins::RenderAlphaAtomics();
e->bImBeingRendered = false;
@@ -347,6 +374,14 @@ CRenderer::RenderCollisionLines(void)
}
}
+// unused
+void
+CRenderer::RenderBlockBuildingLines(void)
+{
+ for(BlockedRange *br = pFullBlockedRanges; br; br = br->next)
+ printf("Blocked: %f %f\n", br->a, br->b);
+}
+
enum Visbility
{
VIS_INVISIBLE,
@@ -355,14 +390,6 @@ enum Visbility
VIS_STREAMME
};
-#ifdef FIX_BUGS
-#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier)
-#else
-#define LOD_DISTANCE 300.0f
-#endif
-#define FADE_DISTANCE 20.0f
-#define STREAM_DISTANCE 30.0f
-
// Time Objects can be time culled if
// other == -1 || CModelInfo::GetModelInfo(other)->GetRwObject()
// i.e. we have to draw even at the wrong time if
@@ -570,7 +597,7 @@ 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())
+ if (!ent->IsVisible() || !ent->GetIsOnScreenComplex())
return VIS_INVISIBLE;
if(mi->m_drawLast){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
@@ -600,7 +627,7 @@ 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())
+ if (ent->IsVisible() && ent->GetIsOnScreenComplex())
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
return VIS_INVISIBLE;
}
@@ -611,7 +638,21 @@ CRenderer::ConstructRenderList(void)
ms_nNoOfVisibleEntities = 0;
ms_nNoOfInVisibleEntities = 0;
ms_vecCameraPosition = TheCamera.GetPosition();
- // TODO: blocked ranges, but unused
+
+ // unused
+ pFullBlockedRanges = nil;
+ pEmptyBlockedRanges = aBlockedRanges;
+ for(int i = 0; i < 16; i++){
+ aBlockedRanges[i].prev = &aBlockedRanges[i-1];
+ aBlockedRanges[i].next = &aBlockedRanges[i+1];
+ }
+ aBlockedRanges[0].prev = nil;
+ aBlockedRanges[15].next = nil;
+
+ // unused
+ TestCloseThings = 0;
+ TestBigThings = 0;
+
ScanWorld();
}
@@ -647,6 +688,24 @@ CRenderer::ScanWorld(void)
RwMatrix *cammatrix;
RwV2d poly[3];
+#ifndef MASTER
+ // missing in game but has to be done somewhere
+ EntitiesRendered = 0;
+ EntitiesNotRendered = 0;
+ RenderedBigBuildings = 0;
+ RenderedBuildings = 0;
+ RenderedCars = 0;
+ RenderedPeds = 0;
+ RenderedObjects = 0;
+ RenderedDummies = 0;
+ TestedBigBuildings = 0;
+ TestedBuildings = 0;
+ TestedCars = 0;
+ TestedPeds = 0;
+ TestedObjects = 0;
+ TestedDummies = 0;
+#endif
+
memset(vectors, 0, sizeof(vectors));
vectors[CORNER_FAR_TOPLEFT].x = -vw.x * f;
vectors[CORNER_FAR_TOPLEFT].y = vw.y * f;
@@ -765,6 +824,19 @@ CRenderer::ScanWorld(void)
ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC));
}
}
+
+#ifndef MASTER
+ if(gbShowCullZoneDebugStuff){
+ sprintf(gString, "Rejected: %d/%d.", EntitiesNotRendered, EntitiesNotRendered + EntitiesRendered);
+ CDebug::PrintAt(gString, 10, 10);
+ sprintf(gString, "Tested:BBuild:%d Build:%d Peds:%d Cars:%d Obj:%d Dummies:%d",
+ TestedBigBuildings, TestedBuildings, TestedPeds, TestedCars, TestedObjects, TestedDummies);
+ CDebug::PrintAt(gString, 10, 11);
+ sprintf(gString, "Rendered:BBuild:%d Build:%d Peds:%d Cars:%d Obj:%d Dummies:%d",
+ RenderedBigBuildings, RenderedBuildings, RenderedPeds, RenderedCars, RenderedObjects, RenderedDummies);
+ CDebug::PrintAt(gString, 10, 12);
+ }
+#endif
}
void
@@ -848,6 +920,37 @@ CRenderer::RequestObjectsInFrustum(void)
}
}
+bool
+CPed::SetupLighting(void)
+{
+ ActivateDirectional();
+ SetAmbientColoursForPedsCarsAndObjects();
+
+#ifndef MASTER
+ // Originally this was being called through iteration of Sectors, but putting it here is better.
+ if (GetDebugDisplay() != 0 && !IsPlayer())
+ DebugRenderOnePedText();
+#endif
+
+ if (bRenderScorched) {
+ WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
+ } else {
+ // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0.
+ float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition());
+ if (!bHasBlip && lightMult != 1.0f) {
+ SetAmbientAndDirectionalColours(lightMult);
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+CPed::RemoveLighting(bool reset)
+{
+ CRenderer::RemoveVehiclePedLights(this, reset);
+}
+
float
CalcNewDelta(RwV2d *a, RwV2d *b)
{
@@ -1014,8 +1117,20 @@ CRenderer::ScanBigBuildingList(CPtrList &list)
for(node = list.first; node; node = node->next){
ent = (CEntity*)node->item;
- if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE)
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+#ifndef MASTER
+ // all missing from game actually
+ TestedBigBuildings++;
+#endif
+ if(!ent->bZoneCulled){
+ if(SetupBigBuildingVisibility(ent) == VIS_VISIBLE)
+ ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+#ifndef MASTER
+ EntitiesRendered++;
+ RenderedBigBuildings++;
+ }else{
+ EntitiesNotRendered++;
+#endif
+ }
}
}
@@ -1036,7 +1151,7 @@ CRenderer::ScanSectorList(CPtrList *lists)
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
- if(IsEntityCullZoneVisible(ent))
+ if(IsEntityCullZoneVisible(ent)){
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
@@ -1059,11 +1174,37 @@ CRenderer::ScanSectorList(CPtrList *lists)
CStreaming::RequestModel(ent->GetModelIndex(), 0);
break;
}
- else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
- if(!CStreaming::ms_disableStreaming)
- if(SetupEntityVisibility(ent) == VIS_STREAMME)
- if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+#ifndef MASTER
+ EntitiesRendered++;
+ switch(ent->GetType()){
+ case ENTITY_TYPE_BUILDING:
+ if(ent->bIsBIGBuilding)
+ RenderedBigBuildings++;
+ else
+ RenderedBuildings++;
+ break;
+ case ENTITY_TYPE_VEHICLE:
+ RenderedCars++;
+ break;
+ case ENTITY_TYPE_PED:
+ RenderedPeds++;
+ break;
+ case ENTITY_TYPE_OBJECT:
+ RenderedObjects++;
+ break;
+ case ENTITY_TYPE_DUMMY:
+ RenderedDummies++;
+ break;
+ }
+#endif
+ }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){
+ if(SetupEntityVisibility(ent) == VIS_STREAMME)
+ if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ }else{
+#ifndef MASTER
+ EntitiesNotRendered++;
+#endif
}
}
}
@@ -1086,7 +1227,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
continue; // already seen
ent->m_scanCode = CWorld::GetCurrentScanCode();
- if(IsEntityCullZoneVisible(ent))
+ if(IsEntityCullZoneVisible(ent)){
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
@@ -1111,10 +1252,38 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
}
break;
}
- else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
- if(!CStreaming::ms_disableStreaming)
- if(SetupEntityVisibility(ent) == VIS_STREAMME)
- CStreaming::RequestModel(ent->GetModelIndex(), 0);
+#ifndef MASTER
+ // actually missing in game
+ EntitiesRendered++;
+ switch(ent->GetType()){
+ case ENTITY_TYPE_BUILDING:
+ if(ent->bIsBIGBuilding)
+ RenderedBigBuildings++;
+ else
+ RenderedBuildings++;
+ break;
+ case ENTITY_TYPE_VEHICLE:
+ RenderedCars++;
+ break;
+ case ENTITY_TYPE_PED:
+ RenderedPeds++;
+ break;
+ case ENTITY_TYPE_OBJECT:
+ RenderedObjects++;
+ break;
+ case ENTITY_TYPE_DUMMY:
+ RenderedDummies++;
+ break;
+ }
+#endif
+ }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){
+ if(SetupEntityVisibility(ent) == VIS_STREAMME)
+ CStreaming::RequestModel(ent->GetModelIndex(), 0);
+ }else{
+#ifndef MASTER
+ // actually missing in game
+ EntitiesNotRendered++;
+#endif
}
}
}
@@ -1220,9 +1389,34 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent)
CPed *ped;
CObject *obj;
+ if(gbDisableZoneCull) return true;
+
+#ifndef MASTER
+ switch(ent->GetType()){
+ case ENTITY_TYPE_BUILDING:
+ if(ent->bIsBIGBuilding)
+ TestedBigBuildings++;
+ else
+ TestedBuildings++;
+ break;
+ case ENTITY_TYPE_VEHICLE:
+ TestedCars++;
+ break;
+ case ENTITY_TYPE_PED:
+ TestedPeds++;
+ break;
+ case ENTITY_TYPE_OBJECT:
+ TestedObjects++;
+ break;
+ case ENTITY_TYPE_DUMMY:
+ TestedDummies++;
+ break;
+ }
+#endif
if(ent->bZoneCulled)
return false;
+
switch(ent->GetType()){
case ENTITY_TYPE_VEHICLE:
return IsVehicleCullZoneVisible(ent);
diff --git a/src/render/Renderer.h b/src/render/Renderer.h
index 362741e3..e14f73b1 100644
--- a/src/render/Renderer.h
+++ b/src/render/Renderer.h
@@ -2,11 +2,20 @@
class CEntity;
+#ifdef FIX_BUGS
+#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier)
+#else
+#define LOD_DISTANCE 300.0f
+#endif
+#define FADE_DISTANCE 20.0f
+#define STREAM_DISTANCE 30.0f
+
extern bool gbShowPedRoadGroups;
extern bool gbShowCarRoadGroups;
extern bool gbShowCollisionPolys;
extern bool gbShowCollisionLines;
extern bool gbShowCullZoneDebugStuff;
+extern bool gbDisableZoneCull; // not original
extern bool gbBigWhiteDebugLightSwitchedOn;
extern bool gbDontRenderBuildings;
@@ -18,6 +27,13 @@ extern bool gbDontRenderVehicles;
class CVehicle;
class CPtrList;
+// unused
+struct BlockedRange
+{
+ float a, b; // unknown
+ BlockedRange *prev, *next;
+};
+
class CRenderer
{
static int32 ms_nNoOfVisibleEntities;
@@ -28,6 +44,10 @@ class CRenderer
static CVector ms_vecCameraPosition;
static CVehicle *m_pFirstPersonVehicle;
+ // unused
+ static BlockedRange aBlockedRanges[16];
+ static BlockedRange *pFullBlockedRanges;
+ static BlockedRange *pEmptyBlockedRanges;
public:
static float ms_lodDistScale;
static bool m_loadingPriority;
@@ -46,6 +66,8 @@ public:
static void RenderFirstPersonVehicle(void);
static void RenderCollisionLines(void);
+ // unused
+ static void RenderBlockBuildingLines(void);
static int32 SetupEntityVisibility(CEntity *ent);
static int32 SetupBigBuildingVisibility(CEntity *ent);
diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp
index bfd50c07..18a20bc7 100644
--- a/src/render/Rubbish.cpp
+++ b/src/render/Rubbish.cpp
@@ -414,19 +414,19 @@ void
CRubbish::Shutdown(void)
{
RwTextureDestroy(gpRubbishTexture[0]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRubbishTexture[0] = nil;
#endif
RwTextureDestroy(gpRubbishTexture[1]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRubbishTexture[1] = nil;
#endif
RwTextureDestroy(gpRubbishTexture[2]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRubbishTexture[2] = nil;
#endif
RwTextureDestroy(gpRubbishTexture[3]);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpRubbishTexture[3] = nil;
#endif
}
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index ad036d58..9e509b52 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -54,15 +54,15 @@ void
CSkidmarks::Shutdown(void)
{
RwTextureDestroy(gpSkidTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpSkidTex = nil;
#endif
RwTextureDestroy(gpSkidBloodTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpSkidBloodTex = nil;
#endif
RwTextureDestroy(gpSkidMudTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpSkidMudTex = nil;
#endif
}
diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp
index 6133b1d7..ecfccc90 100644
--- a/src/render/WaterLevel.cpp
+++ b/src/render/WaterLevel.cpp
@@ -21,6 +21,7 @@
#include "RenderBuffer.h"
#include <rpworld.h>
#include "WaterLevel.h"
+#include "MemoryHeap.h"
float TEXTURE_ADDU;
@@ -1157,6 +1158,8 @@ CWaterLevel::AllocateBoatWakeArray()
{
CStreaming::MakeSpaceFor(14 * CDSTREAM_SECTOR_SIZE);
+ PUSH_MEMID(MEMID_STREAM);
+
ASSERT(ms_pWavyAtomic != NULL );
RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);
@@ -1230,6 +1233,8 @@ CWaterLevel::AllocateBoatWakeArray()
RpGeometryUnlock(apGeomArray[geom]);
}
}
+
+ POP_MEMID();
}
void
diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp
index 5a253854..b3cef6d4 100644
--- a/src/rw/Lights.cpp
+++ b/src/rw/Lights.cpp
@@ -3,6 +3,7 @@
#include <rpworld.h>
#include "Lights.h"
+#include "Timer.h"
#include "Timecycle.h"
#include "Coronas.h"
#include "Weather.h"
@@ -248,6 +249,46 @@ SetAmbientAndDirectionalColours(float f)
RpLightSetColor(pDirect, &DirectionalLightColour);
}
+// unused
+void
+SetFlashyColours(float f)
+{
+ if(CTimer::GetTimeInMilliseconds() & 0x100){
+ AmbientLightColour.red = 1.0f;
+ AmbientLightColour.green = 1.0f;
+ AmbientLightColour.blue = 1.0f;
+
+ DirectionalLightColour.red = DirectionalLightColourForFrame.red;
+ DirectionalLightColour.green = DirectionalLightColourForFrame.green;
+ DirectionalLightColour.blue = DirectionalLightColourForFrame.blue;
+
+ RpLightSetColor(pAmbient, &AmbientLightColour);
+ RpLightSetColor(pDirect, &DirectionalLightColour);
+ }else{
+ SetAmbientAndDirectionalColours(f * 0.75f);
+ }
+}
+
+// unused
+void
+SetFlashyColours_Mild(float f)
+{
+ if(CTimer::GetTimeInMilliseconds() & 0x100){
+ AmbientLightColour.red = 0.65f;
+ AmbientLightColour.green = 0.65f;
+ AmbientLightColour.blue = 0.65f;
+
+ DirectionalLightColour.red = DirectionalLightColourForFrame.red;
+ DirectionalLightColour.green = DirectionalLightColourForFrame.green;
+ DirectionalLightColour.blue = DirectionalLightColourForFrame.blue;
+
+ RpLightSetColor(pAmbient, &AmbientLightColour);
+ RpLightSetColor(pDirect, &DirectionalLightColour);
+ }else{
+ SetAmbientAndDirectionalColours(f * 0.9f);
+ }
+}
+
void
SetBrightMarkerColours(float f)
{
diff --git a/src/rw/Lights.h b/src/rw/Lights.h
index b296816b..5057f1d0 100644
--- a/src/rw/Lights.h
+++ b/src/rw/Lights.h
@@ -14,6 +14,8 @@ void WorldReplaceScorchedLightsWithNormal(RpWorld *world);
void AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, float red, float green, float blue);
void RemoveExtraDirectionalLights(RpWorld *world);
void SetAmbientAndDirectionalColours(float f);
+void SetFlashyColours(float f);
+void SetFlashyColours_Mild(float f);
void SetBrightMarkerColours(float f);
void ReSetAmbientAndDirectionalColours(void);
void DeActivateDirectional(void);
diff --git a/src/rw/MemoryHeap.cpp b/src/rw/MemoryHeap.cpp
new file mode 100644
index 00000000..469262d3
--- /dev/null
+++ b/src/rw/MemoryHeap.cpp
@@ -0,0 +1,497 @@
+#include "common.h"
+#include "main.h"
+#include "FileMgr.h"
+#include "Timer.h"
+#include "ModelInfo.h"
+#include "Streaming.h"
+#include "FileLoader.h"
+#include "MemoryHeap.h"
+
+#ifdef USE_CUSTOM_ALLOCATOR
+
+//#define MEMORYHEAP_ASSERT(cond) { if (!(cond)) { printf("ASSERT File:%s Line:%d\n", __FILE__, __LINE__); exit(1); } }
+//#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) { if (!(cond)) { printf("ASSERT File:%s Line:%d:\n\t%s\n", __FILE__, __LINE__, message); exit(1); } }
+
+#define MEMORYHEAP_ASSERT(cond) assert(cond)
+#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) assert(cond)
+
+// registered pointers that we keep track of
+void **gPtrList[4000];
+int32 numPtrs;
+int32 gPosnInList;
+// indices into the ptr list in here are free
+CStack<int32, 4000> m_ptrListIndexStack;
+// how much memory we've moved
+uint32 memMoved;
+
+CMemoryHeap gMainHeap;
+
+void
+CMemoryHeap::Init(uint32 total)
+{
+ MEMORYHEAP_ASSERT((total != 0xF) != 0);
+
+ m_totalMemUsed = 0;
+ m_memUsed = nil;
+ m_currentMemID = MEMID_FREE;
+ m_blocksUsed = nil;
+ m_totalBlocksUsed = 0;
+ m_unkMemId = -1;
+
+ uint8 *mem = (uint8*)malloc(total);
+ assert(((uintptr)mem & 0xF) == 0);
+ m_start = (HeapBlockDesc*)mem;
+ m_end = (HeapBlockDesc*)(mem + total - sizeof(HeapBlockDesc));
+ m_start->m_memId = MEMID_FREE;
+ m_start->m_size = total - 2*sizeof(HeapBlockDesc);
+ m_end->m_memId = MEMID_GAME;
+ m_end->m_size = 0;
+
+ m_freeList.m_last.m_size = INT_MAX;
+ m_freeList.Init();
+ m_freeList.Insert(m_start);
+
+ // TODO: figure out what these are and use sizeof
+ m_fixedSize[0].Init(0x10);
+ m_fixedSize[1].Init(0x20);
+ m_fixedSize[2].Init(0xE0);
+ m_fixedSize[3].Init(0x60);
+ m_fixedSize[4].Init(0x1C0);
+ m_fixedSize[5].Init(0x50);
+
+ m_currentMemID = MEMID_FREE; // disable registration
+ m_memUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32));
+ m_blocksUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32));
+ RegisterMalloc(GetDescFromHeapPointer(m_memUsed));
+ RegisterMalloc(GetDescFromHeapPointer(m_blocksUsed));
+
+ m_currentMemID = MEMID_GAME;
+ for(int i = 0; i < NUM_MEMIDS; i++){
+ m_memUsed[i] = 0;
+ m_blocksUsed[i] = 0;
+ }
+}
+
+void
+CMemoryHeap::RegisterMalloc(HeapBlockDesc *block)
+{
+ block->m_memId = m_currentMemID;
+ if(m_currentMemID == MEMID_FREE)
+ return;
+ m_totalMemUsed += block->m_size + sizeof(HeapBlockDesc);
+ m_memUsed[m_currentMemID] += block->m_size + sizeof(HeapBlockDesc);
+ m_blocksUsed[m_currentMemID]++;
+ m_totalBlocksUsed++;
+}
+
+void
+CMemoryHeap::RegisterFree(HeapBlockDesc *block)
+{
+ if(block->m_memId == MEMID_FREE)
+ return;
+ m_totalMemUsed -= block->m_size + sizeof(HeapBlockDesc);
+ m_memUsed[block->m_memId] -= block->m_size + sizeof(HeapBlockDesc);
+ m_blocksUsed[block->m_memId]--;
+ m_totalBlocksUsed--;
+}
+
+void*
+CMemoryHeap::Malloc(uint32 size)
+{
+ static int recursion = 0;
+
+ // weird way to round up
+ if((size & 0xF) != 0)
+ size = (size&~0xF) + 0x10;
+
+ recursion++;
+
+ // See if we can allocate from one of the fixed-size lists
+ for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){
+ CommonSize *list = &m_fixedSize[i];
+ if(m_fixedSize[i].m_size == size){
+ HeapBlockDesc *block = list->Malloc();
+ if(block){
+ RegisterMalloc(block);
+ recursion--;
+ return block->GetDataPointer();
+ }
+ break;
+ }
+ }
+
+ // now try the normal free list
+ HeapBlockDesc *next;
+ for(HeapBlockDesc *block = m_freeList.m_first.m_next;
+ block != &m_freeList.m_last;
+ block = next){
+ MEMORYHEAP_ASSERT(block->m_memId == MEMID_FREE);
+ MEMORYHEAP_ASSERT_MESSAGE(block >= m_start && block <= m_end, "Block outside of memory");
+
+ // make sure block has maximum size
+ uint32 initialsize = block->m_size;
+ uint32 blocksize = CombineFreeBlocks(block);
+#ifdef FIX_BUGS
+ // has to be done here because block can be moved
+ next = block->m_next;
+#endif
+ if(initialsize != blocksize){
+ block->RemoveHeapFreeBlock();
+ HeapBlockDesc *pos = block->m_prev->FindSmallestFreeBlock(block->m_size);
+ block->InsertHeapFreeBlock(pos->m_prev);
+ }
+ if(block->m_size >= size){
+ // got space to allocate from!
+ block->RemoveHeapFreeBlock();
+ FillInBlockData(block, block->GetNextConsecutive(), size);
+ recursion--;
+ return block->GetDataPointer();
+ }
+#ifndef FIX_BUGS
+ next = block->m_next;
+#endif
+ }
+
+ // oh no, we're losing, try to free some stuff
+ static bool removeCollision = false;
+ static bool removeIslands = false;
+ static bool removeBigBuildings = false;
+ size_t initialMemoryUsed = CStreaming::ms_memoryUsed;
+ CStreaming::MakeSpaceFor(0xCFE800 - CStreaming::ms_memoryUsed);
+ if (recursion > 10)
+ CGame::TidyUpMemory(true, false);
+ else if (recursion > 6)
+ CGame::TidyUpMemory(false, true);
+ if (initialMemoryUsed == CStreaming::ms_memoryUsed && recursion > 11) {
+ if (!removeCollision && !CGame::playingIntro) {
+ CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);
+ removeCollision = true;
+ }
+ else if (!removeIslands && !CGame::playingIntro) {
+ CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
+ CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
+ CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
+ removeIslands = true;
+ }
+ else if (!removeBigBuildings) {
+ CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
+ CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
+ CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
+ }
+ else {
+ LoadingScreen("NO MORE MEMORY", nil, nil);
+ LoadingScreen("NO MORE MEMORY", nil, nil);
+ }
+ CGame::TidyUpMemory(true, false);
+ }
+ void *mem = Malloc(size);
+ if (removeCollision) {
+ CTimer::Stop();
+ // TODO: different on PS2
+ CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory);
+ removeCollision = false;
+ CTimer::Update();
+ }
+ if (removeBigBuildings || removeIslands) {
+ CTimer::Stop();
+ if (!CGame::playingIntro)
+ CStreaming::RequestBigBuildings(CGame::currLevel);
+ CStreaming::LoadAllRequestedModels(true);
+ removeBigBuildings = false;
+ removeIslands = false;
+ CTimer::Update();
+ }
+ recursion--;
+ return mem;
+}
+
+void*
+CMemoryHeap::Realloc(void *ptr, uint32 size)
+{
+ if(ptr == nil)
+ return Malloc(size);
+
+ // weird way to round up
+ if((size & 0xF) != 0)
+ size = (size&~0xF) + 0x10;
+
+ HeapBlockDesc *block = GetDescFromHeapPointer(ptr);
+
+#ifdef FIX_BUGS
+ // better handling of size < block->m_size
+ if(size == 0){
+ Free(ptr);
+ return nil;
+ }
+ if(block->m_size >= size){
+ // shrink allocated block
+ RegisterFree(block);
+ PushMemId(block->m_memId);
+ FillInBlockData(block, block->GetNextConsecutive(), size);
+ PopMemId();
+ return ptr;
+ }
+#else
+ // not growing. just returning here is a bit cheap though
+ if(block->m_size >= size)
+ return ptr;
+#endif
+
+ // have to grow allocated block
+ HeapBlockDesc *next = block->GetNextConsecutive();
+ MEMORYHEAP_ASSERT_MESSAGE(next >= m_start && next <= m_end, "Block outside of memory");
+ if(next->m_memId == MEMID_FREE){
+ // try to grow the current block
+ // make sure the next free block has maximum size
+ uint32 freespace = CombineFreeBlocks(next);
+ HeapBlockDesc *end = next->GetNextConsecutive();
+ MEMORYHEAP_ASSERT_MESSAGE(end >= m_start && end <= m_end, "Block outside of memory");
+ // why the sizeof here?
+ if(block->m_size + next->m_size + sizeof(HeapBlockDesc) >= size){
+ // enough space to grow
+ next->RemoveHeapFreeBlock();
+ RegisterFree(block);
+ PushMemId(block->m_memId);
+ FillInBlockData(block, next->GetNextConsecutive(), size);
+ PopMemId();
+ return ptr;
+ }
+ }
+
+ // can't grow the existing block, have to get a new one and copy
+ PushMemId(block->m_memId);
+ void *dst = Malloc(size);
+ PopMemId();
+ memcpy(dst, ptr, block->m_size);
+ Free(ptr);
+ return dst;
+}
+
+void
+CMemoryHeap::Free(void *ptr)
+{
+ HeapBlockDesc *block = GetDescFromHeapPointer(ptr);
+ MEMORYHEAP_ASSERT_MESSAGE(block->m_memId != MEMID_FREE, "MemoryHeap corrupt");
+ MEMORYHEAP_ASSERT(m_unkMemId == -1 || m_unkMemId == block->m_memId);
+
+ RegisterFree(block);
+ block->m_memId = MEMID_FREE;
+ CombineFreeBlocks(block);
+ FreeBlock(block);
+ if(block->m_ptrListIndex != -1){
+ int32 idx = block->m_ptrListIndex;
+ gPtrList[idx] = nil;
+ m_ptrListIndexStack.push(idx);
+ }
+ block->m_ptrListIndex = -1;
+}
+
+// allocate 'size' bytes from 'block'
+void
+CMemoryHeap::FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size)
+{
+ block->m_size = size;
+ block->m_ptrListIndex = -1;
+ HeapBlockDesc *remainder = block->GetNextConsecutive();
+ MEMORYHEAP_ASSERT(remainder <= end);
+
+ if(remainder < end-1){
+ RegisterMalloc(block);
+
+ // can fit another block in the remaining space
+ remainder->m_size = GetSizeBetweenBlocks(remainder, end);
+ remainder->m_memId = MEMID_FREE;
+ MEMORYHEAP_ASSERT(remainder->m_size != 0);
+ FreeBlock(remainder);
+ }else{
+ // fully allocate this one
+ if(remainder < end)
+ // no gaps allowed
+ block->m_size = GetSizeBetweenBlocks(block, end);
+ RegisterMalloc(block);
+ }
+}
+
+// Make sure free block has no other free blocks after it
+uint32
+CMemoryHeap::CombineFreeBlocks(HeapBlockDesc *block)
+{
+ HeapBlockDesc *next = block->GetNextConsecutive();
+ if(next->m_memId != MEMID_FREE)
+ return block->m_size;
+ // get rid of free blocks after this one and adjust size
+ for(; next->m_memId == MEMID_FREE; next = next->GetNextConsecutive())
+ next->RemoveHeapFreeBlock();
+ block->m_size = GetSizeBetweenBlocks(block, next);
+ return block->m_size;
+}
+
+// Try to move all registered memory blocks into more optimal location
+void
+CMemoryHeap::TidyHeap(void)
+{
+ for(int i = 0; i < numPtrs; i++){
+ if(gPtrList[i] == nil || *gPtrList[i] == nil)
+ continue;
+ HeapBlockDesc *newblock = WhereShouldMemoryMove(*gPtrList[i]);
+ if(newblock)
+ *gPtrList[i] = MoveHeapBlock(newblock, GetDescFromHeapPointer(*gPtrList[i]));
+ }
+}
+
+//
+void
+CMemoryHeap::RegisterMemPointer(void *ptr)
+{
+ HeapBlockDesc *block = GetDescFromHeapPointer(*(void**)ptr);
+
+ if(block->m_ptrListIndex != -1)
+ return; // already registered
+
+ int index;
+ if(m_ptrListIndexStack.sp > 0){
+ // re-use a previously free'd index
+ index = m_ptrListIndexStack.pop();
+ }else{
+ // have to find a new index
+ index = gPosnInList;
+
+ void **pp = gPtrList[index];
+ // we're replacing an old pointer here??
+ if(pp && *pp && *pp != (void*)0xDDDDDDDD)
+ GetDescFromHeapPointer(*pp)->m_ptrListIndex = -1;
+
+ gPosnInList++;
+ if(gPosnInList == 4000)
+ gPosnInList = 0;
+ if(numPtrs < 4000)
+ numPtrs++;
+ }
+ gPtrList[index] = (void**)ptr;
+ block->m_ptrListIndex = index;
+}
+
+void*
+CMemoryHeap::MoveMemory(void *ptr)
+{
+ HeapBlockDesc *newblock = WhereShouldMemoryMove(ptr);
+ if(newblock)
+ return MoveHeapBlock(newblock, GetDescFromHeapPointer(ptr));
+ else
+ return ptr;
+}
+
+HeapBlockDesc*
+CMemoryHeap::WhereShouldMemoryMove(void *ptr)
+{
+ HeapBlockDesc *block = GetDescFromHeapPointer(ptr);
+ MEMORYHEAP_ASSERT(block->m_memId != MEMID_FREE);
+
+ HeapBlockDesc *next = block->GetNextConsecutive();
+ if(next->m_memId != MEMID_FREE)
+ return nil;
+
+ // we want to move the block into another block
+ // such that the free space between this and the next block can be minimized
+ HeapBlockDesc *newblock = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);
+ // size of free space wouldn't decrease, so return
+ if(newblock->m_size >= block->m_size + next->m_size)
+ return nil;
+ // size of free space wouldn't decrease enough
+ if(newblock->m_size >= 16 + 1.125f*block->m_size) // what are 16 and 1.125 here? sizeof(HeapBlockDesc)?
+ return nil;
+ return newblock;
+}
+
+void*
+CMemoryHeap::MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src)
+{
+ PushMemId(src->m_memId);
+ dst->RemoveHeapFreeBlock();
+ FillInBlockData(dst, dst->GetNextConsecutive(), src->m_size);
+ PopMemId();
+ memcpy(dst->GetDataPointer(), src->GetDataPointer(), src->m_size);
+ memMoved += src->m_size;
+ dst->m_ptrListIndex = src->m_ptrListIndex;
+ src->m_ptrListIndex = -1;
+ Free(src->GetDataPointer());
+ return dst->GetDataPointer();
+}
+
+uint32
+CMemoryHeap::GetMemoryUsed(int32 id)
+{
+ return m_memUsed[id];
+}
+
+uint32
+CMemoryHeap::GetBlocksUsed(int32 id)
+{
+ return m_blocksUsed[id];
+}
+
+void
+CMemoryHeap::PopMemId(void)
+{
+ assert(m_idStack.sp > 0);
+ m_currentMemID = m_idStack.pop();
+ assert(m_currentMemID != MEMID_FREE);
+}
+
+void
+CMemoryHeap::PushMemId(int32 id)
+{
+ MEMORYHEAP_ASSERT(id != MEMID_FREE);
+ assert(m_idStack.sp < 16);
+ m_idStack.push(m_currentMemID);
+ m_currentMemID = id;
+}
+
+void
+CMemoryHeap::ParseHeap(void)
+{
+ char tmp[16];
+ int fd = CFileMgr::OpenFileForWriting("heap.txt");
+ CTimer::Stop();
+
+ // CMemoryHeap::IntegrityCheck();
+
+ uint32 addrQW = 0;
+ for(HeapBlockDesc *block = m_start; block < m_end; block = block->GetNextConsecutive()){
+ char chr = '*'; // free
+ if(block->m_memId != MEMID_FREE)
+ chr = block->m_memId-1 + 'A';
+ int numQW = block->m_size>>4;
+
+ if((addrQW & 0x3F) == 0){
+ sprintf(tmp, "\n%5dK:", addrQW>>6);
+ CFileMgr::Write(fd, tmp, 8);
+ }
+ CFileMgr::Write(fd, "#", 1); // the descriptor, has to be 16 bytes!!!!
+ addrQW++;
+
+ while(numQW--){
+ if((addrQW & 0x3F) == 0){
+ sprintf(tmp, "\n%5dK:", addrQW>>6);
+ CFileMgr::Write(fd, tmp, 8);
+ }
+ CFileMgr::Write(fd, &chr, 1);
+ addrQW++;
+ }
+ }
+
+ CTimer::Update();
+ CFileMgr::CloseFile(fd);
+}
+
+
+void
+CommonSize::Init(uint32 size)
+{
+ m_freeList.Init();
+ m_size = size;
+ m_failed = 0;
+ m_remaining = 0;
+}
+
+#endif
diff --git a/src/rw/MemoryHeap.h b/src/rw/MemoryHeap.h
new file mode 100644
index 00000000..23163c1c
--- /dev/null
+++ b/src/rw/MemoryHeap.h
@@ -0,0 +1,225 @@
+#pragma once
+
+// some windows shit
+#ifdef MoveMemory
+#undef MoveMemory
+#endif
+
+#ifdef USE_CUSTOM_ALLOCATOR
+#define PUSH_MEMID(id) gMainHeap.PushMemId(id)
+#define POP_MEMID() gMainHeap.PopMemId()
+#define REGISTER_MEMPTR(ptr) gMainHeap.RegisterMemPointer(ptr)
+#else
+#define PUSH_MEMID(id)
+#define POP_MEMID()
+#define REGISTER_MEMPTR(ptr)
+#endif
+
+enum {
+ MEMID_FREE,
+ // IDs from LCS:
+/*
+ MEMID_GAME = 1, // "Game"
+ MEMID_WORLD = 2, // "World"
+ MEMID_ANIMATION = 3, // "Animation"
+ MEMID_POOLS = 4, // "Pools"
+ MEMID_DEF_MODELS = 5, // "Default Models"
+ MEMID_STREAM = 6, // "Streaming"
+ MEMID_STREAM_MODELS = 7, // "Streamed Models"
+ MEMID_STREAM_LODS = 8, // "Streamed LODs"
+ MEMID_STREAM_TEXUTRES = 9, // "Streamed Textures"
+ MEMID_STREAM_COLLISION = 10, // "Streamed Collision"
+ MEMID_STREAM_ANIMATION = 11, // "Streamed Animation"
+ MEMID_TEXTURES = 12, // "Textures"
+ MEMID_COLLISION = 13, // "Collision"
+ MEMID_PRE_ALLOC = 14, // "PreAlloc"
+ MEMID_GAME_PROCESS = 15, // "Game Process"
+ MEMID_SCRIPT = 16, // "Script"
+ MEMID_CARS = 17, // "Cars"
+ MEMID_RENDER = 18, // "Render"
+ MEMID_PED_ATTR = 19, // "Ped Attr"
+*/
+ // III:
+ MEMID_GAME = 1, // "Game"
+ MEMID_WORLD = 2, // "World"
+ MEMID_ANIMATION = 3, // "Animation"
+ MEMID_POOLS = 4, // "Pools"
+ MEMID_DEF_MODELS = 5, // "Default Models"
+ MEMID_STREAM = 6, // "Streaming"
+ MEMID_STREAM_MODELS = 7, // "Streamed Models" (instance)
+ MEMID_STREAM_TEXUTRES = 8, // "Streamed Textures"
+ MEMID_TEXTURES = 9, // "Textures"
+ MEMID_COLLISION = 10, // "Collision"
+ MEMID_RENDERLIST = 11, // ?
+ MEMID_GAME_PROCESS = 12, // "Game Process"
+ MEMID_SCRIPT = 13, // "Script"
+ MEMID_CARS = 14, // "Cars"
+ MEMID_RENDER = 15, // "Render"
+ MEMID_FRONTEND = 17, // ?
+
+ NUM_MEMIDS,
+
+ NUM_FIXED_MEMBLOCKS = 6
+};
+
+template<typename T, uint32 N>
+class CStack
+{
+public:
+ T values[N];
+ uint32 sp;
+
+ CStack() : sp(0) {}
+ void push(const T& val) { values[sp++] = val; }
+ T& pop() { return values[--sp]; }
+};
+
+
+struct HeapBlockDesc
+{
+ uint32 m_size;
+ int16 m_memId;
+ int16 m_ptrListIndex;
+ HeapBlockDesc *m_next;
+ HeapBlockDesc *m_prev;
+
+ HeapBlockDesc *GetNextConsecutive(void)
+ {
+ return (HeapBlockDesc*)((uintptr)this + sizeof(HeapBlockDesc) + m_size);
+ }
+
+ void *GetDataPointer(void)
+ {
+ return (void*)((uintptr)this + sizeof(HeapBlockDesc));
+ }
+
+ void RemoveHeapFreeBlock(void)
+ {
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
+
+ // after node
+ void InsertHeapFreeBlock(HeapBlockDesc *node)
+ {
+ m_next = node->m_next;
+ node->m_next->m_prev = this;
+ m_prev = node;
+ node->m_next = this;
+ }
+
+ HeapBlockDesc *FindSmallestFreeBlock(uint32 size)
+ {
+ HeapBlockDesc *b;
+ for(b = m_next; b->m_size < size; b = b->m_next);
+ return b;
+ }
+};
+
+#ifdef USE_CUSTOM_ALLOCATOR
+// TODO: figure something out for 64 bit pointers
+static_assert(sizeof(HeapBlockDesc) == 0x10, "HeapBlockDesc must have 0x10 size otherwise most of assumptions don't make sense");
+#endif
+
+struct HeapBlockList
+{
+ HeapBlockDesc m_first;
+ HeapBlockDesc m_last;
+
+ void Init(void)
+ {
+ m_first.m_next = &m_last;
+ m_last.m_prev = &m_first;
+ }
+
+ void Insert(HeapBlockDesc *node)
+ {
+ node->InsertHeapFreeBlock(&m_first);
+ }
+};
+
+struct CommonSize
+{
+ HeapBlockList m_freeList;
+ uint32 m_size;
+ uint32 m_failed;
+ uint32 m_remaining;
+
+ void Init(uint32 size);
+ void Free(HeapBlockDesc *node)
+ {
+ m_freeList.Insert(node);
+ m_remaining++;
+ }
+ HeapBlockDesc *Malloc(void)
+ {
+ if(m_freeList.m_first.m_next == &m_freeList.m_last){
+ m_failed++;
+ return nil;
+ }
+ HeapBlockDesc *block = m_freeList.m_first.m_next;
+ m_remaining--;
+ block->RemoveHeapFreeBlock();
+ block->m_ptrListIndex = -1;
+ return block;
+ }
+};
+
+class CMemoryHeap
+{
+public:
+ HeapBlockDesc *m_start;
+ HeapBlockDesc *m_end;
+ HeapBlockList m_freeList;
+ CommonSize m_fixedSize[NUM_FIXED_MEMBLOCKS];
+ uint32 m_totalMemUsed;
+ CStack<int32, 16> m_idStack;
+ uint32 m_currentMemID;
+ uint32 *m_memUsed;
+ uint32 m_totalBlocksUsed;
+ uint32 *m_blocksUsed;
+ uint32 m_unkMemId;
+
+ CMemoryHeap(void) : m_start(nil) {}
+ void Init(uint32 total);
+ void RegisterMalloc(HeapBlockDesc *block);
+ void RegisterFree(HeapBlockDesc *block);
+ void *Malloc(uint32 size);
+ void *Realloc(void *ptr, uint32 size);
+ void Free(void *ptr);
+ void FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size);
+ uint32 CombineFreeBlocks(HeapBlockDesc *block);
+ void *MoveMemory(void *ptr);
+ HeapBlockDesc *WhereShouldMemoryMove(void *ptr);
+ void *MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src);
+ void PopMemId(void);
+ void PushMemId(int32 id);
+ void RegisterMemPointer(void *ptr);
+ void TidyHeap(void);
+ uint32 GetMemoryUsed(int32 id);
+ uint32 GetBlocksUsed(int32 id);
+ int32 GetLargestFreeBlock(void) { return m_freeList.m_last.m_prev->m_size; }
+
+ void ParseHeap(void);
+
+ HeapBlockDesc *GetDescFromHeapPointer(void *block)
+ {
+ return (HeapBlockDesc*)((uintptr)block - sizeof(HeapBlockDesc));
+ }
+ uint32 GetSizeBetweenBlocks(HeapBlockDesc *first, HeapBlockDesc *second)
+ {
+ return (uintptr)second - (uintptr)first - sizeof(HeapBlockDesc);
+ }
+ void FreeBlock(HeapBlockDesc *block){
+ for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){
+ if(m_fixedSize[i].m_size == block->m_size){
+ m_fixedSize[i].Free(block);
+ return;
+ }
+ }
+ HeapBlockDesc *b = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);
+ block->InsertHeapFreeBlock(b->m_prev);
+ }
+};
+
+extern CMemoryHeap gMainHeap;
diff --git a/src/rw/MemoryMgr.cpp b/src/rw/MemoryMgr.cpp
new file mode 100644
index 00000000..e2f6f144
--- /dev/null
+++ b/src/rw/MemoryMgr.cpp
@@ -0,0 +1,130 @@
+#include "common.h"
+#include "MemoryHeap.h"
+#include "MemoryMgr.h"
+
+
+uint8 *pMemoryTop;
+
+void
+InitMemoryMgr(void)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+#ifdef GTA_PS2
+#error "finish this"
+#else
+ // randomly allocate 128mb
+ gMainHeap.Init(128*1024*1024);
+#endif
+#endif
+}
+
+
+RwMemoryFunctions memFuncs = {
+ MemoryMgrMalloc,
+ MemoryMgrFree,
+ MemoryMgrRealloc,
+ MemoryMgrCalloc
+};
+
+#ifdef USE_CUSTOM_ALLOCATOR
+// game seems to be using heap directly here, but this is nicer
+void *operator new(size_t sz) { return MemoryMgrMalloc(sz); }
+void *operator new[](size_t sz) { return MemoryMgrMalloc(sz); }
+void operator delete(void *ptr) noexcept { MemoryMgrFree(ptr); }
+void operator delete[](void *ptr) noexcept { MemoryMgrFree(ptr); }
+#endif
+
+void*
+MemoryMgrMalloc(size_t size)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+ void *mem = gMainHeap.Malloc(size);
+#else
+ void *mem = malloc(size);
+#endif
+ if((uint8*)mem + size > pMemoryTop)
+ pMemoryTop = (uint8*)mem + size ;
+ return mem;
+}
+
+void*
+MemoryMgrRealloc(void *ptr, size_t size)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+ void *mem = gMainHeap.Realloc(ptr, size);
+#else
+ void *mem = realloc(ptr, size);
+#endif
+ if((uint8*)mem + size > pMemoryTop)
+ pMemoryTop = (uint8*)mem + size ;
+ return mem;
+}
+
+void*
+MemoryMgrCalloc(size_t num, size_t size)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+ void *mem = gMainHeap.Malloc(num*size);
+#else
+ void *mem = calloc(num, size);
+#endif
+ if((uint8*)mem + size > pMemoryTop)
+ pMemoryTop = (uint8*)mem + size ;
+#ifdef FIX_BUGS
+ memset(mem, 0, num*size);
+#endif
+ return mem;
+}
+
+void
+MemoryMgrFree(void *ptr)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+#ifdef FIX_BUGS
+ // i don't suppose this is handled by RW?
+ if(ptr == nil) return;
+#endif
+ gMainHeap.Free(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+void *
+RwMallocAlign(RwUInt32 size, RwUInt32 align)
+{
+#ifdef FIX_BUGS
+ uintptr ptralign = align-1;
+ void *mem = (void *)MemoryMgrMalloc(size + sizeof(uintptr) + ptralign);
+
+ ASSERT(mem != nil);
+
+ void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign);
+
+ ASSERT(addr != nil);
+#else
+ void *mem = (void *)MemoryMgrMalloc(size + align);
+
+ ASSERT(mem != nil);
+
+ void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1));
+
+ ASSERT(addr != nil);
+#endif
+
+ *(((void **)addr) - 1) = mem;
+
+ return addr;
+}
+
+void
+RwFreeAlign(void *mem)
+{
+ ASSERT(mem != nil);
+
+ void *addr = *(((void **)mem) - 1);
+
+ ASSERT(addr != nil);
+
+ MemoryMgrFree(addr);
+}
diff --git a/src/rw/MemoryMgr.h b/src/rw/MemoryMgr.h
new file mode 100644
index 00000000..e2962806
--- /dev/null
+++ b/src/rw/MemoryMgr.h
@@ -0,0 +1,12 @@
+#pragma once
+
+extern RwMemoryFunctions memFuncs;
+void InitMemoryMgr(void);
+
+void *MemoryMgrMalloc(size_t size);
+void *MemoryMgrRealloc(void *ptr, size_t size);
+void *MemoryMgrCalloc(size_t num, size_t size);
+void MemoryMgrFree(void *ptr);
+
+void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
+void RwFreeAlign(void *mem);
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 6a7010e2..e0133985 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -7,8 +7,10 @@
#include "Timecycle.h"
#include "skeleton.h"
#include "Debug.h"
-#ifndef FINAL
+#if !defined(FINAL) || defined(DEBUGMENU)
#include "rtcharse.h"
+#endif
+#ifndef FINAL
RtCharset *debugCharset;
#endif
@@ -19,7 +21,7 @@ bool gPS2alphaTest = false;
#endif
bool gBackfaceCulling = true;
-#ifndef FINAL
+#if !defined(FINAL) || defined(DEBUGMENU)
static bool charsetOpen;
void OpenCharsetSafe()
{
@@ -62,45 +64,6 @@ void FlushObrsPrintfs()
#endif
}
-void *
-RwMallocAlign(RwUInt32 size, RwUInt32 align)
-{
-#ifdef FIX_BUGS
- uintptr ptralign = align-1;
- void *mem = (void *)malloc(size + sizeof(uintptr) + ptralign);
-
- ASSERT(mem != nil);
-
- void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign);
-
- ASSERT(addr != nil);
-#else
- void *mem = (void *)malloc(size + align);
-
- ASSERT(mem != nil);
-
- void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1));
-
- ASSERT(addr != nil);
-#endif
-
- *(((void **)addr) - 1) = mem;
-
- return addr;
-}
-
-void
-RwFreeAlign(void *mem)
-{
- ASSERT(mem != nil);
-
- void *addr = *(((void **)mem) - 1);
-
- ASSERT(addr != nil);
-
- free(addr);
-}
-
void
DefinedState(void)
{
@@ -642,9 +605,81 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
return (nil);
}
-#ifdef USE_TEXTURE_POOL
-WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); }
-WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); }
+#ifdef LIBRW
+#include <rpmatfx.h>
+#include "VehicleModelInfo.h"
+
+int32
+findPlatform(rw::Atomic *a)
+{
+ rw::Geometry *g = a->geometry;
+ if(g->instData)
+ return g->instData->platform;
+ return 0;
+}
+
+// in CVehicleModelInfo in VC
+static RpMaterial*
+GetMatFXEffectMaterialCB(RpMaterial *material, void *data)
+{
+ if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTNULL)
+ return material;
+ *(int*)data = RpMatFXMaterialGetEffects(material);
+ return nil;
+}
+
+// Game doesn't read atomic extensions so we never get any other than the default pipe,
+// but we need it for uninstancing
+void
+attachPipe(rw::Atomic *atomic)
+{
+ if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
+ atomic->pipeline = rw::skinGlobals.pipelines[rw::platform];
+ else{
+ int fx = rpMATFXEFFECTNULL;
+ RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), GetMatFXEffectMaterialCB, &fx);
+ if(fx != rpMATFXEFFECTNULL)
+ RpMatFXAtomicEnableEffects(atomic);
+ }
+}
+
+// Attach pipes for the platform we have native data for so we can uninstance
+void
+switchPipes(rw::Atomic *a, int32 platform)
+{
+ if(a->pipeline && a->pipeline->platform != platform){
+ uint32 plgid = a->pipeline->pluginID;
+ switch(plgid){
+ // assume default pipe won't be attached explicitly
+ case rw::ID_SKIN:
+ a->pipeline = rw::skinGlobals.pipelines[platform];
+ break;
+ case rw::ID_MATFX:
+ a->pipeline = rw::matFXGlobals.pipelines[platform];
+ break;
+ }
+ }
+}
+
+RpAtomic*
+ConvertPlatformAtomic(RpAtomic *atomic, void *data)
+{
+ int32 driver = rw::platform;
+ int32 platform = findPlatform(atomic);
+ if(platform != 0 && platform != driver){
+ attachPipe(atomic); // kludge
+ rw::ObjPipeline *origPipe = atomic->pipeline;
+ rw::platform = platform;
+ switchPipes(atomic, rw::platform);
+ if(atomic->geometry->flags & rw::Geometry::NATIVE)
+ atomic->uninstance();
+ // no ADC in this game
+ //rw::ps2::unconvertADC(atomic->geometry);
+ rw::platform = driver;
+ atomic->pipeline = origPipe;
+ }
+ return atomic;
+}
#endif
#if defined(FIX_BUGS) && defined(GTA_PC)
diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h
index 130eb636..1a5f64b1 100644
--- a/src/rw/RwHelper.h
+++ b/src/rw/RwHelper.h
@@ -2,9 +2,6 @@
extern bool gPS2alphaTest;
-void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
-void RwFreeAlign(void *mem);
-
void OpenCharsetSafe();
void CreateDebugFont();
void DestroyDebugFont();
@@ -53,8 +50,8 @@ RwCamera *CameraCreate(RwInt32 width,
RwBool zBuffer);
-void _TexturePoolsInitialise();
-void _TexturePoolsShutdown();
+
+RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data);
#if defined(FIX_BUGS) && defined (GTA_PC)
void SetAlphaTest(RwUInt32 alpharef);
diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp
index 5dde20dd..d0addcca 100644
--- a/src/rw/TexRead.cpp
+++ b/src/rw/TexRead.cpp
@@ -18,6 +18,7 @@
#include "Sprite2d.h"
#include "Text.h"
#include "RwHelper.h"
+#include "Frontend.h"
#endif //GTA_PC
float texLoadTime;
@@ -150,11 +151,80 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
}
#ifdef GTA_PC
-#ifdef RWLIBS
-extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);
-#else
-RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);
+
+#ifdef LIBRW
+
+#define CAPSVERSION 0
+
+struct GPUcaps
+{
+ uint32 version; // so we can force regeneration easily
+ uint32 platform;
+ uint32 subplatform;
+ uint32 dxtSupport;
+};
+
+static void
+GetGPUcaps(GPUcaps *caps)
+{
+ caps->version = CAPSVERSION;
+ caps->platform = rw::platform;
+ caps->subplatform = 0;
+ caps->dxtSupport = 0;
+ // TODO: more later
+#ifdef RW_GL3
+ caps->subplatform = rw::gl3::gl3Caps.gles;
+ caps->dxtSupport = rw::gl3::gl3Caps.dxtSupported;
+#endif
+#ifdef RW_D3D9
+ caps->dxtSupport = 1; // TODO, probably
#endif
+}
+
+void
+ReadVideoCardCapsFile(GPUcaps *caps)
+{
+ memset(caps, 0, sizeof(GPUcaps));
+
+ int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "rb");
+ if (file != 0) {
+ CFileMgr::Read(file, (char*)&caps->version, 4);
+ CFileMgr::Read(file, (char*)&caps->platform, 4);
+ CFileMgr::Read(file, (char*)&caps->subplatform, 4);
+ CFileMgr::Read(file, (char*)&caps->dxtSupport, 4);
+ CFileMgr::CloseFile(file);
+ }
+}
+
+bool
+CheckVideoCardCaps(void)
+{
+ GPUcaps caps, fcaps;
+ GetGPUcaps(&caps);
+ ReadVideoCardCapsFile(&fcaps);
+ return caps.version != fcaps.version ||
+ caps.platform != fcaps.platform ||
+ caps.subplatform != fcaps.subplatform ||
+ caps.dxtSupport != fcaps.dxtSupport;
+}
+
+void
+WriteVideoCardCapsFile(void)
+{
+ GPUcaps caps;
+ GetGPUcaps(&caps);
+ int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "wb");
+ if (file != 0) {
+ CFileMgr::Write(file, (char*)&caps.version, 4);
+ CFileMgr::Write(file, (char*)&caps.platform, 4);
+ CFileMgr::Write(file, (char*)&caps.subplatform, 4);
+ CFileMgr::Write(file, (char*)&caps.dxtSupport, 4);
+ CFileMgr::CloseFile(file);
+ }
+}
+
+#else
+extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);
void
ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8)
{
@@ -201,6 +271,7 @@ WriteVideoCardCapsFile(void)
CFileMgr::CloseFile(file);
}
}
+#endif
void
ConvertingTexturesScreen(uint32 num, uint32 count, const char *text)
@@ -282,6 +353,22 @@ CreateTxdImageForVideoCard()
return false;
}
+#ifdef RW_GL3
+ // so we can read back DXT with GLES
+ // only works for textures that are not yet loaded
+ // so let's hope that is the case for all
+ rw::gl3::needToReadBackTextures = true;
+#endif
+
+#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION
+ // let's disable vsync and frame limiter to speed up texture conversion
+ // (actually we probably don't need to disable frame limiter in here, but let's do it just in case =P)
+ int8 vsyncState = CMenuManager::m_PrefsVsync;
+ int8 frameLimiterState = CMenuManager::m_PrefsFrameLimiter;
+ CMenuManager::m_PrefsVsync = 0;
+ CMenuManager::m_PrefsFrameLimiter = 0;
+#endif
+
int32 i;
for (i = 0; i < TXDSTORESIZE; i++) {
ConvertingTexturesScreen(i, TXDSTORESIZE, "CVT_MSG");
@@ -309,6 +396,9 @@ CreateTxdImageForVideoCard()
delete []buf;
delete pDir;
CStreaming::RemoveTxd(i);
+#ifdef RW_GL3
+ rw::gl3::needToReadBackTextures = false;
+#endif
return false;
}
@@ -332,9 +422,19 @@ CreateTxdImageForVideoCard()
}
}
+#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION
+ // restore vsync and frame limiter states
+ CMenuManager::m_PrefsVsync = vsyncState;
+ CMenuManager::m_PrefsFrameLimiter = frameLimiterState;
+#endif
+
RwStreamClose(img, nil);
delete []buf;
+#ifdef RW_GL3
+ rw::gl3::needToReadBackTextures = false;
+#endif
+
if (!pDir->WriteDirFile("models\\txd.dir")) {
DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR");
delete pDir;
diff --git a/src/rw/TexturePools.cpp b/src/rw/TexturePools.cpp
new file mode 100644
index 00000000..c2ba6cf9
--- /dev/null
+++ b/src/rw/TexturePools.cpp
@@ -0,0 +1,221 @@
+#ifndef LIBRW
+
+#include <d3d8.h>
+#define WITHD3D
+#include "common.h"
+#include "TexturePools.h"
+
+// TODO: this needs to be integrated into RW
+
+extern "C" LPDIRECT3DDEVICE8 _RwD3DDevice;
+
+CTexturePool aTexturePools[12];
+CPaletteList PaletteList;
+int numTexturePools;
+int MaxPaletteIndex;
+bool bUsePaletteIndex = true;
+
+
+void
+CTexturePool::Create(D3DFORMAT _Format, int _size, uint32 mipmapLevels, int32 numTextures)
+{
+ Format = _Format;
+ size = _size;
+ levels = mipmapLevels;
+ pTextures = new IDirect3DTexture8 *[numTextures];
+ texturesMax = numTextures;
+ texturesNum = 0;
+ texturesUsed = 0;
+}
+
+void
+CTexturePool::Release()
+{
+ int i = 0;
+ while (i < texturesNum) {
+ pTextures[i]->Release();
+ i++;
+ }
+
+ delete[] pTextures;
+
+ pTextures = nil;
+ texturesNum = 0;
+ texturesUsed = 0;
+}
+
+IDirect3DTexture8 *
+CTexturePool::FindTexture()
+{
+ if (texturesNum == 0)
+ return nil;
+ texturesUsed--;
+ return pTextures[--texturesNum];
+}
+
+bool
+CTexturePool::AddTexture(IDirect3DTexture8 *texture)
+{
+ ++texturesUsed;
+ if (texturesNum >= texturesMax)
+ return false;
+ pTextures[texturesNum] = texture;
+ ++texturesNum;
+ return true;
+}
+
+void
+CTexturePool::Resize(int numTextures)
+{
+ if (numTextures == texturesMax)
+ return;
+
+ IDirect3DTexture8 **newTextures = new IDirect3DTexture8 *[numTextures];
+
+ for (int i = 0; i < texturesNum && i < numTextures; i++)
+ newTextures[i] = pTextures[i];
+
+ if (numTextures < texturesNum) {
+ for (int i = numTextures; i < texturesNum; i++)
+ pTextures[i]->Release();
+ }
+ delete[] pTextures;
+ pTextures = newTextures;
+ texturesMax = numTextures;
+}
+
+void
+CPaletteList::Alloc(int max)
+{
+ Data = new int[max];
+ Max = max;
+ Num = 0;
+}
+
+void
+CPaletteList::Free()
+{
+ delete[] Data;
+ Data = nil;
+ Num = 0;
+}
+
+int
+CPaletteList::Find()
+{
+ if (Num == 0)
+ return -1;
+ return Data[--Num];
+}
+
+void
+CPaletteList::Add(int item)
+{
+ if (Num < Max)
+ Data[Num++] = item;
+ else {
+ Resize(2 * Max);
+ Add(item);
+ }
+}
+
+void
+CPaletteList::Resize(int max)
+{
+ if (max == Max)
+ return;
+
+ int *newData = new int[4 * max];
+ for (int i = 0; i < Num && i < max; i++)
+ newData[i] = Data[i];
+ delete[] Data;
+ Data = newData;
+ Max = max;
+}
+
+HRESULT
+CreateTexture(int width, int height, int levels, D3DFORMAT Format, IDirect3DTexture8 **texture)
+{
+ if (width == height) {
+ for (int i = 0; i < numTexturePools; i++) {
+ if (width != aTexturePools[i].GetSize() && levels == aTexturePools[i].levels && Format == aTexturePools[i].Format)
+ *texture = aTexturePools[i].FindTexture();
+ }
+ }
+ if (*texture)
+ return D3D_OK;
+ else
+ return _RwD3DDevice->CreateTexture(width, height, levels, 0, Format, D3DPOOL_MANAGED, texture);
+}
+
+void
+ReleaseTexture(IDirect3DTexture8 *texture)
+{
+ int levels = 1;
+ if (texture->GetLevelCount() > 1)
+ levels = 0;
+
+ D3DSURFACE_DESC SURFACE_DESC;
+
+ texture->GetLevelDesc(0, &SURFACE_DESC);
+
+ if (SURFACE_DESC.Width == SURFACE_DESC.Height) {
+ for (int i = 0; i < numTexturePools; i++) {
+ if (SURFACE_DESC.Width == aTexturePools[i].GetSize() && SURFACE_DESC.Format == aTexturePools[i].Format && levels == aTexturePools[i].levels) {
+ if (!aTexturePools[i].AddTexture(texture)) {
+ if (aTexturePools[i].texturesUsed > 3 * aTexturePools[i].texturesMax / 2) {
+ aTexturePools[i].Resize(2 * aTexturePools[i].texturesMax);
+ aTexturePools[i].texturesUsed--;
+ aTexturePools[i].AddTexture(texture);
+ } else {
+ texture->Release();
+ }
+ }
+ return;
+ }
+ }
+ }
+ if (numTexturePools < 12 && bUsePaletteIndex && levels != 0 && SURFACE_DESC.Width == SURFACE_DESC.Height &&
+ (SURFACE_DESC.Width == 64 || SURFACE_DESC.Width == 128 || SURFACE_DESC.Width == 256)) {
+ aTexturePools[numTexturePools].Create(SURFACE_DESC.Format, SURFACE_DESC.Width, 1, 16);
+ aTexturePools[numTexturePools].AddTexture(texture);
+ numTexturePools++;
+ } else
+ texture->Release();
+}
+
+int
+FindAvailablePaletteIndex()
+{
+ int index = PaletteList.Find();
+ if (index == -1)
+ index = MaxPaletteIndex++;
+ return index;
+}
+
+void
+AddAvailablePaletteIndex(int index)
+{
+ if (bUsePaletteIndex)
+ PaletteList.Add(index);
+}
+
+void
+_TexturePoolsInitialise()
+{
+ PaletteList.Alloc(100);
+ MaxPaletteIndex = 0;
+}
+
+void
+_TexturePoolsShutdown()
+{
+ for (int i = 0; i < numTexturePools; i++)
+ aTexturePools[i].Release();
+
+ numTexturePools = 0;
+ bUsePaletteIndex = false;
+ PaletteList.Free();
+}
+
+#endif // !LIBRW \ No newline at end of file
diff --git a/src/rw/TexturePools.h b/src/rw/TexturePools.h
new file mode 100644
index 00000000..75187432
--- /dev/null
+++ b/src/rw/TexturePools.h
@@ -0,0 +1,42 @@
+#pragma once
+
+class CTexturePool
+{
+public:
+ D3DFORMAT Format;
+ int size;
+ uint32 levels;
+ int32 texturesMax;
+ int32 texturesUsed;
+ int32 texturesNum;
+ IDirect3DTexture8 **pTextures;
+
+public:
+ CTexturePool() {}
+ void Create(D3DFORMAT _Format, int size, uint32 mipmapLevels, int32 numTextures);
+ void Release();
+ IDirect3DTexture8 *FindTexture();
+ bool AddTexture(IDirect3DTexture8 *texture);
+ void Resize(int numTextures);
+#ifdef FIX_BUGS
+ int GetSize() { return size; }
+#else
+ float GetSize() { return size; }
+#endif
+};
+
+class CPaletteList
+{
+ int Max;
+ int Num;
+ int *Data;
+public:
+ void Alloc(int max);
+ void Free();
+ int Find();
+ void Add(int item);
+ void Resize(int max);
+};
+
+void _TexturePoolsInitialise();
+void _TexturePoolsShutdown(); \ No newline at end of file
diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp
index 8878a26a..b27d96c8 100644
--- a/src/rw/VisibilityPlugins.cpp
+++ b/src/rw/VisibilityPlugins.cpp
@@ -10,8 +10,7 @@
#include "VisibilityPlugins.h"
#include "World.h"
#include "custompipes.h"
-
-#define FADE_DISTANCE 20.0f
+#include "MemoryHeap.h"
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList;
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList;
@@ -32,6 +31,119 @@ float CVisibilityPlugins::ms_pedLod0Dist;
float CVisibilityPlugins::ms_pedLod1Dist;
float CVisibilityPlugins::ms_pedFadeDist;
+#ifdef GTA_PS2 // maybe something else?
+// if wanted, delete the original geometry data after rendering
+// and only keep the instanced data
+bool
+rpDefaultGeometryInstance(RpGeometry *geo, void *atomic, int del)
+{
+#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
+ if(RpGeometryGetNumMorphTargets(geo) != 1)
+ return false;
+
+ // this needs R*'s modification that geometry data is
+ // allocated separately from the geometry itself
+ geo->instanceFlags = rpGEOMETRYINSTANCE;
+ AtomicDefaultRenderCallBack((RpAtomic*)atomic);
+
+ if(!del)
+ return true;
+
+ // New mesh without indices
+ RpMeshHeader *newheader = _rpMeshHeaderCreate(sizeof(RpMesh)*geo->mesh->numMeshes + sizeof(RpMeshHeader));
+ newheader->numMeshes = geo->mesh->numMeshes;
+ newheader->serialNum = 1;
+ newheader->totalIndicesInMesh = 0;
+ newheader->firstMeshOffset = 0;
+ RpMesh *oldmesh = (RpMesh*)(geo->mesh+1);
+ RpMesh *newmesh = (RpMesh*)(newheader+1);
+ for(int i = 0; i < geo->mesh->numMeshes; i++){
+ newmesh[i].indices = nil;
+ newmesh[i].numIndices = 0;
+ newmesh[i].material = oldmesh[i].material;
+ }
+
+ geo->refCount++;
+ RpGeometryLock(geo, rpGEOMETRYLOCKPOLYGONS | rpGEOMETRYLOCKVERTICES |
+ rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT |
+ rpGEOMETRYLOCKTEXCOORDS1 | rpGEOMETRYLOCKTEXCOORDS2);
+
+ // vertices and normals
+ RpMorphTarget *mt = RpGeometryGetMorphTarget(geo, 0);
+ if(mt->verts){
+ RwFree(mt->verts);
+ mt->verts = nil;
+ mt->normals = nil;
+ }
+ geo->numVertices = 0;
+
+ // triangles
+ for(int i = 0; i < RpGeometryGetNumTriangles(geo); i++){
+ if(RpGeometryGetTriangles(geo)->matIndex == -1)
+ continue;
+ RpMaterialDestroy(_rpMaterialListGetMaterial(&geo->matList, RpGeometryGetTriangles(geo)->matIndex));
+ }
+ if(RpGeometryGetTriangles(geo)){
+ RwFree(RpGeometryGetTriangles(geo));
+ geo->triangles = nil;
+ geo->numTriangles = 0;
+ }
+
+ // tex coords
+ if(RpGeometryGetVertexTexCoords(geo, 1)){
+ RwFree(RpGeometryGetVertexTexCoords(geo, 1));
+ geo->texCoords[1] = nil;
+ }
+ if(RpGeometryGetVertexTexCoords(geo, 0)){
+ RwFree(RpGeometryGetVertexTexCoords(geo, 0));
+ geo->texCoords[0] = nil;
+ }
+
+ // vertex colors
+ if(RpGeometryGetPreLightColors(geo)){
+ RwFree(RpGeometryGetPreLightColors(geo));
+ geo->preLitLum = nil;
+ }
+
+ RpGeometryUnlock(geo);
+
+ geo->instanceFlags = rpGEOMETRYPERSISTENT;
+ // BUG? don't we have to free the old mesh?
+ geo->mesh = newheader;
+ geo->refCount--;
+#else
+ // We can do something for librw here actually, maybe later
+ AtomicDefaultRenderCallBack((RpAtomic*)atomic);
+#endif
+
+ return true;
+}
+
+RpAtomic*
+PreInstanceRenderCB(RpAtomic *atomic)
+{
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ if(RpGeometryGetTriangles(geo)){
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ rpDefaultGeometryInstance(geo, atomic, 1);
+ POP_MEMID();
+ }else
+ AtomicDefaultRenderCallBack(atomic);
+ return atomic;
+}
+#define RENDERCALLBACK PreInstanceRenderCB
+#else
+RpAtomic*
+DefaultRenderCB_pushid(RpAtomic *atomic)
+{
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ AtomicDefaultRenderCallBack(atomic);
+ POP_MEMID();
+ return atomic;
+}
+#define RENDERCALLBACK DefaultRenderCB_pushid
+#endif
+
void
CVisibilityPlugins::Initialise(void)
{
@@ -134,7 +246,7 @@ CVisibilityPlugins::RenderAlphaAtomics(void)
for(node = m_alphaList.tail.prev;
node != &m_alphaList.head;
node = node->prev)
- AtomicDefaultRenderCallBack(node->item.atomic);
+ RENDERCALLBACK(node->item.atomic);
}
void
@@ -203,7 +315,7 @@ CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic)
if(lodatm){
if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic))
RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -220,7 +332,7 @@ CVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic)
len = RwV3dLength(&view);
if(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f)
return atomic;
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -234,7 +346,7 @@ CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha)
flags = RpGeometryGetFlags(geo);
RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
RpGeometrySetFlags(geo, flags);
return atomic;
@@ -252,7 +364,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);
if(mi->m_additive){
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}else{
fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
@@ -260,7 +372,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
fadefactor = 1.0f;
alpha = mi->m_alpha * fadefactor;
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else{
RpGeometry *geo = RpAtomicGetGeometry(lodatm);
uint32 flags = RpGeometryGetFlags(geo);
@@ -268,7 +380,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
if(geo != RpAtomicGetGeometry(atomic))
RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
RpGeometrySetFlags(geo, flags);
}
@@ -295,7 +407,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic)
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -320,10 +432,10 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic)
if(flags & ATOMIC_FLAG_DRAWLAST){
// sort before clump
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}else{
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
}
return atomic;
@@ -346,7 +458,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic)
if(dot > 0.0f)
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -369,7 +481,7 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)
return atomic;
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -383,7 +495,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic)
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
distsq = GetDistanceSquaredFromCamera(clumpframe);
if(distsq < ms_bigVehicleLod1Dist)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -405,7 +517,7 @@ CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic)
if(dot > 0.0f)
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -429,7 +541,7 @@ CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic)
return atomic;
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -446,7 +558,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)
if(dist >= ms_vehicleLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -463,7 +575,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic)
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
distsq = GetDistanceSquaredFromCamera(clumpframe);
if(distsq >= ms_bigVehicleLod1Dist)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -484,7 +596,7 @@ CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic)
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
return atomic;
}
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
return atomic;
}
@@ -509,10 +621,10 @@ CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)
if(flags & ATOMIC_FLAG_DRAWLAST){
// sort before clump
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}else{
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
}
}
return atomic;
@@ -523,7 +635,7 @@ CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)
{
if(CWorld::Players[0].m_pSkinTexture)
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture);
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
return atomic;
}
@@ -539,7 +651,7 @@ CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic)
if(dist >= ms_pedLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -558,7 +670,7 @@ CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic)
if(dist < ms_pedLod0Dist){
alpha = GetClumpAlpha(clump);
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -577,7 +689,7 @@ CVisibilityPlugins::RenderPedCB(RpAtomic *atomic)
if(RwV3dDotProduct(&cam2atm, &cam2atm) < ms_pedLod1Dist){
alpha = GetClumpAlpha(RpAtomicGetClump(atomic));
if(alpha == 255)
- AtomicDefaultRenderCallBack(atomic);
+ RENDERCALLBACK(atomic);
else
RenderAlphaAtomic(atomic, alpha);
}
@@ -707,6 +819,11 @@ CVisibilityPlugins::PluginAttach(void)
ms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt),
ID_VISIBILITYCLUMP,
ClumpConstructor, ClumpDestructor, ClumpCopyConstructor);
+
+#if GTA_VERSION <= GTA3_PS2_160
+ Initialise();
+#endif
+
return ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1;
}
@@ -777,12 +894,11 @@ CVisibilityPlugins::GetAtomicId(RpAtomic *atomic)
return ATOMICEXT(atomic)->flags;
}
-// This is rather useless, but whatever
void
CVisibilityPlugins::SetAtomicRenderCallback(RpAtomic *atomic, RpAtomicCallBackRender cb)
{
if(cb == nil)
- cb = AtomicDefaultRenderCallBack; // not necessary
+ cb = RENDERCALLBACK;
RpAtomicSetRenderCallBack(atomic, cb);
}
diff --git a/src/save/MemoryCard.cpp b/src/save/MemoryCard.cpp
index a24b754c..c8ebcd86 100644
--- a/src/save/MemoryCard.cpp
+++ b/src/save/MemoryCard.cpp
@@ -11,6 +11,7 @@
#include "Clock.h"
#include "MBlur.h"
#include "Date.h"
+#include "Font.h"
#include "FileMgr.h"
#include "Game.h"
#include "GameLogic.h"
diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp
index 4d41a900..7354c90a 100644
--- a/src/skel/glfw/glfw.cpp
+++ b/src/skel/glfw/glfw.cpp
@@ -40,6 +40,7 @@
#include "Sprite2d.h"
#include "AnimViewer.h"
#include "Font.h"
+#include "MemoryMgr.h"
#define MAX_SUBSYSTEMS (16)
@@ -244,8 +245,10 @@ double
psTimer(void)
{
struct timespec start;
-#ifdef __linux__
+#if defined(CLOCK_MONOTONIC_RAW)
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
+#elif defined(CLOCK_MONOTONIC_FAST)
+ clock_gettime(CLOCK_MONOTONIC_FAST, &start);
#else
clock_gettime(CLOCK_MONOTONIC, &start);
#endif
@@ -275,7 +278,11 @@ psMouseSetPos(RwV2d *pos)
RwMemoryFunctions*
psGetMemoryFunctions(void)
{
+#ifdef USE_CUSTOM_ALLOCATOR
+ return &memFuncs;
+#else
return nil;
+#endif
}
/*
@@ -382,7 +389,7 @@ psInitialize(void)
InitialiseLanguage();
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
FrontEndMenuManager.LoadSettings();
#endif
@@ -436,7 +443,7 @@ psInitialize(void)
#ifndef PS2_MENU
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
FrontEndMenuManager.LoadSettings();
#endif
@@ -826,7 +833,10 @@ psSelectDevice()
PSGLOBAL(fullScreen) = !FrontEndMenuManager.m_nPrefsWindowed;
#endif
-
+
+#ifdef MULTISAMPLING
+ RwD3D8EngineSetMultiSamplingLevels(1 << FrontEndMenuManager.m_nPrefsMSAALevel);
+#endif
return TRUE;
}
@@ -893,7 +903,7 @@ void psPostRWinit(void)
RwEngineGetVideoModeInfo(&vm, GcurSelVM);
glfwSetKeyCallback(PSGLOBAL(window), keypressCB);
- glfwSetWindowSizeCallback(PSGLOBAL(window), resizeCB);
+ glfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB);
glfwSetScrollCallback(PSGLOBAL(window), scrollCB);
glfwSetCursorPosCallback(PSGLOBAL(window), cursorCB);
glfwSetCursorEnterCallback(PSGLOBAL(window), cursorEnterCB);
@@ -1414,8 +1424,13 @@ _InputTranslateShiftKeyUpDown(RsKeyCodes *rs) {
// TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000
void
cursorCB(GLFWwindow* window, double xpos, double ypos) {
- FrontEndMenuManager.m_nMouseTempPosX = xpos;
- FrontEndMenuManager.m_nMouseTempPosY = ypos;
+ if (!FrontEndMenuManager.m_bMenuActive)
+ return;
+
+ int winw, winh;
+ glfwGetWindowSize(PSGLOBAL(window), &winw, &winh);
+ FrontEndMenuManager.m_nMouseTempPosX = xpos * (RsGlobal.maximumWidth / winw);
+ FrontEndMenuManager.m_nMouseTempPosY = ypos * (RsGlobal.maximumHeight / winh);
}
void
@@ -1438,12 +1453,14 @@ WinMain(HINSTANCE instance,
RwChar** argv;
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);
-#if 0
- // TODO: make this an option somewhere
- AllocConsole();
- freopen("CONIN$", "r", stdin);
- freopen("CONOUT$", "w", stdout);
- freopen("CONOUT$", "w", stderr);
+#ifndef MASTER
+ if (strstr(cmdLine, "-console"))
+ {
+ AllocConsole();
+ freopen("CONIN$", "r", stdin);
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);
+ }
#endif
#else
@@ -1454,6 +1471,10 @@ main(int argc, char *argv[])
RwV2d pos;
RwInt32 i;
+#ifdef USE_CUSTOM_ALLOCATOR
+ InitMemoryMgr();
+#endif
+
#ifndef _WIN32
struct sigaction act;
act.sa_sigaction = terminateHandler;
diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp
index 4780316a..3166093e 100644
--- a/src/skel/skeleton.cpp
+++ b/src/skel/skeleton.cpp
@@ -10,6 +10,7 @@
#include "skeleton.h"
#include "platform.h"
+#include "MemoryHeap.h"
@@ -307,6 +308,8 @@ RsRwInitialize(void *displayID)
{
RwEngineOpenParams openParams;
+ PUSH_MEMID(MEMID_RENDER); // NB: not popped on failed return
+
/*
* Start RenderWare...
*/
@@ -374,6 +377,8 @@ RsRwInitialize(void *displayID)
RwTextureSetMipmapping(FALSE);
RwTextureSetAutoMipmapping(FALSE);
+ POP_MEMID();
+
return TRUE;
}
diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp
index 9effaa31..c16ea2a1 100644
--- a/src/skel/win/win.cpp
+++ b/src/skel/win/win.cpp
@@ -97,6 +97,7 @@ static psGlobalType PsGlobal;
#include "Sprite2d.h"
#include "AnimViewer.h"
#include "Font.h"
+#include "MemoryMgr.h"
VALIDATE_SIZE(psGlobalType, 0x28);
@@ -304,7 +305,11 @@ psMouseSetPos(RwV2d *pos)
RwMemoryFunctions*
psGetMemoryFunctions(void)
{
+#ifdef USE_CUSTOM_ALLOCATOR
+ return &memFuncs;
+#else
return nil;
+#endif
}
/*
@@ -646,7 +651,7 @@ psInitialize(void)
C_PcSave::SetSaveDirectory(_psGetUserFilesFolder());
InitialiseLanguage();
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
FrontEndMenuManager.LoadSettings();
#endif
@@ -698,7 +703,7 @@ psInitialize(void)
#ifndef PS2_MENU
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
FrontEndMenuManager.LoadSettings();
#endif
@@ -2006,12 +2011,18 @@ WinMain(HINSTANCE instance,
RwChar **argv;
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);
-#if 0
- // TODO: make this an option somewhere
- AllocConsole();
- freopen("CONIN$", "r", stdin);
- freopen("CONOUT$", "w", stdout);
- freopen("CONOUT$", "w", stderr);
+#ifndef MASTER
+ if (strstr(cmdLine, "-console"))
+ {
+ AllocConsole();
+ freopen("CONIN$", "r", stdin);
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);
+ }
+#endif
+
+#ifdef USE_CUSTOM_ALLOCATOR
+ InitMemoryMgr();
#endif
/*
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 95a68769..ec71f690 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -75,7 +75,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
SetModelIndex(id);
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
+ pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);
m_auto_unused1 = 20.0f;
m_auto_unused2 = 0;
@@ -4183,6 +4183,93 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
}
void
+CPed::DeadPedMakesTyresBloody(void)
+{
+ int minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f);
+ if (minX < 0) minX = 0;
+ int minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f);
+ if (minY < 0) minY = 0;
+ int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);
+ if (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1;
+ int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);
+ if (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1;
+
+ CWorld::AdvanceCurrentScanCode();
+
+ for (int curY = minY; curY <= maxY; curY++) {
+ for (int curX = minX; curX <= maxX; curX++) {
+ CSector *sector = CWorld::GetSector(curX, curY);
+ MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]);
+ MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
+ }
+ }
+}
+
+void
+CPed::MakeTyresMuddySectorList(CPtrList &list)
+{
+ for (CPtrNode *node = list.first; node; node = node->next) {
+ CVehicle *veh = (CVehicle*)node->item;
+ if (veh->IsCar() && veh->m_scanCode != CWorld::GetCurrentScanCode()) {
+ veh->m_scanCode = CWorld::GetCurrentScanCode();
+
+ if (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f) {
+
+ if (Abs(GetPosition().y - veh->GetPosition().y) < 10.0f
+ && veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) {
+
+ for(int wheel = 0; wheel < 4; wheel++) {
+
+ if (!((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel]
+ && ((CAutomobile*)veh)->m_aSuspensionSpringRatio[wheel] < 1.0f) {
+
+ CColModel *vehCol = veh->GetModelInfo()->GetColModel();
+ CVector approxWheelOffset;
+ switch (wheel) {
+ case 0:
+ approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
+ break;
+ case 1:
+ approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
+ break;
+ case 2:
+ approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
+ break;
+ case 3:
+ approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
+ break;
+ default:
+ break;
+ }
+
+ // I hope so
+ CVector wheelPos = veh->GetMatrix() * approxWheelOffset;
+ if (Abs(wheelPos.z - GetPosition().z) < 2.0f) {
+
+ if ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) {
+ if (CGame::nastyGame) {
+ ((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] = true;
+ DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_SPLATTER, 0.0f);
+ }
+ veh->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f));
+
+ CVector vehAndWheelDist = wheelPos - veh->GetPosition();
+ veh->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f), vehAndWheelDist);
+
+ if (veh == FindPlayerVehicle()) {
+ CPad::GetPad(0)->StartShake(300, 70);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void
CAutomobile::SetBusDoorTimer(uint32 timer, uint8 type)
{
if(timer < 1000)
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index dfe9d1d9..aba48bad 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -50,7 +50,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)
m_fMovingRotation = 0.0f;
SetModelIndex(mi);
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId);
+ pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)minfo->m_handlingId);
minfo->ChooseVehicleColour(m_currentColour1, m_currentColour2);
m_fMass = pHandling->fMass;
diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp
index 757974a6..564f493d 100644
--- a/src/vehicles/Cranes.cpp
+++ b/src/vehicles/Cranes.cpp
@@ -639,11 +639,11 @@ void CCranes::Save(uint8* buf, uint32* size)
for (int i = 0; i < NUM_CRANES; i++) {
CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]);
if (pCrane->m_pCraneEntity != nil)
- pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex(pCrane->m_pCraneEntity) + 1);
+ pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1);
if (pCrane->m_pHook != nil)
- pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex(pCrane->m_pHook) + 1);
+ pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1);
if (pCrane->m_pVehiclePickedUp != nil)
- pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex(pCrane->m_pVehiclePickedUp) + 1);
+ pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1);
}
VALIDATESAVEBUF(*size);
diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp
index 5beed29e..18a2481e 100644
--- a/src/vehicles/HandlingMgr.cpp
+++ b/src/vehicles/HandlingMgr.cpp
@@ -127,7 +127,7 @@ cHandlingDataMgr::LoadHandlingData(void)
handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
handling = &HandlingData[handlingId];
- handling->nIdentifier = (eHandlingId)handlingId;
+ handling->nIdentifier = (tVehicleType)handlingId;
break;
case 1: handling->fMass = strtod(word, nil); break;
case 2: handling->Dimension.x = strtod(word, nil); break;
@@ -237,3 +237,27 @@ cHandlingDataMgr::GetHandlingId(const char *name)
break;
return i;
}
+
+void
+cHandlingDataMgr::ConvertDataToWorldUnits(tHandlingData *handling)
+{
+ // TODO: mobile code
+}
+
+void
+cHandlingDataMgr::RangeCheck(tHandlingData *handling)
+{
+ // TODO: mobile code
+}
+
+void
+cHandlingDataMgr::ModifyHandlingValue(CVehicle *, const tVehicleType &, const tField &, const bool &)
+{
+ // TODO: mobile code
+}
+
+void
+cHandlingDataMgr::DisplayHandlingData(CVehicle *, tHandlingData *, uint8, bool)
+{
+ // TODO: mobile code
+} \ No newline at end of file
diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h
index 10e25573..4d3b8389 100644
--- a/src/vehicles/HandlingMgr.h
+++ b/src/vehicles/HandlingMgr.h
@@ -2,7 +2,7 @@
#include "Transmission.h"
-enum eHandlingId
+enum tVehicleType
{
HANDLING_LANDSTAL,
HANDLING_IDAHO,
@@ -65,6 +65,11 @@ enum eHandlingId
NUMHANDLINGS
};
+enum tField : uint32 // most likely a handling field enum, never used so :shrug:
+{
+
+};
+
enum
{
HANDLING_1G_BOOST = 1,
@@ -87,7 +92,7 @@ enum
struct tHandlingData
{
- eHandlingId nIdentifier;
+ tVehicleType nIdentifier;
float fMass;
float fInvMass;
float fTurnMass;
@@ -118,6 +123,8 @@ struct tHandlingData
};
VALIDATE_SIZE(tHandlingData, 0xD8);
+class CVehicle;
+
class cHandlingDataMgr
{
float field_0; // unused it seems
@@ -135,11 +142,15 @@ public:
void Initialise(void);
void LoadHandlingData(void);
int FindExactWord(const char *word, const char *words, int wordLen, int numWords);
+ void ConvertDataToWorldUnits(tHandlingData *handling);
void ConvertDataToGameUnits(tHandlingData *handling);
+ void RangeCheck(tHandlingData *handling);
+ void ModifyHandlingValue(CVehicle *, const tVehicleType &, const tField &, const bool &);
+ void DisplayHandlingData(CVehicle *, tHandlingData *, uint8, bool);
int32 GetHandlingId(const char *name);
- tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; }
- bool HasRearWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'R'; }
- bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; }
+ tHandlingData *GetHandlingData(tVehicleType id) { return &HandlingData[id]; }
+ bool HasRearWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType == 'R'; }
+ bool HasFrontWheelDrive(tVehicleType 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 e1f662d8..7008818b 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -52,7 +52,7 @@ CHeli::CHeli(int32 id, uint8 CreatedBy)
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
m_vehType = VEHICLE_TYPE_HELI;
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
+ pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);
SetModelIndex(id);
m_heliStatus = HELI_STATUS_HOVER;
m_pathState = 0;
@@ -778,8 +778,10 @@ CHeli::InitHelis(void)
for(i = 0; i < NUM_HELIS; i++)
pHelis[i] = nil;
+#if GTA_VERSION >= GTA3_PS2_160
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1);
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);
+#endif
}
CHeli*
@@ -789,6 +791,13 @@ GenerateHeli(bool catalina)
CVector heliPos;
int i;
+#if GTA_VERSION < GTA3_PS2_160
+ if(catalina)
+ ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1);
+ else
+ ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);
+#endif
+
if(catalina)
heli = new CHeli(MI_ESCAPE, PERMANENT_VEHICLE);
else
diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp
index b8a957cf..532be938 100644
--- a/src/vehicles/Plane.cpp
+++ b/src/vehicles/Plane.cpp
@@ -15,6 +15,7 @@
#include "World.h"
#include "HandlingMgr.h"
#include "Plane.h"
+#include "MemoryHeap.h"
CPlaneNode *pPathNodes;
CPlaneNode *pPath2Nodes;
@@ -68,7 +69,7 @@ CPlane::CPlane(int32 id, uint8 CreatedBy)
{
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
m_vehType = VEHICLE_TYPE_PLANE;
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
+ pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);
SetModelIndex(id);
m_fMass = 100000000.0f;
@@ -551,9 +552,11 @@ CPlane::ProcessControl(void)
if(m_rwObject && RwObjectGetType(m_rwObject) == rpCLUMP){
DeleteRwObject();
if(mi->m_planeLodId != -1){
+ PUSH_MEMID(MEMID_WORLD);
m_rwObject = CModelInfo::GetModelInfo(mi->m_planeLodId)->CreateInstance();
+ POP_MEMID();
if(m_rwObject)
- m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)));
+ m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)));
}
}
}else if(CStreaming::HasModelLoaded(GetModelIndex())){
diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp
index 26d0dee7..4250f6f4 100644
--- a/src/vehicles/Train.cpp
+++ b/src/vehicles/Train.cpp
@@ -43,7 +43,7 @@ CTrain::CTrain(int32 id, uint8 CreatedBy)
{
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
m_vehType = VEHICLE_TYPE_TRAIN;
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
+ pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);
SetModelIndex(id);
Doors[0].Init(0.8f, 0.0f, 1, 0);
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index bc77b011..9adcf148 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -405,7 +405,7 @@ CVehicle::FlyingControl(eFlightModel flightModel)
else
fThrust = fThrustVar * (CPad::GetPad(0)->GetAccelerate() - 2 * CPad::GetPad(0)->GetBrake()) / 255.0f + 0.95f;
fThrust -= fRotorFallOff * DotProduct(m_vecMoveSpeed, GetUp());
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
if (fThrust > 0.9f && GetPosition().z > 80.0f)
fThrust = 0.9f;
#endif
@@ -582,6 +582,13 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
}
}
+void
+CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust,
+ float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus)
+{
+ // TODO: mobile code
+}
+
float
CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius)
{
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 999ee002..3933f1dd 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -103,6 +103,15 @@ enum eFlightModel
FLIGHT_MODEL_SEAPLANE
};
+// TODO: what is this even?
+enum eBikeWheelSpecial {
+ BIKE_WHEELSPEC_0, // both wheels on ground
+ BIKE_WHEELSPEC_1, // rear wheel on ground
+ BIKE_WHEELSPEC_2, // only front wheel on ground
+ BIKE_WHEELSPEC_3, // can't happen
+};
+
+
class CVehicle : public CPhysical
{
public:
@@ -237,6 +246,8 @@ public:
void FlyingControl(eFlightModel flightModel);
void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus);
+ void ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust,
+ float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus);
void ExtinguishCarFire(void);
void ProcessDelayedExplosion(void);
float ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius);
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index 9494c745..dc15485e 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -2288,6 +2288,16 @@ CWeapon::HasWeaponAmmoToBeUsed(void)
}
bool
+CPed::IsPedDoingDriveByShooting(void)
+{
+ if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
+ if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
+ return true;
+ }
+ return false;
+}
+
+bool
CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
{
return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects);
diff --git a/src/weapons/WeaponEffects.cpp b/src/weapons/WeaponEffects.cpp
index 46195d2c..214ae9c7 100644
--- a/src/weapons/WeaponEffects.cpp
+++ b/src/weapons/WeaponEffects.cpp
@@ -46,7 +46,7 @@ void
CWeaponEffects::Shutdown(void)
{
RwTextureDestroy(gpCrossHairTex);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
gpCrossHairTex = nil;
#endif
}