Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
877 lines
22 KiB
C++
877 lines
22 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "player.h"
|
|
#include "icom.h"
|
|
#include "camship.h"
|
|
#include "dropzone.h"
|
|
#include "mission.h"
|
|
#include "audio.h"
|
|
#include "director.h"
|
|
#include "app.h"
|
|
#include "hostmgr.h"
|
|
#include "nttmgr.h"
|
|
#include "console.h"
|
|
#include "appmsg.h"
|
|
|
|
//#############################################################################
|
|
//####################### Player::StatusMessage #########################
|
|
//#############################################################################
|
|
|
|
Player__StatusMessage::Player__StatusMessage(Player *player_involved, int message_type, Scalar display_time)
|
|
{
|
|
playerInvolved = player_involved;
|
|
messageType = message_type;
|
|
displayTime = display_time;
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################### Player ################################
|
|
//#############################################################################
|
|
|
|
//#############################################################################
|
|
// Shared Data Support
|
|
//
|
|
Derivation* Player::GetClassDerivations()
|
|
{
|
|
static Derivation classDerivations(Entity::GetClassDerivations(), "Player");
|
|
return &classDerivations;
|
|
}
|
|
|
|
Player::SharedData
|
|
Player::DefaultData(
|
|
Player::GetClassDerivations(),
|
|
Player::GetMessageHandlers(),
|
|
Player::GetAttributeIndex(),
|
|
Player::StateCount,
|
|
(Entity::MakeHandler)Player::Make
|
|
);
|
|
|
|
//#############################################################################
|
|
// Attribute Support
|
|
//
|
|
|
|
const Player::IndexEntry
|
|
Player::AttributePointers[]=
|
|
{
|
|
ATTRIBUTE_ENTRY(Player, CurrentScore, currentScore),
|
|
ATTRIBUTE_ENTRY(Player, PlayerRanking, playerRanking),
|
|
ATTRIBUTE_ENTRY(Player, DropZoneLocation, dropZoneLocation),
|
|
ATTRIBUTE_ENTRY(Player, StatusMessagePointer,statusMessagePointer),
|
|
ATTRIBUTE_ENTRY(Player, PlayerBitmapIndex, playerBitmapIndex),
|
|
ATTRIBUTE_ENTRY(Player, PlayerHighlighted, playerHighlighted)
|
|
};
|
|
|
|
Player::AttributeIndexSet& Player::GetAttributeIndex()
|
|
{
|
|
static Player::AttributeIndexSet attributeIndex(ELEMENTS(Player::AttributePointers),
|
|
Player::AttributePointers,
|
|
Entity::GetAttributeIndex()
|
|
);
|
|
return attributeIndex;
|
|
}
|
|
|
|
//#############################################################################
|
|
// Message Support
|
|
//
|
|
const Receiver::HandlerEntry
|
|
Player::MessageHandlerEntries[]=
|
|
{
|
|
MESSAGE_ENTRY(Player, DropZoneReply),
|
|
MESSAGE_ENTRY(Player, Score),
|
|
MESSAGE_ENTRY(Player, VehicleDead),
|
|
MESSAGE_ENTRY(Player, MissionStarting),
|
|
MESSAGE_ENTRY(Player, MissionEnding)
|
|
};
|
|
|
|
Receiver::MessageHandlerSet& Player::GetMessageHandlers()
|
|
{
|
|
static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(Player::MessageHandlerEntries), Player::MessageHandlerEntries, Entity::GetMessageHandlers());
|
|
return messageHandlers;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::MissionStartingMessageHandler(Message *)
|
|
{
|
|
Check(this);
|
|
Tell("Player::MissionStartingMessageHandler - starting fade in\n");
|
|
fadeTimeRemaining = 3.0f;
|
|
SetSimulationState(MissionStartingState);
|
|
Check_Fpu();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::MissionEndingMessageHandler(Message *)
|
|
{
|
|
Check(this);
|
|
fadeTimeRemaining = 3.0f;
|
|
ForceUpdate();
|
|
SetSimulationState(MissionEndingState);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Enumeration
|
|
Player::GetAudioRepresentation(
|
|
#if DEBUG_LEVEL>0
|
|
Entity *linked_entity
|
|
#else
|
|
Entity *
|
|
#endif
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(linked_entity);
|
|
Check_Fpu();
|
|
|
|
return
|
|
(GetInstance() == MasterInstance) ?
|
|
InternalAudioRepresentation : ExternalAudioRepresentation;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::ScoreMessageHandler(ScoreMessage *message)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
|
|
currentScore += message->scoreAward;
|
|
|
|
//
|
|
// HACK - ECH 7/6/95 - Allow the player vehicle to respond to score
|
|
// messages, allows attribute system to be used for scoring
|
|
//
|
|
Check(playerVehicle);
|
|
playerVehicle->RespondToScoreMessage(message);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::DropZoneReplyMessageHandler(
|
|
DropZone::ReplyMessage * //message
|
|
)
|
|
{
|
|
Check(this);
|
|
Fail("Drop zone reply should not be handled by base player class!\n");
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::CreatePlayerVehicle(Origin camera_origin)
|
|
{
|
|
Check(this);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create any MUNGA level vehicles
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (IsCameraShipPlayer())
|
|
{
|
|
Check(application);
|
|
ResourceFile *resources = application->GetResourceFile();
|
|
Check(resources);
|
|
Check_Pointer(playerMission->GetGameModel());
|
|
|
|
HostManager *host_manager = application->GetHostManager();
|
|
Check(host_manager);
|
|
ResourceDescription *camera_res =
|
|
resources->FindResourceDescription(
|
|
playerMission->GetGameModel(),
|
|
ResourceDescription::ModelListResourceType
|
|
);
|
|
Check(camera_res);
|
|
CameraShip::MakeMessage
|
|
create_camera(
|
|
CameraShip::MakeMessageID,
|
|
sizeof(CameraShip::MakeMessage),
|
|
EntityID(host_manager->GetLocalHostID()),
|
|
CameraShipClassID,
|
|
EntityID::Null,
|
|
camera_res->resourceID,
|
|
CameraShip::DefaultFlags,
|
|
camera_origin,
|
|
Motion::Identity,
|
|
Motion::Identity
|
|
);
|
|
CameraShip *camera =
|
|
(CameraShip*)application->MakeAndLinkViewpointEntity(&create_camera);
|
|
Register_Object(camera);
|
|
playerVehicle = camera;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::VehicleDeadMessageHandler(VehicleDeadMessage *message)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Check(application);
|
|
|
|
|
|
//DEBUG_STREAM << "VEHICLEDEAD : " << endl << std::flush;
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// If we have let the player fry, send a message to the dropzone to give us
|
|
// a new location to return to
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
if (
|
|
message->deathCount == deathCount
|
|
&& GetSimulationState() != DropZoneAcquiredState)
|
|
{
|
|
DropZone *dropzone;
|
|
|
|
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// If no dropzone has been assigned to this death, find the closest one
|
|
//---------------------------------------------------------------------
|
|
//
|
|
if (message->dropZoneID == EntityID::Null)
|
|
{
|
|
|
|
//DEBUG_STREAM << " Find Closest" << endl << std::flush;
|
|
|
|
EntityManager *entity_manager = application->GetEntityManager();
|
|
Check(entity_manager);
|
|
EntityGroup *dropzones = entity_manager->FindGroup("DropZones");
|
|
Check(dropzones);
|
|
ChainIteratorOf<Node*> iterator(dropzones->groupMembers);
|
|
|
|
DropZone *closest_dropzone;
|
|
Vector3D range;
|
|
Scalar closest_range;
|
|
|
|
while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(dropzone);
|
|
|
|
if (!strnicmp(dropzone->GetDropZoneName(), "win", 3))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
closest_dropzone = dropzone;
|
|
range.Subtract(
|
|
localOrigin.linearPosition,
|
|
dropzone->localOrigin.linearPosition
|
|
);
|
|
closest_range = range.LengthSquared();
|
|
break;
|
|
}
|
|
|
|
while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(dropzone);
|
|
if (!strnicmp(dropzone->GetDropZoneName(), "win", 3))
|
|
{
|
|
continue;
|
|
}
|
|
range.Subtract(
|
|
localOrigin.linearPosition,
|
|
dropzone->localOrigin.linearPosition
|
|
);
|
|
Scalar len = range.LengthSquared();
|
|
if (len < closest_range)
|
|
{
|
|
closest_dropzone = dropzone;
|
|
closest_range = len;
|
|
}
|
|
}
|
|
message->dropZoneID = closest_dropzone->GetEntityID();
|
|
dropzone = closest_dropzone;
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Otherwise, get this one from the host manager
|
|
//----------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
//DEBUG_STREAM << " Use Assigned" << endl << std::flush;
|
|
|
|
HostManager *host = application->GetHostManager();
|
|
Check(host);
|
|
dropzone =
|
|
Cast_Object(
|
|
DropZone*,
|
|
host->GetEntityPointer(message->dropZoneID)
|
|
);
|
|
}
|
|
|
|
Check(dropzone);
|
|
DropZone::AssignDropZoneMessage
|
|
request(
|
|
DropZone::AssignDropZoneMessageID,
|
|
sizeof(DropZone::AssignDropZoneMessage),
|
|
GetEntityID(),
|
|
DropZoneReplyMessageID,
|
|
deathCount
|
|
);
|
|
dropzone->Dispatch(&request);
|
|
Time when = Now();
|
|
when += 2.0f;
|
|
application->Post(HighEventPriority, this, message, when);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::HuntForDropZone(Scalar)
|
|
{
|
|
Check(this);
|
|
Check(playerMission);
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// See if our designated drop zone is around yet. If the dropzone group
|
|
// does not exist, then no dropzones at all are available
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Check(application);
|
|
EntityManager *entity_manager = application->GetEntityManager();
|
|
Check(entity_manager);
|
|
EntityGroup *dropzones = entity_manager->FindGroup("DropZones");
|
|
if (!dropzones)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
Check(dropzones);
|
|
ChainIteratorOf<Node*> iterator(dropzones->groupMembers);
|
|
DropZone *dropzone;
|
|
const char* zone_name = playerMission->GetDropZoneName();
|
|
while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL)
|
|
{
|
|
if (!strcmp(dropzone->GetDropZoneName(), zone_name))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// If it is, reset our performance, and send a message to the drop zone to
|
|
// give us a location
|
|
//------------------------------------------------------------------------
|
|
//
|
|
if (dropzone)
|
|
{
|
|
|
|
//DEBUG_STREAM << "FOUND DROPZONE" << endl << std::flush;
|
|
|
|
Check(dropzone);
|
|
SetPerformance(&Player::DoNothingOnce);
|
|
VehicleDeadMessage
|
|
dead(
|
|
VehicleDeadMessageID,
|
|
sizeof(VehicleDeadMessage),
|
|
dropzone->GetEntityID()
|
|
);
|
|
dead.deathCount = -2;
|
|
|
|
DropZone::AssignDropZoneMessage
|
|
request(
|
|
DropZone::AssignDropZoneMessageID,
|
|
sizeof(DropZone::AssignDropZoneMessage),
|
|
GetEntityID(),
|
|
DropZoneReplyMessageID,
|
|
deathCount
|
|
);
|
|
dropzone->Dispatch(&request);
|
|
Time when = Now();
|
|
when += 2.0f;
|
|
application->Post(HighEventPriority, this, &dead, when);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::ManageApplicationStatus(Scalar time_slice)
|
|
{
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// If we are in the game start/stop phase, count the timer down and send the
|
|
// appropriate message to the application when done
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
Check(this);
|
|
Check(application);
|
|
switch (GetSimulationState())
|
|
{
|
|
case MissionStartingState:
|
|
Verify(fadeTimeRemaining <= 3.0f);
|
|
fadeTimeRemaining -= time_slice;
|
|
if (fadeTimeRemaining <= 0.0f)
|
|
{
|
|
SetSimulationState(VehicleTranslocatedState);
|
|
Check(application);
|
|
switch (application->GetApplicationState())
|
|
{
|
|
case Application::LaunchingMission:
|
|
{
|
|
Application::RunMissionMessage message;
|
|
application->Dispatch(&message);
|
|
}
|
|
break;
|
|
case Application::ResumingMission:
|
|
{
|
|
Application::ResumeMissionMessage message;
|
|
application->Dispatch(&message);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case MissionEndingState:
|
|
fadeTimeRemaining -= time_slice;
|
|
if (fadeTimeRemaining <= 0.0f)
|
|
{
|
|
Check(application);
|
|
switch (application->GetApplicationState())
|
|
{
|
|
case Application::EndingMission:
|
|
{
|
|
// Fill in appropriate exit code here. GAH
|
|
Application::StopMissionMessage message(NullExitCodeID);
|
|
application->Dispatch(&message);
|
|
}
|
|
break;
|
|
case Application::AbortingMission:
|
|
{
|
|
// Fill in appropriate exit code here. GAH
|
|
Application::AbortMissionMessage message(NullExitCodeID);
|
|
application->Dispatch(&message);
|
|
}
|
|
break;
|
|
case Application::SuspendingMission:
|
|
{
|
|
Application::SuspendMissionMessage message;
|
|
application->Dispatch(&message);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::CameraShipSimulation(Scalar time_slice)
|
|
{
|
|
Check(this);
|
|
CalcRanking();
|
|
|
|
ManageApplicationStatus(time_slice);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::PlayerSimulation(Scalar time_slice)
|
|
{
|
|
Check(this);
|
|
|
|
//-------------------------------
|
|
// Calculate the player's ranking
|
|
//-------------------------------
|
|
CalcRanking();
|
|
|
|
//----------------------------------
|
|
// ...manage the application status?
|
|
//----------------------------------
|
|
ManageApplicationStatus(time_slice);
|
|
|
|
//-------------------------------
|
|
// Copy vehicle position
|
|
//-------------------------------
|
|
if (playerVehicle)
|
|
{
|
|
Check(playerVehicle);
|
|
localOrigin = playerVehicle->localOrigin;
|
|
localToWorld = playerVehicle->localToWorld;
|
|
}
|
|
|
|
//---------------------------------
|
|
// Service the status message queue
|
|
//---------------------------------
|
|
StatusMessageUpdate(time_slice);
|
|
|
|
Check_Fpu();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::GoToVehicle(Scalar)
|
|
{
|
|
Check(this);
|
|
if (playerVehicle)
|
|
{
|
|
Check(playerVehicle);
|
|
localOrigin = playerVehicle->localOrigin;
|
|
localToWorld = playerVehicle->localToWorld;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
Player::CalcRanking()
|
|
{
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Get all players from the entity group
|
|
//---------------------------------------
|
|
//
|
|
EntityGroup *player_group =
|
|
application->GetEntityManager()->FindGroup("Players");
|
|
if(player_group)
|
|
{
|
|
int num_players = 0;
|
|
Player *active_player;
|
|
//
|
|
//-----------------------------------------------------
|
|
// Iterate through the players add to the sorted chain
|
|
//-----------------------------------------------------
|
|
//
|
|
ChainIteratorOf<Node*> iterator(player_group->groupMembers);
|
|
VChainOf<Player*, Scalar> player_rank(NULL, False);
|
|
while ((active_player = (Player*) iterator.ReadAndNext()) != NULL)
|
|
{
|
|
if(active_player->IsScoringPlayer())
|
|
{
|
|
player_rank.AddValue(active_player, active_player->currentScore);
|
|
++num_players;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Reset Player Highlighted
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
active_player->playerHighlighted = False;
|
|
}
|
|
else
|
|
{
|
|
active_player->playerRanking = -1;
|
|
}
|
|
|
|
}
|
|
--num_players;
|
|
//
|
|
//------------------------------------------------
|
|
// Iterate through the chain assigning the rank
|
|
//------------------------------------------------
|
|
//
|
|
VChainIteratorOf<Player*, Scalar> rank_iterator(player_rank);
|
|
|
|
|
|
while ((active_player = rank_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
active_player->playerRanking = num_players;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// If player in first place turn on player highlighted
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (!active_player->playerRanking)
|
|
{
|
|
active_player->playerHighlighted = True;
|
|
}
|
|
--num_players;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
return 1;
|
|
}
|
|
//#############################################################################
|
|
// Update Support
|
|
//
|
|
void
|
|
Player::ReadUpdateRecord(Simulation::UpdateRecord *message)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(message);
|
|
Entity::ReadUpdateRecord(message);
|
|
UpdateRecord* record = (UpdateRecord*) message;
|
|
|
|
currentScore = record->currentScore;
|
|
dropZoneLocation = record->dropZoneLocation;
|
|
Check_Fpu();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::WriteUpdateRecord(
|
|
Simulation::UpdateRecord *record,
|
|
int update_model
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(record);
|
|
|
|
Entity::WriteUpdateRecord(record, update_model);
|
|
|
|
UpdateRecord* update = (UpdateRecord*) record;
|
|
|
|
update->recordLength = sizeof(*update);
|
|
update->currentScore = currentScore;
|
|
update->dropZoneLocation = dropZoneLocation;
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//#############################################################################
|
|
// Construction and Destruction
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Player::Player(
|
|
Player::MakeMessage *creation_message,
|
|
Player::SharedData &virtual_data
|
|
):
|
|
Entity(creation_message, virtual_data),
|
|
statusMessageQueue(NULL)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Pointer(creation_message);
|
|
|
|
scenarioRole = NULL;
|
|
//---------------------------------
|
|
// Initialize data
|
|
//---------------------------------
|
|
statusMessagePointer = NULL;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize the playerMission
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
playerMission = application->GetCurrentMission();
|
|
Check(playerMission);
|
|
//
|
|
//---------------------------------
|
|
// Set the resource ID for a player
|
|
//---------------------------------
|
|
//
|
|
Check(application);
|
|
Check(application->GetResourceFile());
|
|
ResourceDescription *resource_description =
|
|
application->GetResourceFile()->FindResourceDescription(
|
|
"player",
|
|
ResourceDescription::ModelListResourceType
|
|
);
|
|
if (resource_description != NULL)
|
|
{
|
|
Verify(resourceID == ResourceDescription::NullResourceID);
|
|
resourceID = resource_description->resourceID;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the host type associated with the entity ID
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
HostType host_type;
|
|
|
|
HostID host_ID = entityID.GetHostID();
|
|
Check(application);
|
|
HostManager *host_mgr = application->GetHostManager();
|
|
Check(host_mgr);
|
|
Host *local_host = host_mgr->GetLocalHost();
|
|
Check(local_host);
|
|
if (host_ID == local_host->GetHostID())
|
|
{
|
|
host_type = local_host->GetHostType();
|
|
}
|
|
else
|
|
{
|
|
HostManager::RemoteHostIterator iterator(host_mgr);
|
|
local_host = iterator.Find(host_ID);
|
|
Check(local_host);
|
|
host_type = local_host->GetHostType();
|
|
}
|
|
|
|
if (IsCameraShipPlayer())
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Make A CameraPlayers Entity Group
|
|
// since cameras are not involved in
|
|
// standard game play they need a
|
|
// separate Entity Group!
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
playerBitmapIndex = -1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Make A Regular Players Entity Group
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(application);
|
|
EntityManager *entity_manager = application->GetEntityManager();
|
|
Check(entity_manager);
|
|
EntityGroup *players = entity_manager->UseGroup("Players");
|
|
Check(players);
|
|
players->Add(this);
|
|
playerBitmapIndex = creation_message->playerBitmapIndex;
|
|
}
|
|
|
|
SetValidFlag();
|
|
playerVehicle = NULL;
|
|
if (GetInstance() != ReplicantInstance)
|
|
{
|
|
Check(application->GetCurrentMission());
|
|
playerMission = application->GetCurrentMission();
|
|
SetPerformance(&Player::HuntForDropZone);
|
|
}
|
|
else
|
|
{
|
|
SetPerformance(&Player::GoToVehicle);
|
|
playerMission = NULL;
|
|
}
|
|
|
|
playerRanking = 0;
|
|
deathCount = -2;
|
|
|
|
//-------------------------------------
|
|
// Clear score
|
|
//-------------------------------------
|
|
currentScore = 0.0f;
|
|
//-------------------------------------
|
|
// Create intercom object
|
|
//-------------------------------------
|
|
Check(application);
|
|
IcomManager
|
|
*intercom_manager = application->GetIntercomManager();
|
|
Check(intercom_manager);
|
|
|
|
intercomPointer = intercom_manager->MakeIcom(GetOwnerID());
|
|
Check(intercomPointer);
|
|
// registered in MakeIcom()
|
|
|
|
playerHighlighted = False;
|
|
fadeTimeRemaining = 0.0f;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Player* Player::Make(Player::MakeMessage *creation_message)
|
|
{
|
|
Check_Fpu();
|
|
return new Player(creation_message, DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Player::~Player()
|
|
{
|
|
Check(this);
|
|
|
|
//--------------------------------------------
|
|
// Delete intercom object
|
|
//--------------------------------------------
|
|
Check(intercomPointer);
|
|
Unregister_Object(intercomPointer);
|
|
delete intercomPointer;
|
|
intercomPointer = NULL;
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::AddStatusMessage(StatusMessage *status_message)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(status_message);
|
|
statusMessageQueue.Add(status_message);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Player::StatusMessageUpdate(Scalar time_slice)
|
|
{
|
|
Check(this);
|
|
//-------------------------------------
|
|
// We handle this queue as a STACK.
|
|
// The most recent message is presented
|
|
// first, causing older messages to
|
|
// wait "below" them on the stack.
|
|
// This allows a default message to
|
|
// sit at the "bottom" of the stack
|
|
// and allow others to override it
|
|
// temporarily.
|
|
//-------------------------------------
|
|
//
|
|
ChainIteratorOf<StatusMessage*>
|
|
iterator(statusMessageQueue);
|
|
//----------------------------------------
|
|
// ...we really want iterator.GetLast(),
|
|
// but since it doesn't exist we'll
|
|
// do it directly.
|
|
//----------------------------------------
|
|
statusMessagePointer = NULL;
|
|
{
|
|
StatusMessage
|
|
*the_message;
|
|
|
|
while ((the_message = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
statusMessagePointer = the_message;
|
|
}
|
|
}
|
|
//----------------------------------------
|
|
// If a message exists, decrement the
|
|
// timer: discard it if timed out.
|
|
//----------------------------------------
|
|
if (statusMessagePointer != NULL)
|
|
{
|
|
Check_Pointer(statusMessagePointer);
|
|
|
|
statusMessagePointer->displayTime -= time_slice;
|
|
if (statusMessagePointer->displayTime <= (Scalar) 0.0f)
|
|
{
|
|
Unregister_Object(statusMessagePointer);
|
|
delete statusMessagePointer;
|
|
statusMessagePointer = NULL;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
Player::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(*GetClassDerivations());
|
|
}
|