mirror of
https://github.com/halpz/re3.git
synced 2025-01-09 20:35:27 +00:00
ferries
This commit is contained in:
parent
410eb19ce6
commit
9b9ffc4b13
|
@ -1662,7 +1662,7 @@ const tScriptCommandData commands[] = {
|
||||||
REGISTER_COMMAND(COMMAND_IS_CHAR_CROUCHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""),
|
REGISTER_COMMAND(COMMAND_IS_CHAR_CROUCHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""),
|
||||||
REGISTER_COMMAND(COMMAND_GET_FERRY_BOARDING_SPACE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""),
|
REGISTER_COMMAND(COMMAND_GET_FERRY_BOARDING_SPACE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""),
|
||||||
REGISTER_COMMAND(COMMAND_GET_FERRY_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""),
|
REGISTER_COMMAND(COMMAND_GET_FERRY_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""),
|
||||||
REGISTER_COMMAND(COMMAND_SET_FERRIES_ENABLED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""),
|
REGISTER_COMMAND(COMMAND_SET_FERRIES_DISABLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""),
|
||||||
REGISTER_COMMAND(COMMAND_COMPLETE_FERRY_DOOR_MOVEMENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""),
|
REGISTER_COMMAND(COMMAND_COMPLETE_FERRY_DOOR_MOVEMENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""),
|
||||||
REGISTER_COMMAND(COMMAND_OVERRIDE_CAR_REMOTE_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""),
|
REGISTER_COMMAND(COMMAND_OVERRIDE_CAR_REMOTE_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""),
|
||||||
REGISTER_COMMAND(COMMAND_CANCEL_REMOTE_MODE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
|
REGISTER_COMMAND(COMMAND_CANCEL_REMOTE_MODE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "CarCtrl.h"
|
#include "CarCtrl.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "CutsceneMgr.h"
|
#include "CutsceneMgr.h"
|
||||||
|
#include "Ferry.h"
|
||||||
#include "Garages.h"
|
#include "Garages.h"
|
||||||
#include "GameLogic.h"
|
#include "GameLogic.h"
|
||||||
#include "Hud.h"
|
#include "Hud.h"
|
||||||
|
@ -29,22 +30,22 @@ int8 CRunningScript::ProcessCommands1500To1599(int32 command)
|
||||||
case COMMAND_DISABLE_FERRY_PATH:
|
case COMMAND_DISABLE_FERRY_PATH:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry:DissableFerryPath(GET_INTEGER_PARAM(0)); TODO
|
CFerry::DissableFerryPath(GET_INTEGER_PARAM(0));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_ENABLE_FERRY_PATH:
|
case COMMAND_ENABLE_FERRY_PATH:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry::EnableFerryPath(GET_INTEGER_PARAM(0));
|
CFerry::EnableFerryPath(GET_INTEGER_PARAM(0));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_GET_CLOSEST_DOCKED_FERRY:
|
case COMMAND_GET_CLOSEST_DOCKED_FERRY:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 2);
|
CollectParameters(&m_nIp, 2);
|
||||||
// CFerry* pFerry = CFerry::GetClosestFerry(GET_FLOAT_PARAM(0), GET_FLOAT_PARAM(1));
|
CFerry* pFerry = CFerry::GetClosestFerry(GET_FLOAT_PARAM(0), GET_FLOAT_PARAM(1));
|
||||||
int id = -1;
|
int id = -1;
|
||||||
// if (pFerry && pFerry->IsDocked()
|
if (pFerry && pFerry->IsDocked())
|
||||||
// id = pFerry->GetId();
|
id = pFerry->m_nFerryId;
|
||||||
SET_INTEGER_PARAM(0, id);
|
SET_INTEGER_PARAM(0, id);
|
||||||
StoreParameters(&m_nIp, 1);
|
StoreParameters(&m_nIp, 1);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -52,43 +53,43 @@ int8 CRunningScript::ProcessCommands1500To1599(int32 command)
|
||||||
case COMMAND_OPEN_FERRY_DOOR:
|
case COMMAND_OPEN_FERRY_DOOR:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// pFerry->OpenDoor();
|
pFerry->OpenDoor();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_CLOSE_FERRY_DOOR:
|
case COMMAND_CLOSE_FERRY_DOOR:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// pFerry->CloseDoor();
|
pFerry->CloseDoor();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_IS_FERRY_DOOR_OPEN:
|
case COMMAND_IS_FERRY_DOOR_OPEN:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// UpdateCompareFlag(pFerry->IsDoorOpen());
|
UpdateCompareFlag(pFerry->IsDoorOpen());
|
||||||
UpdateCompareFlag(false);
|
UpdateCompareFlag(false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_IS_FERRY_DOOR_CLOSED:
|
case COMMAND_IS_FERRY_DOOR_CLOSED:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// UpdateCompareFlag(pFerry->IsDoorClosed());
|
UpdateCompareFlag(pFerry->IsDoorClosed());
|
||||||
UpdateCompareFlag(true);
|
UpdateCompareFlag(true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_SKIP_FERRY_TO_NEXT_DOCK:
|
case COMMAND_SKIP_FERRY_TO_NEXT_DOCK:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// pFerry->SkipFerryToNextDock();
|
pFerry->SkipFerryToNextDock();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_SET_CHAR_DROPS_WEAPONS_ON_DEATH:
|
case COMMAND_SET_CHAR_DROPS_WEAPONS_ON_DEATH:
|
||||||
|
@ -110,35 +111,36 @@ int8 CRunningScript::ProcessCommands1500To1599(int32 command)
|
||||||
case COMMAND_GET_FERRY_BOARDING_SPACE:
|
case COMMAND_GET_FERRY_BOARDING_SPACE:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 4);
|
CollectParameters(&m_nIp, 4);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// ? = pFerry->GetBoardingSpace((CFerry::eSpaceUse)GET_INTEGER_PARAMS(1), (CFerry::eSpaceStyle)GET_INTEGER_PARAMS(2), GET_INTEGER_PARAMS(3));
|
CVector space = pFerry->GetBoardingSpace((CFerry::eSpaceUse)GET_INTEGER_PARAM(1), (CFerry::eSpaceStyle)GET_INTEGER_PARAM(2), GET_INTEGER_PARAM(3));
|
||||||
SET_FLOAT_PARAM(0, 0.0f);
|
SET_FLOAT_PARAM(0, space.x);
|
||||||
SET_FLOAT_PARAM(1, 0.0f); // TODO
|
SET_FLOAT_PARAM(1, space.y);
|
||||||
StoreParameters(&m_nIp, 2);
|
StoreParameters(&m_nIp, 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_GET_FERRY_HEADING:
|
case COMMAND_GET_FERRY_HEADING:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
// script_assert(pFerry);
|
script_assert(pFerry);
|
||||||
// float fHeading = CGeneral::GetATanOfXY(pFerry->GetForward().x, pFerry->GetForward().y);
|
float fHeading = Atan2(-pFerry->GetForward().x, pFerry->GetForward().y);
|
||||||
// SET_FLOAT_PARAM(0, fHeading);
|
SET_FLOAT_PARAM(0, fHeading);
|
||||||
SET_FLOAT_PARAM(0, 0.0f);
|
|
||||||
StoreParameters(&m_nIp, 1);
|
StoreParameters(&m_nIp, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_SET_FERRIES_ENABLED:
|
case COMMAND_SET_FERRIES_DISABLED:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 2);
|
||||||
// CFerry::SetFerriesEnabled(GET_INTEGER_PARAM(0));
|
CFerry::SetFerriesDisabled(GET_INTEGER_PARAM(1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_COMPLETE_FERRY_DOOR_MOVEMENT:
|
case COMMAND_COMPLETE_FERRY_DOOR_MOVEMENT:
|
||||||
{
|
{
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry::CompleteDorrMovement(GET_INTEGER_PARAM(0));
|
CFerry* pFerry = CFerry::GetFerry(GET_INTEGER_PARAM(0));
|
||||||
|
script_assert(pFerry);
|
||||||
|
pFerry->CompleteDorrMovement();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_OVERRIDE_CAR_REMOTE_CONTROL:
|
case COMMAND_OVERRIDE_CAR_REMOTE_CONTROL:
|
||||||
|
@ -157,7 +159,7 @@ int8 CRunningScript::ProcessCommands1500To1599(int32 command)
|
||||||
else {
|
else {
|
||||||
TheCamera.TakeControl(pVehicle, CCam::MODE_1STPERSON, GET_INTEGER_PARAM(1) ? INTERPOLATION : JUMP_CUT, CAMCONTROL_SCRIPT);
|
TheCamera.TakeControl(pVehicle, CCam::MODE_1STPERSON, GET_INTEGER_PARAM(1) ? INTERPOLATION : JUMP_CUT, CAMCONTROL_SCRIPT);
|
||||||
script_assert(pVehicle->IsCar());
|
script_assert(pVehicle->IsCar());
|
||||||
//((CAutomobile*)pVehicle)->Damage.m_bSmashedDoorDoesntClose = true;
|
((CAutomobile*)pVehicle)->Damage.m_bSmashedDoorDoesntClose = true;
|
||||||
}
|
}
|
||||||
if (m_bIsMissionScript)
|
if (m_bIsMissionScript)
|
||||||
CTheScripts::MissionCleanUp.RemoveEntityFromList(GET_INTEGER_PARAM(0), CLEANUP_CAR);
|
CTheScripts::MissionCleanUp.RemoveEntityFromList(GET_INTEGER_PARAM(0), CLEANUP_CAR);
|
||||||
|
@ -670,7 +672,7 @@ int8 CRunningScript::ProcessCommands1500To1599(int32 command)
|
||||||
}
|
}
|
||||||
case COMMAND_SWITCH_FERRY_COLLISION:
|
case COMMAND_SWITCH_FERRY_COLLISION:
|
||||||
CollectParameters(&m_nIp, 1);
|
CollectParameters(&m_nIp, 1);
|
||||||
// CFerry::SwitchFerryCollision(GET_INTEGER_PARAM(0));
|
CFerry::SwitchFerryCollision(GET_INTEGER_PARAM(0));
|
||||||
return 0;
|
return 0;
|
||||||
case COMMAND_SET_CHAR_MAX_HEALTH:
|
case COMMAND_SET_CHAR_MAX_HEALTH:
|
||||||
{
|
{
|
||||||
|
|
|
@ -1510,7 +1510,7 @@ enum {
|
||||||
COMMAND_IS_CHAR_CROUCHING,
|
COMMAND_IS_CHAR_CROUCHING,
|
||||||
COMMAND_GET_FERRY_BOARDING_SPACE,
|
COMMAND_GET_FERRY_BOARDING_SPACE,
|
||||||
COMMAND_GET_FERRY_HEADING,
|
COMMAND_GET_FERRY_HEADING,
|
||||||
COMMAND_SET_FERRIES_ENABLED,
|
COMMAND_SET_FERRIES_DISABLED,
|
||||||
COMMAND_COMPLETE_FERRY_DOOR_MOVEMENT,
|
COMMAND_COMPLETE_FERRY_DOOR_MOVEMENT,
|
||||||
COMMAND_OVERRIDE_CAR_REMOTE_CONTROL,
|
COMMAND_OVERRIDE_CAR_REMOTE_CONTROL,
|
||||||
COMMAND_CANCEL_REMOTE_MODE,
|
COMMAND_CANCEL_REMOTE_MODE,
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "Darkel.h"
|
#include "Darkel.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "EventList.h"
|
#include "EventList.h"
|
||||||
|
#include "Ferry.h"
|
||||||
#include "FileLoader.h"
|
#include "FileLoader.h"
|
||||||
#include "FileMgr.h"
|
#include "FileMgr.h"
|
||||||
#include "Fire.h"
|
#include "Fire.h"
|
||||||
|
@ -539,6 +540,7 @@ bool CGame::Initialise(const char* datFile)
|
||||||
LoadingScreen("Loading the Game", "Position dynamic objects", nil);
|
LoadingScreen("Loading the Game", "Position dynamic objects", nil);
|
||||||
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
|
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
|
||||||
|
|
||||||
|
CFerry::InitFerrys();
|
||||||
CTrain::InitTrains();
|
CTrain::InitTrains();
|
||||||
CPlane::InitPlanes();
|
CPlane::InitPlanes();
|
||||||
CCredits::Init();
|
CCredits::Init();
|
||||||
|
@ -713,6 +715,7 @@ void CGame::ReInitGameObjectVariables(void)
|
||||||
CTheScripts::StartTestScript();
|
CTheScripts::StartTestScript();
|
||||||
CTheScripts::Process();
|
CTheScripts::Process();
|
||||||
TheCamera.Process();
|
TheCamera.Process();
|
||||||
|
CFerry::InitFerrys();
|
||||||
CTrain::InitTrains();
|
CTrain::InitTrains();
|
||||||
CPlane::InitPlanes();
|
CPlane::InitPlanes();
|
||||||
}
|
}
|
||||||
|
@ -798,6 +801,7 @@ void CGame::InitialiseWhenRestarting(void)
|
||||||
if ( GenericLoad() == true )
|
if ( GenericLoad() == true )
|
||||||
{
|
{
|
||||||
DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds());
|
DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds());
|
||||||
|
CFerry::InitFerrys();
|
||||||
CTrain::InitTrains();
|
CTrain::InitTrains();
|
||||||
CPlane::InitPlanes();
|
CPlane::InitPlanes();
|
||||||
}
|
}
|
||||||
|
@ -881,6 +885,7 @@ void CGame::Process(void)
|
||||||
|
|
||||||
CCollision::Update();
|
CCollision::Update();
|
||||||
CScriptPaths::Update();
|
CScriptPaths::Update();
|
||||||
|
CFerry::UpdateFerrys();
|
||||||
CTrain::UpdateTrains();
|
CTrain::UpdateTrains();
|
||||||
CPlane::UpdatePlanes();
|
CPlane::UpdatePlanes();
|
||||||
CHeli::UpdateHelis();
|
CHeli::UpdateHelis();
|
||||||
|
|
|
@ -146,7 +146,9 @@ enum Config {
|
||||||
NUM_EXPLOSIONS = 48,
|
NUM_EXPLOSIONS = 48,
|
||||||
|
|
||||||
NUM_SETPIECES = 96,
|
NUM_SETPIECES = 96,
|
||||||
NUM_SHORTCUT_START_POINTS = 16
|
NUM_SHORTCUT_START_POINTS = 16,
|
||||||
|
|
||||||
|
NUM_FERRY_PATHS = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// We don't expect to compile for PS2 or Xbox
|
// We don't expect to compile for PS2 or Xbox
|
||||||
|
|
|
@ -24,11 +24,13 @@ enum eEntityStatus
|
||||||
STATUS_PHYSICS,
|
STATUS_PHYSICS,
|
||||||
STATUS_ABANDONED,
|
STATUS_ABANDONED,
|
||||||
STATUS_WRECKED,
|
STATUS_WRECKED,
|
||||||
STATUS_TRAIN_MOVING, // these probably copied for FERRY
|
STATUS_TRAIN_MOVING,
|
||||||
STATUS_TRAIN_NOT_MOVING,
|
STATUS_TRAIN_NOT_MOVING,
|
||||||
|
STATUS_FERRY_MOVING,
|
||||||
|
STATUS_FERRY_NOT_MOVING,
|
||||||
STATUS_HELI,
|
STATUS_HELI,
|
||||||
STATUS_PLANE,
|
STATUS_PLANE,
|
||||||
STATUS_PLAYER_REMOTE, // 12 in LCS
|
STATUS_PLAYER_REMOTE,
|
||||||
STATUS_PLAYER_DISABLED,
|
STATUS_PLAYER_DISABLED,
|
||||||
STATUS_GHOST
|
STATUS_GHOST
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "custompipes.h"
|
#include "custompipes.h"
|
||||||
#include "Frontend.h"
|
#include "Frontend.h"
|
||||||
|
#include "Ferry.h"
|
||||||
|
|
||||||
bool gbShowPedRoadGroups;
|
bool gbShowPedRoadGroups;
|
||||||
bool gbShowCarRoadGroups;
|
bool gbShowCarRoadGroups;
|
||||||
|
@ -522,6 +523,8 @@ CRenderer::RenderVehicles(void)
|
||||||
node != &gSortedVehiclesAndPeds.head;
|
node != &gSortedVehiclesAndPeds.head;
|
||||||
node = node->prev)
|
node = node->prev)
|
||||||
RenderOneNonRoad(node->item.ent);
|
RenderOneNonRoad(node->item.ent);
|
||||||
|
|
||||||
|
CFerry::RenderAllRemaning();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
822
src/vehicles/Ferry.cpp
Normal file
822
src/vehicles/Ferry.cpp
Normal file
|
@ -0,0 +1,822 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "Ferry.h"
|
||||||
|
|
||||||
|
#include "AudioManager.h"
|
||||||
|
#include "Camera.h"
|
||||||
|
#include "Coronas.h"
|
||||||
|
#include "FileMgr.h"
|
||||||
|
#include "General.h"
|
||||||
|
#include "Leeds.h"
|
||||||
|
#include "Particle.h"
|
||||||
|
#include "PlayerPed.h"
|
||||||
|
#include "Streaming.h"
|
||||||
|
#include "TempColModels.h"
|
||||||
|
#include "WaterLevel.h"
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
CFerryInst* CFerry::mspInst;
|
||||||
|
|
||||||
|
#define FERRY_SPEED (0.1f)
|
||||||
|
#define FERRY_SLOWDOWN_DISTANCE (50.0f)
|
||||||
|
#define FERRY_TIME_STOPPED_AT_STATION (10.0f)
|
||||||
|
|
||||||
|
CFerry::CFerry(int32 id, uint8 owner) : CVehicle(owner)
|
||||||
|
{
|
||||||
|
m_bPlayerArrivedHorn = false;
|
||||||
|
m_nTimeAlongPath = 0;
|
||||||
|
m_vehType = VEHICLE_TYPE_FERRY;
|
||||||
|
CVehicleModelInfo* mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
|
||||||
|
pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);
|
||||||
|
SetModelIndex(id);
|
||||||
|
m_doors[0].Init(DEGTORAD(90.0f), 0.0f, 1, 0);
|
||||||
|
m_doors[1].Init(DEGTORAD(-95.0f), 0.0f, 1, 0);
|
||||||
|
m_doors[2].Init(DEGTORAD(-90.0f), 0.0f, 1, 0);
|
||||||
|
m_doors[3].Init(DEGTORAD(95.0f), 0.0f, 1, 0);
|
||||||
|
m_fTurnMass = 100000000.0f;
|
||||||
|
m_fAirResistance = 0.9994f;
|
||||||
|
m_fElasticity = 0.05f;
|
||||||
|
m_nNumMaxPassengers = 1;
|
||||||
|
m_fMass = 100000000.0f;
|
||||||
|
bInfiniteMass = true;
|
||||||
|
m_phy_flagA08 = true;
|
||||||
|
m_bFerryDocked = false;
|
||||||
|
SetStatus(STATUS_FERRY_MOVING);
|
||||||
|
bUsesCollision = true;
|
||||||
|
m_nDoorTimer = CTimer::GetTimeInMilliseconds();
|
||||||
|
m_nDoorState = FERRY_DOOR_CLOSED;
|
||||||
|
m_bApproachingDock = false;
|
||||||
|
m_nSkipFerryStatus = 0;
|
||||||
|
m_nCollision = 0;
|
||||||
|
m_pDefaultColModel = mi->GetColModel();
|
||||||
|
m_level = LEVEL_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::Init(void* pInstancePtr)
|
||||||
|
{
|
||||||
|
mspInst = (CFerryInst*)pInstancePtr;
|
||||||
|
if (mspInst)
|
||||||
|
return;
|
||||||
|
// the following code should be wrapped in a define
|
||||||
|
mspInst = new CFerryInst();
|
||||||
|
memset(mspInst, 0, sizeof(CFerryInst));
|
||||||
|
for (int k = 0; k < NUM_FERRY_PATHS; k++) {
|
||||||
|
mspInst->pPathData[k] = new CFerryPath();
|
||||||
|
mspInst->pPathData[k]->aLineBits = new CFerryInterpolationLine[NUM_FERRY_STATIONS * 4 + 2];
|
||||||
|
|
||||||
|
const char* filename = "Data\\PATHS\\FERRY1.DAT"; // actually base::cStringT<char> filename; filename += k+1; filename += ".DAT"
|
||||||
|
|
||||||
|
bool readingFile = false;
|
||||||
|
int bp, lp;
|
||||||
|
int i, tmp;
|
||||||
|
CFerryPath* pPath = mspInst->pPathData[k];
|
||||||
|
|
||||||
|
if (pPath->aTrackNodes == nil) {
|
||||||
|
readingFile = true;
|
||||||
|
|
||||||
|
CFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), "r");
|
||||||
|
*gString = '\0';
|
||||||
|
for (bp = 0, lp = 0; work_buff[bp] != '\n'; bp++, lp++)
|
||||||
|
gString[lp] = work_buff[bp];
|
||||||
|
bp++;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
gString[lp] = '\0';
|
||||||
|
#endif
|
||||||
|
sscanf(gString, "%d", &tmp);
|
||||||
|
pPath->NumTrackNodes = tmp;
|
||||||
|
pPath->aTrackNodes = new CFerryNode[tmp];
|
||||||
|
|
||||||
|
for (i = 0; i < pPath->NumTrackNodes; i++) {
|
||||||
|
*gString = '\0';
|
||||||
|
for (lp = 0; work_buff[bp] != '\n'; bp++, lp++)
|
||||||
|
gString[lp] = work_buff[bp];
|
||||||
|
bp++;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
gString[lp] = '\0';
|
||||||
|
#endif
|
||||||
|
sscanf(gString, "%f %f %f", &pPath->aTrackNodes[i].x, &pPath->aTrackNodes[i].y, &pPath->aTrackNodes[i].z);
|
||||||
|
pPath->aTrackNodes[i].z = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate length of segments and track
|
||||||
|
float t = 0.0f;
|
||||||
|
for (i = 0; i < pPath->NumTrackNodes; i++) {
|
||||||
|
pPath->aTrackNodes[i].t = t;
|
||||||
|
t += Sqrt(SQR(pPath->aTrackNodes[(i + 1) % pPath->NumTrackNodes].x - pPath->aTrackNodes[i].x)) +
|
||||||
|
(SQR(pPath->aTrackNodes[(i + 1) % pPath->NumTrackNodes].y - pPath->aTrackNodes[i].y));
|
||||||
|
}
|
||||||
|
pPath->TotalLengthOfTrack = t;
|
||||||
|
|
||||||
|
// Find correct z values
|
||||||
|
if (readingFile) {
|
||||||
|
CColPoint colpoint;
|
||||||
|
CEntity* entity;
|
||||||
|
for (i = 0; i < pPath->NumTrackNodes; i++) {
|
||||||
|
CVector p(pPath->aTrackNodes[i].x, pPath->aTrackNodes[i].y, pPath->aTrackNodes[i].z + 1.0f);
|
||||||
|
if (CWorld::ProcessVerticalLine(p, p.z - 0.5f, colpoint, entity, true, false, false, false, true, false, nil))
|
||||||
|
pPath->aTrackNodes[i].z = colpoint.point.z;
|
||||||
|
pPath->aTrackNodes[i].z += 0.2f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nStationIndices[NUM_FERRY_STATIONS];
|
||||||
|
for (int i = 0; i < NUM_FERRY_STATIONS; i++)
|
||||||
|
nStationIndices[i] = 0;
|
||||||
|
int nCurrentStation = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < pPath->NumTrackNodes; i++) {
|
||||||
|
CFerryNode* pCurNode = &pPath->aTrackNodes[i];
|
||||||
|
CFerryNode* pNextNode = (i + 1 < pPath->NumTrackNodes) ? &pPath->aTrackNodes[i + 1] : &pPath->aTrackNodes[0];
|
||||||
|
CFerryNode* pPrevNode = (i - 1 >= 0) ? &pPath->aTrackNodes[i - 1] : &pPath->aTrackNodes[pPath->NumTrackNodes - 1];
|
||||||
|
if (pCurNode->x - pNextNode->x > 0.0f && pPrevNode->x - pCurNode->x < 0.0f)
|
||||||
|
nStationIndices[nCurrentStation++] = i;
|
||||||
|
if (pCurNode->x - pNextNode->x < 0.0f && pPrevNode->x - pCurNode->x > 0.0f)
|
||||||
|
nStationIndices[nCurrentStation++] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
float stationDists[NUM_FERRY_STATIONS];
|
||||||
|
for (i = 0; i < NUM_FERRY_STATIONS; i++)
|
||||||
|
stationDists[i] = pPath->aTrackNodes[nStationIndices[i]].t;
|
||||||
|
|
||||||
|
// Create animation for stopping at stations
|
||||||
|
float position = 0.0f;
|
||||||
|
float time = 0.0f;
|
||||||
|
int j = 0;
|
||||||
|
for (i = 0; i < NUM_FERRY_STATIONS; i++) {
|
||||||
|
// Start at full speed
|
||||||
|
pPath->aLineBits[j].type = FERRY_CRUISING;
|
||||||
|
pPath->aLineBits[j].time = time;
|
||||||
|
pPath->aLineBits[j].position = position;
|
||||||
|
pPath->aLineBits[j].speed = FERRY_SPEED;
|
||||||
|
pPath->aLineBits[j].acceleration = 0.0f;
|
||||||
|
j++;
|
||||||
|
// distance to next keyframe
|
||||||
|
float dist = (stationDists[i] - FERRY_SLOWDOWN_DISTANCE) - position;
|
||||||
|
time += dist / FERRY_SPEED;
|
||||||
|
position += dist;
|
||||||
|
|
||||||
|
// Now slow down 50 units before stop
|
||||||
|
pPath->aLineBits[j].type = FERRY_SLOWING;
|
||||||
|
pPath->aLineBits[j].time = time;
|
||||||
|
pPath->aLineBits[j].position = position;
|
||||||
|
pPath->aLineBits[j].speed = FERRY_SPEED;
|
||||||
|
pPath->aLineBits[j].acceleration = -(FERRY_SPEED * FERRY_SPEED) / (4 * FERRY_SLOWDOWN_DISTANCE);
|
||||||
|
j++;
|
||||||
|
time += 2 * FERRY_SLOWDOWN_DISTANCE / FERRY_SPEED;
|
||||||
|
position += FERRY_SLOWDOWN_DISTANCE; // at station
|
||||||
|
|
||||||
|
// stopping
|
||||||
|
pPath->aLineBits[j].type = FERRY_STOPPED;
|
||||||
|
pPath->aLineBits[j].time = time;
|
||||||
|
pPath->aLineBits[j].position = position;
|
||||||
|
pPath->aLineBits[j].speed = 0.0f;
|
||||||
|
pPath->aLineBits[j].acceleration = 0.0f;
|
||||||
|
j++;
|
||||||
|
time += FERRY_TIME_STOPPED_AT_STATION;
|
||||||
|
|
||||||
|
// accelerate again
|
||||||
|
pPath->aLineBits[j].type = FERRY_ACCELERATING;
|
||||||
|
pPath->aLineBits[j].time = time;
|
||||||
|
pPath->aLineBits[j].position = position;
|
||||||
|
pPath->aLineBits[j].speed = 0.0f;
|
||||||
|
pPath->aLineBits[j].acceleration = (FERRY_SPEED * FERRY_SPEED) / (4 * FERRY_SLOWDOWN_DISTANCE);
|
||||||
|
j++;
|
||||||
|
time += 2 * FERRY_SLOWDOWN_DISTANCE / FERRY_SPEED;
|
||||||
|
position += FERRY_SLOWDOWN_DISTANCE; // after station
|
||||||
|
}
|
||||||
|
// last keyframe
|
||||||
|
pPath->aLineBits[j].type = FERRY_CRUISING;
|
||||||
|
pPath->aLineBits[j].time = time;
|
||||||
|
pPath->aLineBits[j].position = position;
|
||||||
|
pPath->aLineBits[j].speed = FERRY_SPEED;
|
||||||
|
pPath->aLineBits[j].acceleration = 0.0f;
|
||||||
|
j++;
|
||||||
|
pPath->TotalDurationOfTrack = time + (pPath->TotalLengthOfTrack - position) / FERRY_SPEED;
|
||||||
|
|
||||||
|
// end
|
||||||
|
pPath->aLineBits[j].time = pPath->TotalDurationOfTrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::InitFerrys(void)
|
||||||
|
{
|
||||||
|
if (!mspInst)
|
||||||
|
Init(nil);
|
||||||
|
for (int i = 0; i < NUM_FERRIES; i++)
|
||||||
|
mspInst->m_apFerries[i] = nil;
|
||||||
|
CStreaming::LoadAllRequestedModels(false);
|
||||||
|
CStreaming::RequestModel(MI_FERRY, 0);
|
||||||
|
CStreaming::LoadAllRequestedModels(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::SwitchFerryCollision(int type)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_FERRIES; i++) {
|
||||||
|
CFerry* pFerry = GetFerry(i);
|
||||||
|
if (pFerry && pFerry->m_nCollision != type) {
|
||||||
|
pFerry->m_nCollision = type;
|
||||||
|
CVehicleModelInfo* mi = pFerry->GetModelInfo();
|
||||||
|
if (type == 1)
|
||||||
|
mi->SetColModel(&CTempColModels::ms_colModelFerryDocked);
|
||||||
|
else
|
||||||
|
mi->SetColModel(pFerry->m_pDefaultColModel, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::UpdateFerrys(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
float t, deltaT;
|
||||||
|
if (mspInst->m_bFerriesDisabled)
|
||||||
|
return;
|
||||||
|
for (i = 0; i < NUM_FERRIES; i++) {
|
||||||
|
CFerry* pFerry = GetFerry(i);
|
||||||
|
if (pFerry) {
|
||||||
|
pFerry->m_nTimeAlongPath += CTimer::GetTimeStepInMilliseconds();
|
||||||
|
t = mspInst->pPathData[i/2]->TotalDurationOfTrack * (float)((pFerry->m_nTimeAlongPath + (i & 1) * 0x20000) & 0x3FFFF) / 0x40000;
|
||||||
|
// find current frame
|
||||||
|
for (j = 0; t > mspInst->pPathData[i / 2]->aLineBits[j + 1].time; j++);
|
||||||
|
|
||||||
|
deltaT = t - mspInst->pPathData[i / 2]->aLineBits[j].time;
|
||||||
|
if (pFerry->m_bFerryDocked) {
|
||||||
|
if (mspInst->pPathData[i / 2]->aLineBits[j].type == FERRY_SLOWING) {
|
||||||
|
pFerry->m_nTimeAlongPath += (mspInst->pPathData[i / 2]->aLineBits[j + 1].time - mspInst->pPathData[i / 2]->aLineBits[j].time);
|
||||||
|
j++;
|
||||||
|
if (j > NUM_FERRY_STATIONS * 4 + 1)
|
||||||
|
j = 0;
|
||||||
|
pFerry->m_bApproachingDock = true;
|
||||||
|
if ((i & 1) == 0) {
|
||||||
|
GetFerry(i + 1)->m_bApproachingDock = true;
|
||||||
|
GetFerry(i + 1)->m_nTimeAlongPath += (mspInst->pPathData[i / 2]->aLineBits[j + 1].time - mspInst->pPathData[i / 2]->aLineBits[j].time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GetFerry(i - 1)->m_bApproachingDock = true;
|
||||||
|
GetFerry(i - 1)->m_nTimeAlongPath += (mspInst->pPathData[i / 2]->aLineBits[j + 1].time - mspInst->pPathData[i / 2]->aLineBits[j].time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pFerry->m_nSkipFerryStatus == 1) {
|
||||||
|
float fDelta = 0.0f;
|
||||||
|
pFerry->m_nSkipFerryStatus = 2;
|
||||||
|
while (mspInst->pPathData[i / 2]->aLineBits[j].type != FERRY_STOPPED) {
|
||||||
|
fDelta += (mspInst->pPathData[i / 2]->aLineBits[j + 1].time - mspInst->pPathData[i / 2]->aLineBits[j].time);
|
||||||
|
j++;
|
||||||
|
if (j > NUM_FERRY_STATIONS * 4)
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
pFerry->m_nTimeAlongPath += fDelta;
|
||||||
|
pFerry->m_bApproachingDock = true;
|
||||||
|
if ((i & 1) == 0) {
|
||||||
|
GetFerry(i + 1)->m_bApproachingDock = true;
|
||||||
|
GetFerry(i + 1)->m_nTimeAlongPath += fDelta;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GetFerry(i - 1)->m_bApproachingDock = true;
|
||||||
|
GetFerry(i - 1)->m_nTimeAlongPath += fDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (mspInst->pPathData[i / 2]->aLineBits[j].type) {
|
||||||
|
case FERRY_STOPPED:
|
||||||
|
mspInst->m_afPositions[i] = mspInst->pPathData[i / 2]->aLineBits[j].position;
|
||||||
|
mspInst->m_afSpeeds[i] = 0.0f;
|
||||||
|
break;
|
||||||
|
case FERRY_CRUISING:
|
||||||
|
mspInst->m_afPositions[i] = mspInst->pPathData[i / 2]->aLineBits[j].position + mspInst->pPathData[i / 2]->aLineBits[j].speed * deltaT;
|
||||||
|
mspInst->m_afSpeeds[i] = (mspInst->pPathData[i / 2]->TotalDurationOfTrack * 1000.0f / 0x40000) * mspInst->pPathData[i / 2]->aLineBits[j].speed;
|
||||||
|
break;
|
||||||
|
case FERRY_SLOWING:
|
||||||
|
case FERRY_ACCELERATING:
|
||||||
|
pFerry->m_bApproachingDock = (mspInst->pPathData[i / 2]->aLineBits[j].type == FERRY_SLOWING);
|
||||||
|
mspInst->m_afPositions[i] = mspInst->pPathData[i / 2]->aLineBits[j].position + (mspInst->pPathData[i / 2]->aLineBits[j].speed + mspInst->pPathData[i / 2]->aLineBits[j].acceleration * deltaT) * deltaT;
|
||||||
|
mspInst->m_afSpeeds[i] = (mspInst->pPathData[i / 2]->TotalDurationOfTrack * 1000.0f / 0x40000) * (mspInst->pPathData[i / 2]->aLineBits[j].speed + 2 * mspInst->pPathData[i / 2]->aLineBits[j].acceleration * deltaT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::SetModelIndex(uint32 mi)
|
||||||
|
{
|
||||||
|
CVehicle::SetModelIndex(mi);
|
||||||
|
for (int i = 0; i < NUM_FERRY_NODES; i++)
|
||||||
|
m_aFerryNodes[i] = nil;
|
||||||
|
CClumpModelInfo::FillFrameArray(GetClump(), m_aFerryNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::PreRender(void)
|
||||||
|
{
|
||||||
|
CVehicleModelInfo* mi = GetModelInfo();
|
||||||
|
if (CGeneral::GetRandomTrueFalse())
|
||||||
|
CParticle::AddParticle(PARTICLE_FERRY_CHIM_SMOKE, GetMatrix() * mi->m_positions[FERRY_POS_CHIM_LEFT], CVector(0.0f, 0.0f, 0.2f));
|
||||||
|
CVector vVectorToCamera = GetPosition() - TheCamera.GetPosition();
|
||||||
|
CVector vDirectionToCamera;
|
||||||
|
float fDistanceToCamera = vVectorToCamera.Magnitude();
|
||||||
|
if (fDistanceToCamera == 0.0f)
|
||||||
|
vVectorToCamera = vDirectionToCamera = CVector(1.0f, 0.0f, 0.0f);
|
||||||
|
else
|
||||||
|
vDirectionToCamera = vVectorToCamera / fDistanceToCamera;
|
||||||
|
float dp = DotProduct(GetForward(), vDirectionToCamera);
|
||||||
|
if (dp < 0.0f) {
|
||||||
|
CVector vFrontLightPosition = GetMatrix() * mi->m_positions[FERRY_POS_LIGHT_FRONT];
|
||||||
|
CVector vFrontLightPosition2 = vFrontLightPosition - 2 * mi->m_positions[FERRY_POS_LIGHT_FRONT].x * GetRight();
|
||||||
|
float size = -dp + 1.0f;
|
||||||
|
float fIntensity = -dp * 0.4f + 0.2f;
|
||||||
|
if (dp < -0.9f && fDistanceToCamera < 35.0f) {
|
||||||
|
uint8 intensity = fIntensity * 255.0f;
|
||||||
|
CCoronas::RegisterCorona((uint32)(uintptr)this + 26, intensity, intensity, intensity, 255, vFrontLightPosition2, size, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
|
||||||
|
CCoronas::RegisterCorona((uint32)(uintptr)this + 27, intensity, intensity, intensity, 255, vFrontLightPosition, size, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint8 intensity = fIntensity * 255.0f;
|
||||||
|
CCoronas::RegisterCorona((uint32)(uintptr)this + 26, intensity, intensity, intensity, 255, vFrontLightPosition2, size, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
|
||||||
|
CCoronas::RegisterCorona((uint32)(uintptr)this + 27, intensity, intensity, intensity, 255, vFrontLightPosition, size, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CVector vRearLightPosition = GetMatrix() * mi->m_positions[FERRY_POS_LIGHT_REAR];
|
||||||
|
CVector vRearLightPosition2 = vRearLightPosition - 2 * mi->m_positions[FERRY_POS_LIGHT_REAR].x * GetRight();
|
||||||
|
CCoronas::RegisterCorona((uint32)(uintptr)this + 28, 255, 0, 0, 255, vRearLightPosition2, 1.0f, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
|
||||||
|
CCoronas::RegisterCorona((uint32)(uintptr)this + 29, 255, 0, 0, 255, vRearLightPosition, 1.0f, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::Render(void)
|
||||||
|
{
|
||||||
|
m_bAlreadyRendered = true;
|
||||||
|
CEntity::Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::RenderAllRemaning(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_FERRIES; i++) {
|
||||||
|
CFerry* pFerry = GetFerry(i);
|
||||||
|
if (pFerry) {
|
||||||
|
if (!pFerry->m_bAlreadyRendered)
|
||||||
|
pFerry->Render();
|
||||||
|
pFerry->m_bAlreadyRendered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::FerryHitStuff(CPtrList& lst)
|
||||||
|
{
|
||||||
|
for (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next) {
|
||||||
|
CPhysical* pEntity = (CPhysical*)pNode->item;
|
||||||
|
if (pEntity != this && Abs(GetPosition().x - pEntity->GetPosition().z) < 1.5f)
|
||||||
|
pEntity->bHitByTrain = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::ProcessControl(void)
|
||||||
|
{
|
||||||
|
if (gbModelViewer)
|
||||||
|
return;
|
||||||
|
PruneWakeTrail();
|
||||||
|
if (m_isFarAway && (m_nFerryId + CTimer::GetFrameCounter() & 0xF) != 0)
|
||||||
|
return;
|
||||||
|
CFerryPath* pPath = mspInst->pPathData[m_nFerryId / 2];
|
||||||
|
float fPosition = mspInst->m_afPositions[m_nFerryId];
|
||||||
|
float fSpeed = mspInst->m_afSpeeds[m_nFerryId];
|
||||||
|
if (fPosition < 0.0f)
|
||||||
|
fPosition += pPath->TotalLengthOfTrack;
|
||||||
|
|
||||||
|
CFerryNode* trackNodes = mspInst->pPathData[m_nFerryId / 2]->aTrackNodes;
|
||||||
|
int16 numTrackNodes = mspInst->pPathData[m_nFerryId / 2]->NumTrackNodes;
|
||||||
|
float totalLengthOfTrack = mspInst->pPathData[m_nFerryId / 2]->TotalLengthOfTrack;
|
||||||
|
float trackPosition = mspInst->m_afPositions[m_nFerryId];
|
||||||
|
float trackSpeed = mspInst->m_afSpeeds[m_nFerryId];
|
||||||
|
|
||||||
|
float trackPositionRear = trackPosition;
|
||||||
|
if (trackPositionRear < 0.0f)
|
||||||
|
trackPositionRear += totalLengthOfTrack;
|
||||||
|
|
||||||
|
// Advance current node to appropriate position
|
||||||
|
float pos1, pos2;
|
||||||
|
int nextTrackNode = m_nCurTrackNode + 1;
|
||||||
|
pos1 = trackNodes[m_nCurTrackNode].t;
|
||||||
|
if (nextTrackNode < numTrackNodes)
|
||||||
|
pos2 = trackNodes[nextTrackNode].t;
|
||||||
|
else {
|
||||||
|
nextTrackNode = 0;
|
||||||
|
pos2 = totalLengthOfTrack;
|
||||||
|
}
|
||||||
|
while (trackPositionRear < pos1 || trackPositionRear > pos2) {
|
||||||
|
m_nCurTrackNode = (m_nCurTrackNode + 1) % numTrackNodes;
|
||||||
|
nextTrackNode = m_nCurTrackNode + 1;
|
||||||
|
pos1 = trackNodes[m_nCurTrackNode].t;
|
||||||
|
if (nextTrackNode < numTrackNodes)
|
||||||
|
pos2 = trackNodes[nextTrackNode].t;
|
||||||
|
else {
|
||||||
|
nextTrackNode = 0;
|
||||||
|
pos2 = totalLengthOfTrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float dist = trackNodes[nextTrackNode].t - trackNodes[m_nCurTrackNode].t;
|
||||||
|
if (dist < 0.0f)
|
||||||
|
dist += totalLengthOfTrack;
|
||||||
|
float f = (trackPositionRear - trackNodes[m_nCurTrackNode].t) / dist;
|
||||||
|
CVector posRear = (1.0f - f) * CVector(trackNodes[m_nCurTrackNode].x, trackNodes[m_nCurTrackNode].y, trackNodes[m_nCurTrackNode].z) +
|
||||||
|
f * CVector(trackNodes[nextTrackNode].x, trackNodes[nextTrackNode].y, trackNodes[nextTrackNode].z);
|
||||||
|
|
||||||
|
// Now same again for the front
|
||||||
|
float trackPositionFront = trackPositionRear + 20.0f;
|
||||||
|
if (trackPositionFront > totalLengthOfTrack)
|
||||||
|
trackPositionFront -= totalLengthOfTrack;
|
||||||
|
int curTrackNodeFront = m_nCurTrackNode;
|
||||||
|
int nextTrackNodeFront = curTrackNodeFront + 1;
|
||||||
|
pos1 = trackNodes[curTrackNodeFront].t;
|
||||||
|
if (nextTrackNodeFront < numTrackNodes)
|
||||||
|
pos2 = trackNodes[nextTrackNodeFront].t;
|
||||||
|
else {
|
||||||
|
nextTrackNodeFront = 0;
|
||||||
|
pos2 = totalLengthOfTrack;
|
||||||
|
}
|
||||||
|
while (trackPositionFront < pos1 || trackPositionFront > pos2) {
|
||||||
|
curTrackNodeFront = (curTrackNodeFront + 1) % numTrackNodes;
|
||||||
|
nextTrackNodeFront = curTrackNodeFront + 1;
|
||||||
|
pos1 = trackNodes[curTrackNodeFront].t;
|
||||||
|
if (nextTrackNodeFront < numTrackNodes)
|
||||||
|
pos2 = trackNodes[nextTrackNodeFront].t;
|
||||||
|
else {
|
||||||
|
nextTrackNodeFront = 0;
|
||||||
|
pos2 = totalLengthOfTrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dist = trackNodes[nextTrackNodeFront].t - trackNodes[curTrackNodeFront].t;
|
||||||
|
if (dist < 0.0f)
|
||||||
|
dist += totalLengthOfTrack;
|
||||||
|
f = (trackPositionFront - trackNodes[curTrackNodeFront].t) / dist;
|
||||||
|
CVector posFront = (1.0f - f) * CVector(trackNodes[curTrackNodeFront].x, trackNodes[curTrackNodeFront].y, trackNodes[curTrackNodeFront].z) +
|
||||||
|
f * CVector(trackNodes[nextTrackNodeFront].x, trackNodes[nextTrackNodeFront].y, trackNodes[nextTrackNodeFront].z);
|
||||||
|
|
||||||
|
// Now set matrix
|
||||||
|
SetPosition((posRear + posFront) / 2.0f);
|
||||||
|
CVector fwd = posFront - posRear;
|
||||||
|
m_vecForwardSpeed = fwd;
|
||||||
|
fwd.Normalise();
|
||||||
|
float dp = DotProduct(fwd, GetForward());
|
||||||
|
if (Abs(dp) > 1.001f || Abs(dp) < 0.999f) {
|
||||||
|
CVector df = CrossProduct(fwd, GetForward());
|
||||||
|
CMatrix tmp;
|
||||||
|
float angle;
|
||||||
|
if (m_nSkipFerryStatus == 2) {
|
||||||
|
m_nSkipFerryStatus = 0;
|
||||||
|
angle = (fwd.x < 0.0f && GetForward().x < 0.0f) ? PI - Acos(dp) : Acos(dp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
angle = 0.001f;
|
||||||
|
}
|
||||||
|
if (dp > 0.0f && df.z < 0.0f || dp <= 0.0f && df.z > 0.0f)
|
||||||
|
angle = -angle;
|
||||||
|
tmp.SetRotateZ(angle);
|
||||||
|
fwd = Multiply3x3(GetForward(), tmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fwd = GetForward();
|
||||||
|
CVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));
|
||||||
|
right.Normalise();
|
||||||
|
CVector up = CrossProduct(right, fwd);
|
||||||
|
GetRight() = right;
|
||||||
|
GetUp() = up;
|
||||||
|
GetForward() = fwd;
|
||||||
|
|
||||||
|
// Set speed
|
||||||
|
m_vecMoveSpeed = fwd * trackSpeed / 60.0f;
|
||||||
|
m_fSpeed = trackSpeed / 60.0f;
|
||||||
|
m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
if (m_vecMoveSpeed.MagnitudeSqr() > 0.001f || !m_bApproachingDock) {
|
||||||
|
SetStatus(STATUS_FERRY_MOVING);
|
||||||
|
m_bFerryDocked = false;
|
||||||
|
m_bPlayerArrivedHorn = false;
|
||||||
|
m_nTimeLeftStation = CTimer::GetTimeInMilliseconds();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetStatus(STATUS_FERRY_NOT_MOVING);
|
||||||
|
PlayArrivedHorn();
|
||||||
|
m_bFerryDocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(1000.0f));
|
||||||
|
|
||||||
|
switch (m_nDoorState) {
|
||||||
|
case FERRY_DOOR_CLOSED:
|
||||||
|
break;
|
||||||
|
case FERRY_DOOR_OPENING:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() < m_nDoorTimer) {
|
||||||
|
OpenFerryDoor(1.0f - (m_nDoorTimer - CTimer::GetTimeInMilliseconds()) / 1000.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
OpenFerryDoor(1.0f);
|
||||||
|
m_nDoorState = FERRY_DOOR_OPEN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FERRY_DOOR_OPEN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FERRY_DOOR_CLOSING:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() < m_nDoorTimer) {
|
||||||
|
OpenFerryDoor((m_nDoorTimer - CTimer::GetTimeInMilliseconds()) / 1000.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
OpenFerryDoor(0.0f);
|
||||||
|
m_nDoorState = FERRY_DOOR_CLOSED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector wn = CWaterLevel::GetWaterNormal(GetPosition().x, GetPosition().y);
|
||||||
|
float fRollAngle = wn.x - GetUp().x;
|
||||||
|
if (fRollAngle < 0.0f)
|
||||||
|
fRollAngle = Max(-0.05f, fRollAngle);
|
||||||
|
else
|
||||||
|
fRollAngle = Min(0.05f, fRollAngle);
|
||||||
|
|
||||||
|
CVector oldPos = GetPosition();
|
||||||
|
SetPosition(-GetPosition());
|
||||||
|
CMatrix tmp2;
|
||||||
|
tmp2.SetRotateX(fRollAngle);
|
||||||
|
tmp2 = tmp2 * GetMatrix();
|
||||||
|
tmp2.SetTranslateOnly(oldPos);
|
||||||
|
GetMatrix() = tmp2;
|
||||||
|
|
||||||
|
GetMatrix().UpdateRW();
|
||||||
|
UpdateRwFrame();
|
||||||
|
RemoveAndAdd();
|
||||||
|
|
||||||
|
bIsStuck = false;
|
||||||
|
bIsInSafePosition = true;
|
||||||
|
bWasPostponed = false;
|
||||||
|
|
||||||
|
// request/remove model
|
||||||
|
if (m_isFarAway) {
|
||||||
|
if (m_rwObject)
|
||||||
|
DeleteRwObject();
|
||||||
|
}
|
||||||
|
else if (CStreaming::HasModelLoaded(MI_FERRY)) {
|
||||||
|
if (m_rwObject == nil) {
|
||||||
|
m_modelIndex = -1;
|
||||||
|
SetModelIndex(MI_FERRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (FindPlayerCoors().z * GetPosition().z >= 0.0f)
|
||||||
|
CStreaming::RequestModel(MI_FERRY, STREAMFLAGS_DEPENDENCY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hit stuff
|
||||||
|
if (GetStatus() == STATUS_TRAIN_MOVING) {
|
||||||
|
CVector nfwd = GetForward() * GetColModel()->boundingBox.max.y;
|
||||||
|
if (m_vecForwardSpeed.x > 0.0f)
|
||||||
|
nfwd = -nfwd;
|
||||||
|
if ((m_nFerryId & 1) == 0)
|
||||||
|
nfwd = -nfwd;
|
||||||
|
|
||||||
|
int x, xmin, xmax;
|
||||||
|
int y, ymin, ymax;
|
||||||
|
|
||||||
|
CVector front = GetPosition() + nfwd + m_vecMoveSpeed * CTimer::GetTimeStep();
|
||||||
|
if (!m_isFarAway && m_vecMoveSpeed.Magnitude2D() > 0.05f)
|
||||||
|
AddWakePoint(nfwd * 0.85f + GetPosition());
|
||||||
|
|
||||||
|
xmin = CWorld::GetSectorIndexX(front.x - 3.0f);
|
||||||
|
if (xmin < 0) xmin = 0;
|
||||||
|
xmax = CWorld::GetSectorIndexX(front.x + 3.0f);
|
||||||
|
if (xmax > NUMSECTORS_X - 1) xmax = NUMSECTORS_X - 1;
|
||||||
|
ymin = CWorld::GetSectorIndexY(front.y - 3.0f);
|
||||||
|
if (ymin < 0) ymin = 0;
|
||||||
|
ymax = CWorld::GetSectorIndexY(front.y + 3.0f);
|
||||||
|
if (ymax > NUMSECTORS_Y - 1) ymax = NUMSECTORS_X - 1;
|
||||||
|
|
||||||
|
CWorld::AdvanceCurrentScanCode();
|
||||||
|
|
||||||
|
for (y = ymin; y <= ymax; y++)
|
||||||
|
for (x = xmin; x <= xmax; x++) {
|
||||||
|
CSector* s = CWorld::GetSector(x, y);
|
||||||
|
FerryHitStuff(s->m_lists[ENTITYLIST_VEHICLES]);
|
||||||
|
FerryHitStuff(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
|
||||||
|
FerryHitStuff(s->m_lists[ENTITYLIST_PEDS]);
|
||||||
|
FerryHitStuff(s->m_lists[ENTITYLIST_PEDS_OVERLAP]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::OpenFerryDoor(float ratio)
|
||||||
|
{
|
||||||
|
if (!m_rwObject)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int door1 = 0;
|
||||||
|
int door2 = 1;
|
||||||
|
if (!m_bUseFrontDoor) {
|
||||||
|
door1 = 2;
|
||||||
|
door2 = 3;
|
||||||
|
}
|
||||||
|
int node1 = m_bUseFrontDoor ? FERRY_DOOR_FRONT : FERRY_DOOR_BACK;
|
||||||
|
int node2 = m_bUseFrontDoor ? FERRY_RAMP_FRONT : FERRY_RAMP_BACK;
|
||||||
|
CMatrix doorL(RwFrameGetMatrix(m_aFerryNodes[node1]));
|
||||||
|
CMatrix doorR(RwFrameGetMatrix(m_aFerryNodes[node2]));
|
||||||
|
CVector posL = doorL.GetPosition();
|
||||||
|
CVector posR = doorR.GetPosition();
|
||||||
|
|
||||||
|
bool isClosed = m_doors[0].IsClosed(); // useless
|
||||||
|
|
||||||
|
m_doors[door1].Open(ratio);
|
||||||
|
m_doors[door2].Open(ratio);
|
||||||
|
|
||||||
|
doorL.SetRotateXOnly(m_doors[door1].m_fAngle);
|
||||||
|
doorR.SetRotateXOnly(m_doors[door2].m_fAngle);
|
||||||
|
|
||||||
|
doorL.UpdateRW();
|
||||||
|
doorR.UpdateRW();
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector CFerry::GetBoardingSpace(CFerry::eSpaceUse use, CFerry::eSpaceStyle style, uint8 position)
|
||||||
|
{
|
||||||
|
CVehicleModelInfo* pModelInfo = GetModelInfo();
|
||||||
|
CVector space;
|
||||||
|
if (m_nFerryId & 1) {
|
||||||
|
if (style == FERRY_SPACE_STYLE_0)
|
||||||
|
style = FERRY_SPACE_STYLE_1;
|
||||||
|
else
|
||||||
|
style = FERRY_SPACE_STYLE_0;
|
||||||
|
}
|
||||||
|
switch (use) {
|
||||||
|
case FERRY_SPACE_PED:
|
||||||
|
space = pModelInfo->m_positions[FERRY_POS_PED_POINT];
|
||||||
|
break;
|
||||||
|
case FERRY_SPACE_CAR:
|
||||||
|
space = pModelInfo->m_positions[FERRY_POS_CAR1 + position];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (style) {
|
||||||
|
case FERRY_SPACE_STYLE_0:
|
||||||
|
space = GetMatrix() * space;
|
||||||
|
break;
|
||||||
|
case FERRY_SPACE_STYLE_1:
|
||||||
|
space = GetMatrix() * space - (2 * space.x) * GetRight() - (2 * space.y) * GetForward();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFerry* CFerry::GetClosestFerry(float x, float y)
|
||||||
|
{
|
||||||
|
int closest = -1;
|
||||||
|
float mindist = 9999.9f;
|
||||||
|
for (int i = 0; i < NUM_FERRIES; i++) {
|
||||||
|
CFerry* pFerry = GetFerry(i);
|
||||||
|
if (pFerry) {
|
||||||
|
float dist = ((CVector2D)pFerry->GetPosition() - CVector2D(x, y)).Magnitude();
|
||||||
|
if (dist < 300.0f && dist < mindist) {
|
||||||
|
mindist = dist;
|
||||||
|
closest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (closest == -1)
|
||||||
|
return nil;
|
||||||
|
return GetFerry(closest);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFerry::IsDocked(void)
|
||||||
|
{
|
||||||
|
return m_bFerryDocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::OpenDoor(void)
|
||||||
|
{
|
||||||
|
printf("opening the ferry door\n");
|
||||||
|
m_nDoorState = FERRY_DOOR_OPENING;
|
||||||
|
m_nDoorTimer = CTimer::GetTimeInMilliseconds() + 10000;
|
||||||
|
CVehicleModelInfo* pModelInfo = GetModelInfo();
|
||||||
|
CVector2D vPlayerPos = FindPlayerPed()->GetPosition();
|
||||||
|
float fDistToCar4 = (vPlayerPos - GetMatrix() * pModelInfo->m_positions[FERRY_POS_CAR4]).Magnitude();
|
||||||
|
float fDistToCar1 = (vPlayerPos - GetMatrix() * pModelInfo->m_positions[FERRY_POS_CAR1]).Magnitude();
|
||||||
|
m_bUseFrontDoor = true;
|
||||||
|
if (fDistToCar4 < fDistToCar1)
|
||||||
|
m_bUseFrontDoor = false;
|
||||||
|
// AudioManager.DirectlyEnqueueSample(0xb8,0,0,1,0x5622,0x7f,0x14,0); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::CloseDoor(void)
|
||||||
|
{
|
||||||
|
printf("closing the ferry door\n");
|
||||||
|
m_nDoorState = FERRY_DOOR_CLOSING;
|
||||||
|
m_nDoorTimer = CTimer::GetTimeInMilliseconds() + 10000;
|
||||||
|
// AudioManager.DirectlyEnqueueSample(0xb8, 0, 0, 1, 0x5622, 0x7f, 0x14, 0); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFerry::IsDoorOpen(void)
|
||||||
|
{
|
||||||
|
return m_nDoorState == FERRY_DOOR_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFerry::IsDoorClosed(void)
|
||||||
|
{
|
||||||
|
return m_nDoorState == FERRY_DOOR_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::CompleteDorrMovement(void)
|
||||||
|
{
|
||||||
|
m_nDoorTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::DissableFerryPath(int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::EnableFerryPath(int path)
|
||||||
|
{
|
||||||
|
CStreaming::LoadAllRequestedModels(false);
|
||||||
|
CStreaming::RequestModel(MI_FERRY, 0);
|
||||||
|
CStreaming::LoadAllRequestedModels(false);
|
||||||
|
for (int i = path * 2; i < path * 2 + 2; i++) {
|
||||||
|
CFerry* pFerry = new CFerry(MI_FERRY, PERMANENT_VEHICLE);
|
||||||
|
bool bDirect = i & 1;
|
||||||
|
mspInst->m_apFerries[i] = pFerry;
|
||||||
|
pFerry->SetPosition(0.0f, 0.0f, 0.0f);
|
||||||
|
pFerry->SetStatus(STATUS_ABANDONED);
|
||||||
|
pFerry->bIsLocked = true;
|
||||||
|
pFerry->SetHeading(bDirect ? HALFPI : 3 * HALFPI);
|
||||||
|
pFerry->m_nFerryId = i;
|
||||||
|
pFerry->m_nCurTrackNode = 0;
|
||||||
|
CWorld::Add(pFerry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::SkipFerryToNextDock(void)
|
||||||
|
{
|
||||||
|
m_nSkipFerryStatus = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::PruneWakeTrail(void)
|
||||||
|
{
|
||||||
|
int16 num_remaining = 0;
|
||||||
|
for (int i = 0; i < NUM_WAKE_POINTS; i++) {
|
||||||
|
if (mspInst->m_afWakePointTimer[m_nFerryId][i] <= 0.0f)
|
||||||
|
break;
|
||||||
|
if (mspInst->m_afWakePointTimer[m_nFerryId][i] <= CTimer::GetTimeStep()) {
|
||||||
|
mspInst->m_afWakePointTimer[m_nFerryId][i] = 0.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mspInst->m_afWakePointTimer[m_nFerryId][i] -= CTimer::GetTimeStep();
|
||||||
|
num_remaining++;
|
||||||
|
}
|
||||||
|
mspInst->m_anNumWakePoints[m_nFerryId] = num_remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::AddWakePoint(CVector point)
|
||||||
|
{
|
||||||
|
if (mspInst->m_afWakePointTimer[m_nFerryId][0] > 0.0f) {
|
||||||
|
int nNewWakePoints = Min(NUM_WAKE_POINTS - 1, mspInst->m_anNumWakePoints[m_nFerryId]);
|
||||||
|
for (int i = 0; i < nNewWakePoints; i++) {
|
||||||
|
mspInst->m_avWakePoints[m_nFerryId][i + 1] = mspInst->m_avWakePoints[m_nFerryId][i];
|
||||||
|
mspInst->m_afWakePointTimer[m_nFerryId][i + 1] = mspInst->m_afWakePointTimer[m_nFerryId][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mspInst->m_avWakePoints[m_nFerryId][0] = point;
|
||||||
|
mspInst->m_afWakePointTimer[m_nFerryId][0] = 900.0f; // TODO: define
|
||||||
|
mspInst->m_anNumWakePoints[m_nFerryId] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::PlayArrivedHorn(void)
|
||||||
|
{
|
||||||
|
if (m_bPlayerArrivedHorn)
|
||||||
|
return;
|
||||||
|
m_bPlayerArrivedHorn = true;
|
||||||
|
float fDistToCamera = (GetPosition() - TheCamera.GetPosition()).Magnitude();
|
||||||
|
if (fDistToCamera < 200.0f) {
|
||||||
|
uint8 volume = (200.0f - fDistToCamera) / 200.0f * 127;
|
||||||
|
// AudioManager.DirectlyEnqueueSample(0x32, 0, 0, 1, 18000, volume, 0x32, 0); // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector CFerry::GetNearestDoor(CVector)
|
||||||
|
{
|
||||||
|
return CVector(0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::SetupForMultiplayer(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_FERRIES; i++)
|
||||||
|
mspInst->m_apFerries[i] = nil;
|
||||||
|
CStreaming::SetModelIsDeletable(MI_FERRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFerry::Write(base::cRelocatableChunkWriter& writer)
|
||||||
|
{
|
||||||
|
writer.AllocateRaw(mspInst, sizeof(*mspInst), 4);
|
||||||
|
if (!mspInst)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < NUM_FERRY_PATHS; i++) {
|
||||||
|
writer.AllocateRaw(mspInst->pPathData[i], sizeof(*mspInst->pPathData[i]), 4);
|
||||||
|
writer.AddPatch(&mspInst->pPathData[i]);
|
||||||
|
writer.AllocateRaw(mspInst->pPathData[i]->aTrackNodes, mspInst->pPathData[i]->NumTrackNodes * sizeof(CFerryNode), 4);
|
||||||
|
writer.AddPatch(&mspInst->pPathData[i]->aTrackNodes);
|
||||||
|
writer.AllocateRaw(mspInst->pPathData[i]->aLineBits, (NUM_FERRY_STATIONS * 4 + 2) * sizeof(CFerryInterpolationLine), 4);
|
||||||
|
writer.AddPatch(&mspInst->pPathData[i]->aTrackNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,3 +11,133 @@ enum eFerryNodes
|
||||||
FERRY_RAMP_BACK,
|
FERRY_RAMP_BACK,
|
||||||
NUM_FERRY_NODES
|
NUM_FERRY_NODES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NUM_FERRY_STATIONS = 2,
|
||||||
|
NUM_FERRIES = NUM_FERRY_PATHS * 2,
|
||||||
|
NUM_WAKE_POINTS = 64
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FERRY_STOPPED = 0,
|
||||||
|
FERRY_CRUISING,
|
||||||
|
FERRY_SLOWING,
|
||||||
|
FERRY_ACCELERATING
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FERRY_DOOR_CLOSED = 0,
|
||||||
|
FERRY_DOOR_OPENING,
|
||||||
|
FERRY_DOOR_OPEN,
|
||||||
|
FERRY_DOOR_CLOSING
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CFerryNode
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float t;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CFerryInterpolationLine
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
float time; // when does this keyframe start
|
||||||
|
// initial values at start of frame
|
||||||
|
float position;
|
||||||
|
float speed;
|
||||||
|
float acceleration;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CFerryPath
|
||||||
|
{
|
||||||
|
float TotalLengthOfTrack;
|
||||||
|
float TotalDurationOfTrack;
|
||||||
|
int16 NumTrackNodes;
|
||||||
|
CFerryNode* aTrackNodes;
|
||||||
|
CFerryInterpolationLine* aLineBits;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFerry;
|
||||||
|
|
||||||
|
class CFerryInst
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CFerryPath* pPathData[NUM_FERRY_PATHS];
|
||||||
|
float m_afPositions[NUM_FERRIES];
|
||||||
|
float m_afSpeeds[NUM_FERRIES];
|
||||||
|
CFerry* m_apFerries[NUM_FERRIES];
|
||||||
|
bool m_bFerriesDisabled;
|
||||||
|
uint16 m_anNumWakePoints[NUM_FERRIES];
|
||||||
|
CVector2D m_avWakePoints[NUM_FERRIES][NUM_WAKE_POINTS];
|
||||||
|
float m_afWakePointTimer[NUM_FERRIES][NUM_WAKE_POINTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFerry : public CVehicle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint16 m_nFerryId;
|
||||||
|
uint16 m_isFarAway;
|
||||||
|
uint16 m_nCurTrackNode;
|
||||||
|
float m_fSpeed;
|
||||||
|
bool m_bFerryDocked;
|
||||||
|
uint32 m_nDoorTimer;
|
||||||
|
uint32 m_nTimeLeftStation;
|
||||||
|
int16 m_nDoorState;
|
||||||
|
bool m_bApproachingDock;
|
||||||
|
uint8 m_nSkipFerryStatus;
|
||||||
|
uint32 m_nTimeAlongPath;
|
||||||
|
bool m_bUseFrontDoor;
|
||||||
|
CVector m_vecForwardSpeed;
|
||||||
|
CColModel* m_pDefaultColModel;
|
||||||
|
uint8 m_nCollision;
|
||||||
|
CDoor m_doors[4];
|
||||||
|
RwFrame* m_aFerryNodes[NUM_FERRY_NODES];
|
||||||
|
bool m_bAlreadyRendered;
|
||||||
|
bool m_bPlayerArrivedHorn;
|
||||||
|
|
||||||
|
static CFerryInst* mspInst;
|
||||||
|
|
||||||
|
enum eSpaceUse {
|
||||||
|
FERRY_SPACE_PED = 0,
|
||||||
|
FERRY_SPACE_CAR
|
||||||
|
};
|
||||||
|
enum eSpaceStyle {
|
||||||
|
FERRY_SPACE_STYLE_0 = 0,
|
||||||
|
FERRY_SPACE_STYLE_1
|
||||||
|
};
|
||||||
|
void Render(void);
|
||||||
|
static void EnableFerryPath(int);
|
||||||
|
CFerry(int32, uint8);
|
||||||
|
void SetModelIndex(uint32);
|
||||||
|
static void InitFerrys(void);
|
||||||
|
static void Init(void*);
|
||||||
|
void ProcessControl(void);
|
||||||
|
void PlayArrivedHorn(void);
|
||||||
|
void AddWakePoint(CVector);
|
||||||
|
void PruneWakeTrail(void);
|
||||||
|
void SkipFerryToNextDock(void);
|
||||||
|
static void DissableFerryPath(int);
|
||||||
|
void CompleteDorrMovement(void);
|
||||||
|
bool IsDoorOpen(void);
|
||||||
|
void CloseDoor(void);
|
||||||
|
bool IsDocked(void);
|
||||||
|
static CFerry* GetClosestFerry(float, float);
|
||||||
|
CVector GetBoardingSpace(CFerry::eSpaceUse, CFerry::eSpaceStyle, uint8);
|
||||||
|
CVector GetNearestDoor(CVector);
|
||||||
|
void OpenFerryDoor(float);
|
||||||
|
void FerryHitStuff(CPtrList&);
|
||||||
|
static void RenderAllRemaning(void);
|
||||||
|
static void UpdateFerrys(void);
|
||||||
|
static void SwitchFerryCollision(int);
|
||||||
|
void SetupForMultiplayer(void);
|
||||||
|
void Write(base::cRelocatableChunkWriter&);
|
||||||
|
virtual void OpenDoor(void);
|
||||||
|
void PreRender(void);
|
||||||
|
virtual bool IsDoorClosed(void);
|
||||||
|
|
||||||
|
static CFerry* GetFerry(int i) { return mspInst ? mspInst->m_apFerries[i] : nil; }
|
||||||
|
static void SetFerriesDisabled(bool disabled) { mspInst->m_bFerriesDisabled = disabled; }
|
||||||
|
};
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
#include "Train.h"
|
#include "Train.h"
|
||||||
#include "AudioScriptObject.h"
|
#include "AudioScriptObject.h"
|
||||||
|
|
||||||
|
#define TRAIN_SPEED (15.0f)
|
||||||
|
#define TRAIN_SLOWDOWN_DISTANCE (40.0f)
|
||||||
|
#define TRAIN_TIME_STOPPED_AT_STATION (25.0f)
|
||||||
|
|
||||||
static CTrainNode* pTrackNodes;
|
static CTrainNode* pTrackNodes;
|
||||||
static int16 NumTrackNodes;
|
static int16 NumTrackNodes;
|
||||||
static float StationDist[3] = { 873.0f, 1522.0f, 2481.0f };
|
static float StationDist[3] = { 873.0f, 1522.0f, 2481.0f };
|
||||||
|
@ -598,23 +602,23 @@ CTrain::ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int1
|
||||||
interpLines[j].type = 1;
|
interpLines[j].type = 1;
|
||||||
interpLines[j].time = time;
|
interpLines[j].time = time;
|
||||||
interpLines[j].position = position;
|
interpLines[j].position = position;
|
||||||
interpLines[j].speed = 15.0f;
|
interpLines[j].speed = TRAIN_SPEED;
|
||||||
interpLines[j].acceleration = 0.0f;
|
interpLines[j].acceleration = 0.0f;
|
||||||
j++;
|
j++;
|
||||||
// distance to next keyframe
|
// distance to next keyframe
|
||||||
float dist = (stationDists[i]-40.0f) - position;
|
float dist = (stationDists[i]-TRAIN_SLOWDOWN_DISTANCE) - position;
|
||||||
time += dist/15.0f;
|
time += dist/TRAIN_SPEED;
|
||||||
position += dist;
|
position += dist;
|
||||||
|
|
||||||
// Now slow down 40 units before stop
|
// Now slow down 40 units before stop
|
||||||
interpLines[j].type = 2;
|
interpLines[j].type = 2;
|
||||||
interpLines[j].time = time;
|
interpLines[j].time = time;
|
||||||
interpLines[j].position = position;
|
interpLines[j].position = position;
|
||||||
interpLines[j].speed = 15.0f;
|
interpLines[j].speed = TRAIN_SPEED;
|
||||||
interpLines[j].acceleration = -45.0f/32.0f;
|
interpLines[j].acceleration = -(TRAIN_SPEED * TRAIN_SPEED) / (4 * TRAIN_SLOWDOWN_DISTANCE);
|
||||||
j++;
|
j++;
|
||||||
time += 80.0f/15.0f;
|
time += 2*TRAIN_SLOWDOWN_DISTANCE/TRAIN_SPEED;
|
||||||
position += 40.0f; // at station
|
position += TRAIN_SLOWDOWN_DISTANCE; // at station
|
||||||
|
|
||||||
// stopping
|
// stopping
|
||||||
interpLines[j].type = 0;
|
interpLines[j].type = 0;
|
||||||
|
@ -623,26 +627,26 @@ CTrain::ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int1
|
||||||
interpLines[j].speed = 0.0f;
|
interpLines[j].speed = 0.0f;
|
||||||
interpLines[j].acceleration = 0.0f;
|
interpLines[j].acceleration = 0.0f;
|
||||||
j++;
|
j++;
|
||||||
time += 25.0f;
|
time += TRAIN_TIME_STOPPED_AT_STATION;
|
||||||
|
|
||||||
// accelerate again
|
// accelerate again
|
||||||
interpLines[j].type = 2;
|
interpLines[j].type = 2;
|
||||||
interpLines[j].time = time;
|
interpLines[j].time = time;
|
||||||
interpLines[j].position = position;
|
interpLines[j].position = position;
|
||||||
interpLines[j].speed = 0.0f;
|
interpLines[j].speed = 0.0f;
|
||||||
interpLines[j].acceleration = 45.0f/32.0f;
|
interpLines[j].acceleration = (TRAIN_SPEED * TRAIN_SPEED) / (4 * TRAIN_SLOWDOWN_DISTANCE);
|
||||||
j++;
|
j++;
|
||||||
time += 80.0f/15.0f;
|
time += 2*TRAIN_SLOWDOWN_DISTANCE /TRAIN_SPEED;
|
||||||
position += 40.0f; // after station
|
position += TRAIN_SLOWDOWN_DISTANCE; // after station
|
||||||
}
|
}
|
||||||
// last keyframe
|
// last keyframe
|
||||||
interpLines[j].type = 1;
|
interpLines[j].type = 1;
|
||||||
interpLines[j].time = time;
|
interpLines[j].time = time;
|
||||||
interpLines[j].position = position;
|
interpLines[j].position = position;
|
||||||
interpLines[j].speed = 15.0f;
|
interpLines[j].speed = TRAIN_SPEED;
|
||||||
interpLines[j].acceleration = 0.0f;
|
interpLines[j].acceleration = 0.0f;
|
||||||
j++;
|
j++;
|
||||||
*totalDuration = time + (*totalLength - position)/15.0f;
|
*totalDuration = time + (*totalLength - position)/ TRAIN_SPEED;
|
||||||
|
|
||||||
// end
|
// end
|
||||||
interpLines[j].time = *totalDuration;
|
interpLines[j].time = *totalDuration;
|
||||||
|
|
Loading…
Reference in a new issue