void UpdateAI(const uint32 uiDiff) { npc_escortAI::UpdateAI(uiDiff); if (HasEscortState(STATE_ESCORT_PAUSED)) { if (m_uiWave_Timer <= uiDiff) { switch (m_uiWave) { case 0: DoScriptText(SAY_BREAKOUT3, me); SummonAcolyte(3); m_uiWave_Timer = 20000; break; case 1: DoScriptText(SAY_BREAKOUT4, me); SummonAcolyte(3); m_uiWave_Timer = 20000; break; case 2: DoScriptText(SAY_BREAKOUT5, me); SummonAcolyte(4); m_uiWave_Timer = 20000; break; case 3: DoScriptText(SAY_BREAKOUT6, me); me->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329f, -6045.818f, 127.583f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); m_uiWave_Timer = 1000; break; case 4: { Creature* temp = Unit::GetCreature(*me, m_uiValrothGUID); if (!temp || !temp->isAlive()) { DoScriptText(SAY_BREAKOUT8, me); m_uiWave_Timer = 5000; } else { m_uiWave_Timer = 2500; return; //return, we don't want m_uiWave to increment now } break; } case 5: DoScriptText(SAY_BREAKOUT9, me); me->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); // i do not know why the armor will also be removed m_uiWave_Timer = 2500; break; case 6: DoScriptText(SAY_BREAKOUT10, me); SetEscortPaused(false); break; } ++m_uiWave; } else m_uiWave_Timer -= uiDiff; } }
void UpdateAI(const uint32 diff) { if (!StartCombat) return; if (IsBanished) { // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check if (me->getThreatManager().getThreatList().size() < 2) { EnterEvadeMode(); return; } if (DefenderTimer <= diff) { uint32 ran = rand()%2; Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); if (Defender) { Defender->RemoveUnitMovementFlag(MOVEFLAG_WALK_MODE); bool move = true; if (AkamaGUID) { if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) { float x, y, z; Akama->GetPosition(x,y,z); // They move towards AKama Defender->GetMotionMaster()->MovePoint(0, x, y, z); Defender->AI()->AttackStart(Akama); } else move = false; } else move = false; if (!move) Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); } DefenderTimer = 15000; } else DefenderTimer -= diff; if (SummonTimer <= diff) { SummonCreature(); SummonTimer = 35000; } else SummonTimer -= diff; if (DeathCount >= 6) { if (AkamaGUID) { Creature* Akama = Unit::GetCreature((*me), AkamaGUID); if (Akama && Akama->isAlive()) { IsBanished = false; me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveChase(Akama); Akama->GetMotionMaster()->Clear(); // Shade should move to Akama, not the other way around Akama->GetMotionMaster()->MoveIdle(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // Crazy amount of threat me->AddThreat(Akama, 10000000.0f); Akama->AddThreat(me, 10000000.0f); me->Attack(Akama, true); Akama->Attack(me, true); } } } } else // No longer banished, let's fight Akama now { if (ReduceHealthTimer <= diff) { if (AkamaGUID) { Creature* Akama = Unit::GetCreature((*me), AkamaGUID); if (Akama && Akama->isAlive()) { //10 % less health every few seconds. me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); ReduceHealthTimer = 12000; } } } else ReduceHealthTimer -= diff; if (HasKilledAkama) { if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug { HasKilledAkamaAndReseting = true; me->RemoveAllAuras(); me->DeleteThreatList(); me->CombatStop(); //me->SetHealth(me->GetMaxHealth()); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->GetMotionMaster()->MoveTargetedHome(); } if (ResetTimer <= diff) { EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama return; } else ResetTimer -= diff; } DoMeleeAttackIfReady(); } }
void SetData(uint32 type, uint32 data) { switch (type) { case DATA_MAGTHERIDON_EVENT: m_auiEncounter[0] = data; if (data == NOT_STARTED) RespawnTimer = 10000; if (data != IN_PROGRESS) HandleGameObject(DoorGUID, true); break; case DATA_CHANNELER_EVENT: switch (data) { case NOT_STARTED: // Reset all channelers once one is reset. if (m_auiEncounter[1] != NOT_STARTED) { m_auiEncounter[1] = NOT_STARTED; for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { if (Creature* Channeler = instance->GetCreature(*i)) { if (Channeler->isAlive()) Channeler->AI()->EnterEvadeMode(); else Channeler->Respawn(); } } CageTimer = 0; HandleGameObject(DoorGUID, true); } break; case IN_PROGRESS: // Event start. if (m_auiEncounter[1] != IN_PROGRESS) { m_auiEncounter[1] = IN_PROGRESS; // Let all five channelers aggro. for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { Creature* Channeler = instance->GetCreature(*i); if (Channeler && Channeler->isAlive()) Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); } // Release Magtheridon after two minutes. Creature* Magtheridon = instance->GetCreature(MagtheridonGUID); if (Magtheridon && Magtheridon->isAlive()) { Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); CageTimer = 120000; } HandleGameObject(DoorGUID, false); } break; case DONE: // Add buff and check if all channelers are dead. for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { Creature* Channeler = instance->GetCreature(*i); if (Channeler && Channeler->isAlive()) { //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); data = IN_PROGRESS; break; } } break; } m_auiEncounter[1] = data; break; case DATA_COLLAPSE: // true - collapse / false - reset for (std::set<uint64>::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) DoUseDoorOrButton(*i); break; default: break; } }
void UpdateAI(const uint32 diff) { if (EventInProgress) { Player* pWarrior = NULL; if (PlayerGUID) pWarrior = Unit::GetPlayer(*me, PlayerGUID); if (!pWarrior) return; if (!pWarrior->isAlive() && pWarrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { EventInProgress = false; DoScriptText(SAY_TWIGGY_FLATHEAD_DOWN, me); pWarrior->FailQuest(1719); for (uint8 i = 0; i < 6; ++i) { if (AffrayChallenger[i]) { Creature* creature = Unit::GetCreature((*me), AffrayChallenger[i]); if (creature) { if (creature->isAlive()) { creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->setDeathState(JUST_DIED); } } } AffrayChallenger[i] = 0; Challenger_down[i] = false; } if (BigWill) { Creature* creature = Unit::GetCreature((*me), BigWill); if (creature) { if (creature->isAlive()) { creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->setDeathState(JUST_DIED); } } } BigWill = 0; } if (!EventGrate && EventInProgress) { float x, y, z; pWarrior->GetPosition(x, y, z); if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) { pWarrior->AreaExploredOrEventHappens(1719); DoScriptText(SAY_TWIGGY_FLATHEAD_BEGIN, me); for (uint8 i = 0; i < 6; ++i) { Creature* creature = me->SummonCreature(NPC_AFFRAY_CHALLENGER, AffrayChallengerLoc[i][0], AffrayChallengerLoc[i][1], AffrayChallengerLoc[i][2], AffrayChallengerLoc[i][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); if (!creature) continue; creature->setFaction(35); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); AffrayChallenger[i] = creature->GetGUID(); } Wave_Timer = 5000; Challenger_checker = 1000; EventGrate = true; } } else if (EventInProgress) { if (Challenger_checker <= diff) { for (uint8 i = 0; i < 6; ++i) { if (AffrayChallenger[i]) { Creature* creature = Unit::GetCreature((*me), AffrayChallenger[i]); if ((!creature || (!creature->isAlive())) && !Challenger_down[i]) { DoScriptText(SAY_TWIGGY_FLATHEAD_DOWN, me); Challenger_down[i] = true; } } } Challenger_checker = 1000; } else Challenger_checker -= diff; if (Wave_Timer <= diff) { if (Wave < 6 && AffrayChallenger[Wave] && !EventBigWill) { DoScriptText(SAY_TWIGGY_FLATHEAD_FRAY, me); Creature* creature = Unit::GetCreature((*me), AffrayChallenger[Wave]); if (creature && (creature->isAlive())) { creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); creature->setFaction(14); creature->AI()->AttackStart(pWarrior); ++Wave; Wave_Timer = 20000; } } else if (Wave >= 6 && !EventBigWill) { if (Creature* creature = me->SummonCreature(NPC_BIG_WILL, -1722, -4341, 6.12f, 6.26f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 480000)) { BigWill = creature->GetGUID(); //creature->GetMotionMaster()->MovePoint(0, -1693, -4343, 4.32f); //creature->GetMotionMaster()->MovePoint(1, -1684, -4333, 2.78f); creature->GetMotionMaster()->MovePoint(2, -1682, -4329, 2.79f); creature->HandleEmoteCommand(EMOTE_STATE_READYUNARMED); EventBigWill = true; Wave_Timer = 1000; } } else if (Wave >= 6 && EventBigWill && BigWill) { Creature* creature = Unit::GetCreature((*me), BigWill); if (!creature || !creature->isAlive()) { DoScriptText(SAY_TWIGGY_FLATHEAD_OVER, me); EventInProgress = false; EventBigWill = false; EventGrate = false; PlayerGUID = 0; Wave = 0; } } } else Wave_Timer -= diff; } } }
/**HandleNpcSetMoveTypeCommand * Set the movement type for an NPC.<br/> * <br/> * Valid movement types are: * <ul> * <li> stay - NPC wont move </li> * <li> random - NPC will move randomly according to the spawndist </li> * <li> way - NPC will move with given waypoints set </li> * </ul> * additional parameter: NODEL - so no waypoints are deleted, if you * change the movement type */ static bool HandleNpcSetMoveTypeCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // 3 arguments: // GUID (optional - you can also select the creature) // stay|random|way (determines the kind of movement) // NODEL (optional - tells the system NOT to delete any waypoints) // this is very handy if you want to do waypoints, that are // later switched on/off according to special events (like escort // quests, etc) char* guid_str = strtok((char*) args, " "); char* type_str = strtok((char*) NULL, " "); char* dontdel_str = strtok((char*) NULL, " "); bool doNotDelete = false; if (!guid_str) return false; uint32 lowguid = 0; Creature* pCreature = NULL; if (dontdel_str) { //sLog->outError("DEBUG: All 3 params are set"); // All 3 params are set // GUID // type // doNotDEL if (stricmp(dontdel_str, "NODEL") == 0) { //sLog->outError("DEBUG: doNotDelete = true;"); doNotDelete = true; } } else { // Only 2 params - but maybe NODEL is set if (type_str) { sLog->outError("DEBUG: Only 2 params "); if (stricmp(type_str, "NODEL") == 0) { //sLog->outError("DEBUG: type_str, NODEL "); doNotDelete = true; type_str = NULL; } } } if (!type_str) // case .setmovetype $move_type (with selected creature) { type_str = guid_str; pCreature = handler->getSelectedCreature(); if (!pCreature || pCreature->isPet()) return false; lowguid = pCreature->GetDBTableGUIDLow(); } else // case .setmovetype #creature_guid $move_type (with selected creature) { lowguid = atoi((char*) guid_str); /* impossible without entry if (lowguid) pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); */ // attempt check creature existence by DB data if (!pCreature) { CreatureData const* data = sObjectMgr->GetCreatureData(lowguid); if (!data) { handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); handler->SetSentErrorMessage(true); return false; } } else { lowguid = pCreature->GetDBTableGUIDLow(); } } // now lowguid is low guid really existed creature // and pCreature point (maybe) to this creature or NULL MovementGeneratorType move_type; std::string type = type_str; if (type == "stay") move_type = IDLE_MOTION_TYPE; else if (type == "random") move_type = RANDOM_MOTION_TYPE; else if (type == "way") move_type = WAYPOINT_MOTION_TYPE; else return false; // update movement type //if (doNotDelete == false) // WaypointMgr.DeletePath(lowguid); if (pCreature) { // update movement type if (doNotDelete == false) pCreature->LoadPath(0); pCreature->SetDefaultMovementType(move_type); pCreature->GetMotionMaster()->Initialize(); if (pCreature->isAlive()) // dead creature will reset movement generator at respawn { pCreature->setDeathState(JUST_DIED); pCreature->Respawn(); } pCreature->SaveToDB(); } if (doNotDelete == false) { handler->PSendSysMessage(LANG_MOVE_TYPE_SET, type_str); } else { handler->PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL, type_str); } return true; }
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 /*action*/) { player->PlayerTalkClass->ClearMenus(); player->CLOSE_GOSSIP_MENU(); InstanceScript* instance = creature->GetInstanceScript(); if (!instance) return true; if (instance->GetBossState(BOSS_BEASTS) != DONE) { instance->SetData(TYPE_EVENT, 110); instance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED); instance->SetBossState(BOSS_BEASTS, NOT_STARTED); } else if (instance->GetBossState(BOSS_JARAXXUS) != DONE) { // if Jaraxxus is spawned, but the raid wiped if (Creature* jaraxxus = Unit::GetCreature(*player, instance->GetData64(NPC_JARAXXUS))) { jaraxxus->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); jaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); jaraxxus->SetReactState(REACT_DEFENSIVE); jaraxxus->SetInCombatWithZone(); } else { instance->SetData(TYPE_EVENT, 1010); instance->SetBossState(BOSS_JARAXXUS, NOT_STARTED); } } else if (instance->GetBossState(BOSS_CRUSADERS) != DONE) { if (player->GetTeam() == ALLIANCE) instance->SetData(TYPE_EVENT, 3000); else instance->SetData(TYPE_EVENT, 3001); instance->SetBossState(BOSS_CRUSADERS, NOT_STARTED); } else if (instance->GetBossState(BOSS_VALKIRIES) != DONE) { instance->SetData(TYPE_EVENT, 4000); instance->SetBossState(BOSS_VALKIRIES, NOT_STARTED); } else if (instance->GetBossState(BOSS_LICH_KING) != DONE) { if (GameObject* floor = GameObject::GetGameObject(*player, instance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) floor->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); creature->CastSpell(creature, SPELL_CORPSE_TELEPORT, false); creature->CastSpell(creature, SPELL_DESTROY_FLOOR_KNOCKUP, false); Creature* anubArak = Unit::GetCreature(*creature, instance->GetData64(NPC_ANUBARAK)); if (!anubArak || !anubArak->isAlive()) anubArak = creature->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); instance->SetBossState(BOSS_ANUBARAK, NOT_STARTED); if (creature->IsVisible()) creature->SetVisible(false); } creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); return true; }
void UpdateAI(const uint32 diff) { //Only if not incombat check if the event is started if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) { Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); if (pTarget) { AttackStart(pTarget); GetAdvisors(); } } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; } //CataclysmicBolt_Timer if (CataclysmicBolt_Timer <= diff) { //select a random unit other than the main tank Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); //if there aren't other units, cast on the tank if (!pTarget) pTarget = me->getVictim(); if (pTarget) DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); CataclysmicBolt_Timer = 10000; } else CataclysmicBolt_Timer -= diff; //SearNova_Timer if (SearNova_Timer <= diff) { DoCast(me->getVictim(), SPELL_SEAR_NOVA); SearNova_Timer = 20000+rand()%40000; } else SearNova_Timer -= diff; //Enrage_Timer if (Enrage_Timer <= diff) { DoCast(me, SPELL_ENRAGE); Enrage_Timer = 90000; } else Enrage_Timer -= diff; //Blessing of Tides Trigger if (!HealthAbovePct(75) && !BlessingOfTides) { BlessingOfTides = true; bool continueTriggering = false; Creature* Advisor; for (uint8 i = 0; i < MAX_ADVISORS; ++i) if (Advisors[i]) { Advisor = (Unit::GetCreature(*me, Advisors[i])); if (Advisor && Advisor->isAlive()) { continueTriggering = true; break; } } if (continueTriggering) { DoCast(me, SPELL_BLESSING_OF_THE_TIDES); me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); } } DoMeleeAttackIfReady(); }
void WorldSession::DoLootRelease(ObjectGuid lguid) { Player* player = GetPlayer(); Loot* loot; player->SetLootGuid(ObjectGuid()); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT); float min_amount = go_min * amount_rate; float max_amount = go_max * amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING)) / (ReqValue + 25); double chance = pow(0.8 * chance_rate, 4 * (1 / double(max_amount)) * double(uses)); if (roll_chance_f(float(100.0f * chance + skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned at next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else // not fully looted object go->SetLootState(GO_ACTIVATED); break; } case HIGHGUID_CORPSE: // ONLY remove insignia at BG { Corpse* corpse = _player->GetMap()->GetCorpse(lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } break; } case HIGHGUID_ITEM: { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; switch (pItem->loot.loot_type) { // temporary loot in stacking items, clear loot state, no auto loot move case LOOT_PROSPECTING: { uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; // reset loot for allow repeat looting if stack > 5 pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItemCount(pItem, count, true); break; } // temporary loot, auto loot move case LOOT_DISENCHANTING: { if (!pItem->loot.isLooted()) player->AutoStoreLoot(pItem->loot); // can be lost if no space pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); break; } // normal persistence loot default: { // must be destroyed only if no loot if (pItem->loot.isLooted()) { pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } break; } } return; // item can be looted only single player } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; // update next looter if (Group* group = pCreature->GetGroupLootRecipient()) if (group->GetLooterGuid() == player->GetObjectGuid()) group->UpdateLooterGuid(pCreature); if (loot->isLooted() && !pCreature->isAlive()) { // for example skinning after normal loot pCreature->PrepareBodyLootState(); pCreature->AllLootRemovedFromCorpse(); } break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } // Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetObjectGuid()); }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); ObjectGuid lguid = player->GetLootGuid(); Loot* loot; uint8 lootSlot; Item* pItem = NULL; recv_data >> lootSlot; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; break; } case HIGHGUID_ITEM: { pItem = player->GetItemByGuid(lguid); if (!pItem || !pItem->HasGeneratedLoot()) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; break; } case HIGHGUID_CORPSE: { Corpse* bones = player->GetMap()->GetCorpse(lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } QuestItem* qitem = NULL; QuestItem* ffaitem = NULL; QuestItem* conditem = NULL; LootItem* item = loot->LootItemInSlot(lootSlot, player, &qitem, &ffaitem, &conditem); if (!item) { player->SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL); return; } // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) { player->SendLootRelease(lguid); return; } if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count); if (msg == EQUIP_ERR_OK) { Item* newitem = player->StoreNewItem(dest, item->itemid, true, item->randomPropertyId); if (qitem) { qitem->is_looted = true; // freeforall is 1 if everyone's supposed to get the quest item. if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) player->SendNotifyLootItemRemoved(lootSlot); else loot->NotifyQuestItemRemoved(qitem->index); } else { if (ffaitem) { // freeforall case, notify only one player of the removal ffaitem->is_looted = true; player->SendNotifyLootItemRemoved(lootSlot); } else { // not freeforall, notify everyone if (conditem) conditem->is_looted = true; loot->NotifyItemRemoved(lootSlot); } } // if only one person is supposed to loot the item, then set it to looted if (!item->freeforall) item->is_looted = true; --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); } else player->SendEquipError(msg, NULL, NULL, item->itemid); }
void UpdateAI(uint32 uiDiff) { npc_escortAI::UpdateAI(uiDiff); if (HasEscortState(STATE_ESCORT_PAUSED)) { if (waveTimer <= uiDiff) { switch (wave) { case 0: Talk(SAY_BREAKOUT3); SummonAcolyte(3); waveTimer = 20000; break; case 1: Talk(SAY_BREAKOUT4); SummonAcolyte(3); waveTimer = 20000; break; case 2: Talk(SAY_BREAKOUT5); SummonAcolyte(4); waveTimer = 20000; break; case 3: Talk(SAY_BREAKOUT6); me->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329f, -6045.818f, 127.583f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); waveTimer = 1000; break; case 4: { Creature* temp = Unit::GetCreature(*me, valrothGUID); if (!temp || !temp->isAlive()) { Talk(SAY_BREAKOUT8); waveTimer = 5000; } else { waveTimer = 2500; return; } break; } case 5: Talk(SAY_BREAKOUT9); me->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); waveTimer = 2500; break; case 6: Talk(SAY_BREAKOUT10); SetEscortPaused(false); break; } ++wave; } else waveTimer -= uiDiff; } }
void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) { DEBUG_LOG("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); ObjectGuid guid = player->GetLootGuid(); if (!guid) return; Loot* pLoot = NULL; Item* pItem = NULL; switch (guid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && (pGameObject->GetOwnerGuid() == _player->GetObjectGuid() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = _player->GetMap()->GetCorpse(guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { pItem = GetPlayer()->GetItemByGuid(guid); if (!pItem || !pItem->HasGeneratedLoot()) return; pLoot = &pItem->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (!guid.IsItem() && player->GetGroup()) // item can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else player->ModifyMoney(pLoot->gold); pLoot->gold = 0; if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); } }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (Fireball_Timer <= diff) { if (Unit* pVictim = SelectUnit(SELECT_TARGET_RANDOM,0)) DoCast(pVictim, DUNGEON_MODE(SPELL_FIREBALL, SPELL_FIREBALL_H), true); Fireball_Timer = urand(4000,7000); } else Fireball_Timer -= diff; if (flight) // phase 1 - the flight { Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && Vazruden->HealthAbovePct(20))) { flight = false; BellowingRoar_Timer = 6000; ConeOfFire_Timer = 12000; me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); me->GetMotionMaster()->Clear(); if (Unit* pVictim = SelectUnit(SELECT_TARGET_NEAREST,0)) me->AI()->AttackStart(pVictim); DoStartMovement(me->getVictim()); DoScriptText(EMOTE, me); return; } else Fly_Timer -= diff; if (Turn_Timer <= diff) { uint32 waypoint = (Fly_Timer/10000)%2; if (!me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); Turn_Timer = 10000; } else Turn_Timer -= diff; } else // phase 2 - land fight { if (ConeOfFire_Timer <= diff) { DoCast(me, DUNGEON_MODE(SPELL_CONE_OF_FIRE, SPELL_CONE_OF_FIRE_H)); ConeOfFire_Timer = 12000; Fireball_Timer = 4000; } else ConeOfFire_Timer -= diff; if (IsHeroic()) { if (BellowingRoar_Timer <= diff) { DoCast(me, SPELL_BELLOWING_ROAR); BellowingRoar_Timer = 45000; } else BellowingRoar_Timer -= diff; } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { if (!pInstance) return; if (MobDeath_Timer) { if (MobDeath_Timer <= diff) { MobDeath_Timer = 2500; if (RingBossGUID) { Creature *boss = Unit::GetCreature(*me,RingBossGUID); if (boss && !boss->isAlive() && boss->isDead()) { RingBossGUID = 0; Event_Timer = 5000; MobDeath_Timer = 0; return; } return; } for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) { Creature *mob = Unit::GetCreature(*me,RingMobGUID[i]); if (mob && !mob->isAlive() && mob->isDead()) { RingMobGUID[i] = 0; --MobCount; //seems all are gone, so set timer to continue and discontinue this if (!MobCount) { Event_Timer = 5000; MobDeath_Timer = 0; } } } } else MobDeath_Timer -= diff; } if (Event_Timer) { if (Event_Timer <= diff) { switch(EventPhase) { case 0: DoScriptText(SCRIPT_TEXT5, me);//1 HandleGameObject(DATA_ARENA4, false); Start(false, false); CanWalk = true; Event_Timer = 0; break; case 1: CanWalk = true; Event_Timer = 0; break; case 2: Event_Timer = 2000; break; case 3: HandleGameObject(DATA_ARENA1, true); Event_Timer = 3000; break; case 4: CanWalk = true; me->SetVisibility(VISIBILITY_OFF); SummonRingMob(); Event_Timer = 8000; break; case 5: SummonRingMob(); SummonRingMob(); Event_Timer = 8000; break; case 6: SummonRingMob(); Event_Timer = 0; break; case 7: me->SetVisibility(VISIBILITY_ON); HandleGameObject(DATA_ARENA1, false); DoScriptText(SCRIPT_TEXT6, me);//4 CanWalk = true; Event_Timer = 0; break; case 8: HandleGameObject(DATA_ARENA2, true); Event_Timer = 5000; break; case 9: me->SetVisibility(VISIBILITY_OFF); SummonRingBoss(); Event_Timer = 0; break; case 10: //if quest, complete HandleGameObject(DATA_ARENA2, false); HandleGameObject(DATA_ARENA3, true); HandleGameObject(DATA_ARENA4, true); CanWalk = true; Event_Timer = 0; break; } ++EventPhase; } else Event_Timer -= diff; } if (CanWalk) npc_escortAI::UpdateAI(diff); }
void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; //Only do this if we haven't spawned nef yet if (SpawnedAdds < 42) { //ShadowBoltTimer if (ShadowBoltTimer < diff) { Unit* target = NULL; target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target) DoCastSpellIfCan(target,SPELL_SHADOWBOLT); ShadowBoltTimer = urand(3000, 10000); }else ShadowBoltTimer -= diff; //FearTimer if (FearTimer < diff) { Unit* target = NULL; target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target) DoCastSpellIfCan(target,SPELL_FEAR); FearTimer = urand(10000, 20000); }else FearTimer -= diff; //Add spawning mechanism if (AddSpawnTimer < diff) { //Spawn 2 random types of creatures at the 2 locations uint32 CreatureID; Creature* Spawned = NULL; Unit* target = NULL; //1 in 3 chance it will be a chromatic if (!urand(0, 2)) CreatureID = CREATURE_CHROMATIC_DRAKANOID; else CreatureID = DrakType1; ++SpawnedAdds; //Spawn creature and force it to start attacking a random target Spawned = m_creature->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000f,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target && Spawned) { Spawned->AI()->AttackStart(target); Spawned->setFaction(103); } //1 in 3 chance it will be a chromatic if (!urand(0, 2)) CreatureID = CREATURE_CHROMATIC_DRAKANOID; else CreatureID = DrakType2; ++SpawnedAdds; target = NULL; Spawned = NULL; Spawned = m_creature->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target && Spawned) { Spawned->AI()->AttackStart(target); Spawned->setFaction(103); } //Begin phase 2 by spawning Nefarian and what not if (SpawnedAdds >= 42) { //Teleport Victor Nefarius way out of the map //MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->CreatureRelocation(m_creature,0,0,-5000,0); //Inturrupt any spell casting m_creature->InterruptNonMeleeSpells(false); //Root self DoCastSpellIfCan(m_creature,33356); //Make super invis DoCastSpellIfCan(m_creature,8149); //Teleport self to a hiding spot m_creature->NearTeleportTo(HIDE_X, HIDE_Y, HIDE_Z, 0.0f); //Spawn nef and have him attack a random target Creature* Nefarian = m_creature->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target && Nefarian) { Nefarian->AI()->AttackStart(target); Nefarian->setFaction(103); NefarianGUID = Nefarian->GetGUID(); } else error_log("SD2: Blackwing Lair: Unable to spawn nefarian properly."); } AddSpawnTimer = 4000; }else AddSpawnTimer -= diff; } else if (NefarianGUID) { if (NefCheckTime < diff) { Creature* pNefarian = m_creature->GetMap()->GetCreature(NefarianGUID); //If nef is dead then we die to so the players get out of combat //and cannot repeat the event if (!pNefarian || !pNefarian->isAlive()) { NefarianGUID = 0; m_creature->ForcedDespawn(); } NefCheckTime = 2000; }else NefCheckTime -= diff; } }
void instance_stratholme::OnCreatureDeath(Creature* pCreature) { switch (pCreature->GetEntry()) { case NPC_BARONESS_ANASTARI: SetData(TYPE_BARONESS, DONE); break; case NPC_MALEKI_THE_PALLID: SetData(TYPE_PALLID, DONE); break; case NPC_NERUBENKAN: SetData(TYPE_NERUB, DONE); break; case NPC_RAMSTEIN: SetData(TYPE_RAMSTEIN, DONE); break; case NPC_BARON: SetData(TYPE_BARON, DONE); break; case NPC_AURIUS: SetData(TYPE_AURIUS, FAIL); break; case NPC_THUZADIN_ACOLYTE: ThazudinAcolyteJustDied(pCreature); break; case NPC_ABOM_BILE: case NPC_ABOM_VENOM: // Start Slaughterhouse Event SetData(TYPE_RAMSTEIN, SPECIAL); break; case NPC_MINDLESS_UNDEAD: m_luiUndeadGUIDs.remove(pCreature->GetObjectGuid()); if (m_luiUndeadGUIDs.empty()) { // Let the black Guards move out of the citadel for (GuidList::const_iterator itr = m_luiGuardGUIDs.begin(); itr != m_luiGuardGUIDs.end(); ++itr) { Creature* pGuard = instance->GetCreature(*itr); if (pGuard && pGuard->isAlive() && !pGuard->isInCombat()) { float fX, fY, fZ; pGuard->GetRandomPoint(aStratholmeLocation[5].m_fX, aStratholmeLocation[5].m_fY, aStratholmeLocation[5].m_fZ, 10.0f, fX, fY, fZ); pGuard->GetMotionMaster()->MovePoint(0, fX, fY, fZ); } } } break; case NPC_BLACK_GUARD: m_luiGuardGUIDs.remove(pCreature->GetObjectGuid()); if (m_luiGuardGUIDs.empty()) SetData(TYPE_BLACK_GUARDS, DONE); break; // Timmy spawn support case NPC_CRIMSON_INITIATE: case NPC_CRIMSON_GALLANT: case NPC_CRIMSON_GUARDSMAN: case NPC_CRIMSON_CONJURER: if (m_suiCrimsonLowGuids.find(pCreature->GetGUIDLow()) != m_suiCrimsonLowGuids.end()) { m_suiCrimsonLowGuids.erase(pCreature->GetGUIDLow()); // If all courtyard mobs are dead then summon Timmy if (m_suiCrimsonLowGuids.empty()) pCreature->SummonCreature(NPC_TIMMY_THE_CRUEL, aTimmyLocation[0].m_fX, aTimmyLocation[0].m_fY, aTimmyLocation[0].m_fZ, aTimmyLocation[0].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0); } break; } }
void instance_naxxramas::SetData(uint32 uiType, uint32 uiData) { switch(uiType) { case TYPE_ANUB_REKHAN: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiAnubDoorGUID); if (uiData == DONE) DoUseDoorOrButton(m_uiAnubGateGUID); break; case TYPE_FAERLINA: DoUseDoorOrButton(m_uiFaerWebGUID); if (uiData == DONE) { DoUseDoorOrButton(m_uiFaerDoorGUID); DoUseDoorOrButton(m_uiMaexOuterGUID); } if (uiData == FAIL) { for (GUIDList::const_iterator itr = m_lFaerlinaAddGUIDs.begin(); itr != m_lFaerlinaAddGUIDs.end(); ++itr) { Creature* pAdd = instance->GetCreature(*itr); if (pAdd && !pAdd->isAlive()) pAdd->Respawn(); } } m_auiEncounter[uiType] = uiData; break; case TYPE_MAEXXNA: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiMaexInnerGUID, uiData); if (uiData == DONE) { DoUseDoorOrButton(m_uiAracEyeRampGUID); DoRespawnGameObject(m_uiAracPortalGUID, 30*MINUTE); DoTaunt(); } break; case TYPE_NOTH: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiNothEntryDoorGUID); if (uiData == DONE) { DoUseDoorOrButton(m_uiNothExitDoorGUID); DoUseDoorOrButton(m_uiHeigEntryDoorGUID); } break; case TYPE_HEIGAN: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiHeigEntryDoorGUID); if (uiData == DONE) DoUseDoorOrButton(m_uiHeigExitDoorGUID); break; case TYPE_LOATHEB: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiLoathebDoorGUID); if (uiData == DONE) { DoUseDoorOrButton(m_uiPlagEyeRampGUID); DoRespawnGameObject(m_uiPlagPortalGUID, 30*MINUTE); DoTaunt(); } break; case TYPE_RAZUVIOUS: m_auiEncounter[uiType] = uiData; break; case TYPE_GOTHIK: switch(uiData) { case IN_PROGRESS: DoUseDoorOrButton(m_uiGothikEntryDoorGUID); DoUseDoorOrButton(m_uiGothCombatGateGUID); break; case SPECIAL: DoUseDoorOrButton(m_uiGothCombatGateGUID); break; case FAIL: if (m_auiEncounter[uiType] == IN_PROGRESS) DoUseDoorOrButton(m_uiGothCombatGateGUID); DoUseDoorOrButton(m_uiGothikEntryDoorGUID); break; case DONE: DoUseDoorOrButton(m_uiGothikEntryDoorGUID); DoUseDoorOrButton(m_uiGothikExitDoorGUID); DoUseDoorOrButton(m_uiHorsemenDoorGUID); break; } m_auiEncounter[uiType] = uiData; break; case TYPE_FOUR_HORSEMEN: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiHorsemenDoorGUID); if (uiData == DONE) { DoUseDoorOrButton(m_uiMiliEyeRampGUID); DoRespawnGameObject(m_uiMiliPortalGUID, 30*MINUTE); DoRespawnGameObject(m_uiHorsemenChestGUID, 30*MINUTE); DoTaunt(); } break; case TYPE_PATCHWERK: m_auiEncounter[uiType] = uiData; if (uiData == DONE) DoUseDoorOrButton(m_uiPathExitDoorGUID); break; case TYPE_GROBBULUS: m_auiEncounter[uiType] = uiData; break; case TYPE_GLUTH: m_auiEncounter[uiType] = uiData; if (uiData == DONE) { DoUseDoorOrButton(m_uiGlutExitDoorGUID); DoUseDoorOrButton(m_uiThadDoorGUID); } break; case TYPE_THADDIUS: // Only process real changes here if (m_auiEncounter[uiType] == uiData) return; m_auiEncounter[uiType] = uiData; if (uiData != SPECIAL) DoUseDoorOrButton(m_uiThadDoorGUID, uiData); if (uiData == DONE) { DoUseDoorOrButton(m_uiConsEyeRampGUID); DoRespawnGameObject(m_uiConsPortalGUID, 30*MINUTE); DoTaunt(); } break; case TYPE_SAPPHIRON: m_auiEncounter[uiType] = uiData; if (uiData == DONE) DoUseDoorOrButton(m_uiKelthuzadDoorGUID); break; case TYPE_KELTHUZAD: m_auiEncounter[uiType] = uiData; DoUseDoorOrButton(m_uiKelthuzadExitDoorGUID); break; } if (uiData == DONE) { OUT_SAVE_INST_DATA; std::ostringstream saveStream; saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11] << " " << m_auiEncounter[12] << " " << m_auiEncounter[13] << " " << m_auiEncounter[14] << " " << m_auiEncounter[15]; m_strInstData = saveStream.str(); SaveToDB(); OUT_SAVE_INST_DATA_COMPLETE; } }
void instance_stratholme::Update(uint32 uiDiff) { if (m_uiBarthilasRunTimer) { if (m_uiBarthilasRunTimer <= uiDiff) { Creature* pBarthilas = GetSingleCreatureFromStorage(NPC_BARTHILAS); if (pBarthilas && pBarthilas->isAlive() && !pBarthilas->isInCombat()) pBarthilas->NearTeleportTo(aStratholmeLocation[1].m_fX, aStratholmeLocation[1].m_fY, aStratholmeLocation[1].m_fZ, aStratholmeLocation[1].m_fO); SetData(TYPE_BARTHILAS_RUN, DONE); m_uiBarthilasRunTimer = 0; } else m_uiBarthilasRunTimer -= uiDiff; } // Timer to summon Aurius into the Slaughter House once Baron is engaged if (m_uiAuriusSummonTimer) { if (m_uiAuriusSummonTimer <= uiDiff) { SetData(TYPE_AURIUS, IN_PROGRESS); m_uiAuriusSummonTimer = 0; } else m_uiAuriusSummonTimer -= uiDiff; } // Check changes for Baron ultimatum timer only if Baron is not already in combat if (m_uiBaronRunTimer && GetData(TYPE_BARON) != IN_PROGRESS) { if (m_uiYellCounter == 0 && m_uiBaronRunTimer <= 10 * MINUTE * IN_MILLISECONDS) { DoOrSimulateScriptTextForThisInstance(SAY_ANNOUNCE_RUN_10_MIN, NPC_BARON); ++m_uiYellCounter; } else if (m_uiYellCounter == 1 && m_uiBaronRunTimer <= 5 * MINUTE * IN_MILLISECONDS) { DoOrSimulateScriptTextForThisInstance(SAY_ANNOUNCE_RUN_5_MIN, NPC_BARON); ++m_uiYellCounter; } // Used to create a delay of 10s between Baron speech and Ysida's answer else if (m_uiYellCounter == 2 && m_uiBaronRunTimer <= (5 * MINUTE - 10) * IN_MILLISECONDS) { DoOrSimulateScriptTextForThisInstance(YSIDA_SAY_RUN_5_MIN, NPC_YSIDA); ++m_uiYellCounter; } if (m_uiBaronRunTimer <= uiDiff) { if (GetData(TYPE_BARON_RUN) != FAIL) { SetData(TYPE_BARON_RUN, FAIL); // Open the cage and let Ysida face her doom if (Creature* pYsida = GetSingleCreatureFromStorage(NPC_YSIDA)) { pYsida->GetMotionMaster()->MovePoint(0, aStratholmeLocation[8].m_fX, aStratholmeLocation[8].m_fY, aStratholmeLocation[8].m_fZ, aStratholmeLocation[8].m_fO); DoUseDoorOrButton(GO_YSIDA_CAGE); } DoOrSimulateScriptTextForThisInstance(SAY_ANNOUNCE_RUN_FAIL, NPC_BARON); m_uiBaronRunTimer = 8000; // We reset the timer so the speech of Ysida is not said at the same time than the Baron's one } else { // Baron ultimatum failed: let the Baron kill her if (Creature* pYsida = GetSingleCreatureFromStorage(NPC_YSIDA)) if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) pBaron->CastSpell(pYsida, SPELL_BARON_SOUL_DRAIN, true); DoOrSimulateScriptTextForThisInstance(YSIDA_SAY_RUN_FAIL, NPC_YSIDA); m_uiBaronRunTimer = 0; // event done for good, no more speech debug_log("SD2: Instance Stratholme: Baron run event reached end. Event has state %u.", GetData(TYPE_BARON_RUN)); } } else m_uiBaronRunTimer -= uiDiff; } if (m_uiMindlessSummonTimer) { if (m_uiMindlessCount < 30) { if (m_uiMindlessSummonTimer <= uiDiff) { if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) { // Summon mindless skeletons and move them to random point in the center of the square if (Creature* pTemp = pBaron->SummonCreature(NPC_MINDLESS_UNDEAD, aStratholmeLocation[4].m_fX, aStratholmeLocation[4].m_fY, aStratholmeLocation[4].m_fZ, aStratholmeLocation[4].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0)) { float fX, fY, fZ; pBaron->GetRandomPoint(aStratholmeLocation[5].m_fX, aStratholmeLocation[5].m_fY, aStratholmeLocation[5].m_fZ, 20.0f, fX, fY, fZ); pTemp->GetMotionMaster()->MovePoint(0, fX, fY, fZ); m_luiUndeadGUIDs.push_back(pTemp->GetObjectGuid()); ++m_uiMindlessCount; } } m_uiMindlessSummonTimer = 400; } else m_uiMindlessSummonTimer -= uiDiff; } else m_uiMindlessSummonTimer = 0; } if (m_uiSlaugtherSquareTimer) { if (m_uiSlaugtherSquareTimer <= uiDiff) { // Call next Abomnations for (GuidSet::const_iterator itr = m_sAbomnationGUID.begin(); itr != m_sAbomnationGUID.end(); ++itr) { Creature* pAbom = instance->GetCreature(*itr); // Skip killed and already walking Abomnations if (!pAbom || !pAbom->isAlive() || pAbom->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) continue; // Let Move to somewhere in the middle if (!pAbom->isInCombat()) { if (GameObject* pDoor = GetSingleGameObjectFromStorage(GO_PORT_SLAUGTHER)) { float fX, fY, fZ; pAbom->GetRandomPoint(pDoor->GetPositionX(), pDoor->GetPositionY(), pDoor->GetPositionZ(), 10.0f, fX, fY, fZ); pAbom->GetMotionMaster()->MovePoint(0, fX, fY, fZ); } } break; } // TODO - how fast are they called? m_uiSlaugtherSquareTimer = urand(15000, 30000); } else m_uiSlaugtherSquareTimer -= uiDiff; } }
void UpdateAI(const uint32 diff) { if (!m_pInstance) return; if (MobDeath_Timer) { if (MobDeath_Timer <= diff) { MobDeath_Timer = 2500; if (RingBossGUID) { Creature *boss = (Creature*)Unit::GetUnit(*m_creature,RingBossGUID); if (boss && !boss->isAlive() && boss->isDead()) { RingBossGUID = 0; Event_Timer = 5000; MobDeath_Timer = 0; return; } return; } for(uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) { Creature *mob = (Creature*)Unit::GetUnit(*m_creature,RingMobGUID[i]); if (mob && !mob->isAlive() && mob->isDead()) { RingMobGUID[i] = 0; --MobCount; //seems all are gone, so set timer to continue and discontinue this if (!MobCount) { Event_Timer = 5000; MobDeath_Timer = 0; } } } }else MobDeath_Timer -= diff; } if (Event_Timer) { if (Event_Timer <= diff) { switch(EventPhase) { case 0: DoScriptText(-1000000, m_creature);//1 DoGate(DATA_ARENA4,1); Start(false, false, false); CanWalk = true; Event_Timer = 0; break; case 1: CanWalk = true; Event_Timer = 0; break; case 2: Event_Timer = 2000; break; case 3: DoGate(DATA_ARENA1,GO_STATE_ACTIVE); Event_Timer = 3000; break; case 4: CanWalk = true; m_creature->SetVisibility(VISIBILITY_OFF); SummonRingMob(); Event_Timer = 8000; break; case 5: SummonRingMob(); SummonRingMob(); Event_Timer = 8000; break; case 6: SummonRingMob(); Event_Timer = 0; break; case 7: m_creature->SetVisibility(VISIBILITY_ON); DoGate(DATA_ARENA1,GO_STATE_READY); DoScriptText(-1000000, m_creature);//4 CanWalk = true; Event_Timer = 0; break; case 8: DoGate(DATA_ARENA2,GO_STATE_ACTIVE); Event_Timer = 5000; break; case 9: m_creature->SetVisibility(VISIBILITY_OFF); SummonRingBoss(); Event_Timer = 0; break; case 10: //if quest, complete DoGate(DATA_ARENA2,GO_STATE_READY); DoGate(DATA_ARENA3,GO_STATE_ACTIVE); DoGate(DATA_ARENA4,GO_STATE_ACTIVE); CanWalk = true; Event_Timer = 0; break; } ++EventPhase; }else Event_Timer -= diff; } if (CanWalk) npc_escortAI::UpdateAI(diff); }
void UpdateAI(uint32 uiDiff) { if (!_instance) return; if (_instance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING_1) return; _updateTimer = _instance->GetData(TYPE_EVENT_TIMER); if (_updateTimer <= uiDiff) { switch (_instance->GetData(TYPE_EVENT)) { case 5010: Talk(SAY_STAGE_4_02); _updateTimer = 3*IN_MILLISECONDS; me->GetMotionMaster()->MovePoint(0, LichKingLoc[0]); _instance->SetData(TYPE_EVENT, 5020); break; case 5030: Talk(SAY_STAGE_4_04); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); _updateTimer = 10*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 5040); break; case 5040: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); me->GetMotionMaster()->MovePoint(1, LichKingLoc[1]); _updateTimer = 1*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 0); break; case 5050: me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); _updateTimer = 3*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 5060); break; case 5060: Talk(SAY_STAGE_4_05); me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); _updateTimer = 2.5*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 5070); break; case 5070: me->CastSpell(me, 68198, false); _updateTimer = 1.5*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 5080); break; case 5080: if (GameObject* go = _instance->instance->GetGameObject(_instance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) { go->SetDisplayId(DISPLAYID_DESTROYED_FLOOR); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); go->SetGoState(GO_STATE_ACTIVE); } me->CastSpell(me, SPELL_CORPSE_TELEPORT, false); me->CastSpell(me, SPELL_DESTROY_FLOOR_KNOCKUP, false); if (_instance) { _instance->SetBossState(BOSS_LICH_KING, DONE); Creature* temp = Unit::GetCreature(*me, _instance->GetData64(NPC_ANUBARAK)); if (!temp || !temp->isAlive()) temp = me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); _instance->SetData(TYPE_EVENT, 0); } me->DespawnOrUnsummon(); _updateTimer = 20*IN_MILLISECONDS; break; default: break; } } else _updateTimer -= uiDiff; _instance->SetData(TYPE_EVENT_TIMER, _updateTimer); }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); uint64 lguid = player->GetLootGUID(); Loot* loot = NULL; uint8 lootSlot = 0; recv_data >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; } else if (IS_CORPSE_GUID(lguid)) { Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; } player->StoreLootItem(lootSlot, loot); }
void UpdateAI(const uint32 diff) { //Only if not incombat check if the event is started if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) { Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); if (pTarget) { AttackStart(pTarget); } } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; } //LeechingThrow_Timer if (LeechingThrow_Timer <= diff) { DoCast(me->getVictim(), SPELL_LEECHING_THROW); LeechingThrow_Timer = 20000; } else LeechingThrow_Timer -= diff; //Multishot_Timer if (Multishot_Timer <= diff) { DoCast(me->getVictim(), SPELL_MULTISHOT); Multishot_Timer = 20000; } else Multishot_Timer -= diff; //TheBeastWithin_Timer if (TheBeastWithin_Timer <= diff) { DoCast(me, SPELL_THE_BEAST_WITHIN); Creature *Pet = Unit::GetCreature(*me, SummonedPet); if (Pet && Pet->isAlive()) { Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); } TheBeastWithin_Timer = 30000; } else TheBeastWithin_Timer -= diff; //Pet_Timer if (Pet_Timer < diff && pet == false) { pet = true; //uint32 spell_id; uint32 pet_id; if (!urand(0, 1)) { //spell_id = SPELL_SUMMON_FATHOM_LURKER; pet_id = CREATURE_FATHOM_LURKER; } else { //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; pet_id = CREATURE_FATHOM_SPOREBAT; } //DoCast(me, spell_id, true); Creature *Pet = DoSpawnCreature(pet_id, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (Pet && pTarget) { Pet->AI()->AttackStart(pTarget); SummonedPet = Pet->GetGUID(); } } else Pet_Timer -= diff; DoMeleeAttackIfReady(); }
void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* loot = NULL; bool shareMoney = true; switch (GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); // do not check distance for GO if player is the owner of it (ex. fishing bobber) if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player, INTERACTION_DISTANCE)))) loot = &go->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*player, guid); if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = player->GetItemByGuid(guid)) { loot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* creature = player->GetMap()->GetCreature(guid); bool lootAllowed = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &creature->loot; if (creature->isAlive()) shareMoney = false; } break; } default: return; // unlootable type } if (loot) { loot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false)) playersNear.push_back(member); } uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(goldPerPlayer); (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(goldPerPlayer); data << uint8(playersNear.size() > 1 ? 0 : 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(loot->gold); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(loot->gold); data << uint8(1); SendPacket(&data); } loot->gold = 0; } }
//move selected creature static bool HandleNpcMoveCommand(ChatHandler* handler, const char* args) { uint32 lowguid = 0; Creature* pCreature = handler->getSelectedCreature(); if (!pCreature) { // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r char* cId = handler->extractKeyFromLink((char*) args, "Hcreature"); if (!cId) return false; lowguid = atoi(cId); /* FIXME: impossible without entry if (lowguid) pCreature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); */ // Attempting creature load from DB data if (!pCreature) { CreatureData const* data = sObjectMgr->GetCreatureData(lowguid); if (!data) { handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); handler->SetSentErrorMessage(true); return false; } uint32 map_id = data->mapid; if (handler->GetSession()->GetPlayer()->GetMapId() != map_id) { handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); handler->SetSentErrorMessage(true); return false; } } else { lowguid = pCreature->GetDBTableGUIDLow(); } } else { lowguid = pCreature->GetDBTableGUIDLow(); } float x = handler->GetSession()->GetPlayer()->GetPositionX(); float y = handler->GetSession()->GetPlayer()->GetPositionY(); float z = handler->GetSession()->GetPlayer()->GetPositionZ(); float o = handler->GetSession()->GetPlayer()->GetOrientation(); if (pCreature) { if (CreatureData const* data = sObjectMgr->GetCreatureData(pCreature->GetDBTableGUIDLow())) { const_cast<CreatureData*>(data)->posX = x; const_cast<CreatureData*>(data)->posY = y; const_cast<CreatureData*>(data)->posZ = z; const_cast<CreatureData*>(data)->orientation = o; } pCreature->GetMap()->CreatureRelocation(pCreature, x, y, z, o); pCreature->GetMotionMaster()->Initialize(); if (pCreature->isAlive()) // dead creature will reset movement generator at respawn { pCreature->setDeathState(JUST_DIED); pCreature->Respawn(); } } WorldDatabase.PExecute( "UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); handler->PSendSysMessage(LANG_COMMAND_CREATUREMOVED); return true; }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) { if (UnsummonCheck < diff && m_creature->isAlive()) m_creature->DisappearAndDie(); else UnsummonCheck -= diff; return; } if (Fireball_Timer <= diff) { if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) DoCast(victim, SPELL_FIREBALL,true); Fireball_Timer = urand(4000,7000); } else Fireball_Timer -= diff; if (flight) // phase 1 - the flight { Creature *Vazruden = Unit::GetCreature(*m_creature,VazrudenGUID); if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) { flight = false; BellowingRoar_Timer = 6000; ConeOfFire_Timer = 12000; m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); m_creature->GetMotionMaster()->Clear(); if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) m_creature->AI()->AttackStart(victim); DoStartMovement(m_creature->getVictim()); DoScriptText(EMOTE, m_creature); return; } else Fly_Timer -= diff; if (Turn_Timer <= diff) { uint32 waypoint = (Fly_Timer/10000)%2; if (m_creature->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) m_creature->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); Turn_Timer = 10000; } else Turn_Timer -= diff; } else // phase 2 - land fight { if (ConeOfFire_Timer <= diff) { DoCast(m_creature, SPELL_CONE_OF_FIRE); ConeOfFire_Timer = 12000; Fireball_Timer = 4000; } else ConeOfFire_Timer -= diff; if (HeroicMode && BellowingRoar_Timer <= diff) { DoCast(m_creature, SPELL_BELLOWING_ROAR); BellowingRoar_Timer = 45000; } else BellowingRoar_Timer -= diff; DoMeleeAttackIfReady(); } }
// Function to process actions for linked NPCs void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventType, Creature* pSource, Unit* pEnemy /* = NULL*/) { // This check will be needed in reload case if (!sCreatureLinkingMgr.IsLinkedEventTrigger(pSource)) return; // Ignore atypic behaviour if (pSource->IsControlledByPlayer()) return; if (eventType == LINKING_EVENT_AGGRO && !pEnemy) return; uint32 eventFlagFilter = 0; uint32 reverseEventFlagFilter = 0; switch (eventType) { case LINKING_EVENT_AGGRO: eventFlagFilter = EVENT_MASK_ON_AGGRO; reverseEventFlagFilter = FLAG_TO_AGGRO_ON_AGGRO; break; case LINKING_EVENT_EVADE: eventFlagFilter = EVENT_MASK_ON_EVADE; reverseEventFlagFilter = FLAG_TO_RESPAWN_ON_EVADE; break; case LINKING_EVENT_DIE: eventFlagFilter = EVENT_MASK_ON_DIE; reverseEventFlagFilter = 0; break; case LINKING_EVENT_RESPAWN: eventFlagFilter = EVENT_MASK_ON_RESPAWN; reverseEventFlagFilter = FLAG_FOLLOW; break; } // Process Slaves (by entry) HolderMapBounds bounds = m_holderMap.equal_range(pSource->GetEntry()); for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr) ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy); // Process Slaves (by guid) bounds = m_holderGuidMap.equal_range(pSource->GetGUIDLow()); for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr) ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy); // Process Master if (CreatureLinkingInfo const* pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(pSource)) { if (pInfo->linkingFlag & reverseEventFlagFilter) { Creature* pMaster = NULL; if (pInfo->mapId != INVALID_MAP_ID) // entry case { BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId); for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr) { pMaster = pSource->GetMap()->GetCreature(itr->second); if (pMaster && IsSlaveInRangeOfBoss(pSource, pMaster, pInfo->searchRange)) break; } } else // guid case { CreatureData const* masterData = sObjectMgr.GetCreatureData(pInfo->masterDBGuid); CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(masterData->id); pMaster = pSource->GetMap()->GetCreature(ObjectGuid(cInfo->GetHighGuid(), cInfo->Entry, pInfo->masterDBGuid)); } if (pMaster) { switch (eventType) { case LINKING_EVENT_AGGRO: if (pMaster->IsControlledByPlayer()) return; if (pMaster->isInCombat()) pMaster->SetInCombatWith(pEnemy); else pMaster->AI()->AttackStart(pEnemy); break; case LINKING_EVENT_EVADE: if (!pMaster->isAlive()) pMaster->Respawn(); break; case LINKING_EVENT_RESPAWN: if (pMaster->isAlive()) SetFollowing(pSource, pMaster); break; case LINKING_EVENT_DIE: // Nothing linked for this case break; } } } } }
void UpdateAI(const uint32 diff) { if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); if (!UpdateVictim()) return; if (CheckTimer <= diff) { Creature *Kalec = Unit::GetCreature(*me, KalecGUID); if (!Kalec || (Kalec && !Kalec->isAlive())) { if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) Kalecgos->AI()->EnterEvadeMode(); return; } if (HealthBelowPct(10) && !isEnraged) { if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) Kalecgos->AI()->DoAction(DO_ENRAGE); DoAction(DO_ENRAGE); } Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID); if (Kalecgos) { if (!Kalecgos->isInCombat()) { me->AI()->EnterEvadeMode(); return; } } if (!isBanished && HealthBelowPct(1)) { if (Kalecgos) { if (Kalecgos->HasAura(SPELL_BANISH)) { me->DealDamage(me, me->GetHealth()); return; } else DoAction(DO_BANISH); } else { me->MonsterTextEmote(EMOTE_UNABLE_TO_FIND, NULL); EnterEvadeMode(); return; } } CheckTimer = 1000; } else CheckTimer -= diff; if (ResetThreat <= diff) { for (std::list<HostileReference*>::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) { if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) { if (pUnit->GetPositionZ() > me->GetPositionZ()+5) { me->getThreatManager().modifyThreatPercent(pUnit,-100); } } } ResetThreat = 1000; } else ResetThreat -= diff; if (ShadowBoltTimer <= diff) { if (!(rand()%5))DoScriptText(SAY_SATH_SPELL1, me); DoCast(me, SPELL_SHADOW_BOLT); ShadowBoltTimer = 7000+(rand()%3000); } else ShadowBoltTimer -= diff; if (AgonyCurseTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (!pTarget) pTarget = me->getVictim(); DoCast(pTarget, SPELL_AGONY_CURSE); AgonyCurseTimer = 20000; } else AgonyCurseTimer -= diff; if (CorruptionStrikeTimer <= diff) { if (!(rand()%5))DoScriptText(SAY_SATH_SPELL2, me); DoCast(me->getVictim(), SPELL_CORRUPTION_STRIKE); CorruptionStrikeTimer = 13000; } else CorruptionStrikeTimer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!EventBegun) return; if ((me->GetHealth()*100 / me->GetMaxHealth()) < 15 && !HasYelledOnce) { DoScriptText(SAY_LOW_HEALTH, me); HasYelledOnce = true; } if (ShadeGUID && !StartCombat) { Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); if (Shade && Shade->isAlive()) { if (CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IsBanished) { if (CastSoulRetrieveTimer <= diff) { DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL); CastSoulRetrieveTimer = 60000; } else CastSoulRetrieveTimer -= diff; } else { me->InterruptNonMeleeSpells(false); StartCombat = true; } } } if (ShadeHasDied && (WayPointId == 1)) { if (pInstance) pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z); ++WayPointId; } if (!ShadeHasDied && StartCombat) { if (CheckTimer <= diff) { if (ShadeGUID) { Creature* Shade = Unit::GetCreature((*me), ShadeGUID); if (Shade && !Shade->isAlive()) { ShadeHasDied = true; WayPointId = 0; me->SetUnitMovementFlags(MOVEFLAG_WALK_MODE); me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); } if (Shade && Shade->isAlive()) { if (Shade->getThreatManager().getThreatList().size() < 2) Shade->AI()->EnterEvadeMode(); } } CheckTimer = 5000; } else CheckTimer -= diff; } if (SummonBrokenTimer && BrokenSummonIndex < 4) { if (SummonBrokenTimer <= diff) { for (uint8 i = 0; i < 4; ++i) { float x = BrokenCoords[BrokenSummonIndex].x + (i*5); float y = BrokenCoords[BrokenSummonIndex].y + (1*5); float z = BrokenCoords[BrokenSummonIndex].z; float o = BrokenCoords[BrokenSummonIndex].o; Creature* Broken = me->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); if (Broken) { float wx = BrokenWP[BrokenSummonIndex].x + (i*5); float wy = BrokenWP[BrokenSummonIndex].y + (i*5); float wz = BrokenWP[BrokenSummonIndex].z; Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz); Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); BrokenList.push_back(Broken->GetGUID()); } } ++BrokenSummonIndex; SummonBrokenTimer = 1000; } else SummonBrokenTimer -= diff; } if (SoulRetrieveTimer) if (SoulRetrieveTimer <= diff) { switch (EndingTalkCount) { case 0: me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); ++EndingTalkCount; SoulRetrieveTimer = 2000; SummonBrokenTimer = 1; break; case 1: DoScriptText(SAY_FREE, me); ++EndingTalkCount; SoulRetrieveTimer = 25000; break; case 2: if (!BrokenList.empty()) { bool Yelled = false; for (std::list<uint64>::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) if (Creature* pUnit = Unit::GetCreature(*me, *itr)) { if (!Yelled) { DoScriptText(SAY_BROKEN_FREE_01, pUnit); Yelled = true; } pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); } } ++EndingTalkCount; SoulRetrieveTimer = 1500; break; case 3: if (!BrokenList.empty()) { for (std::list<uint64>::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) if (Creature* pUnit = Unit::GetCreature(*me, *itr)) // This is the incorrect spell, but can't seem to find the right one. pUnit->CastSpell(pUnit, 39656, true); } ++EndingTalkCount; SoulRetrieveTimer = 5000; break; case 4: if (!BrokenList.empty()) { for (std::list<uint64>::iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) if (Creature* pUnit = Unit::GetCreature((*me), *itr)) pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); } SoulRetrieveTimer = 0; break; } } else SoulRetrieveTimer -= diff; if (!UpdateVictim()) return; if (DestructivePoisonTimer <= diff) { Creature* Shade = Unit::GetCreature((*me), ShadeGUID); if (Shade && Shade->isAlive()) DoCast(Shade, SPELL_DESTRUCTIVE_POISON); DestructivePoisonTimer = 15000; } else DestructivePoisonTimer -= diff; if (LightningBoltTimer <= diff) { DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); LightningBoltTimer = 10000; } else LightningBoltTimer -= diff; DoMeleeAttackIfReady(); }
void instance_stratholme::SetData(uint32 uiType, uint32 uiData) { // TODO: Remove the hard-coded indexes from array accessing switch (uiType) { case TYPE_BARON_RUN: switch (uiData) { case IN_PROGRESS: if (m_auiEncounter[uiType] == IN_PROGRESS || m_auiEncounter[uiType] == FAIL) break; // Baron ultimatum starts: summon Ysida in the cage if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) { DoOrSimulateScriptTextForThisInstance(SAY_ANNOUNCE_RUN_START, NPC_BARON); pBaron->SummonCreature(NPC_YSIDA, aStratholmeLocation[7].m_fX, aStratholmeLocation[7].m_fY, aStratholmeLocation[7].m_fZ, aStratholmeLocation[7].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0); } m_uiBaronRunTimer = 45 * MINUTE * IN_MILLISECONDS; debug_log("SD2: Instance Stratholme: Baron run in progress."); break; case FAIL: // may add code to remove aura from players, but in theory the time should be up already and removed. break; case DONE: m_uiBaronRunTimer = 0; break; } m_auiEncounter[uiType] = uiData; break; case TYPE_BARONESS: case TYPE_NERUB: case TYPE_PALLID: m_auiEncounter[uiType] = uiData; if (uiData == DONE) { DoSortZiggurats(); DoUseDoorOrButton(m_zigguratStorage[uiType - TYPE_BARONESS].m_doorGuid); } if (uiData == SPECIAL) StartSlaugtherSquare(); break; case TYPE_RAMSTEIN: if (uiData == SPECIAL) { if (m_auiEncounter[uiType] != SPECIAL && m_auiEncounter[uiType] != DONE) { m_uiSlaugtherSquareTimer = 20000; // TODO - unknown, also possible that this is not the very correct place.. DoUseDoorOrButton(GO_PORT_GAUNTLET); } uint32 uiCount = m_sAbomnationGUID.size(); for (GuidSet::iterator itr = m_sAbomnationGUID.begin(); itr != m_sAbomnationGUID.end();) { if (Creature* pAbom = instance->GetCreature(*itr)) { ++itr; if (!pAbom->isAlive()) --uiCount; } else { // Remove obsolete guid from set and decrement count m_sAbomnationGUID.erase(itr++); --uiCount; } } if (!uiCount) { // Old Comment: a bit itchy, it should close GO_ZIGGURAT_DOOR_4 door after 10 secs, but it doesn't. skipping it for now. // However looks like that this door is no more closed DoUseDoorOrButton(GO_ZIGGURAT_DOOR_4); // No more handlng of Abomnations m_uiSlaugtherSquareTimer = 0; if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) { DoScriptText(SAY_ANNOUNCE_RAMSTEIN, pBaron); if (Creature* pRamstein = pBaron->SummonCreature(NPC_RAMSTEIN, aStratholmeLocation[2].m_fX, aStratholmeLocation[2].m_fY, aStratholmeLocation[2].m_fZ, aStratholmeLocation[2].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0)) pRamstein->GetMotionMaster()->MovePoint(0, aStratholmeLocation[3].m_fX, aStratholmeLocation[3].m_fY, aStratholmeLocation[3].m_fZ); debug_log("SD2: Instance Stratholme - Slaugther event: Ramstein spawned."); } } else debug_log("SD2: Instance Stratholme - Slaugther event: %u Abomnation left to kill.", uiCount); } // After fail aggroing Ramstein means wipe on Ramstein, so close door again if (uiData == IN_PROGRESS && m_auiEncounter[uiType] == FAIL) DoUseDoorOrButton(GO_PORT_GAUNTLET); if (uiData == DONE) { // Open side gate and start summoning skeletons DoUseDoorOrButton(GO_PORT_SLAUGHTER_GATE); // use this timer as a bool just to start summoning m_uiMindlessSummonTimer = 500; m_uiMindlessCount = 0; m_luiUndeadGUIDs.clear(); // Summon 5 guards if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) { for (uint8 i = 0; i < 5; ++i) { float fX, fY, fZ; pBaron->GetRandomPoint(aStratholmeLocation[6].m_fX, aStratholmeLocation[6].m_fY, aStratholmeLocation[6].m_fZ, 5.0f, fX, fY, fZ); if (Creature* pTemp = pBaron->SummonCreature(NPC_BLACK_GUARD, aStratholmeLocation[6].m_fX, aStratholmeLocation[6].m_fY, aStratholmeLocation[6].m_fZ, aStratholmeLocation[6].m_fO, TEMPSUMMON_DEAD_DESPAWN, 0)) m_luiGuardGUIDs.push_back(pTemp->GetObjectGuid()); } debug_log("SD2: Instance Stratholme - Slaugther event: Summoned 5 guards."); } } // Open Door again and stop Abomnation if (uiData == FAIL && m_auiEncounter[uiType] != FAIL) { DoUseDoorOrButton(GO_PORT_GAUNTLET); m_uiSlaugtherSquareTimer = 0; // Let already moving Abomnations stop for (GuidSet::const_iterator itr = m_sAbomnationGUID.begin(); itr != m_sAbomnationGUID.end(); ++itr) { Creature* pAbom = instance->GetCreature(*itr); if (pAbom && pAbom->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) pAbom->GetMotionMaster()->MovementExpired(); } } m_auiEncounter[uiType] = uiData; break; case TYPE_BARON: if (uiData == IN_PROGRESS) { // Close Slaughterhouse door if needed if (m_auiEncounter[uiType] == FAIL) DoUseDoorOrButton(GO_PORT_GAUNTLET); // If Aurius was given the medaillon wait 5s before summoning him if (m_auiEncounter[TYPE_AURIUS] == SPECIAL) m_uiAuriusSummonTimer = 5000; } if (uiData == DONE) { // Players successfully engaged Baron within the time-limit of his ultimatum // Note: UpdateAI() prevents TYPE_BARON_RUN to be marked as FAILED if the // Baron is already engaged (in progress) when the ultimatum timer expires if (m_auiEncounter[TYPE_BARON_RUN] == IN_PROGRESS) { SetData(TYPE_BARON_RUN, DONE); Map::PlayerList const& players = instance->GetPlayers(); for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { if (Player* pPlayer = itr->getSource()) { if (pPlayer->HasAura(SPELL_BARON_ULTIMATUM)) pPlayer->RemoveAurasDueToSpell(SPELL_BARON_ULTIMATUM); if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE) pPlayer->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA); // Argent Dawn reputation reward pPlayer->CastSpell(pPlayer, SPELL_YSIDA_FREED, true); } } // Open cage, finish rescue event if (Creature* pYsida = GetSingleCreatureFromStorage(NPC_YSIDA)) { DoScriptText(SAY_EPILOGUE, pYsida); DoUseDoorOrButton(GO_YSIDA_CAGE); pYsida->GetMotionMaster()->MovePoint(0, aStratholmeLocation[8].m_fX, aStratholmeLocation[8].m_fY, aStratholmeLocation[8].m_fZ, aStratholmeLocation[8].m_fO); } } // If Aurius was spawned to help fight the Baron, mark that event as DONE if (m_auiEncounter[TYPE_AURIUS] == IN_PROGRESS) SetData(TYPE_AURIUS, DONE); // Open Slaughterhouse door again DoUseDoorOrButton(GO_PORT_GAUNTLET); } if (uiData == FAIL) DoUseDoorOrButton(GO_PORT_GAUNTLET); m_auiEncounter[uiType] = uiData; break; case TYPE_BARTHILAS_RUN: if (uiData == IN_PROGRESS) { Creature* pBarthilas = GetSingleCreatureFromStorage(NPC_BARTHILAS); if (pBarthilas && pBarthilas->isAlive() && !pBarthilas->isInCombat()) { DoScriptText(SAY_WARN_BARON, pBarthilas); pBarthilas->SetWalk(false); pBarthilas->GetMotionMaster()->MovePoint(0, aStratholmeLocation[0].m_fX, aStratholmeLocation[0].m_fY, aStratholmeLocation[0].m_fZ); m_uiBarthilasRunTimer = 8000; } } m_auiEncounter[uiType] = uiData; break; case TYPE_BLACK_GUARDS: // Prevent double action if (m_auiEncounter[uiType] == uiData) return; // Restart after failure, close Gauntlet if (uiData == IN_PROGRESS && m_auiEncounter[uiType] == FAIL) DoUseDoorOrButton(GO_PORT_GAUNTLET); // Wipe case - open gauntlet if (uiData == FAIL) DoUseDoorOrButton(GO_PORT_GAUNTLET); if (uiData == DONE) { if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) DoScriptText(SAY_UNDEAD_DEFEAT, pBaron); DoUseDoorOrButton(GO_ZIGGURAT_DOOR_5); } m_auiEncounter[uiType] = uiData; // No need to save anything here, so return return; case TYPE_POSTMASTER: m_auiEncounter[uiType] = uiData; if (uiData == IN_PROGRESS) { ++m_uiPostboxesUsed; // After the second post box prepare to spawn the Post Master if (m_uiPostboxesUsed == 2) SetData(TYPE_POSTMASTER, SPECIAL); } // No need to save anything here, so return return; case TYPE_AURIUS: m_auiEncounter[uiType] = uiData; // Prevent further players to complete the quest in that instance // or autocomplete the follow-up quest // the flag will be set back if event is succeed if (uiData == SPECIAL) { if (Creature* pAurius = GetSingleCreatureFromStorage(NPC_AURIUS)) pAurius->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); break; } // Baron killed and Aurius is alive: give him his NPC Flags back // So players can complete the quest // Fake his death if (uiData == DONE) { if (Creature* pAurius = GetSingleCreatureFromStorage(NPC_AURIUS)) { DoScriptText(SAY_AURIUS_DEATH, pAurius); pAurius->StopMoving(); pAurius->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); pAurius->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); pAurius->InterruptNonMeleeSpells(true); pAurius->SetHealth(1); pAurius->GetMotionMaster()->MovementExpired(); pAurius->GetMotionMaster()->MoveIdle(); pAurius->RemoveAllAurasOnDeath(); pAurius->SetStandState(UNIT_STAND_STATE_DEAD); } break; } if (uiData == IN_PROGRESS) { // Despawn Aurius in the Chapel and spawn it in the Slaughter House to engage Baron if (Creature* pAurius_original = GetSingleCreatureFromStorage(NPC_AURIUS)) pAurius_original->ForcedDespawn(); if (Creature* pBaron = GetSingleCreatureFromStorage(NPC_BARON)) { float fX, fY, fZ, fPosX, fPosY, fPosZ; fX = pBaron->GetPositionX(); fY = pBaron->GetPositionY(); fZ = pBaron->GetPositionZ(); pBaron->GetRandomPoint(fX, fY, fZ, 4.0f, fPosX, fPosY, fPosZ); if (Creature* pAurius = pBaron->SummonCreature(NPC_AURIUS, fPosX, fPosY, fPosZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) { DoScriptText(YELL_AURIUS_AGGRO, pAurius); pAurius->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); pAurius->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); pAurius->AI()->AttackStart(pBaron); } } } if (uiData == FAIL) { // Baron encounter failed and Aurius is spawned: kill him if (Creature* pAurius = GetSingleCreatureFromStorage(NPC_AURIUS)) { if (pAurius->isAlive()) { DoScriptText(SAY_AURIUS_DEATH, pAurius); pAurius->DealDamage(pAurius, pAurius->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, nullptr, false); } } break; } } if (uiData == DONE) { OUT_SAVE_INST_DATA; std::ostringstream saveStream; saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7]; m_strInstData = saveStream.str(); SaveToDB(); OUT_SAVE_INST_DATA_COMPLETE; } }
void WorldSession::DoLootRelease(uint64 lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld->getRate(RATE_MINING_AMOUNT); float min_amount = go_min*amount_rate; float max_amount = go_max*amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld->getRate(RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate, 4*(1/double(max_amount))*double(uses)); if (roll_chance_f((float)(100*chance+skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* pGroup = player->GetGroup()) { if (pGroup->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; } } else loot->roundRobinPlayer = 0; } } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemPrototype const* proto = pItem->GetProto(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); return; // item can be looted only single player } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; if (loot->isLooted()) { // skip pickpocketing loot for speed, skinning timer redunction is no-op in fact if (!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* pGroup = player->GetGroup()) { if (pGroup->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; pGroup->SendLooter(pCreature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } else loot->roundRobinPlayer = 0; } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
void hyjalAI::UpdateAI(const uint32 uiDiff) { if (!m_bIsEventInProgress) return; if (m_bIsSummoningWaves && m_pInstance) { if (m_uiWaveMoveTimer < uiDiff) { // Skip the master timer, and start next wave in 5. Clear the list, it should not be any here now. if (!m_pInstance->GetData(TYPE_TRASH_COUNT)) { lWaveMobGUIDList.clear(); m_uiNextWaveTimer = std::min(m_uiNextWaveTimer, (uint32)5000); } for (GuidList::const_iterator itr = lWaveMobGUIDList.begin(); itr != lWaveMobGUIDList.end(); ++itr) { if (Creature* pTemp = m_pInstance->instance->GetCreature(*itr)) { if (!pTemp->isAlive() || pTemp->getVictim()) continue; pTemp->SetWalk(false); pTemp->GetMotionMaster()->MovePoint(1, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); } } m_uiWaveMoveTimer = 10000; } else m_uiWaveMoveTimer -= uiDiff; if (m_uiNextWaveTimer < uiDiff) SummonNextWave(); else m_uiNextWaveTimer -= uiDiff; } if (m_uiCheckTimer < uiDiff) { for (uint8 i = 0; i < 2; ++i) { if (m_aBossGuid[i]) { Creature* pBoss = m_creature->GetMap()->GetCreature(m_aBossGuid[i]); if (pBoss && !pBoss->isAlive()) { if (m_aBossGuid[i] == m_aBossGuid[0]) { DoTalk(INCOMING); m_bIsFirstBossDead = true; } else if (m_aBossGuid[i] == m_aBossGuid[1]) { DoTalk(SUCCESS); m_bIsSecondBossDead = true; } m_bIsEventInProgress = false; m_uiCheckTimer = 0; m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); m_aBossGuid[i].Clear(); // Reset world state for enemies to disable it m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); m_creature->SetActiveObjectState(false); } } } m_uiCheckTimer = 5000; } else m_uiCheckTimer -= uiDiff; if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; for (uint8 i = 0; i < MAX_SPELL; ++i) { if (m_aSpells[i].m_uiSpellId) { if (m_uiSpellTimer[i] < uiDiff) { if (m_creature->IsNonMeleeSpellCasted(false)) m_creature->InterruptNonMeleeSpells(false); Unit* pTarget = NULL; switch (m_aSpells[i].m_pType) { case TARGETTYPE_SELF: pTarget = m_creature; break; case TARGETTYPE_RANDOM: pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); break; case TARGETTYPE_VICTIM: pTarget = m_creature->getVictim(); break; } if (pTarget) { DoCastSpellIfCan(pTarget, m_aSpells[i].m_uiSpellId); m_uiSpellTimer[i] = m_aSpells[i].m_uiCooldown; } } else m_uiSpellTimer[i] -= uiDiff; } } DoMeleeAttackIfReady(); }