void Pet::InitializeMe(bool first) { // set up ai and shit GetAIInterface()->Init(this,AITYPE_PET,MOVEMENTTYPE_NONE,m_Owner); GetAIInterface()->SetUnitToFollow(m_Owner); GetAIInterface()->SetFollowDistance(3.0f); SetCreatureName(objmgr.GetCreatureName(GetEntry())); m_Owner->SetSummon(this); m_Owner->SetUInt64Value(UNIT_FIELD_SUMMON, this->GetGUID()); SetUInt32Value(UNIT_FIELD_PETNUMBER, GetGUIDLow()); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, (uint32)time(NULL)); bHasLoyalty = m_Owner->getClass() == HUNTER ? true : false; // Load our spells if(Summon) { SetDefaultSpells(); } else { // Pull from database... :/ QueryResult * query = sDatabase.Query("SELECT * FROM playerpetspells WHERE ownerguid=%u and petnumber=%u", m_Owner->GetGUIDLow(), m_PetNumber); if(query) { do { Field * f = query->Fetch(); SpellEntry* spell = sSpellStore.LookupEntry(f[2].GetUInt32()); uint16 flags = f[3].GetUInt16(); mSpells.insert ( make_pair( spell, flags ) ); } while(query->NextRow()); } delete query; } SetPetDiet(); _setFaction(); m_State = 1; // dont set agro on spawn if(first) { // Set up default actionbar SetDefaultActionbar(); } InitializeSpells(); AddToWorld(); // Add into the world sEventMgr.AddEvent(this, &Pet::Update, (uint32)100, EVENT_PET_UPDATE, 100, 0); // set to active if(!bExpires) UpdatePetInfo(false); }
void Pet::RemoveSpell(SpellEntry * sp) { mSpells.erase(sp); map<uint32, AI_Spell*>::iterator itr = m_AISpellStore.find(sp->Id); if(itr != m_AISpellStore.end()) { delete itr->second; if(GetAIInterface()->GetDefaultSpell() == itr->second) GetAIInterface()->SetDefaultSpell(0); m_AISpellStore.erase(itr); } }
Pet::~Pet() { for(std::map<uint32, AI_Spell*>::iterator itr = m_AISpellStore.begin(); itr != m_AISpellStore.end(); ++itr) delete itr->second; GetAIInterface()->SetDefaultSpell(NULL); sEventMgr.RemoveEvents(this); if(IsInWorld()) static_cast<Pet*>(this)->Remove(); }
// Generates 3 random waypoints around the NPC void Creature::SetGuardWaypoints() { if(!GetMapMgr()) return; if(!GetCreatureName()) return; GetAIInterface()->setMoveType(1); for(int i = 1; i <= 4; i++) { float ang = rand()/100.0f; float ran = (rand()%(100))/10.0f; while(ran < 1) ran = (rand()%(100))/10.0f; WayPoint * wp = new WayPoint; wp->id = i; wp->flags = 0; wp->waittime = 800; /* these guards are antsy :P */ wp->x = GetSpawnX()+ran*sin(ang); wp->y = GetSpawnY()+ran*cos(ang); #ifdef COLLISION wp->z = CollideInterface.GetHeight(m_mapId, wp->x, wp->y, m_spawnLocation.z + 2.0f); if( wp->z == NO_WMO_HEIGHT ) wp->z = m_mapMgr->GetLandHeight(wp->x, wp->y); if( fabs( wp->z - m_spawnLocation.z ) > 10.0f ) wp->z = m_spawnLocation.z; #else wp->z = GetMapMgr()->GetLandHeight(wp->x, wp->y); #endif // COLLISION wp->o = 0; wp->backwardemoteid = 0; wp->backwardemoteoneshot = 0; wp->forwardemoteid = 0; wp->forwardemoteoneshot = 0; wp->backwardskinid = m_uint32Values[UNIT_FIELD_NATIVEDISPLAYID]; wp->forwardskinid = m_uint32Values[UNIT_FIELD_NATIVEDISPLAYID]; GetAIInterface()->addWayPoint(wp); } }
void Creature::setDeathState(DeathState s) { if(s == JUST_DIED) { GetAIInterface()->SetUnitToFollow(NULL); m_deathState = CORPSE; m_corpseEvent=true; /*sEventMgr.AddEvent(this, &Creature::OnRemoveCorpse, EVENT_CREATURE_REMOVE_CORPSE, 180000, 1,EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);*/ if(m_enslaveSpell) RemoveEnslave(); if(m_currentSpell) m_currentSpell->cancel(); }else m_deathState = s; }
void Creature::EnslaveExpire() { m_enslaveCount++; Player *caster = objmgr.GetPlayer(GetUInt32Value(UNIT_FIELD_CHARMEDBY)); if(caster) { caster->SetUInt64Value(UNIT_FIELD_CHARM, 0); caster->SetUInt64Value(UNIT_FIELD_SUMMON, 0); WorldPacket data(8); data.Initialize(SMSG_PET_SPELLS); data << uint64(0); caster->GetSession()->SendPacket(&data); } SetUInt64Value(UNIT_FIELD_CHARMEDBY, 0); SetUInt64Value(UNIT_FIELD_SUMMONEDBY, 0); SetIsPet(false); m_walkSpeed = m_base_walkSpeed; m_runSpeed = m_base_runSpeed; switch(GetCreatureName()->Type) { case DEMON: SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, 90); break; default: SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, 954); break; }; _setFaction(); GetAIInterface()->Init(((Unit *)this), AITYPE_AGRO, MOVEMENTTYPE_NONE); // Update InRangeSet UpdateOppFactionSet(); }
void Creature::OnRespawn(MapMgr * m) { sLog.outDetail("Respawning "I64FMT"...", GetGUID()); SetUInt32Value(UNIT_FIELD_HEALTH, GetUInt32Value(UNIT_FIELD_MAXHEALTH)); SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); // not tagging shiat if(proto && m_spawn) { SetUInt32Value(UNIT_NPC_FLAGS, proto->NPCFLags); SetUInt32Value(UNIT_NPC_EMOTESTATE, m_spawn->emote_state); } RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); Skinned = false; Tagged = false; TaggerGuid = 0; m_lootMethod = -1; /* creature death state */ if(proto && proto->death_state == 1) { uint32 newhealth = m_uint32Values[UNIT_FIELD_HEALTH] / 100; if(!newhealth) newhealth = 1; SetUInt32Value(UNIT_FIELD_HEALTH, 1); m_limbostate = true; bInvincible = true; SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DEAD); } //empty loot loot.items.clear(); setDeathState(ALIVE); GetAIInterface()->StopMovement(0); // after respawn monster can move m_PickPocketed = false; PushToWorld(m); }
bool Creature::Load(CreatureSpawn *spawn, uint32 mode, MapInfo *info) { m_spawn = spawn; proto = CreatureProtoStorage.LookupEntry(spawn->entry); if(!proto) return false; creature_info = CreatureNameStorage.LookupEntry(spawn->entry); if(!creature_info) return false; spawnid = spawn->id; m_walkSpeed = m_base_walkSpeed = proto->walk_speed; //set speeds m_runSpeed = m_base_runSpeed = proto->run_speed; //set speeds m_flySpeed = proto->fly_speed; //Set fields SetUInt32Value(OBJECT_FIELD_ENTRY,proto->Id); SetFloatValue(OBJECT_FIELD_SCALE_X,proto->Scale); //SetUInt32Value(UNIT_FIELD_HEALTH, (mode ? long2int32(proto->Health * 1.5) : proto->Health)); //SetUInt32Value(UNIT_FIELD_BASE_HEALTH, (mode ? long2int32(proto->Health * 1.5) : proto->Health)); //SetUInt32Value(UNIT_FIELD_MAXHEALTH, (mode ? long2int32(proto->Health * 1.5) : proto->Health)); uint32 health = proto->MinHealth + RandomUInt(proto->MaxHealth - proto->MinHealth); if(mode) health = long2int32(double(health) * 1.5); SetUInt32Value(UNIT_FIELD_HEALTH, health); SetUInt32Value(UNIT_FIELD_MAXHEALTH, health); SetUInt32Value(UNIT_FIELD_BASE_HEALTH, health); SetUInt32Value(UNIT_FIELD_POWER1,proto->Mana); SetUInt32Value(UNIT_FIELD_MAXPOWER1,proto->Mana); SetUInt32Value(UNIT_FIELD_BASE_MANA,proto->Mana); // Whee, thank you blizz, I love patch 2.2! Later on, we can randomize male/female mobs! xD // Determine gender (for voices) //if(spawn->displayid != creature_info->Male_DisplayID) // setGender(1); // Female uint32 model; uint32 gender = creature_info->GenerateModelId(&model); setGender(gender); SetUInt32Value(UNIT_FIELD_DISPLAYID,model); SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID,model); SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,proto->MountedDisplayID); //SetUInt32Value(UNIT_FIELD_LEVEL, (mode ? proto->Level + (info ? info->lvl_mod_a : 0) : proto->Level)); SetUInt32Value(UNIT_FIELD_LEVEL, proto->MinLevel + (RandomUInt(proto->MaxLevel - proto->MinLevel))); if(mode && info) ModUnsigned32Value(UNIT_FIELD_LEVEL, info->lvl_mod_a); for(uint32 i = 0; i < 7; ++i) SetUInt32Value(UNIT_FIELD_RESISTANCES+i,proto->Resistances[i]); SetUInt32Value(UNIT_FIELD_BASEATTACKTIME,proto->AttackTime); SetFloatValue(UNIT_FIELD_MINDAMAGE, (mode ? proto->MinDamage * 1.5f : proto->MinDamage)); SetFloatValue(UNIT_FIELD_MAXDAMAGE, (mode ? proto->MaxDamage * 1.5f : proto->MaxDamage)); SetUInt32Value(UNIT_FIELD_RANGEDATTACKTIME,proto->RangedAttackTime); SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,proto->RangedMinDamage); SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,proto->RangedMaxDamage); SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, proto->Item1SlotDisplay); SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, proto->Item2SlotDisplay); SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, proto->Item3SlotDisplay); SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, proto->Item1Info1); SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_01, proto->Item1Info2); SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_02, proto->Item2Info1); SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_03, proto->Item2Info2); SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_04, proto->Item3Info1); SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_05, proto->Item3Info2); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, spawn->factionid); SetUInt32Value(UNIT_FIELD_FLAGS, spawn->flags); SetUInt32Value(UNIT_NPC_EMOTESTATE, spawn->emote_state); SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, proto->BoundingRadius); SetFloatValue(UNIT_FIELD_COMBATREACH, proto->CombatReach); original_emotestate = spawn->emote_state; // set position m_position.ChangeCoords( spawn->x, spawn->y, spawn->z, spawn->o ); m_spawnLocation.ChangeCoords(spawn->x, spawn->y, spawn->z, spawn->o); m_aiInterface->setMoveType(spawn->movetype); m_aiInterface->m_waypoints = objmgr.GetWayPointMap(spawn->id); m_faction = dbcFactionTemplate.LookupEntry(spawn->factionid); if(m_faction) { m_factionDBC = dbcFaction.LookupEntry(m_faction->Faction); // not a neutral creature if(!(m_factionDBC->RepListId == -1 && m_faction->HostileMask == 0 && m_faction->FriendlyMask == 0)) { GetAIInterface()->m_canCallForHelp = true; } } //SETUP NPC FLAGS SetUInt32Value(UNIT_NPC_FLAGS,proto->NPCFLags); if ( HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ) ) m_SellItems = objmgr.GetVendorList(GetEntry()); if ( HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER ) ) _LoadQuests(); if ( HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TAXIVENDOR) ) m_TaxiNode = sTaxiMgr.GetNearestTaxiNode( m_position.x, m_position.y, m_position.z, GetMapId() ); if ( HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER) || HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER_PROF)) mTrainer = objmgr.GetTrainer(GetEntry()); if ( HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER ) ) auctionHouse = sAuctionMgr.GetAuctionHouse(GetEntry()); //NPC FLAGS m_aiInterface->m_waypoints=objmgr.GetWayPointMap(spawn->id); //load resistances for(uint32 x=0;x<7;x++) BaseResistance[x]=GetUInt32Value(UNIT_FIELD_RESISTANCES+x); for(uint32 x=0;x<5;x++) BaseStats[x]=GetUInt32Value(UNIT_FIELD_STAT0+x); BaseDamage[0]=GetFloatValue(UNIT_FIELD_MINDAMAGE); BaseDamage[1]=GetFloatValue(UNIT_FIELD_MAXDAMAGE); BaseOffhandDamage[0]=GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE); BaseOffhandDamage[1]=GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE); BaseRangedDamage[0]=GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE); BaseRangedDamage[1]=GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE); BaseAttackType=proto->AttackType; SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // better set this one SetUInt32Value(UNIT_FIELD_BYTES_0, spawn->bytes); SetUInt32Value(UNIT_FIELD_BYTES_2, spawn->bytes2); ////////////AI // kek for(list<AI_Spell*>::iterator itr = proto->spells.begin(); itr != proto->spells.end(); ++itr) { m_aiInterface->addSpellToList(*itr); } //m_aiInterface->m_canCallForHelp = proto->m_canCallForHelp; //m_aiInterface->m_CallForHelpHealth = proto->m_callForHelpHealth; m_aiInterface->m_canFlee = proto->m_canFlee; m_aiInterface->m_FleeHealth = proto->m_fleeHealth; m_aiInterface->m_FleeDuration = proto->m_fleeDuration; //these fields are always 0 in db GetAIInterface()->setMoveType(0); GetAIInterface()->setMoveRunFlag(0); // load formation data if( spawn->form != NULL ) { m_aiInterface->m_formationLinkSqlId = spawn->form->fol; m_aiInterface->m_formationFollowDistance = spawn->form->dist; m_aiInterface->m_formationFollowAngle = spawn->form->ang; } else { m_aiInterface->m_formationLinkSqlId = 0; m_aiInterface->m_formationFollowDistance = 0; m_aiInterface->m_formationFollowAngle = 0; } //////////////AI myFamily = dbcCreatureFamily.LookupEntry(creature_info->Family); // PLACE FOR DIRTY FIX BASTARDS // HACK! set call for help on civ health @ 100% if(creature_info->Civilian >= 1) m_aiInterface->m_CallForHelpHealth = 100; //HACK! if(m_uint32Values[UNIT_FIELD_DISPLAYID] == 17743 || m_uint32Values[UNIT_FIELD_DISPLAYID] == 20242 || m_uint32Values[UNIT_FIELD_DISPLAYID] == 15435 || (creature_info->Family == UNIT_TYPE_MISC)) { m_useAI = false; } /* more hacks! */ if(proto->Mana != 0) SetPowerType(POWER_TYPE_MANA); else SetPowerType(0); has_combat_text = objmgr.HasMonsterSay(GetEntry(), MONSTER_SAY_EVENT_ENTER_COMBAT); has_waypoint_text = objmgr.HasMonsterSay(GetEntry(), MONSTER_SAY_EVENT_RANDOM_WAYPOINT); m_aiInterface->m_isGuard = isGuard(GetEntry()); m_aiInterface->getMoveFlags(); /* creature death state */ if(proto->death_state == 1) { uint32 newhealth = m_uint32Values[UNIT_FIELD_HEALTH] / 100; if(!newhealth) newhealth = 1; SetUInt32Value(UNIT_FIELD_HEALTH, 1); m_limbostate = true; bInvincible = true; SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DEAD); } m_invisFlag = proto->invisibility_type; if( spawn->stand_state ) SetStandState( (uint8)spawn->stand_state ); return true; }
void Creature::OnRespawn(MapMgr * m) { if(m_noRespawn) return; InstanceBossInfoMap *bossInfoMap = objmgr.m_InstanceBossInfoMap[m->GetMapId()]; if(bossInfoMap != NULL) { bool skip = false; Instance *pInstance = m->pInstance; for(std::set<uint32>::iterator killedNpc = pInstance->m_killedNpcs.begin(); killedNpc != pInstance->m_killedNpcs.end(); ++killedNpc) { // Is killed boss? if((*killedNpc) == this->creature_info->Id) { skip = true; break; } // Is add from killed boss? InstanceBossInfoMap::const_iterator bossInfo = bossInfoMap->find((*killedNpc)); if(bossInfo != bossInfoMap->end() && bossInfo->second->trash.find(this->spawnid) != bossInfo->second->trash.end()) { skip = true; break; } } if(skip) { this->m_noRespawn = true; this->DeleteMe(); return; } } sLog.outDetail("Respawning "I64FMT"...", GetGUID()); SetUInt32Value(UNIT_FIELD_HEALTH, GetUInt32Value(UNIT_FIELD_MAXHEALTH)); SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); // not tagging shiat if(proto && m_spawn) { SetUInt32Value(UNIT_NPC_FLAGS, proto->NPCFLags); SetUInt32Value(UNIT_NPC_EMOTESTATE, m_spawn->emote_state); } RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); Skinned = false; Tagged = false; TaggerGuid = 0; m_lootMethod = -1; /* creature death state */ if(proto && proto->death_state == 1) { uint32 newhealth = m_uint32Values[UNIT_FIELD_HEALTH] / 100; if(!newhealth) newhealth = 1; SetUInt32Value(UNIT_FIELD_HEALTH, 1); m_limbostate = true; bInvincible = true; SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DEAD); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, 35); } //empty loot loot.items.clear(); setDeathState(ALIVE); GetAIInterface()->StopMovement(0); // after respawn monster can move GetAIInterface()->m_canMove = true; m_PickPocketed = false; PushToWorld(m); }