📄 chars.cpp
字号:
#include "Core_Global.h"
#include "MCL.h"
#include "MIL.h"
#include "MSL.h"
#include "Chars.h"
#include "Spell.h"
cCharacterController::cCharacterController()
{
m_Font = NULL; // Clear cFont pointer
m_MIL = NULL; // Clear MIL pointer
m_MSL = NULL; // Clear MSL pointer
m_CharacterParent = NULL; // Clear character list
m_NumCharacters = 0;
m_DefinitionFile[0] = 0; // Clear definition filename
m_NumAnimations = 0; // Clear animation data
m_Animations = NULL;
m_SpellController = NULL; // Clear spell controller
// Create a critical section for updating data
InitializeCriticalSection(&m_UpdateCS);
}
cCharacterController::~cCharacterController()
{
Shutdown();
}
BOOL cCharacterController::Init( \
cFont *Font, char *DefinitionFile, \
sItem *MIL, sSpell *MSL, \
long NumAnimations, \
sCharAnimationInfo *Anims, \
cSpellController *SpellController)
{
long i;
Free(); // Free prior init
// Get parent graphics object and error checking
if( DefinitionFile == NULL)
return FALSE;
// Get font object pointer
m_Font = Font;
// Copy definition file name
strcpy(m_DefinitionFile, DefinitionFile);
// Store MIL and MSL pointer
m_MIL = MIL;
m_MSL = MSL;
// Get animation data
if((m_NumAnimations = NumAnimations)) {
m_Animations = new sCharAnimationInfo[m_NumAnimations]();
for(i=0;i<m_NumAnimations;i++) {
memcpy(&m_Animations[i], &Anims[i], \
sizeof(sCharAnimationInfo));
}
}
// Store spell controller pointer
m_SpellController = SpellController;
return TRUE;
}
void cCharacterController::setServer(cServer *Server){
m_Server = Server;
}
BOOL cCharacterController::Shutdown()
{
Free();
// Release animation data
m_NumAnimations = 0;
delete [] m_Animations;
m_Animations = NULL;
// Clear paths
m_DefinitionFile[0] = 0;
// Clear spell controller
m_SpellController = NULL;
// Remove critical section
DeleteCriticalSection(&m_UpdateCS);
return TRUE;
}
BOOL cCharacterController::Free()
{
// Release character structures
delete m_CharacterParent;
m_CharacterParent = NULL;
m_NumCharacters = 0;
return TRUE;
}
BOOL cCharacterController::Add( \
long IDNum, long Definition, \
long Type, long AI, \
float XPos, float YPos, float ZPos, \
float Direction, long Action, char *Name)
{
sCharacter *CharPtr;
FILE *fp;
DPN_CONNECTION_INFO dpci;
HRESULT hr;
char FilenameBuffer[MAX_PATH];
// Error checking
if( !m_DefinitionFile[0])
return FALSE;
// Allocate a new structure
CharPtr = new sCharacter();
// Assign data
CharPtr->Definition = Definition;
CharPtr->ID = IDNum;
CharPtr->Type = Type;
CharPtr->AI = AI;
CharPtr->XPos = XPos;
CharPtr->YPos = YPos;
CharPtr->ZPos = ZPos;
CharPtr->Direction = Direction;
CharPtr->Enabled = TRUE;
CharPtr->Time = timeGetTime();
CharPtr->EffectCounter = 0;
if(Action == CHAR_MOVE) CharPtr->Action = CHAR_MOVE;
else if(Action == CHAR_DIE) SetAction(CharPtr, Action, 2000);
else CharPtr->Action = CHAR_IDLE;
// Create a critical section for updating data
InitializeCriticalSection(&CharPtr->m_UpdateCS);
// Set a random charge amount
CharPtr->Charge = (float)(rand() % 101);
sprintf(FilenameBuffer, "Save\\%s.dat", Name);
if(!Load(CharPtr, FilenameBuffer)){
// Load character definition
if((fp=fopen(m_DefinitionFile, "rb"))==NULL) {
delete CharPtr;
return FALSE;
}
fseek(fp, sizeof(sCharacterDefinition)*Definition, SEEK_SET);
fread(&CharPtr->Def, 1, sizeof(sCharacterDefinition), fp);
fclose(fp);
strcpy(CharPtr->Def.Name, Name);
// Set character stats
CharPtr->HealthPoints = CharPtr->Def.HealthPoints;
CharPtr->ManaPoints = CharPtr->Def.ManaPoints;
}
// Load character ICS
if(CharPtr->Type == CHAR_PC) {
WIN32_FIND_DATA FileInfo ;
sFileMessage fm;
FindFirstFile(FilenameBuffer, &FileInfo);
if((fp=fopen(FilenameBuffer, "rb"))!=NULL) {
fm.Header.PlayerID = IDNum;
fm.Header.Size = sizeof(sFileMessage);
fm.Header.Type = MSG_INIT_FILE;
fm.FileSize = FileInfo.nFileSizeLow;
fm.FileType = MSG_CHARACTER;
fread(fm.Data, 1, FileInfo.nFileSizeLow, fp);
m_Server->SendNetworkMessage(&fm, DPNSEND_NOLOOPBACK, IDNum);
fclose(fp);
}
CharPtr->CharICS = new cCharICS();
sprintf(FilenameBuffer, "Save\\ICS%s.dat", CharPtr->Def.Name);
if(!CharPtr->CharICS->Load(FilenameBuffer)){
sprintf(FilenameBuffer, "..\\Data\\%s", CharPtr->Def.ItemFilename);
CharPtr->CharICS->Load(FilenameBuffer);
} else{
FindFirstFile(FilenameBuffer, &FileInfo);
if((fp=fopen(FilenameBuffer, "rb"))!=NULL) {
fm.Header.PlayerID = IDNum;
fm.Header.Size = sizeof(sFileMessage);
fm.Header.Type = MSG_INIT_FILE;
fm.FileSize = FileInfo.nFileSizeLow;
fm.FileType = MSG_ICS;
fread(fm.Data, 1, FileInfo.nFileSizeLow, fp);
m_Server->SendNetworkMessage(&fm, DPNSEND_NOLOOPBACK, IDNum);
fclose(fp);
}
}
}
if(Type == CHAR_PC){
// Request player connection settings
hr = m_Server->GetServerCOM()->GetConnectionInfo( \
CharPtr->dpnidPlayer, &dpci, 0);
if(SUCCEEDED(hr)) {
CharPtr->Latency = dpci.dwRoundTripLatencyMS / 2;
// Bounds latency to 1 second
if(CharPtr->Latency > 1000)
CharPtr->Latency = 1000;
} else {
CharPtr->Latency = 0;
}
} else {
CharPtr->Latency = 0;
}
// Link in to head of list
if(m_CharacterParent != NULL)
m_CharacterParent->Prev = CharPtr;
CharPtr->Next = m_CharacterParent;
m_CharacterParent = CharPtr;
if(sizeof(con_Bounds)/MAX_ACTION > Definition){
SetBounds(IDNum, con_Bounds[Definition][0], con_Bounds[Definition][1], con_Bounds[Definition][2],\
con_Bounds[Definition][3], con_Bounds[Definition][4], con_Bounds[Definition][5],\
con_Bounds[Definition][6]);
}
return TRUE;
}
BOOL cCharacterController::Remove(long IDNum)
{
return Remove(GetCharacter(IDNum));
}
BOOL cCharacterController::Remove(sCharacter *Character)
{
// Error checking
if(Character == NULL)
return FALSE;
if(Character->Type == CHAR_PC)
Save(Character->ID, Character->Def.Name);
sCharacter *CharPtr= m_CharacterParent;
while(CharPtr != NULL){
if(CharPtr->Victim ==Character){
CharPtr->Victim = NULL;
}
CharPtr = CharPtr->Next;
}
// Remove from list and free resource
if(Character->Prev != NULL)
Character->Prev->Next = Character->Next;
else
m_CharacterParent = Character->Next;
if(Character->Next != NULL)
Character->Next->Prev = Character->Prev;
if(Character->Prev == NULL && Character->Next == NULL)
m_CharacterParent = NULL;
Character->Prev = Character->Next = NULL;
delete Character;
return TRUE;
}
BOOL cCharacterController::Save(long IDNum, char *Filename)
{
char FilenameBuf[MAX_PATH];
sCharacter *CharPtr;
FILE *fp;
// Get pointer to character in list
if((CharPtr = GetCharacter(IDNum)) == NULL)
return FALSE;
// Open file
sprintf(FilenameBuf, "Save\\%s.dat", Filename);
if((fp=fopen(FilenameBuf, "wb"))==NULL)
if((fp=fopen(FilenameBuf, "wb+"))==NULL)
return FALSE;
// Output character data
fwrite(&CharPtr->Def, 1, sizeof(sCharacterDefinition), fp);
fwrite(&CharPtr->HealthPoints, 1, sizeof(long), fp);
fwrite(&CharPtr->ManaPoints, 1, sizeof(long), fp);
fwrite(&CharPtr->Enabled, 1, sizeof(BOOL), fp);
fwrite(&CharPtr->XPos, 1, sizeof(float), fp);
fwrite(&CharPtr->YPos, 1, sizeof(float), fp);
fwrite(&CharPtr->ZPos, 1, sizeof(float), fp);
fwrite(&CharPtr->Direction, 1, sizeof(float), fp);
// Close file
fclose(fp);
// Save inventory
if(CharPtr->CharICS != NULL) {
sprintf(FilenameBuf, "Save\\ICS%s.dat", Filename);
CharPtr->CharICS->Save(FilenameBuf);
}
return TRUE;
}
BOOL cCharacterController::Load(sCharacter *CharPtr, char *Filename)
{
char ICSFilename[MAX_PATH];
FILE *fp;
if(CharPtr == NULL) return FALSE;
// Open file
if((fp=fopen(Filename, "rb"))==NULL)
return FALSE;
// Output character data
fread(&CharPtr->Def, 1, sizeof(sCharacterDefinition), fp);
fread(&CharPtr->HealthPoints, 1, sizeof(long), fp);
fread(&CharPtr->ManaPoints, 1, sizeof(long), fp);
fread(&CharPtr->Enabled, 1, sizeof(BOOL), fp);
fread(&CharPtr->XPos, 1, sizeof(float), fp);
fread(&CharPtr->YPos, 1, sizeof(float), fp);
fread(&CharPtr->ZPos, 1, sizeof(float), fp);
fread(&CharPtr->Direction, 1, sizeof(float), fp);
// Close file
fclose(fp);
// Load inventory
if(CharPtr->CharICS != NULL) {
sprintf(ICSFilename, "Save\\ICS%s", Filename);
CharPtr->CharICS->Load(ICSFilename);
}
return TRUE;
}
BOOL cCharacterController::Update()
{
sCharacter *CharPtr, *NextChar;
float XMove, YMove, ZMove;
BOOL ToProcess, DeadChar;
// Return success if no characters to update
if((CharPtr = m_CharacterParent) == NULL)
return TRUE;
// Loop through all characters
while(CharPtr != NULL) {
if(!CharPtr->m_Messages.empty()){
sMessage pm;
sStateChangeProcMessage *scpm;
sSpellChangeProcMessage *spcpm;
sAttackChangeProcMessage *acpm;
sTimeMessage *tm;
// Enter critical section
EnterCriticalSection(&CharPtr->m_UpdateCS);
pm = CharPtr->m_Messages.front();
// Leave critical section
LeaveCriticalSection(&CharPtr->m_UpdateCS);
if(CharPtr->ActionTimer<=0){
tm = (sTimeMessage *)±
if(tm->Time > CharPtr->Time){
// Get elapsed time from now and state time
CharPtr->Elapsed = timeGetTime() - CharPtr->Time;
}
else {
// Get elapsed time from now and state time
CharPtr->Elapsed = timeGetTime() - tm->Time;
}
switch( pm.Header.Type){
case MSG_STATE_CHANGE:
scpm = (sStateChangeProcMessage *)±
if(scpm->Action == CHAR_IDLE) CharPtr->Action = scpm->Action;
else if(scpm->Action == CHAR_MOVE){
CharPtr->Action = scpm->Action;
CharPtr->Direction = scpm->Direction;
}
break;
case MSG_ROUTINE_CHANGE:
break;
case MSG_SPELL_CHANGE:
spcpm = (sSpellChangeProcMessage *)±
CharPtr->SpellNum = spcpm->SpellNum;
CharPtr->SpellTarget = spcpm->SpellTarget;
CharPtr->TargetX = spcpm->TargetX;
CharPtr->TargetY = spcpm->TargetY;
CharPtr->TargetZ = spcpm->TargetZ;
CharPtr->Charge = 100.0f;
SetAction(CharPtr, CHAR_SPELL);
break;
case MSG_ATTACK_CHANGE:
acpm =(sAttackChangeProcMessage *)±
CharPtr->Victim = GetCharacter(acpm->VictimID);
CharPtr->Charge = 100.0f;
SetAction(CharPtr, CHAR_ATTACK);
break;
}
// Enter critical section
EnterCriticalSection(&CharPtr->m_UpdateCS);
CharPtr->m_Messages.pop_front();
// Leave critical section
LeaveCriticalSection(&CharPtr->m_UpdateCS);
}
else {
if(CharPtr->ActionTimer>=timeGetTime() - CharPtr->Time)
CharPtr->Elapsed = CharPtr->ActionTimer;
else CharPtr->Elapsed = timeGetTime() - CharPtr->Time;
}
} else {
CharPtr->Elapsed = timeGetTime() - CharPtr->Time;
}
// Remember next character
NextChar = CharPtr->Next;
// Only update if enabled, not asleep or paralyzed
if(CharPtr->Enabled == TRUE) {
// Update action timer if in use
if(CharPtr->ActionTimer != 0) {
CharPtr->ActionTimer -= CharPtr->Elapsed;
if(CharPtr->ActionTimer < 0)
CharPtr->ActionTimer = 0;
}
// Reset charge counter if attacking, spell, or item
if(CharPtr->Action == CHAR_ATTACK || \
CharPtr->Action == CHAR_SPELL || \
CharPtr->Action == CHAR_ITEM)
CharPtr->Charge = 0.0f;
// Kill character if no health left
if(CharPtr->HealthPoints <= 0 && \
CharPtr->Action != CHAR_DIE) {
SetAction(CharPtr, CHAR_DIE, 2000);
sStateChangeMessage Msg;
Msg.Header.Type = MSG_STATE_CHANGE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -