1
0
Fork 0
mirror of https://git.rip/DMCA_FUCKER/re3.git synced 2024-06-29 10:17:06 +00:00

sync with upstream

This commit is contained in:
Nikolay Korolev 2021-01-07 18:38:40 +03:00
commit 5e10f1fe6a
67 changed files with 2439 additions and 613 deletions

View file

@ -125,11 +125,9 @@ workspace "reVC"
filter { "platforms:*x86*" }
architecture "x86"
floatingpoint "Fast"
filter { "platforms:*amd64*" }
architecture "amd64"
floatingpoint "Fast"
filter { "platforms:*arm*" }
architecture "ARM"
@ -192,11 +190,9 @@ project "librw"
filter { "platforms:*x86*" }
architecture "x86"
floatingpoint "Fast"
filter { "platforms:*amd64*" }
architecture "amd64"
floatingpoint "Fast"
filter "platforms:win*"
staticruntime "on"

View file

@ -4201,109 +4201,109 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
switch (sound) {
case SOUND_STEP_START:
case SOUND_STEP_END:
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) {
case SURFACE_GRASS:
sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1;
break;
case SURFACE_GRAVEL:
case SURFACE_MUD_DRY:
sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1;
break;
case SURFACE_CAR:
case SURFACE_GARAGE_DOOR:
case SURFACE_CAR_PANEL:
case SURFACE_THICK_METAL_PLATE:
case SURFACE_SCAFFOLD_POLE:
case SURFACE_LAMP_POST:
case SURFACE_FIRE_HYDRANT:
case SURFACE_GIRDER:
case SURFACE_METAL_CHAIN_FENCE:
case SURFACE_CONTAINER:
case SURFACE_NEWS_VENDOR:
sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1;
break;
case SURFACE_SAND:
sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1;
break;
case SURFACE_WATER:
sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
break;
case SURFACE_WOOD_CRATES:
case SURFACE_WOOD_BENCH:
case SURFACE_WOOD_SOLID:
sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1;
break;
case SURFACE_HEDGE:
sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1;
break;
default:
sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1;
break;
}
m_sQueueSample.m_nSampleIndex = sampleIndex;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - 32;
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) {
case PEDMOVE_WALK:
emittingVol /= 4;
m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10;
break;
case PEDMOVE_RUN:
emittingVol /= 2;
m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10;
break;
case PEDMOVE_SPRINT:
m_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10;
break;
default:
break;
}
m_sQueueSample.m_nReleasingVolumeModificator = 5;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
m_sQueueSample.m_fSoundIntensity = 20.0f;
m_sQueueSample.m_nLoopCount = 1;
m_sQueueSample.m_nLoopStart = 0;
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;
if (params.m_pPed->bIsInTheAir)
continue;
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) {
case SURFACE_GRASS:
sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1;
break;
case SURFACE_GRAVEL:
case SURFACE_MUD_DRY:
sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1;
break;
case SURFACE_CAR:
case SURFACE_GARAGE_DOOR:
case SURFACE_CAR_PANEL:
case SURFACE_THICK_METAL_PLATE:
case SURFACE_SCAFFOLD_POLE:
case SURFACE_LAMP_POST:
case SURFACE_FIRE_HYDRANT:
case SURFACE_GIRDER:
case SURFACE_METAL_CHAIN_FENCE:
case SURFACE_CONTAINER:
case SURFACE_NEWS_VENDOR:
sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1;
break;
case SURFACE_SAND:
sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1;
break;
case SURFACE_WATER:
sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
break;
case SURFACE_WOOD_CRATES:
case SURFACE_WOOD_BENCH:
case SURFACE_WOOD_SOLID:
sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1;
break;
case SURFACE_HEDGE:
sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1;
break;
default:
sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1;
break;
}
m_sQueueSample.m_nSampleIndex = sampleIndex;
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - SOUND_STEP_START + 1;
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) {
case PEDMOVE_WALK:
emittingVol /= 4;
m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10;
break;
case PEDMOVE_RUN:
emittingVol /= 2;
m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10;
break;
case PEDMOVE_SPRINT:
m_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10;
break;
default:
break;
}
m_sQueueSample.m_nReleasingVolumeModificator = 5;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
m_sQueueSample.m_fSoundIntensity = 20.0f;
m_sQueueSample.m_nLoopCount = 1;
m_sQueueSample.m_nLoopStart = 0;
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;
case SOUND_FALL_LAND:
case SOUND_FALL_COLLAPSE:
if (!ped->bIsLooking) {
maxDist = SQR(30);
emittingVol = m_anRandomTable[3] % 20 + 80;
if (ped->m_nSurfaceTouched == SURFACE_WATER) {
m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
} else if (sound == SOUND_FALL_LAND) {
m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND;
} else {
m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL;
}
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = 1;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
m_sQueueSample.m_nReleasingVolumeModificator = 2;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
m_sQueueSample.m_fSoundIntensity = 30.0f;
m_sQueueSample.m_nLoopCount = 1;
m_sQueueSample.m_nLoopStart = 0;
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;
if (ped->bIsInTheAir)
continue;
maxDist = SQR(30);
emittingVol = m_anRandomTable[3] % 20 + 80;
if (ped->m_nSurfaceTouched == SURFACE_WATER) {
m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
} else if (sound == SOUND_FALL_LAND) {
m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND;
} else {
m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL;
}
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_nCounter = 1;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
m_sQueueSample.m_nReleasingVolumeModificator = 2;
m_sQueueSample.m_fSpeedMultiplier = 0.0f;
m_sQueueSample.m_fSoundIntensity = 30.0f;
m_sQueueSample.m_nLoopCount = 1;
m_sQueueSample.m_nLoopStart = 0;
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;
case SOUND_FIGHT_37:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;
@ -4342,6 +4342,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nFrequency = 20000;
goto AddFightSound;
case SOUND_FIGHT_46:
case SOUND_187:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;
m_sQueueSample.m_nFrequency = 18000;
goto AddFightSound;
@ -4354,7 +4355,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nFrequency = 20000;
AddFightSound:
{
uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? stroring int as float
uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? storing int as float
uint8 damagerType = soundParams & 0xFF;
uint32 weaponType = soundParams >> 8;
@ -4402,7 +4403,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
case SOUND_WEAPON_BAT_ATTACK:
case SOUND_WEAPON_KNIFE_ATTACK:
{
uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? stroring int as float
uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? storing int as float
uint8 damagerType = soundParams & 0xFF;
uint32 weaponType = soundParams >> 8;
if (damagerType == ENTITY_TYPE_PED) {
@ -4461,7 +4462,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
continue;
m_sQueueSample.m_nSampleIndex = SFX_CAR_ACCEL_13;
m_sQueueSample.m_nBankIndex = SFX_BANK_0; // SFX_BANK_CAR_CHAINSAW
m_sQueueSample.m_nCounter = 64;
m_sQueueSample.m_nCounter = 70;
m_sQueueSample.m_nFrequency = 27000;
m_sQueueSample.m_nReleasingVolumeModificator = 3;
m_sQueueSample.m_fSpeedMultiplier = 3.0f;
@ -4473,7 +4474,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_CAR_ACCEL_13);
m_sQueueSample.m_nEmittingVolume = 100;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_bReverbFlag = false;
m_sQueueSample.m_bReleasingSoundFlag = false;
m_sQueueSample.m_nReleasingVolumeDivider = 5;
break;
case SOUND_WEAPON_CHAINSAW_IDLE:
@ -5159,7 +5160,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nReleasingVolumeDivider = 3;
}
}
break;
continue;
default:
SetupPedComments(params, sound);
continue;
@ -9922,7 +9923,7 @@ cAudioManager::ProcessMissionAudioSlot(uint8 slot)
nCheckPlayingDelay[slot] = 0;
nFramesUntilFailedLoad[slot] = 0;
} else if (!m_nUserPause) {
if (++nFramesForPretendPlaying[slot] < 120) {
if (++nFramesForPretendPlaying[slot] < 90) {
m_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_PLAYING;
} else {
m_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_FINISHED;
@ -9938,7 +9939,7 @@ cAudioManager::ProcessMissionAudioSlot(uint8 slot)
} else {
if (m_nUserPause)
SampleManager.PauseStream(1, slot + 1);
if (m_sMissionAudio.m_bPredefinedProperties) {
if (m_sMissionAudio.m_bPredefinedProperties[slot]) {
if (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_CAMERAL)
SampleManager.SetStreamedVolumeAndPan(80, 0, 1, slot + 1);
else if (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_CAMERAR)
@ -9992,7 +9993,7 @@ cAudioManager::ProcessMissionAudioSlot(uint8 slot)
else
{
SampleManager.PauseStream(0, slot + 1);
if (!m_sMissionAudio.m_bPredefinedProperties) {
if (!m_sMissionAudio.m_bPredefinedProperties[slot]) {
distSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos[slot]);
if (distSquared >= SQR(80.0f)) {
emittingVol = 0;

View file

@ -10,6 +10,7 @@
#include "sampman.h"
#include "Camera.h"
#include "World.h"
#include "ZoneCull.h"
cAudioManager AudioManager;
@ -17,12 +18,16 @@ const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples);
const int policeChannel = channels + 1;
const int allChannels = channels + 2;
#define SPEED_OF_SOUND 343.f
#define TIME_SPENT 40
cAudioManager::cAudioManager()
{
m_bIsInitialised = false;
m_bReverb = true;
m_fSpeedOfSound = 6.86f;
m_nTimeSpent = 50;
field_6 = 0;
m_fSpeedOfSound = SPEED_OF_SOUND / TIME_SPENT;
m_nTimeSpent = TIME_SPENT;
m_nActiveSamples = NUM_SOUNDS_SAMPLES_SLOTS;
m_nActiveSampleQueue = 1;
ClearRequestedQueue();
@ -585,7 +590,7 @@ cAudioManager::AddSampleToRequestedQueue()
}
m_sQueueSample.m_nCalculatedVolume = calculatedVolume;
m_sQueueSample.m_bLoopEnded = false;
if (m_sQueueSample.m_bIs2D) {
if (m_sQueueSample.m_bIs2D || CCullZones::InRoomForAudio()) {
m_sQueueSample.m_bRequireReflection = false;
m_sQueueSample.m_nLoopsRemaining = 0;
}
@ -597,6 +602,9 @@ cAudioManager::AddSampleToRequestedQueue()
}
m_sQueueSample.m_bRequireReflection = false;
if ( m_bReverb && m_sQueueSample.m_bIs2D )
m_sQueueSample.field_4C = 30;
if (!m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bReverbFlag = false;
@ -643,9 +651,9 @@ cAudioManager::AddReflectionsToRequestedQueue()
emittingVolume = m_sQueueSample.m_nVolume;
oldFreq = m_sQueueSample.m_nFrequency;
} else {
emittingVolume = (m_sQueueSample.m_nVolume / 2) + (m_sQueueSample.m_nVolume / 16);
emittingVolume = (9 * m_sQueueSample.m_nVolume) / 16;
}
m_sQueueSample.m_fSoundIntensity = m_sQueueSample.m_fSoundIntensity / 2.f;
m_sQueueSample.m_fSoundIntensity /= 2.f;
int halfOldFreq = oldFreq >> 1;

View file

@ -25,7 +25,7 @@ cMusicManager MusicManager;
int32 gNumRetunePresses;
int32 gRetuneCounter;
bool g_bAnnouncementReadPosAlready;
uint8 RadioStaticCounter;
uint8 RadioStaticCounter = 5;
uint32 RadioStaticTimer;
CVector vecRiotPosition(300.7f, -322.0f, 12.0f);
@ -435,7 +435,7 @@ cMusicManager::ServiceFrontEndMode()
else {
if (m_nCurrentVolume < m_nMaxVolume)
m_nCurrentVolume = Min(m_nMaxVolume, m_nCurrentVolume + 6);
SampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63u, 0, 0);
SampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);
}
} else {
if (m_nPlayingTrack == STREAMED_SOUND_RADIO_MP3_PLAYER)
@ -991,6 +991,7 @@ cMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)
}
} else if (AudioManager.ShouldDuckMissionAudio(0) || AudioManager.ShouldDuckMissionAudio(1)) {
SampleManager.SetStreamedVolumeAndPan(Min(m_nCurrentVolume, 25), 63, 0, 0);
nFramesSinceCutsceneEnded = 0;
} else {
if (nFramesSinceCutsceneEnded == -1)
volume = m_nCurrentVolume;

View file

@ -8,10 +8,14 @@
#include <opusfile.h>
#else
#ifdef _WIN32
#ifdef AUDIO_OAL_USE_SNDFILE
#pragma comment( lib, "libsndfile-1.lib" )
#endif
#pragma comment( lib, "libmpg123-0.lib" )
#endif
#ifdef AUDIO_OAL_USE_SNDFILE
#include <sndfile.h>
#endif
#include <mpg123.h>
#endif
@ -19,7 +23,374 @@
#include "crossplatform.h"
#endif
/*
As we ran onto an issue of having different volume levels for mono streams
and stereo streams we are now handling all the stereo panning ourselves.
Each stream now has two sources - one panned to the left and one to the right,
and uses two separate buffers to store data for each individual channel.
For that we also have to reshuffle all decoded PCM stereo data from LRLRLRLR to
LLLLRRRR (handled by CSortStereoBuffer).
*/
class CSortStereoBuffer
{
uint16* PcmBuf;
size_t BufSize;
public:
CSortStereoBuffer() : PcmBuf(nil), BufSize(0) {}
~CSortStereoBuffer()
{
if (PcmBuf)
free(PcmBuf);
}
uint16* GetBuffer(size_t size)
{
if (size == 0) return nil;
if (!PcmBuf)
{
BufSize = size;
PcmBuf = (uint16*)malloc(BufSize);
}
else if (BufSize < size)
{
BufSize = size;
PcmBuf = (uint16*)realloc(PcmBuf, size);
}
return PcmBuf;
}
void SortStereo(void* buf, size_t size)
{
uint16* InBuf = (uint16*)buf;
uint16* OutBuf = GetBuffer(size);
if (!OutBuf) return;
size_t rightStart = size / 4;
for (size_t i = 0; i < size / 4; i++)
{
OutBuf[i] = InBuf[i*2];
OutBuf[i+rightStart] = InBuf[i*2+1];
}
memcpy(InBuf, OutBuf, size);
}
};
CSortStereoBuffer SortStereoBuffer;
#ifndef AUDIO_OPUS
class CImaADPCMDecoder
{
const uint16 StepTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411,
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
};
int16 Sample, StepIndex;
public:
CImaADPCMDecoder()
{
Init(0, 0);
}
void Init(int16 _Sample, int16 _StepIndex)
{
Sample = _Sample;
StepIndex = _StepIndex;
}
void Decode(uint8 *inbuf, int16 *_outbuf, size_t size)
{
int16* outbuf = _outbuf;
for (size_t i = 0; i < size; i++)
{
*(outbuf++) = DecodeSample(inbuf[i] & 0xF);
*(outbuf++) = DecodeSample(inbuf[i] >> 4);
}
}
int16 DecodeSample(uint8 adpcm)
{
uint16 step = StepTable[StepIndex];
if (adpcm & 4)
StepIndex += ((adpcm & 3) + 1) * 2;
else
StepIndex--;
StepIndex = clamp(StepIndex, 0, 88);
int delta = step >> 3;
if (adpcm & 1) delta += step >> 2;
if (adpcm & 2) delta += step >> 1;
if (adpcm & 4) delta += step;
if (adpcm & 8) delta = -delta;
int newSample = Sample + delta;
Sample = clamp(newSample, -32768, 32767);
return Sample;
}
};
class CWavFile : public IDecoder
{
enum
{
WAVEFMT_PCM = 1,
WAVEFMT_IMA_ADPCM = 0x11,
WAVEFMT_XBOX_ADPCM = 0x69,
};
struct tDataHeader
{
uint32 ID;
uint32 Size;
};
struct tFormatHeader
{
uint16 AudioFormat;
uint16 NumChannels;
uint32 SampleRate;
uint32 ByteRate;
uint16 BlockAlign;
uint16 BitsPerSample;
uint16 extra[2]; // adpcm only
tFormatHeader() { memset(this, 0, sizeof(*this)); }
};
FILE *m_pFile;
bool m_bIsOpen;
tFormatHeader m_FormatHeader;
uint32 m_DataStartOffset; // TODO: 64 bit?
uint32 m_nSampleCount;
uint32 m_nSamplesPerBlock;
// ADPCM things
uint8 *m_pAdpcmBuffer;
int16 **m_ppPcmBuffers;
CImaADPCMDecoder *m_pAdpcmDecoders;
void Close()
{
if (m_pFile) {
fclose(m_pFile);
m_pFile = nil;
}
delete[] m_pAdpcmBuffer;
delete[] m_ppPcmBuffers;
delete[] m_pAdpcmDecoders;
}
uint32 GetCurrentSample() const
{
// TODO: 64 bit?
uint32 FilePos = ftell(m_pFile);
if (FilePos <= m_DataStartOffset)
return 0;
return (FilePos - m_DataStartOffset) / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;
}
public:
CWavFile(const char* path) : m_bIsOpen(false), m_DataStartOffset(0), m_nSampleCount(0), m_nSamplesPerBlock(0), m_pAdpcmBuffer(nil), m_ppPcmBuffers(nil), m_pAdpcmDecoders(nil)
{
m_pFile = fopen(path, "rb");
if (!m_pFile) return;
#define CLOSE_ON_ERROR(op)\
if (op) { \
Close(); \
return; \
}
tDataHeader DataHeader;
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
CLOSE_ON_ERROR(DataHeader.ID != 'FFIR');
// TODO? validate filesizes
int WAVE;
CLOSE_ON_ERROR(fread(&WAVE, 4, 1, m_pFile) == 0);
CLOSE_ON_ERROR(WAVE != 'EVAW')
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
CLOSE_ON_ERROR(DataHeader.ID != ' tmf');
CLOSE_ON_ERROR(fread(&m_FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, m_pFile) == 0);
CLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader));
switch (m_FormatHeader.AudioFormat)
{
case WAVEFMT_XBOX_ADPCM:
m_FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM;
case WAVEFMT_IMA_ADPCM:
m_nSamplesPerBlock = (m_FormatHeader.BlockAlign / m_FormatHeader.NumChannels - 4) * 2 + 1;
m_pAdpcmBuffer = new uint8[m_FormatHeader.BlockAlign];
m_ppPcmBuffers = new int16*[m_FormatHeader.NumChannels];
m_pAdpcmDecoders = new CImaADPCMDecoder[m_FormatHeader.NumChannels];
break;
case WAVEFMT_PCM:
m_nSamplesPerBlock = 1;
if (m_FormatHeader.BitsPerSample != 16)
{
debug("Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\n", m_FormatHeader.BitsPerSample, path);
Close();
return;
}
break;
default:
debug("Unsupported wav format 0x%x (%s)\n", m_FormatHeader.AudioFormat, path);
Close();
return;
}
while (true) {
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
if (DataHeader.ID == 'atad')
break;
fseek(m_pFile, DataHeader.Size, SEEK_CUR);
// TODO? validate data size
// maybe check if there no extreme custom headers that might break this
}
m_DataStartOffset = ftell(m_pFile);
m_nSampleCount = DataHeader.Size / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;
m_bIsOpen = true;
#undef CLOSE_ON_ERROR
}
~CWavFile()
{
Close();
}
bool IsOpened()
{
return m_bIsOpen;
}
uint32 GetSampleSize()
{
return sizeof(uint16);
}
uint32 GetSampleCount()
{
return m_nSampleCount;
}
uint32 GetSampleRate()
{
return m_FormatHeader.SampleRate;
}
uint32 GetChannels()
{
return m_FormatHeader.NumChannels;
}
void Seek(uint32 milliseconds)
{
if (!IsOpened()) return;
fseek(m_pFile, m_DataStartOffset + ms2samples(milliseconds) / m_nSamplesPerBlock * m_FormatHeader.BlockAlign, SEEK_SET);
}
uint32 Tell()
{
if (!IsOpened()) return 0;
return samples2ms(GetCurrentSample());
}
#define SAMPLES_IN_LINE (8)
uint32 Decode(void* buffer)
{
if (!IsOpened()) return 0;
if (m_FormatHeader.AudioFormat == WAVEFMT_PCM)
{
// just read the file and sort the samples
uint32 size = fread(buffer, 1, GetBufferSize(), m_pFile);
if (m_FormatHeader.NumChannels == 2)
SortStereoBuffer.SortStereo(buffer, size);
return size;
}
else if (m_FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM)
{
// trim the buffer size if we're at the end of our file
uint32 nMaxSamples = GetBufferSamples() / m_FormatHeader.NumChannels;
uint32 nSamplesLeft = m_nSampleCount - GetCurrentSample();
nMaxSamples = Min(nMaxSamples, nSamplesLeft);
// align sample count to our block
nMaxSamples = nMaxSamples / m_nSamplesPerBlock * m_nSamplesPerBlock;
// count the size of output buffer
uint32 OutBufSizePerChannel = nMaxSamples * GetSampleSize();
uint32 OutBufSize = OutBufSizePerChannel * m_FormatHeader.NumChannels;
// calculate the pointers to individual channel buffers
for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
m_ppPcmBuffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i);
uint32 samplesRead = 0;
while (samplesRead < nMaxSamples)
{
// read the file
uint8 *pAdpcmBuf = m_pAdpcmBuffer;
if (fread(m_pAdpcmBuffer, 1, m_FormatHeader.BlockAlign, m_pFile) == 0)
return 0;
// get the first sample in adpcm block and initialise the decoder(s)
for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
{
int16 Sample = *(int16*)pAdpcmBuf;
pAdpcmBuf += sizeof(int16);
int16 Step = *(int16*)pAdpcmBuf;
pAdpcmBuf += sizeof(int16);
m_pAdpcmDecoders[i].Init(Sample, Step);
*(m_ppPcmBuffers[i]) = Sample;
m_ppPcmBuffers[i]++;
}
samplesRead++;
// decode the rest of the block
for (uint32 s = 1; s < m_nSamplesPerBlock; s += SAMPLES_IN_LINE)
{
for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
{
m_pAdpcmDecoders[i].Decode(pAdpcmBuf, m_ppPcmBuffers[i], SAMPLES_IN_LINE / 2);
pAdpcmBuf += SAMPLES_IN_LINE / 2;
m_ppPcmBuffers[i] += SAMPLES_IN_LINE;
}
samplesRead += SAMPLES_IN_LINE;
}
}
return OutBufSize;
}
return 0;
}
};
#ifdef AUDIO_OAL_USE_SNDFILE
class CSndFile : public IDecoder
{
SNDFILE *m_pfSound;
@ -81,9 +452,20 @@ public:
uint32 Decode(void *buffer)
{
if ( !IsOpened() ) return 0;
return sf_read_short(m_pfSound, (short *)buffer, GetBufferSamples()) * GetSampleSize();
size_t size = sf_read_short(m_pfSound, (short*)buffer, GetBufferSamples()) * GetSampleSize();
if (GetChannels()==2)
SortStereoBuffer.SortStereo(buffer, size);
return size;
}
};
#endif
#ifdef _WIN32
// fuzzy seek eliminates stutter when playing ADF but spams errors a lot (nothing breaks though)
#define MP3_USE_FUZZY_SEEK
#endif // _WIN32
class CMP3File : public IDecoder
{
@ -108,6 +490,9 @@ public:
m_pMH = mpg123_new(nil, nil);
if ( m_pMH )
{
#ifdef MP3_USE_FUZZY_SEEK
mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
#endif
long rate = 0;
int channels = 0;
int encoding = 0;
@ -183,9 +568,249 @@ public:
assert("We can't handle audio files more then 2 GB yet :shrug:" && (size < UINT32_MAX));
#endif
if (err != MPG123_OK && err != MPG123_DONE) return 0;
if (GetChannels() == 2)
SortStereoBuffer.SortStereo(buffer, size);
return (uint32)size;
}
};
#define VAG_LINE_SIZE (0x10)
#define VAG_SAMPLES_IN_LINE (28)
class CVagDecoder
{
const double f[5][2] = { { 0.0, 0.0 },
{ 60.0 / 64.0, 0.0 },
{ 115.0 / 64.0, -52.0 / 64.0 },
{ 98.0 / 64.0, -55.0 / 64.0 },
{ 122.0 / 64.0, -60.0 / 64.0 } };
double s_1;
double s_2;
public:
CVagDecoder()
{
ResetState();
}
void ResetState()
{
s_1 = s_2 = 0.0;
}
static short quantize(double sample)
{
int a = int(sample + 0.5);
return short(clamp(a, -32768, 32767));
}
void Decode(void* _inbuf, int16* _outbuf, size_t size)
{
uint8* inbuf = (uint8*)_inbuf;
int16* outbuf = _outbuf;
size &= ~(VAG_LINE_SIZE - 1);
while (size > 0) {
double samples[VAG_SAMPLES_IN_LINE];
int predict_nr, shift_factor, flags;
predict_nr = *(inbuf++);
shift_factor = predict_nr & 0xf;
predict_nr >>= 4;
flags = *(inbuf++);
if (flags == 7) // TODO: ignore?
break;
for (int i = 0; i < VAG_SAMPLES_IN_LINE; i += 2) {
int d = *(inbuf++);
int16 s = int16((d & 0xf) << 12);
samples[i] = (double)(s >> shift_factor);
s = int16((d & 0xf0) << 8);
samples[i + 1] = (double)(s >> shift_factor);
}
for (int i = 0; i < VAG_SAMPLES_IN_LINE; i++) {
samples[i] = samples[i] + s_1 * f[predict_nr][0] + s_2 * f[predict_nr][1];
s_2 = s_1;
s_1 = samples[i];
*(outbuf++) = quantize(samples[i] + 0.5);
}
size -= VAG_LINE_SIZE;
}
}
};
#define VB_BLOCK_SIZE (0x2000)
#define NUM_VAG_LINES_IN_BLOCK (VB_BLOCK_SIZE / VAG_LINE_SIZE)
#define NUM_VAG_SAMPLES_IN_BLOCK (NUM_VAG_LINES_IN_BLOCK * VAG_SAMPLES_IN_LINE)
class CVbFile : public IDecoder
{
FILE *m_pFile;
CVagDecoder *m_pVagDecoders;
size_t m_FileSize;
size_t m_nNumberOfBlocks;
uint32 m_nSampleRate;
uint8 m_nChannels;
bool m_bBlockRead;
uint16 m_LineInBlock;
size_t m_CurrentBlock;
uint8 **m_ppVagBuffers; // buffers that cache actual ADPCM file data
int16 **m_ppPcmBuffers;
void ReadBlock(int32 block = -1)
{
// just read next block if -1
if (block != -1)
fseek(m_pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET);
for (int i = 0; i < m_nChannels; i++)
fread(m_ppVagBuffers[i], VB_BLOCK_SIZE, 1, m_pFile);
m_bBlockRead = true;
}
public:
CVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels), m_pVagDecoders(nil), m_ppVagBuffers(nil), m_ppPcmBuffers(nil),
m_FileSize(0), m_nNumberOfBlocks(0), m_bBlockRead(false), m_LineInBlock(0), m_CurrentBlock(0)
{
m_pFile = fopen(path, "rb");
if (!m_pFile) return;
fseek(m_pFile, 0, SEEK_END);
m_FileSize = ftell(m_pFile);
fseek(m_pFile, 0, SEEK_SET);
m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE);
m_pVagDecoders = new CVagDecoder[nChannels];
m_ppVagBuffers = new uint8*[nChannels];
m_ppPcmBuffers = new int16*[nChannels];
for (uint8 i = 0; i < nChannels; i++)
m_ppVagBuffers[i] = new uint8[VB_BLOCK_SIZE];
}
~CVbFile()
{
if (m_pFile)
{
fclose(m_pFile);
delete[] m_pVagDecoders;
for (int i = 0; i < m_nChannels; i++)
delete[] m_ppVagBuffers[i];
delete[] m_ppVagBuffers;
delete[] m_ppPcmBuffers;
}
}
bool IsOpened()
{
return m_pFile != nil;
}
uint32 GetSampleSize()
{
return sizeof(uint16);
}
uint32 GetSampleCount()
{
if (!IsOpened()) return 0;
return m_nNumberOfBlocks * NUM_VAG_LINES_IN_BLOCK * VAG_SAMPLES_IN_LINE;
}
uint32 GetSampleRate()
{
return m_nSampleRate;
}
uint32 GetChannels()
{
return m_nChannels;
}
void Seek(uint32 milliseconds)
{
if (!IsOpened()) return;
uint32 samples = ms2samples(milliseconds);
// find the block of our sample
uint32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK;
if (block > m_nNumberOfBlocks)
{
samples = 0;
block = 0;
}
if (block != m_CurrentBlock)
m_bBlockRead = false;
// find a line of our sample within our block
uint32 remainingSamples = samples - block * NUM_VAG_SAMPLES_IN_BLOCK;
uint32 newLine = remainingSamples / VAG_SAMPLES_IN_LINE / VAG_LINE_SIZE;
if (m_CurrentBlock != block || m_LineInBlock != newLine)
{
m_CurrentBlock = block;
m_LineInBlock = newLine;
for (uint32 i = 0; i < GetChannels(); i++)
m_pVagDecoders[i].ResetState();
}
}
uint32 Tell()
{
if (!IsOpened()) return 0;
uint32 pos = (m_CurrentBlock * NUM_VAG_LINES_IN_BLOCK + m_LineInBlock) * VAG_SAMPLES_IN_LINE;
return samples2ms(pos);
}
uint32 Decode(void* buffer)
{
if (!IsOpened()) return 0;
if (m_CurrentBlock >= m_nNumberOfBlocks) return 0;
// cache current ADPCM block
if (!m_bBlockRead)
ReadBlock(m_CurrentBlock);
// trim the buffer size if we're at the end of our file
int numberOfRequiredLines = GetBufferSamples() / m_nChannels / VAG_SAMPLES_IN_LINE;
int numberOfRemainingLines = (m_nNumberOfBlocks - m_CurrentBlock) * NUM_VAG_LINES_IN_BLOCK - m_LineInBlock;
int bufSizePerChannel = Min(numberOfRequiredLines, numberOfRemainingLines) * VAG_SAMPLES_IN_LINE * GetSampleSize();
// calculate the pointers to individual channel buffers
for (uint32 i = 0; i < m_nChannels; i++)
m_ppPcmBuffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * i);
int size = 0;
while (size < bufSizePerChannel)
{
// decode the VAG lines
for (uint32 i = 0; i < m_nChannels; i++)
{
m_pVagDecoders[i].Decode(m_ppVagBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, m_ppPcmBuffers[i], VAG_LINE_SIZE);
m_ppPcmBuffers[i] += VAG_SAMPLES_IN_LINE;
}
size += VAG_SAMPLES_IN_LINE * GetSampleSize();
m_LineInBlock++;
// block is over, read the next block
if (m_LineInBlock >= NUM_VAG_LINES_IN_BLOCK)
{
m_CurrentBlock++;
if (m_CurrentBlock >= m_nNumberOfBlocks) // end of file
break;
m_LineInBlock = 0;
ReadBlock();
}
}
return bufSizePerChannel * m_nChannels;
}
};
#else
class COpusFile : public IDecoder
{
@ -274,6 +899,9 @@ public:
if (size < 0)
return 0;
if (GetChannels() == 2)
SortStereoBuffer.SortStereo(buffer, size * m_nChannels * GetSampleSize());
return size * m_nChannels * GetSampleSize();
}
};
@ -285,7 +913,7 @@ class CADFFile : public CMP3File
{
size_t bytesRead = fread(buf, 1, size, (FILE*)fh);
uint8* _buf = (uint8*)buf;
for (int i = 0; i < size; i++)
for (size_t i = 0; i < size; i++)
_buf[i] ^= 0x22;
return bytesRead;
}
@ -304,6 +932,9 @@ public:
m_pMH = mpg123_new(nil, nil);
if (m_pMH)
{
#ifdef MP3_USE_FUZZY_SEEK
mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
#endif
long rate = 0;
int channels = 0;
int encoding = 0;
@ -338,8 +969,8 @@ void CStream::Terminate()
#endif
}
CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]) :
m_alSource(source),
CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate) :
m_pAlSources(sources),
m_alBuffers(buffers),
m_pBuffer(nil),
m_bPaused(false),
@ -370,9 +1001,15 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF
if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".mp3")], ".mp3"))
m_pSoundFile = new CMP3File(m_aFilename);
else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".wav")], ".wav"))
#ifdef AUDIO_OAL_USE_SNDFILE
m_pSoundFile = new CSndFile(m_aFilename);
#else
m_pSoundFile = new CWavFile(m_aFilename);
#endif
else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".adf")], ".adf"))
m_pSoundFile = new CADFFile(m_aFilename);
else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".vb")], ".VB"))
m_pSoundFile = new CVbFile(m_aFilename, overrideSampleRate);
#else
if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".opus")], ".opus"))
m_pSoundFile = new COpusFile(m_aFilename);
@ -422,7 +1059,7 @@ void CStream::Delete()
bool CStream::HasSource()
{
return m_alSource != AL_NONE;
return (m_pAlSources[0] != AL_NONE) && (m_pAlSources[1] != AL_NONE);
}
bool CStream::IsOpened()
@ -436,9 +1073,10 @@ bool CStream::IsPlaying()
if ( !m_bPaused )
{
ALint sourceState;
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
if ( m_bActive || sourceState == AL_PLAYING )
ALint sourceState[2];
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
if ( m_bActive || sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING)
return true;
}
@ -449,9 +1087,12 @@ void CStream::Pause()
{
if ( !HasSource() ) return;
ALint sourceState = AL_PAUSED;
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_PAUSED )
alSourcePause(m_alSource);
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_PAUSED)
alSourcePause(m_pAlSources[0]);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_PAUSED)
alSourcePause(m_pAlSources[1]);
}
void CStream::SetPause(bool bPause)
@ -473,19 +1114,21 @@ void CStream::SetPause(bool bPause)
void CStream::SetPitch(float pitch)
{
if ( !HasSource() ) return;
alSourcef(m_alSource, AL_PITCH, pitch);
alSourcef(m_pAlSources[0], AL_PITCH, pitch);
alSourcef(m_pAlSources[1], AL_PITCH, pitch);
}
void CStream::SetGain(float gain)
{
if ( !HasSource() ) return;
alSourcef(m_alSource, AL_GAIN, gain);
alSourcef(m_pAlSources[0], AL_GAIN, gain);
alSourcef(m_pAlSources[1], AL_GAIN, gain);
}
void CStream::SetPosition(float x, float y, float z)
void CStream::SetPosition(int i, float x, float y, float z)
{
if ( !HasSource() ) return;
alSource3f(m_alSource, AL_POSITION, x, y, z);
alSource3f(m_pAlSources[i], AL_POSITION, x, y, z);
}
void CStream::SetVolume(uint32 nVol)
@ -496,8 +1139,13 @@ void CStream::SetVolume(uint32 nVol)
void CStream::SetPan(uint8 nPan)
{
m_nPan = clamp((int8)nPan - 63, 0, 63);
SetPosition(0, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));
m_nPan = clamp((int8)nPan + 64, 64, 127);
SetPosition(1, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));
m_nPan = nPan;
SetPosition((nPan - 63)/64.0f, 0.0f, Sqrt(1.0f-SQR((nPan-63)/64.0f)));
}
void CStream::SetPosMS(uint32 nPos)
@ -514,10 +1162,10 @@ uint32 CStream::GetPosMS()
ALint offset;
//alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset);
alGetSourcei(m_alSource, AL_BYTE_OFFSET, &offset);
alGetSourcei(m_pAlSources[0], AL_BYTE_OFFSET, &offset);
return m_pSoundFile->Tell()
- m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1)) / m_pSoundFile->GetChannels()
- m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS/2-1)) / m_pSoundFile->GetChannels()
+ m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()) / m_pSoundFile->GetChannels();
}
@ -527,33 +1175,41 @@ uint32 CStream::GetLengthMS()
return m_pSoundFile->GetLength();
}
bool CStream::FillBuffer(ALuint alBuffer)
bool CStream::FillBuffer(ALuint *alBuffer)
{
if ( !HasSource() )
return false;
if ( !IsOpened() )
return false;
if ( !(alBuffer != AL_NONE && alIsBuffer(alBuffer)) )
if ( !(alBuffer[0] != AL_NONE && alIsBuffer(alBuffer[0])) )
return false;
if ( !(alBuffer[1] != AL_NONE && alIsBuffer(alBuffer[1])) )
return false;
uint32 size = m_pSoundFile->Decode(m_pBuffer);
if( size == 0 )
return false;
alBufferData(alBuffer, m_pSoundFile->GetChannels() == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
m_pBuffer, size, m_pSoundFile->GetSampleRate());
uint32 channelSize = size / m_pSoundFile->GetChannels();
alBufferData(alBuffer[0], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());
// TODO: use just one buffer if we play mono
if (m_pSoundFile->GetChannels() == 1)
alBufferData(alBuffer[1], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());
else
alBufferData(alBuffer[1], AL_FORMAT_MONO16, (uint8*)m_pBuffer + channelSize, channelSize, m_pSoundFile->GetSampleRate());
return true;
}
int32 CStream::FillBuffers()
{
int32 i = 0;
for ( i = 0; i < NUM_STREAMBUFFERS; i++ )
for ( i = 0; i < NUM_STREAMBUFFERS/2; i++ )
{
if ( !FillBuffer(m_alBuffers[i]) )
if ( !FillBuffer(&m_alBuffers[i*2]) )
break;
alSourceQueueBuffers(m_alSource, 1, &m_alBuffers[i]);
alSourceQueueBuffers(m_pAlSources[0], 1, &m_alBuffers[i*2]);
alSourceQueueBuffers(m_pAlSources[1], 1, &m_alBuffers[i*2+1]);
}
return i;
@ -563,12 +1219,15 @@ void CStream::ClearBuffers()
{
if ( !HasSource() ) return;
ALint buffersQueued;
alGetSourcei(m_alSource, AL_BUFFERS_QUEUED, &buffersQueued);
ALint buffersQueued[2];
alGetSourcei(m_pAlSources[0], AL_BUFFERS_QUEUED, &buffersQueued[0]);
alGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &buffersQueued[1]);
ALuint value;
while (buffersQueued--)
alSourceUnqueueBuffers(m_alSource, 1, &value);
while (buffersQueued[0]--)
alSourceUnqueueBuffers(m_pAlSources[0], 1, &value);
while (buffersQueued[1]--)
alSourceUnqueueBuffers(m_pAlSources[1], 1, &value);
}
bool CStream::Setup()
@ -576,7 +1235,6 @@ bool CStream::Setup()
if ( IsOpened() )
{
m_pSoundFile->Seek(0);
alSourcei(m_alSource, AL_SOURCE_RELATIVE, AL_TRUE);
//SetPosition(0.0f, 0.0f, 0.0f);
SetPitch(1.0f);
//SetPan(m_nPan);
@ -592,17 +1250,29 @@ void CStream::SetPlay(bool state)
if ( state )
{
ALint sourceState = AL_PLAYING;
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_PLAYING )
alSourcePlay(m_alSource);
alSourcePlay(m_pAlSources[0]);
sourceState = AL_PLAYING;
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_PLAYING)
alSourcePlay(m_pAlSources[1]);
m_bActive = true;
}
else
{
ALint sourceState = AL_STOPPED;
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_STOPPED )
alSourceStop(m_alSource);
alSourceStop(m_pAlSources[0]);
sourceState = AL_STOPPED;
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_STOPPED)
alSourceStop(m_pAlSources[1]);
m_bActive = false;
}
}
@ -633,35 +1303,51 @@ void CStream::Update()
if ( !m_bPaused )
{
ALint sourceState;
ALint buffersProcessed = 0;
ALint sourceState[2];
ALint buffersProcessed[2] = { 0, 0 };
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed);
// Relying a lot on left buffer states in here
do
{
//alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f);
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);
alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
//alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]);
} while (buffersProcessed[0] != buffersProcessed[1]);
ALint looping = AL_FALSE;
alGetSourcei(m_alSource, AL_LOOPING, &looping);
alGetSourcei(m_pAlSources[0], AL_LOOPING, &looping);
if ( looping == AL_TRUE )
{
TRACE("stream set looping");
alSourcei(m_alSource, AL_LOOPING, AL_TRUE);
alSourcei(m_pAlSources[0], AL_LOOPING, AL_TRUE);
alSourcei(m_pAlSources[1], AL_LOOPING, AL_TRUE);
}
while( buffersProcessed-- )
assert(buffersProcessed[0] == buffersProcessed[1]);
while( buffersProcessed[0]-- )
{
ALuint buffer;
ALuint buffer[2];
alSourceUnqueueBuffers(m_alSource, 1, &buffer);
alSourceUnqueueBuffers(m_pAlSources[0], 1, &buffer[0]);
alSourceUnqueueBuffers(m_pAlSources[1], 1, &buffer[1]);
if ( m_bActive && FillBuffer(buffer) )
alSourceQueueBuffers(m_alSource, 1, &buffer);
if (m_bActive && FillBuffer(buffer))
{
alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]);
alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);
}
}
if ( sourceState != AL_PLAYING )
if ( sourceState[0] != AL_PLAYING )
{
alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed);
SetPlay(buffersProcessed!=0);
alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
SetPlay(buffersProcessed[0]!=0);
}
}
}

View file

@ -3,7 +3,7 @@
#ifdef AUDIO_OAL
#include <AL/al.h>
#define NUM_STREAMBUFFERS 4
#define NUM_STREAMBUFFERS 8
class IDecoder
{
@ -57,7 +57,7 @@ public:
class CStream
{
char m_aFilename[128];
ALuint &m_alSource;
ALuint *m_pAlSources;
ALuint (&m_alBuffers)[NUM_STREAMBUFFERS];
bool m_bPaused;
@ -73,20 +73,20 @@ class CStream
IDecoder *m_pSoundFile;
bool HasSource();
void SetPosition(float x, float y, float z);
void SetPosition(int i, float x, float y, float z);
void SetPitch(float pitch);
void SetGain(float gain);
void Pause();
void SetPlay(bool state);
bool FillBuffer(ALuint alBuffer);
bool FillBuffer(ALuint *alBuffer);
int32 FillBuffers();
void ClearBuffers();
public:
static void Initialise();
static void Terminate();
CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]);
CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate = 32000);
~CStream();
void Delete();

View file

@ -102,7 +102,7 @@ CChannel aChannel[MAXCHANNELS+MAX2DCHANNELS];
uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS];
uint32 nStreamLength[TOTAL_STREAMED_SOUNDS];
ALuint ALStreamSources[MAX_STREAMS];
ALuint ALStreamSources[MAX_STREAMS][2];
ALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS];
struct tMP3Entry
@ -245,9 +245,9 @@ release_existing()
if (stream)
stream->ProviderTerm();
alDeleteSources(1, &ALStreamSources[i]);
alDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
}
alDeleteSources(MAX_STREAMS*2, ALStreamSources[0]);
CChannel::DestroyChannels();
@ -287,7 +287,10 @@ set_new_provider(int index)
//TODO:
_maxSamples = MAXCHANNELS;
ALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,0};
ALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,
ALC_MONO_SOURCES, MAX_STREAMS * 2 + MAXCHANNELS,
0,
};
ALDevice = alcOpenDevice(providers[index].id);
ASSERT(ALDevice != NULL);
@ -319,11 +322,17 @@ set_new_provider(int index)
alGenAuxiliaryEffectSlots(1, &ALEffectSlot);
alGenEffects(1, &ALEffect);
}
alGenSources(MAX_STREAMS*2, ALStreamSources[0]);
for ( int32 i = 0; i < MAX_STREAMS; i++ )
{
alGenSources(1, &ALStreamSources[i]);
alGenBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
alSourcei(ALStreamSources[i][0], AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(ALStreamSources[i][0], AL_POSITION, 0.0f, 0.0f, 0.0f);
alSourcef(ALStreamSources[i][0], AL_GAIN, 1.0f);
alSourcei(ALStreamSources[i][1], AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(ALStreamSources[i][1], AL_POSITION, 0.0f, 0.0f, 0.0f);
alSourcef(ALStreamSources[i][1], AL_GAIN, 1.0f);
CStream *stream = aStream[i];
if (stream)
@ -384,6 +393,12 @@ set_new_provider(int index)
return false;
}
static bool
IsThisTrackAt16KHz(uint32 track)
{
return track == STREAMED_SOUND_RADIO_KCHAT || track == STREAMED_SOUND_RADIO_VCPR || track == STREAMED_SOUND_RADIO_POLICE;
}
cSampleManager::cSampleManager(void)
{
;
@ -989,7 +1004,7 @@ cSampleManager::Initialise(void)
for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )
{
aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0]);
aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0], IsThisTrackAt16KHz(i) ? 16000 : 32000);
if ( aStream[0] && aStream[0]->IsOpened() )
{
@ -1542,10 +1557,11 @@ cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)
nChannelVolume[nChannel] = vol;
if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_FINALE )
{
nChannelVolume[nChannel] = vol / 4;
if (MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE ) {
if (MusicManager.GetCurrentTrack() == STREAMED_SOUND_CUTSCENE_FINALE)
nChannelVolume[nChannel] = 0;
else
nChannelVolume[nChannel] >>= 2;
}
// no idea, does this one looks like a bug or it's SetChannelVolume ?
@ -1671,7 +1687,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
strcpy(filename, StreamedNameTable[nFile]);
CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
@ -1746,7 +1762,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
nFile = 0;
strcat(filename, StreamedNameTable[nFile]);
CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
@ -1770,12 +1786,12 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
}
if (mp3->pLinkPath != NULL)
aStream[nStream] = new CStream(mp3->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream]);
aStream[nStream] = new CStream(mp3->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
else {
strcpy(filename, _mp3DirectoryPath);
strcat(filename, mp3->aFilename);
aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
}
if (aStream[nStream]->IsOpened()) {
@ -1802,7 +1818,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
{
nFile = 0;
strcat(filename, StreamedNameTable[nFile]);
CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
@ -1826,7 +1842,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
}
if (e->pLinkPath != NULL)
aStream[nStream] = new CStream(e->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream]);
aStream[nStream] = new CStream(e->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
else {
strcpy(filename, _mp3DirectoryPath);
strcat(filename, e->aFilename);
@ -1859,7 +1875,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
strcpy(filename, StreamedNameTable[nFile]);
CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;

View file

@ -11,8 +11,13 @@
#include "Frontend.h"
#include "Physical.h"
#include "ColStore.h"
#include "VarConsole.h"
#include "Pools.h"
CPool<ColDef,ColDef> *CColStore::ms_pColPool;
#ifndef MASTER
bool bDispColInMem;
#endif
void
CColStore::Initialise(void)
@ -20,6 +25,9 @@ CColStore::Initialise(void)
if(ms_pColPool == nil)
ms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, "CollisionFiles");
AddColSlot("generic"); // slot 0. not streamed
#ifndef MASTER
VarConsole.Add("Display collision in memory", &bDispColInMem, true);
#endif
}
void
@ -177,7 +185,18 @@ CColStore::LoadCollision(const CVector2D &pos)
wantThisOne = true;
}else{
for (int j = 0; j < MAX_CLEANUP; j++) {
CPhysical* pEntity = CTheScripts::MissionCleanup.DoesThisEntityWaitForCollision(j);
CPhysical* pEntity = nil;
cleanup_entity_struct* pCleanup = &CTheScripts::MissionCleanUp.m_sEntities[i];
if (pCleanup->type == CLEANUP_CAR) {
pEntity = CPools::GetVehiclePool()->GetAt(pCleanup->id);
if (!pEntity || pEntity->GetStatus() == STATUS_WRECKED)
continue;
}
else if (pCleanup->type == CLEANUP_CHAR) {
pEntity = CPools::GetPedPool()->GetAt(pCleanup->id);
if (!pEntity || ((CPed*)pEntity)->DyingOrDead())
continue;
}
if (pEntity && !pEntity->bDontLoadCollision && !pEntity->bIsFrozen) {
if (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f))
wantThisOne = true;

View file

@ -23,6 +23,7 @@
#include "Vehicle.h"
#include "Wanted.h"
#include "World.h"
#include "VarConsole.h"
//--MIAMI: file done
@ -129,8 +130,15 @@ int32 hGarages = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde;
#ifndef MASTER
bool bPrintNearestObject;
#endif
void CGarages::Init(void)
{
#ifndef MASTER
VarConsole.Add("Print nearest object", &bPrintNearestObject, true);
#endif
CrushedCarId = -1;
NumGarages = 0;
MessageEndTime = 0;

View file

@ -93,6 +93,7 @@ VALIDATE_SIZE(CStoredCar, 0x28);
class CGarage
{
public:
uint8 m_eGarageType;
uint8 m_eGarageState;
uint8 m_nMaxStoredCars;
@ -189,9 +190,6 @@ class CGarage
int32 FindMaxNumStoredCarsForGarage() { return Min(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }
friend class CGarages;
friend class cAudioManager;
friend class CCamera;
};
class CGarages
@ -199,6 +197,7 @@ class CGarages
enum {
MESSAGE_LENGTH = 8,
};
public:
static int32 BankVansCollected;
static bool BombsAreFree;
static bool RespraysAreFree;
@ -218,7 +217,6 @@ class CGarages
static CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];
static bool bCamShouldBeOutisde;
public:
static void Init(void);
#ifndef PS2
static void Shutdown(void);
@ -259,7 +257,6 @@ public:
static void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }
static void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }
private:
static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void);
@ -296,7 +293,4 @@ private:
}
static bool IsThisGarageTypeSafehouse(uint8 type) { return FindSafeHouseIndexForGarageType(type) >= 0; }
friend class cAudioManager;
friend class CReplay;
friend class CGarage;
};

View file

@ -1508,12 +1508,12 @@ void CReplay::RestoreStuffFromMem(void)
tmp1.UpdateRW();
}
else if (mi == MI_HUNTER) {
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);
}
else if (vehicle->IsRealHeli()) {
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);
}

View file

@ -85,7 +85,7 @@ uint16 CTheScripts::NumScriptDebugLines;
uint16 CTheScripts::NumberOfIntroRectanglesThisFrame;
uint16 CTheScripts::NumberOfIntroTextLinesThisFrame;
uint8 CTheScripts::UseTextCommands;
CMissionCleanup CTheScripts::MissionCleanup;
CMissionCleanup CTheScripts::MissionCleanUp;
CUpsideDownCarCheck CTheScripts::UpsideDownCars;
CStuckCarCheck CTheScripts::StuckCars;
uint16 CTheScripts::CommandsExecuted;
@ -1751,19 +1751,6 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type)
m_nCount++;
}
// done(LCS)
static void PossiblyWakeThisEntity(CPhysical* pEntity, bool ifColLoaded = false)
{
if (!pEntity->bIsStaticWaitingForCollision)
return;
if (!ifColLoaded || CColStore::HasCollisionLoaded(pEntity->GetPosition())) {
pEntity->bIsStaticWaitingForCollision = false;
if (!pEntity->GetIsStatic())
pEntity->AddToMovingList();
}
}
// done(LCS)
void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
{
for (int i = 0; i < MAX_CLEANUP; i++){
@ -1771,23 +1758,38 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
switch (m_sEntities[i].type) {
case CLEANUP_CAR:
{
CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
if (v)
PossiblyWakeThisEntity(v);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
if (pVehicle) {
if (pVehicle->bIsStaticWaitingForCollision) {
pVehicle->bIsStaticWaitingForCollision = false;
if (!pVehicle->GetIsStatic())
pVehicle->AddToMovingList();
}
}
break;
}
case CLEANUP_CHAR:
{
CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
if (p)
PossiblyWakeThisEntity(p);
CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
if (pPed) {
if (pPed->bIsStaticWaitingForCollision) {
pPed->bIsStaticWaitingForCollision = false;
if (!pPed->GetIsStatic())
pPed->AddToMovingList();
}
}
break;
}
case CLEANUP_OBJECT:
{
CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
if (o)
PossiblyWakeThisEntity(o);
CObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
if (pObject) {
if (pObject->bIsStaticWaitingForCollision) {
pObject->bIsStaticWaitingForCollision = false;
if (!pObject->GetIsStatic())
pObject->AddToMovingList();
}
}
break;
}
default:
@ -1895,23 +1897,6 @@ void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects()
}
}
// TODO(LCS)
CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i)
{
if (m_sEntities[i].type == CLEANUP_CAR) {
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
if (pVehicle && pVehicle->GetStatus() != STATUS_WRECKED)
return pVehicle;
}
else if (m_sEntities[i].type == CLEANUP_CHAR) {
CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
if (pPed && !pPed->DyingOrDead())
return pPed;
}
return nil;
}
// done(LCS) except TODO
void CMissionCleanup::Process()
{
CPopulation::m_AllRandomPedsThisType = -1;
@ -2012,13 +1997,18 @@ void CUpsideDownCarCheck::Init()
// done(LCS)
bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id)
{
CVehicle* v = CPools::GetVehiclePool()->GetAt(id);
return v->GetUp().z <= -0.97f &&
v->GetMoveSpeed().Magnitude() < 0.01f &&
v->GetTurnSpeed().Magnitude() < 0.02f;
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(id);
return IsCarUpsideDown(pVehicle);
}
bool CUpsideDownCarCheck::IsCarUpsideDown(CVehicle* pVehicle)
{
assert(pVehicle);
return pVehicle->GetUp().z <= UPSIDEDOWN_UP_THRESHOLD &&
pVehicle->GetMoveSpeed().Magnitude() < UPSIDEDOWN_MOVE_SPEED_THRESHOLD &&
pVehicle->GetTurnSpeed().Magnitude() < UPSIDEDOWN_TURN_SPEED_THRESHOLD;
}
// done(LCS)
void CUpsideDownCarCheck::UpdateTimers()
{
uint32 timeStep = CTimer::GetTimeStepInMilliseconds();
@ -2040,7 +2030,7 @@ void CUpsideDownCarCheck::UpdateTimers()
bool CUpsideDownCarCheck::AreAnyCarsUpsideDown()
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > 1000)
if (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > UPSIDEDOWN_TIMER_THRESHOLD)
return true;
}
return false;
@ -2052,8 +2042,10 @@ void CUpsideDownCarCheck::AddCarToCheck(int32 id)
uint16 index = 0;
while (index < MAX_UPSIDEDOWN_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
index++;
#ifdef FIX_BUGS
if (index >= MAX_UPSIDEDOWN_CAR_CHECKS)
return;
#endif
m_sCars[index].m_nVehicleIndex = id;
m_sCars[index].m_nUpsideDownTimer = 0;
}
@ -2074,7 +2066,7 @@ bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex == id)
return m_sCars[i].m_nUpsideDownTimer > 1000;
return m_sCars[i].m_nUpsideDownTimer > UPSIDEDOWN_TIMER_THRESHOLD;
}
return false;
}
@ -2124,7 +2116,10 @@ void CStuckCarCheck::AddCarToCheck(int32 id, float radius, uint32 time)
int index = 0;
while (index < MAX_STUCK_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
index++;
/* Would be nice to return if index >= MAX_STUCK_CAR_CHECKS... */
#ifdef FIX_BUGS
if (index >= MAX_STUCK_CAR_CHECKS)
return;
#endif
m_sCars[index].m_nVehicleIndex = id;
m_sCars[index].m_vecPos = pv->GetPosition();
m_sCars[index].m_nLastCheck = CTimer::GetTimeInMilliseconds();
@ -2356,7 +2351,7 @@ void CTheScripts::Init()
ScriptsArray[i].Init();
ScriptsArray[i].AddScriptToList(&pIdleScripts);
}
MissionCleanup.Init();
MissionCleanUp.Init();
UpsideDownCars.Init();
StuckCars.Init();
CFileMgr::SetDir("data");
@ -2484,7 +2479,7 @@ void CTheScripts::Process()
float timeStep = CTimer::GetTimeStepInMilliseconds();
UpsideDownCars.UpdateTimers();
StuckCars.Process();
MissionCleanup.CheckIfCollisionHasLoadedForMissionObjects();
MissionCleanUp.CheckIfCollisionHasLoadedForMissionObjects();
DrawScriptSpheres();
if (FailCurrentMission)
--FailCurrentMission;
@ -3808,7 +3803,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_DELETE_CHAR:
@ -3817,7 +3812,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
CTheScripts::RemoveThisPed(ped);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_CHAR_WANDER_DIR:
@ -4038,7 +4033,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ScriptParams[0] = handle;
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);
return 0;
}
case COMMAND_DELETE_CAR:
@ -4051,7 +4046,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
delete car;
}
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_CAR_GOTO_COORDINATES:
@ -4171,9 +4166,9 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
car->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];
if (missionRetryScriptIndex == 40 && car->GetModelIndex() == MI_CHEETAH) // Turismo
car->AutoPilot.m_nCruiseSpeed = 8 * car->AutoPilot.m_nCruiseSpeed / 10;
car->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fUnkMaxVelocity);
car->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);
#else
car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fUnkMaxVelocity);
car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);
#endif
return 0;
}
@ -4366,7 +4361,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
if (!m_bIsMissionScript)
return 0;
CTheScripts::MissionCleanup.Process();
CTheScripts::MissionCleanUp.Process();
return 0;
}
case COMMAND_STORE_CAR_CHAR_IS_IN:
@ -4389,7 +4384,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
}
@ -4400,14 +4395,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CCarCtrl::NumMissionCars++;
CCarCtrl::NumRandomCars--;
CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case PARKED_VEHICLE:
pCurrent->VehicleCreatedBy = MISSION_VEHICLE;
CCarCtrl::NumMissionCars++;
CCarCtrl::NumParkedCars--;
CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case MISSION_VEHICLE:
case PERMANENT_VEHICLE:
@ -4440,7 +4435,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
}
@ -4451,14 +4446,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CCarCtrl::NumMissionCars++;
CCarCtrl::NumRandomCars--;
CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case PARKED_VEHICLE:
pCurrent->VehicleCreatedBy = MISSION_VEHICLE;
CCarCtrl::NumMissionCars++;
CCarCtrl::NumParkedCars--;
CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case MISSION_VEHICLE:
case PERMANENT_VEHICLE:
@ -4607,7 +4602,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_DELETE_OBJECT:
@ -4620,7 +4615,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
delete pObj;
}
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_ADD_SCORE:
@ -4836,7 +4831,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD:
@ -4886,81 +4881,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
return -1;
}
void CRunningScript::Save(uint8*& buf)
{
#ifdef COMPATIBLE_SAVES
SkipSaveBuf(buf, 8);
for (int i = 0; i < 8; i++)
WriteSaveBuf<char>(buf, m_abScriptName[i]);
WriteSaveBuf<uint32>(buf, m_nIp);
#ifdef CHECK_STRUCT_SIZES
static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6");
#endif
for (int i = 0; i < MAX_STACK_DEPTH; i++)
WriteSaveBuf<uint32>(buf, m_anStack[i]);
WriteSaveBuf<uint16>(buf, m_nStackPointer);
SkipSaveBuf(buf, 2);
#ifdef CHECK_STRUCT_SIZES
static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18");
#endif
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
WriteSaveBuf<int32>(buf, m_anLocalVariables[i]);
WriteSaveBuf<bool>(buf, m_bIsActive);
WriteSaveBuf<bool>(buf, m_bCondResult);
WriteSaveBuf<bool>(buf, m_bIsMissionScript);
WriteSaveBuf<bool>(buf, m_bSkipWakeTime);
WriteSaveBuf<uint32>(buf, m_nWakeTime);
WriteSaveBuf<uint16>(buf, m_nAndOrState);
WriteSaveBuf<bool>(buf, m_bNotFlag);
WriteSaveBuf<bool>(buf, m_bDeatharrestEnabled);
WriteSaveBuf<bool>(buf, m_bDeatharrestExecuted);
WriteSaveBuf<bool>(buf, m_bMissionFlag);
SkipSaveBuf(buf, 2);
#else
WriteSaveBuf(buf, *this);
#endif
}
void CRunningScript::Load(uint8*& buf)
{
#ifdef COMPATIBLE_SAVES
SkipSaveBuf(buf, 8);
for (int i = 0; i < 8; i++)
m_abScriptName[i] = ReadSaveBuf<char>(buf);
m_nIp = ReadSaveBuf<uint32>(buf);
#ifdef CHECK_STRUCT_SIZES
static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6");
#endif
for (int i = 0; i < MAX_STACK_DEPTH; i++)
m_anStack[i] = ReadSaveBuf<uint32>(buf);
m_nStackPointer = ReadSaveBuf<uint16>(buf);
SkipSaveBuf(buf, 2);
#ifdef CHECK_STRUCT_SIZES
static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18");
#endif
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
m_anLocalVariables[i] = ReadSaveBuf<int32>(buf);
m_bIsActive = ReadSaveBuf<bool>(buf);
m_bCondResult = ReadSaveBuf<bool>(buf);
m_bIsMissionScript = ReadSaveBuf<bool>(buf);
m_bSkipWakeTime = ReadSaveBuf<bool>(buf);
m_nWakeTime = ReadSaveBuf<uint32>(buf);
m_nAndOrState = ReadSaveBuf<uint16>(buf);
m_bNotFlag = ReadSaveBuf<bool>(buf);
m_bDeatharrestEnabled = ReadSaveBuf<bool>(buf);
m_bDeatharrestExecuted = ReadSaveBuf<bool>(buf);
m_bMissionFlag = ReadSaveBuf<bool>(buf);
SkipSaveBuf(buf, 2);
#else
CRunningScript* n = next;
CRunningScript* p = prev;
*this = ReadSaveBuf<CRunningScript>(buf);
next = n;
prev = p;
#endif
}
#ifdef MISSION_REPLAY
bool CRunningScript::CanAllowMissionReplay()
@ -4995,7 +4915,7 @@ void RetryMission(int type, int unk)
else if (type == 2) {
doingMissionRetry = false;
AllowMissionReplay = 6;
CTheScripts::MissionCleanup.Process();
CTheScripts::MissionCleanUp.Process();
}
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "common.h"
#include "Font.h"
#include "Ped.h"
#include "PedType.h"
#include "Text.h"
@ -20,26 +21,31 @@ 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 COP_PED_FIND_Z_OFFSET 10.0f
#define PICKUP_PLACEMENT_OFFSET (0.5f)
#define PED_FIND_Z_OFFSET (5.0f)
#define COP_PED_FIND_Z_OFFSET (10.0f)
#define SPHERE_MARKER_R 252
#define SPHERE_MARKER_G 138
#define SPHERE_MARKER_B 242
#define SPHERE_MARKER_A 228
#define UPSIDEDOWN_UP_THRESHOLD (-0.97f)
#define UPSIDEDOWN_MOVE_SPEED_THRESHOLD (0.01f)
#define UPSIDEDOWN_TURN_SPEED_THRESHOLD (0.02f)
#define UPSIDEDOWN_TIMER_THRESHOLD (1000)
#define SPHERE_MARKER_R (252)
#define SPHERE_MARKER_G (138)
#define SPHERE_MARKER_B (242)
#define SPHERE_MARKER_A (228)
#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
#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
#define METERS_IN_FOOT (0.3f)
#define FEET_IN_METER (3.33f)
#endif
#define KEY_LENGTH_IN_SCRIPT 8
#define KEY_LENGTH_IN_SCRIPT (8)
//#define GTA_SCRIPT_COLLECTIVE
@ -94,12 +100,12 @@ struct intro_text_line
m_bCentered = false;
m_bBackground = false;
m_bBackgroundOnly = false;
m_fWrapX = 182.0f; /* TODO: scaling as bugfix */
m_fCenterSize = 640.0f; /* --||-- */
m_fWrapX = 182.0f;
m_fCenterSize = DEFAULT_SCREEN_WIDTH;
m_sBackgroundColor = CRGBA(128, 128, 128, 128);
m_bTextProportional = true;
m_bTextBeforeFade = false;
m_nFont = 2; /* enum? */
m_nFont = FONT_STANDARD;
m_fAtX = 0.0f;
m_fAtY = 0.0f;
memset(&m_Text, 0, sizeof(m_Text));
@ -148,10 +154,10 @@ enum {
class CMissionCleanup
{
public:
cleanup_entity_struct m_sEntities[MAX_CLEANUP];
uint8 m_nCount;
public:
CMissionCleanup();
void Init();
@ -160,10 +166,9 @@ public:
void RemoveEntityFromList(int32, uint8);
void Process();
void CheckIfCollisionHasLoadedForMissionObjects();
CPhysical* DoesThisEntityWaitForCollision(int i);
};
struct CUpsideDownCarCheckEntry
struct upsidedown_car_data
{
int32 m_nVehicleIndex;
uint32 m_nUpsideDownTimer;
@ -171,11 +176,12 @@ struct CUpsideDownCarCheckEntry
class CUpsideDownCarCheck
{
CUpsideDownCarCheckEntry m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS];
upsidedown_car_data m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS];
public:
void Init();
bool IsCarUpsideDown(int32);
bool IsCarUpsideDown(CVehicle*);
void UpdateTimers();
bool AreAnyCarsUpsideDown();
void AddCarToCheck(int32);
@ -193,7 +199,7 @@ struct stuck_car_data
bool m_bStuck;
stuck_car_data() { }
inline void Reset();
void Reset();
};
class CStuckCarCheck
@ -259,7 +265,7 @@ enum {
enum {
MAX_NUM_SCRIPTS = 128,
MAX_NUM_INTRO_TEXT_LINES = 2,
MAX_NUM_INTRO_TEXT_LINES = 48,
MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16,
@ -273,6 +279,7 @@ enum {
class CTheScripts
{
public:
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];
static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
@ -286,7 +293,7 @@ class CTheScripts
static CStoredLine aStoredLines[MAX_NUM_STORED_LINES];
static bool DbgFlag;
static uint32 OnAMissionFlag;
static CMissionCleanup MissionCleanup;
static CMissionCleanup MissionCleanUp;
static CStuckCarCheck StuckCars;
static CUpsideDownCarCheck UpsideDownCars;
static int32 StoreVehicleIndex;
@ -321,11 +328,10 @@ class CTheScripts
static int AllowedCollision[MAX_ALLOWED_COLLISIONS];
#endif
public:
static bool bPlayerIsInTheStatium;
static uint8 RiotIntensity;
static bool bPlayerHasMetDebbieHarry;
public:
static void Init();
static void Process();
@ -379,8 +385,6 @@ public:
return Read4BytesFromScript(&tmp);
}
private:
static CRunningScript* StartNewScript(uint32);
static void CleanUpThisVehicle(CVehicle*);
@ -438,18 +442,11 @@ public:
static void SetObjectiveForAllPedsInCollective(int, eObjective);
#endif
friend class CRunningScript;
friend class CHud;
friend void CMissionCleanup::Process();
friend class CColStore;
#ifdef FIX_BUGS
friend void RetryMission(int, int);
#endif
};
enum {
MAX_STACK_DEPTH = 6, // 4 PS2
MAX_STACK_DEPTH = 6,
NUM_LOCAL_VARS = 16,
NUM_TIMERS = 2
};
@ -476,6 +473,7 @@ class CRunningScript
ORS_8
};
public:
CRunningScript* next;
CRunningScript* prev;
char m_abScriptName[8];
@ -514,7 +512,6 @@ public:
static const uint32 nSaveStructSize;
private:
void CollectParameters(uint32*, int16);
int32 CollectNextParameterWithoutIncreasingPC(uint32);
int32* GetPointerToScriptVariable(uint32*, int16);
@ -582,7 +579,6 @@ private:
static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami);
friend class CTheScripts;
};
#ifdef USE_DEBUG_SCRIPT_LOADER

View file

@ -1048,7 +1048,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
CTheScripts::CleanUpThisPed(pPed);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED:
@ -1057,7 +1057,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
CTheScripts::CleanUpThisVehicle(pVehicle);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED:
@ -1066,7 +1066,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
CTheScripts::CleanUpThisObject(pObject);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_DONT_REMOVE_CHAR:
@ -1074,7 +1074,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_DONT_REMOVE_CAR:
@ -1082,7 +1082,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_DONT_REMOVE_OBJECT:
@ -1090,7 +1090,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 1);
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
script_assert(pObject);
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_CREATE_CHAR_AS_PASSENGER:
@ -1142,6 +1142,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetPosition(pVehicle->GetPosition());
pPed->SetOrientation(0.0f, 0.0f, 0.0f);
CPopulation::ms_nTotalMissionPeds++;
CWorld::Add(pPed);
if (ScriptParams[3] >= 0)
pVehicle->AddPassenger(pPed, ScriptParams[3]);
else
@ -1149,16 +1150,14 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->m_pMyVehicle = pVehicle;
pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
pPed->bInVehicle = true;
pVehicle->SetStatus(STATUS_PHYSICS);
pPed->SetPedState(PED_DRIVING);
pPed->bUsesCollision = false;
pPed->AddInCarAnims(pVehicle, false);
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);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT:

View file

@ -325,11 +325,11 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
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);
@ -363,8 +363,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
return 0;
}
#endif // GTA_PS2
/*
case COMMAND_SET_ALL_TAXI_LIGHTS:
CollectParameters(&m_nIp, 1);
CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0);
@ -1279,7 +1277,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
/*
@ -1343,7 +1341,6 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
return 0;
}
#endif
/*
case COMMAND_IS_PLAYER_STOPPED:
{
CollectParameters(&m_nIp, 1);
@ -1835,7 +1832,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
@ -1890,7 +1887,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);

View file

@ -155,7 +155,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
++CCarCtrl::NumMissionCars;
--CCarCtrl::NumRandomCars;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);
}
ScriptParams[0] = handle;
StoreParameters(&m_nIp, 1);
@ -188,7 +188,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
++CCarCtrl::NumMissionCars;
--CCarCtrl::NumRandomCars;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);
}
ScriptParams[0] = handle;
StoreParameters(&m_nIp, 1);
@ -254,6 +254,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->SetObjective(OBJECTIVE_CATCH_TRAIN);
return 0;
}
*/
#ifdef GTA_SCRIPT_COLLECTIVE
case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
CollectParameters(&m_nIp, 1);
@ -608,7 +609,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
}
}
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:
@ -1055,7 +1056,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:

View file

@ -2251,6 +2251,80 @@ VALIDATESAVEBUF(size)
#undef SCRIPT_DATA_SIZE
void CRunningScript::Save(uint8*& buf)
{
#ifdef COMPATIBLE_SAVES
SkipSaveBuf(buf, 8);
for (int i = 0; i < 8; i++)
WriteSaveBuf<char>(buf, m_abScriptName[i]);
WriteSaveBuf<uint32>(buf, m_nIp);
#ifdef CHECK_STRUCT_SIZES
static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6");
#endif
for (int i = 0; i < MAX_STACK_DEPTH; i++)
WriteSaveBuf<uint32>(buf, m_anStack[i]);
WriteSaveBuf<uint16>(buf, m_nStackPointer);
SkipSaveBuf(buf, 2);
#ifdef CHECK_STRUCT_SIZES
static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18");
#endif
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
WriteSaveBuf<int32>(buf, m_anLocalVariables[i]);
WriteSaveBuf<bool>(buf, m_bIsActive);
WriteSaveBuf<bool>(buf, m_bCondResult);
WriteSaveBuf<bool>(buf, m_bIsMissionScript);
WriteSaveBuf<bool>(buf, m_bSkipWakeTime);
WriteSaveBuf<uint32>(buf, m_nWakeTime);
WriteSaveBuf<uint16>(buf, m_nAndOrState);
WriteSaveBuf<bool>(buf, m_bNotFlag);
WriteSaveBuf<bool>(buf, m_bDeatharrestEnabled);
WriteSaveBuf<bool>(buf, m_bDeatharrestExecuted);
WriteSaveBuf<bool>(buf, m_bMissionFlag);
SkipSaveBuf(buf, 2);
#else
WriteSaveBuf(buf, *this);
#endif
}
void CRunningScript::Load(uint8*& buf)
{
#ifdef COMPATIBLE_SAVES
SkipSaveBuf(buf, 8);
for (int i = 0; i < 8; i++)
m_abScriptName[i] = ReadSaveBuf<char>(buf);
m_nIp = ReadSaveBuf<uint32>(buf);
#ifdef CHECK_STRUCT_SIZES
static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6");
#endif
for (int i = 0; i < MAX_STACK_DEPTH; i++)
m_anStack[i] = ReadSaveBuf<uint32>(buf);
m_nStackPointer = ReadSaveBuf<uint16>(buf);
SkipSaveBuf(buf, 2);
#ifdef CHECK_STRUCT_SIZES
static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18");
#endif
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
m_anLocalVariables[i] = ReadSaveBuf<int32>(buf);
m_bIsActive = ReadSaveBuf<bool>(buf);
m_bCondResult = ReadSaveBuf<bool>(buf);
m_bIsMissionScript = ReadSaveBuf<bool>(buf);
m_bSkipWakeTime = ReadSaveBuf<bool>(buf);
m_nWakeTime = ReadSaveBuf<uint32>(buf);
m_nAndOrState = ReadSaveBuf<uint16>(buf);
m_bNotFlag = ReadSaveBuf<bool>(buf);
m_bDeatharrestEnabled = ReadSaveBuf<bool>(buf);
m_bDeatharrestExecuted = ReadSaveBuf<bool>(buf);
m_bMissionFlag = ReadSaveBuf<bool>(buf);
SkipSaveBuf(buf, 2);
#else
CRunningScript* n = next;
CRunningScript* p = prev;
*this = ReadSaveBuf<CRunningScript>(buf);
next = n;
prev = p;
#endif
}
void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity)
{
static CColPoint aTempColPoints[MAX_COLLISION_POINTS];

View file

@ -703,7 +703,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CAR);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_START_BOAT_FOAM_ANIMATION:
@ -1191,7 +1191,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 8);
CPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
CVehicle *pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
pPed->AttachPedToEntity(pVehicle, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(ScriptParams[6]), (eWeaponType)ScriptParams[7]);
pPed->AttachPedToEntity(pVehicle, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(*(float*)&ScriptParams[6]), (eWeaponType)ScriptParams[7]);
return 0;
}
case COMMAND_DETACH_CHAR_FROM_CAR:
@ -1272,7 +1272,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
@ -1320,7 +1320,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);

View file

@ -576,11 +576,11 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
CollectParameters(&m_nIp, 1);
CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
ScriptParams[0] = pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels;
ScriptParams[1] = *(int*)&pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels;
*(float*)&ScriptParams[1] = pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels;
ScriptParams[2] = pPlayerInfo->m_nLastTimeSpentOnWheelie;
ScriptParams[3] = *(int*)&pPlayerInfo->m_nLastDistanceTravelledOnWheelie;
*(float*)&ScriptParams[3] = pPlayerInfo->m_nLastDistanceTravelledOnWheelie;
ScriptParams[4] = pPlayerInfo->m_nLastTimeSpentOnStoppie;
ScriptParams[5] = *(int*)&pPlayerInfo->m_nLastDistanceTravelledOnStoppie;
*(float*)&ScriptParams[5] = pPlayerInfo->m_nLastDistanceTravelledOnStoppie;
StoreParameters(&m_nIp, 6);
pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels = 0;
pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels = 0.0f;
@ -1201,7 +1201,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER:
@ -1231,7 +1231,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS:

View file

@ -283,7 +283,7 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);

View file

@ -10,6 +10,7 @@
#include "Vehicle.h"
#include "Wanted.h"
#include "World.h"
#include "VarConsole.h"
#define TIME_BETWEEN_SETPIECE_SPAWNS 20000
@ -23,6 +24,9 @@ void CSetPieces::Init(void)
{
bDebug = false;
NumSetPieces = 0;
#ifndef MASTER
VarConsole.Add("Show set pieces", &bDebug, true);
#endif
}
void CSetPieces::AddOne(uint8 type, CVector2D vTriggerInf, CVector2D vTriggerSup, CVector2D vSpawn1, CVector2D vTarget1, CVector2D vSpawn2, CVector2D vTarget2)
@ -47,6 +51,9 @@ void CSetPieces::Update(void)
int nLast = NumSetPieces * (CTimer::GetFrameCounter() % 8 + 1) / 8;
for (int i = nFirst; i < nLast; i++)
aSetPieces[i].Update();
#ifndef MASTER
// TODO: debug code from mobile
#endif // !MASTER
}
void CSetPieces::Save(uint8* buf, uint32* size)

View file

@ -2370,8 +2370,10 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
}
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if (!isAttached) {
while(Beta >= TWOPI) Beta -= TWOPI;
while(Beta < 0) Beta += TWOPI;
}
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
@ -2414,13 +2416,14 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
}
}
}else{
while(Beta < -PI) Beta += 2*PI;
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += TWOPI;
while(Beta >= PI) Beta -= TWOPI;
}
mat = TargetPed->m_attachedTo->GetMatrix();
rot.SetRotateX(Alpha);
switch(TargetPed->m_attachType){
case 0: rot.RotateZ(Beta); break;
case 1: rot.RotateZ(Beta + HALFPI); break;
case 2: rot.RotateZ(Beta + PI); break;
case 3: rot.RotateZ(Beta - HALFPI); break;

View file

@ -4,6 +4,7 @@
#include "Pad.h"
#include "Clock.h"
#include "Stats.h"
#include "VarConsole.h"
// --MIAMI: File done
@ -20,6 +21,10 @@ uint32 CClock::ms_nMillisecondsPerGameMinute;
uint32 CClock::ms_nLastClockTick;
bool CClock::ms_bClockHasBeenStored;
#ifndef MASTER
bool gbFreezeTime;
#endif
void
CClock::Initialise(uint32 scale)
{
@ -31,6 +36,10 @@ CClock::Initialise(uint32 scale)
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
ms_bClockHasBeenStored = false;
debug("CClock ready\n");
#ifndef MASTER
VarConsole.Add("Time (hour of day)", &ms_nGameClockHours, 1, 0, 23, true);
VarConsole.Add("Freeze time", &gbFreezeTime, true);
#endif
}
void
@ -50,6 +59,10 @@ CClock::Update(void)
}
}
#ifndef MASTER
else if (gbFreezeTime)
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
#endif
else if(CTimer::GetTimeInMilliseconds() - ms_nLastClockTick > ms_nMillisecondsPerGameMinute || gbFastTime)
{
ms_nGameClockMinutes++;

View file

@ -2354,15 +2354,15 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
#define VFB(b)
#endif
#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT) \
#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT, RSL, RSR) \
{{ \
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 */ \
LEFT, /* GO_LEFT */ \
RIGHT, /* GO_RIGHT */ \
Q, /* PED_SNIPER_ZOOM_IN */ \
X, /* PED_SNIPER_ZOOM_OUT */ \
T, /* VEHICLE_ENTER_EXIT */ \
@ -2370,6 +2370,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
X, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
L3, /* PED_DUCK */ \
L1, /* PED_ANSWER_PHONE */ \
VFB(O) /* VEHICLE_FIREWEAPON */ \
X, /* VEHICLE_ACCELERATE */ \
Q, /* VEHICLE_BRAKE */ \
@ -2382,10 +2384,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
nil, /* VEHICLE_TURRETLEFT */ \
nil, /* VEHICLE_TURRETRIGHT */ \
nil, /* VEHICLE_TURRETUP */ \
nil, /* VEHICLE_TURRETDOWN */ \
RSL, /* VEHICLE_TURRETLEFT */ \
RSR, /* VEHICLE_TURRETRIGHT */ \
UP, /* VEHICLE_TURRETUP */ \
DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@ -2397,6 +2399,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}, \
{ \
@ -2405,8 +2408,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
nil, /* GO_LEFT */ \
nil, /* GO_RIGHT */ \
LEFT, /* GO_LEFT */ \
RIGHT, /* GO_RIGHT */ \
Q, /* PED_SNIPER_ZOOM_IN */ \
X, /* PED_SNIPER_ZOOM_OUT */ \
T, /* VEHICLE_ENTER_EXIT */ \
@ -2414,6 +2417,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
X, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
L3, /* PED_DUCK */ \
L1, /* PED_ANSWER_PHONE */ \
VFB(O) /* VEHICLE_FIREWEAPON */ \
X, /* VEHICLE_ACCELERATE */ \
Q, /* VEHICLE_BRAKE */ \
@ -2426,10 +2431,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
nil, /* VEHICLE_TURRETLEFT */ \
nil, /* VEHICLE_TURRETRIGHT */ \
nil, /* VEHICLE_TURRETUP */ \
nil, /* VEHICLE_TURRETDOWN */ \
RSL, /* VEHICLE_TURRETLEFT */ \
RSR, /* VEHICLE_TURRETRIGHT */ \
UP, /* VEHICLE_TURRETUP */ \
DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@ -2441,6 +2446,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}, \
{ \
@ -2449,8 +2455,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
nil, /* GO_LEFT */ \
nil, /* GO_RIGHT */ \
LEFT, /* GO_LEFT */ \
RIGHT, /* GO_RIGHT */ \
T, /* PED_SNIPER_ZOOM_IN */ \
Q, /* PED_SNIPER_ZOOM_OUT */ \
L1, /* VEHICLE_ENTER_EXIT */ \
@ -2458,6 +2464,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
O, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
L3, /* PED_DUCK */ \
L1, /* PED_ANSWER_PHONE */ \
VFB(O) /* VEHICLE_FIREWEAPON */ \
X, /* VEHICLE_ACCELERATE */ \
Q, /* VEHICLE_BRAKE */ \
@ -2470,10 +2478,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
nil, /* VEHICLE_TURRETLEFT */ \
nil, /* VEHICLE_TURRETRIGHT */ \
nil, /* VEHICLE_TURRETUP */ \
nil, /* VEHICLE_TURRETDOWN */ \
RSL, /* VEHICLE_TURRETLEFT */ \
RSR, /* VEHICLE_TURRETRIGHT */ \
UP, /* VEHICLE_TURRETUP */ \
DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
T, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@ -2485,6 +2493,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}, \
{ \
@ -2493,8 +2502,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
nil, /* GO_LEFT */ \
nil, /* GO_RIGHT */ \
LEFT, /* GO_LEFT */ \
RIGHT, /* GO_RIGHT */ \
Q, /* PED_SNIPER_ZOOM_IN */ \
X, /* PED_SNIPER_ZOOM_OUT */ \
T, /* VEHICLE_ENTER_EXIT */ \
@ -2502,6 +2511,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
X, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
L3, /* PED_DUCK */ \
L1, /* PED_ANSWER_PHONE */ \
VFB(R1) /* VEHICLE_FIREWEAPON */ \
nil, /* VEHICLE_ACCELERATE */ \
nil, /* VEHICLE_BRAKE */ \
@ -2514,10 +2525,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
nil, /* VEHICLE_TURRETLEFT */ \
nil, /* VEHICLE_TURRETRIGHT */ \
nil, /* VEHICLE_TURRETUP */ \
nil, /* VEHICLE_TURRETDOWN */ \
RSL, /* VEHICLE_TURRETLEFT */ \
RSR, /* VEHICLE_TURRETRIGHT */ \
UP, /* VEHICLE_TURRETUP */ \
DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
O, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@ -2529,14 +2540,26 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}}
#ifdef BUTTON_ICONS
#define UP "~U~"
#define DOWN "~D~"
#define LEFT "~<~"
#define RIGHT "~>~"
#else
#define UP "UP"
#define DOWN "DOWN"
#define LEFT "LEFT"
#define RIGHT "RIGHT"
#endif
const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK");
const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK", "right stick left", "right stick right");
#ifdef BUTTON_ICONS
const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK");
const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK", "~(~", "~)~");
#endif
@ -2558,11 +2581,11 @@ const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O
#endif
const char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] =
CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT");
CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT", "right stick left", "right stick right");
#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");
CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT", "~(~", "~)~");
#endif
#undef PS2_TRIANGLE
@ -2570,6 +2593,11 @@ const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =
#undef PS2_CROSS
#undef PS2_SQUARE
#undef UP
#undef DOWN
#undef LEFT
#undef RIGHT
#undef CONTROLLER_BUTTONS
#undef VFB

View file

@ -1280,6 +1280,9 @@ CMenuManager::DrawStandardMenus(bool activeScreen)
case MENUACTION_CFO_SELECT:
CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];
if (option.m_Action == MENUACTION_CFO_SELECT) {
if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)
CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));
// 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;
@ -4786,7 +4789,11 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
TheCamera.m_fMouseAccelHorzntl = 0.0025f;
CVehicle::m_bDisableMouseSteering = true;
m_ControlMethod = CONTROL_STANDARD;
#ifdef PC_PLAYER_CONTROLS
TheCamera.m_bUseMouse3rdPerson = true;
#else
TheCamera.m_bUseMouse3rdPerson = false;
#endif
SaveSettings();
}
SetHelperText(2);
@ -4806,6 +4813,9 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
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->disableIfGameLoaded && !m_bGameNotLoaded)
break;
if (!option.m_CFOSelect->onlyApplyOnEnter) {
option.m_CFOSelect->displayedValue++;
if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)
@ -4954,6 +4964,9 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
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->disableIfGameLoaded && !m_bGameNotLoaded)
break;
if (changeAmount > 0) {
option.m_CFOSelect->displayedValue++;
if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts)

View file

@ -403,9 +403,10 @@ struct CCFOSelect : CCFO
int8 displayedValue; // only if onlyApplyOnEnter enabled for now
int8 lastSavedValue; // only if onlyApplyOnEnter enabled
ChangeFunc changeFunc;
bool disableIfGameLoaded;
CCFOSelect() {};
CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc){
CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc = nil, bool disableIfGameLoaded = false){
this->value = value;
if (value)
this->lastSavedValue = this->displayedValue = *value;
@ -415,6 +416,7 @@ struct CCFOSelect : CCFO
this->numRightTexts = numRightTexts;
this->onlyApplyOnEnter = onlyApplyOnEnter;
this->changeFunc = changeFunc;
this->disableIfGameLoaded = disableIfGameLoaded;
}
};

View file

@ -96,6 +96,7 @@
#include "postfx.h"
#include "custompipes.h"
#include "screendroplets.h"
#include "VarConsole.h"
#ifdef USE_TEXTURE_POOL
#include "TexturePools.h"
#endif
@ -113,6 +114,10 @@ char CGame::aDatFile[32];
bool CGame::russianGame = false;
bool CGame::japaneseGame = false;
#endif
#ifndef MASTER
CVector CGame::PlayerCoords;
bool8 CGame::VarUpdatePlayerCoords;
#endif
int gameTxdSlot;
@ -557,6 +562,16 @@ bool CGame::Initialise(const char* datFile)
#ifdef USE_TEXTURE_POOL
_TexturePoolsUnknown(true);
#endif
#ifndef MASTER
PlayerCoords = FindPlayerCoors();
VarConsole.Add("X PLAYER COORD", &PlayerCoords.x, 10.0f, -10000.0f, 10000.0f, true);
VarConsole.Add("Y PLAYER COORD", &PlayerCoords.y, 10.0f, -10000.0f, 10000.0f, true);
VarConsole.Add("Z PLAYER COORD", &PlayerCoords.z, 10.0f, -10000.0f, 10000.0f, true);
VarConsole.Add("UPDATE PLAYER COORD", &VarUpdatePlayerCoords, true);
#endif
DMAudio.SetStartingTrackPositions(true);
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
return true;
@ -837,6 +852,12 @@ void CGame::Process(void)
CWindModifiers::Number = 0;
if (!CTimer::GetIsPaused())
{
#ifndef MASTER
if (VarUpdatePlayerCoords) {
FindPlayerPed()->Teleport(PlayerCoords);
VarUpdatePlayerCoords = false;
}
#endif
CSprite2d::SetRecipNearClip();
CSprite2d::InitPerFrame();
CFont::InitPerFrame();

View file

@ -48,6 +48,11 @@ public:
static bool playingIntro;
static char aDatFile[32];
#ifndef MASTER
static CVector PlayerCoords;
static bool8 VarUpdatePlayerCoords;
#endif
static bool InitialiseOnceBeforeRW(void);
static bool InitialiseRenderWare(void);
static void ShutdownRenderWare(void);

View file

@ -217,8 +217,10 @@ CMenuScreen aScreens[] = {
{ "FET_CTL", MENUPAGE_OPTIONS, 0,
#ifdef PC_PLAYER_CONTROLS
MENUACTION_CTRLMETHOD, "FET_STI", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 320, 150, MENUALIGN_CENTER,
#endif
MENUACTION_KEYBOARDCTRLS,"FEC_RED", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 0, 0, MENUALIGN_CENTER,
#else
MENUACTION_KEYBOARDCTRLS,"FEC_RED", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 320, 150, MENUALIGN_CENTER,
#endif
MENUACTION_CHANGEMENU, "FEC_MOU", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_CENTER,
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 0, 0, MENUALIGN_CENTER,
MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER,

View file

@ -24,7 +24,7 @@
#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) }, 0, 0, MENUALIGN_LEFT,
#define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, nil, screenModes, 2, true, ScreenModeAfterChange, true) }, 0, 0, MENUALIGN_LEFT,
#else
#define VIDEOMODE_SELECTOR
#endif
@ -36,19 +36,19 @@
#endif
#ifdef CUTSCENE_BORDERS_SWITCH
#define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&FrontEndMenuManager.m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false, nil) }, 0, 0, MENUALIGN_LEFT,
#define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&FrontEndMenuManager.m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#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) }, 0, 0, MENUALIGN_LEFT,
#define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "FreeCam", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#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) }, 0, 0, MENUALIGN_LEFT,
#define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "PS2AlphaTest", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#else
#define DUALPASS_SELECTOR
#endif
@ -61,14 +61,14 @@
#ifdef EXTENDED_COLOURFILTER
#define POSTFX_SELECTORS \
MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, 0, 0, MENUALIGN_LEFT, \
MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, 0, 0, MENUALIGN_LEFT,
MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false) }, 0, 0, MENUALIGN_LEFT, \
MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#else
#define POSTFX_SELECTORS
#endif
#ifdef INVERT_LOOK_FOR_PAD
#define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_ILU", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, nil, off_on, 2, false, nil) }, 150, 0, MENUALIGN_LEFT,
#define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_ILU", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, nil, off_on, 2, false) }, 150, 0, MENUALIGN_LEFT,
#else
#define INVERT_PAD_SELECTOR
#endif
@ -548,8 +548,10 @@ CMenuScreenCustom aScreens[] = {
{ "FET_CTL", MENUPAGE_OPTIONS, new CCustomScreenLayout({0, 0, MENU_DEFAULT_LINE_HEIGHT, false, false, 150}), nil,
#ifdef PC_PLAYER_CONTROLS
MENUACTION_CTRLMETHOD, "FET_STI", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 150, MENUALIGN_CENTER,
#endif
MENUACTION_KEYBOARDCTRLS,"FEC_RED", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 0, 0, MENUALIGN_CENTER,
#else
MENUACTION_KEYBOARDCTRLS,"FEC_RED", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 320, 150, MENUALIGN_CENTER,
#endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
MENUACTION_CHANGEMENU, "FEC_JOD", {nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK}, 0, 0, MENUALIGN_CENTER,
#endif

View file

@ -1692,12 +1692,11 @@ void CPad::UpdatePads(void)
bUpdate = false;
if ( bUpdate )
{
GetPad(0)->Update(0);
// GetPad(1)->Update(0); // not in VC
}
#if defined(MASTER) && !defined(XINPUT)
#ifndef MASTER
GetPad(1)->Update(1);
#else
GetPad(1)->NewState.Clear();
GetPad(1)->OldState.Clear();
#endif

View file

@ -36,6 +36,7 @@
#include "MemoryHeap.h"
#include "Font.h"
#include "Frontend.h"
#include "VarConsole.h"
//--MIAMI: file done (possibly bugs)
@ -82,6 +83,12 @@ CEntity *pIslandLODbeachEntity;
int32 islandLODmainland;
int32 islandLODbeach;
#ifndef MASTER
bool gbPrintStats;
bool gbPrintVehiclesInMemory; // TODO
bool gbPrintStreamingBuffer; // TODO
#endif
bool
CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
{
@ -237,8 +244,14 @@ CStreaming::Init2(void)
pIslandLODbeachEntity = nil;
islandLODmainland = -1;
islandLODbeach = -1;
CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland);
CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach);
CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland);
CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach);
#ifndef MASTER
VarConsole.Add("Streaming Debug", &gbPrintStats, true);
VarConsole.Add("Streaming Vehicle Debug", &gbPrintVehiclesInMemory, true);
VarConsole.Add("Printf Streaming Buffer contents", &gbPrintStreamingBuffer, true);
#endif
}
void
@ -1908,10 +1921,12 @@ CStreaming::LoadBigBuildingsWhenNeeded(void)
ISLAND_LOADING_IS(LOW)
CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition());
#ifdef NO_ISLAND_LOADING
else if(FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM) {
RemoveIslandsNotUsed(CGame::currLevel);
CStreaming::RequestIslands(CGame::currLevel);
}
#endif
CStreaming::LoadAllRequestedModels(false);

View file

@ -138,7 +138,7 @@ CSurfaceTable::GetWetMultiplier(uint8 surfaceType)
case SURFACE_SAND:
case SURFACE_SAND_BEACH:
return 1.0f - CWeather::WetRoads*0.5f;
return 1.0f + CWeather::WetRoads*0.5f;
default:
return 1.0f;

View file

@ -79,6 +79,10 @@ typedef int64_t int64;
// hardcode ucs-2
typedef uint16_t wchar;
typedef uint8 bool8;
typedef uint16 bool16;
typedef uint32 bool32;
#if defined(_MSC_VER)
typedef ptrdiff_t ssize_t;
#endif

View file

@ -338,6 +338,11 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#define USE_BASIC_SCRIPT_DEBUG_OUTPUT
#endif
#ifdef MASTER
#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT
#endif
// Replay
//#define DONT_FIX_REPLAY_BUGS // keeps various bugs in CReplay, some of which are fairly cool!
//#define USE_BETA_REPLAY_MODE // adds another replay mode, a few seconds slomo (caution: buggy!)
@ -360,6 +365,7 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
// Audio
#define AUDIO_CACHE // cache sound lengths to speed up the cold boot
//#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS
//#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder
#ifdef LIBRW

View file

@ -72,6 +72,7 @@
#include "postfx.h"
#include "custompipes.h"
#include "screendroplets.h"
#include "VarConsole.h"
GlobalScene Scene;
@ -133,6 +134,9 @@ bool gbNewRenderer;
#define CLEARMODE (rwCAMERACLEARZ)
#endif
bool bDisplayNumOfAtomicsRendered = false;
bool bDisplayPosn = false;
void
ValidateVersion()
{
@ -473,6 +477,11 @@ Initialise3D(void *param)
{
PUSH_MEMID(MEMID_RENDER);
#ifndef MASTER
VarConsole.Add("Display number of atomics rendered", &bDisplayNumOfAtomicsRendered, true);
VarConsole.Add("Display posn and framerate", &bDisplayPosn, true);
#endif
if (RsRwInitialize(param))
{
POP_MEMID();
@ -1008,7 +1017,6 @@ return;
void
DisplayGameDebugText()
{
static bool bDisplayPosn = false;
static bool bDisplayCheatStr = false; // custom
#ifndef FINAL
@ -1382,6 +1390,10 @@ RenderMenus(void)
{
FrontEndMenuManager.DrawFrontEnd();
}
#ifndef MASTER
else
VarConsole.Check();
#endif
}
void

View file

@ -225,7 +225,6 @@ void LoadINISettings()
void SaveINISettings()
{
bool changed = false;
char temp[4];
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
if (strncmp(cfg.get("DetectJoystick", "JoystickName", "").c_str(), gSelectedJoystickName, strlen(gSelectedJoystickName)) != 0) {
@ -647,7 +646,7 @@ extern bool gbRenderWorld2;
#endif
DebugMenuAddVar("Render", "Drunkness", &CMBlur::Drunkness, nil, 0.05f, 0, 1.0f);
#ifndef MASTER
DebugMenuAddVarBool8("Render", "Occlusion debug", &bDisplayOccDebugStuff, nil);
DebugMenuAddVarBool8("Render", "Occlusion debug", &bDispayOccDebugStuff, nil);
#endif
#ifdef EXTENDED_PIPELINES
static const char *vehpipenames[] = { "MatFX", "Neo" };

View file

@ -126,6 +126,7 @@ CEntity::CreateRwObject(void)
m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
mi->AddRef();
}
}
@ -139,6 +140,7 @@ CEntity::AttachToRwObject(RwObject *obj)
m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
}
}
@ -239,12 +241,8 @@ CEntity::GetBoundRadius(void)
void
CEntity::UpdateRwFrame(void)
{
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC)
RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
RwFrameUpdateObjects(RpClumpGetFrame((RpClump*)m_rwObject));
}
if(m_rwObject)
RwFrameUpdateObjects((RwFrame*)rwObjectGetParent(m_rwObject));
}
void

View file

@ -235,6 +235,7 @@ CPhysical::GetBoundRect(void)
return CRect(center.x-radius, center.y-radius, center.x+radius, center.y+radius);
}
// --MIAMI: Proof-read once
void
CPhysical::AddToMovingList(void)
{
@ -242,6 +243,7 @@ CPhysical::AddToMovingList(void)
m_movingListNode = CWorld::GetMovingEntityList().InsertItem(this);
}
// --MIAMI: Proof-read once
void
CPhysical::RemoveFromMovingList(void)
{
@ -261,12 +263,14 @@ CPhysical::SetDamagedPieceRecord(uint16 piece, float impulse, CEntity *entity, C
m_vecDamageNormal = dir;
}
// --MIAMI: Proof-read once
void
CPhysical::AddCollisionRecord(CEntity *ent)
{
AddCollisionRecord_Treadable(ent);
this->bHasCollided = true;
ent->bHasCollided = true;
this->m_nLastTimeCollided = CTimer::GetTimeInMilliseconds();
if(IsVehicle() && ent->IsVehicle()){
if(((CVehicle*)this)->m_nAlarmState == -1)
((CVehicle*)this)->m_nAlarmState = 15000;
@ -280,10 +284,10 @@ CPhysical::AddCollisionRecord(CEntity *ent)
return;
if(m_nCollisionRecords < PHYSICAL_MAX_COLLISIONRECORDS)
m_aCollisionRecords[m_nCollisionRecords++] = ent;
m_nLastTimeCollided = CTimer::GetTimeInMilliseconds();
}
}
// --MIAMI: Proof-read once
void
CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
{
@ -291,6 +295,7 @@ CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
}
}
// --MIAMI: Proof-read once
bool
CPhysical::GetHasCollidedWith(CEntity *ent)
{
@ -302,20 +307,23 @@ CPhysical::GetHasCollidedWith(CEntity *ent)
return false;
}
// --MIAMI: Proof-read once
void
CPhysical::RemoveRefsToEntity(CEntity *ent)
{
int i, j;
int i = 0, j;
for(i = 0; i < m_nCollisionRecords; i++){
while (i < m_nCollisionRecords){
if(m_aCollisionRecords[i] == ent){
for(j = i; j < m_nCollisionRecords-1; j++)
m_aCollisionRecords[j] = m_aCollisionRecords[j+1];
m_nCollisionRecords--;
}
} else
i++;
}
}
// --MIAMI: Proof-read once
void
CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos)
{
@ -332,6 +340,7 @@ CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phy
CWorld::Add(phys);
}
// --MIAMI: Proof-read once
int32
CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
{
@ -350,6 +359,7 @@ CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
return numSpheres;
}
// --MIAMI: Proof-read once
void
CPhysical::ProcessControl(void)
{
@ -417,6 +427,7 @@ CPhysical::GetSpeed(const CVector &r)
return m_vecMoveSpeed + m_vecMoveFriction + CrossProduct(m_vecTurnFriction + m_vecTurnSpeed, r);
}
// --MIAMI: Proof-read once
void
CPhysical::ApplyMoveSpeed(void)
{
@ -426,7 +437,7 @@ CPhysical::ApplyMoveSpeed(void)
GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep());
}
// --MIAMI: Proof-read once
void
CPhysical::ApplyTurnSpeed(void)
{
@ -442,12 +453,14 @@ CPhysical::ApplyTurnSpeed(void)
}
}
// --MIAMI: Proof-read once
void
CPhysical::ApplyMoveForce(float jx, float jy, float jz)
{
m_vecMoveSpeed += CVector(jx, jy, jz)*(1.0f/m_fMass);
}
// --MIAMI: Proof-read once
void
CPhysical::ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz)
{
@ -462,6 +475,7 @@ CPhysical::ApplyFrictionMoveForce(float jx, float jy, float jz)
m_vecMoveFriction += CVector(jx, jy, jz)*(1.0f/m_fMass);
}
// --MIAMI: Proof-read once
void
CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float py, float pz)
{
@ -470,6 +484,7 @@ CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float
m_vecTurnFriction += turnimpulse*(1.0f/m_fTurnMass);
}
// --MIAMI: Proof-read once
bool
CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias)
{
@ -483,6 +498,7 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &
return true;
}
// --MIAMI: Proof-read once
bool
CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)
{
@ -500,6 +516,7 @@ CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVecto
return true;
}
// --MIAMI: Proof-read once
// What exactly is speed?
bool
CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
@ -560,17 +577,16 @@ CPhysical::ApplyFriction(void)
m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);
}
// --MIAMI: Proof-read once
void
CPhysical::ApplyAirResistance(void)
{
if(m_fAirResistance > 0.1f){
if(GetStatus() != STATUS_GHOST){
float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
m_vecMoveSpeed *= f;
m_vecTurnSpeed *= f;
}
}else{
float f = Pow(1.0f/(m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr() + 1.0f), CTimer::GetTimeStep());
float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
m_vecMoveSpeed *= f;
m_vecTurnSpeed *= f;
}else if(GetStatus() != STATUS_GHOST){
float f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep());
m_vecMoveSpeed *= f;
m_vecTurnSpeed *= 0.99f;
}
@ -1015,6 +1031,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV
return false;
}
// --MIAMI: Proof-read once
bool
CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
{
@ -1044,7 +1061,11 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
impulseB = (speedSum - fOtherSpeedB) * B->m_fMass;
impulseLimit = adhesiveLimit*CTimer::GetTimeStep();
if(impulseA < -impulseLimit) impulseA = -impulseLimit;
if(impulseB > impulseLimit) impulseB = impulseLimit; // BUG: game has A's clamp again here, but this can't be right
#ifdef FIX_BUGS
if(impulseB > impulseLimit) impulseB = impulseLimit;
#else
if(impulseA < -impulseLimit) impulseA = -impulseLimit; // duplicate
#endif
A->ApplyFrictionMoveForce(frictionDir*impulseA);
B->ApplyFrictionMoveForce(frictionDir*impulseB);
return true;
@ -1139,6 +1160,7 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
return false;
}
// --MIAMI: Proof-read once
bool
CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
{
@ -1176,7 +1198,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
if(fOtherSpeed > 0.0f){
frictionDir = vOtherSpeed * (1.0f/fOtherSpeed);
fImpulse = -fOtherSpeed * m_fMass;
impulseLimit = adhesiveLimit*CTimer::GetTimeStep() * 1.5f;
impulseLimit = adhesiveLimit*CTimer::GetTimeStep() * 1.5;
if(fImpulse < -impulseLimit) fImpulse = -impulseLimit;
ApplyFrictionMoveForce(frictionDir*fImpulse);
ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos);
@ -1194,6 +1216,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
return false;
}
// --MIAMI: Proof-read once
bool
CPhysical::ProcessShiftSectorList(CPtrList *lists)
{
@ -1267,7 +1290,8 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
skipShift = true;
Aobj->m_pCollidingEntity = B;
}
}
} else
skipShift = true;
}else if(B->IsObject() && A->IsVehicle()){
CObject *Bobj = (CObject*)B;
if(Bobj->ObjectCreatedBy != TEMP_OBJECT &&
@ -1282,7 +1306,8 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
if(size.z < A->GetPosition().z ||
(Invert(A->GetMatrix(), inv) * size).z < 0.0f)
skipShift = true;
}
} else
skipShift = true;
}else if(IsBodyPart(A->GetModelIndex()) && B->IsPed())
skipShift = true;
else if(A->IsPed() && IsBodyPart(B->GetModelIndex()))
@ -1354,6 +1379,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
return true;
}
// --MIAMI: Proof-read once
bool
CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists)
{
@ -1520,6 +1546,7 @@ collision:
return true;
}
// --MIAMI: Proof-read once
bool
CPhysical::ProcessCollisionSectorList(CPtrList *lists)
{
@ -1656,8 +1683,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
return true;
if(numCollisions == 0 && A == (CEntity*)FindPlayerPed() && Aped->m_pCollidingEntity == B)
Aped->m_pCollidingEntity = nil;
}else if(B->IsBuilding() || B->bIsStuck || B->bInfiniteMass || altcollision){
}else if(B->IsBuilding() || B->bIsStuck || B->m_phy_flagA08 || altcollision){
// This is the case where B doesn't move
B->m_scanCode = CWorld::GetCurrentScanCode();
@ -1925,18 +1951,22 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
CMatrix inv;
CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = B->GetMatrix() * size;
if(size.z < B->GetPosition().z ||
if(size.z < A->GetPosition().z ||
(Invert(A->GetMatrix(), inv) * size).z < 0.0f)
Bobj->ObjectDamage(50.0f);
}
}else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){
if(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f)
Aobj->ObjectDamage(maxImpulseB);
#ifdef FIX_BUGS
else if(Aobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){
#else
else if(Bobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){
#endif
CMatrix inv;
CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = A->GetMatrix() * size;
if(size.z < A->GetPosition().z ||
if(size.z < B->GetPosition().z ||
(Invert(B->GetMatrix(), inv) * size).z < 0.0f)
Aobj->ObjectDamage(50.0f);
}
@ -1987,6 +2017,7 @@ CPhysical::CheckCollision_SimpleCar(void)
float PHYSICAL_SHIFT_SPEED_DAMP = 0.707f;
// --MIAMI: Proof-read once
void
CPhysical::ProcessShift(void)
{
@ -1997,8 +2028,8 @@ CPhysical::ProcessShift(void)
RemoveAndAdd();
}else{
CPhysical *surf;
if(bHasHitWall && IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) ||
CWorld::bSecondShift){
if(bHasHitWall && (IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) ||
CWorld::bSecondShift)){
m_vecMoveSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());
m_vecTurnSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());
}

View file

@ -111,7 +111,7 @@ void FrontendOptionAddBuiltinAction(const char* gxtKey, uint16 x, uint16 y, uint
option.m_TargetMenu = targetMenu;
}
void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName)
void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName, bool disableIfGameLoaded)
{
int8 screenOptionOrder = RegisterNewOption();
@ -133,6 +133,7 @@ void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align
option.m_CFOSelect->save = saveName;
option.m_CFOSelect->onlyApplyOnEnter = onlyApplyOnEnter;
option.m_CFOSelect->changeFunc = changeFunc;
option.m_CFOSelect->disableIfGameLoaded = disableIfGameLoaded;
}
void FrontendOptionAddDynamic(const char* gxtKey, uint16 x, uint16 y, uint8 align, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName)

View file

@ -78,7 +78,7 @@ 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 char* gxtKey, uint16 x, uint16 y, uint8 align, int action, int targetMenu = MENUPAGE_NONE, int saveSlot = SAVESLOT_NONE);
void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName = nil);
void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName = nil, bool disableIfGameLoaded = false);
void FrontendOptionAddDynamic(const char* gxtKey, uint16 x, uint16 y, uint8 align, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName = nil);
// lineHeight = 0 means game will use MENU_DEFAULT_LINE_HEIGHT

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com>
* Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages

View file

@ -391,7 +391,7 @@ void
ScreenDroplets::RegisterSplash(CParticleObject *pobj)
{
CVector dist = pobj->GetPosition() - ms_prevCamPos;
if(dist.MagnitudeSqr() < 20.0f){
if(dist.MagnitudeSqr() < 50.0f){ // 20 originally
ms_splashDuration = 14;
ms_splashObject = pobj;
}

View file

@ -14,6 +14,7 @@
using namespace rw;
RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; }
RwFrame* rwObjectGetParent(const RwObject *obj) { return (RwFrame*)obj->parent; }
void *RwMalloc(size_t size) { return engine->memfuncs.rwmalloc(size, 0); }

View file

@ -108,12 +108,12 @@ enum RwCorePluginID
//struct RwObject;
typedef rw::Object RwObject;
typedef rw::Frame RwFrame;
typedef RwObject *(*RwObjectCallBack)(RwObject *object, void *data);
RwUInt8 RwObjectGetType(const RwObject *obj);
RwFrame* rwObjectGetParent(const RwObject *obj);
#define rwsprintf sprintf
#define rwvsprintf vsprintf

View file

@ -1003,7 +1003,7 @@ public:
// My names. Inlined in VC
AnimationId GetFireAnimNotDucking(CWeaponInfo* weapon) {
if (m_nPedType == PEDTYPE_COP && weapon->IsFlagSet(WEAPONFLAG_COP3_RD))
return ANIM_WEAPON_FIRE_3RD;
return Get3rdFireAnim(weapon);
else
return GetPrimaryFireAnim(weapon);
}

View file

@ -924,10 +924,10 @@ CPed::ProcessObjective(void)
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_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity);
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_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity * 0.8f;
m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
}
m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
@ -1921,7 +1921,7 @@ CPed::ProcessObjective(void)
ClearObjective();
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->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity;
m_pMyVehicle->SetStatus(STATUS_PHYSICS);
} else {
SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
@ -2147,10 +2147,10 @@ CPed::SelectGunIfArmed(void)
if (GetWeapon(i).m_nAmmoTotal > 0) {
eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
if (weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||
if (weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_MP5 || weaponType == WEAPONTYPE_M4 ||
weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||
weaponType == WEAPONTYPE_SPAS12_SHOTGUN || weaponType == WEAPONTYPE_STUBBY_SHOTGUN ||
weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M4 || weaponType == WEAPONTYPE_MP5 ||
weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_SNIPERRIFLE) {
weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_FLAMETHROWER) {
SetCurrentWeapon(i);
return true;
}
@ -2269,7 +2269,7 @@ CPed::ReactToAttack(CEntity *attacker)
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->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity;
m_pMyVehicle->SetStatus(STATUS_PHYSICS);
}
@ -5458,7 +5458,7 @@ CPed::RegisterThreatWithGangPeds(CEntity *attacker)
if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType && nearVehDriver->CharCreatedBy == RANDOM_CHAR) {
if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fMaxCruiseVelocity * 0.8f;
nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
nearVeh->SetStatus(STATUS_PHYSICS);
nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;

View file

@ -661,9 +661,7 @@ CPed::Attack(void)
{
CAnimBlendAssociation *weaponAnimAssoc;
int32 weaponAnim;
eWeaponType ourWeaponType;
float weaponAnimTime;
eWeaponFire ourWeaponFire;
float animLoopEnd;
CWeaponInfo *ourWeapon;
bool attackShouldContinue;
@ -673,9 +671,7 @@ CPed::Attack(void)
float animLoopStart;
CVector firePos;
ourWeaponType = GetWeapon()->m_eWeaponType;
ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
ourWeaponFire = ourWeapon->m_eWeaponFire;
ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
weaponAnimAssoc = nil;
attackShouldContinue = !!bIsAttacking;
reloadAnimAssoc = nil;
@ -694,14 +690,15 @@ CPed::Attack(void)
delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
}
}
} else {
AnimationId anim = GetFireAnimNotDucking(ourWeapon);
weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), anim);
if (anim == ANIM_WEAPON_FIRE_3RD && weaponAnimAssoc) {
} else if (m_nPedType == PEDTYPE_COP && Get3rdFireAnim(ourWeapon)){
weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), Get3rdFireAnim(ourWeapon));
if (weaponAnimAssoc) {
animLoopStart = 11.f/30.f;
animLoopEnd = 19.f/30.f;
delayBetweenAnimAndFire = 14.f/30.f;
}
} else {
weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(ourWeapon));
}
if (GetReloadAnim(ourWeapon)) {
@ -778,15 +775,15 @@ CPed::Attack(void)
if (!weaponAnimAssoc) {
if (!throwAssoc) {
if (attackShouldContinue) {
if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
if (ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(ourWeapon)) {
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f);
} else if(GetSecondFireAnim(ourWeapon) && CGeneral::GetRandomNumber() & 1){
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f);
} else if(!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE ||
GetFireAnimGround(ourWeapon) ||
} else if(!CGame::nastyGame || ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE ||
!GetFireAnimGround(ourWeapon, false) ||
CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimNotDucking(ourWeapon), 8.0f);
@ -831,11 +828,11 @@ CPed::Attack(void)
m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
if (ourWeaponType != WEAPONTYPE_CHAINSAW
if (GetWeapon()->m_eWeaponType != WEAPONTYPE_CHAINSAW
|| !meleeAttackStarted && delayBetweenAnimAndFire - 0.5f >= weaponAnimAssoc->currentTime
|| weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire) {
if (ourWeaponType == WEAPONTYPE_CHAINSAW) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW) {
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_ATTACK, 0.0f);
} else if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
if (weaponAnimAssoc->speed < 1.0f)
@ -859,11 +856,11 @@ CPed::Attack(void)
GetWeapon()->Fire(this, &firePos);
if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE ||
ourWeaponType == WEAPONTYPE_TEARGAS) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_MOLOTOV || GetWeapon()->m_eWeaponType == WEAPONTYPE_GRENADE || GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE ||
GetWeapon()->m_eWeaponType == WEAPONTYPE_TEARGAS) {
RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nModelId);
}
if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
if (GetWeapon()->m_nAmmoTotal == 0 && ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
SelectGunIfArmed();
}
@ -875,13 +872,13 @@ CPed::Attack(void)
switch (ourWeapon->m_AnimToPlay) {
case ASSOCGRP_UNARMED:
if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START)
DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, (damagerType | (ourWeaponType << 8)));
DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, (damagerType | (GetWeapon()->m_eWeaponType << 8)));
break;
case ASSOCGRP_KNIFE:
case ASSOCGRP_BASEBALLBAT:
case ASSOCGRP_GOLFCLUB:
case ASSOCGRP_CHAINSAW:
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (ourWeaponType << 8)));
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (GetWeapon()->m_eWeaponType << 8)));
break;
default:
break;
@ -944,14 +941,13 @@ CPed::Attack(void)
}
if (IsPlayer()) {
eWeaponType weaponType = GetWeapon()->m_eWeaponType;
if (weaponType == WEAPONTYPE_BASEBALLBAT || weaponType == WEAPONTYPE_GOLFCLUB || weaponType == WEAPONTYPE_KATANA) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT || GetWeapon()->m_eWeaponType == WEAPONTYPE_GOLFCLUB || GetWeapon()->m_eWeaponType == WEAPONTYPE_KATANA) {
float loopEndWithDelay = animLoopEnd;
if (loopEndWithDelay >= 98.0f)
loopEndWithDelay = (14.0f / 30.0f) + delayBetweenAnimAndFire;
if (weaponAnimAssoc->flags & ASSOC_RUNNING) {
if (weaponAnimAssoc->currentTime >= animLoopStart && weaponAnimAssoc->currentTime <= loopEndWithDelay)
CSpecialFX::AddWeaponStreak(weaponType);
CSpecialFX::AddWeaponStreak(GetWeapon()->m_eWeaponType);
}
}
}
@ -970,7 +966,7 @@ CPed::Attack(void)
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 > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE) {
if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING) {
if (GetReloadAnim(ourWeapon) && !reloadAnimAssoc) {
if (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) {
@ -997,7 +993,7 @@ CPed::Attack(void)
PedOnGroundState pedOnGroundState;
if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE &&
(CGame::nastyGame && ((pedOnGroundState = CheckForPedsOnGroundToAttack(this, nil)) > PED_IN_FRONT_OF_ATTACKER)
|| ourWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {
|| GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {
AnimationId fireAnim = GetFireAnimGround(ourWeapon, false);
if (weaponAnimAssoc->animId == fireAnim)
@ -1030,10 +1026,10 @@ CPed::Attack(void)
// Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < animLoopEnd)
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, ourWeaponType);
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);
// Fun fact: removing this part leds to reloading flamethrower
if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
weaponAnimAssoc->blendDelta = -4.0f;
@ -2021,9 +2017,9 @@ CPed::PlayHitSound(CPed *hitTo)
if (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE) {
if (m_curFightMove >= FIGHTMOVE_MELEE1) {
if (m_curFightMove == FIGHTMOVE_MELEE3) {
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | 3);
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);
} else {
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | 3);
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);
}
return;
}
@ -2048,7 +2044,7 @@ CPed::PlayHitSound(CPed *hitTo)
}
if (soundId != NO_SND)
DMAudio.PlayOneShot(m_audioEntityId, soundId, (weapon << 8) | 3);
DMAudio.PlayOneShot(m_audioEntityId, soundId, (weapon << 8) | ENTITY_TYPE_PED);
}
// --MIAMI: Done
@ -3567,7 +3563,7 @@ CPed::CollideWithPed(CPed *collideWith)
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
if (m_nPedState == PED_ATTACK)
DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, 0.0f);
DMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);
}
} else {
// We're at his right side
@ -3985,7 +3981,7 @@ CPed::DriveVehicle(void)
}
if (neededAngForWheelie >= 0.15f) {
if (bike->m_fBrakePedal <= 0.5f || velocityFwdDotProd <= 0.01f) {
if (bike->m_fGasPedal > 0.5f && targetUDLean <= 0.0f && 0.3f * bike->pHandling->Transmission.fUnkMaxVelocity > velocityFwdDotProd) {
if (bike->m_fGasPedal > 0.5f && targetUDLean <= 0.0f && 0.3f * bike->pHandling->Transmission.fMaxCruiseVelocity > velocityFwdDotProd) {
targetUDLean = Min(0.1f, targetUDLean);
}
} else {

View file

@ -22,10 +22,14 @@
#include "Script.h"
#include "Replay.h"
#include "PedPlacement.h"
#include "VarConsole.h"
#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f
bool CPlayerPed::bDontAllowWeaponChange;
#ifndef MASTER
bool CPlayerPed::bDebugPlayerInfo;
#endif
const uint32 CPlayerPed::nSaveStructSize =
#ifdef COMPATIBLE_SAVES
@ -61,7 +65,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
m_pWanted->Initialise();
m_pArrestingCop = nil;
m_currentWeapon = WEAPONTYPE_UNARMED;
m_nSelectedWepSlot = 0;
m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
m_nSpeedTimer = 0;
m_bSpeedTimerFlag = false;
SetWeaponLockOnTarget(nil);
@ -182,6 +186,11 @@ CPlayerPed::SetupPlayerPed(int32 index)
CWorld::Add(player);
player->m_wepAccuracy = 100;
#ifndef MASTER
VarConsole.Add("Debug PlayerPed", &CPlayerPed::bDebugPlayerInfo, true);
VarConsole.Add("Tweak Vehicle Handling", &CVehicle::m_bDisplayHandlingInfo, true);
#endif
}
// --MIAMI: Done
@ -300,7 +309,7 @@ CPlayerPed::SetInitialState(void)
m_nLastPedState = PED_NONE;
m_animGroup = ASSOCGRP_PLAYER;
m_fMoveSpeed = 0.0f;
m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
m_nEvadeAmount = 0;
m_pEvadingFrom = nil;
bIsPedDieAnimPlaying = false;
@ -748,17 +757,20 @@ CPlayerPed::ProcessWeaponSwitch(CPad *padUsed)
&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER
&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_CAMERA) {
for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) {
// I don't know what kind of loop that was
m_nSelectedWepSlot = m_currentWeapon - 1;
do {
if (m_nSelectedWepSlot < 0)
m_nSelectedWepSlot = TOTAL_WEAPON_SLOTS - 1;
if (m_nSelectedWepSlot == 0)
if (m_nSelectedWepSlot == WEAPONSLOT_UNARMED)
break;
if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed())
break;
}
}
--m_nSelectedWepSlot;
} while (m_nSelectedWepSlot != WEAPONSLOT_UNARMED);
}
}
}
@ -772,17 +784,17 @@ spentAmmoCheck:
|| TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)
return;
if (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR
|| GetWeapon(2).m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE)
m_nSelectedWepSlot = m_currentWeapon - 1;
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR
&& GetWeapon(WEAPONSLOT_PROJECTILE).m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE)
m_nSelectedWepSlot = WEAPONSLOT_PROJECTILE;
else
m_nSelectedWepSlot = 2;
m_nSelectedWepSlot = m_currentWeapon - 1;
for (; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) {
for (; m_nSelectedWepSlot >= WEAPONSLOT_UNARMED; --m_nSelectedWepSlot) {
// BUG: m_nSelectedWepSlot and GetWeapon(..) takes slot in VC but they compared them against weapon types in whole condition! jeez
#ifdef FIX_BUGS
if (m_nSelectedWepSlot == 1 || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != 2) {
if (m_nSelectedWepSlot == WEAPONSLOT_MELEE || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONSLOT_PROJECTILE) {
#else
if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(WEAPONTYPE_BASEBALLBAT).m_eWeaponType == WEAPONTYPE_BASEBALLBAT
|| GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0
@ -791,15 +803,16 @@ spentAmmoCheck:
goto switchDetectDone;
}
}
m_nSelectedWepSlot = 0;
m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
}
}
switchDetectDone:
if (m_nSelectedWepSlot != m_currentWeapon) {
if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT)
if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT) {
RemoveWeaponAnims(m_currentWeapon, -1000.0f);
MakeChangesForNewWeapon(m_nSelectedWepSlot);
}
}
}
@ -1775,7 +1788,7 @@ CPlayerPed::ProcessControl(void)
if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK) && !m_attachedTo) {
if (TheCamera.Using1stPersonWeaponMode()) {
if (padUsed)
PlayerControlFighter(padUsed);
PlayerControlSniper(padUsed);
} else if (TheCamera.Cams[0].Using3rdPersonMouseCam()
#ifdef FREE_CAM

View file

@ -15,7 +15,7 @@ public:
float m_fCurrentStamina;
float m_fMaxStamina;
float m_fStaminaProgress;
int8 m_nSelectedWepSlot; // eWeaponType
int8 m_nSelectedWepSlot;
bool m_bSpeedTimerFlag;
uint8 m_nEvadeAmount;
uint32 m_nSpeedTimer; // m_nStandStillTimer?
@ -46,6 +46,9 @@ public:
unsigned int m_nLastBusFareCollected;
static bool bDontAllowWeaponChange;
#ifndef MASTER
static bool bDebugPlayerInfo;
#endif
CPlayerPed();
~CPlayerPed();

View file

@ -297,12 +297,10 @@ CFont::Initialise(void)
CTxdStore::AddRef(ButtonsSlot);
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(ButtonsSlot);
#if 0 // unused
ButtonSprite[BUTTON_UP].SetTexture("up");
ButtonSprite[BUTTON_DOWN].SetTexture("down");
ButtonSprite[BUTTON_LEFT].SetTexture("left");
ButtonSprite[BUTTON_RIGHT].SetTexture("right");
#endif
ButtonSprite[BUTTON_UP].SetTexture("thumblyu");
ButtonSprite[BUTTON_DOWN].SetTexture("thumblyd");
ButtonSprite[BUTTON_LEFT].SetTexture("thumblxl");
ButtonSprite[BUTTON_RIGHT].SetTexture("thumblxr");
ButtonSprite[BUTTON_CROSS].SetTexture("cross");
ButtonSprite[BUTTON_CIRCLE].SetTexture("circle");
ButtonSprite[BUTTON_SQUARE].SetTexture("square");
@ -313,6 +311,8 @@ CFont::Initialise(void)
ButtonSprite[BUTTON_R1].SetTexture("r1");
ButtonSprite[BUTTON_R2].SetTexture("r2");
ButtonSprite[BUTTON_R3].SetTexture("r3");
ButtonSprite[BUTTON_RSTICK_LEFT].SetTexture("thumbrxl");
ButtonSprite[BUTTON_RSTICK_RIGHT].SetTexture("thumbrxr");
CTxdStore::PopCurrentTxd();
}
#endif // BUTTON_ICONS
@ -411,9 +411,12 @@ CFont::DrawButton(float x, float y)
rect.bottom = Details.scaleY * 19.0f + y;
int vertexAlphaState;
void *raster;
RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState);
RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, Details.color.a));
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState);
}
}
@ -926,14 +929,6 @@ CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, f
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
@ -1132,12 +1127,10 @@ CFont::GetStringWidth(wchar *s, bool spaces)
s++;
#ifdef BUTTON_ICONS
switch (*s) {
#if 0 // unused
case 'U':
case 'D':
case '<':
case '>':
#endif
case 'X':
case 'O':
case 'Q':
@ -1148,6 +1141,8 @@ CFont::GetStringWidth(wchar *s, bool spaces)
case 'J':
case 'V':
case 'C':
case '(':
case ')':
w += 17.0f * Details.scaleY;
break;
default:
@ -1170,12 +1165,10 @@ CFont::GetStringWidth(wchar *s, bool spaces)
s++;
#ifdef BUTTON_ICONS
switch (*s) {
#if 0 // unused
case 'U':
case 'D':
case '<':
case '>':
#endif
case 'X':
case 'O':
case 'Q':
@ -1186,6 +1179,8 @@ CFont::GetStringWidth(wchar *s, bool spaces)
case 'J':
case 'V':
case 'C':
case '(':
case ')':
w += 17.0f * Details.scaleY;
break;
default:
@ -1280,12 +1275,10 @@ CFont::ParseToken(wchar *s, bool japShit)
case 'w': SetColor(CRGBA(175, 175, 175, 255)); break;
case 'y': SetColor(CRGBA(210, 196, 106, 255)); break;
#ifdef BUTTON_ICONS
#if 0 // unused
case 'U': PS2Symbol = BUTTON_UP; break;
case 'D': PS2Symbol = BUTTON_DOWN; break;
case '<': PS2Symbol = BUTTON_LEFT; break;
case '>': PS2Symbol = BUTTON_RIGHT; break;
#endif
case 'X': PS2Symbol = BUTTON_CROSS; break;
case 'O': PS2Symbol = BUTTON_CIRCLE; break;
case 'Q': PS2Symbol = BUTTON_SQUARE; break;
@ -1296,6 +1289,8 @@ CFont::ParseToken(wchar *s, bool japShit)
case 'J': PS2Symbol = BUTTON_R1; break;
case 'V': PS2Symbol = BUTTON_R2; break;
case 'C': PS2Symbol = BUTTON_R3; break;
case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;
case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;
#endif
}
} else if (IsJapanese()) {
@ -1342,12 +1337,10 @@ CFont::ParseToken(wchar *s)
#endif
case 'y': SetColor(CRGBA(255, 227, 79, 255)); Details.anonymous_23 = true; break;
#ifdef BUTTON_ICONS
#if 0 // unused
case 'U': PS2Symbol = BUTTON_UP; break;
case 'D': PS2Symbol = BUTTON_DOWN; break;
case '<': PS2Symbol = BUTTON_LEFT; break;
case '>': PS2Symbol = BUTTON_RIGHT; break;
#endif
case 'X': PS2Symbol = BUTTON_CROSS; break;
case 'O': PS2Symbol = BUTTON_CIRCLE; break;
case 'Q': PS2Symbol = BUTTON_SQUARE; break;
@ -1358,6 +1351,8 @@ CFont::ParseToken(wchar *s)
case 'J': PS2Symbol = BUTTON_R1; break;
case 'V': PS2Symbol = BUTTON_R2; break;
case 'C': PS2Symbol = BUTTON_R3; break;
case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;
case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;
#endif
}
while(*s != '~') s++;
@ -1450,6 +1445,24 @@ CFont::ParseToken(wchar* str, CRGBA &color, bool &flash, bool &bold)
color.g = 227;
color.b = 79;
break;
#ifdef BUTTON_ICONS
case 'U': PS2Symbol = BUTTON_UP; break;
case 'D': PS2Symbol = BUTTON_DOWN; break;
case '<': PS2Symbol = BUTTON_LEFT; break;
case '>': PS2Symbol = BUTTON_RIGHT; break;
case 'X': PS2Symbol = BUTTON_CROSS; break;
case 'O': PS2Symbol = BUTTON_CIRCLE; break;
case 'Q': PS2Symbol = BUTTON_SQUARE; break;
case 'T': PS2Symbol = BUTTON_TRIANGLE; break;
case 'K': PS2Symbol = BUTTON_L1; break;
case 'M': PS2Symbol = BUTTON_L2; break;
case 'A': PS2Symbol = BUTTON_L3; break;
case 'J': PS2Symbol = BUTTON_R1; break;
case 'V': PS2Symbol = BUTTON_R2; break;
case 'C': PS2Symbol = BUTTON_R3; break;
case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;
case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;
#endif
default:
break;
}
@ -1503,7 +1516,17 @@ CFont::RenderFontBuffer()
color = RenderState.color;
}
if (*pRenderStateBufPointer.pStr == '~') {
#ifdef BUTTON_ICONS
PS2Symbol = BUTTON_NONE;
#endif
pRenderStateBufPointer.pStr = ParseToken(pRenderStateBufPointer.pStr, color, bFlash, bBold);
#ifdef BUTTON_ICONS
if(PS2Symbol != BUTTON_NONE) {
DrawButton(textPosX, textPosY);
textPosX += Details.scaleY * 17.0f;
PS2Symbol = BUTTON_NONE;
}
#endif
if (bFlash) {
if (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) {
Details.bFlashState = !Details.bFlashState;

View file

@ -95,12 +95,10 @@ enum
enum
{
BUTTON_NONE = -1,
#if 0 // unused
BUTTON_UP,
BUTTON_DOWN,
BUTTON_LEFT,
BUTTON_RIGHT,
#endif
BUTTON_CROSS,
BUTTON_CIRCLE,
BUTTON_SQUARE,
@ -111,6 +109,8 @@ enum
BUTTON_R1,
BUTTON_R2,
BUTTON_R3,
BUTTON_RSTICK_LEFT,
BUTTON_RSTICK_RIGHT,
MAX_BUTTON_ICONS
};
#endif // BUTTON_ICONS

View file

@ -24,6 +24,7 @@
#include "Stats.h"
#include "main.h"
#include "General.h"
#include "VarConsole.h"
// --MIAMI: file done
@ -1119,7 +1120,7 @@ void CHud::Draw()
CFont::SetPropOff();
CFont::SetFontStyle(FONT_LOCALE(CTheScripts::IntroTextLines[i].m_nFont));
CFont::PrintString(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text);
CFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text);
}
}
for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) {
@ -1461,7 +1462,7 @@ void CHud::DrawAfterFade()
CFont::SetPropOff();
CFont::SetFontStyle(line.m_nFont);
CFont::PrintString(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text);
CFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text);
}
}
for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) {
@ -1760,6 +1761,9 @@ void CHud::Initialise()
m_LastWanted = 0;
m_LastWeapon = 0;
#ifndef MASTER
VarConsole.Add("Draw HUD", &m_Wants_To_Draw_Hud, false);
#endif
CTxdStore::PopCurrentTxd();
}

View file

@ -9,6 +9,7 @@
#include "Draw.h"
#include "Timer.h"
#include "RwHelper.h"
#include "VarConsole.h"
int32 COcclusion::NumOccludersOnMap;
int16 COcclusion::FarAwayList;
@ -31,20 +32,20 @@ CVector gOccluderCoorsOnScreen[8];
CVector gOccluderCoors[8];
#ifndef MASTER
bool bDisplayOccDebugStuff;
bool bDispayOccDebugStuff; // disPAY, yeah
#endif
void
COcclusion::Init(void)
{
NumOccludersOnMap = 0;
#ifndef MASTER
VarConsole.Add("Occlusion debug", &bDispayOccDebugStuff, true);
#endif
FarAwayList = -1;
NearbyList = -1;
ListWalkThroughFA = -1;
PreviousListWalkThroughFA = -1;
#ifndef MASTER
bDisplayOccDebugStuff = false;
#endif
}
void
@ -458,7 +459,7 @@ bool COcclusion::IsPositionOccluded(CVector pos, float side) {
RwIm2DVertex vertexbufferT[2];
void COcclusion::Render() {
if (!bDisplayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200))
if (!bDispayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200))
return;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);

View file

@ -58,5 +58,5 @@ bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh);
bool CalcScreenCoors(CVector const &in, CVector *out);
#ifndef MASTER
extern bool bDisplayOccDebugStuff;
extern bool bDispayOccDebugStuff;
#endif

View file

@ -25,6 +25,7 @@
#include "CutsceneObject.h"
#include "CutsceneShadow.h"
#include "Clock.h"
#include "VarConsole.h"
#ifdef DEBUGMENU
SETTWEAKPATH("Shadows");
@ -57,6 +58,9 @@ CStaticShadow CShadows::aStaticShadows [MAX_STATICSHADOWS];
CPolyBunch *CShadows::pEmptyBunchList;
CPermanentShadow CShadows::aPermanentShadows[MAX_PERMAMENTSHADOWS];
#ifndef MASTER
bool gbCountPolysInShadow;
#endif
void
CShadows::Init(void)
@ -154,6 +158,10 @@ CShadows::Init(void)
{
aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
}
#ifndef MASTER
VarConsole.Add("Count polys in shadow", &gbCountPolysInShadow, true);
#endif
}
void

786
src/render/VarConsole.cpp Normal file
View file

@ -0,0 +1,786 @@
#include "common.h"
#include "VarConsole.h"
#include "Font.h"
#include "Pad.h"
#define VAR_CONSOLE_PAD 1
CVarConsole VarConsole;
void
CVarConsole::Initialise()
{
m_nCountEntries = 0;
m_nCurPage = 1;
m_bIsOpen = false;
m_nCurEntry = 0;
m_nFirstEntryOnPage = 0;
}
void
CVarConsole::Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt8Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT8;
m_aEntries[i].I8_step = step;
m_aEntries[i].I8_min = min;
m_aEntries[i].I8_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt16Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT16;
m_aEntries[i].I16_step = step;
m_aEntries[i].I16_min = min;
m_aEntries[i].I16_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt32Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT32;
m_aEntries[i].I32_step = step;
m_aEntries[i].I32_min = min;
m_aEntries[i].I32_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pInt64Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_INT64;
m_aEntries[i].I64_step = step;
m_aEntries[i].I64_min = min;
m_aEntries[i].I64_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint8Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT8;
m_aEntries[i].I8_step = step;
m_aEntries[i].I8_min = min;
m_aEntries[i].I8_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint16Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT16;
m_aEntries[i].I16_step = step;
m_aEntries[i].I16_min = min;
m_aEntries[i].I16_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint32Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT32;
m_aEntries[i].I32_step = step;
m_aEntries[i].I32_min = min;
m_aEntries[i].I32_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint64Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_UINT64;
m_aEntries[i].I64_step = step;
m_aEntries[i].I64_min = min;
m_aEntries[i].I64_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, float *pVal, float step, float min, float max, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pFloatValue = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_FLOAT;
m_aEntries[i].F_step = step;
m_aEntries[i].F_min = min;
m_aEntries[i].F_max = max;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pBoolValue = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool8 *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint8Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL8;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool16 *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint16Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL16;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, bool32 *pVal, bool8 isVar)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pUint32Value = pVal;
m_aEntries[i].bAllowExceedBounds = isVar;
m_aEntries[i].VarType = VCE_TYPE_BOOL32;
m_nCountEntries++;
}
void
CVarConsole::Add(char *text, void (*pCallback)(void))
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
return;
}
m_aEntries[i].text = text;
m_aEntries[i].pCallback = pCallback;
m_aEntries[i].VarType = VCE_TYPE_FUNCTION;
m_nCountEntries++;
}
void
CVarConsole::Remove(char *text)
{
int i;
for (i = 0; i < m_nCountEntries; i++) {
if (m_aEntries[i].text == text)
{
for (int j = i; j < m_nCountEntries-1; j++)
m_aEntries[j] = m_aEntries[j+1];
m_nCountEntries--;
return;
}
}
}
void
CVarConsole::SortPages()
{
m_nNumPages = m_nCountEntries / 30 + 1;
}
void
CVarConsole::Display()
{
char s[256];
wchar ws[256];
CFont::SetColor(CRGBA(200, 200, 200, 255));
CFont::SetFontStyle(FONT_STANDARD);
CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.6f));
CFont::SetDropShadowPosition(2);
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetPropOn();
CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
CFont::SetRightJustifyWrap(0.0f);
sprintf(s, "PAGE %d", m_nCurPage);
AsciiToUnicode(s, ws);
CFont::SetRightJustifyOn();
CFont::PrintString(SCREEN_SCALE_X(310.0f), SCREEN_SCALE_Y(30.0f), ws);
CFont::SetRightJustifyOff();
int y = 45;
for (int i = m_nFirstEntryOnPage; i < m_nCountEntries && i < m_nFirstEntryOnPage + 30; i++)
{
switch (m_aEntries[i].VarType)
{
case VCE_TYPE_INT8:
sprintf(s, "(%d) %s:I8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt8Value);
break;
case VCE_TYPE_INT16:
sprintf(s, "(%d) %s:I16:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt16Value);
break;
case VCE_TYPE_INT32:
sprintf(s, "(%d) %s:I32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt32Value);
break;
case VCE_TYPE_INT64:
#ifdef FIX_BUGS
sprintf(s, "(%d) %s:I64:%lld", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt64Value);
#else
sprintf(s, "(%d) %s:I64:%d", i + 1, m_aEntries[i].text, (int32)*m_aEntries[i].pInt64Value);
#endif
break;
case VCE_TYPE_UINT8:
sprintf(s, "(%d) %s:U8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint8Value);
break;
case VCE_TYPE_UINT16:
sprintf(s, "(%d) %s:U6:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint16Value);
break;
case VCE_TYPE_UINT32:
sprintf(s, "(%d) %s:U32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint32Value);
break;
case VCE_TYPE_UINT64:
#ifdef FIX_BUGS
sprintf(s, "(%d) %s:U64:%llu", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint64Value);
#else
sprintf(s, "(%d) %s:U64:%d", i + 1, m_aEntries[i].text, (uint32)*m_aEntries[i].pUint64Value);
#endif
break;
case VCE_TYPE_FLOAT:
sprintf(s, "(%d) %s:F:%f", i + 1, m_aEntries[i].text, *m_aEntries[i].pFloatValue);
break;
case VCE_TYPE_BOOL:
if (*m_aEntries[i].pBoolValue)
sprintf(s, "(%d) %s:B:TRUE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B : FALSE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_BOOL8:
if (*m_aEntries[i].pUint8Value == FALSE)
sprintf(s, "(%d) %s:B8:FALSE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B8:TRUE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_BOOL16:
if (*m_aEntries[i].pUint16Value == FALSE)
sprintf(s, "(%d) %s:B16:FALSE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B16:TRUE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_BOOL32:
if (*m_aEntries[i].pUint32Value == FALSE)
sprintf(s, "(%d) %s:B32:FALSE", i + 1, m_aEntries[i].text);
else
sprintf(s, "(%d) %s:B32:TRUE", i + 1, m_aEntries[i].text);
break;
case VCE_TYPE_FUNCTION:
sprintf(s, "(%d) %s:FUNCTION:call this function?", i + 1, m_aEntries[i].text);
break;
}
AsciiToUnicode(s, ws);
if (m_nCurEntry == i) {
CFont::SetBackgroundOn();
#ifdef FIX_BUGS
CFont::SetBackgroundColor(CRGBA(128, 128, 128, 128));
#endif
}
#ifdef FIX_BUGS
else
CFont::SetBackgroundColor(CRGBA(128, 128, 128, 0));
#endif
CFont::SetColor(CRGBA(200, 200, 200, 255));
CFont::PrintString(SCREEN_SCALE_X(30.0f), SCREEN_SCALE_Y(y), ws);
if (m_nCurEntry == i)
CFont::SetBackgroundOff();
y += 12;
}
}
void
CVarConsole::ModifyLeft()
{
CVarConsoleEntry &entry = m_aEntries[m_nCurEntry];
switch (entry.VarType)
{
case VCE_TYPE_INT8:
*entry.pInt8Value -= entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt8Value < entry.I8_min)
*entry.pInt8Value = entry.I8_max;
} else {
if (*entry.pInt8Value < entry.I8_min)
*entry.pInt8Value = entry.I8_min;
}
break;
case VCE_TYPE_INT16:
*entry.pInt16Value -= entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt16Value < entry.I16_min)
*entry.pInt16Value = entry.I16_max;
}
else {
if (*entry.pInt16Value < entry.I16_min)
*entry.pInt16Value = entry.I16_min;
}
break;
case VCE_TYPE_INT32:
*entry.pInt32Value -= entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt32Value < entry.I32_min)
*entry.pInt32Value = entry.I32_max;
}
else {
if (*entry.pInt32Value < entry.I32_min)
*entry.pInt32Value = entry.I32_min;
}
break;
case VCE_TYPE_INT64:
*entry.pInt64Value -= entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt64Value < entry.I64_min)
*entry.pInt64Value = entry.I64_max;
}
else {
if (*entry.pInt64Value < entry.I64_min)
*entry.pInt64Value = entry.I64_min;
}
break;
case VCE_TYPE_UINT8:
*entry.pUint8Value -= entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*(int8*)entry.pUint8Value < entry.I8_min)
*entry.pUint8Value = entry.I8_max;
}
else {
if (*(int8*)entry.pUint8Value < entry.I8_min)
*entry.pUint8Value = entry.I8_min;
}
break;
case VCE_TYPE_UINT16:
*entry.pUint16Value -= entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*(int16*)entry.pUint16Value < entry.I16_min)
*entry.pUint16Value = entry.I16_max;
}
else {
if (*(int16*)entry.pUint16Value < entry.I16_min)
*entry.pUint16Value = entry.I16_min;
}
break;
case VCE_TYPE_UINT32:
*entry.pUint32Value -= entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*(int32*)entry.pUint32Value < entry.I32_min)
*entry.pUint32Value = entry.I32_max;
}
else {
if (*(int32*)entry.pUint32Value < entry.I32_min)
*entry.pUint32Value = entry.I32_min;
}
break;
case VCE_TYPE_UINT64:
*entry.pUint64Value -= entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*(int64*)entry.pUint64Value < entry.I64_min)
*entry.pUint64Value = entry.I64_max;
}
else {
if (*(int64*)entry.pUint64Value < entry.I64_min)
*entry.pUint64Value = entry.I64_min;
}
break;
case VCE_TYPE_FLOAT:
*entry.pFloatValue -= entry.F_step;
if (entry.bAllowExceedBounds) {
if (*entry.pFloatValue < entry.F_min)
*entry.pFloatValue = entry.F_max;
}
else {
if (*entry.pFloatValue < entry.F_min)
*entry.pFloatValue = entry.F_min;
}
break;
case VCE_TYPE_BOOL:
if (entry.bAllowExceedBounds)
*entry.pBoolValue ^= true;
else
*entry.pBoolValue = false;
break;
case VCE_TYPE_BOOL8:
if (entry.bAllowExceedBounds)
*entry.pUint8Value = *entry.pUint8Value == false;
else
*entry.pUint8Value = false;
break;
case VCE_TYPE_BOOL16:
if (entry.bAllowExceedBounds)
*entry.pUint16Value = *entry.pUint16Value == false;
else
*entry.pUint16Value = false;
break;
case VCE_TYPE_BOOL32:
if (entry.bAllowExceedBounds)
*entry.pUint32Value = *entry.pUint32Value == false;
else
*entry.pUint32Value = false;
break;
case VCE_TYPE_FUNCTION:
entry.pCallback();
break;
default:
return;
}
}
void
CVarConsole::ModifyRight()
{
CVarConsoleEntry &entry = m_aEntries[m_nCurEntry];
switch (entry.VarType)
{
case VCE_TYPE_INT8:
*entry.pInt8Value += entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt8Value > entry.I8_max)
*entry.pInt8Value = entry.I8_min;
}
else {
if (*entry.pInt8Value > entry.I8_max)
*entry.pInt8Value = entry.I8_max;
}
break;
case VCE_TYPE_INT16:
*entry.pInt16Value += entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt16Value > entry.I16_max)
*entry.pInt16Value = entry.I16_min;
}
else {
if (*entry.pInt16Value > entry.I16_max)
*entry.pInt16Value = entry.I16_max;
}
break;
case VCE_TYPE_INT32:
*entry.pInt32Value += entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt32Value > entry.I32_max)
*entry.pInt32Value = entry.I32_min;
}
else {
if (*entry.pInt32Value > entry.I32_max)
*entry.pInt32Value = entry.I32_max;
}
break;
case VCE_TYPE_INT64:
*entry.pInt64Value += entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*entry.pInt64Value > entry.I64_max)
*entry.pInt64Value = entry.I64_min;
}
else {
if (*entry.pInt64Value > entry.I64_max)
*entry.pInt64Value = entry.I64_max;
}
break;
case VCE_TYPE_UINT8:
*entry.pUint8Value += entry.I8_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint8Value > (uint8)entry.I8_max)
*entry.pUint8Value = entry.I8_min;
}
else {
if (*entry.pUint8Value > (uint8)entry.I8_max)
*entry.pUint8Value = entry.I8_max;
}
break;
case VCE_TYPE_UINT16:
*entry.pUint16Value += entry.I16_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint16Value > (uint16)entry.I16_max)
*entry.pUint16Value = entry.I16_min;
}
else {
if (*entry.pUint16Value > (uint16)entry.I16_max)
*entry.pUint16Value = entry.I16_max;
}
break;
case VCE_TYPE_UINT32:
*entry.pUint32Value += entry.I32_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint32Value > (uint32)entry.I32_max)
*entry.pUint32Value = entry.I32_min;
}
else {
if (*entry.pUint32Value > (uint32)entry.I32_max)
*entry.pUint32Value = entry.I32_max;
}
break;
case VCE_TYPE_UINT64:
*entry.pUint64Value += entry.I64_step;
if (entry.bAllowExceedBounds) {
if (*entry.pUint64Value > (uint64)entry.I64_max)
*entry.pUint64Value = entry.I64_min;
}
else {
if (*entry.pUint64Value > (uint64)entry.I64_max)
*entry.pUint64Value = entry.I64_max;
}
break;
case VCE_TYPE_FLOAT:
*entry.pFloatValue += entry.F_step;
if (entry.bAllowExceedBounds) {
if (*entry.pFloatValue > entry.F_max)
*entry.pFloatValue = entry.F_min;
}
else {
if (*entry.pFloatValue > entry.F_max)
*entry.pFloatValue = entry.F_max;
}
break;
case VCE_TYPE_BOOL:
if (entry.bAllowExceedBounds)
*entry.pBoolValue ^= true;
else
*entry.pBoolValue = true;
break;
case VCE_TYPE_BOOL8:
if (entry.bAllowExceedBounds)
*entry.pUint8Value = *entry.pUint8Value == false;
else
*entry.pUint8Value = true;
break;
case VCE_TYPE_BOOL16:
if (entry.bAllowExceedBounds)
*entry.pUint16Value = *entry.pUint16Value == false;
else
*entry.pUint16Value = true;
break;
case VCE_TYPE_BOOL32:
if (entry.bAllowExceedBounds)
*entry.pUint32Value = *entry.pUint32Value == false;
else
*entry.pUint32Value = true;
break;
case VCE_TYPE_FUNCTION:
entry.pCallback();
break;
default:
return;
}
}
void
CVarConsole::Enter()
{
m_bIsOpen = true;
}
void
CVarConsole::Exit()
{
m_bIsOpen = false;
}
void
CVarConsole::Input()
{
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadDownJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadDown())
{
m_nCurEntry++;
if (m_nCurEntry < m_nCountEntries)
{
if (m_nCurEntry > m_nFirstEntryOnPage + 29)
{
m_nFirstEntryOnPage = m_nCurEntry;
++m_nCurPage;
}
}
else
{
m_nCurEntry = m_nCountEntries - 1;
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadUpJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadUp())
{
m_nCurEntry--;
if (m_nCurEntry < m_nFirstEntryOnPage)
{
m_nFirstEntryOnPage = m_nCurEntry - 29;
--m_nCurPage;
}
if (m_nFirstEntryOnPage < 0)
{
m_nCurEntry = 0;
m_nFirstEntryOnPage = 0;
m_nCurPage = 1;
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetSquare())
ModifyLeft();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetTriangle())
ModifyRight();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadLeftJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadLeft())
ModifyLeft();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadRightJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadRight())
ModifyRight();
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder2JustDown())
{
if (m_nCurPage > 1)
{
m_nCurPage--;
m_nFirstEntryOnPage -= 30;
m_nCurEntry = m_nFirstEntryOnPage;
if (m_nFirstEntryOnPage < 0)
{
m_nFirstEntryOnPage = 0;
m_nCurEntry = m_nFirstEntryOnPage;
m_nCurPage = 1;
}
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder2JustDown())
{
if (m_nCurPage < m_nNumPages)
{
m_nCurPage++;
m_nFirstEntryOnPage += 30;
m_nCurEntry = m_nFirstEntryOnPage;
if (m_nFirstEntryOnPage >= m_nCountEntries)
{
m_nFirstEntryOnPage -= 30;
m_nCurEntry = m_nFirstEntryOnPage;
m_nCurPage--;
}
}
}
if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())
Exit();
}
void
CVarConsole::Process()
{
Input();
SortPages();
Display();
}
bool8
CVarConsole::Open()
{
return m_bIsOpen;
}
void
CVarConsole::Check()
{
if (Open())
Process();
else if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())
Enter();
}

92
src/render/VarConsole.h Normal file
View file

@ -0,0 +1,92 @@
#pragma once
enum eVarConsoleEntryType
{
VCE_TYPE_INT8,
VCE_TYPE_INT16,
VCE_TYPE_INT32,
VCE_TYPE_INT64,
VCE_TYPE_UINT8,
VCE_TYPE_UINT16,
VCE_TYPE_UINT32,
VCE_TYPE_UINT64,
VCE_TYPE_FLOAT,
VCE_TYPE_BOOL,
VCE_TYPE_BOOL8,
VCE_TYPE_BOOL16,
VCE_TYPE_BOOL32,
VCE_TYPE_FUNCTION,
};
struct CVarConsoleEntry
{
char *text;
int8 *pInt8Value;
int16 *pInt16Value;
int32 *pInt32Value;
int64 *pInt64Value;
uint8 *pUint8Value;
uint16 *pUint16Value;
uint32 *pUint32Value;
uint64 *pUint64Value;
float *pFloatValue;
bool *pBoolValue;
void (*pCallback)(void);
int8 I8_step, I8_max, I8_min;
int16 I16_step, I16_max, I16_min;
int32 I32_step, I32_max, I32_min;
int64 I64_step, I64_max, I64_min;
float F_step, F_max, F_min;
bool8 bAllowExceedBounds;
uint8 VarType;
};
class CVarConsole
{
int32 m_nCountEntries;
bool8 m_bIsOpen;
int32 m_nCurEntry;
int32 m_nFirstEntryOnPage;
int32 m_nCurPage;
int32 m_nNumPages;
CVarConsoleEntry m_aEntries[91];
public:
#ifdef FIX_BUGS
CVarConsole() { Initialise(); }
#endif
void Initialise();
void Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);
void Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);
void Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);
void Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);
void Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);
void Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);
void Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);
void Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);
void Add(char *text, float *pVal, float step, float min, float max, bool8 isVar);
void Add(char *text, bool *pVal, bool8 isVar);
void Add(char *text, bool8 *pVal, bool8 isVar);
void Add(char *text, bool16 *pVal, bool8 isVar);
void Add(char *text, bool32 *pVal, bool8 isVar);
void Add(char *text, void (*pVar)(void));
void Remove(char *text);
void SortPages();
void Display();
void ModifyLeft();
void ModifyRight();
void Enter();
void Exit();
void Input();
void Process();
bool8 Open();
void Check();
};
extern CVarConsole VarConsole;

View file

@ -58,7 +58,7 @@ int32 CWaterLevel::m_nRenderWaterLayers;
RpAtomic *CWaterLevel::ms_pWavyAtomic;
RpAtomic *CWaterLevel::ms_pMaskAtomic;
//"Custom" Don´t Render Water Toggle
//"Custom" Don't Render Water Toggle
bool gbDontRenderWater;
@ -895,7 +895,7 @@ SectorRadius(float fSize)
void
CWaterLevel::RenderWater()
{
//"Custom" Don´t Render Water Toggle
//"Custom" Don't Render Water Toggle
#ifndef MASTER
if (gbDontRenderWater)
return;

View file

@ -226,15 +226,15 @@ void CWeather::Update(void)
// Rain
float fNewRain;
if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {
// if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
// if raining for >1 hour, values: 0, 0.33, switching every ~16.5s
fNewRain = (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.33f;
if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {
if (InterpolationValue < 0.4f)
// if rain has just started (<24 minutes), always 0.5
fNewRain = 0.5f;
else
// if rain is ongoing for >24 minutes, values: 0.25, 0.5, 0.75, 1.0, switching every ~16.5s
fNewRain = 0.25f + ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.25f;
// if rain is ongoing for >24 minutes, values: 0.25, 0.5, switching every ~16.5s
fNewRain = 0.25f + (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.25f;
}
fNewRain = Max(fNewRain, 0.5f);
}

View file

@ -252,12 +252,15 @@ CVector vecHunterRocketPos(2.5f, 1.0f, -0.5f);
CVector vecDAMAGE_ENGINE_POS_SMALL(-0.1f, -0.1f, 0.0f);
CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);
#pragma optimize("", off) // a workaround for another compiler bug
void
CAutomobile::ProcessControl(void)
{
int i;
float wheelRot;
CColModel *colModel;
float brake = 0.0f;
if(bUsingSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
@ -448,7 +451,7 @@ CAutomobile::ProcessControl(void)
m_fBrakePedal = 1.0f;
m_fGasPedal = 0.0f;
}
if(CPad::GetPad(0)->WeaponJustDown())
if(CPad::GetPad(0)->CarGunJustDown())
ActivateBomb();
break;
@ -680,7 +683,6 @@ CAutomobile::ProcessControl(void)
AutoPilot.m_nCarMission == MISSION_PLANE_FLYTOCOORS)
skipPhysics = true;
float brake;
if(skipPhysics){
bHasContacted = false;
bIsInSafePosition = false;
@ -835,11 +837,16 @@ CAutomobile::ProcessControl(void)
if(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f &&
this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){
if(GetStatus() == STATUS_PLAYER && pHandling->Flags & HANDLING_IS_BUS){
if(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){
if(m_nBusDoorTimerEnd == 0)
m_nBusDoorTimerEnd = 1000;
else if(m_nBusDoorTimerEnd > CTimer::GetTimeStepInMilliseconds())
m_nBusDoorTimerEnd -= CTimer::GetTimeStepInMilliseconds();
else {
uint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds();
if(m_nBusDoorTimerEnd > timeStepInMs)
m_nBusDoorTimerEnd -= timeStepInMs;
else
m_nBusDoorTimerEnd = 0;
}
}
if((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) &&
@ -1676,8 +1683,8 @@ CAutomobile::ProcessControl(void)
Abs(m_vecMoveSpeed.y) < 0.005f &&
Abs(m_vecMoveSpeed.z) < 0.005f &&
!(m_fDamageImpulse > 0.0f && m_pDamageEntity == FindPlayerPed()) &&
(m_aSuspensionSpringRatioPrev[0] < 1.0f && m_aSuspensionSpringRatioPrev[1] < 1.0f &&
m_aSuspensionSpringRatioPrev[2] < 1.0f && m_aSuspensionSpringRatioPrev[3] < 1.0f)){
(m_aSuspensionSpringRatioPrev[0] < 1.0f || m_aSuspensionSpringRatioPrev[1] < 1.0f ||
m_aSuspensionSpringRatioPrev[2] < 1.0f || m_aSuspensionSpringRatioPrev[3] < 1.0f)){
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
m_vecTurnSpeed.z = 0.0f;
}
@ -1701,6 +1708,8 @@ CAutomobile::ProcessControl(void)
}
}
#pragma optimize("", on)
void
CAutomobile::Teleport(CVector pos)
{
@ -5786,7 +5795,7 @@ CAutomobile::PopBootUsingPhysics(void)
case DOOR_STATUS_OK:
case DOOR_STATUS_SMASHED:
Damage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_SWINGING);
Doors[DOOR_BOOT].m_fAngle = -2.0f;
Doors[DOOR_BOOT].m_fAngVel = -2.0f;
}
void

View file

@ -2694,7 +2694,7 @@ CBike::KnockOffRider(eWeaponType weapon, uint8 direction, CPed *ped, bool bGetBa
switch(direction){
case 0: anim = ANIM_KO_SKID_BACK; break;
case 1: anim = ANIM_KD_RIGHT; break;
case 2: anim = ANIM_KO_SKID_FRONT; break;
case 2: anim = ANIM_BIKE_FALL_R; break;
case 3: anim = ANIM_KD_LEFT; break;
}
if(m_nWheelsOnGround == 0)

View file

@ -300,7 +300,7 @@ cHandlingDataMgr::LoadHandlingData(void)
case 11: handling->fTractionBias = atof(word); break;
case 12: handling->Transmission.nNumberOfGears = atoi(word); break;
case 13: handling->Transmission.fMaxVelocity = atof(word); break;
case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4f; break;
case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break;
case 15: handling->Transmission.nDriveType = word[0]; break;
case 16: handling->Transmission.nEngineType = word[0]; break;
case 17: handling->fBrakeDeceleration = atof(word); break;
@ -362,26 +362,32 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;
handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->fMass;
// What the hell is going on here?
specificVolume = handling->Dimension.x*handling->Dimension.z*0.5f / handling->fMass; // ?
// Don't quite understand this. What seems to be going on is that
// we calculate a drag (air resistance) deceleration for a given velocity and
// find the intersection between that and the max engine acceleration.
// at that point the car cannot accelerate any further and we've found the max velocity.
a = 0.0f;
b = 100.0f;
velocity = handling->Transmission.fMaxVelocity;
while(a < b && velocity > 0.0f){
velocity -= 0.01f;
// what's the 1/6?
a = handling->Transmission.fEngineAcceleration/6.0f;
b = -velocity * (1.0f/(specificVolume * sq(velocity) + 1.0f) - 1.0f);
// no density or drag coefficient here...
float a_drag = 0.5f*SQR(velocity) * handling->Dimension.x*handling->Dimension.z / handling->fMass;
// can't make sense of this... maybe v - v/(drag + 1) ? but that doesn't make so much sense either
b = -velocity * (1.0f/(a_drag + 1.0f) - 1.0f);
}
if(handling->nIdentifier == HANDLING_RCBANDIT){
handling->Transmission.fUnkMaxVelocity = handling->Transmission.fMaxVelocity;
handling->Transmission.fMaxCruiseVelocity = handling->Transmission.fMaxVelocity;
handling->Transmission.fMaxReverseVelocity = -handling->Transmission.fMaxVelocity;
}else if(handling->nIdentifier >= HANDLING_BIKE && handling->nIdentifier <= HANDLING_FREEWAY){
handling->Transmission.fUnkMaxVelocity = velocity;
handling->Transmission.fMaxCruiseVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.05f;
}else{
handling->Transmission.fUnkMaxVelocity = velocity;
handling->Transmission.fMaxCruiseVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.2f;
}

View file

@ -123,7 +123,7 @@ cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, fl
else
fCheat = 1.0f;
float targetVelocity = Gears[gear].fMaxVelocity*speedMul*fCheat;
float accel = fEngineAcceleration*accelMul * (targetVelocity - fVelocity)/Abs(targetVelocity);
float accel = (targetVelocity - fVelocity) * (fEngineAcceleration*accelMul) / Abs(targetVelocity);
if(Abs(fVelocity) < Abs(Gears[gear].fMaxVelocity*fCheat))
fAcceleration = gasPedal * accel * CTimer::GetTimeStep();
else

View file

@ -18,7 +18,7 @@ public:
uint8 Flags;
float fEngineAcceleration;
float fMaxVelocity;
float fUnkMaxVelocity;
float fMaxCruiseVelocity;
float fMaxReverseVelocity;
float fCurVelocity;

View file

@ -48,6 +48,9 @@ bool CVehicle::bAllTaxisHaveNitro;
bool CVehicle::m_bDisableMouseSteering = true;
bool CVehicle::bDisableRemoteDetonation;
bool CVehicle::bDisableRemoteDetonationOnContact;
#ifndef MASTER
bool CVehicle::m_bDisplayHandlingInfo;
#endif
void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); }
void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); }
@ -146,6 +149,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED;
m_nLastWeaponDamage = -1;
m_pLastDamageEntity = nil;
m_fMapObjectHeightAhead = m_fMapObjectHeightBehind = 0.0f;
m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this);
if(m_audioEntityId >= 0)
@ -836,11 +840,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
if(IsBike())
brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);
else if(pHandling->fMass < 500.0f)
brake = mod_HandlingManager.fWheelFriction / m_fMass;
brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
else if(GetModelIndex() == MI_RCBANDIT)
brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
else
brake = mod_HandlingManager.fWheelFriction / m_fMass;
brake = mod_HandlingManager.fWheelFriction / pHandling->fMass;
#ifdef FIX_BUGS
brake *= CTimer::GetTimeStepFix();
#endif
@ -1232,7 +1236,7 @@ CVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage
if (m_randomSeed < DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE) {
CCarCtrl::SwitchVehicleToRealPhysics(this);
AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fUnkMaxVelocity;
AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fMaxCruiseVelocity;
SetStatus(STATUS_PHYSICS);
}
}
@ -1873,7 +1877,7 @@ CVehicle::AddPassenger(CPed *passenger)
int i;
if(IsBike())
ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
ApplyTurnForce(-0.02f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
else
ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
passenger->GetPosition().x - GetPosition().x,
@ -1896,7 +1900,7 @@ CVehicle::AddPassenger(CPed *passenger, uint8 n)
return AddPassenger(passenger);
if(IsBike())
ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
ApplyTurnForce(-0.02f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
else
ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
passenger->GetPosition().x - GetPosition().x,

View file

@ -402,6 +402,9 @@ public:
static bool m_bDisableMouseSteering;
static bool bDisableRemoteDetonation;
static bool bDisableRemoteDetonationOnContact;
#ifndef MASTER
static bool m_bDisplayHandlingInfo;
#endif
};
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);