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

📄 chars.cpp

📁 这是一个服务端/客户端模式的小型网络游戏
💻 CPP
📖 第 1 页 / 共 4 页
字号:


BOOL cCharacterController::Move(                              \
               long IDNum,                                    \
               float XPos, float YPos, float ZPos)
{
  sCharacter *CharPtr;

  // Get pointer to character
  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  // Set new values
  CharPtr->XPos = XPos;
  CharPtr->YPos = YPos;
  CharPtr->ZPos = ZPos;
  return TRUE;
}

BOOL cCharacterController::GetPosition(                       \
               long IDNum,                                    \
               float *XPos, float *YPos, float *ZPos)
{
  sCharacter *CharPtr;

  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  if(XPos != NULL)
    *XPos = CharPtr->XPos;
  if(YPos != NULL)
    *YPos = CharPtr->YPos;
  if(ZPos != NULL)
    *ZPos = CharPtr->ZPos;

  return TRUE;
}

BOOL cCharacterController::SetBounds(                         \
               long IDNum,                                    \
               float MinX, float MinY, float MinZ,            \
               float MaxX, float MaxY, float MaxZ, float Radius)
{
  sCharacter *CharPtr;

  // Get pointer to character
  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  // Set new values
  CharPtr->MinX = min(MinX, MaxX);
  CharPtr->MinY = min(MinY, MaxY);
  CharPtr->MinZ = min(MinZ, MaxZ);
  CharPtr->MaxX = max(MinX, MaxX);
  CharPtr->MaxY = max(MinY, MaxY);
  CharPtr->MaxZ = max(MinZ, MaxZ);
  CharPtr->Radius = Radius;

  return TRUE;
}   

BOOL cCharacterController::GetBounds(                         \
               long IDNum,                                    \
               float *MinX, float *MinY, float *MinZ,         \
               float *MaxX, float *MaxY, float *MaxZ, float *Radius)
{
  sCharacter *CharPtr;

  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  if(MinX != NULL)
    *MinX = CharPtr->MinX;
  if(MinY != NULL)
    *MinY = CharPtr->MinY;
  if(MinZ != NULL)
    *MinZ = CharPtr->MinZ;
  if(MaxX != NULL)
    *MaxX = CharPtr->MaxX;
  if(MaxY != NULL)
    *MaxY = CharPtr->MaxY;
  if(MaxZ != NULL)
    *MaxZ = CharPtr->MaxZ;
  if(Radius != NULL)
    *Radius = CharPtr->Radius;

  return TRUE;
}

BOOL cCharacterController::SetType(long IDNum, long Type)
{
  sCharacter *CharPtr;

  // Get pointer to character
  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  // Set new value
  CharPtr->Type = Type;
  return TRUE;
}

long cCharacterController::GetType(long IDNum)
{
  sCharacter *CharPtr;

  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return 0;
  return CharPtr->Type;
}

BOOL cCharacterController::SetAI(long IDNum, long Type)
{
  sCharacter *CharPtr;

  // Get pointer to character
  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  // Set new value
  CharPtr->AI = Type;
  return TRUE;
}

long cCharacterController::GetAI(long IDNum)
{
  sCharacter *CharPtr;

  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return 0;
  return CharPtr->AI;
}

BOOL cCharacterController::SetTargetCharacter(long IDNum,     \
                                              long TargetNum)
{
  sCharacter *CharPtr, *CharTarget;

  // Get pointer to character
  if((CharPtr = GetCharacter(IDNum)) == NULL)
    return FALSE;

  // Clear if TargetNum == -1
  if(TargetNum == -1)
    CharPtr->TargetChar = NULL;
  else {
    // Scan through list and target 1st TargetNum found
    CharTarget = m_CharacterParent;
    while(CharTarget != NULL) {
      if(CharTarget->ID == TargetNum) {
        CharPtr->TargetChar = CharTarget;
        break;
      }
      CharTarget = CharTarget->Next;
    }

    // Clear target if not found in list
    if(CharTarget == NULL)
      CharPtr->TargetChar = NULL;
  }
  return TRUE;
}

BOOL cCharacterController::CharUpdate(                        \
               sCharacter *Character, long Elapsed,           \
               float *XMove, float *YMove, float *ZMove)
{
  float MoveX, MoveY, MoveZ, Speed;
  float XDiff, YDiff, ZDiff, Dist, Radius;
  float y1, y2;
  long  i, SpellNum;
  BOOL SpellCast;
  sCharacter *CharPtr;
  //long VictimDpnid;

  // Error checking
  if(Character == NULL)
    return FALSE;

  // Clear movements and action
  MoveX = MoveY = MoveZ = 0.0f;

  // Calculate movement speed
  Speed = (float)Elapsed / 1000.0f * GetSpeed(Character);

  // Move character based on their type
  switch(Character->AI) {
    case CHAR_STAND:
      break;
      
    case CHAR_WANDER:
      // Calculate new distance and direction if needed
      Character->Distance -= Elapsed;

      if(Character->Distance <= 0.0f) {

        // Calculate a new distance to travel
        Character->Distance = (float)(rand() % 2000) + 2000.0f;

        // Calculate a new direction
        Character->Direction = (float)(rand()%360)*0.01744444f;
      }

      // Process walk or stand still
      if(Character->Distance > 1000.0f) {
        MoveX = (float)sin(Character->Direction) * Speed;
        MoveZ = (float)cos(Character->Direction) * Speed;
        Character->Action = CHAR_MOVE;
  
      } else {
        // Stand still for one second
        Character->Action = CHAR_IDLE;    
      }

      break;

    case CHAR_FOLLOW:
	  float minDist;
	  sCharacter *CharPtrMinDist;
	  minDist = MAX_FLOAT;
	  CharPtrMinDist = NULL;
      // Scan through list and pick a character
      CharPtr = m_CharacterParent;
      while(CharPtr != NULL) {
        // Randomly pick enabled target (a PC),
        // and make sure the target is not hurt or dead.
        if(CharPtr != Character && CharPtr->Type==CHAR_PC &&
		   CharPtr->Enabled == TRUE &&                        \
           CharPtr->Action != CHAR_DIE ) {

          // Get distance to target
          XDiff = (float)fabs(Character->XPos - CharPtr->XPos);
          YDiff = (float)fabs(Character->YPos - CharPtr->YPos);
          ZDiff = (float)fabs(Character->ZPos - CharPtr->ZPos);
          Dist  = XDiff * XDiff + YDiff * YDiff + ZDiff * ZDiff;

          // Attack if in range
          if(minDist > Dist) {
			minDist = Dist;
			CharPtrMinDist = CharPtr;
		  }
        }

        // Go to next character
        CharPtr = CharPtr->Next;
      }
	  if(CharPtrMinDist != NULL){

		  // Update if further then distance
		  if(minDist > (Character->Distance*Character->Distance)) {
			  
			  // Setup movement towards target
			  minDist = (float)sqrt(minDist);
			  if(Speed > minDist)
				  Speed = minDist;
			  MoveX = (CharPtrMinDist->XPos -              \
				  Character->XPos) / minDist * Speed;
			  MoveZ = (CharPtrMinDist->ZPos -              \
				  Character->ZPos) / minDist * Speed;
			  
			  // Set new direction
			  Character->Direction = (float)atan2(MoveX, MoveZ);
			  
			  // Set new action
			  Character->Action = CHAR_MOVE;
		  }
      }

      break;

  }

  // Process monster actions if at full charge
  if(Character->Type == CHAR_MONSTER &&                       \
                                Character->Charge >= 100.0f) {
    // Determine chance of attacking
    if((rand() % 100) <= Character->Def.ToAttack) {
      // Scan through list and pick a character
      CharPtr = m_CharacterParent;
      while(CharPtr != NULL) {
        // Randomly pick enabled target (a PC),
        // and make sure the target is not hurt or dead.
        if(CharPtr != Character && CharPtr->Type==CHAR_PC &&  \
           (rand() % 100) < 50 &&                             \
           CharPtr->Enabled == TRUE &&                        \
           CharPtr->Action != CHAR_DIE &&                     \
           CharPtr->Action != CHAR_HURT) {

          // Get distance to target
          XDiff = (float)fabs(Character->XPos - CharPtr->XPos);
          YDiff = (float)fabs(Character->YPos - CharPtr->YPos);
          ZDiff = (float)fabs(Character->ZPos - CharPtr->ZPos);
          Dist  = XDiff * XDiff + YDiff * YDiff + ZDiff * ZDiff;

          // Make sure in range to attack
          Radius = GetXZRadius(Character);
          Radius += Character->Def.Range;

          // Attack if in range
          if((Radius*Radius) >= Dist && !CheckIntersect(Character->XPos, Character->YPos, Character->ZPos,
						CharPtr->XPos, CharPtr->YPos, CharPtr->ZPos) ) {
			  // Set attack data
			  Character->Victim = CharPtr;
			  CharPtr->Attacker = Character;
			  
			  // Clear movement
			  MoveX = MoveY = MoveZ = 0.0f;
			  
			  // Point towards target character
			  XDiff = CharPtr->XPos - Character->XPos;
			  ZDiff = CharPtr->ZPos - Character->ZPos;
			  Character->Direction = (float)atan2(XDiff, ZDiff);
			  
			  if(SetAction(Character, CHAR_ATTACK)){
				  sAttackChangeMessage sacm;
				  sacm.Header.Type     = MSG_ATTACK_CHANGE;
				  sacm.Header.Size     = sizeof(sAttackChangeMessage);
				  sacm.Header.PlayerID = Character->dpnidPlayer;
				  sacm.VictimDpnid     = CharPtr->dpnidPlayer;

				  // Send the message over network
				  m_Server->SendNetworkMessage(&sacm, DPNSEND_NOLOOPBACK, -1);
				  // Perform attack action
			  }
			  break;
		  }
        }

        // Go to next character
        CharPtr = CharPtr->Next;
      }
    } else

    // Determine chance of spell casting
    if((rand() % 100) <= Character->Def.ToMagic &&            \
                 m_MSL != NULL && m_SpellController != NULL) {

	  // Flag no spells cast
      SpellCast = FALSE;


      // If now spells already cast, then pick a random one
      if(SpellCast == FALSE) {

        // Pick a random spell to attack with
        SpellNum = rand() % 64;

        // Scan through list until a spell is found the
        // monster can cast.
        for(i=0;i<64;i++) {
          if(m_MSL[SpellNum].Name[0] &&                       \
             Character->Def.MagicSpells[SpellNum / 32] &      \
                                   (1 << (SpellNum & 31)) &&  \
             Character->ManaPoints >= m_MSL[SpellNum].Cost && \
             (rand() % 100) < 50) {

            // Scan through list and pick a character
            CharPtr = m_CharacterParent;
            while(CharPtr != NULL) {

              // Randomly pick an enabled target (a PC), 
              // and make sure the target is not hurt or dead.
              // Also, don't cast self-targeting spells here.
              if(CharPtr != Character &&                      \
                 CharPtr->Type == CHAR_PC &&                  \
                 m_MSL[SpellNum].Target != TARGET_SELF &&     \
                 (rand() % 100) < 50 &&                       \
                 CharPtr->Enabled == TRUE &&                  \
                 CharPtr->Action != CHAR_DIE &&               \
                 CharPtr->Action != CHAR_HURT) {

                // Get heights of attacker and target
                // for line of sight checking
                GetBounds(CharPtr->ID, NULL,NULL,NULL,   \
                                            NULL,&y1,NULL,NULL);
                y1 = (y1 * 0.5f) + Character->YPos;

                GetBounds(CharPtr->ID, NULL,NULL,NULL,     \
                                          NULL,&y2,NULL,NULL);
                y2 = (y2 * 0.5f) + CharPtr->YPos;

                // Get distance to target
                XDiff = (float)fabs(Character->XPos -         \
                                    CharPtr->XPos);
                YDiff = (float)fabs(Character->YPos -         \
                                    CharPtr->YPos);
                ZDiff = (float)fabs(Character->ZPos -         \
                                    CharPtr->ZPos);
                Dist  = XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff;

                // Reduce distance by character's radius
                Radius = GetXZRadius(CharPtr);
                Dist -= (Radius*Radius);

                // Get spell radius
                Radius = m_MSL[SpellNum].Distance;

                // Make sure target is in range and in sight
                if(!CheckIntersect( Character->XPos, y1,           \
                               Character->ZPos,               \
                               CharPtr->XPos, y2,             \
                               CharPtr->ZPos) &&              \
                   Dist <= (Radius * Radius)) {

                  // Set the spell data
                  Character->Victim      = CharPtr;
				//  VictimDpnid =  CharPtr->dpnidPlayer;
                  CharPtr->Attacker      = Character;
			     // AttackerDpnid = Character->dpnidPlayer;
                  Character->SpellNum    = SpellNum;
                  Character->SpellTarget = CHAR_PC;

                  // Store target coordinates
                  Character->TargetX = CharPtr->XPos;
                  Character->TargetY = CharPtr->YPos;
                  Character->TargetZ = CharPtr->ZPos;

                  // Face toward target (only if not self)
                  if(m_MSL[SpellNum].Target != TARGET_SELF) {
                    XDiff = CharPtr->XPos - Character->XPos;
                    ZDiff = CharPtr->ZPos - Character->ZPos;
                    Character->Direction =                    \
                                 (float)atan2(XDiff, ZDiff);
                  }

                  // Clear movement
                  MoveX = MoveY = MoveZ = 0.0f;

                  // Set the spell action
                  SetAction(Character, CHAR_SPELL);

                  // Flag spell as cast
                  SpellCast = TRUE;

                  break;
                }
              }

              // Go to next character
              CharPtr = CharPtr->Next;
            }
            break;
          }

          // Go to next spell
          SpellNum = (SpellNum + 1) % 64;
        }
      }

    }
	if(SpellCast == TRUE){

  	    sSpellChangeMessage spcm;
        spcm.Header.Type     = MSG_SPELL_CHANGE;
        spcm.Header.Size     = sizeof(sSpellChangeMessage);
        spcm.Header.PlayerID = Character->dpnidPlayer;
        spcm.SpellNum        = Character->SpellNum;
	    spcm.SpellTarget     = Character->SpellTarget;
        spcm.TargetX         = Character->TargetX;
        spcm.TargetY         = Character->TargetY;
        spcm.TargetZ         = Character->TargetZ;

      // Send the message over network
        m_Server->SendNetworkMessage(&spcm, DPNSEND_NOLOOPBACK, -1);
	}
  }

  // Store movement and return
  *XMove = MoveX;
  *YMove = MoveY;
  *ZMove = MoveZ;

	// Set new animation
	if(Character->LastAnim != Character->Action) {
		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -