Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
359 lines
10 KiB
C++
359 lines
10 KiB
C++
//===========================================================================//
|
|
// File: Interface.cpp //
|
|
// Project: MUNGA Brick: Interest Manager //
|
|
// Contents: Interface specifications for interest manager //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- -----------------------------------------------------------//
|
|
// 08/25/97 JMA Infrastructure changes. //
|
|
// 08/25/97 ECH Infrastructure changes. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "AdeptHeaders.hpp"
|
|
|
|
#include "Interface.hpp"
|
|
#include "Controls.hpp"
|
|
#include "EntityManager.hpp"
|
|
#include "CollisionGrid.hpp"
|
|
#include "Player.hpp"
|
|
|
|
extern "C"
|
|
{
|
|
typedef int BOOL;
|
|
typedef unsigned char BYTE;
|
|
BOOL _stdcall IsDBCSLeadByte(BYTE TestChar);
|
|
char* _stdcall CharPrevA(const char* lpszStart, const char* lpszCurrent);
|
|
char* _stdcall CharNextA(const char* lpsz);
|
|
}
|
|
#define CharPrev CharPrevA
|
|
#define CharNext CharNextA
|
|
extern DWORD g_bDisableImeCompletely;
|
|
//#############################################################################
|
|
//########################### Interface #################################
|
|
//#############################################################################
|
|
|
|
Interface::ClassData*
|
|
Interface::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Interface::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
InterfaceClassID,
|
|
"Adept::Interface",
|
|
BaseClass::DefaultData,
|
|
0, NULL,
|
|
(Entity::Factory)Make,
|
|
(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
|
|
ExecutionStateEngine::DefaultData,
|
|
(Entity::GameModel::Factory)GameModel::ConstructGameModel,
|
|
NULL,
|
|
(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
|
|
(Entity::GameModel::ModelWrite)GameModel::WriteToText,
|
|
(Entity::GameModel::ModelSave)GameModel::SaveGameModel
|
|
);
|
|
Register_Object(DefaultData);
|
|
g_ControlList = new CControlMappingList ();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Interface::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
delete g_ControlList;
|
|
g_ControlList = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Interface*
|
|
Interface::Make(
|
|
const CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(message);
|
|
gos_PushCurrentHeap(g_LibraryHeap);
|
|
Interface *new_entity = new Interface(DefaultData, message, base_id, NULL);
|
|
Check_Object(new_entity);
|
|
gos_PopCurrentHeap();
|
|
return new_entity;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Interface::~Interface()
|
|
{
|
|
LeaveChatMode ();
|
|
Check_Object(ControlsManager::Instance);
|
|
ControlsManager::Instance->RemoveAllMappings();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Interface::Interface(
|
|
ClassData *class_data,
|
|
const CreateMessage *message,
|
|
ReplicatorID *base_id,
|
|
ElementRenderer::Element *element
|
|
):
|
|
Entity(class_data, message, base_id, element),
|
|
reticuleEntity(NULL),
|
|
targetQuery(NULL, NULL, CanBeShotFlag, NULL)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
//
|
|
//------------------------------------------------------------
|
|
// Interfaces should only map controls on their master machine
|
|
//------------------------------------------------------------
|
|
//
|
|
m_ChatMode = false;
|
|
m_InChatMessage = 0;
|
|
m_InsertMode = true;
|
|
m_CurrentChatMessage[m_InChatMessage] = 0;
|
|
reticuleOffset = Point3D::Identity;
|
|
Verify(GetReplicatorMode() == HermitMode);
|
|
|
|
targetDistance = 2000.0f;
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Create the mapping stream and figure out how many mappings to create
|
|
//---------------------------------------------------------------------
|
|
//
|
|
// const GameModel *model = GetGameModel();
|
|
// Check_Object(model);
|
|
Check_Object(ControlsManager::Instance);
|
|
|
|
//
|
|
//------------------------------------------
|
|
// Spin through the mappings and create them
|
|
//------------------------------------------
|
|
//
|
|
// LoadControlStream (model->mappingStreamResourceID);
|
|
}
|
|
|
|
void Interface::ClearMappings (void)
|
|
{
|
|
Check_Object (ControlsManager::Instance);
|
|
ControlsManager::Instance->RemoveAllMappings ();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
static void MyInsertChar(char m_CurrentChatMessage[MaxChatSize], char c1, char c2, int& m_InChatMessage, int& m_ChatLen)
|
|
{
|
|
gosASSERT(m_ChatLen >= m_InChatMessage);
|
|
|
|
int num = c2 ? 2 : 1;
|
|
memmove(m_CurrentChatMessage + m_InChatMessage + num, m_CurrentChatMessage + m_InChatMessage, m_ChatLen - m_InChatMessage);
|
|
m_CurrentChatMessage[m_InChatMessage++] = c1;
|
|
if (c2)
|
|
m_CurrentChatMessage[m_InChatMessage++] = c2;
|
|
m_ChatLen += num;
|
|
m_CurrentChatMessage[m_ChatLen] = 0;
|
|
}
|
|
|
|
static void MyDeleteChar(char m_CurrentChatMessage[MaxChatSize], int& m_InChatMessage, int& m_ChatLen)
|
|
{
|
|
gosASSERT(m_ChatLen >= m_InChatMessage);
|
|
|
|
char* pszPrev = CharPrev(m_CurrentChatMessage, m_CurrentChatMessage + m_InChatMessage);
|
|
int num = m_CurrentChatMessage + m_InChatMessage - pszPrev;
|
|
memmove(pszPrev, m_CurrentChatMessage + m_InChatMessage, m_ChatLen - m_InChatMessage + 1);
|
|
m_ChatLen -= num;
|
|
m_InChatMessage -= num;
|
|
}
|
|
|
|
void Interface::pushChatKey (DWORD key)
|
|
{
|
|
char chr = char (key & 0xff);
|
|
unsigned int ctrl = unsigned int ((key >> 8) & 0xff);
|
|
if ((chr == 13) || (m_InChatMessage == (MaxChatSize-1)))
|
|
{
|
|
LeaveChatMode ();
|
|
m_InChatMessage = 0;
|
|
m_CurrentChatMessage[m_InChatMessage] = 0;
|
|
return;
|
|
}
|
|
|
|
if (!g_bDisableImeCompletely)
|
|
{
|
|
switch (ctrl) {
|
|
case KEY_LEFT:
|
|
// Left arrow must be processed to make GOS IME support work correctly.
|
|
m_InChatMessage = CharPrev(m_CurrentChatMessage, m_CurrentChatMessage + m_InChatMessage) - m_CurrentChatMessage;
|
|
break;
|
|
|
|
case KEY_RIGHT:
|
|
// This is necessary as we support left arrow key.
|
|
m_InChatMessage = CharNext(m_CurrentChatMessage + m_InChatMessage) - m_CurrentChatMessage;
|
|
break;
|
|
|
|
// Fix for patch 2 #403 (feature request)
|
|
case KEY_DELETE:
|
|
{
|
|
char* p = m_CurrentChatMessage + m_InChatMessage;
|
|
if (*p) {
|
|
char* pNext = CharNext(p);
|
|
memmove(p, pNext, strlen(pNext) + 1);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!chr)
|
|
return;
|
|
|
|
static char bLeadByte;
|
|
if (bLeadByte)
|
|
{
|
|
if (m_ChatLen + 2 < MaxChatSize)
|
|
MyInsertChar(m_CurrentChatMessage, bLeadByte, chr, m_InChatMessage, m_ChatLen);
|
|
bLeadByte = 0;
|
|
}
|
|
else if (IsDBCSLeadByte(chr))
|
|
bLeadByte = chr;
|
|
else {
|
|
switch (chr)
|
|
{
|
|
case '\\': // invalid keys
|
|
case '/':
|
|
break;
|
|
case KEY_ESCAPE:
|
|
m_CurrentChatMessage[0] = 0;
|
|
LeaveChatMode ();
|
|
break;
|
|
case '\b':
|
|
if (m_InChatMessage)
|
|
MyDeleteChar(m_CurrentChatMessage, m_InChatMessage, m_ChatLen);
|
|
break;
|
|
default:
|
|
MyInsertChar(m_CurrentChatMessage, chr, 0, m_InChatMessage, m_ChatLen);
|
|
break;
|
|
}
|
|
}
|
|
if (m_InChatMessage == (MaxChatSize-1))
|
|
{
|
|
LeaveChatMode ();
|
|
m_InChatMessage = 0;
|
|
m_CurrentChatMessage[m_InChatMessage] = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
static bool g_bImeOn = true;
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Interface::EnterChatMode (bool team)
|
|
{
|
|
m_ChatMode = true;
|
|
m_TeamChat = team;
|
|
m_InChatMessage = 0;
|
|
m_ChatLen = 0;
|
|
memset (m_CurrentChatMessage,0,MaxChatSize);
|
|
m_CurrentChatMessage[m_InChatMessage] = 0;
|
|
Check_Object(ControlsManager::Instance);
|
|
ControlsManager::Instance->EnterChatMode(this);
|
|
gos_EnableIME(true);
|
|
gos_ToggleIME(g_bImeOn);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Interface::LeaveChatMode (void)
|
|
{
|
|
m_ChatMode = false;
|
|
if (ControlsManager::Instance)
|
|
{
|
|
Check_Object(ControlsManager::Instance);
|
|
ControlsManager::Instance->LeaveChatMode();
|
|
}
|
|
g_bImeOn = gos_GetMachineInformation(gos_Info_GetIMEStatus) ? true : false;
|
|
gos_EnableIME(false);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Interface::LoadControlStream (const ResourceID& control_stream)
|
|
{
|
|
// ClearMappings ();
|
|
// g_ControlList->LoadList (control_stream);
|
|
g_ControlList->ApplyList (this); // list is already loaded by the player
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Entity*
|
|
Interface::CastCollisionLine()
|
|
{
|
|
Check_Object(this);
|
|
|
|
Stuff::Point3D local_point;
|
|
Stuff::Point3D origin_point;
|
|
LinearMatrix4D our_matrix;
|
|
|
|
origin_point = GetLocalToWorld();
|
|
our_matrix = GetLocalToWorld();
|
|
|
|
UnitVector3D origin_direction;
|
|
our_matrix.GetLocalForwardInWorld(&origin_direction);
|
|
|
|
targetLine.SetOrigin(origin_point);
|
|
targetLine.SetDirection(origin_direction);
|
|
targetLine.m_length = targetDistance;
|
|
|
|
targetQuery.m_line = &targetLine;
|
|
targetQuery.m_normal = &reticuleNormal;
|
|
targetQuery.m_collisionMask = CanBeShotFlag;
|
|
Check_Object(Player::GetInstance());
|
|
Entity *vehicle = Player::GetInstance()->vehicle;
|
|
Check_Object(vehicle);
|
|
targetQuery.m_raySource = vehicle;
|
|
|
|
Adept::Entity *entity_hit;
|
|
Check_Object(CollisionGrid::Instance);
|
|
entity_hit = CollisionGrid::Instance->ProjectLine(&targetQuery);
|
|
|
|
targetQuery.m_raySource = entity_hit;
|
|
reticuleEntity.Remove();
|
|
|
|
if (entity_hit != NULL)
|
|
{
|
|
Check_Object(entity_hit);
|
|
reticuleEntity.Add(entity_hit);
|
|
Point3D trans;
|
|
targetLine.FindEnd(&trans);
|
|
reticuleOffset.MultiplyByInverse(
|
|
trans,
|
|
entity_hit->GetLocalToWorld()
|
|
);
|
|
}
|
|
|
|
return entity_hit;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Interface::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|