📄 spell.cpp
字号:
#include "Core_Global.h"
#include "MCL.h"
#include "MSL.h"
#include "Chars.h"
#include "Spell.h"
cSpellController::cSpellController()
{
m_Chars = NULL; // Clear character controller
m_SpellParent = NULL;
}
cSpellController::~cSpellController()
{
Shutdown();
}
BOOL cSpellController::Init(char *DefinitionFile, cCharacterController *Controller)
{
FILE *fp;
long i;
Free(); // Free prior init
// Get parent graphics object
if( DefinitionFile == NULL)
return FALSE;
// Load the spells
if((fp=fopen(DefinitionFile, "rb"))==NULL)
return FALSE;
for(i=0;i<NUM_SPELL_DEFINITIONS;i++)
fread(&m_Spells[i], 1, sizeof(sSpell), fp);
fclose(fp);
m_Chars = Controller; // Store controller pointer
return TRUE;
}
BOOL cSpellController::Shutdown()
{
Free(); // Free class data
return TRUE;
}
BOOL cSpellController::Free()
{
// Release spell list
delete m_SpellParent;
m_SpellParent = NULL;
return TRUE;
}
sSpell *cSpellController::GetSpell(long SpellNum)
{
return &m_Spells[SpellNum];
}
BOOL cSpellController::Add(long SpellNum, \
sCharacter *Caster, long TargetType, \
float SourceX, float SourceY, float SourceZ, \
float TargetX, float TargetY, float TargetZ)
{
sSpellTracker *SpellPtr;
// Make sure character is allowed to cast spell
if(Caster != NULL) {
if(!(Caster->Def.MagicSpells[SpellNum/32] & \
(1 << (SpellNum & 31))))
return FALSE;
// Make sure caster has enough MP to cast and reduce MP
if(Caster != NULL) {
// Return if not enough mana
if(Caster->ManaPoints < m_Spells[SpellNum].Cost)
return FALSE;
}
}
// Allocate a new structure and link in to head of list
SpellPtr = new sSpellTracker();
if(m_SpellParent != NULL)
m_SpellParent->Prev = SpellPtr;
SpellPtr->Next = m_SpellParent;
m_SpellParent = SpellPtr;
// Set structure data
SpellPtr->SpellNum = SpellNum;
SpellPtr->Caster = Caster;
SpellPtr->Type = TargetType;
SpellPtr->SourceX = SourceX;
SpellPtr->SourceY = SourceY;
SpellPtr->SourceZ = SourceZ;
SpellPtr->TargetX = TargetX;
SpellPtr->TargetY = TargetY;
SpellPtr->TargetZ = TargetZ;
// Setup the mesh and movement data
SetAnimData(SpellPtr, 0);
return TRUE;
}
BOOL cSpellController::Update()
{
sSpellTracker *SpellPtr, *NextSpell;
long SpellNum, Anim;
BOOL GotoNextAnim;
float Speed;
long Elapsed;
if((SpellPtr = m_SpellParent) == NULL)
return FALSE;
// Scan through all spells in use
while(SpellPtr != NULL) {
// Get elapsed time from now and state time
Elapsed = SpellPtr->Caster->Elapsed;
// Remember next spell in list
NextSpell = SpellPtr->Next;
// Get local data
SpellNum = SpellPtr->SpellNum;
Anim = SpellPtr->CurrentAnimation;
// Update/move/countdown spell object
GotoNextAnim = FALSE;
switch(m_Spells[SpellNum].MeshPos[Anim]) {
case POSITION_NONE:
// Go to next animation
GotoNextAnim = TRUE;
break;
case POSITION_CASTER:
case POSITION_TARGET:
case POSITION_SCALE:
SpellPtr->Time -= Elapsed;
if(SpellPtr->Time <= 0)
GotoNextAnim = TRUE;
break;
case POSITION_TOTARGET:
case POSITION_TOCASTER:
Speed = (float)Elapsed / 1000.0f * SpellPtr->Speed;
// Decrease distance amount
SpellPtr->Distance -= Speed;
if(SpellPtr->Distance <= 0.0f)
GotoNextAnim = TRUE;
else {
SpellPtr->XPos += (SpellPtr->XAdd * Speed);
SpellPtr->YPos += (SpellPtr->YAdd * Speed);
SpellPtr->ZPos += (SpellPtr->ZAdd * Speed);
}
break;
}
// Update to next animation
if(GotoNextAnim == TRUE){
SetAnimData(SpellPtr, Anim+1);
}
// Go to next spell
SpellPtr = NextSpell;
}
return TRUE;
}
BOOL cSpellController::SetAnimData(sSpellTracker *SpellPtr, \
long Num)
{
float XDiff, YDiff, ZDiff, Dist;
float XAngle = 0.0f, YAngle = 0.0f;
float Scale = 1.0f;
long SpellNum;
float SourceX, SourceY, SourceZ;
float TargetX, TargetY, TargetZ;
// Process spell effect if no more animations left
// while storing the current animation number.
if((SpellPtr->CurrentAnimation = Num) >= 3) {
if(m_Chars != NULL)
m_Chars->Spell(SpellPtr->Caster, SpellPtr, m_Spells);
// Remove spell from list
if(SpellPtr->Prev != NULL)
SpellPtr->Prev->Next = SpellPtr->Next;
else
m_SpellParent = SpellPtr->Next;
if(SpellPtr->Next != NULL)
SpellPtr->Next->Prev = SpellPtr->Prev;
SpellPtr->Prev = SpellPtr->Next = NULL;
delete SpellPtr;
return TRUE;
}
// Setup local data
SourceX = SpellPtr->SourceX;
SourceY = SpellPtr->SourceY;
SourceZ = SpellPtr->SourceZ;
TargetX = SpellPtr->TargetX;
TargetY = SpellPtr->TargetY;
TargetZ = SpellPtr->TargetZ;
SpellNum = SpellPtr->SpellNum;
// Go to next animation if no mesh to use
if(m_Spells[SpellNum].MeshPos[Num] == POSITION_NONE)
return SetAnimData(SpellPtr,Num+1);
// Setup mesh movements
switch(m_Spells[SpellNum].MeshPos[Num]) {
case POSITION_CASTER:
SpellPtr->XPos = SourceX;
SpellPtr->YPos = SourceY;
SpellPtr->ZPos = SourceZ;
SpellPtr->Time = (long)m_Spells[SpellNum].MeshSpeed[Num];
if(SpellPtr->Caster != NULL)
YAngle = SpellPtr->Caster->Direction;
break;
case POSITION_TOTARGET:
// Store position and speed info
SpellPtr->XPos = SourceX;
SpellPtr->YPos = SourceY;
SpellPtr->ZPos = SourceZ;
SpellPtr->Speed = m_Spells[SpellNum].MeshSpeed[Num];
// Calculate movement
XDiff = (float)fabs(TargetX - SourceX);
YDiff = (float)fabs(TargetY - SourceY);
ZDiff = (float)fabs(TargetZ - SourceZ);
Dist = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);
if((SpellPtr->Distance = Dist) != 0.0f) {
SpellPtr->XAdd = (TargetX - SourceX) / Dist;
SpellPtr->YAdd = (TargetY - SourceY) / Dist;
SpellPtr->ZAdd = (TargetZ - SourceZ) / Dist;
}
break;
case POSITION_TARGET:
SpellPtr->XPos = TargetX;
SpellPtr->YPos = TargetY;
SpellPtr->ZPos = TargetZ;
SpellPtr->Time = (long)m_Spells[SpellNum].MeshSpeed[Num];
// Calculate distance from source to target
XDiff = (float)fabs(TargetX - SourceX);
ZDiff = (float)fabs(TargetZ - SourceZ);
Dist = (float)sqrt(XDiff*XDiff+ZDiff*ZDiff);
SpellPtr->XAdd = (TargetX - SourceX) / Dist;
SpellPtr->ZAdd = (TargetZ - SourceZ) / Dist;
break;
case POSITION_TOCASTER:
// Store position and speed info
SpellPtr->XPos = TargetX;
SpellPtr->YPos = TargetY;
SpellPtr->ZPos = TargetZ;
SpellPtr->Speed = m_Spells[SpellNum].MeshSpeed[Num];
// Calculate movement
XDiff = (float)fabs(SourceX - TargetX);
YDiff = (float)fabs(SourceY - TargetY);
ZDiff = (float)fabs(SourceZ - TargetZ);
Dist = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);
if((SpellPtr->Distance = Dist) != 0.0f) {
SpellPtr->XAdd = (SourceX - TargetX) / Dist;
SpellPtr->YAdd = (SourceY - TargetY) / Dist;
SpellPtr->ZAdd = (SourceZ - TargetZ) / Dist;
}
break;
case POSITION_SCALE:
// Store position and speed info
SpellPtr->XPos = SourceX;
SpellPtr->YPos = SourceY;
SpellPtr->ZPos = SourceZ;
SpellPtr->Time = (long)m_Spells[SpellNum].MeshSpeed[Num];
// Get distance from source to target and size of mesh
XDiff = (float)fabs(TargetX - SourceX);
YDiff = (float)fabs(TargetY - SourceY);
ZDiff = (float)fabs(TargetZ - SourceZ);
Dist = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);
// Calculate scale
Scale = Dist / 130.0f;
// Calculate angles
SpellPtr->XAdd = (TargetX - SourceX) / Dist;
SpellPtr->YAdd = (TargetY - SourceY) / Dist;
SpellPtr->ZAdd = (TargetZ - SourceZ) / Dist;
break;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -