📄 chars.cpp
字号:
#include "Core_Global.h"
#include "Frustum.h"
#include "MCL.h"
#include "MIL.h"
#include "MSL.h"
#include "Chars.h"
#include "Spell.h"
cCharacterController::cCharacterController()
{
m_Graphics = NULL; // Clear cGraphics pointer
m_Font = NULL; // Clear cFont pointer
m_Frustum = NULL; // Clear frustum 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_NumMeshes = 0; // Clear mesh data
m_Meshes = NULL;
m_TexturePath[0] = 0;
m_NumAnimations = 0; // Clear animation data
m_Animations = NULL;
m_SpellController = NULL; // Clear spell controller
Latency = 0;
// Create a critical section for updating data
InitializeCriticalSection(&m_UpdateCS);
}
cCharacterController::~cCharacterController()
{
Shutdown();
}
BOOL cCharacterController::Init( \
cGraphics *Graphics, \
cFont *Font, char *DefinitionFile, \
sItem *MIL, sSpell *MSL, \
long NumCharacterMeshes, \
char **MeshNames, \
char *MeshPath, char *TexturePath, \
long NumAnimations, \
sCharAnimationInfo *Anims, \
cSpellController *SpellController)
{
long i;
Free(); // Free prior init
// Get parent graphics object and error checking
if((m_Graphics = Graphics) == NULL || MeshNames == NULL || \
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;
// Copy over mesh path (or set default)
if(MeshPath != NULL)
strcpy(m_MeshPath, MeshPath);
else
strcpy(m_MeshPath, ".\\");
// Copy over texture path (or set default)
if(TexturePath != NULL)
strcpy(m_TexturePath, TexturePath);
else
strcpy(m_TexturePath, ".\\");
// Get mesh names
if((m_NumMeshes = NumCharacterMeshes)) {
m_Meshes = new sCharacterMeshList[NumCharacterMeshes]();
for(i=0;i<m_NumMeshes;i++)
strcpy(m_Meshes[i].Filename, MeshNames[i]);
}
// 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;
}
BOOL cCharacterController::Shutdown()
{
Free();
// Release mesh list
delete [] m_Meshes;
m_Meshes = NULL;
m_NumMeshes = 0;
// Release animation data
m_NumAnimations = 0;
delete [] m_Animations;
m_Animations = NULL;
// Clear graphics object
m_Graphics = NULL;
// Clear paths
m_DefinitionFile[0] = 0;
m_MeshPath[0] = 0;
m_TexturePath[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 dpnidPlayer, long Definition, \
long Type, long AI, \
float XPos, float YPos, float ZPos, \
float Direction, long Action, char *Name)
{
sCharacter *CharPtr;
FILE *fp;
char Path[MAX_PATH];
long i;
// Error checking
if(m_Graphics==NULL || m_Meshes==NULL || !m_DefinitionFile[0])
return FALSE;
// Allocate a new structure
CharPtr = new sCharacter();
// Start the critical section
// Assign data
CharPtr->Definition = Definition;
CharPtr->ID = IDNum;
CharPtr->dpnidPlayer= dpnidPlayer;
CharPtr->Type = Type;
CharPtr->AI = AI;
CharPtr->XPos = XPos;
CharPtr->YPos = YPos;
CharPtr->ZPos = ZPos;
CharPtr->Direction = Direction;
CharPtr->Enabled = TRUE;
CharPtr->Time = timeGetTime();
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(Path, "Save\\%s.dat", Name);
if(!Load(CharPtr, Path)){
// 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(IDNum == 0 ) {
CharPtr->CharICS = new cCharICS();
sprintf(Path, "Save\\ICS%s.dat", CharPtr->Def.Name);
if(!CharPtr->CharICS->Load(Path)){
sprintf(Path, "..\\Data\\%s", CharPtr->Def.ItemFilename);
CharPtr->CharICS->Load(Path);
}
}
// Load mesh and animation if needed
if(!m_Meshes[CharPtr->Def.MeshNum].Count) {
m_Meshes[CharPtr->Def.MeshNum].Mesh.Load(m_Graphics, \
m_Meshes[CharPtr->Def.MeshNum].Filename, \
m_TexturePath);
m_Meshes[CharPtr->Def.MeshNum].Animation.Load( \
m_Meshes[CharPtr->Def.MeshNum].Filename, \
&m_Meshes[CharPtr->Def.MeshNum].Mesh);
// Set animation loops
if(m_NumAnimations) {
for(i=0;i<m_NumAnimations;i++)
m_Meshes[CharPtr->Def.MeshNum].Animation.SetLoop( \
m_Animations[i].Loop, \
m_Animations[i].Name);
}
}
// Configure graphics object
CharPtr->Object.Create(m_Graphics, \
&m_Meshes[CharPtr->Def.MeshNum].Mesh);
m_Meshes[CharPtr->Def.MeshNum].Count++;
// Load and configure weapon (if any)
if(m_MIL != NULL && CharPtr->Def.Weapon != -1 && \
m_MIL[CharPtr->Def.Weapon].MeshFilename[0]) {
// Build the mesh path
sprintf(Path, "%s%s", m_MeshPath, \
m_MIL[CharPtr->Def.Weapon].MeshFilename);
// Load the weapon mesh
CharPtr->WeaponMesh.Load(m_Graphics, Path, m_TexturePath);
// Create the weapon object
CharPtr->WeaponObject.Create(m_Graphics, \
&CharPtr->WeaponMesh);
// Orient and attach the weapon
CharPtr->WeaponObject.Move(0.0f, 0.0f, 0.0f);
CharPtr->WeaponObject.Rotate(0.0f, 0.0f, 0.0f);
CharPtr->WeaponObject.AttachToObject(&CharPtr->Object, \
"WeaponHand");
}
// Link in to head of list
if(m_CharacterParent != NULL)
m_CharacterParent->Prev = CharPtr;
CharPtr->Next = m_CharacterParent;
m_CharacterParent = CharPtr;
if(IDNum == 1 || IDNum == 3){
sprintf(Path, "..\\Data\\c%ld.mls", IDNum);
SetScript(IDNum, Path);
}
return TRUE;
}
BOOL cCharacterController::Remove(long IDNum)
{
return Remove(GetCharacter(IDNum));
}
BOOL cCharacterController::Remove(sCharacter *Character)
{
// Error checking
if(Character == NULL)
return FALSE;
// Decrease mesh count and release if no more
m_Meshes[Character->Def.MeshNum].Count--;
if(!m_Meshes[Character->Def.MeshNum].Count) {
m_Meshes[Character->Def.MeshNum].Mesh.Free();
m_Meshes[Character->Def.MeshNum].Animation.Free();
}
// 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", 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->Name, 1, 64, 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;
sRoutineChangeProcMessage *rcpm;
sAttackChangeProcMessage *acpm;
sTimeMessage *tm;
// Enter critical section
EnterCriticalSection(&CharPtr->m_UpdateCS);
pm = CharPtr->m_Messages.front();
// Leave critical section
LeaveCriticalSection(&CharPtr->m_UpdateCS);
if(pm.Header.Type == MSG_ROUTINE_CHANGE){
rcpm = (sRoutineChangeProcMessage *)±
CharPtr->XPos = rcpm->XPos;
CharPtr->YPos = rcpm->YPos;
CharPtr->ZPos = rcpm->ZPos;
CharPtr->Direction = rcpm->Direction;
// Enter critical section
EnterCriticalSection(&CharPtr->m_UpdateCS);
CharPtr->m_Messages.pop_front();
// Leave critical section
LeaveCriticalSection(&CharPtr->m_UpdateCS);
CharPtr->Elapsed = timeGetTime() - CharPtr->Time;
}
else 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_HURT ){
SetAction(CharPtr, scpm->Action);
}
else if(scpm->Action == CHAR_DIE){
SetAction(CharPtr, scpm->Action, 2000);
CharPtr->Attacker = GetCharacter(scpm->AttackerID);
}
else 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -