Files
firestorm/Gameleap/code/mw4/Code/MW4/CRIOMAIN.CPP
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

3306 lines
88 KiB
C++

#define USE_OVRIO
#include "criomain.h"
#include "Vehicle.hpp"
#ifdef _DEBUG
#define AUTO_DENY_TIME 30.0f
#else // !_DEBUG
#define AUTO_DENY_TIME 5.0f
#endif // _DEBUG
Time g_AUX_ADT = AUTO_DENY_TIME;
extern CRIOMAIN *g_pRIOMain;
CRIOMAIN *g_pRIOMain;
extern int m_gCool;
BOOL g_bCrouch = FALSE;//han
//BOOL g_bCool = FALSE;
BOOL g_SearchLight = FALSE;
BOOL g_UsingSearchLight = FALSE;//han
BOOL g_LightAmp = FALSE;
BOOL g_UsingLightAmp = FALSE;//han
LONG *g_lpPadalMode = NULL;
LONG *g_lpJoystickXMode = NULL;
LONG g_Throttle;
LONG g_LeftPedal;
LONG g_RightPedal;
LONG g_JoystickY;
LONG g_JoystickX;
LONG g_ThrottleResult = -1L;
LONG g_HatResult = -1L;
LONG g_ThrottleStart = INT_MIN;
LONG g_LeftPedalStart = INT_MAX;
LONG g_RightPedalStart = INT_MAX;
LONG g_JoystickXLast = 0;
LONG g_JoystickYLast = 0;
LONG g_ThrottleLast = 0;
LONG g_LeftPedalLast = 0;
LONG g_RightPedalLast = 0;
BOOL g_StartGame = FALSE;
static int g_nOpenComState = 0; // 鉉
DWORD g_dwLastAnalogUpdate = 0;
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13
#define ACK_CHAR 0xFC
#define NAK_CHAR 0xFD
#define RESTART_CHAR 0xFE
#define IDLE_CHAR 0xFF
//member 변수처럼 활용할것.
static HANDLE g_hCom = INVALID_HANDLE_VALUE;
static OVERLAPPED wos;
static OVERLAPPED ros;
static OVERLAPPED wcos;//WaitCommEvent
static HANDLE g_hCommWatchThread = NULL, g_hWatchEvent = NULL, g_hLampEvent = NULL;
static DWORD g_dwThreadID;
static BYTE packetbytes[16];
static packetbyteremain=0;
static int chinpacket=0;
static int g_naButtonThrottles[8];
// old(original) RIO Board
static BYTE g_baRIOLengthsA[] = {
0, // 0.CheckRequest
0, // 1.VersionRequest
0, // 2.AnalogRequest
1, // 3.ResetRequest
2, // 4.LampRequest
2, // 5.CheckReply
2, // 6.VersionReply
10, // 7.AnalogReply
1, // 8.ButtonPressed
1, // 9.ButtonReleased
2, // 10.KeyPressed
2, // 11.KeyReleased
1, // 12.TestModeChange
};
int g_nRIOPacketCountA = (sizeof(g_baRIOLengthsA) / sizeof(g_baRIOLengthsA[0]));
// new RIO Board
static BYTE g_baRIOLengthsB[] = {
0, // 0.CheckRequest
0, // 1.VersionRequest
0+1, // 2.AnalogRequest + frequency
1, // 3.ResetRequest
2+1, // 4.LampRequest + id
2, // 5.CheckReply
2, // 6.VersionReply
10, // 7.AnalogReply
1+1, // 8.ButtonPressed + id
1+1, // 9.ButtonReleased + id
2, // 10.KeyPressed
2, // 11.KeyReleased
1, // 12.TestModeChange
1, // 13.Ack2 + id
1, // 14.Nak2 + id
};
int g_nRIOPacketCountB = (sizeof(g_baRIOLengthsB) / sizeof(g_baRIOLengthsB[0]));
int g_nRIOType = 0; // 0: old(original) type, 1: new type
int g_nEjectButton = 61; // 61: original, 31: new type
BYTE* g_pbRIOLengths = NULL;
int g_nRIOPacketCount = 0;
enum RIOCommand {
rio_CheckRequest = 0x80, // 128
rio_VersionRequest, // 129
rio_AnalogRequest, // 130
rio_ResetRequest, // 131
rio_LampRequest, // 132
rio_CheckReply, // 133
rio_VersionReply, // 134
rio_AnalogReply, // 135
rio_ButtonPressed, // 136
rio_ButtonReleased, // 137
rio_KeyPressed, // 138
rio_KeyReleased, // 139
rio_TestModeChange, // 140
// new RIO Board Only...
rio_Ack2, // 141,0x8D
rio_Nak2, // 142,0x8E
};
enum RIOStatusType {
BoardOk, BoardMissing, BoardBad, LampBad, RestartCount, AbandonCount, FullBufferCount
};
enum LampState {
solid=0, flashSlow=1, flashMed=2, flashFast=3,
state1Off=0x00, state1Dim=0x04, state1Bright=0x0C,
state2Off=0x00, state2Dim=0x10, state2Bright=0x30,
};
enum {
LampSolidOff = solid + state1Off + state2Off,
LampSolidDim = solid + state1Dim + state2Dim,
LampSolidBright = solid + state1Bright + state2Bright
};
int g_bNoPlasma = 1;
extern bool g_bCOOP;
extern int g_nCoinCount;
extern int g_nCoinCountTemp;
extern int g_nCoinPerGame;
RIOBUTTON CBUTTON_GROUP::s_aButtonTable[] =
{
//-------------------------------
// #Aux Monitor5 (Bottom Right)
// UP : 7 6 5 4
// DOWN: 3 2 1 0
//-------------------------------
{'P', SYSKEY_NULL, LAMP_DIM}, // 0 48 Assign Group3
{'P', SYSKEY_NULL, LAMP_DIM}, // 1 49 Assign Group2
{'P', SYSKEY_NULL, LAMP_DIM}, // 2 50 Assign Group1
{-1, SYSKEY_NULL, LAMP_DIM}, // 3 51 firing Mode
{'P', SYSKEY_NULL, LAMP_DIM}, // 4 52 Prev Weapon
{'P', SYSKEY_NULL, LAMP_DIM}, // 5 53 Next Weapon
{-1, SYSKEY_NULL, LAMP_DIM}, // 6 54 Chainfire Mode
{-1, SYSKEY_NULL, LAMP_DIM}, // 7 55 Groupfire Mode
//-------------------------------
// #Aux Monitor4 (Bottom Left)
// UP : 15 14 13 12
// DOWN: 11 10 9 8
//-------------------------------
{'Q', SYSKEY_NULL, LAMP_DIM}, // 8 Cross Hair Target
{'E', SYSKEY_CTRL, LAMP_DIM}, // 9
{'E', SYSKEY_NULL, LAMP_DIM}, //10
{'E', SYSKEY_SHFT, LAMP_DIM}, //11
{188, SYSKEY_NULL, LAMP_DIM}, //12 Target Armor State
{'W', SYSKEY_CTRL, LAMP_DIM}, //13
{'W', SYSKEY_NULL, LAMP_DIM}, //14
{'W', SYSKEY_SHFT, LAMP_DIM}, //15
//-------------------------------
// Secondary Screen
// LEFT: 16 - 21 , RIGHT: 24 - 29
//-------------------------------
{'J', SYSKEY_NULL, LAMP_DIM}, //16 Jump Jets
{'S', SYSKEY_NULL, LAMP_DIM}, //17 ShutDownCommand
{-1, SYSKEY_NULL, LAMP_DIM}, //18 Damage
{'F', SYSKEY_NULL, LAMP_DIM}, //19 Flush
{'C', SYSKEY_NULL, LAMP_DIM}, //20 Crouch
{-1 , SYSKEY_NULL, LAMP_DIM}, //21 Program
LAMPBLANK, //22
LAMPBLANK, //23
{'R', SYSKEY_NULL, LAMP_DIM}, //24 Radar Range
{'R', SYSKEY_CTRL, LAMP_DIM}, //25 Radar Mode
{'A', SYSKEY_NULL, LAMP_DIM}, //26 Light Amp
{'L', SYSKEY_NULL, LAMP_DIM}, //27 Search Light
{186, SYSKEY_NULL, LAMP_DIM}, //28 AutoCenter
{-1 , SYSKEY_NULL, LAMP_DIM}, //29 {InputMode}-beginner/middle/advanced
LAMPBLANK, //30 {Coin Inserted Signal if wired}
{'Z', SYSKEY_CTRL, LAMP_NONE}, //31 {act as Eject if wired}
//-------------------------------
// #Aux Monitor2 (Bottom Center)
// UP : 39 38 37 36
// DOWN: 35 34 33 32
//-------------------------------
{-1, SYSKEY_NULL, LAMP_DIM}, //32 Ammo Dump Magazine
{'J', SYSKEY_NULL, LAMP_DIM}, //33 Jump Jets
{'J', SYSKEY_NULL, LAMP_DIM}, //34 Jump Jets
{-1, SYSKEY_NULL, LAMP_DIM}, //35 Ammo Dump Round
{'O', SYSKEY_CTRL, LAMP_DIM}, //36 Objectives
{'N', SYSKEY_CTRL, LAMP_DIM}, //37 NAV point
{'N', SYSKEY_NULL, LAMP_DIM}, //38 NAV point
LAMPBLANK, //39 Team Speak?
// {-1, SYSKEY_NULL, LAMP_NONE}, //39 Team Speak?
//-------------------------------
// #Aux Monitor1 (Upper Left)
// UP : 47 46 45 44
// DOWN: 43 42 41 40
//-------------------------------
{KEY_8, SYSKEY_CTRL, LAMP_DIM}, //40 yes/no
{KEY_7, SYSKEY_CTRL, LAMP_DIM}, //41 ...
{KEY_6, SYSKEY_CTRL, LAMP_DIM}, //42 ...
{KEY_5, SYSKEY_CTRL, LAMP_DIM}, //43 ...
{KEY_4, SYSKEY_CTRL, LAMP_DIM}, //44 team-mate 3
{KEY_3, SYSKEY_CTRL, LAMP_DIM}, //45 team-mate 2
{KEY_2, SYSKEY_CTRL, LAMP_DIM}, //46 team-mate 1
{KEY_1, SYSKEY_CTRL, LAMP_DIM}, //47 team-mate all
//-------------------------------
// #Aux Monitor3 (Upper Right)
// UP : 55 54 53 52
// DOWN: 51 50 49 48
//-------------------------------
{-1, SYSKEY_NULL, LAMP_DIM}, //48 0 Light Amp - Pinky Trigger
{-1, SYSKEY_NULL, LAMP_DIM}, //49 1 Flush - Pinky Trigger
{-1, SYSKEY_NULL, LAMP_DIM}, //50 2 Jump - Pinky Trigger
{-1, SYSKEY_NULL, LAMP_DIM}, //51 3 Zoom - Pinky Trigger
{190, SYSKEY_NULL, LAMP_DIM}, //52 4 Right MFD - Damage MFD(Armor Mode)
{-1, SYSKEY_NULL, LAMP_DIM}, //53 5 CrossTarget - Pinky Trigger
{-1, SYSKEY_NULL, LAMP_DIM}, //54 6 NextTarget - Pinky Trigger
{'O', SYSKEY_NULL, LAMP_DIM}, //55 7 MUTE
//-------------------------------
// #Throttle 56 ~ 63 (8)
//-------------------------------
LAMPBLANK, //56 {Coin Inserted Signal if wired}
LAMPBLANK, //57
LAMPBLANK, //58
LAMPBLANK, //59
LAMPBLANK, //60
{'Z', SYSKEY_CTRL, LAMP_NONE}, //61 {act as Eject if wired}
LAMPBLANK, //62
{-1, SYSKEY_NULL, LAMP_NONE}, //63 dir toggle or JUMP ==> {'J', SYSKEY_NULL, LAMP_DIM}, //16 Jump Jets
//-------------------------------
// #JoyStick 64 ~ 71 (8)
//-------------------------------
LAMPBLANK,// {KEY_INSERT, SYSKEY_NULL, LAMP_NONE}, //64 Fire Group 1 (Main Triger)
{-1, SYSKEY_NULL, LAMP_NONE}, //65 Hat_Down
{-1, SYSKEY_NULL, LAMP_NONE}, //66 Hat_Up
{-1, SYSKEY_NULL, LAMP_NONE}, //67 Hat_right
{-1, SYSKEY_NULL, LAMP_NONE}, //68 Hat_left
{VK_NUMPAD0, SYSKEY_NULL, LAMP_NONE}, //69 ZOOM - Pinky button
LAMPBLANK,// {KEY_PRIOR, SYSKEY_NULL, LAMP_NONE}, //70 Fire Group 3 (Lower Trigger)
LAMPBLANK,// {KEY_HOME, SYSKEY_NULL, LAMP_NONE}, //71 Fire Group 2 (Upper Trigger)
};
#define MAXBUTTON_TABLE (sizeof(CBUTTON_GROUP::s_aButtonTable) / sizeof(CBUTTON_GROUP::s_aButtonTable[0]))
BYTE CBUTTON_GROUP::s_aSaveLamp[MAXBUTTON_TABLE];
BYTE CBUTTON_GROUP::s_aCtrlLamp[MAXBUTTON_TABLE];
void CRIO_StartFrame();
void CRIO_StopFrame();
int IsLampOFF (int n);
int _stdcall VehGetShutdownState();
int _stdcall VehGetJumpJetState();
void DoSaveMechInfos(PMechInfo pDest, PMechInfo pSrc, int nCount);
void __stdcall PLASMA_Do(int nMode);
void __stdcall RIO_Joy(DIJOYSTATE& js);
void __stdcall RIO_ButEvent (BYTE *by);
void __stdcall RIO_StartStop (BOOL bStart);
BOOL SetupConnection(HANDLE hCom);
HANDLE OpenConnection(int port);
BOOL CloseConnection();
void TransmitCommChar2(HANDLE g_hCom,int ch);
int ReadCommBlock( LPSTR lpszBlock, int nMaxLength );
DWORD g_dwLastPacketTime;
DWORD g_dwLastBytesToWrite = 0;
DWORD g_dCancelCount = 0;
BYTE g_baLastPacket[20];
BOOL WriteCommBlock(LPSTR lpByte , DWORD dwBytesToWrite);
DWORD FAR PASCAL CommWatchProc( LPSTR lpData );
short CombinePair(BYTE low_value, BYTE high_value);
void AnalogEvent (BYTE *pData);
BOOL SendPacket (const BYTE *ba,int length);
BOOL SendCommand (const BYTE* pbPacket);
BOOL SetLamp(int lampNumber, int state);
void AnalogAllReset ();
void GeneralReset();
void ResetThrottle();
void ResetLeftPedal();
void ResetRightPedal();
void ResetVerticalJoystick();
void ResetHorizontalJoystick();
void RequestCheck();
void RequestVersion();
void RequestAnalogUpdate(BYTE bFreq = 3);
// start - for new RIO Board only...
//received packet은 각각 다른 스레드에서 처리하므로.. ciritical section이 필요하다..
BYTE received_buffer[128][16];
int received_packet=0;//packets count in the received_buffer.
DWORD received_serial=0;
BYTE sent_buffer[128][16];
int sent_packet=0;//packets count in the sent_buffer.
int sent_serial=0;
DWORD ack_timeout=0;
bool SaveReceivedPacket(const BYTE*ba,int length);
bool GetSerialFromReceivedBuffer(char * ba);
bool QueuePacket(const BYTE *ba,int length);
int PopPacket(BYTE id);
int GetPacketLength(BYTE * ba);
void ReSendPackets(int count);
void SendAck2(BYTE id);
void SendNak2(BYTE id);
int CompareID(int id,int serial);
// end - for new RIO Board only...
class CRIO_Module
{
private:
CRITICAL_SECTION m_csJoyButtons;
public:
BYTE m_baButtons[4];
public:
CRIO_Module()
{
InitializeCriticalSection(&m_csJoyButtons);
for(int i = 0; i < sizeof(m_baButtons) / sizeof(m_baButtons[0]); i++)
m_baButtons[i] = 0;
}
~CRIO_Module()
{
DeleteCriticalSection(&m_csJoyButtons);
}
inline void EnterJoyButtons()
{
EnterCriticalSection(&m_csJoyButtons);
}
inline void LeaveJoyButtons()
{
LeaveCriticalSection(&m_csJoyButtons);
}
inline void SetJoyButton(int nIndex, BYTE bValue)
{
gosASSERT((0 <= nIndex) && (nIndex < sizeof(m_baButtons) / sizeof(m_baButtons[0])));
EnterCriticalSection(&m_csJoyButtons);
m_baButtons[nIndex] = bValue;
LeaveCriticalSection(&m_csJoyButtons);
}
inline void GetJoyButtons(BYTE baButtons[])
{
EnterCriticalSection(&m_csJoyButtons);
for(int i = 0; i < sizeof(m_baButtons) / sizeof(m_baButtons[0]); i++)
baButtons[i] = m_baButtons[i];
/*
static DWORD s_dwLT = 0;
if (baButtons[0] && (!s_dwLT || (s_dwLT + 50 <= GetTickCount()))) {
//MessageBeep(0);
s_dwLT = GetTickCount();
}
*/
LeaveCriticalSection(&m_csJoyButtons);
}
void DoProcessButtons(const BYTE* pcbData);
} s_RIO;
void CRIO_Module::DoProcessButtons(const BYTE* pcbData)
{
BYTE state = pcbData[0];
BYTE index = pcbData[1];
switch(index)
{
case 64: // Fire Group 1 (Main Triger)
SetJoyButton(0, (state == rio_ButtonPressed) ? 0x80: 0);
break;
case 70: // Fire Group 3 (Lower Trigger)
SetJoyButton(3, (state == rio_ButtonPressed) ? 0x80: 0);
break;
case 71: // Fire Group 2 (Upper Trigger)
SetJoyButton(2, (state == rio_ButtonPressed) ? 0x80: 0);
break;
default:
PostMessage(g_hWnd,WM_USER+100,0,*(const DWORD*)pcbData);
break;
}
}
void CRIO_StartFrame()
{
}
void CRIO_StopFrame()
{
if (g_hLampEvent) {
if (g_dwLastBytesToWrite == 0) {
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
if (CBUTTON_GROUP::s_aCtrlLamp[b] != CBUTTON_GROUP::s_aButtonTable[b].lamp) {
SetEvent(g_hLampEvent);
return;
}
}
}
ResetEvent(g_hLampEvent);
}
}
int IsLampOFF (int n)
{
if (g_pRIOMain) {
return ((CBUTTON_GROUP::s_aCtrlLamp[n]) == LAMP_OFF) ? 1: 0;
} else {
return -1;
}
}
int _stdcall VehGetShutdownState()
{
VehicleInterface* p = VehicleInterface::GetInstance();
if (p) {
return p->GetShutdownState();
} else {
return -3;
}
}
int _stdcall VehGetJumpJetState()
{
VehicleInterface* p = VehicleInterface::GetInstance();
if (p) {
return p->GetJumpJetState();
} else {
return -4;
}
}
void DoSaveMechInfos(PMechInfo pDest, PMechInfo pSrc, int nCount)
{
if (nCount > 0) {
memcpy(&pDest[0], &pSrc[0], sizeof(SMechInfo) * nCount);
}
}
void __stdcall PLASMA_Do(int nMode)
{
g_pRIOMain->DoPlasma((char)nMode);
}
void __stdcall RIO_Joy(DIJOYSTATE& js)
{
if (g_pRIOMain) {
g_pRIOMain->UpdateAnalog(js);
}
}
void __stdcall RIO_ButEvent(BYTE *by)
{
if (g_pRIOMain) {
#if 0
if (CTCL_IsConsole()) {
// console...
if (!g_bCOOP) {
if ((by[0] == 255) && (by[1] == 0) && (by[2] == 255) && (by[3] == 0)) {
g_nCoinCount++;
}
}
return;
}
#endif
g_pRIOMain->ButtonEvent(by[0], by[1]);
} else {
}
}
void __stdcall RIO_StartStop (BOOL bStart)
{
if (g_pRIOMain) {
g_pRIOMain->m_bGamePlaying = bStart;
if (bStart) {
g_pRIOMain->SetTable(TRUE);
} else {
g_pRIOMain->ResetTable(TRUE);
}
}
}
BOOL SetupConnection(HANDLE hCom)
{
DCB dcb;
BOOL fRetVal ;
dcb.DCBlength = sizeof( DCB ) ;
GetCommState( hCom, &dcb);
if (CTCL_IsConsole()) {
dcb.BaudRate = CBR_9600;
} else {
dcb.BaudRate = (g_nRIOType == 0) ? CBR_9600: CBR_115200;
}
dcb.ByteSize = 8 ;
dcb.Parity = 0;
dcb.StopBits = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_ENABLE ;
dcb.fOutxCtsFlow = 0;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fInX = 0;
dcb.fOutX = 0;
dcb.XonChar = ASCII_XON ;
dcb.XoffChar = ASCII_XOFF ;
dcb.XonLim = 100 ;
dcb.XoffLim = 100 ;
dcb.fBinary = TRUE ;
dcb.fParity = TRUE ;
fRetVal=SetCommState( hCom, &dcb ) ;
if(fRetVal==0)return FALSE;
// get any early notifications
fRetVal=SetCommMask(hCom, EV_RXCHAR ) ;
if(fRetVal==0)return FALSE;
// setup device buffers
fRetVal=SetupComm(hCom, 2, 2 );
if(fRetVal==0)return FALSE;
// purge any information in the buffer
fRetVal=PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT |PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
if(fRetVal==0)return FALSE;
// set up for overlapped I/O
COMMTIMEOUTS CommTimeOuts={0,};
CommTimeOuts.ReadIntervalTimeout = 1 ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 1 ;
CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0 ;
fRetVal=SetCommTimeouts(hCom, &CommTimeOuts ) ;
if(fRetVal==0)return FALSE;
return TRUE;
/*
원래 처리 루틴..
NPTTYINFO npTTYInfo=0 ;
BYTE bset1 = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_DTRDSR) != 0) ;
BYTE bset2 = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_RTSCTS) != 0) ;
BYTE bset3 = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_XONXOFF) != 0) ;
dcb.DCBlength = sizeof( DCB ) ;
GetCommState( hCom, &dcb ) ;
dcb.BaudRate = BAUDRATE( npTTYInfo ) ;
dcb.ByteSize = BYTESIZE( npTTYInfo ) ;
dcb.Parity = PARITY( npTTYInfo ) ;
dcb.StopBits = STOPBITS( npTTYInfo ) ;
dcb.fOutxDsrFlow = bset1;
dcb.fDtrControl = bset1 ? DTR_CONTROL_HANDSHAKE : DTR_CONTROL_ENABLE ;
dcb.fOutxCtsFlow = bset2 ;
dcb.fRtsControl = bset2?RTS_CONTROL_HANDSHAKE :RTS_CONTROL_ENABLE;
dcb.fInX = bset3;
dcb.fOutX = bset3 ;
dcb.XonChar = ASCII_XON ;
dcb.XoffChar = ASCII_XOFF ;
dcb.XonLim = 100 ;
dcb.XoffLim = 100 ;
dcb.fBinary = TRUE ;
dcb.fParity = TRUE ;
fRetVal = SetCommState( hCom, &dcb ) ;
*/
/*
return fRetVal;
//처리되지 않는 항목들.. GetCommState의 기본값으로 처리한다.
DWORD fDsrSensitivity:1; // DSR sensitivity
DWORD fTXContinueOnXoff:1; // XOFF continues Tx
DWORD fErrorChar: 1; // enable error replacement
DWORD fNull: 1; // enable null stripping
DWORD fAbortOnError:1; // abort on error
DWORD fDummy2:17; // reserved
WORD wReserved; // not currently used
char ErrorChar; // error replacement character
char EofChar; // end of input character
char EvtChar; // received event character
WORD wReserved1; // reserved; do not use
*/
}
HANDLE OpenConnection(int port)
{
if (g_nRIOType == 0) {
g_pbRIOLengths = &g_baRIOLengthsA[0];
g_nRIOPacketCount = g_nRIOPacketCountA;
g_nEjectButton = 61;
} else {
g_pbRIOLengths = &g_baRIOLengthsB[0];
g_nRIOPacketCount = g_nRIOPacketCountB;
g_nEjectButton = 31;
}
//port: 1~n
char portname[8];
wsprintf(portname,"COM%d",port);
DWORD dwFAs = FILE_ATTRIBUTE_NORMAL;
#ifdef USE_OVRIO
dwFAs |= FILE_FLAG_OVERLAPPED;
#endif // USE_OVRIO
g_hCom = CreateFile( portname, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING, dwFAs, NULL );
if (g_hCom != INVALID_HANDLE_VALUE) {
if (SetupConnection(g_hCom)) {
ros.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
wos.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
g_hWatchEvent = CreateEvent(0,0,0,0);
g_hLampEvent = CreateEvent(0,FALSE,0,0);
g_hCommWatchThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0, (LPTHREAD_START_ROUTINE)CommWatchProc, NULL, CREATE_SUSPENDED, &g_dwThreadID);
if (g_hCommWatchThread) {
//Thread까지 정상적으로 생성되었다.
//////////////////////////////////////////////
//All OK
//Exit Point <======
EscapeCommFunction( g_hCom, SETDTR ) ;
Sleep(50);
EscapeCommFunction( g_hCom, CLRDTR ) ;
Sleep(1000);
//SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
SetThreadPriority(g_hCommWatchThread,THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(g_hCommWatchThread);
g_nOpenComState = 1;
return g_hCom;
}
}
CloseConnection();
}
return INVALID_HANDLE_VALUE;
}
BOOL CloseConnection()
{
if (g_hCom != INVALID_HANDLE_VALUE) {
SetCommMask(g_hCom, 0);
//Terminate Watch Thread
if (g_hCommWatchThread) {
SetEvent(g_hWatchEvent);
WaitForSingleObject(g_hCommWatchThread, INFINITE);
g_hCommWatchThread = NULL;
}
if (g_hWatchEvent) {
CloseHandle(g_hWatchEvent);
g_hWatchEvent = NULL;
}
if (g_hLampEvent) {
CloseHandle(g_hLampEvent);
g_hLampEvent = NULL;
}
EscapeCommFunction(g_hCom, CLRDTR);
// purge any outstanding reads/writes and close device handle
PurgeComm(g_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
CloseHandle(g_hCom);
g_hCom = INVALID_HANDLE_VALUE;
// clean up event objects
if (ros.hEvent) {
CloseHandle(ros.hEvent);
ros.hEvent = NULL;
}
if (wos.hEvent) {
CloseHandle(wos.hEvent);
wos.hEvent = NULL;
}
g_nOpenComState = 0;
}
return TRUE;
}
void TransmitCommChar2(HANDLE g_hCom,int ch)
{
#if 0
DWORD bytes;
WriteFile(g_hCom,&ch,1,&bytes,NULL);
FlushFileBuffers(g_hCom);
#else
TransmitCommChar(g_hCom,(char)ch);
#endif
}
int ReadCommBlock( LPSTR lpszBlock, int nMaxLength )
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
// only try to read number of bytes in queue
ClearCommError( g_hCom, &dwErrorFlags, &ComStat ) ;
retry:
dwLength = __min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
if (dwLength > 0){
fReadStat = ReadFile( g_hCom, lpszBlock,dwLength, &dwLength, &ros);
for(int i=0;i<(int)dwLength;i++){
int ch=(BYTE)lpszBlock[i];
//받은 문자만큼 루프를 돈다.
//현재.. 받고 있는 packet이 없고.. 어떤 control문자라도 올 수 있는 상태이다.
if(packetbyteremain!=0){
//패킷에 해당하는 문자가 도착했다.. 나머지 문자들을 받는다.
if (ch & 0x80) {
packetbyteremain=0;
chinpacket=0;
continue;
}
packetbyteremain--;
packetbytes[chinpacket] = ch;
chinpacket++;
if (packetbyteremain == 0) {
//하나의 패킷이 완성되었다. 도착했다.. 즉시 반응한다.
chinpacket--; // exclude check byte
int packettype=packetbytes[0];
BYTE bCheckByte = 0;
for(int kkk = 0; kkk < chinpacket; kkk++) {
bCheckByte += packetbytes[kkk] & 0x7f;
}
static bool s_bool = true;
if (s_bool || (bCheckByte & 0x7f) ==packetbytes[chinpacket]) {
switch(packettype) {
//PC to RIO
case rio_CheckRequest:
case rio_VersionRequest:
case rio_AnalogRequest:
case rio_ResetRequest:
case rio_LampRequest:
/*if(ComStat.cbOutQue==0)
TransmitCommChar2(g_hCom,NAK_CHAR);
break;
*/
//RIO to PC
case rio_CheckReply:
case rio_VersionReply:
case rio_KeyPressed:
case rio_KeyReleased:
case rio_TestModeChange:
if(ComStat.cbOutQue==0)
TransmitCommChar2(g_hCom,ACK_CHAR);
break;
case rio_AnalogReply:
if(ComStat.cbOutQue==0)
TransmitCommChar2(g_hCom,ACK_CHAR);
AnalogEvent (packetbytes);
g_dwLastAnalogUpdate = 0;
break;
case rio_ButtonPressed:
case rio_ButtonReleased:
if (g_nRIOType == 0) {
if(ComStat.cbOutQue==0)
TransmitCommChar2(g_hCom,ACK_CHAR);
s_RIO.DoProcessButtons(&packetbytes[0]);
} else {
//MessageBeep(0);
BYTE id=packetbytes[2];
//if(CompareID(id,received_serial)==0){
SendAck2(id);
//if (packetbytes[1] != 4) {
// MessageBeep(0);
s_RIO.DoProcessButtons(&packetbytes[0]);
//}
received_serial++;
/*
char buf[16];
while(GetSerialFromReceivedBuffer(buf)){//check if any more serial packet in the received_buffer.
//if (packetbytes[1] != 4) {
// MessageBeep(0);
s_RIO.DoProcessButtons(&packetbytes[0]);
//}
}
}else{//id is not serial
if(CompareID(id,received_serial)>0) {
SendNak2(received_serial & 0x7f);
//new one..
SaveReceivedPacket(packetbytes,GetPacketLength(packetbytes));
} else if(CompareID(id,received_serial)<0) {
SendAck2(id);
//old pakcet ignore..
}
}
*/
}
break;
case rio_Nak2:
#ifdef _DEBUG
packettype++;
packettype--;
#endif // _DEBUG
case rio_Ack2://◆◆◆◆◆◆◆◆◆◆
if (g_nRIOType != 0) {
BYTE id=packetbytes[1];
int popped_index=PopPacket(id);
ack_timeout=GetTickCount()+30;
if(popped_index==0){
//맨처음것... 정상적인 경우이다.
}else if(popped_index>0){
//맨처음것이 아닌것.
//이전것들이 정상적으로 보내지지 않았으므로 다시 보낸다...
ReSendPackets(popped_index);//잘못된 개수 만큼..
}else{
//실패 했다는것은.. 없는 id가 왔다는 것인데..
//명백한 에러.. 그러나 특별히 대처할 방법은 없다.
//그냥 무시한다.
}
}
break;
}
} else {
if (g_nRIOType == 0) {
if (ComStat.cbOutQue==0) {
if ((packettype == rio_ButtonPressed) || (packettype == rio_ButtonReleased))
TransmitCommChar2(g_hCom,NAK_CHAR);
else
TransmitCommChar2(g_hCom,ACK_CHAR);
}
}
}
// TransmitCommChar2(g_hCom,0xFC);
// WriteTTYBlock(hWnd,"|",1);
chinpacket=0;
//packetbytes버퍼를 지운다.
} else {
//아직 패킷 문자들이 다 도착하지 않았다.. 아무것도 하지 않는다.
;
}
}else{
chinpacket=0;
if ((rio_CheckRequest <= ch) && (ch < (rio_CheckRequest+g_nRIOPacketCount))) {
packetbyteremain = g_pbRIOLengths[ch-rio_CheckRequest]+1;
chinpacket=0;
packetbytes[chinpacket]=ch;
chinpacket++;
} else {
WriteCommBlock(NULL, ch);
}
}
}//for(int i=0;i<(int)dwLength;i++)
//상훈 뒤
if (!fReadStat){
if (GetLastError() == ERROR_IO_PENDING){
while(!GetOverlappedResult( g_hCom,&ros, &dwLength, TRUE )){
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
// normal result if not finished
continue;
else{
// an error occurred, try to recover
ClearCommError( g_hCom, &dwErrorFlags, &ComStat ) ;
break;
}
}
goto retry;
}else{
// some other error occurred
dwLength = 0 ;
ClearCommError( g_hCom, &dwErrorFlags, &ComStat ) ;
}
}
}
return dwLength;
}
BOOL WriteCommBlock(LPSTR lpByte, DWORD dwBytesToWrite)
{
if (lpByte == NULL) {
switch(dwBytesToWrite) {
case ACK_CHAR:
g_dwLastBytesToWrite = 0;
break;
case NAK_CHAR:
if (g_dwLastBytesToWrite != 0) {
if (g_baLastPacket[0] == rio_LampRequest) {
CBUTTON_GROUP::s_aButtonTable[g_baLastPacket[1]].lamp = LAMP_NOTEXIST;
}
g_dwLastBytesToWrite = 0;
}
break;
case RESTART_CHAR:
break;
case IDLE_CHAR:
break;
default:
break;
}
return FALSE;
}
//Normal Variables
BOOL fWriteStat ;
DWORD dwBytesWritten ;
DWORD dwBytesSent=0;
//Error Report
DWORD dwErrorFlags;
COMSTAT ComStat;
if (g_dwLastBytesToWrite == 0) {
g_dCancelCount = 0;
g_dwLastPacketTime = GetTickCount();
if (g_nRIOType == 0) {
g_dwLastBytesToWrite = dwBytesToWrite;
}
memcpy(g_baLastPacket, lpByte, dwBytesToWrite);
} else {
if (lpByte[0] == rio_LampRequest) {
CBUTTON_GROUP::s_aButtonTable[lpByte[1]].lamp = LAMP_NOTEXIST;
}
if (++g_dCancelCount >= 5) {
g_dwLastBytesToWrite = 0;
}
return FALSE;
}
fWriteStat = WriteFile(g_hCom, lpByte, dwBytesToWrite,&dwBytesWritten, &wos) ;
if (fWriteStat == FALSE) {
if (GetLastError() == ERROR_IO_PENDING) {
while(!GetOverlappedResult(g_hCom,&wos, &dwBytesWritten, TRUE)) {
if(GetLastError() == ERROR_IO_INCOMPLETE){
dwBytesSent += dwBytesWritten;
Sleep(0);//Yield the process to the others
} else {
ClearCommError(g_hCom, &dwErrorFlags, &ComStat ) ;
g_dwLastBytesToWrite = 0;
return FALSE;
}
}
} else {
ClearCommError(g_hCom, &dwErrorFlags, &ComStat ) ;
g_dwLastBytesToWrite = 0;
return FALSE;
}
}
return TRUE;
}
DWORD FAR PASCAL CommWatchProc( LPSTR lpData )
{
wcos.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE events[3]={wcos.hEvent,g_hWatchEvent,g_hLampEvent};
if (CTCL_IsConsole()) {
if (!SetCommMask( g_hCom, EV_RXCHAR/*|EV_CTS*/))
return ( FALSE ) ;
} else {
if (!SetCommMask( g_hCom, EV_RXCHAR ))
return ( FALSE ) ;
}
g_dwLastAnalogUpdate = GetTickCount() + 2800;
while(1) {
DWORD dwEvtMask = 0;
WaitCommEvent( g_hCom, &dwEvtMask,&wcos );
DWORD ret=WaitForMultipleObjects(3,events,FALSE,50/*INFINITE*/);
if(ret==WAIT_OBJECT_0){
//An Comm Event has arrived.
DWORD bytesread;
#ifdef USE_OVRIO
GetOverlappedResult(g_hCom,&wcos,&bytesread,FALSE);
#endif // USE_OVRIO
BYTE abIn[16] ;
ReadCommBlock((LPSTR) abIn, 16 );
//((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
/*if (CTCL_IsConsole()) {
if ((dwEvtMask & EV_CTS) == EV_CTS) {
static BYTE s_ba4[4] = { 255,0,255,0};
s_RIO.DoProcessButtons(&s_ba4[0]);
}
} else {*/
if (g_nRIOType != 0) {
///◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆위의 ReadCommBlock에서 ack를 받았을 경우 duetime을 update시킨다.
///◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆CheckSentBuffer...
if(GetTickCount()>ack_timeout)
ReSendPackets(sent_packet);//sent_buffer에 있는 모든것들을 다시 보내본다.
}
/*}*/
}else if(ret==WAIT_OBJECT_0+1){
//Terminate This Thread.
goto terminate;
}else if(ret==WAIT_OBJECT_0+2){
//g_hLampEvent is set.
g_pRIOMain->RunMain();
}else if(ret==WAIT_FAILED){
//can't be reached here.!!!
//break;
}else if (ret==WAIT_TIMEOUT) {
if (g_nRIOType != 0) {
///◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆CheckSentBuffer...
if(GetTickCount()>ack_timeout)
ReSendPackets(sent_packet);//sent_buffer에 있는 모든것들을 다시 보내본다.
}
if (packetbyteremain == 0) {
RequestAnalogUpdate();
/*
DWORD dwTicks = GetTickCount();
if ((g_dwLastAnalogUpdate == 0) || ((g_dwLastAnalogUpdate + 200) <= dwTicks)) {
g_dwLastAnalogUpdate = dwTicks;
RequestAnalogUpdate();
}
*/
} else {
}
}
}
terminate:
// get rid of event handle
CloseHandle( wcos.hEvent ) ;
return( TRUE ) ;
}
short CombinePair(BYTE low_value, BYTE high_value)
{
short result;
result = (short)(((short) (low_value & 0x7F)) | (((short) high_value) << 7));
if (result & 0x2000)
{
result |= ~0x3FFF;
}
return result;
}
void AnalogEvent (BYTE *pData)
{
/*
for (int i = 1; i <= 10; i++) {
if (pData[i] == 0xFE) {
//AnalogAllReset ();
return;
}
}
*/
g_Throttle = CombinePair (pData[1], pData[2]);
g_LeftPedal = CombinePair(pData[3], pData[4]);
g_RightPedal = CombinePair(pData[5], pData[6]);
g_JoystickY = CombinePair(pData[7], pData[8]);
g_JoystickX = CombinePair(pData[9], pData[10]);
/*
static char s_szStr[256];
sprintf (s_szStr, "JOYX[%d]\n",g_JoystickX);
::OutputDebugString(s_szStr);
*/
}
BOOL SendPacket (const BYTE *ba,int length)
{
if (g_nRIOType != 0) {
if(ba[0]==rio_LampRequest){
QueuePacket(ba,length);
}
}
return WriteCommBlock((LPSTR)ba,length);
}
BOOL SendCommand (const BYTE* pbPacket)
{
BYTE ba[256];
BYTE bCmd = *pbPacket;
int cmdindex=bCmd & 0x7F;
if (bCmd & 0x80) {
if (cmdindex < g_nRIOPacketCount) {
int nLeft = 1/* 1byte command */ + g_pbRIOLengths[cmdindex];
BYTE bCheck = 0;
BYTE * p=ba;
while (nLeft > 0) {
BYTE b = *pbPacket++;
*p++ = b;
bCheck += b & 0x7F;
nLeft--;
}
*p++ = bCheck & 0x7F;
return SendPacket (ba, p - ba);
} else {
//unknown command
}
} else {
;//error
}
return TRUE;
}
BOOL SetLamp(int lampNumber, int state)
{
static BYTE request_lamp_string[] = { rio_LampRequest, 0, 0, 0 };
request_lamp_string[1] = (BYTE) (lampNumber & 0x7F);
request_lamp_string[2] = (BYTE) (state & 0x7F);
if (g_nRIOType != 0) {
request_lamp_string[3] = (BYTE) (sent_serial++ & 0x7F);
}
return SendCommand (request_lamp_string);
}
void AnalogAllReset ()
{
ResetThrottle ();
ResetLeftPedal ();
ResetRightPedal();
ResetVerticalJoystick();
ResetHorizontalJoystick();
}
void GeneralReset()
{
received_serial = 0;
static BYTE request_reset_string[] = { rio_ResetRequest, 0 };
SendCommand (request_reset_string);
}
void ResetThrottle()
{
static BYTE request_throttle_string[] = { rio_ResetRequest, 1 };
SendCommand (request_throttle_string);
}
void ResetLeftPedal()
{
static BYTE request_lpedal_string[] = { rio_ResetRequest, 2 };
SendCommand (request_lpedal_string);
}
void ResetRightPedal()
{
static BYTE request_rpedal_string[] = { rio_ResetRequest, 3 };
SendCommand (request_rpedal_string);
}
void ResetVerticalJoystick()
{
static BYTE request_vstick_string[] = { rio_ResetRequest, 4 };
SendCommand (request_vstick_string);
}
void ResetHorizontalJoystick()
{
static BYTE request_hstick_string[] = { rio_ResetRequest, 5 };
SendCommand (request_hstick_string);
}
void RequestCheck()
{
static BYTE request_check_string[] = { rio_CheckRequest };
SendCommand (request_check_string);
}
void RequestVersion()
{
static BYTE request_version_string[] = { rio_VersionRequest };
SendCommand (request_version_string);
}
void RequestAnalogUpdate(BYTE bFreq/* = 3*/)
{
static BYTE request_analog_string[] = { rio_AnalogRequest, 3/* freq */ };
if (g_nRIOType != 0) {
request_analog_string[1] = bFreq;
}
SendCommand (request_analog_string);
}
bool SaveReceivedPacket(const BYTE*ba,int length)
{
if(received_packet<127){
//MessageBeep(0);
CopyMemory(received_buffer[received_packet],ba,length);
received_packet++;
return true;
}else{
return false;
}
}
bool GetSerialFromReceivedBuffer(char * ba)
{
//ButtonPressed/Released만 저장해 놓는다..
//모든 serial packet을 옮긴다.
if(received_packet>0){
if(received_buffer[0][2]==received_serial){
CopyMemory(ba,received_buffer[0],16);
if(received_packet>1)
MoveMemory(received_buffer[0],received_buffer[1],(received_packet-1)*16);
received_packet--;
received_serial++;
return true;
}
}
return false;
}
bool QueuePacket(const BYTE *ba,int length)
{
if(sent_packet<127){
CopyMemory(sent_buffer[sent_packet],ba,length);
sent_packet++;
return true;
}else{
return false;
}
}
int PopPacket(BYTE id)
{
//lamp는.. id가..
//search the packet..
for(int i=0;i<sent_packet;i++){
if(sent_buffer[i][3]==id){
//found the packet..
int packets_to_move=sent_packet-i-1;
if(packets_to_move>0)
MoveMemory(sent_buffer[i],sent_buffer[i+1],packets_to_move*16);
sent_packet--;
//if (i == 0)
// return 0;
return i;//found the item sucessfully
}
}
return -1;//didn't find the item
}
int GetPacketLength(BYTE * ba)
{
return (1+g_pbRIOLengths[ba[0]-rio_CheckRequest]+1);//header+body+CS
}
void ReSendPackets(int count)
{
gosASSERT(count<=sent_packet);
ack_timeout=GetTickCount()+30;
for(int i=0;i<count;++i){
BYTE ba[16];
CopyMemory(ba,sent_buffer[0],16);
int packets_to_move=sent_packet-1;
if(packets_to_move)
MoveMemory(sent_buffer[0],sent_buffer[1],packets_to_move*16);
sent_packet--;
int length=1+g_pbRIOLengths[ba[0]-rio_CheckRequest]+1;//header+body+CS
SendPacket(ba,length);
}
}
void SendAck2(BYTE id)
{
BYTE packet[2]={rio_Ack2,id};
SendCommand(packet);
}
void SendNak2(BYTE id)
{
BYTE packet[2]={rio_Nak2,id};
SendCommand(packet);
}
int CompareID(int id,int serial)
{
serial &= 0x7F;
if (id !=serial) {
if (id>serial) {
if(id-serial<63)
return 1;
else
return -1;
} else {//if(id<serial)
if(serial-id<63)
return -1;
else
return 1;
}
} else {
return 0;
}
}
CBUTTON_GROUP::CBUTTON_GROUP ()
{
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
s_aSaveLamp[b] = s_aButtonTable[b].lamp;
}
}
CBUTTON_GROUP::~CBUTTON_GROUP ()
{
}
void CBUTTON_GROUP::SetTable(BOOL bFlag/* = true*/)
{
if (bFlag == TRUE)
{
if (!g_StartGame) {
g_StartGame = TRUE;
memset(g_naButtonThrottles, 0, sizeof(g_naButtonThrottles));
//GeneralReset ();
m_bFreeForAll = MWApplication::GetInstance()->IsTeamAllowed() ? FALSE: TRUE;
if (m_bFreeForAll)
g_nTeamOrderMode = FREEFORALL_MODE;
else
g_nTeamOrderMode = TEAM_MODE;
MWApplication::GetInstance()->ClearTOC();
g_fLastStartTime = 0.0;
g_fLastCameraShipTime = gos_GetElapsedTime();
g_fLastScoringTime = g_fLastScoringTimeCechk = gos_GetElapsedTime();
m_bOneFlagShutDown = FALSE;
// MSL 5.03 Ammo Dump
g_nAmmoDump1 = FALSE;
g_nAmmoDump2 = FALSE;
g_nAssignGroup1 = FALSE;
g_nAssignGroup2 = FALSE;
g_nAssignGroup3 = FALSE;
g_nPrevWeapon = FALSE;
g_nNextWeapon = FALSE;
g_nProgramMode = FALSE;
g_nFiringMode = FALSE;
MechWarrior4::g_baChainFireMode[0] = MechWarrior4::g_baChainFireMode[1] = MechWarrior4::g_baChainFireMode[2] = FALSE;//han
// MSL 5.05 Objective Display
g_bObjMode = false;
g_bMuteMode = false;
// MSL 5.03 Secondary Damage Display
g_nAuxilMode = 0;
// MSL 5.02 Pinky Button
if (VehGetJumpJetState() > 0)
{
g_bJumpZoom = true; // Secondary button 16 set to Jump
s_aButtonTable[69].norm_key = VK_NUMPAD0;
s_aButtonTable[16].norm_key = 'J';
g_bZoomMode = true;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
else
{
g_bJumpZoom = false; // Secondary button 16 set to Zoom
s_aButtonTable[69].norm_key = VK_NUMPAD0;
s_aButtonTable[16].norm_key = VK_NUMPAD0;
g_bZoomMode = true;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
g_nInputMode = g_nOldInputMode = _BIGINNER_MODE;
g_ThrottleResult = -1L;
g_HatResult = -1L;
g_ThrottleStart = INT_MIN;
g_LeftPedalStart = INT_MAX;
g_RightPedalStart = INT_MAX;
g_JoystickXLast = 0;
g_JoystickYLast = 0;
g_ThrottleLast = 0;
g_LeftPedalLast = 0;
g_RightPedalLast = 0;
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
s_aCtrlLamp[b] = s_aSaveLamp[b];// = s_aButtonTable[b].lamp;
// s_aButtonTable는 Old값이므로 초기치는 Off
s_aButtonTable[b].lamp = LAMP_OFF;
}
PLASMA_Do(2);
SetLampState (30, LAMP_BRIGHT);
SetLampState (59, LAMP_BRIGHT);
}
}
else
{
// 모든 테이블을 원래 상태로
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
s_aCtrlLamp[b] = s_aSaveLamp[b];
}
}
}
void CBUTTON_GROUP::ResetTable(BOOL bFlag/* = true*/)
{
if (bFlag == TRUE)
{
if (g_StartGame) {
g_StartGame = FALSE;
PLASMA_Do(1);
//GeneralReset ();
m_bFreeForAll = FALSE;
MWApplication::GetInstance()->ClearTOC();
g_fLastStartTime = 0.0;
g_fLastCameraShipTime = 0.0;
g_fLastScoringTimeCechk = 0.0;
g_fLastScoringTime = 0.0;
m_bOneFlagShutDown = FALSE;
// MSL 5.03 Ammo Dump
g_nAmmoDump1 = FALSE;
g_nAmmoDump2 = FALSE;
g_nAssignGroup1 = FALSE;
g_nAssignGroup2 = FALSE;
g_nAssignGroup3 = FALSE;
g_nPrevWeapon = FALSE;
g_nNextWeapon = FALSE;
g_nProgramMode = FALSE;
g_nFiringMode = FALSE;
MechWarrior4::g_baChainFireMode[0] = MechWarrior4::g_baChainFireMode[2] = MechWarrior4::g_baChainFireMode[2] = FALSE;//han
// MSL 5.05 Objective Display
g_bObjMode = false;
g_bMuteMode = false;
// MSL 5.03 Secondary Damage Display
g_nAuxilMode = 0;
// MSL 5.02 Pinky Button
if (VehGetJumpJetState() > 0)
{
g_bJumpZoom = true; // Secondary button 16 set to Jump
s_aButtonTable[69].norm_key = VK_NUMPAD0;
s_aButtonTable[16].norm_key = 'J';
g_bZoomMode = true;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
else
{
g_bJumpZoom = false; // Secondary button 16 set to Zoom
s_aButtonTable[69].norm_key = VK_NUMPAD0;
s_aButtonTable[16].norm_key = VK_NUMPAD0;
g_bZoomMode = true;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
g_nInputMode = g_nOldInputMode = _BIGINNER_MODE;
g_ThrottleResult = -1L;
g_HatResult = -1L;
//g_JoystickXStart = INT_MIN;
//g_JoystickXEnd = INT_MAX;
//g_JoystickYStart = INT_MAX;
//g_JoystickYEnd = INT_MIN;
g_ThrottleStart = INT_MIN;
g_LeftPedalStart = INT_MAX;
g_RightPedalStart = INT_MAX;
g_JoystickXLast = 0;
g_JoystickYLast = 0;
g_ThrottleLast = 0;
g_LeftPedalLast = 0;
g_RightPedalLast = 0;
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
s_aCtrlLamp[b] = LAMP_OFF; // s_aSaveLamp[b];
}
SetLampState (59, LAMP_OFF);
SetLampState (30, LAMP_OFF);
}
}
else
{
// 모든 테이블을 Off
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
switch(b)
{
case 17: // ShutDown Command
case 48: // Pinky Trigger
case 49: // Pinky Trigger
case 50: // Pinky Trigger
case 51: // Pinky Trigger
case 52: // Right MFD - Damage MFD(Armor Mode)
case 53: // Pinky Trigger
case 54: // Pinky Trigger
case 55: // MUTE
// case 39: // Team Speak?
case 36: // Objective Display
case 12: // Target Armor State
case 8: // Corss Hair Target
case 0: // Assign Group3
case 1: // Assign Group2
case 2: // Assign Group1
case 3: // firing Mode
case 4: // Prev Weapon
case 5: // Next Weapon
case 6: // Chainfire Mode
case 7: // Groupfire Mode
break;
default:
s_aCtrlLamp[b] = LAMP_OFF;
break;
}
}
}
}
int CBUTTON_GROUP::GetLampState(BYTE b) const
{
return s_aCtrlLamp[b];
}
void CBUTTON_GROUP::SetLampState(BYTE b, int State)
{
BYTE &lamp = s_aCtrlLamp[b];
BYTE Oldlamp = lamp;
#ifdef _DEBUG
static BYTE g_bWatch = 26;
if (b == g_bWatch) {
int a = 0;
a++;
a--;
}
#endif // _DEBUG
if (State == LAMP_DEFAULT) { //Defalult Lamp Set
const BYTE dlamp = s_aSaveLamp[b];
lamp = dlamp;
#ifdef _DEBUG
State = dlamp;
#endif // _DEBUG
} else {
lamp = (BYTE)State;
}
if (Oldlamp != lamp) {
#if 0 // def _DEBUG
char sz[64];
sprintf(sz, "but: %d, old %d -> new %d\n", b, Oldlamp, State);
::OutputDebugString(sz);
#endif // _DEBUG
//SetEvent(g_hLampEvent);
}
}
CRIOMAIN::CRIOMAIN (HWND hWnd)
{
g_hWnd = hWnd;
m_bGamePlaying = FALSE;
m_bFreeForAll = FALSE;
MWApplication::GetInstance()->ClearTOC();
g_fLastStartTime = 0.0;
g_fLastCameraShipTime = 0.0;
g_fLastScoringTimeCechk = 0.0;
g_fLastScoringTime = 0.0;
m_bOneFlagShutDown = FALSE;
OpenConnection(1); //
GeneralReset ();
RequestAnalogUpdate ();
//SetTable ();
}
CRIOMAIN::~CRIOMAIN ()
{
GeneralReset ();
CloseConnection ();
}
int CRIOMAIN::IsLampOFF(int n) const
{
if (s_aCtrlLamp[n] == LAMP_OFF) {
return 1;
} else {
return 0;
}
}
void CRIOMAIN::RunMain ()
{
if (this) {
//RequestAnalogUpdate ();
if (g_nOpenComState) {
if (g_dwLastBytesToWrite == 0) {
for (int b = 0; b < MAXBUTTON_TABLE; b++)
{
BYTE Newlamp = s_aCtrlLamp[b];
BYTE &Oldlamp = s_aButtonTable[b].lamp;
if (Newlamp != Oldlamp)
{
Oldlamp = Newlamp;
LampEvent (b);
return;
}
}
}
}
}
}
BOOL CRIOMAIN::LampEvent (BYTE b)
{
BYTE state = s_aButtonTable[b].lamp;
switch (state)
{
case LAMP_NONE:
return TRUE;
case LAMP_OFF:
state = LampSolidOff;
break;
case LAMP_DIM:
state = LampSolidDim;
break;
case LAMP_BRIGHT:
state = LampSolidBright;
break;
case LAMP_FLASH:
state = solid + flashMed + state2Bright;
break;
default:
state = LampSolidOff;
break;
}
return SetLamp (b, state);
}
void CRIOMAIN::ButtonEvent(BYTE state, BYTE index)
{
if ((index < 0) || (MAXBUTTON_TABLE <= index)) {
return;
}
if (g_StartGame)
AnalogButton(state, index);
// Is Biginner mode -> disable key
switch (index)
{
//case 16: // Jump Jets
//case 33: // Jump Jets
//case 34: // Jump Jets
case 31: // Eject
case 61: // Eject
case 20: // Crouch
case 17: // ShutDown
case 25: // radar Mode
case 26: // light amp
if (g_nInputMode == _BIGINNER_MODE) {
return;
} else {
break;
}
case 30:
case 56:
if (g_bCOOP && (state == rio_ButtonPressed)) {
extern void _stdcall PlayCoinSound(int nSound);
g_nCoinCount++;
PlayCoinSound(0);
}
break;
default:
break;
}
if (!g_StartGame) {
#if 0 // def _DEBUG
if (state == rio_ButtonPressed) {
int n = GetLampState(index);
if (n < LAMP_FLASH) {
if (n <= LAMP_OFF)
n = LAMP_DIM;
else
n++;
} else {
n = LAMP_OFF;
}
//LAMP_OFF, LAMP_DIM, LAMP_BRIGHT, LAMP_FLASH
SetLampState(index, n);
}
#endif // _DEBUG
return;
}
int norm_key = CBUTTON_GROUP::s_aButtonTable[index].norm_key;
if (norm_key < 0)
return;
int mod_key = CBUTTON_GROUP::s_aButtonTable[index].mod_key;
if (mod_key < 0)
return;
switch (state)
{
case rio_ButtonPressed:
if (mod_key > 0) {
SendMessage (g_hWnd, WM_KEYDOWN, mod_key, 0);
}
SendMessage (g_hWnd, WM_KEYDOWN, norm_key, 0);
break;
case rio_ButtonReleased:
SendMessage (g_hWnd, WM_KEYUP, norm_key, 0);
if (mod_key > 0) {
SendMessage (g_hWnd, WM_KEYUP, mod_key, 0);
}
break;
default:
break;
}
#if defined(_DEBUG) && 0 // watcom
static char s_szStr[256];
sprintf (s_szStr, "Key:[%d]\n",index);
::OutputDebugString(s_szStr);
#endif // watcom
}
void CRIOMAIN::AnalogButton(const BYTE state, const BYTE index)
{
NetMissionParameters::MWNetMissionParameters *params;
if (MWApplication::GetInstance()->serverFlag)
params = MWApplication::GetInstance()->GetLocalNetParams();
else
params = MWApplication::GetInstance()->GetServerNetParams();
m_HeatMode = params->m_heatOn;
int m_AmmoMode = params->m_ammobayfireOn;
int m_WeaponJamMode = params->m_weaponjamOn;
if (state == rio_ButtonPressed)
{
switch(index) {
case 29:
if (VehGetShutdownState() == 0) {
if (g_nProgramMode) {
if (g_nInputMode < _EXPERT_MODE) {
g_nInputMode++;
} else {
g_nInputMode = _BIGINNER_MODE;
}
SetLampState (29, LAMP_BRIGHT);
}
} else {
#if 0 // def _DEBUG
switch(VehGetShutdownState()) {
case -3:
SetLampState (29, flashFast | state1Bright | state2Off);
break;
case -2:
SetLampState (29, flashSlow | state1Dim | state2Off);
break;
case -1:
SetLampState (29, state1Dim | state2Dim);
break;
case +1:
SetLampState (29, state1Dim | state2Bright);
break;
}
#endif // _DEBUG
}
break;
// case 39:
// {
// SetLampState (39, LAMP_BRIGHT);
// SendMessage (HWND_BROADCAST, WM_KEYDOWN, 'T', 0);
// }
// break;
case 48:
if (g_LightAmp == TRUE)
{
if ((g_bJumpMode == true) && (GetLampState(33) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'J', 0);
if ((g_bFlushMode == true) && (GetLampState(19) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'F', 0);
s_aButtonTable[69].norm_key = 'A';
s_aButtonTable[69].mod_key = SYSKEY_NULL;
SetLampState (48, LAMP_BRIGHT);
g_bZoomMode = false;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = true;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
break;
case 49:
if ((g_bJumpMode == true) && (GetLampState(33) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'J', 0);
if (m_HeatMode)
{
s_aButtonTable[69].norm_key = 'F';
s_aButtonTable[69].mod_key = SYSKEY_NULL;
SetLampState (49, LAMP_BRIGHT);
SetLampState (1, LAMP_BRIGHT);
g_bZoomMode = false;
g_bJumpMode = false;
g_bFlushMode = true;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
else
{
g_bFlushMode = false;
SetLampState (49, LAMP_OFF);
SetLampState (19, LAMP_OFF);
}
break;
case 50:
if ((g_bFlushMode == true) && (GetLampState(19) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'F', 0);
SetLampState (50, LAMP_BRIGHT);
if (VehGetJumpJetState() > 0)
{
g_bJumpZoom = false; // Secondary button 16 set to Zoom
s_aButtonTable[69].norm_key = 'J';
s_aButtonTable[16].norm_key = VK_NUMPAD0;
s_aButtonTable[69].mod_key = SYSKEY_NULL;
g_bZoomMode = false;
g_bJumpMode = true;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
else
{
g_bJumpZoom = false; // Secondary button 16 set to Zoom
s_aButtonTable[16].norm_key = VK_NUMPAD0;
s_aButtonTable[69].mod_key = SYSKEY_NULL;
}
break;
case 51:
if ((g_bJumpMode == true) && (GetLampState(33) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'J', 0);
if ((g_bFlushMode == true) && (GetLampState(19) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'F', 0);
SetLampState (51, LAMP_BRIGHT);
if (VehGetJumpJetState() > 0)
{
g_bJumpZoom = true; // Secondary button 16 set to Jump
s_aButtonTable[69].norm_key = VK_NUMPAD0;
s_aButtonTable[16].norm_key = 'J';
s_aButtonTable[69].mod_key = SYSKEY_NULL;
g_bZoomMode = true;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
else
{
g_bJumpZoom = false; // Secondary button 16 set to Zoom
s_aButtonTable[69].norm_key = VK_NUMPAD0;
s_aButtonTable[16].norm_key = VK_NUMPAD0;
s_aButtonTable[69].mod_key = SYSKEY_NULL;
g_bZoomMode = true;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = false;
}
break;
case 53: // Crosshair Target
{
if ((g_bJumpMode == true) && (GetLampState(33) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'J', 0);
if ((g_bFlushMode == true) && (GetLampState(19) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'F', 0);
s_aButtonTable[69].norm_key = 'Q';
s_aButtonTable[69].mod_key = SYSKEY_NULL;
SetLampState (53, LAMP_BRIGHT);
g_bZoomMode = false;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = false;
g_bCrossTargetMode = true;
}
break;
case 54: // Next Target
{
if ((g_bJumpMode == true) && (GetLampState(33) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'J', 0);
if ((g_bFlushMode == true) && (GetLampState(19) == LAMP_BRIGHT))
SendMessage (g_hWnd, WM_KEYUP, 'F', 0);
s_aButtonTable[69].norm_key = 'E';
s_aButtonTable[69].mod_key = SYSKEY_SHFT;
SetLampState (54, LAMP_BRIGHT);
g_bZoomMode = false;
g_bJumpMode = false;
g_bFlushMode = false;
g_bLightAmpMode = false;
g_bNextTargetMode = true;
g_bCrossTargetMode = false;
}
break;
// MSL 5.03 Secondary Damage Display
case 18:
g_nAuxilMode++;
if (g_nAuxilMode > 2)
{
g_nAuxilMode = 0;
}
SetLampState (18, LAMP_BRIGHT);
break;
case 21:
if (VehGetShutdownState() == 0) {
g_nProgramMode = TRUE;
SetLampState (21, LAMP_BRIGHT);
} else {
#if 0 // def _DEBUG
switch(VehGetShutdownState()) {
case -3:
SetLampState (29, flashFast | state1Bright | state2Off);
break;
case -2:
SetLampState (29, flashSlow | state1Dim | state2Off);
break;
case -1:
SetLampState (29, state1Dim | state2Dim);
break;
case +1:
SetLampState (29, state1Dim | state2Bright);
break;
}
#endif // _DEBUG
}
break;
// MSL 5.03 Dump Ammo
case 32:
g_nAmmoDump2 = TRUE;
SetLampState (32, LAMP_BRIGHT);
break;
// MSL 5.03 Dump Ammo
case 35:
g_nAmmoDump1 = TRUE;
SetLampState (35, LAMP_BRIGHT);
break;
case 0:
g_nAssignGroup3 = TRUE;
break;
case 1:
g_nAssignGroup2 = TRUE;
break;
case 2:
g_nAssignGroup1 = TRUE;
break;
case 3:
g_nFiringMode = TRUE;
SetLampState (3, LAMP_BRIGHT);
break;
case 4:
g_nPrevWeapon = TRUE;
break;
case 5:
g_nNextWeapon = TRUE;
break;
case 6: // Chainfire Mode
MechWarrior4::g_baChainFireMode[0] = MechWarrior4::g_baChainFireMode[1] = MechWarrior4::g_baChainFireMode[2] = TRUE;
SetLampState(6, LAMP_BRIGHT);
break;
case 7: // Groupfire Mode
MechWarrior4::g_baChainFireMode[0] = MechWarrior4::g_baChainFireMode[1] = MechWarrior4::g_baChainFireMode[2] = FALSE;
SetLampState(7, LAMP_BRIGHT);
break;
case 63: // Throttle Back
g_ThrottleResult = 1L;
break;
case 65: // Hat_Down
g_HatResult = 18000L;
break;
case 66: // Hat_Up
g_HatResult = 0L;
break;
case 67: // Hat_right
g_HatResult = 9000L;
break;
case 68: // Hat_left
g_HatResult = 27000L;
break;
}
}
else if (state == rio_ButtonReleased)
{
switch(index)
{
case 29:
SetLampState (29, LAMP_DEFAULT);
break;
// case 39:
// {
// SetLampState (39, LAMP_DEFAULT);
// SendMessage (HWND_BROADCAST, WM_KEYUP, 'T', 0);
// }
// break;
case 48:
if (g_LightAmp == TRUE)
SetLampState (48, LAMP_DEFAULT);
break;
case 49:
if (m_HeatMode)
SetLampState (49, LAMP_DEFAULT);
else
SetLampState (49, LAMP_OFF);
break;
case 50:
if (VehGetJumpJetState() > 0)
{
SetLampState (50, LAMP_DEFAULT);
}
else
{
SetLampState (50, LAMP_OFF);
}
break;
case 51:
SetLampState (51, LAMP_DEFAULT);
break;
case 53:
SetLampState (53, LAMP_DEFAULT);
break;
case 54:
SetLampState (54, LAMP_DEFAULT);
break;
// MSL 5.03 Secondary Damage Display
case 18:
SetLampState (18, LAMP_DEFAULT);
break;
case 21:
g_nProgramMode = FALSE;
SetLampState (21, LAMP_DEFAULT);
break;
// MSL 5.03 Dump Ammo
case 32:
g_nAmmoDump2 = FALSE;
SetLampState (32, LAMP_DEFAULT);
break;
// MSL 5.03 Dump Ammo
case 35:
g_nAmmoDump1 = FALSE;
SetLampState (35, LAMP_DEFAULT);
break;
case 3:
g_nFiringMode = FALSE;
SetLampState (3, LAMP_DEFAULT);
break;
case 6: // Chainfire Mode
SetLampState(6, LAMP_DEFAULT);
break;
case 7: // Groupfire Mode
SetLampState(7, LAMP_DEFAULT);
break;
case 63:
g_ThrottleResult = -1L;
break;
case 65: // Hat_Down
case 66: // Hat_Up
case 67: // Hat_right
case 68: // Hat_left
g_HatResult = -1L; // Hat_center
break;
default:
break;
}
}
}
void CRIOMAIN::UpdateAnalog (DIJOYSTATE &js)
{
#if 0
if (!g_StartGame) {
if (!g_bCOOP) {
// Analog Values Could be Updated & Used in Menu State(GOSScript)
return;
}
}
#endif
g_lpPadalMode = NULL;
g_lpJoystickXMode = NULL;
switch (g_nInputMode)
{
default: // case _BIGINNER_MODE:
g_lpJoystickXMode = &js.lX;
g_lpPadalMode = NULL;
break;
case _VETERAN_MODE:
g_lpJoystickXMode = &js.lX;
g_lpPadalMode = &js.lRz;
break;
case _EXPERT_MODE:
g_lpJoystickXMode = &js.lRz;
g_lpPadalMode = &js.lX;
break;
}
//if (!g_StartGame && g_bCOOP) {
s_RIO.GetJoyButtons(js.rgbButtons);
/*} else {
js.rgbButtons[0] = 0;
js.rgbButtons[1] = 0;
js.rgbButtons[2] = 0;
js.rgbButtons[3] = 0;
}*/
UpdateHat (js);
UpdatePadal (js);
UpdateThrottle (js);
//UpdateJoystickX (js);
//UpdateJoystickY (js);
UpdateJoystick (js);
}
void CRIOMAIN::UpdateHat (DIJOYSTATE &js)
{
js.rgdwPOV[0] = g_HatResult;
}
void CRIOMAIN::UpdatePadal (DIJOYSTATE &js)
{
#define RANGE_PADAL 500L
#define DEADZONE_PADAL 10L
/*
== PADAL ==
Up : (-)
Down : (+)
------------------
Set Start Position
------------------
Down Up
======================
← (+) (-) →
======================
g_LeftPedalStart: INT_MAX (+)
lP = (LONG)g_LeftPedalStart - g_LeftPedal;
lP 결과값은 무조건 음수
*/
LONG lP = 0;
//
// LEFT PADAL
//
if ((g_LeftPedal < -RANGE_PADAL) || (g_LeftPedal > RANGE_PADAL))
{
// error!
//::OutputDebugString ("!!!!! LEFT PEDAL ERROR !!!!!\n");
if (g_LeftPedal > RANGE_PADAL) {
g_LeftPedalLast = -1000L;
} else {
g_LeftPedalLast = 0L;
}
}
else
{
if (g_LeftPedalStart > g_LeftPedal) {
g_LeftPedalStart = g_LeftPedal;
}
lP = (LONG)g_LeftPedalStart - g_LeftPedal;
if (lP != 0) {
lP = lP * 1000 / RANGE_PADAL;
}
// Dead Zone
if (abs(lP) < DEADZONE_PADAL) {
lP = 0;
}
g_LeftPedalLast = lP;
}
//
// RIGHT PADAL
//
lP = 0;
if ((g_RightPedal < -RANGE_PADAL) || (g_RightPedal > RANGE_PADAL))
{
// error!
//::OutputDebugString ("!!!!! RIGHT PEDAL ERROR !!!!!\n");
if (g_RightPedal > RANGE_PADAL) {
g_RightPedalLast = 1000L;
} else {
g_RightPedalLast = 0L;
}
}
else
{
if (g_RightPedalStart > g_RightPedal) {
g_RightPedalStart = g_RightPedal;
}
lP = (LONG)g_RightPedalStart - g_RightPedal;
if (lP != 0) {
lP = lP * 1000 / RANGE_PADAL;
}
// Dead Zone
if (abs(lP) < DEADZONE_PADAL) {
lP = 0;
}
g_RightPedalLast = -lP;
}
// Update Analog
if (g_lpPadalMode)
{
if (abs(g_LeftPedalLast) > 0 && abs(g_RightPedalLast) > 0) { // Left + Right
*g_lpPadalMode = g_RightPedalLast + g_LeftPedalLast;
} else if (abs(g_LeftPedalLast) > 0) { // Only Left
*g_lpPadalMode = g_LeftPedalLast;
} else if (abs(g_RightPedalLast) > 0) { // Only Right
*g_lpPadalMode = g_RightPedalLast;
}
}
#if defined(_DEBUG) && 0 // watcom
static char s_szStr[256];
sprintf (s_szStr, "LEFT: RIO (%ld), START (%ld), LAST (%ld) \n",
g_LeftPedal, g_LeftPedalStart, g_LeftPedalLast);
::OutputDebugString(s_szStr);
sprintf (s_szStr, "RIGHT: RIO (%ld), START (%ld), LAST (%ld) \n",
g_RightPedal, g_RightPedalStart, g_RightPedalLast);
::OutputDebugString(s_szStr);
#endif // watcom
}
void CRIOMAIN::UpdateThrottle (DIJOYSTATE &js)
{
// [[RIO button value range]]
// RIO board spec: (up) -800 ~ +800 (down)
// actually maximum throttle-value-range is 800, not 1600(-800 ~ 800)
// possible throttle value (g_ThrottleMax ~ (g_ThrottleMax - 800))
// g_ThrottleMax will be changedfrom input value...
//
// g_Throttle/g_ThrottleMax
#define RANGE_THROTTLE 800L
// [[joy button value range - (0 ~ 1000 <- we use this, one way throttle) or (-1000 ~ +1000)]]
// g_ThrottleLast
// -rbjump // dead zone (200-10 ---- 200+15)
#define ZERO_THROTTLE 600L // see,,, control_mapping.cpp, 0.3
// CRIOMain will return MW4 as -1000 - +1000
// & MW4 will convert that value 0.0 = +1.0
// so around 0.3(from bithrottlecenter-bithrottlelow to bithrottlecenter+bithrottlehigh) will be dead-zone
// active low zone is from 0.0 to (bithrottlecenter-bithrottlelow)
// active high zone is from (bithrottlecenter+bithrottlelow) to 1.0
// so 0.3 is same 600
//#define DEAD_THROTTLE 50L // see,,, control_mapping.cpp, 0.025
#define DEADZONE_THROTTLE 50L
/*
== THROTTLE ==
Up : (-)
Down : (+)
------------------
Set Start Position
------------------
Up Down
======================
← (-) (+) →
======================
g_ThrottleStart: INT_MIN (-)
*/
LONG lT;
if ((g_Throttle < -RANGE_THROTTLE) || (g_Throttle > RANGE_THROTTLE))
{
// error
if (g_Throttle < RANGE_THROTTLE) {
if (g_ThrottleResult > 0L) { // back
g_ThrottleLast = 1000L;
} else {
g_ThrottleLast = -1000L;
}
} else {
g_ThrottleLast = 600L;
}
}
else
{
// Set StartPosition
if (g_ThrottleStart < g_Throttle)
g_ThrottleStart = g_Throttle;
lT = (LONG)g_ThrottleStart - g_Throttle;
if (lT > 800L)
lT = 800L;
if (lT != 0) {
lT = lT * 1000L / 800L;
if ((lT > -DEADZONE_THROTTLE) && (lT < DEADZONE_THROTTLE)) {
g_ThrottleLast = ZERO_THROTTLE;
} else {
if (g_ThrottleResult > 0L) { // back
g_ThrottleLast = 900L + (lT * g_ThrottleResult * 0.1L);
} else { // front
g_ThrottleLast = lT * g_ThrottleResult;
}
}
}
}
js.rglSlider[0] = g_ThrottleLast;
#if defined(_DEBUG) && 0 // watcom
static char s_szStr[256];
sprintf (s_szStr, "THROTTLE: RIO (%ld), START (%ld), LAST (%ld) \n",
g_Throttle, g_ThrottleStart, g_ThrottleLast);
::OutputDebugString(s_szStr);
#endif // watcom
}
void CRIOMAIN::UpdateJoystick (DIJOYSTATE &js)
{
/*
#define DEADZONE_JOYSTICKX 20L
#define DEADZONE_JOYSTICKY 20L
LONG lJ;
lJ = -g_JoystickX;
if (lJ > 0) {
lJ -= DEADZONE_JOYSTICKX;
} else if (lJ < 0) {
lJ += DEADZONE_JOYSTICKX;
}
if ((g_JoystickX > DEADZONE_JOYSTICKX) || (g_JoystickX < -DEADZONE_JOYSTICKX)) {
g_JoystickXLast = lJ * 12.5L;
if (g_JoystickXLast < -1000L) {
g_JoystickXLast = -1000L;
} else if (g_JoystickXLast > 1000L) {
g_JoystickXLast = 1000L;
}
} else {
g_JoystickXLast = 0L;
}
*/
//////////////////////////////////////////////////////////////////////////////////
/*
80 의 의미
RIO (LEFT :120 ~ RIGHT :-80) 까지의 수를 돌려준다고 가정하고
(LEFT의경우) RIGHT 의 최대값 80 이상인 값을 잘라버리고 나머지는
버릴경우 LEFT 와 RIGHT가 동일한 속도로 움직일수 있다
*/
//////////////////////////////////////////////////////////////////////////////////
LONG lJ;
// MSL 5.03 Joystick Deadzone
//#define DEADZONE_JOYSTICKX_LEFT 10L
//#define DEADZONE_JOYSTICKX_RIGHT 10L
#define DEADZONE_JOYSTICKX_LEFT 5L
#define DEADZONE_JOYSTICKX_RIGHT 5L
static const LONG sLeftRate = (LONG)((1000L) / (LONG)(80L - DEADZONE_JOYSTICKX_LEFT));
static const LONG sRightRate = (LONG)((1000L) / (LONG)(80L - DEADZONE_JOYSTICKX_RIGHT));
lJ = g_JoystickX;
if (lJ < 0) // LEFT
{
lJ += DEADZONE_JOYSTICKX_LEFT;
if ((lJ < 0)) {
if (lJ < (-80 + DEADZONE_JOYSTICKX_LEFT))
lJ = (-80 + DEADZONE_JOYSTICKX_LEFT);
g_JoystickXLast = lJ * sLeftRate;
} else {
g_JoystickXLast = 0L;
}
}
else if (lJ > 0) // RIGHT
{
lJ -= DEADZONE_JOYSTICKX_RIGHT;
if (lJ > 0) {
if (lJ > (80 - DEADZONE_JOYSTICKX_RIGHT))
lJ = (80 - DEADZONE_JOYSTICKX_RIGHT);
g_JoystickXLast = lJ * sRightRate;
} else {
g_JoystickXLast = 0L;
}
}
if (g_JoystickXLast < -1000L)
{
g_JoystickXLast = -1000L;
}
else if (g_JoystickXLast > 1000L)
{
g_JoystickXLast = 1000L;
}
g_JoystickXLast = -g_JoystickXLast;
if (g_lpJoystickXMode)
{
*g_lpJoystickXMode = g_JoystickXLast;
}
#if 0 // def _DEBUG
extern char DisplayInfoText[128];
extern DWORD EndDisplayInfoTime;
extern DWORD EnableDisplayInfo;
if( EnableDisplayInfo==0 ) {
disp:
sprintf(DisplayInfoText, "X(%ld) L(%ld)", g_JoystickX, g_JoystickXLast);
EnableDisplayInfo = 1;
} else if (EnableDisplayInfo==2) {
if( timeGetTime() < EndDisplayInfoTime+50 ) {
} else {
goto disp;
}
} else {
}
#endif // _DEBUG
/////////////////////////
/////////////////////////
/////////////////////////
// MSL 5.03 Joystick Deadzone
//#define DEADZONE_JOYSTICKY_UP 10L
//#define DEADZONE_JOYSTICKY_DOWN 10L
#define DEADZONE_JOYSTICKY_UP 5L
#define DEADZONE_JOYSTICKY_DOWN 5L
static const LONG sUpRate = (LONG)((1000L) / (LONG)(80L - DEADZONE_JOYSTICKY_UP));
static const LONG sDownRate = (LONG)((1000L) / (LONG)(80L - DEADZONE_JOYSTICKY_DOWN));
lJ = g_JoystickY;
if (lJ < 0) // UP
{
lJ += DEADZONE_JOYSTICKY_UP;
if ((lJ < 0)) {
if (lJ < (-80 + DEADZONE_JOYSTICKY_UP))
lJ = (-80 + DEADZONE_JOYSTICKY_UP);
g_JoystickYLast = lJ * sUpRate;
} else {
g_JoystickYLast = 0L;
}
}
else if (lJ > 0) // Down
{
lJ -= DEADZONE_JOYSTICKY_DOWN;
if (lJ > 0) {
if (lJ > (80 - DEADZONE_JOYSTICKY_DOWN))
lJ = (80 - DEADZONE_JOYSTICKY_DOWN);
g_JoystickYLast = lJ * sDownRate;
} else {
g_JoystickYLast = 0L;
}
}
if (g_JoystickYLast < -1000L)
{
g_JoystickYLast = -1000L;
}
else if (g_JoystickYLast > 1000L)
{
g_JoystickYLast = 1000L;
}
/*
if (lJ > 0) {
lJ -= DEADZONE_JOYSTICKY;
} else if (lJ < 0) {
lJ += DEADZONE_JOYSTICKY;
}
if ((g_JoystickY > DEADZONE_JOYSTICKY) || (g_JoystickY < -DEADZONE_JOYSTICKY)) {
if (lJ < 0) { // Up
g_JoystickYLast = lJ * 15.0L;
} else if (lJ > 0) { // Down
g_JoystickYLast = lJ * 12.5L;
}
if (g_JoystickYLast < -1000L) {
g_JoystickYLast = -1000L;
} else if (g_JoystickYLast > 1000L) {
g_JoystickYLast = 1000L;
}
} else {
g_JoystickYLast = 0L;
}
*/
js.lY = g_JoystickYLast;
#if defined(_DEBUG) && 0 // watcom
static char s_szStr[256];
sprintf (s_szStr, "@JOY_Y@ RIO (%ld), LAST (%ld) \n",
g_JoystickY, g_JoystickYLast);
::OutputDebugString(s_szStr);
sprintf (s_szStr, "@JOY_X@ RIO (%ld), LAST (%ld) \n",
g_JoystickX, g_JoystickXLast);
::OutputDebugString(s_szStr);
#endif // watcom
}
void CRIOMAIN::Redf_ThrottleMessageHandler (VehicleInterface& vh, BYTE btnIndex, int data)
{
if (data > 0) {
g_naButtonThrottles[btnIndex] = 1;
//
} else {
if (g_naButtonThrottles[btnIndex] <= 0) {
return;
}
g_naButtonThrottles[btnIndex] = 0;
}
BYTE button = 47 - btnIndex; // 0 - 47, 1 - 46, 2 - 45...
if (vh.GetShutdownState())
return;
// m_bFreeForAll, g_nTeamOrderMode, g_TeamOrderCount, g_TeamOrderOthers, g_fLastStartTime
SetTeamOrderButtons(true);
BYTE& bButtonValue = s_aCtrlLamp[button];
if (bButtonValue != LAMP_OFF) {
if (data > 0)
{
SetLampState (button, LAMP_BRIGHT);
}
else
{
SetLampState (button, LAMP_DEFAULT);
DoTeamOrderButton(vh, button);
}
}
}
void CRIOMAIN::DoTeamOrderButton(VehicleInterface& vh, int button)
{
switch(g_nTeamOrderMode) {
case FREEFORALL_MODE:
g_nTeamOrderSelect = button;
g_TeamOrderCountSave = g_TeamOrderCount;
g_TeamOrderOthersSave = g_TeamOrderOthers;
DoSaveMechInfos(&g_aSavedMechInfos[0], &g_aMechInfos[0], 1 + g_TeamOrderCount + g_TeamOrderOthers);
g_nTeamOrderMode = TEAM_MESSAGE2;
break;
case TEAM_MODE:
g_nTeamOrderSelect = button;
g_TeamOrderCountSave = g_TeamOrderCount;
g_TeamOrderOthersSave = g_TeamOrderOthers;
DoSaveMechInfos(&g_aSavedMechInfos[0], &g_aMechInfos[0], 1 + g_TeamOrderCount + g_TeamOrderOthers);
if ((40 <= button) && (button <= 41)) {
if (!g_pCurTOC) {
break;
}
// Affirmative or negative
MWApplication *app = MWApplication::GetInstance();
const ServedConnectionData& scd = app->servedConnectionData[g_pCurTOC->m_nFrom];
if (scd.clientConnected && scd.clientLoaded) {
MWPlayer* plyr = scd.clientPlayer;
if (plyr) {
Vehicle* pv = plyr->GetVehicle();
if (pv && (pv->GetClassID() == MechClassID)) {
DynamicMemoryStream stream;
int nMsgIndex = (button == 41) ? 14: 15; // yes: no
if (!app->serverFlag) {
stream.WriteBytes(&g_pCurTOC->m_nFrom, 1); // to
}
stream.WriteBytes(&g_aSavedMechInfos[0].connectionID, 1); // from...
stream.WriteBytes(&nMsgIndex, 1);
stream.WriteByteAlign();
stream.Rewind();
if (app->serverFlag) {
Network::GetInstance()->SendNetMessage(g_pCurTOC->m_nFrom, MWApplication::RepTeamOrderMessageID, &stream, true);
} else {
Network::GetInstance()->SendNetMessage(Connection::Server->GetID(), MWApplication::svrRepTeamOrderMessageID, &stream, true);
}
}
}
}
app->EndTOC();
if (button == 40) {
// negative - restore last selection
if (g_LastTarget != ReplicatorID::Null) {
Connection *connection = Network::GetInstance()->GetConnection(g_LastTarget.connectionID);
if (connection != NULL) {
Check_Object(connection);
Entity * target_entity = (Entity *)connection->FindReplicator(g_LastTarget);
if (target_entity) {
vh.SetGUITarget(target_entity);
}
}
g_LastTarget = ReplicatorID::Null;
}
}
} else if ((44 <= button) && (button <= 47))
// Do Team Message
g_nTeamOrderMode = TEAM_MESSAGE1;
else {
// Do non-Team Message
g_nTeamOrderMode = TEAM_MESSAGE2;
}
break;
default: // case TEAM_MESSAGE1, TEAM_MESSAGE2:
if (40 != button) {
int nMsgIndex;
nMsgIndex = 47 - button; // 47 - 0, 46 - 1 ... 41-6
if (g_nTeamOrderMode == TEAM_MESSAGE2) {
nMsgIndex += 7;
}
int nMIStart, nMIs;
SMechInfo aMIs[16];
nMIs = g_TeamOrderCountSave;
nMIStart = 1;
if (m_bFreeForAll) {
if (g_nTeamOrderSelect != 40) {
nMIs = 1;
nMIStart = 1 + (47 - g_nTeamOrderSelect); // 47 - 1, 46 - 2...
}
} else {
// team mode
switch(g_nTeamOrderSelect) {
case 47: // team all
nMIs = g_TeamOrderCountSave;
nMIStart = 1;
break;
case 46: // team mate 1
case 45: // team mate 2
case 44: // team mate 3
nMIs = 1;
nMIStart = 47 - g_nTeamOrderSelect; // 46 - 1, 45 - 2, 44 - 3
break;
case 43: // all
nMIs = g_TeamOrderCountSave + g_TeamOrderOthersSave;
nMIStart = 1;
break;
case 42: // all others...
nMIs = g_TeamOrderOthersSave;
nMIStart = 1 + g_TeamOrderCountSave;
break;
}
}
memcpy(aMIs, &g_aSavedMechInfos[nMIStart], sizeof(g_aSavedMechInfos[0]) * nMIs);
if (m_bFreeForAll)
g_nTeamOrderMode = FREEFORALL_MODE;
else
g_nTeamOrderMode = TEAM_MODE;
Entity* target_entity = NULL;
if ((nMsgIndex == 0) || (nMsgIndex == 1)) {
// attack|defend my target
target_entity = vh.m_interfaceTarget.GetCurrent();
if (!target_entity) {
// no target...
return;
}
}
int i;
MWApplication *app = MWApplication::GetInstance();
Network* pNet = Network::GetInstance();
bool b1stBOT = true;
for(i = 0; i < nMIs; i++) {
if (target_entity) {
if (target_entity->GetReplicatorID() == aMIs[i])
continue;
}
DynamicMemoryStream stream;
if (aMIs[i].m_bBOT) { // always to server directly...
if (b1stBOT && ((nMsgIndex == 0) || (nMsgIndex == 1) || (nMsgIndex == 2) || (nMsgIndex == 6))) {
b1stBOT = false;
int nBot, nBOTs = 0;
for(nBot = i; nBot < nMIs; nBot++) {
if (aMIs[nBot].m_bBOT) {
if (target_entity) {
if (target_entity->GetReplicatorID() == aMIs[nBot])
continue;
}
nBOTs++;
}
}
if (nBOTs <= 0)
continue;
stream.WriteBytes(&nBOTs, 1);
// no meanning... stream.WriteBytes(&g_aSavedMechInfos[0].connectionID, 1); // from...
stream.WriteBytes(&nMsgIndex, 1);
for(nBot = i; nBot < nMIs; nBot++) {
if (aMIs[nBot].m_bBOT) {
if (target_entity) {
if (target_entity->GetReplicatorID() == aMIs[nBot])
continue;
}
stream.WriteBytes(&aMIs[nBot].localID, 2);
}
}
} else {
b1stBOT = false;
continue;
}
} else {
if (!app->serverFlag) { // to server directly...
// redirected part
int nBOTs = 0;
stream.WriteBytes(&nBOTs, 1);
stream.WriteBytes(&aMIs[i].connectionID, 1); // to
}
// real part
stream.WriteBytes(&g_aSavedMechInfos[0].connectionID, 1); // from...
stream.WriteBytes(&nMsgIndex, 1);
}
if ((nMsgIndex == 0) || (nMsgIndex == 1)) {
// attack|defend my target
ReplicatorID id = target_entity->GetReplicatorID();
stream.WriteBytes(&id.connectionID, 1);
stream.WriteBytes(&id.localID, 2);
}
stream.WriteByteAlign();
stream.Rewind();
//pNet->netStatCollector[Network::OutgoingSystemMessageBitSizeStat].AddToStatistic(aMIs[i].connectionID,stream.GetBufferBytesUsed()*8);
if (app->serverFlag && !aMIs[i].m_bBOT) {
pNet->SendNetMessage(aMIs[i].connectionID, MWApplication::TeamOrderMessageID, &stream, true);
} else {
pNet->SendNetMessage(Connection::Server->GetID(), MWApplication::svrTeamOrderMessageID, &stream, true);
//if (app->serverFlag && aMIs[i].m_bBOT) {
//}
}
}
} else {
// exit - do nothing
if (m_bFreeForAll)
g_nTeamOrderMode = FREEFORALL_MODE;
else
g_nTeamOrderMode = TEAM_MODE;
}
break;
}
}
void CRIOMAIN::SetTeamOrderButtons(bool bForce/* = false*/)
{
if (!hsh_initialized || bForce) {
if (g_nTeamOrderMode == TEAM_MODE) {
g_TeamOrderCount=MWApplication::GetInstance()->GetMechInfos(0, g_aMechInfos, g_TeamOrderOthers) - 1;
} else if(g_nTeamOrderMode == FREEFORALL_MODE) {
g_TeamOrderCount=MWApplication::GetInstance()->GetMechInfos(2, g_aMechInfos, g_TeamOrderOthers) - 1;
}
}
if (VehGetShutdownState()) {
BYTE kkkkk;
for(kkkkk = 40; kkkkk < 48; kkkkk++) {
SetLampState (kkkkk, LAMP_OFF);
}
return;
}
int i;
int TeamOrderCount = g_TeamOrderCount;
switch(g_nTeamOrderMode) {
case FREEFORALL_MODE:
if (TeamOrderCount > 7)
TeamOrderCount = 7;
// all
if (TeamOrderCount) {
if (IsLampOFF(40)) {
SetLampState (40, LAMP_DEFAULT);
}
} else {
if (!IsLampOFF(40)) {
SetLampState(40, LAMP_OFF);
}
}
// each player
for(i = 41; i <= 47; i++) {
if (i <= 47 - TeamOrderCount)
{
if (!IsLampOFF(i)) {
SetLampState (i, LAMP_OFF);
}
}
else
{
if (IsLampOFF(i)) {
SetLampState (i, LAMP_DEFAULT);
}
}
}
break;
case TEAM_MODE:
if (TeamOrderCount > 3)
TeamOrderCount = 3;
// team all
if (TeamOrderCount) {
if (IsLampOFF(47)) {
SetLampState (47, LAMP_DEFAULT);
}
} else {
if (!IsLampOFF(47)) {
SetLampState(47, LAMP_OFF);
}
}
// each team player
for(i = 44; i <= 46; i++) {
if (i <= 46 - TeamOrderCount)
{
if (!IsLampOFF(i)) {
SetLampState (i, LAMP_OFF);
}
}
else
{
if (IsLampOFF(i)) {
SetLampState (i, LAMP_DEFAULT);
}
}
}
// all
if (TeamOrderCount || g_TeamOrderOthers) {
if (IsLampOFF(43)) {
SetLampState (43, LAMP_DEFAULT);
}
} else {
if (!IsLampOFF(43)) {
SetLampState(43, LAMP_OFF);
}
}
// all others...
if (g_TeamOrderOthers) {
if (IsLampOFF(42)) {
SetLampState (42, LAMP_DEFAULT);
}
} else {
if (!IsLampOFF(42)) {
SetLampState(42, LAMP_OFF);
}
}
// Affirmative or negative
if (g_pCurTOC)
{
Scalar fT = gos_GetElapsedTime();
if ((fT - g_fLastStartTime) > AUTO_DENY_TIME) {
g_fLastStartTime = 0.0f;
MWApplication::GetInstance()->EndTOC(true);
// negative - restore last selection
if (g_LastTarget != ReplicatorID::Null) {
Connection *connection = Network::GetInstance()->GetConnection(g_LastTarget.connectionID);
if (connection != NULL) {
Check_Object(connection);
Entity * target_entity = (Entity *)connection->FindReplicator(g_LastTarget);
if (target_entity) {
VehicleInterface::GetInstance()->SetGUITarget(target_entity);
}
}
g_LastTarget = ReplicatorID::Null;
}
goto auto_deny;
}
if (IsLampOFF (40))
SetLampState (40, LAMP_DEFAULT);
if (IsLampOFF (41))
SetLampState (41, LAMP_DEFAULT);
} else {
auto_deny:
if (!IsLampOFF (40))
SetLampState (40, LAMP_OFF);
if (!IsLampOFF (41))
SetLampState (41, LAMP_OFF);
}
break;
default: // case TEAM_MESSAGE1, TEAM_MESSAGE2:
for(i = 40; i <= 47; i++) {
if (IsLampOFF (i)) {
SetLampState ((BYTE)i, LAMP_DEFAULT);
}
}
break;
}
}
void CPlasma::SendPacket (const BYTE* pbPacket, char nLen)
{
if (IsValid())
txComLoop (pbPacket, nLen);
}
void CPlasma::PlasmaClear ()
{
char string[] = { ESC, '@'};
SendPacket ((BYTE*)string, 2);
}
void CPlasma::PlasmaCursor (char n)
{
char string[] = { ESC, 'G', char (n) };
SendPacket ((BYTE*)string, 3);
}
void CPlasma::PlasmaCursorHome ()
{
char string[] = { ESC, 'L'};
SendPacket ((BYTE*)string, 2);
}
void CPlasma::PlasmaCursorX (char n)
{
char string[] = { ESC, 'R', n};
SendPacket ((BYTE*)string, 3);
}
void CPlasma::PlasmaCursorY (char n)
{
char string[] = { ESC, 'Q', n};
SendPacket ((BYTE*)string, 3);
}
void CPlasma::PlasmaFontAttr (char n)
{
char string[] = { ESC, 'H', (BYTE)n };
SendPacket ((BYTE*)string, 3);
}
void CPlasma::PlasmaFont (char n)
{
char string[] = { 27 /*ESC*/, 'K', n};
SendPacket ((BYTE*)string, 3);
}
void CPlasma::PlasmaText (const char *szText)
{
if (!szText)
return;
int len = strlen (szText);
if (len >= 256)
return;
SendPacket ((BYTE*)szText, (char)len);
}
POINT CPlasma::GetFontSize (int Font)
{
POINT size = {0, 0};
switch (Font)
{
case 0:
case 1:
case 2:
case 3:
size.x = 5;
size.y = 7;
break;
case 4:
case 5:
size.x = 10;
size.y = 14;
break;
case 6:
case 7:
size.x = 5;
size.y = 7;
break;
}
return size;
}
void CPlasma::PlasmaBoxDraw (RECT tag)
{
char string[] = { ESC, 'X', (char)tag.left, (char)tag.top, (char)tag.right, (char)tag.bottom};
SendPacket ((BYTE*)string, 6);
}
void CPlasma::PlasmaBoxFill (RECT tag)
{
char string[] = { ESC, 'x', 0, (char)tag.left, (char)tag.top, (char)tag.right, (char)tag.bottom};
SendPacket ((BYTE*)string, 7);
}
void CPlasma::PlasmaPosText (const char *szText, char x, char y, char Attr, char Font)
{
if (!szText)
return;
int len = strlen (szText);
if (len <= 0)
return;
if (Font != 2) // !Score
{
if (len <= 9) {
Font = 5;
} else if (len <= 20) {
Font = 2;
} else {
Font = 2;
len = 20;
}
}
else
{
if (len > 20)
len = 20;
}
if (x == 0 && y == 0) {
x = 56 - ((len * GetFontSize (Font).x) / 2);
y = 15 - ((GetFontSize (Font).y) / 2);
}
PlasmaCursorX (x);
PlasmaCursorY (y);
PlasmaFontAttr (Attr);
PlasmaFont (Font);
if (len >= 256)
return;
SendPacket ((const BYTE*)szText, len);
}
void CPlasma::PlasmaScoreDraw (const char *Rank, const char *Score, BOOL bFlag)
{
int CurRank = atoi (Rank);
int CurScore = atoi (Score);
RECT tag1 = {27,19,42,30};
RECT tag2 = {42,19,93,30};
RECT tag3 = {27,19,93,30}; //Fill
if (bFlag == TRUE)
{
PlasmaBoxFill (tag3);
PlasmaBoxDraw (tag1);
PlasmaBoxDraw (tag2);
}
int len_Rank = strlen (Rank);
int len_Score = strlen (Score);
//{
if (len_Rank <= 2 && len_Rank > 0)
if (len_Score <= 8 && len_Score > 0)
{
if (CurRank != m_nOldRank)
{
PlasmaPosText (" ", 29, 20, 0, 2);
if (len_Rank == 1)
PlasmaPosText (Rank, 33, 20, 0, 2);
else
PlasmaPosText (Rank, 29, 20, 0, 2);
}
if (m_nOldScore != CurScore)
{
PlasmaPosText (" ", 44, 20, 0, 2);
PlasmaPosText (Score, (char)(85 - (len_Score * 5)), 20, 0, 2);
}
}
m_nOldRank = CurRank;
m_nOldScore = CurScore;
//}
}
void CPlasma::DoPlasma(char nMode)
{
if (g_bNoPlasma)
return;
switch(nMode)
{
case 0:
m_nGlobalState = -1;
break;
case 1:
if ((m_nGlobalState != 0) && (m_nGlobalState != 2))
return;
break;
case 2:
if ((m_nGlobalState != 1) && (m_nGlobalState != 2))
return;
break;
case 9:
if ((m_nGlobalState != 1) && (m_nGlobalState != 2))
return;
if (gos_GetElapsedTime() - m_timeLastPlasma2 < g_PlasmaClearTime)
return;
if (MWApplication::GetInstance()->GetApplicationState() != ApplicationStateEngine::WaitingForGameState)
return;
PlasmaDisplay(0, NULL, NULL, NULL);
m_nGlobalState = -1;
return;
default:
return;
}
MWApplication* app = MWApplication::GetInstance();
if (Connection::Local) {
int nID = Connection::Local->GetID();
const ServedConnectionData& scd = app->servedConnectionData[nID];
if (scd.clientConnected) {
if (nMode == 0) {
PlasmaDisplay(0, NULL, NULL, NULL);
m_nGlobalState = 0;
} else if (nMode == 1) {
PlasmaDisplay(1, scd.pilotName, NULL, NULL);
m_nGlobalState = 1;
m_timeLastPlasma2 = gos_GetElapsedTime();
} else {
Time timeLastPlasma2 = gos_GetElapsedTime();
Time timeElapsed = timeLastPlasma2 -m_timeLastPlasma2;
if (timeElapsed > 1.0f) {
if (scd.clientLoaded) {
MWPlayer* plyr = scd.clientPlayer;
if (plyr) {
Vehicle* pv = plyr->GetVehicle();
if (pv && (pv->GetClassID() == MechClassID)) {
const ReplicatorID& RepID = pv->GetReplicatorID();
MWGUIManager *manager = MWGUIManager::GetInstance ();
if (manager)
{
if (manager->Component(MWGUIManager::HUD_SCORE))
{
HUDScore* hud = Cast_Object (HUDScore *,manager->Component(MWGUIManager::HUD_SCORE));
if (hud) {
CHudScoreInfo aScores[16];
int i, nScore, nCount = hud->GetScoreArray(aScores, *(const ReplicatorID*)NULL, 1);
for(i = 0; i < nCount; i++) {
const CHudScoreInfo& HSI = aScores[i];
if (RepID == HSI) {
nScore = HSI.m_nScore;
while(i > 0) {
if (aScores[i - 1].m_nScore != nScore)
break;
i--;
}
char szRank[10], szScore[20];
sprintf(szRank, "%d", i + 1);
sprintf(szScore, "%d", nScore);
PlasmaDisplay(2, NULL, szRank, szScore);
m_nGlobalState = nMode;
m_timeLastPlasma2 = timeLastPlasma2;
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
void CPlasma::PlasmaDisplay (int Gamestate, const char *szName/*9*/, const char *Rank/*2*/, const char *Score/*8*/)
{
static BOOL BoxFlag = FALSE;
static BOOL NameFlag = FALSE;
if (Gamestate == 0) // end
{
NameFlag = TRUE;
PlasmaClear ();
}
else if (Gamestate == 1) // ready
{
if (NameFlag) {
PlasmaPosText (" ");
PlasmaPosText (szName);
}
NameFlag = FALSE;
BoxFlag = TRUE;
m_nOldRank = INT_MIN;
m_nOldScore = INT_MIN;
}
else if (Gamestate == 2) // start
{
PlasmaScoreDraw (Rank, Score, BoxFlag);
BoxFlag = FALSE;
}
}