diff options
-rw-r--r-- | src/audio/oal/stream.cpp | 12 | ||||
-rw-r--r-- | src/core/CdStreamPosix.cpp | 16 | ||||
-rw-r--r-- | src/core/FileMgr.cpp | 37 | ||||
-rw-r--r-- | src/core/Game.cpp | 9 | ||||
-rw-r--r-- | src/core/Ropes.cpp | 12 | ||||
-rw-r--r-- | src/core/main.cpp | 2 | ||||
-rw-r--r-- | src/fakerw/fake.cpp | 65 | ||||
-rw-r--r-- | src/peds/CopPed.cpp | 339 | ||||
-rw-r--r-- | src/peds/CopPed.h | 7 | ||||
-rw-r--r-- | src/peds/PedPlacement.cpp | 8 | ||||
-rw-r--r-- | src/peds/PedPlacement.h | 2 | ||||
-rw-r--r-- | src/skel/crossplatform.cpp | 129 | ||||
-rw-r--r-- | src/skel/crossplatform.h | 6 | ||||
-rw-r--r-- | src/vehicles/Heli.cpp | 4 |
14 files changed, 403 insertions, 245 deletions
diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 40ec57fa..b689e929 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -255,15 +255,11 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF { // Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) #if !defined(_WIN32) - FILE *test = fopen(filename, "r"); - if (!test) { - char *r = (char*)alloca(strlen(filename) + 2); - if (casepath(filename, r)) - { - strcpy(m_aFilename, r); - } + char *real = casepath(filename); + if (real) { + strcpy(m_aFilename, real); + free(real); } else { - fclose(test); #else { #endif diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index 4d6bcdab..45fd9832 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -189,10 +189,11 @@ GetGTA3ImgSize(void) realpath(gImgNames[0], path); if (stat(path, &statbuf) == -1) { // Try case-insensitivity - char *r = (char*)alloca(strlen(gImgNames[0]) + 2); - if (casepath(gImgNames[0], r)) + char* real = casepath(gImgNames[0], false); + if (real) { - realpath(r, path); + realpath(real, path); + free(real); if (stat(path, &statbuf) != -1) goto ok; } @@ -210,7 +211,6 @@ CdStreamShutdown(void) { // Destroying semaphores and free(gpReadInfo) will be done at threads #ifndef ONE_THREAD_PER_CHANNEL - free(gChannelRequestQ.items); gCdStreamThreadStatus = 2; sem_post(&gCdStreamSema); #endif @@ -442,6 +442,7 @@ void *CdStreamThread(void *param) sem_destroy(&gpReadInfo[i].pDoneSemaphore); } sem_destroy(&gCdStreamSema); + free(gChannelRequestQ.items); #else sem_destroy(&gpReadInfo[channel].pStartSemaphore); sem_destroy(&gpReadInfo[channel].pDoneSemaphore); @@ -460,10 +461,11 @@ CdStreamAddImage(char const *path) // Fix case sensitivity and backslashes. if (gImgFiles[gNumImages] == -1) { - char *r = (char*)alloca(strlen(path) + 2); - if (casepath(path, r)) + char* real = casepath(path, false); + if (real) { - gImgFiles[gNumImages] = open(r, _gdwCdStreamFlags); + gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags); + free(real); } } diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index cdcb80f0..4477a190 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -4,6 +4,7 @@ #include <direct.h> #endif #include "common.h" +#include "crossplatform.h" #include "FileMgr.h" @@ -31,19 +32,16 @@ static myFILE myfiles[NUMFILES]; #include <dirent.h> #include <errno.h> #include <unistd.h> -#include "crossplatform.h" #define _getcwd getcwd // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) void mychdir(char const *path) { - char *r = (char*)alloca(strlen(path) + 2); - if (casepath(path, r)) - { + char* r = casepath(path, false); + if (r) { chdir(r); - } - else - { + free(r); + } else { errno = ENOENT; } } @@ -73,30 +71,7 @@ found: *p++ = 'b'; *p = '\0'; -#if !defined(_WIN32) - char *newPath = strdup(filename); - // Normally casepath() fixes backslashes, but if the mode is sth other than r/rb it will create new file with backslashes on linux, so fix backslashes here - char *nextBs; - while(nextBs = strstr(newPath, "\\")){ - *nextBs = '/'; - } -#else - const char *newPath = filename; -#endif - - myfiles[fd].file = fopen(newPath, realmode); -// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) -#if !defined(_WIN32) - if (!myfiles[fd].file) { - char *r = (char*)alloca(strlen(newPath) + 2); - if (casepath(newPath, r)) - { - myfiles[fd].file = fopen(r, realmode); - } - } - - free(newPath); -#endif + myfiles[fd].file = fcaseopen(filename, realmode); if(myfiles[fd].file == nil) return 0; return fd; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 072bc7be..39bbd364 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -88,6 +88,7 @@ #include "Zones.h" #include "Occlusion.h" #include "debugmenu.h" +#include "Ropes.h" eLevelName CGame::currLevel; int32 CGame::currArea; @@ -403,9 +404,11 @@ bool CGame::Initialise(const char* datFile) CRubbish::Init(); CClouds::Init(); CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CBridge::Init(); CGarages::Init(); + LoadingScreen("Loading the Game", "Position dynamic objects", nil); LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); CTrain::InitTrains(); CPlane::InitPlanes(); @@ -416,6 +419,7 @@ bool CGame::Initialise(const char* datFile) if ( !TheMemoryCard.m_bWantToLoad ) { #endif + LoadingScreen("Loading the Game", "Start script", nil); CTheScripts::StartTestScript(); CTheScripts::Process(); TheCamera.Process(); @@ -426,6 +430,9 @@ bool CGame::Initialise(const char* datFile) CCollision::ms_collisionInMemory = currLevel; for (int i = 0; i < MAX_PADS; i++) CPad::GetPad(i)->Clear(true); + // TODO(Miami) + // DMAudio.SetStartingTrackPositions(1); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); return true; } @@ -546,6 +553,7 @@ void CGame::ReInitGameObjectVariables(void) CRemote::Init(); #endif CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CParticle::ReloadConfig(); @@ -718,6 +726,7 @@ void CGame::Process(void) CGarages::Update(); CRubbish::Update(); CSpecialFX::Update(); + CRopes::Update(); CTimeCycle::Update(); if (CReplay::ShouldStandardCameraBeProcessed()) TheCamera.Process(); diff --git a/src/core/Ropes.cpp b/src/core/Ropes.cpp index 4c57f190..dbae9ee3 100644 --- a/src/core/Ropes.cpp +++ b/src/core/Ropes.cpp @@ -31,14 +31,14 @@ CRope::Update(void) for(i = 1; i < ARRAY_SIZE(m_pos); i++){ CVector prevPos = m_pos[i]; m_pos[i] += m_speed[i]*step*CTimer::GetTimeStep(); - m_pos[0].z -= 0.05f*CTimer::GetTimeStep(); + m_pos[i].z -= 0.05f*CTimer::GetTimeStep(); CVector dist = m_pos[i] - m_pos[i-1]; - m_pos[i] = m_pos[i-1] + dist/dist.Magnitude()*0.625f; + m_pos[i] = m_pos[i-1] + (0.625f/dist.Magnitude())*dist; m_speed[i] = (m_pos[i] - prevPos)/CTimer::GetTimeStep(); } if(!m_bWasRegistered && m_pos[0].z < 0.0f) m_bActive = false; - m_bWasRegistered = true; + m_bWasRegistered = false; } void @@ -60,7 +60,11 @@ CRope::Render(void) RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); if(RwIm3DTransform(TempBufferRenderVertices, ARRAY_SIZE(m_pos), nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){ +#ifdef FIX_BUGS RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); +#else + RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); +#endif RwIm3DEnd(); } } @@ -159,7 +163,7 @@ CRopes::CreateRopeWithSwatComingDown(CVector pos) if(!CStreaming::HasModelLoaded(MI_SWAT) || !RegisterRope(ropeId+100, pos, true)) return false; - CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_ARMY, pos); + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos); swat->bUsesCollision = false; swat->m_pRopeEntity = (CEntity*)1; swat->m_nRopeID = 100 + ropeId; diff --git a/src/core/main.cpp b/src/core/main.cpp index 0ea95c6e..d4ef8c4b 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -62,6 +62,7 @@ #include "SceneEdit.h" #include "debugmenu.h" #include "Occlusion.h" +#include "Ropes.h" GlobalScene Scene; @@ -873,6 +874,7 @@ RenderEffects(void) CGlass::Render(); CWaterCannons::Render(); CSpecialFX::Render(); + CRopes::Render(); CShadows::RenderStaticShadows(); CShadows::RenderStoredShadows(); CSkidmarks::Render(); diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 0bc69abe..7139292e 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -376,23 +376,19 @@ RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const v file = rwNewT(StreamFile, 1, 0); memcpy(file, &fakefile, sizeof(StreamFile)); #ifndef _WIN32 - // Be case-insensitive and fix backslashes (from https://github.com/OneSadCookie/fcaseopen/) - FILE* first = fopen((char*)pData, "r"); - char *r; - if (!first) { - r = (char*)alloca(strlen((char*)pData) + 2); - // Use default path(and pass error handling to librw) if we can't find any match - if (!casepath((char*)pData, r)) - r = (char*)pData; + char *r = casepath((char*)pData); + if (r) { + if (file->open((char*)r, mode)) { + free(r); + return file; + } + free(r); } else - fclose(first); - - if(file->open((char*)r, mode)) - return file; -#else - if(file->open((char*)pData, mode)) - return file; #endif + { + if (file->open((char*)pData, mode)) + return file; + } rwFree(file); return nil; } @@ -856,12 +852,41 @@ RpSkin *RpSkinGeometryGetSkin( RpGeometry *geometry ) { return Skin::get(geometr RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ) { Skin::setHierarchy(atomic, hierarchy); return atomic; } RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { return Skin::getHierarchy(atomic); } +RwImage * +RtBMPImageWrite(RwImage *image, const RwChar *imageName) +{ +#ifndef _WIN32 + char *r = casepath(imageName); + if (r) { + rw::writeBMP(image, r); + free(r); + } else { + rw::writeBMP(image, imageName); + } + +#else + rw::writeBMP(image, imageName); +#endif + return image; +} +RwImage * +RtBMPImageRead(const RwChar *imageName) +{ +#ifndef _WIN32 + RwImage *image; + char *r = casepath(imageName); + if (r) { + image = rw::readBMP(r); + free(r); + } else { + image = rw::readBMP(imageName); + } + return image; - - - -RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName) { rw::writeBMP(image, imageName); return image; } -RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName); } +#else + return rw::readBMP(imageName); +#endif +} #include "rtquat.h" diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index dd122477..6c9eb276 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -16,6 +16,8 @@ #include "CarCtrl.h" #include "Renderer.h" #include "Camera.h" +#include "PedPlacement.h" +#include "Ropes.h" CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) { @@ -39,12 +41,13 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_wepAccuracy = 76; break; case COP_SWAT: + case COP_HELI_SWAT: SetModelIndex(MI_SWAT); GiveDelayedWeapon(WEAPONTYPE_UZI, 1000); SetCurrentWeapon(WEAPONTYPE_UZI); m_fArmour = 50.0f; m_wepSkills = 32; /* TODO: what is this? seems unused */ - m_wepAccuracy = 64; + m_wepAccuracy = 68; break; case COP_ARMY: SetModelIndex(MI_ARMY); @@ -77,18 +80,21 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) field_5FE = 1; m_bIsDisabledCop = false; m_attackTimer = 0; + m_bBeatingSuspect = false; m_bStopAndShootDisabledZone = false; field_601 = false; m_bZoneDisabled = false; field_628 = -1; m_nRoadblockNode = -1; // TODO(Miami): this will be nil m_bThrowsSpikeTrap = false; - field_5FF = 0; m_pRopeEntity = nil; m_fAbseilPos = 0.0f; - m_bBeatingSuspect = false; - m_pPointGunAt = nil; + m_nHassleTimer = 0; + field_61C = 0; field_624 = 0; + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference((CEntity**)&m_pPointGunAt); + m_pPointGunAt = nil; } CCopPed::~CCopPed() @@ -96,24 +102,17 @@ CCopPed::~CCopPed() ClearPursuit(); } +// --MIAMI: Done // Parameter should always be CPlayerPed, but it seems they considered making civilians arrestable at some point void CCopPed::SetArrestPlayer(CPed *player) { if (!IsPedInControl() || !player) return; - /* - switch (m_nCopType) { - case COP_FBI: - Say(SOUND_PED_ARREST_FBI); - break; - case COP_SWAT: - Say(SOUND_PED_ARREST_SWAT); - break; - default: - Say(SOUND_PED_ARREST_COP); - break; - } */ + + player->Say(SOUND_PED_PLAYER_REACTTOCOP); + Say(SOUND_PED_ARREST_COP); + if (player->EnteringCar()) { if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) return; @@ -128,14 +127,14 @@ CCopPed::SetArrestPlayer(CPed *player) } else if (player->m_nPedState != PED_DIE && player->m_nPedState != PED_DEAD && player->m_nPedState != PED_ARRESTED) { player->m_nLastPedState = player->m_nPedState; - player->m_nPedState = PED_ARRESTED; + player->SetPedState(PED_ARRESTED); FindPlayerPed()->m_bCanBeDamaged = false; ((CPlayerPed*)player)->m_pArrestingCop = this; this->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop); } - m_nPedState = PED_ARREST_PLAYER; + SetPedState(PED_ARREST_PLAYER); SetObjective(OBJECTIVE_NONE); m_prevObjective = OBJECTIVE_NONE; bIsPointingGunAt = false; @@ -148,10 +147,11 @@ CCopPed::SetArrestPlayer(CPed *player) player->m_pMyVehicle->bIsHandbrakeOn = true; player->m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED); } - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) SetCurrentWeapon(WEAPONTYPE_COLT45); } +// --MIAMI: Done void CCopPed::ClearPursuit(void) { @@ -190,6 +190,7 @@ CCopPed::ClearPursuit(void) bNotAllowedToDuck = false; bKindaStayInSamePlace = false; m_bStopAndShootDisabledZone = false; + field_601 = false; m_bZoneDisabled = false; ClearObjective(); if (IsPedInControl()) { @@ -207,10 +208,14 @@ CCopPed::ClearPursuit(void) } } +// --MIAMI: Done // TODO: I don't know why they needed that parameter. void CCopPed::SetPursuit(bool ignoreCopLimit) { + if (CTimer::GetTimeInMilliseconds() < field_61C) + return; + CWanted *wanted = FindPlayerPed()->m_pWanted; if (m_bIsInPursuit || !IsPedInControl()) return; @@ -236,6 +241,7 @@ CCopPed::SetPursuit(bool ignoreCopLimit) } } +// --MIAMI: Done void CCopPed::ArrestPlayer(void) { @@ -301,6 +307,7 @@ CCopPed::ScanForCrimes(void) } } +// --MIAMI: Done void CCopPed::CopAI(void) { @@ -318,11 +325,6 @@ CCopPed::CopAI(void) if (bHitSomethingLastFrame) { m_bZoneDisabled = true; m_bIsDisabledCop = true; -#ifdef FIX_BUGS - m_nRoadblockNode = -1; -#else - m_nRoadblockNode = 0; -#endif bKindaStayInSamePlace = true; bIsRunning = false; bNotAllowedToDuck = false; @@ -349,6 +351,27 @@ CCopPed::CopAI(void) } if (wantedLevel > 0) { if (!m_bIsDisabledCop) { + // Turn and shoot the player's vehicle, if possible + if (!m_bIsInPursuit && !GetWeapon()->IsTypeMelee() && FindPlayerVehicle() && m_fDistanceToTarget < CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange) { + if (FindPlayerVehicle()->m_vecMoveSpeed.Magnitude2D() > 0.1f) { + CVector2D distToVeh = GetPosition() - FindPlayerVehicle()->GetPosition(); + distToVeh.Normalise(); + CVector2D vehSpeed = FindPlayerVehicle()->m_vecMoveSpeed; + vehSpeed.Normalise(); + + if (DotProduct2D(distToVeh, vehSpeed) > 0.8f) { + SetLookFlag(playerOrHisVeh, true); + SetMoveState(PEDMOVE_STILL); + if (TurnBody()) { + SetAttack(FindPlayerVehicle()); + SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); + SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 300.0f)); + } + } else if (m_nPedState == PED_ATTACK) + RestorePreviousState(); + } + } + if (!m_bIsInPursuit || wanted->m_CurrentCops > wanted->m_MaxCops) { CCopPed *copFarthestToTarget = nil; float copFarthestToTargetDist = m_fDistanceToTarget; @@ -391,11 +414,14 @@ CCopPed::CopAI(void) if (wantedLevel > 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) SetCurrentWeapon(WEAPONTYPE_COLT45); - else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) { + else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) { // i.e. if player is on top of car, cop will still use colt45. - SetCurrentWeapon(WEAPONTYPE_UNARMED); + SetCurrentWeapon(GetWeaponSlot(WEAPONTYPE_NIGHTSTICK) >= 0 ? WEAPONTYPE_NIGHTSTICK : WEAPONTYPE_UNARMED); } + if (m_bBeatingSuspect && GetWeapon()->m_eWeaponType == WEAPONTYPE_NIGHTSTICK) + Say(SOUND_PED_PULLOUTWEAPON); + if (FindPlayerVehicle()) { if (m_bBeatingSuspect) { --wanted->m_CopsBeatingSuspect; @@ -406,18 +432,18 @@ CCopPed::CopAI(void) } return; } - float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange; + SetCurrentWeapon(WEAPONTYPE_COLT45); + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + float weaponRange = weaponInfo->m_fRange; SetLookFlag(playerOrHisVeh, true); TurnBody(); - SetCurrentWeapon(WEAPONTYPE_COLT45); - if (!bIsDucking) { + if (!bIsDucking || bCrouchWhenShooting && GetCrouchFireAnim(weaponInfo)) { if (m_attackTimer >= CTimer::GetTimeInMilliseconds()) { if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT && !m_bZoneDisabled) { CVector targetDist = playerOrHisVeh->GetPosition() - GetPosition(); if (m_fDistanceToTarget > 30.0f) { - CAnimBlendAssociation* crouchShootAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); - if (crouchShootAssoc) - crouchShootAssoc->blendDelta = -1000.0f; + if (bIsDucking) + ClearDuck(); // Target is coming onto us if (DotProduct(playerOrHisVeh->m_vecMoveSpeed, targetDist) > 0.0f) { @@ -435,42 +461,23 @@ CCopPed::CopAI(void) bNotAllowedToDuck = false; bDuckAndCover = false; } else { - // VC checks for != nil compared to buggy behaviour of III. I check for != -1 here. -#ifdef VC_PED_PORTS + // TODO(Miami): Roadblock system is still III float dotProd; if (m_nRoadblockNode != -1) { - // TODO(MIAMI): check this, i'm only getting this compile here.... CPathNode *roadBlockNode = &ThePaths.m_pathNodes[CRoadBlocks::RoadBlockNodes[m_nRoadblockNode]]; dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockNode->GetPosition(), GetPosition() - roadBlockNode->GetPosition()); } else dotProd = -1.0f; if(dotProd >= 0.0f) { -#else - -#ifndef FIX_BUGS - float copRoadDotProd, targetRoadDotProd; -#else - float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f; - if (m_nRoadblockNode != -1) -#endif - { - CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]]; - CVector2D roadFwd = roadBlockRoad->GetForward(); - copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd); - targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd); - } - // Roadblock may be towards road's fwd or opposite, so check both - if ((copRoadDotProd >= 0.0f || targetRoadDotProd >= 0.0f) - && (copRoadDotProd <= 0.0f || targetRoadDotProd <= 0.0f)) { -#endif bIsPointingGunAt = true; } else { + if (bIsDucking) + ClearDuck(); m_bIsDisabledCop = false; bKindaStayInSamePlace = false; bNotAllowedToDuck = false; bCrouchWhenShooting = false; - bIsDucking = false; bDuckAndCover = false; SetPursuit(false); } @@ -478,7 +485,6 @@ CCopPed::CopAI(void) } } else { if (m_fDistanceToTarget < weaponRange) { - CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); CVector gunPos = weaponInfo->m_vecFireOffset; TransformToNode(gunPos, PED_HANDR); @@ -487,6 +493,9 @@ CCopPed::CopAI(void) if (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt, false, true, false, false, true, false, false) || foundEnt && foundEnt == playerOrHisVeh) { + + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference((CEntity**) &m_pPointGunAt); m_pPointGunAt = playerOrHisVeh; if (playerOrHisVeh) playerOrHisVeh->RegisterReference((CEntity**) &m_pPointGunAt); @@ -494,7 +503,7 @@ CCopPed::CopAI(void) SetAttack(playerOrHisVeh); SetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000)); } - SetAttackTimer(CGeneral::GetRandomNumberInRange(100, 300)); + SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 300)); } SetMoveState(PEDMOVE_STILL); } @@ -524,10 +533,8 @@ CCopPed::CopAI(void) ClearObjective(); SetWanderPath(CGeneral::GetRandomNumber() & 7); } - } -#ifdef VC_PED_PORTS - else { - if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && CharCreatedBy == RANDOM_CHAR) { + } else { + if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_HASSLE_CHAR && CharCreatedBy == RANDOM_CHAR) { for (int i = 0; i < m_numNearPeds; i++) { CPed *nearPed = m_nearPeds[i]; if (nearPed->CharCreatedBy == RANDOM_CHAR) { @@ -547,12 +554,30 @@ CCopPed::CopAI(void) nearPed->bBeingChasedByPolice = true; return; } + } else { + if (nearPed->m_nPedType != PEDTYPE_COP && !nearPed->IsPlayer() + && nearPed->IsPedInControl() && m_nHassleTimer < CTimer::GetTimeInMilliseconds()) { + + if (nearPed->m_objective == OBJECTIVE_NONE && nearPed->m_nPedState == PED_WANDER_PATH + && !nearPed->m_pLookTarget && nearPed->m_lookTimer < CTimer::GetTimeInMilliseconds()) { + + if ((GetPosition() - nearPed->GetPosition()).MagnitudeSqr() < sq(5.0f)) { + + if (CWorld::GetIsLineOfSightClear(GetPosition(), nearPed->GetPosition(), + true, false, false, false, false, false, false)) { + Say(SOUND_PED_COP_REACTION); + SetObjective(OBJECTIVE_HASSLE_CHAR, nearPed); + nearPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT_FOR_COP, this); + m_nHassleTimer = CTimer::GetTimeInMilliseconds() + 100000; + } + } + } + } } } } } } -#endif } } } else { @@ -563,18 +588,35 @@ CCopPed::CopAI(void) bKindaStayInSamePlace = false; bNotAllowedToDuck = false; bCrouchWhenShooting = false; - bIsDucking = false; bDuckAndCover = false; + if (bIsDucking) + ClearDuck(); if (m_pMyVehicle) SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); } } } +// --MIAMI: Done except commented things void CCopPed::ProcessControl(void) { + if (m_nCopType == COP_HELI_SWAT) + ProcessHeliSwat(); + CPed::ProcessControl(); + + if (m_bThrowsSpikeTrap) { + // TODO(Miami) + /* + if (CGame::currArea != AREA_MALL) + ProcessStingerCop(); + */ + return; + } + + // TODO(Miami): CStinger::Process + if (bWasPostponed) return; @@ -606,25 +648,36 @@ CCopPed::ProcessControl(void) if (IsPedInControl()) SetIdle(); } - /* + if (m_bIsInPursuit) { if (player->m_nPedState != PED_ARRESTED && !player->DyingOrDead()) { - switch (m_nCopType) { - case COP_FBI: - Say(SOUND_PED_PURSUIT_FBI); - break; - case COP_SWAT: - Say(SOUND_PED_PURSUIT_SWAT); - break; - case COP_ARMY: - Say(SOUND_PED_PURSUIT_ARMY); - break; - default: - Say(SOUND_PED_PURSUIT_COP); - break; + if (player->m_pWanted->m_CurrentCops == 1) { + Say(SOUND_PED_COP_ALONE); + } else { + int numCopsNear = 0; + for (int i = 0; i < player->m_numNearPeds; ++i) { + CPed *nearPed = player->m_nearPeds[i]; + if (nearPed->m_nPedType == PEDTYPE_COP && nearPed->m_nPedState != PED_DEAD) + ++numCopsNear; + } + if (numCopsNear <= 3) { + Say(SOUND_PED_COP_LITTLECOPSAROUND); + if (!player->bInVehicle) { + CVector distToPlayer = player->GetPosition() - GetPosition(); + if (distToPlayer.MagnitudeSqr() < sq(20.0f)) { + player->Say(SOUND_PED_PLAYER_FARFROMCOPS); + if (player->m_nPedState != PED_ATTACK && player->m_nPedState != PED_AIM_GUN) { + player->SetLookFlag(this, false); + player->SetLookTimer(1000); + } + } + } + } else if ((CGeneral::GetRandomNumber() % 16) == 1) { + Say(SOUND_PED_COP_MANYCOPSAROUND); + } } } - } */ + } if (IsPedInControl()) { CopAI(); @@ -671,23 +724,10 @@ CCopPed::ProcessControl(void) RestorePreviousObjective(); } else { if (player->m_pMyVehicle && player->m_pMyVehicle->m_nNumGettingIn != 0) { - // This is 1.3f when arresting in car without seeking first (in above) -#if defined(VC_PED_PORTS) || defined(FIX_BUGS) m_distanceToCountSeekDone = 1.3f; -#else - m_distanceToCountSeekDone = 2.0f; -#endif } - if (bDuckAndCover) { -#if !defined(GTA3_1_1_PATCH) && !defined(VC_PED_PORTS) - if (!bNotAllowedToDuck && Seek()) { - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - SetPointGunAt(m_pedInObjective); - } -#endif - } else if (Seek()) { + if (!bDuckAndCover && Seek()) { CVehicle *playerVeh = FindPlayerVehicle(); if (!playerVeh && player && player->EnteringCar()) { SetArrestPlayer(player); @@ -718,35 +758,100 @@ CCopPed::ProcessControl(void) } } } - if (!m_bStopAndShootDisabledZone) - return; - bool dontShoot = false; - if (GetIsOnScreen()) { - if (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) { - CEntity *foundBuilding = nil; - CColPoint foundCol; - CVector lookPos = GetPosition() + CVector(0.0f, 0.0f, 0.7f); - CVector camPos = TheCamera.GetGameCamPosition(); - CWorld::ProcessLineOfSight(camPos, lookPos, foundCol, foundBuilding, - true, false, false, false, false, false, false); - - // He's at least 15.0 far, in disabled zone, collided into somewhere (that's why m_bStopAndShootDisabledZone set), - // and now has building on front of him. He's stupid, we don't need him. - if (foundBuilding) { - FlagToDestroyWhenNextProcessed(); - dontShoot = true; + if (m_pPointGunAt) + Say(SOUND_PED_COP_UNK_129); + + if (m_bStopAndShootDisabledZone) { + bool dontShoot = false; + if (GetIsOnScreen()) { + if (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) { + CEntity* foundBuilding = nil; + CColPoint foundCol; + CVector lookPos = GetPosition() + CVector(0.0f, 0.0f, 0.7f); + CVector camPos = TheCamera.GetGameCamPosition(); + CWorld::ProcessLineOfSight(camPos, lookPos, foundCol, foundBuilding, + true, false, false, false, false, false, false); + + // He's at least 15.0 far, in disabled zone, collided into somewhere (that's why m_bStopAndShootDisabledZone set), + // and now has building on front of him. He's stupid, we don't need him. + if (foundBuilding) { + FlagToDestroyWhenNextProcessed(); + dontShoot = true; + } } + } else { + FlagToDestroyWhenNextProcessed(); + dontShoot = true; } - } else { - FlagToDestroyWhenNextProcessed(); - dontShoot = true; - } - if (!dontShoot) { - bStopAndShoot = true; - bKindaStayInSamePlace = true; - bIsPointingGunAt = true; - SetAttack(m_pedInObjective); + if (!dontShoot) { + bStopAndShoot = true; + bKindaStayInSamePlace = true; + bIsPointingGunAt = true; + SetAttack(m_pedInObjective); + } } + + if (field_624 >= 2 && m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { + CVector centre = GetPosition() + CVector(0.f, 0.f, 0.65f); + if (CWorld::TestSphereAgainstWorld(centre, 0.35f, this, true, false, false, false, false, false)) { + field_624 = 0; + m_bStopAndShootDisabledZone = true; + ClearPursuit(); + SetObjective(OBJECTIVE_NONE); + SetWanderPath(CGeneral::GetRandomNumberInRange(0,8)); + field_61C = CTimer::GetTimeInMilliseconds() + 30000; + } else { + field_624 = 0; + if (GetWeapon()->IsTypeMelee()) { + // TODO(Miami): enum + for (int i = 3; i < 7; i++) { + if (HasWeaponSlot(i)) { + SetCurrentWeapon(i); + break; + } + } + SetMoveState(PEDMOVE_STILL); + bStopAndShoot = true; + } + } + } else if (CTimer::GetTimeStep() / 100.f <= m_fDistanceTravelled) + field_624 = 0; } + +// --MIAMI: Done +void +CCopPed::ProcessHeliSwat(void) +{ + CVector bestPos = GetPosition(); + SetPedState(PED_ABSEIL); + CPedPlacement::FindZCoorForPed(&bestPos); + if (GetPosition().z - 2.0f >= bestPos.z && m_pRopeEntity) { + m_fAbseilPos += 0.003f * CTimer::GetTimeStep(); + m_vecMoveSpeed.z = -0.03f; + m_vecTurnSpeed = CVector(0.f, 0.f, (m_randomSeed % 32) * 0.003f - 0.05f); + CPhysical::ApplyTurnSpeed(); + GetMatrix().Reorthogonalise(); + CVector posOnRope; + + if (CRopes::FindCoorsAlongRope(m_nRopeID, m_fAbseilPos, &posOnRope)) { + SetPosition(posOnRope); + } else { + bUsesCollision = true; + m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + SetPedState(PED_IDLE); + m_nCopType = COP_SWAT; + SetInTheAir(); + bKnockedUpIntoAir = true; + } + Say(SOUND_PED_COP_HELIPILOTPHRASE); + } else { + bUsesCollision = true; + m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + SetPedState(PED_IDLE); + m_nCopType = COP_SWAT; + SetInTheAir(); + bKnockedUpIntoAir = true; + } +}
\ No newline at end of file diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index e48984ff..edec145e 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -6,7 +6,8 @@ enum eCopType COP_STREET = 0, COP_FBI = 1, COP_SWAT = 2, - COP_ARMY = 3, + COP_HELI_SWAT = 3, + COP_ARMY = 4, COP_MIAMIVICE = 5 }; @@ -18,7 +19,6 @@ public: bool m_bIsInPursuit; bool m_bIsDisabledCop; int8 field_5FE; - int8 field_5FF; bool m_bBeatingSuspect; bool m_bStopAndShootDisabledZone; bool field_601; // set when police dragging player from car @@ -28,6 +28,8 @@ public: bool m_bThrowsSpikeTrap; CEntity *m_pRopeEntity; // CHeli or 1 uintptr m_nRopeID; + uint32 m_nHassleTimer; + uint32 field_61C; int32 field_624; int8 field_628; @@ -41,6 +43,7 @@ public: void ArrestPlayer(void); void ScanForCrimes(void); void CopAI(void); + void ProcessHeliSwat(void); }; #ifndef PED_SKIN diff --git a/src/peds/PedPlacement.cpp b/src/peds/PedPlacement.cpp index 6011ce44..8012650a 100644 --- a/src/peds/PedPlacement.cpp +++ b/src/peds/PedPlacement.cpp @@ -4,7 +4,8 @@ #include "PedPlacement.h" #include "World.h" -void +// --MIAMI: Done +bool CPedPlacement::FindZCoorForPed(CVector* pos) { float zForPed; @@ -32,8 +33,11 @@ CPedPlacement::FindZCoorForPed(CVector* pos) zForPed = Max(foundColZ, foundColZ2); - if (zForPed > -99.0f) + if (zForPed > -99.0f) { pos->z = FEET_OFFSET + zForPed; + return true; + } + return false; } CEntity* diff --git a/src/peds/PedPlacement.h b/src/peds/PedPlacement.h index 5b8354d4..d1b0cd16 100644 --- a/src/peds/PedPlacement.h +++ b/src/peds/PedPlacement.h @@ -2,7 +2,7 @@ class CPedPlacement { public: - static void FindZCoorForPed(CVector* pos); + static bool FindZCoorForPed(CVector* pos); static CEntity* IsPositionClearOfCars(Const CVector*); static bool IsPositionClearForPed(const CVector& pos, float radius = -1.0f, int total = -1, CEntity** entities = nil); };
\ No newline at end of file diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 40f4f053..6188992d 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -87,7 +87,7 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) { // Funcs/features from Windows that we need on other platforms #ifndef _WIN32 char *strupr(char *s) { - char* tmp = s; + char* tmp = s; for (;*tmp;++tmp) { *tmp = toupper((unsigned char) *tmp); @@ -96,7 +96,7 @@ char *strupr(char *s) { return s; } char *strlwr(char *s) { - char* tmp = s; + char* tmp = s; for (;*tmp;++tmp) { *tmp = tolower((unsigned char) *tmp); @@ -116,86 +116,117 @@ char *trim(char *s) { return s; } +FILE* _fcaseopen(char const* filename, char const* mode) +{ + FILE* result; + char* real = casepath(filename); + if (!real) + result = fopen(filename, mode); + else { + result = fopen(real, mode); + free(real); + } + return result; +} + // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) -// r must have strlen(path) + 2 bytes -int casepath(char const *path, char *r) +// Returned string should freed manually (if exists) +char* casepath(char const* path, bool checkPathFirst) { + if (checkPathFirst && access(path, F_OK) != -1) { + // File path is correct + return nil; + } + size_t l = strlen(path); - char *p = (char*)alloca(l + 1); + char* p = (char*)alloca(l + 1); + char* out = (char*)malloc(l + 3); // for extra ./ strcpy(p, path); - // my addon: change \'s with / - char *nextBs; - while(nextBs = strstr(p, "\\")){ - *nextBs = '/'; - } - - // my addon: linux doesn't handle filenames with spaces at the end nicely - p = trim(p); + // my addon: linux doesn't handle filenames with spaces at the end nicely + p = trim(p); size_t rl = 0; - - DIR *d; - if (p[0] == '/') + + DIR* d; + if (p[0] == '/' || p[0] == '\\') { d = opendir("/"); - p = p + 1; } else { d = opendir("."); - r[0] = '.'; - r[1] = 0; + out[0] = '.'; + out[1] = 0; rl = 1; } - - int last = 0; - char *c = strsep(&p, "/"); - while (c) + + bool cantProceed = false; // just convert slashes in what's left in string, not case sensitivity + bool mayBeTrailingSlash = false; + char* c; + while (c = strsep(&p, "/\\")) { - if (!d) + // May be trailing slash(allow), slash at the start(avoid), or multiple slashes(avoid) + if (*c == '\0') { - return 0; + mayBeTrailingSlash = true; + continue; + } else { + mayBeTrailingSlash = false; } - - if (last) + + out[rl] = '/'; + rl += 1; + out[rl] = 0; + + if (cantProceed) { - closedir(d); - return 0; + strcpy(out + rl, c); + rl += strlen(c); + continue; } - - r[rl] = '/'; - rl += 1; - r[rl] = 0; - - struct dirent *e = readdir(d); - while (e) + + struct dirent* e; + while (e = readdir(d)) { if (strcasecmp(c, e->d_name) == 0) { - strcpy(r + rl, e->d_name); - rl += strlen(e->d_name); + strcpy(out + rl, e->d_name); + int reportedLen = (int)strlen(e->d_name); + rl += reportedLen; + assert(reportedLen == strlen(c) && "casepath: This is not good at all"); closedir(d); - d = opendir(r); - + d = opendir(out); + + // Either it wasn't a folder, or permission error, I/O error etc. + if (!d) { + cantProceed = true; + } + break; } - - e = readdir(d); } - + if (!e) { - strcpy(r + rl, c); + printf("casepath couldn't find dir/file \"%s\", full path was %s\n", c, path); + // No match, add original name and continue converting further slashes. + strcpy(out + rl, c); rl += strlen(c); - last = 1; + cantProceed = true; } - - c = strsep(&p, "/"); } - + if (d) closedir(d); - return 1; + if (mayBeTrailingSlash) { + out[rl] = '/'; rl += 1; + out[rl] = '\0'; + } + + if (rl > l + 2) { + printf("\n\ncasepath: Corrected path length is longer then original+2:\n\tOriginal: %s (%d chars)\n\tCorrected: %s (%d chars)\n\n", path, l, out, rl); + } + return out; } #endif diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 268eedff..69600385 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -23,7 +23,7 @@ enum eWinVersion #include "win.h" #endif extern DWORD _dwOperatingSystemVersion; - +#define fcaseopen fopen #else char *strupr(char *str); char *strlwr(char *str); @@ -43,7 +43,9 @@ enum { }; extern long _dwOperatingSystemVersion; -int casepath(char const *path, char *r); +char *casepath(char const *path, bool checkPathFirst = true); +FILE *_fcaseopen(char const *filename, char const *mode); +#define fcaseopen _fcaseopen #endif #ifdef RW_GL3 diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 408fb8f9..00bb0023 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -731,12 +731,12 @@ CHeli::SendDownSwat(void) float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, nil); if(Abs(FindPlayerCoors().z - groundZ) < 2.5f && CRopes::RegisterRope((uintptr)this + m_numSwat-1, pos, false)){ - CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_ARMY, pos); + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos); swat->bUsesCollision = false; swat->m_pRopeEntity = this; RegisterReference(&swat->m_pRopeEntity); m_numSwat--; - swat->m_nRopeID = m_numSwat; + swat->m_nRopeID = (uintptr)this + m_numSwat; m_aSwatState[m_numSwat] = 255; CAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_ABSEIL, 4.0f); return true; |