📄 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
}
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();
m_Graphics = NULL;
return TRUE;
}
BOOL cCharacterController::Free()
{
// Release character structures
delete m_CharacterParent;
m_CharacterParent = NULL;
m_NumCharacters = 0;
// 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 paths
m_DefinitionFile[0] = 0;
m_MeshPath[0] = 0;
m_TexturePath[0] = 0;
// Clear spell controller
m_SpellController = NULL;
return TRUE;
}
BOOL cCharacterController::Add( \
long IDNum, long Definition, \
long Type, long AI, \
float XPos, float YPos, float ZPos, \
float Direction)
{
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();
// 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;
// Set a random charge amount
CharPtr->Charge = (float)(rand() % 101);
// 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);
// Load character ICS
if(CharPtr->Def.ItemFilename[0]) {
CharPtr->CharICS = new cCharICS();
CharPtr->CharICS->Load(CharPtr->Def.ItemFilename);
}
// Set character stats
CharPtr->HealthPoints = CharPtr->Def.HealthPoints;
CharPtr->ManaPoints = CharPtr->Def.ManaPoints;
// 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;
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 ICSFilename[MAX_PATH];
sCharacter *CharPtr;
FILE *fp;
// Get pointer to character in list
if((CharPtr = GetCharacter(IDNum)) == NULL)
return FALSE;
// Open file
if((fp=fopen(Filename, "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->Ailments, 1, sizeof(long), 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(ICSFilename, "ICS%s", Filename);
CharPtr->CharICS->Save(ICSFilename);
}
return TRUE;
}
BOOL cCharacterController::Load(long IDNum, char *Filename)
{
char ICSFilename[MAX_PATH];
sCharacter *CharPtr;
FILE *fp;
// Get pointer to character in list
if((CharPtr = GetCharacter(IDNum)) == NULL)
return FALSE;
// Open file
if((fp=fopen(Filename, "rb"))==NULL)
return FALSE;
// Read in 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->Ailments, 1, sizeof(long), 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, "ICS%s", Filename);
CharPtr->CharICS->Load(ICSFilename);
}
return TRUE;
}
BOOL cCharacterController::Update(long Elapsed)
{
sCharacter *CharPtr, *NextChar;
float XMove, YMove, ZMove;
static long EffectCounter = 0;
BOOL ToProcess, DeadChar;
// Return success if no characters to update
if((CharPtr = m_CharacterParent) == NULL)
return TRUE;
// Update effect counter
EffectCounter += Elapsed;
// Loop through all characters
while(CharPtr != NULL) {
// 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 -= Elapsed;
if(CharPtr->ActionTimer < 0)
CharPtr->ActionTimer = 0;
}
// Update text message timer
if(CharPtr->MessageTimer > 0)
CharPtr->MessageTimer -= Elapsed;
// 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);
}
// Mark that processing can continue later on
ToProcess = TRUE;
// Mark character as still alive
DeadChar = FALSE;
// Don't allow an update if asleep or paralyzed
if((CharPtr->Ailments & AILMENT_SLEEP) || \
(CharPtr->Ailments & AILMENT_PARALYZE))
ToProcess = FALSE;
// Process non-idle, non-walk actions
if(CharPtr->Action != CHAR_IDLE && \
CharPtr->Action != CHAR_MOVE && \
!CharPtr->ActionTimer) {
switch(CharPtr->Action) {
case CHAR_ATTACK:
// Process attack
if(ToProcess == TRUE)
Attack(CharPtr, CharPtr->Victim);
break;
case CHAR_SPELL:
// Manually cast a spell
if(m_SpellController != NULL && m_MSL != NULL && \
ToProcess == TRUE) {
m_SpellController->Add(CharPtr->SpellNum, \
CharPtr, CharPtr->SpellTarget, \
CharPtr->XPos, \
CharPtr->YPos, \
CharPtr->ZPos, \
CharPtr->TargetX, \
CharPtr->TargetY, \
CharPtr->TargetZ);
}
break;
case CHAR_ITEM:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -