Initial import of Red Planet v4.10 Win32 source
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>
This commit is contained in:
@@ -0,0 +1,447 @@
|
||||
#include "munga.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "dropzone.h"
|
||||
#include "random.h"
|
||||
#include "app.h"
|
||||
#include "hostmgr.h"
|
||||
#include "nttmgr.h"
|
||||
#include "notation.h"
|
||||
#include "namelist.h"
|
||||
#include "player.h"
|
||||
|
||||
#define DOWN_TIME 5.0f
|
||||
|
||||
//#############################################################################
|
||||
//############################### DropZone #################################
|
||||
//#############################################################################
|
||||
|
||||
//#############################################################################
|
||||
// Shared Data Support
|
||||
//
|
||||
Derivation* DropZone::GetClassDerivations()
|
||||
{
|
||||
static Derivation classDerivations(Entity::GetClassDerivations(),"DropZone");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
DropZone::SharedData
|
||||
DropZone::DefaultData(
|
||||
DropZone::GetClassDerivations(),
|
||||
DropZone::GetMessageHandlers(),
|
||||
DropZone::GetAttributeIndex(),
|
||||
DropZone::StateCount,
|
||||
(Entity::MakeHandler)DropZone::Make
|
||||
);
|
||||
|
||||
//#############################################################################
|
||||
// Message Support
|
||||
//
|
||||
const Receiver::HandlerEntry
|
||||
DropZone::MessageHandlerEntries[]=
|
||||
{
|
||||
MESSAGE_ENTRY(DropZone, AssignDropZone)
|
||||
};
|
||||
|
||||
Receiver::MessageHandlerSet& DropZone::GetMessageHandlers()
|
||||
{
|
||||
static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(DropZone::MessageHandlerEntries), DropZone::MessageHandlerEntries, Entity::GetMessageHandlers());
|
||||
return messageHandlers;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Construction and Destruction
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
DropZone::DropZone(
|
||||
DropZone::MakeMessage *creation_message,
|
||||
DropZone::SharedData &virtual_data
|
||||
):
|
||||
Entity(creation_message, virtual_data)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
Check_Pointer(creation_message);
|
||||
|
||||
SetValidFlag();
|
||||
dropZoneCount = 0;
|
||||
dropZones = NULL;
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// Name the drop zone, and enter the zone in the drop zone group
|
||||
//--------------------------------------------------------------
|
||||
//
|
||||
Str_Copy(dropZoneName, creation_message->dropZoneName, sizeof(dropZoneName));
|
||||
EntityManager *entity_manager = application->GetEntityManager();
|
||||
Check(entity_manager);
|
||||
EntityGroup* drop_zones = entity_manager->UseGroup("DropZones");
|
||||
Check(drop_zones);
|
||||
drop_zones->Add(this);
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// Now, interpret the data to create the appropriate number of drop zones
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
MemoryStream
|
||||
stream(
|
||||
creation_message,
|
||||
creation_message->messageLength,
|
||||
sizeof(*creation_message)
|
||||
);
|
||||
dropZoneCount = creation_message->dropZoneCount;
|
||||
Verify(dropZoneCount > 0);
|
||||
dropZones = new Origin[dropZoneCount];
|
||||
Register_Pointer(dropZones);
|
||||
lastUsageTime = new Time[dropZoneCount];
|
||||
Register_Pointer(lastUsageTime);
|
||||
lastUsedBy = new EntityID[dropZoneCount];
|
||||
Register_Pointer(lastUsedBy);
|
||||
lastDeathCount = new int[dropZoneCount];
|
||||
Register_Pointer(lastDeathCount);
|
||||
|
||||
for (int i=0; i<dropZoneCount; ++i)
|
||||
{
|
||||
dropZones[i] = *(Origin*)stream.GetPointer();
|
||||
lastUsageTime[i] = Time::Null;
|
||||
lastUsedBy[i] = EntityID::Null;
|
||||
lastDeathCount[i] = -3;
|
||||
stream.AdvancePointer(sizeof(Origin));
|
||||
}
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
DropZone*
|
||||
DropZone::Make(DropZone::MakeMessage *creation_message)
|
||||
{
|
||||
return new DropZone(creation_message);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
DropZone::~DropZone()
|
||||
{
|
||||
if (dropZones)
|
||||
{
|
||||
Unregister_Pointer(dropZones);
|
||||
delete[] dropZones;
|
||||
Unregister_Pointer(lastUsageTime);
|
||||
delete[] lastUsageTime;
|
||||
Unregister_Pointer(lastUsedBy);
|
||||
delete[] lastUsedBy;
|
||||
Unregister_Pointer(lastDeathCount);
|
||||
delete[] lastDeathCount;
|
||||
}
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Dropzone assignment
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
DropZone::IsAvailable(int index)
|
||||
{
|
||||
Check(this);
|
||||
Verify(index >= 0 && index < dropZoneCount);
|
||||
Check(application);
|
||||
|
||||
return
|
||||
!lastUsageTime[index].ticks
|
||||
|| Now() - lastUsageTime[index] > DOWN_TIME
|
||||
&& application->GetApplicationState() == Application::RunningMission;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
DropZone::AssignDropZoneMessageHandler(AssignDropZoneMessage* message)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
|
||||
Check(application);
|
||||
HostManager *host = application->GetHostManager();
|
||||
Check(host);
|
||||
Entity *entity = host->GetEntityPointer(message->requestingEntity);
|
||||
Check(entity);
|
||||
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
// If we have allocated a dropzone within the last ten seconds for this
|
||||
// player, resend the data
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
Origin *drop_zone = NULL;
|
||||
int
|
||||
lowest, highest, remaining, i;
|
||||
for (i=0; i<dropZoneCount; ++i)
|
||||
{
|
||||
if (
|
||||
!IsAvailable(i)
|
||||
&& lastUsedBy[i] == message->requestingEntity
|
||||
&& lastDeathCount[i] == message->deathCount
|
||||
)
|
||||
{
|
||||
lastUsageTime[i] = Now();
|
||||
drop_zone = &dropZones[i];
|
||||
goto Found_One;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// Figure out how many drop zones are available. If none are, repost this
|
||||
// message to ourself
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
lowest = dropZoneCount;
|
||||
highest = -1;
|
||||
remaining = 0;
|
||||
for (i=0; i<dropZoneCount; ++i)
|
||||
{
|
||||
if (IsAvailable(i))
|
||||
{
|
||||
++remaining;
|
||||
if (i < lowest)
|
||||
{
|
||||
lowest = i;
|
||||
}
|
||||
if (i > highest)
|
||||
{
|
||||
highest = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
// Now, randomly look about until we find one available
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
highest = highest - lowest + 1;
|
||||
while (remaining)
|
||||
{
|
||||
i = lowest + Random(highest);
|
||||
Verify(i < dropZoneCount && i >= 0);
|
||||
if (IsAvailable(i))
|
||||
{
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// Check to see if vehicle attached to a player is within 2 meters of
|
||||
// this drop zone. If so, mark it unavailable for 3 seconds
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
EntityManager *entity_mgr = application->GetEntityManager();
|
||||
Check(entity_mgr);
|
||||
EntityGroup *player_group = entity_mgr->FindGroup("Players");
|
||||
if (
|
||||
player_group
|
||||
&& application->GetApplicationState()
|
||||
== Application::RunningMission
|
||||
)
|
||||
{
|
||||
Player *player;
|
||||
ChainIteratorOf<Node*> iterator(player_group->groupMembers);
|
||||
while ((player = (Player*)iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
Check(player);
|
||||
Entity *vehicle = player->GetPlayerVehicle();
|
||||
if (vehicle && player != entity)
|
||||
{
|
||||
Check(vehicle);
|
||||
Vector3D distance;
|
||||
distance.Subtract(
|
||||
vehicle->localOrigin.linearPosition,
|
||||
dropZones[i].linearPosition
|
||||
);
|
||||
if (distance.LengthSquared() <= 4.0f)
|
||||
{
|
||||
lastUsedBy[i] = NULL;
|
||||
lastUsageTime[i] = Now();
|
||||
lastUsageTime[i] -= DOWN_TIME - 1.0f;
|
||||
--remaining;
|
||||
if (i == lowest)
|
||||
{
|
||||
++lowest;
|
||||
--highest;
|
||||
}
|
||||
else if (i == lowest + highest - 1)
|
||||
{
|
||||
--highest;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
// If someone was in this spot, keep looking for another one
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
if (player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
lastUsageTime[i] = Now();
|
||||
drop_zone = &dropZones[i];
|
||||
lastUsedBy[i] = message->requestingEntity;
|
||||
lastDeathCount[i] = message->deathCount;
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------
|
||||
// If no drop_zone could be found, repost the message to ourselves
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
if (!drop_zone)
|
||||
{
|
||||
Time when=Now();
|
||||
when += 0.1f;
|
||||
application->Post(MaxEventPriority, this, message, when);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
// Send a message back to the requesting object what sent this message
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
Found_One:
|
||||
ReplyMessage
|
||||
reply(
|
||||
message->replyMessageID,
|
||||
sizeof(ReplyMessage),
|
||||
*drop_zone,
|
||||
message->deathCount
|
||||
);
|
||||
entity->Dispatch(&reply);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
DropZone::CreateMakeMessage(
|
||||
MakeMessage *creation_message,
|
||||
const char* model_name,
|
||||
const char* resource_name,
|
||||
NotationFile *map_file
|
||||
)
|
||||
{
|
||||
Check(creation_message);
|
||||
Check(map_file);
|
||||
Check_Pointer(model_name);
|
||||
Check_Pointer(resource_name);
|
||||
|
||||
if (!Entity::CreateMakeMessage(creation_message, map_file, NULL))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
creation_message->classToCreate = RegisteredClass::DropZoneClassID;
|
||||
creation_message->instanceFlags = MapFlag|TrappedFlag;
|
||||
|
||||
//
|
||||
//-----------------------------------------------
|
||||
// Count up the number of drop zones in our model
|
||||
//-----------------------------------------------
|
||||
//
|
||||
Enumeration save_modes = map_file->GetModes();
|
||||
map_file->SetMode(NotationFile::CleanListMode);
|
||||
|
||||
NameList *zone_list =
|
||||
map_file->MakeEntryList(model_name, "dropzone");
|
||||
Register_Object(zone_list);
|
||||
creation_message->dropZoneCount = zone_list->EntryCount();
|
||||
creation_message->messageLength =
|
||||
sizeof(*creation_message)
|
||||
+ creation_message->dropZoneCount*sizeof(Origin);
|
||||
if (!creation_message->dropZoneCount)
|
||||
{
|
||||
std::cout << "Error: " << model_name << " hasn't specified any drop zones!\n";
|
||||
Dump_And_Die:
|
||||
Unregister_Object(zone_list);
|
||||
delete zone_list;
|
||||
map_file->PutModes(save_modes);
|
||||
return False;
|
||||
}
|
||||
|
||||
//
|
||||
//---------------------------------------------
|
||||
// Allocate a buffer to hold the drop zone data
|
||||
//---------------------------------------------
|
||||
//
|
||||
MemoryStream
|
||||
stream(
|
||||
creation_message,
|
||||
creation_message->messageLength,
|
||||
sizeof(*creation_message)
|
||||
);
|
||||
|
||||
//
|
||||
//----------------------------
|
||||
// zero out the drop zone name
|
||||
//----------------------------
|
||||
//
|
||||
for (int ii=0; ii<sizeof(creation_message->dropZoneName); ii++)
|
||||
{
|
||||
creation_message->dropZoneName[ii] = '\0';
|
||||
}
|
||||
|
||||
Str_Copy(
|
||||
creation_message->dropZoneName,
|
||||
resource_name,
|
||||
sizeof(creation_message->dropZoneName)
|
||||
);
|
||||
|
||||
//
|
||||
//-----------------
|
||||
// Read in the data
|
||||
//-----------------
|
||||
//
|
||||
NameList::Entry *drop_zone = zone_list->GetFirstEntry();
|
||||
while (drop_zone)
|
||||
{
|
||||
Point3D translation;
|
||||
EulerAngles tmp_rotation;
|
||||
|
||||
const char* zone_data = drop_zone->GetChar();
|
||||
sscanf(
|
||||
zone_data,
|
||||
"%f %f %f %f %f %f",
|
||||
&translation.x,
|
||||
&translation.y,
|
||||
&translation.z,
|
||||
&tmp_rotation.pitch,
|
||||
&tmp_rotation.yaw,
|
||||
&tmp_rotation.roll
|
||||
);
|
||||
|
||||
((Origin*)stream.GetPointer())->linearPosition = translation;
|
||||
((Origin*)stream.GetPointer())->angularPosition = tmp_rotation;
|
||||
stream.AdvancePointer(sizeof(Origin));
|
||||
drop_zone = drop_zone->GetNextEntry();
|
||||
}
|
||||
|
||||
Unregister_Object(zone_list);
|
||||
delete zone_list;
|
||||
map_file->PutModes(save_modes);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
Logical
|
||||
DropZone::TestInstance() const
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations());
|
||||
}
|
||||
Reference in New Issue
Block a user