Unit.cpp
上传用户:jxpjxmjjw
上传日期:2009-12-07
资源大小:5877k
文件大小:28k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. // Copyright (C) 2004 Team Python // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "Unit.h" #include "UpdateMask.h" #include "WorldServer.h" #include "Quest.h" #include "Character.h" #include "Opcodes.h" #include "Timer.h" #include "math.h" #define world WorldServer::getSingleton() Unit::Unit() : Object() {     m_objectType |= TYPE_UNIT;     m_objectTypeId = 3;     m_updateValues[ OBJECT_FIELD_TYPE ] = m_objectType;     setAnimFrequency( 1, 5 );     mQuestIds.clear();     m_corpseDelay = 30000;     m_respawnDelay = 420000;     m_respawnTimer = 0;     m_deathTimer = 0;     m_attackTimer = 0;     m_moveTimer = 0;     itemcount = 0;     memset(item_list, 0, 8*128);     m_deathState = ALIVE;     m_state = 0; m_combat = false; m_wport = false; m_taxi = 0; m_taxinode = 0;     m_nWaypoints = 0;     m_currentWaypoint = 0;     m_moveBackward = false;     m_moveRandom = false;     m_moveRun = false;     m_creatureState = STOPPED;     m_destinationX = m_destinationY = m_destinationZ = 0;     m_moveSpeed = 0; // nothin changes - start m_damageDuration = 0; m_damageTimer = 1000; m_damage = 0; m_Attacker; m_absorb = 0; m_absorbTimer = 0; m_absorbDuration = 0; m_auraDuration = 0; m_auraTimer = 0; m_shieldDuration = 0; m_shieldTimer = 0; m_shield = 0; m_follow=0; //m_pet_state = 2; // nothin changes - end
  2. m_Pet=false; } Unit::~Unit() {     mQuestIds.clear( ); } void Unit::setAnimFrequency( uint32 anim, float frequency ) 
  3. {     mAnimFrequencies[ anim ] = frequency; } // <WoW Chile Dev Team> Start Change // Asus: soon i optimized the code, for better visual look. void Unit::UpdateMobMovement( uint32 p_time) {     uint32 timediff = 0;     if(m_moveTimer > 0)     {         if(p_time >= m_moveTimer)         {             timediff = p_time - m_moveTimer;             m_moveTimer = 0;         }         else             m_moveTimer -= p_time;     }     if(m_creatureState == MOVING)     {         if(!m_moveTimer)         {             float dx, dy, dz;             float destMoved = m_moveSpeed*(UNIT_MOVEMENT_INTERPOLATE_INTERVAL + timediff); // moveTimer interval             float moveDistance;             dx = m_destinationX - m_positionX;             dy = m_destinationY - m_positionY;             dz = m_destinationZ - m_positionZ;             if(!dx && !dy && !dz || (moveDistance = sqrt((dx*dx) + (dy*dy) + (dz*dz))) <= destMoved)             {                 m_creatureState = STOPPED;                 m_moveTimer = rand() % (m_moveRun ? 5000 : 10000); // wait before next move                 m_positionX = m_destinationX;                 m_positionY = m_destinationY;                 m_positionZ = m_destinationZ;                 //uint8 pAnnounce[256];                 //sprintf((char*)pAnnounce, "%i done moving", m_guid[0]);   // Adds BROADCAST:                 //WorldServer::getSingleton().SendWorldText((uint8*)pAnnounce); // send message                 m_destinationX = m_destinationY = m_destinationZ = 0;                 UpdateObject();             }             else             {                 float q = destMoved/(moveDistance - destMoved);                 m_positionX = (m_positionX + m_destinationX*q)/(1+q);                 m_positionY = (m_positionY + m_destinationY*q)/(1+q);                 m_positionZ = (m_positionZ + m_destinationZ*q)/(1+q);                 uint32 moveTime = (uint32) ((moveDistance-destMoved) / m_moveSpeed);                 //printf("moving %f %f %fn", m_positionX, m_positionY, m_positionZ);                 AI_SendMoveToPacket(m_destinationX, m_destinationY, m_destinationZ, moveTime, m_moveSpeed == 7.0*0.001);                 m_moveTimer = UNIT_MOVEMENT_INTERPOLATE_INTERVAL; //                UpdateObject();             }         } // still moving     }     else if(m_creatureState == STOPPED && !m_moveTimer && m_nWaypoints > 1) //creature is stoped     {         int destpoint;         if(m_moveRandom)             destpoint = rand() % m_nWaypoints;         else         {             if (m_currentWaypoint == (m_nWaypoints-1))                 m_moveBackward = true;             if (m_currentWaypoint == 0)                 m_moveBackward = false;             if (!m_moveBackward) // going 0..n                 destpoint = ++m_currentWaypoint;             else                // going (n-1)..0                 destpoint = --m_currentWaypoint;         }         AI_MoveTo(m_waypoints[destpoint][0], m_waypoints[destpoint][1], m_waypoints[destpoint][2], m_moveRun);     } } // <WoW Chile Dev Team> Stop Change void Unit::Update( uint32 p_time ) 
  4. {     if (m_deathState == JUST_DIED)
  5. {         // remove me as an attacker from the AttackMap         m_attackers.clear();         m_deathState = CORPSE;     }     if (m_state & UF_TARGET_DIED)
  6. {
  7. if (m_Pet == false) AI_MoveTo(respawn_cord[0][0], respawn_cord[0][1], respawn_cord[0][2], true); //LINA, force mobs to return to there respawn         uint32 new_health = getUpdateValue(UNIT_FIELD_MAXHEALTH)*.8; if (new_health > getUpdateValue(UNIT_FIELD_HEALTH)) setUpdateValue(UNIT_FIELD_HEALTH, new_health);     }     if(m_attackTimer > 0)     {         if(p_time >= m_attackTimer)             m_attackTimer = 0;         else             m_attackTimer -= p_time;     }     if(m_deathTimer > 0)     {         if(p_time >= m_deathTimer)             m_deathTimer = 0;         else             m_deathTimer -= p_time;         if (m_deathTimer <= 0)         {             // time to respawn!             wowWData data;             data.clear();             data.Initialise(8, SMSG_DESTROY_OBJECT);             data << (uint32)m_guid[0] << m_guid[1]; //            SendMessageToSet(&data, false); world.SendUnitAreaMessage(&data, WorldServer::getSingletonPtr()->GetCreature(m_guid[0]));             m_respawnTimer = m_respawnDelay;             setDeathState(DEAD);             // <WoW Chile Dev Team> Start Change             //set to spawn point             m_positionX=respawn_cord[0][0];             m_positionY=respawn_cord[0][1];             m_positionZ=respawn_cord[0][2];             //printf("PT %f, %f, %f n", respawn_cord[0][0],respawn_cord[0][1],respawn_cord[0][2]);             //printf("ACT MOV respawn coords--> Mob ID: %i - Nodo:X (x:%i, y:%i, z:%i)n",m_guid[0],(int)creature_cord[0][0],(int)creature_cord[0][1],(int)creature_cord[0][2]);             // <WoW Chile Dev Team> Stop Change //            printf("Removing corpse...n");     std::list<Unit*>::iterator itr; //erase mobs attack list     for (itr = m_attackers.begin(); itr != m_attackers.end(); ++itr) itr = m_attackers.erase(itr);         }     }     else if (m_respawnTimer > 0)     {         if(p_time >= m_respawnTimer)             m_respawnTimer = 0;         else             m_respawnTimer -= p_time;         if(m_respawnTimer <= 0)         {             UpdateMask mask;             wowWData data;             WorldServer::getSingletonPtr()->mObjectMgr.SetCreateUnitBits(mask);         uint32 max_health = getUpdateValue(UNIT_FIELD_MAXHEALTH);     setUpdateValue(UNIT_FIELD_HEALTH, max_health);             CreateObject(&mask, &data, 0); //            SendMessageToSet(&data, false); world.SendUnitAreaMessage(&data, WorldServer::getSingletonPtr()->GetCreature(m_guid[0])); setDeathState(ALIVE); //            printf("Respawning...n");             // <WoW Chile Dev Team> Start Change             m_creatureState = STOPPED; //after respawn monster can move             // <WoW Chile Dev Team> Start Change         }     }     if(isAlive())     {         UpdateMobMovement( p_time );         AI_Update();     }     ////////////DAMAGE LASTS SOME TIME - changed by nothin//////////////////     if(m_damageDuration > 0) { if(m_damageTimer > 0) { if(p_time >= m_damageTimer) m_damageTimer = 0; else m_damageTimer -= p_time; }
  8. if(m_damageTimer == 0) { m_damageDuration--; m_damageTimer = 1000; uint32 health = getUpdateValue( UNIT_FIELD_HEALTH ); Unit* DamageAttacker;
  9. if(world.GetCharacter(m_Attacker)!=0) DamageAttacker = world.GetCharacter(m_Attacker); else DamageAttacker = world.GetCreature(m_Attacker); if(health-m_damage < 0 || health-m_damage > health) m_damageDuration = 0; else world.mCombatHandler.DealDamage(DamageAttacker, (Unit*)this, m_damage);  } }     ///////////////////////////////////////////////////////////////////////     ////////////DAMAGE ABSORB TIMER - changed by nothin////////////////// if(m_absorbDuration > 0) { m_absorb = 1;
  10. if(m_absorbTimer > 0) { if(p_time >= m_absorbTimer) m_absorbTimer = 0; else m_absorbTimer -= p_time; }
  11. if(m_absorbTimer == 0) { m_absorbDuration--; m_absorbTimer = 1000; printf("Absorb Time: %un", m_absorbDuration); }
  12. if(m_absorbDuration == 0)
  13. { m_absorb = 0; printf("OK time is up for now :(n"); } }     ///////////////////////////////////////////////////////////////////////     ////////////Aura TIMER - changed by nothin///////////////////////////// if(m_auraDuration > 0) { printf("ok we got aura on now :)n");
  14. if(m_auraTimer > 0) { if(p_time >= m_auraTimer) m_auraTimer = 0; else m_auraTimer -= p_time; }
  15. if(m_auraTimer == 0) { m_auraDuration--; m_auraTimer = 1000; printf("Aura Time: %un", m_auraDuration); }
  16. if(m_auraDuration == 0)
  17. { setUpdateValue(UNIT_FIELD_AURALEVELS + m_aura_found, 0); setUpdateValue(UNIT_FIELD_AURAAPPLICATIONS + m_aura_found, 0); setUpdateValue(UNIT_FIELD_AURA + m_aura_found*4 + m_aura_found2, 0); printf("OK time is up for now :(n"); } }     /////////////////////////////////////////////////////////////////////// ////////////MANA SHIELD TIMER - changed by nothin////////////////////// if(m_shieldDuration > 0) { m_shield = 1;
  18. if(m_shieldTimer > 0) { if(p_time >= m_shieldTimer) m_shieldTimer = 0; else m_shieldTimer -= p_time; }
  19. if(m_shieldTimer == 0) { m_shieldDuration--; m_shieldTimer = 1000; printf("Shield Time: %un", m_shieldDuration); }
  20. if(m_shieldDuration == 0)
  21. { m_shield = 0; printf("OK shield time is up for now :(n"); } } //////////////FOLLOW CODE////////////////////////////////////////////// if(m_follow)
  22. { if(m_creatureState != ATTACKING)
  23. {
  24. uint32 summID = getUpdateValue(UNIT_FIELD_SUMMONEDBY);
  25. Character * pChar = world.GetCharacter(summID);
  26. if(pChar)
  27. { //printf("followingn"); float dx = pChar->getPositionX(); float dy = pChar->getPositionY(); float dz = pChar->getPositionZ(); AI_MoveTo(dx, dy, dz, true);
  28. } } //m_creatureState = MOVING; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // PET AGGRESSIVE MODE ATTACKS CREEPS IN RANGE(STATIC 20) if(m_pet_state == 2)
  29. { if(m_creatureState != ATTACKING)
  30. { Unit * pUnit = world.GetClosestUnit(this); if(pUnit)
  31. { if( closest_dist < 20)
  32. { AI_MoveTo(pUnit->getPositionX(),pUnit->getPositionY(),pUnit->getPositionZ(), true); AI_AttackReaction(pUnit,1); AI_Update();
  33. } } } } // AGGRESSIVE MOB CODE BY NOTHIN IT ATTACKS ENEMYS IF THEY GET IN RANGE ( CURRENTLY STATIC 20) SET m_aggressive to 1 to activate if( m_aggressive == 1 || m_aggressive == 3 )
  34. {
  35. if(m_creatureState != ATTACKING)
  36. {
  37. Character * pChar = world.GetClosestChar(this);
  38. if(pChar)
  39. {
  40. if( closest_dist < 10)
  41. {
  42. AI_MoveTo(pChar->getPositionX(),pChar->getPositionY(),pChar->getPositionZ(), true);
  43. AI_AttackReaction(pChar,1);
  44. AI_Update();
  45. }
  46. }
  47. }
  48. }     // Clear the NPC flags bit so it doesn't get auto- updated each frame.  NPC flags are set per player and this would ruin is     unsetUpdateMaskBit(UNIT_NPC_FLAGS);     UpdateObject(); } void Unit::Create( uint32 guidlow ) {     Object::Create(guidlow);     m_guid[1] = 0xF0001000; m_kguid = 0; } void Unit::Create (uint32 guidlow, uint8* creature_name, float x, float y, float z, float ang) {     strcpy((char*)m_creatureName, (char*)creature_name);     Object::Create(guidlow, x,y,z,ang);     m_guid[1] = 0xF0001000; m_kguid = 0; } void Unit::BuildUpdateBlock(UpdateMask *updateMask, uint8 *data, int *length) {     m_updateValues[ UNIT_NPC_EMOTESTATE ] = m_emoteState;     Object::BuildUpdateBlock(updateMask, data, length); } /////////////////////////////////// QUESTS //////////////////////////////////////////// uint32 Unit::getQuestStatus(Character *pPlayer) {     for( std::list<uint32>::iterator i = mQuestIds.begin( ); i != mQuestIds.end( ); ++ i ) {         uint32 quest_id = *i;         uint32 status = pPlayer->getQuestStatus(quest_id);         if (status == 0 || status == QUEST_STATUS_UNAVAILABLE) {             Quest *pQuest = world.getQuest(quest_id);             // if 0, then the player has never been offered this before             // Add it to the player with a new quest value of 4             if (pQuest->m_requiredLevel >= pPlayer->getUpdateValue(UNIT_FIELD_LEVEL))                 status = pPlayer->addNewQuest(quest_id,2);             else                 status = pPlayer->addNewQuest(quest_id);         }         if (status != QUEST_STATUS_COMPLETE)             return status;     }     return 0; } uint32 Unit::getCurrentQuest(Character *pPlayer) {     for( std::list<uint32>::iterator i = mQuestIds.begin( ); i != mQuestIds.end( ); ++ i ) {         uint32 quest_id = *i;         uint32 status = pPlayer->getQuestStatus(quest_id);         if (status == 0)             // if 0, then the player has never been offered this before             // Add it to the player with a new quest value of 4             status = pPlayer->addNewQuest(quest_id);         if (status != QUEST_STATUS_COMPLETE) // if quest is not completed yet, then this is the active quest to return             return quest_id;     }     return 0; } char* Unit::getQuestTitle(uint32 quest_id) {     Quest *pQuest = world.getQuest(quest_id);     return (char*)pQuest->m_title.c_str(); } char* Unit::getQuestDetails(uint32 quest_id) {     Quest *pQuest = world.getQuest(quest_id);     return (char*)pQuest->m_details.c_str(); } char* Unit::getQuestObjectives(uint32 quest_id) {     Quest *pQuest = world.getQuest(quest_id);     return (char*)pQuest->m_objectives.c_str(); } char* Unit::getQuestCompleteText(uint32 quest_id) {     Quest *pQuest = world.getQuest(quest_id);     return (char*)pQuest->m_completedText.c_str(); } char* Unit::getQuestIncompleteText(uint32 quest_id) {     Quest *pQuest = world.getQuest(quest_id);     return (char*)pQuest->m_incompleteText.c_str(); } bool Unit::hasQuest(uint32 quest_id) {     for( std::list<uint32>::iterator i = mQuestIds.begin( ); i != mQuestIds.end( ); ++ i ) {         if (*i == quest_id)             return true;     }     return false; } /* void Unit::SendCreateWithTempNpcFlags(UpdateMask *updateMask, GameClient *pClient) {     if (m_deathState == DEAD) return;     // for each quest this creature has,     //   if player->getStatus != 0     //     if quest->targetGuid != 0 && quest->targetGuid != thisCreature->guid and status==3     //       thisCreature->npcflags = 0     //     else if quest->targetGuid == thisCreature->guid && quest->status == 1||3     //       thisCreature->npc_flags = 2     Character *pPlayer = pClient->getCurrentChar();     wowWData data;     for( std::list<uint32>::iterator i = mQuestIds.begin( ); i != mQuestIds.end( ); ++ i ) {         uint32 quest_id = *i;         uint32 status = pPlayer->getQuestStatus(quest_id);         Quest *pQuest = world.getQuest(quest_id);         if (status != 0)         {             if (pQuest->m_targetGuid != 0 && pQuest->m_targetGuid != m_guid[0] && status==QUEST_STATUS_INCOMPLETE)             {                 // If this is a talk to quest, and the target NPC is not THIS npc, and the status is Incomplete,...                 // Set NPC_FLAGS to 0 so it doesn't offer a quest to this player                 setUpdateValue(UNIT_NPC_FLAGS, 0);                 CreateObject(updateMask, &data, 0);                 pClient->SendMsg(&data);                 setUpdateValue(UNIT_NPC_FLAGS, 2);                 return;             }             else if (pQuest->m_targetGuid == m_guid[0] && (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_INCOMPLETE))             {                 // If this creature has a Talk To quest, and it is the target of the quest, and the quest is either complete or currently                 // underway, then allow this creature to have quest flags                 setUpdateValue(UNIT_NPC_FLAGS, 2);                 CreateObject(updateMask, &data, 0);                 pClient->SendMsg(&data);                 setUpdateValue(UNIT_NPC_FLAGS, 0);                 return;             }             else if (pQuest->m_targetGuid == m_guid[0] && status == QUEST_STATUS_AVAILABLE)             {                 // If this Creature has a Talk to quest, and is the target of the quest, and the quest is currently available,                 // Remove Questgiver flags                 setUpdateValue(UNIT_NPC_FLAGS, 0);                 CreateObject(updateMask, &data, 0);                 pClient->SendMsg(&data);                 setUpdateValue(UNIT_NPC_FLAGS, 2);                 return;             }         }     }     CreateObject(updateMask, &data, 0);     pClient->SendMsg(&data); } */ int Unit::CheckQuestgiverFlag(Character *pPlayer, UpdateMask *unitMask, wowWData * data) {     for( std::list<uint32>::iterator i = mQuestIds.begin( ); i != mQuestIds.end( ); ++ i )     {         uint32 quest_id = *i;         uint32 status = pPlayer->getQuestStatus(quest_id);         Quest *pQuest = world.getQuest(quest_id); //        if (status != 0) //        {             if (pQuest->m_targetGuid != 0 && pQuest->m_targetGuid != m_guid[0] && status==QUEST_STATUS_INCOMPLETE)             {                 // If this is a talk to quest, and the target NPC is not THIS npc, and the status is Incomplete,...                 // Set NPC_FLAGS to 0 so it doesn't offer a quest to this player                 setUpdateValue(UNIT_NPC_FLAGS, 0);                 CreateObject(unitMask, data, 0);                 setUpdateValue(UNIT_NPC_FLAGS, 2);                 return 1;             }             else if (pQuest->m_targetGuid == m_guid[0] && (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_INCOMPLETE))             {                 // If this creature has a Talk To quest, and it is the target of the quest, and the quest is either complete or currently                 // underway, then allow this creature to have quest flags                 setUpdateValue(UNIT_NPC_FLAGS, 2);                 CreateObject(unitMask, data, 0);                 setUpdateValue(UNIT_NPC_FLAGS, 0);                 return 1;             }             else if (pQuest->m_targetGuid == m_guid[0] && (status == QUEST_STATUS_AVAILABLE || status == 0))             {                 // If this Creature has a Talk to quest, and is the target of the quest, and the quest is currently available,                 // Remove Questgiver flags                 setUpdateValue(UNIT_NPC_FLAGS, 0);                 CreateObject(unitMask, data, 0);                 setUpdateValue(UNIT_NPC_FLAGS, 2);                 return 1;             } //        }     }     return 0; } void Unit::setAttackTimer() {     m_attackTimer = getUpdateValue(UNIT_FIELD_BASEATTACKTIME); } //////////////////////////////////////////////////////////////////////////////// //  Fill the object's Update Values from a space deliminated list of values. //////////////////////////////////////////////////////////////////////////////// void Unit::LoadUpdateValues(uint8* data) {     char* next = strtok((char*)data, " ");     m_updateValues[0] = atol(next);     for( uint16 index = 1; index < UNIT_END; index++)     {         char* next = strtok(NULL, " ");         m_updateValues[index] = atol(next);     } //printf("Creature id: %u Updated!n", m_guid[0]); } /////////////////////////////////////////////////////////////////////////////////////////////////// //    Looting /////////////////////////////////////////////////////////////////////////////////////////////////// void Unit::generateLoot() {     int retryCount = 0;     itemcount = 0;     memset(item_list, 0, 8*128);     int itemCount,i,randItem,found = 0,tempLevel;     this->m_lootMoney = this->getLevel() * (rand()%5 + 1);     itemCount = (this->getLevel() + rand()%7) / 5;     if (itemCount > 3)         itemCount = 3;     //itemCount = 2; //temp if (rand()%100 > 35)
  49. itemcount = 0;
  50.     for(i = 0; i < itemCount; i++) {         //This is an ugly way to do it         //I may implement a 'baskets' system later - tmm`         retryCount = 0;         while(!found && (retryCount <= 150)) {             retryCount++;             randItem = rand()%10000;             if (world.GetItem(randItem) != NULL) {                 tempLevel = world.GetItem(randItem)->ItemLevel; if (tempLevel < this->getLevel() +2) { //&& (tempLevel > this->getLevel() -2)) { //                    if ((world.GetItem(randItem)->Class == 2) || (world.GetItem(randItem)->Class == 4)) { if (world.GetItem(randItem)->Sellprice)                         found = 1; //                    }                 }             }         }         if (found == 0)         {             //this is getting dangerous, we don't want an infinite loop :/             //lets just not give him any items             itemcount = 0;             return;         }         this->addItem(randItem,1);         found = 0;     } } /////////////////////////////////////////////////////////////////////////////////////////////////// //    Unit AI /////////////////////////////////////////////////////////////////////////////////////////////////// // This Unit has just been attacked by someone // Reaction:  Add this Unit to the list of current attackers void Unit::AI_AttackReaction(Unit *pAttacker, uint32 damage_dealt) {     std::list<Unit*>::iterator itr;     for (itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)         if (*itr == pAttacker)
  51. {             // Attacker already in list             return;         }     m_attackers.push_back(pAttacker); } void Unit::AI_Update() {     // Cycle through attackers     // If one is out of range, remove from the map     std::list<Unit*>::iterator itr;     for (itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)     {         Unit *pVictim = *itr;         if (!pVictim || !pVictim->isAlive())
  52. {
  53. if (m_Pet == false) AI_MoveTo(respawn_cord[0][0], respawn_cord[0][1], respawn_cord[0][2], true); //LINA, force mobs to return to there respawn
  54.         uint32 max_health = getUpdateValue(UNIT_FIELD_MAXHEALTH)*.8;     setUpdateValue(UNIT_FIELD_HEALTH, max_health); pVictim->setCombat(false); itr = m_attackers.erase(itr);             continue;         }
  55. //LINA TEST
  56. if (pVictim->getGUIDHigh() == 0 ) //if victim was a player
  57. {
  58. if(!((Character*)pVictim)->pClient->IsInWorld()) //test if in world
  59. {
  60. if (m_Pet == false) AI_MoveTo(respawn_cord[0][0], respawn_cord[0][1], respawn_cord[0][2], true); //LINA, force mobs to return to there respawn
  61.         uint32 max_health = getUpdateValue(UNIT_FIELD_MAXHEALTH)*.8;         setUpdateValue(UNIT_FIELD_HEALTH, max_health); pVictim->setCombat(false); itr = m_attackers.erase(itr);
  62. continue;
  63. }
  64. }         float dx, dy, dz;         dx = pVictim->getPositionX() - getPositionX();         dy = pVictim->getPositionY() - getPositionY();         dz = pVictim->getPositionZ() - getPositionZ();         float length = sqrt((dx*dx) + (dy*dy) + (dz*dz));         float reach = getUpdateFloatValue(UNIT_FIELD_COMBATREACH);         float radius = getUpdateFloatValue(UNIT_FIELD_BOUNDINGRADIUS);         if (length > 30.0f) // must be greater then the max range of spells         {             // stop attacking because the target is too far
  65. if (m_Pet == false) AI_MoveTo(respawn_cord[0][0], respawn_cord[0][1], respawn_cord[0][2], true); //LINA, force mobs to return to there respawn         uint32 max_health = getUpdateValue(UNIT_FIELD_MAXHEALTH)*.8;     setUpdateValue(UNIT_FIELD_HEALTH, max_health); pVictim->setCombat(false); itr = m_attackers.erase(itr);             continue;         }         if (length > reach + radius)         {             float q = (length - radius)/length;             float x = (m_positionX + pVictim->getPositionX()*q)/(1+q);             float y = (m_positionY + pVictim->getPositionY()*q)/(1+q);             float z = (m_positionZ + pVictim->getPositionZ()*q)/(1+q);             AI_MoveTo(x, y, z, true);         }         else         {             AI_ChangeState(ATTACKING);             if (isAttackReady())             {                 world.mCombatHandler.AttackerStateUpdate((Unit*)this, pVictim, 0);                 setAttackTimer();             }         }
  66. //lina
  67. if(m_creatureState == ATTACKING )
  68. {
  69. if(m_aggressive==2 || m_aggressive==3)
  70. {
  71. world.setAttackGroupUnit(this, pVictim);
  72. }
  73. }     } } void Unit::AI_SendMoveToPacket(float x, float y, float z, uint32 time, bool run) {     wowWData data;     data.Initialise(49, SMSG_MONSTER_MOVE);     data << m_guid[0] << m_guid[1];     data << getPositionX() << getPositionY() << getPositionZ() << getOrientation();     data << uint8(0);     data << uint32(run ? 0x00000100 : 0x00000000);     data << time;     data << uint32(1);     data << x << y << z;     //world.SendGlobalMessage(&data); world.SendUnitAreaMessage(&data, WorldServer::getSingletonPtr()->GetCreature(m_guid[0])); } void Unit::AI_MoveTo(float x, float y, float z, bool run) {     float dx = x - m_positionX;     float dy = y - m_positionY;     float dz = z - m_positionZ;     float distance = sqrt((dx*dx) + (dy*dy) + (dz*dz));     if(!distance)         return;     m_destinationX = x;     m_destinationY = y;     m_destinationZ = z;     if(m_creatureState != MOVING)     {         m_creatureState = MOVING;         if(!run)             m_moveSpeed = float(2.5*0.001);         else             m_moveSpeed = float(7.0*0.001);         uint32 moveTime = (uint32) (distance / m_moveSpeed);         AI_SendMoveToPacket(x, y, z, moveTime, run);         //uint8 pAnnounce[256];         //sprintf((char*)pAnnounce, "%i started moving from %f %f %f to %f %f %f should get there in %i msecs, distance is %fn",         //    m_guid[0], m_positionX, m_positionY, m_positionZ,         //    m_destinationX, m_destinationY, m_destinationZ, moveTime, distance);         //WorldServer::getSingleton().SendWorldText((uint8*)pAnnounce); // send message         m_moveTimer = UNIT_MOVEMENT_INTERPOLATE_INTERVAL; // update every 300 msecs         UpdateObject();     } } bool Unit::addWaypoint(float x, float y, float z) {     if(m_nWaypoints+1 >= MAX_CREATURE_WAYPOINTS)         return false;     m_waypoints[m_nWaypoints][0] = x;     m_waypoints[m_nWaypoints][1] = y;     m_waypoints[m_nWaypoints][2] = z;     m_nWaypoints++;     return true; } bool Unit::canReachWithAttack(Unit *pVictim) {     float dx, dy, dz;     float reach = getUpdateFloatValue(UNIT_FIELD_COMBATREACH);     float radius = getUpdateFloatValue(UNIT_FIELD_BOUNDINGRADIUS);     dx = m_positionX - pVictim->getPositionX();     dy = m_positionY - pVictim->getPositionY();     dz = m_positionZ - pVictim->getPositionZ();     float length = sqrt((dx*dx) + (dy*dy) + (dz*dz));     if (length > reach + radius)         return false;     return true; } void Unit::setCreatureName(char* CreatureName) {     strcpy((char*)m_creatureName, CreatureName); }