Files
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

571 lines
17 KiB
C++

#pragma once
#include "network.h"
#include "host.h"
#include "intorgn.h"
#include "entityid.h"
class Renderer;
class Entity;
class Entity__MakeMessage;
class Entity__UpdateMessage;
class Entity__DestroyEntityMessage;
class Entity__Message;
//##########################################################################
//####################### InterestManager ############################
//##########################################################################
#define INTERESTMANAGER_MESSAGE_BUFFER_SIZE (1536)
class Mission;
class InterestManager__EntitySubscribeToUpdatesMessage;
class InterestManager__EntityBroadcastToReplicantsMessage;
class InterestManager__EntityNewInterestZoneMessage;
class InterestManager__HostInterestArenaChangedMessage;
class InterestManager__InterestZoneDeltaMessage;
//
//--------------------------------------------------------------------------
// InterestManager
//
// Entity types relevant to the interest managers operation:
//
// Static Entity (!replicated, !executing, !moving, trapped, map, id)
// - an entity that is not replicated, it does not execute or move.
// It is a component of the map and therefore trapped within its
// interest zone. It has a preallocated entity id. (rock, fence, wall)
//
// Dynamic Entity (replicated, executing, moving, !trapped, !map, !id)
// - an entity that may be replicated. It executes upon its host
// machine. It is also moves freely, crossing interest zones if it
// wishes. It is not a component of the map and can not be given a
// preallocated entity id. (VTV, Mech, missile)
//
// Dynamic Trapped Entity (replicated, executing, moving, trapped, !map, !id)
// - an entity that may be replicated. It executes upon its host
// machine. It may move but not out of its interest zone. It is not
// a component of the map and can not be given a preallocated entity id.
// (mines, burning husk of Mech)
//
// Dynamic Map Entity (replicated, executing, moving, !trapped, map, id)
// - an entity that may be replicated. It executes upon its host machine.
// It is also moves freely, crossing interest zones if it wishes. It
// is a component of the map and can be given a preallocated entity id.
// (The ork that activates upon entering the dungeon and then follows you,
// the one moon around the planet that orbits once every 24 hours)
//
// Dynamic Trapped Map Entity (replicated, executing, moving, trapped, map, id)
// - an entity that may be replicated. It executes upon its host machine.
// It is also moves freely, but may not change interest zones. It is a
// component of the map and can be given a preallocated entity id.
// (The swinging crane, the RP door)
//--------------------------------------------------------------------------
//
class InterestManager:
public NetworkClient
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
InterestManager();
~InterestManager();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execution control
//
public:
virtual void
LoadInterestArenas(Mission *mission);
virtual void
LoadMission(Mission *mission);
void
LoadMapStream(
MemoryStream *map_stream,
const Origin& root,
EntityID& static_id,
int &landmark_id
);
virtual void
Shutdown();
void
Execute();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Interest Origin methods
//
public:
//
//-----------------------------------------------------------------------
// AdoptInterestOrigin
//
// Asserts that the entity is a origin of interest of a specified
// type (example: visual, auditory, radar). Traversals of the interest
// lattice are performed with respect to this origin and may be
// performed with different algorithms depending upon type. The
// Lattice is traversed to a particular "depth" or "cost" for a
// specific interest type and may be calibrated with the
// DepthCalibration parameter.
//-----------------------------------------------------------------------
//
void
AdoptInterestOrigin(InterestOrigin *interestOrigin);
//
//-----------------------------------------------------------------------
// OrphanInterestOrigin
//-----------------------------------------------------------------------
//
void
OrphanInterestOrigin(InterestOrigin *interest_origin);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Entity methods
//
public:
//
//-----------------------------------------------------------------------
// NotifyOfEntityCreation
//-----------------------------------------------------------------------
//
void
NotifyOfEntityCreation(
Entity *entity,
Entity__MakeMessage *creation_message
);
//
//-----------------------------------------------------------------------
// NotifyOfEntityDestruction
//
// This method is called to notify the interest manager that a
// entity has been destroyed.
//-----------------------------------------------------------------------
//
void
NotifyOfEntityDestruction(Entity *entity);
//
//-----------------------------------------------------------------------
// EntityUpdateInterestZone
//
// This method is called if the entity may have changed the
// interest zone that it is in. This is used by the update
// manager.
//-----------------------------------------------------------------------
//
void
EntityUpdateInterestZone(Entity *entity);
//
//-----------------------------------------------------------------------
// EntityForceToInteresting
//
// This forces the interest manager to treat the entity as
// interesting.
//
// HACK - Is effect local? Is the entity forced to be
// interesting on just this host? Or, does the effect pervade
// all hosts?
//-----------------------------------------------------------------------
//
void
EntityForceToInteresting(Entity *entity);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Accesors for interest lattice manager
//
public:
InterestLatticeManager*
GetInterestLatticeManager();
InterestZone*
GetInterestZone(InterestZoneID interestZoneID);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
//
// Message IDs
//
enum
{
//
//--------------------------------------------------------------------
// Sent by an interest manager to itself and others when it has been
// notified that a new dynamic entity has been created on the host
// machine.
//--------------------------------------------------------------------
//
NewDynamicEntityMessageID = NetworkClient::NextMessageID,
#if 0
//
//--------------------------------------------------------------------
// Sent by an interest manager to itself and others when it has been
// notified that a new dynamic map entity has been created on the
// host machine.
//--------------------------------------------------------------------
//
NewMapEntityMessageID,
#endif
//
//--------------------------------------------------------------------
// Sent by an interest manager to itself and others when it has been
// notified that a entity is under going deletion.
//--------------------------------------------------------------------
//
DestroyDynamicEntityMessageID,
//
//--------------------------------------------------------------------
// Message is sent to the host of the original (serving) entity that
// the host id wishes to be on the entities update list.
//--------------------------------------------------------------------
//
EntitySubscribeToUpdatesMessageID,
//
//--------------------------------------------------------------------
// Sent by the interest manager to itself and others when a hosted
// entity needs to send updates to its replicants.
//--------------------------------------------------------------------
//
EntityUpdateReplicantsMessageID,
//
//--------------------------------------------------------------------
// Sent by the interest manager to itself and others when a hosted
// entity needs to broadcast a message to its replicants.
//--------------------------------------------------------------------
//
EntityBroadcastToReplicantsMessageID,
//
//--------------------------------------------------------------------
// Sent by the interest manager to itself and others when a hosted
// entity has changed interest zones.
//--------------------------------------------------------------------
//
EntityNewInterestZoneMessageID,
//
//--------------------------------------------------------------------
// Sent by the interest manager to others when its interest arena has
// changed.
//--------------------------------------------------------------------
//
HostInterestArenaChangedMessageID,
//
//--------------------------------------------------------------------
// Tells interest managers of a change to a interest zone. This is
// for the purpose of creating and destroying Dynamic Map Entities.
// The creation time stamp is used by the interest manager to resolve
// synchronization problems.
//--------------------------------------------------------------------
//
InterestZoneDeltaMessageID,
NextMessageID
};
//
// Message types
//
typedef Entity__MakeMessage
NewDynamicEntityMessage;
typedef Entity__DestroyEntityMessage
DestroyDynamicEntityMessage;
typedef Entity__UpdateMessage
EntityUpdateReplicantsMessage;
typedef InterestManager__EntitySubscribeToUpdatesMessage
EntitySubscribeToUpdatesMessage;
typedef InterestManager__EntityBroadcastToReplicantsMessage
EntityBroadcastToReplicantsMessage;
typedef InterestManager__EntityNewInterestZoneMessage
EntityNewInterestZoneMessage;
typedef InterestManager__HostInterestArenaChangedMessage
HostInterestArenaChangedMessage;
typedef InterestManager__InterestZoneDeltaMessage
InterestZoneDeltaMessage;
//
//-----------------------------------------------------------------------
// NewDynamicEntityHandler
//-----------------------------------------------------------------------
//
void
NewDynamicEntityHandler(NewDynamicEntityMessage *message);
//
//-----------------------------------------------------------------------
// DestroyEntityHandler
//-----------------------------------------------------------------------
//
void
DestroyDynamicEntityHandler(DestroyDynamicEntityMessage *message);
//
//-----------------------------------------------------------------------
// EntitySubscribeToUpdates & EntitySubscribeToUpdatesHandler
//-----------------------------------------------------------------------
//
void
EntitySubscribeToUpdates(
EntityID entity_ID,
HostID master_host,
HostID replicant_host
);
void
EntitySubscribeToUpdatesHandler(
EntitySubscribeToUpdatesMessage *message
);
//
//-----------------------------------------------------------------------
// EntityUpdateReplicants & EntityUpdateReplicantsHandler
//
// If the entity has any subscribers then send then update to subscribers.
//-----------------------------------------------------------------------
//
void
EntityUpdateReplicants(
Entity *entity,
Entity__UpdateMessage *update_message
);
void
EntityUpdateReplicantsHandler(
EntityUpdateReplicantsMessage *update_message
);
//
//-----------------------------------------------------------------------
// EntityBroadcastToReplicants & EntityBroadcastToReplicantsHandler
//
// If the entity has any subscribers then send then update to subscribers.
//-----------------------------------------------------------------------
//
void
EntityBroadcastToReplicants(
Entity *entity,
Entity__Message *broadcast_message
);
void
EntityBroadcastToReplicantsHandler(
EntityBroadcastToReplicantsMessage *broadcast_message
);
//
//-----------------------------------------------------------------------
// EntityNewInterestZoneHandler
//-----------------------------------------------------------------------
//
void
EntityNewInterestZoneHandler(
EntityNewInterestZoneMessage *message
);
//
//-----------------------------------------------------------------------
// HostInterestArenaChanged
//-----------------------------------------------------------------------
//
void
HostInterestArenaChangedHandler(
HostInterestArenaChangedMessage *message
);
//
//-----------------------------------------------------------------------
// InterestZoneDelta
//-----------------------------------------------------------------------
//
void
InterestZoneDeltaHandler(
InterestZoneDeltaMessage *message
);
//
//-----------------------------------------------------------------------
// LoadResourceFinished
//-----------------------------------------------------------------------
//
void
LoadResourceFinishedHandler(Message *message);
//
//-----------------------------------------------------------------------
// Shared Data and message tables
//-----------------------------------------------------------------------
//
static Derivation *GetClassDerivations();
static SharedData
DefaultData;
static const HandlerEntry
MessageHandlerEntries[];
//static MessageHandlerSet MessageHandlers;
static MessageHandlerSet& GetMessageHandlers();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Creation and Interest Event Posting
//
public:
void
PostRendererEvent(
Entity *entity,
Renderer *renderer,
Receiver::Message *message
);
private:
void
PostCreationEvent(Receiver::Message *message);
void
PostUpdateEvent(
Entity *entity,
Receiver::Message *message
);
void
PostDestructionEvent(
Entity *entity,
Receiver::Message *message
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private entity creation and destruction management
//
private:
void
StaticEntityCreation(
Entity *entity,
Entity__MakeMessage *creation_message
);
void
DynamicEntityCreation(
Entity *entity,
Entity__MakeMessage *creation_message
);
void
ReplicantEntityCreation(
Entity *entity,
Entity__MakeMessage *creation_message
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private interest origin management
//
private:
void
AddInterestingEntityToInterestOrigins(Entity *entity);
void
RemoveUninterestingEntityFromInterestOrigins(Entity *entity);
void
AddInterestingEntitiesToInterestOrigin(
InterestOrigin *interest_origin
);
void
RemoveUninterestingEntitiesFromInterestOrigin(
InterestOrigin *interest_origin
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
InterestLatticeManager
interestLatticeManager;
SChainOf<InterestOrigin*>
interestOriginSocket;
InterestArena
*interestArena;
static unsigned char
messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE];
};
//~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~~
class InterestManager__EntitySubscribeToUpdatesMessage:
public NetworkClient::Message
{
public:
InterestManager__EntitySubscribeToUpdatesMessage();
};
//~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~
class InterestManager__EntityBroadcastToReplicantsMessage:
public NetworkClient::Message
{
public:
InterestManager__EntityBroadcastToReplicantsMessage(
size_t message_length
);
};
//~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~~
class InterestManager__EntityNewInterestZoneMessage:
public NetworkClient::Message
{
public:
InterestManager__EntityNewInterestZoneMessage(
const EntityID &entity_ID,
InterestZoneID interest_zone_ID
);
EntityID
entityID;
InterestZoneID
interestZoneID;
//
// HACK - a way is needed to get from the entity the information
// required for another host to create the replicant
//
};
//~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~~
class InterestManager__HostInterestArenaChangedMessage:
public NetworkClient::Message
{
public:
InterestManager__HostInterestArenaChangedMessage();
};
//~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~
class InterestManager__InterestZoneDeltaMessage:
public NetworkClient::Message
{
public:
InterestManager__InterestZoneDeltaMessage();
};
//~~~~~~~~~~~~~~~~~~~~~~~~ InterestManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline InterestLatticeManager*
InterestManager::GetInterestLatticeManager()
{
return &interestLatticeManager;
}
inline InterestZone*
InterestManager::GetInterestZone(InterestZoneID interestZoneID)
{
Check(&interestLatticeManager);
return interestLatticeManager.GetInterestZone(interestZoneID);
}