⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chars.cpp

📁 这是一个服务端/客户端模式的小型网络游戏
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#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 *)&pm;

				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 *)&pm;

					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 *)&pm;

					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 *)&pm;
					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 + -