diff options
author | gvcoman <none@none> | 2008-11-21 19:16:19 -0500 |
---|---|---|
committer | gvcoman <none@none> | 2008-11-21 19:16:19 -0500 |
commit | 9ceb36a5274611e576aa4c5bd4488b9b9bdf18cc (patch) | |
tree | ece878258f15fb5af52e5829e640734dee9c1df2 | |
parent | 1bd37790b564be487ed16ae897484a4d8c80a2de (diff) | |
parent | b2ba78e57a7c1895d1bacf950a3705eedd01c256 (diff) |
Merge with 273 (aab191f73e46).
--HG--
branch : trunk
-rw-r--r-- | sql/updates/273_world_scripts.sql | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/creature/mob_event_ai.cpp | 39 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/creature/mob_event_ai.h | 8 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp | 157 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp | 98 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp | 2 | ||||
-rw-r--r-- | src/game/GridStates.cpp | 8 | ||||
-rw-r--r-- | src/game/Map.cpp | 125 | ||||
-rw-r--r-- | src/game/Map.h | 6 | ||||
-rw-r--r-- | src/game/Object.cpp | 19 | ||||
-rw-r--r-- | src/game/Object.h | 2 | ||||
-rw-r--r-- | src/game/ObjectAccessor.cpp | 44 | ||||
-rw-r--r-- | src/game/ObjectAccessor.h | 6 | ||||
-rw-r--r-- | src/game/Player.h | 2 |
17 files changed, 395 insertions, 129 deletions
diff --git a/sql/updates/273_world_scripts.sql b/sql/updates/273_world_scripts.sql new file mode 100644 index 00000000000..d3188c1306c --- /dev/null +++ b/sql/updates/273_world_scripts.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `ScriptName`='npc_wounded_blood_elf' WHERE `entry`='16993'; +UPDATE `creature_template` SET `ScriptName` = 'mob_phase_hunter' WHERE `entry` = '18879';
\ No newline at end of file diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp index af945282935..289b6b925c5 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp @@ -6,12 +6,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ScriptData @@ -965,6 +965,17 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI DoZoneInCombat(); } break; + + // TRINITY ONLY + case ACTION_T_SET_ACTIVE: + m_creature->setActive(param1 ? true : false); + break; + case ACTION_T_SET_AGGRESSIVE: + m_creature->SetAggressive(param1 ? true : false); + break; + case ACTION_T_ATTACK_START_PULSE: + AttackStart(m_creature->SelectNearestTarget((float)param1)); + break; } } @@ -1192,24 +1203,12 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI } } - if (m_creature->isCivilian() && m_creature->IsNeutralToAll()) - return; - - if (m_creature->canAttack(who) && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who)) - { - if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; + // do we need this? + //if (m_creature->isCivilian() && m_creature->IsNeutralToAll()) + // return; - float attackRadius = m_creature->GetAttackDistance(who); - if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who)) - { - //if(who->HasStealthAura()) - // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - - //Begin melee attack if we are within range - AttackStart(who); - } - } + if(m_creature->canStartAttack(who)) + AttackStart(who); } void SpellHit(Unit* pUnit, const SpellEntry* pSpell) @@ -1292,6 +1291,7 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI //Do not decrement timers if event cannot trigger in this phase if (!((*i).Event.event_inverse_phase_mask & (1 << Phase))) (*i).Time -= EventDiff; + //Skip processing of events that have time remaining continue; } @@ -1328,6 +1328,7 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI //Melee Auto-Attack if (Combat && MeleeEnabled) DoMeleeAttackIfReady(); + } }; diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.h b/src/bindings/scripts/scripts/creature/mob_event_ai.h index 1183fdd3c73..d08a6b33a2b 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.h +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.h @@ -1,6 +1,6 @@ /* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ #ifndef SC_EVENTAI_H #define SC_EVENTAI_H @@ -76,6 +76,10 @@ enum Action_Types ACTION_T_DIE = 37, //No Params ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params + ACTION_T_SET_ACTIVE = 101, //Apply + ACTION_T_SET_AGGRESSIVE = 102, //Apply + ACTION_T_ATTACK_START_PULSE = 103, //Distance + ACTION_T_END, }; diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp index 3ccd790a648..2f92a1e6cd4 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp @@ -301,7 +301,7 @@ void hyjalAI::UpdateWorldState(uint32 field, uint32 value) data << field; data << value; - ((InstanceMap*)map)->SendToPlayers(&data); + map->SendToPlayers(&data); // TODO: Uncomment and remove everything above this line only when the core patch for this is accepted //m_creature->GetMap()->UpdateWorldState(field, value); diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp index 3c3971d6036..66b9a7bfcc3 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp @@ -149,7 +149,7 @@ struct TRINITY_DLL_DECL instance_mount_hyjal : public ScriptedInstance data << field; data << value; - ((InstanceMap*)instance)->SendToPlayers(&data); + instance->SendToPlayers(&data); } const char* Save() diff --git a/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp b/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp index 81d23457aab..d272ac81cb1 100644 --- a/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp +++ b/src/bindings/scripts/scripts/zone/hellfire_peninsula/hellfire_peninsula.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Hellfire_Peninsula SD%Complete: 100 -SDComment: Quest support: 10129, 10146, 10162, 10163, 10340, 10346, 10347, 10382 (Special flight paths) +SDComment: Quest support: 9375, 10129, 10146, 10162, 10163, 10340, 10346, 10347, 10382 (Special flight paths) SDCategory: Hellfire Peninsula EndScriptData */ @@ -25,9 +25,11 @@ EndScriptData */ npc_wing_commander_dabiree npc_gryphoneer_windbellow npc_wing_commander_brack +npc_wounded_blood_elf EndContentData */ #include "precompiled.h" +#include "../../npc/npc_escortAI.h" /*###### ## npc_wing_commander_dabiree @@ -160,6 +162,151 @@ bool GossipSelect_npc_wing_commander_brack(Player *player, Creature *_Creature, } /*###### +## npc_wounded_blood_elf +######*/ + +#define QUEST_THE_ROAD_TO_FALCON_WATCH 9375 +#define SAY1 "Thank you for agreeing to help. Now, let's get out of here $N." +#define SAY2 "Over there! They're following us!" +#define SAY3 "Allow me a moment to rest. The journey taxes what little strength I have." +#define SAY4 "Did you hear something?" +#define SAY5 "Falcon Watch, at last! Now, where's my... Oh no! My pack, it's missing! Where has -" +#define SAYAGGRO "You won't keep me from getting to Falcon Watch!" + +struct TRINITY_DLL_DECL npc_wounded_blood_elfAI : public npc_escortAI +{ + npc_wounded_blood_elfAI(Creature *c) : npc_escortAI(c) {Reset();} + + void WaypointReached(uint32 i) + { + Unit* player = Unit::GetUnit((*m_creature), PlayerGUID); + + if (!player) + return; + + switch (i) + { + + case 0: + DoSay(SAY1, LANG_UNIVERSAL, player); + // Change faction, so mobs can attack + m_creature->setFaction(1610); + break; + + case 9: + DoSay(SAY2, LANG_UNIVERSAL, player); + // Spawn two Haal'eshi Talonguard + { + Creature* temp1 = m_creature->SummonCreature(16967, m_creature->GetPositionX()-15, m_creature->GetPositionY()-15, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + if (temp1) temp1->AI()->AttackStart(m_creature); + Creature* temp2 = m_creature->SummonCreature(16967, m_creature->GetPositionX()-17, m_creature->GetPositionY()-17, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + if (temp2) temp2->AI()->AttackStart(m_creature); + } + break; + + case 13: + DoSay(SAY3, LANG_UNIVERSAL, player); + // NPC "should" kneel + m_creature->HandleEmoteCommand(EMOTE_STATE_KNEEL); + break; + + case 14: + DoSay(SAY4, LANG_UNIVERSAL, player); + // Spawn two Haal'eshi Windwalker + { + Creature* temp3 = m_creature->SummonCreature(16966, m_creature->GetPositionX()-15, m_creature->GetPositionY()-15, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + if (temp3) temp3->AI()->AttackStart(m_creature); + Creature* temp4 = m_creature->SummonCreature(16966, m_creature->GetPositionX()-17, m_creature->GetPositionY()-17, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + if (temp4) temp4->AI()->AttackStart(m_creature); + } + break; + + case 27: + DoSay(SAY5, LANG_UNIVERSAL, player); + // Set faction back to normal + m_creature->setFaction(1604); + // Award quest credit + if( PlayerGUID ) + { + Unit* player = Unit::GetUnit((*m_creature), PlayerGUID); + if( player && player->GetTypeId() == TYPEID_PLAYER ) + ((Player*)player)->GroupEventHappens(9375,m_creature); + } + break; + } + } + + void Aggro(Unit* who) + { + DoSay(SAYAGGRO, LANG_UNIVERSAL, who); + } + + void Reset() { } + + void JustDied(Unit* killer) + // If NPC dies, Quest fail + { + if (PlayerGUID) + { + Unit* player = Unit::GetUnit((*m_creature), PlayerGUID); + if (player) + ((Player*)player)->FailQuest(QUEST_THE_ROAD_TO_FALCON_WATCH); + } + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +bool QuestAccept_wounded_blood_elf(Player* player, Creature* creature, Quest const* quest) +// Begin the escort quest +{ + if (quest->GetQuestId() == QUEST_THE_ROAD_TO_FALCON_WATCH) + { + ((npc_escortAI*)(creature->AI()))->Start(true, true, false, player->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_wounded_blood_elf(Creature *_Creature) +{ + npc_wounded_blood_elfAI* thisAI = new npc_wounded_blood_elfAI(_Creature); + + thisAI->AddWaypoint(0, -1137.72, 4272.10, 14.04, 3000); + thisAI->AddWaypoint(1, -1141.34, 4232.42, 14.63); + thisAI->AddWaypoint(2, -1133.47, 4220.88, 11.78); + thisAI->AddWaypoint(3, -1126.18, 4213.26, 13.51); + thisAI->AddWaypoint(4, -1100.12, 4204.32, 16.41); + thisAI->AddWaypoint(5, -1063.68, 4197.92, 15.51); + thisAI->AddWaypoint(6, -1027.28, 4194.36, 15.52); + thisAI->AddWaypoint(7, -995.68, 4189.59, 19.84); + thisAI->AddWaypoint(8, -970.90, 4188.60, 24.61); + thisAI->AddWaypoint(9, -961.93, 4193.34, 26.11, 80000); // Summon 1 + thisAI->AddWaypoint(10, -935.52, 4210.99, 31.98); + thisAI->AddWaypoint(11, -913.42, 4218.27, 37.29); + thisAI->AddWaypoint(12, -896.53, 4207.73, 43.23); + thisAI->AddWaypoint(13, -868.49, 4194.77, 46.75, 17000); // Kneel and Rest Here + thisAI->AddWaypoint(14, -852.83, 4198.29, 47.28, 80000); // Summon 2 + thisAI->AddWaypoint(15, -819.85, 4200.50, 46.37); + thisAI->AddWaypoint(16, -791.92, 4201.96, 44.19); + thisAI->AddWaypoint(17, -774.42, 4202.46, 47.41); + thisAI->AddWaypoint(18, -762.90, 4202.17, 48.81); + thisAI->AddWaypoint(19, -728.25, 4195.35, 50.68); + thisAI->AddWaypoint(20, -713.58, 4192.07, 53.98); + thisAI->AddWaypoint(21, -703.09, 4189.74, 56.96); + thisAI->AddWaypoint(22, -693.70, 4185.43, 57.06); + thisAI->AddWaypoint(23, -686.38, 4159.81, 60.26); + thisAI->AddWaypoint(24, -679.88, 4147.04, 64.20); + thisAI->AddWaypoint(25, -656.74, 4147.72, 64.11); + thisAI->AddWaypoint(26, -652.22, 4137.50, 64.58); + thisAI->AddWaypoint(27, -649.99, 4136.38, 64.63, 20000); // Award Quest Credit + + return (CreatureAI*)thisAI; +} + +/*###### ## ######*/ @@ -184,4 +331,10 @@ void AddSC_hellfire_peninsula() newscript->pGossipHello = &GossipHello_npc_wing_commander_brack; newscript->pGossipSelect = &GossipSelect_npc_wing_commander_brack; newscript->RegisterSelf(); -} + + newscript = new Script; + newscript->Name="npc_wounded_blood_elf"; + newscript->GetAI = &GetAI_npc_wounded_blood_elf; + newscript->pQuestAccept = &QuestAccept_wounded_blood_elf; + newscript->RegisterSelf(); +}
\ No newline at end of file diff --git a/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp b/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp index 4125c4e888e..fbb4c20379b 100644 --- a/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp +++ b/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp @@ -390,6 +390,99 @@ bool GossipSelect_npc_veronia(Player *player, Creature *_Creature, uint32 sender } /*###### +## mob_phase_hunter +######*/ + +#define SUMMONED_MOB 19595 +#define EMOTE_WEAK "is very weak" + +// Spells +#define SPELL_PHASE_SLIP 36574 +#define SPELL_MANA_BURN 13321 + +struct TRINITY_DLL_DECL mob_phase_hunterAI : public ScriptedAI +{ + + mob_phase_hunterAI(Creature *c) : ScriptedAI(c) {Reset();} + + bool Weak; + int WeakPercent; + uint32 PlayerGUID; + uint32 Health; + uint32 Level; + uint32 PhaseSlipVulnerabilityTimer; + uint32 ManaBurnTimer; + + void Reset() + { + Weak = false; + WeakPercent = 25 + (rand()%16); // 25-40 + PlayerGUID = 0; + ManaBurnTimer = 5000 + (rand()%3 * 1000); // 5-8 sec cd + } + + void Aggro(Unit *who) + { + PlayerGUID = who->GetGUID(); + } + + void UpdateAI(const uint32 diff) + { + + Player* target = NULL; + target = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID)); + + if(!target) + return; + + if(m_creature->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED) || m_creature->hasUnitState(UNIT_STAT_ROOT)) // if the mob is rooted/slowed by spells eg.: Entangling Roots, Frost Nova, Hamstring, Crippling Poison, etc. => remove it + DoCast(m_creature, SPELL_PHASE_SLIP); + if(ManaBurnTimer < diff) // cast Mana Burn + { + if(target->GetCreateMana() > 0) + { + DoCast(target, SPELL_MANA_BURN); + ManaBurnTimer = 8000 + (rand()%10 * 1000); // 8-18 sec cd + } + } + else ManaBurnTimer -= diff; + + if(!Weak && m_creature->GetHealth() < (m_creature->GetMaxHealth() / 100 * WeakPercent) && target->GetQuestStatus(10190) == QUEST_STATUS_INCOMPLETE) // start: support for quest 10190 + { + DoTextEmote(EMOTE_WEAK, 0); + Weak = true; + } + if(Weak && m_creature->HasAura(34219, 0)) + { + Health = m_creature->GetHealth(); // get the normal mob's data + Level = m_creature->getLevel(); + + m_creature->AttackStop(); // delete the normal mob + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + + Creature* DrainedPhaseHunter = NULL; + + if(!DrainedPhaseHunter) + DrainedPhaseHunter = m_creature->SummonCreature(SUMMONED_MOB, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); // summon the mob + + if(DrainedPhaseHunter) + { + DrainedPhaseHunter->SetLevel(Level); // set the summoned mob's data + DrainedPhaseHunter->SetHealth(Health); + DrainedPhaseHunter->AI()->AttackStart(target); + } + } // end: support for quest 10190 + } + +}; + +CreatureAI* GetAI_mob_phase_hunter(Creature *_Creature) +{ + return new mob_phase_hunterAI (_Creature); +} + +/*###### ## ######*/ @@ -418,4 +511,9 @@ void AddSC_netherstorm() newscript->pGossipHello = &GossipHello_npc_veronia; newscript->pGossipSelect = &GossipSelect_npc_veronia; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phase_hunter"; + newscript->GetAI = GetAI_mob_phase_hunter; + newscript->RegisterSelf(); } diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp index 4b9eb2afa88..8f4b4b8d942 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp @@ -169,7 +169,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI WorldPacket data(SMSG_WEATHER, (4+4+4)); data << uint32(weather) << (float)grade << uint8(0); - ((InstanceMap*)map)->SendToPlayers(&data); + map->SendToPlayers(&data); } void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end diff --git a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp index c0c68c1a2e4..bb847169e78 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp @@ -176,7 +176,7 @@ struct TRINITY_DLL_DECL instance_zulaman : public ScriptedInstance { WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8); data << field << value; - ((InstanceMap*)instance)->SendToPlayers(&data); + instance->SendToPlayers(&data); } const char* Save() diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp index 1f2df5e7c59..5cf5c8b8c11 100644 --- a/src/game/GridStates.cpp +++ b/src/game/GridStates.cpp @@ -10,12 +10,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "GridStates.h" @@ -36,7 +36,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { - if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().ActiveObjectsNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) + if( grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y) ) { ObjectGridStoper stoper(grid); stoper.StopN(); @@ -50,7 +50,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c } void -IdleState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &) const +IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &) const { m.ResetGridExpiry(grid); grid.SetGridState(GRID_STATE_REMOVAL); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 39006c932c6..f8201f53219 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -594,57 +594,69 @@ bool Map::loaded(const GridPair &p) const return ( getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord) ); } -void Map::Update(const uint32 &t_diff) +void Map::UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff) { - // TODO: need have an active object list for every map + CellPair standing_cell(Trinity::ComputeCellPair(x, y)); - /*resetMarkedCells(); + // Check for correctness of standing_cell, it also avoids problems with update_cell + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + // will this reduce the speed? Trinity::ObjectUpdater updater(t_diff); // for creature TypeContainerVisitor<Trinity::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater); // for pets TypeContainerVisitor<Trinity::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater); - for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) - { - Player* plr = iter->getSource(); - if(!plr->IsInWorld()) - continue; - - CellPair standing_cell(Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY())); - - // Check for correctness of standing_cell, it also avoids problems with update_cell - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - continue; + // the overloaded operators handle range checking + // so ther's no need for range checking inside the loop + CellPair begin_cell(standing_cell), end_cell(standing_cell); + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right - // the overloaded operators handle range checking - // so ther's no need for range checking inside the loop - CellPair begin_cell(standing_cell), end_cell(standing_cell); - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; end_cell += 1; // lower right - - for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) { - for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + // marked cells are those that have been visited + // don't visit the same cell twice + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if(!isCellMarked(cell_id)) { - // marked cells are those that have been visited - // don't visit the same cell twice - uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; - if(!isCellMarked(cell_id)) - { - markCell(cell_id); - CellPair pair(x,y); - Cell cell(pair); - cell.data.Part.reserved = CENTER_DISTRICT; - cell.SetNoCreate(); - CellLock<NullGuard> cell_lock(cell, pair); - cell_lock->Visit(cell_lock, grid_object_update, *this); - cell_lock->Visit(cell_lock, world_object_update, *this); - } + markCell(cell_id); + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + cell.SetNoCreate(); + CellLock<NullGuard> cell_lock(cell, pair); + cell_lock->Visit(cell_lock, grid_object_update, *this); + cell_lock->Visit(cell_lock, world_object_update, *this); } } - }*/ + } +} + +void Map::Update(const uint32 &t_diff) +{ + resetMarkedCells(); + + // update cells around players + for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) + { + Player* plr = iter->getSource(); + if(plr->IsInWorld()) + UpdateActiveCells(plr->GetPositionX(), plr->GetPositionY(), t_diff); + } + + // update cells around active objects + // clone the active object list, because update might remove from it + std::set<WorldObject *> activeObjects(i_activeObjects); + for(std::set<WorldObject *>::iterator iter = activeObjects.begin(); iter != activeObjects.end(); ++iter) + { + if((*iter)->IsInWorld()) + UpdateActiveCells((*iter)->GetPositionX(), (*iter)->GetPositionY(), t_diff); + } // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended @@ -813,8 +825,13 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang #endif AddCreatureToMoveList(creature,x,y,z,ang); // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList - if(creature->isPossessedByPlayer()) - EnsureGridLoadedForPlayer(new_cell, (Player*)creature->GetCharmer(), false); + if(creature->isActive()) + { + if(creature->isPossessedByPlayer()) + EnsureGridLoadedForPlayer(new_cell, (Player*)creature->GetCharmer(), false); + else + EnsureGridLoadedForPlayer(new_cell, NULL, false); + } } else { @@ -1509,6 +1526,36 @@ bool Map::PlayersNearGrid(uint32 x, uint32 y) const return false; } +bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const +{ + CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + cell_min << 2; + cell_min -= 2; + cell_max >> 2; + cell_max += 2; + + for(MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) + { + Player* plr = iter->getSource(); + + CellPair p = Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY()); + if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && + (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) ) + return true; + } + + for(std::set<WorldObject*>::const_iterator itr = i_activeObjects.begin(); itr != i_activeObjects.end(); ++itr) + { + CellPair p = Trinity::ComputeCellPair((*itr)->GetPositionX(), (*itr)->GetPositionY()); + if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && + (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) ) + return true; + } + + return false; +} + template void Map::Add(Corpse *); template void Map::Add(Creature *); template void Map::Add(GameObject *); diff --git a/src/game/Map.h b/src/game/Map.h index 6e0e9cb37a9..cd476f5e3c6 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -242,6 +242,10 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } uint32 GetPlayersCountExceptGMs() const; bool PlayersNearGrid(uint32 x,uint32 y) const; + bool ActiveObjectsNearGrid(uint32 x, uint32 y) const; + + void AddActiveObject(WorldObject* obj) { i_activeObjects.insert(obj); } + void RemoveActiveObject(WorldObject* obj) { i_activeObjects.erase(obj); } void SendToPlayers(WorldPacket const* data) const; @@ -287,6 +291,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O inline void setNGrid(NGridType* grid, uint32 x, uint32 y); + void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff); protected: typedef Trinity::ObjectLevelLockable<Map, ZThread::Mutex>::Lock Guard; @@ -307,6 +312,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O time_t i_gridExpiry; + std::set<WorldObject *> i_activeObjects; std::set<WorldObject *> i_objectsToRemove; // Type specific code for add/remove to/from grid diff --git a/src/game/Object.cpp b/src/game/Object.cpp index ea59a448f7f..cc754f32bd3 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -990,36 +990,37 @@ WorldObject::WorldObject() WorldObject::~WorldObject() { - if(m_isActive && IsInWorld()) - ObjectAccessor::Instance().RemoveActiveObject(this); + if(m_isActive && !isType(TYPEMASK_PLAYER) && IsInWorld()) + GetMap()->RemoveActiveObject(this); } void WorldObject::setActive(bool isActive) { // if already in the same activity state as we try to set, do nothing - if(isActive == m_isActive) + if(isActive == m_isActive || isType(TYPEMASK_PLAYER)) return; + m_isActive = isActive; if(IsInWorld()) { if(isActive) - ObjectAccessor::Instance().AddActiveObject(this); + GetMap()->AddActiveObject(this); else - ObjectAccessor::Instance().RemoveActiveObject(this); + GetMap()->RemoveActiveObject(this); } } void WorldObject::AddToWorld() { Object::AddToWorld(); - if(m_isActive) - ObjectAccessor::Instance().AddActiveObject(this); + if(m_isActive && !isType(TYPEMASK_PLAYER)) + GetMap()->AddActiveObject(this); } void WorldObject::RemoveFromWorld() { - if(m_isActive) - ObjectAccessor::Instance().RemoveActiveObject(this); + if(m_isActive && !isType(TYPEMASK_PLAYER)) + GetMap()->RemoveActiveObject(this); Object::RemoveFromWorld(); } diff --git a/src/game/Object.h b/src/game/Object.h index 2d8f3a134e6..43ecca2afb0 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -455,7 +455,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime); bool isActive() const { return m_isActive; } - virtual void setActive(bool isActive); + void setActive(bool isActive); protected: explicit WorldObject(); std::string m_name; diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 8d9f3f63fc2..75f0d697771 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -487,24 +487,10 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid) } void -ObjectAccessor::AddActiveObject( WorldObject * obj ) -{ - i_activeobjects.insert(obj); -} - -void -ObjectAccessor::RemoveActiveObject( WorldObject * obj ) -{ - i_activeobjects.erase(obj); -} - -void ObjectAccessor::Update(uint32 diff) { - - { +/* { //Player update now in MapManager -> UpdatePlayers - /* // player update might remove the player from grid, and that causes crashes. We HAVE to update players first, and then the active objects. HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer(); for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter) @@ -513,7 +499,7 @@ ObjectAccessor::Update(uint32 diff) { iter->second->Update(diff); } - }*/ + } // TODO: move this to Map::Update // clone the active object list, because update might remove from it @@ -574,7 +560,7 @@ ObjectAccessor::Update(uint32 diff) } } } - } + }*/ UpdateDataMapType update_players; { @@ -608,30 +594,6 @@ ObjectAccessor::UpdatePlayers(uint32 diff) iter->second->Update(diff); } -bool -ObjectAccessor::ActiveObjectsNearGrid(uint32 x, uint32 y, uint32 m_id, uint32 i_id) const -{ - CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); - CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); - cell_min << 2; - cell_min -= 2; - cell_max >> 2; - cell_max += 2; - - for(std::set<WorldObject*>::const_iterator itr = i_activeobjects.begin(); itr != i_activeobjects.end(); ++itr) - { - if( m_id != (*itr)->GetMapId() || i_id != (*itr)->GetInstanceId() ) - continue; - - CellPair p = Trinity::ComputeCellPair((*itr)->GetPositionX(), (*itr)->GetPositionY()); - if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && - (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) ) - return true; - } - - return false; -} - void ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m) { diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 89ea6d1e43d..21ede723da5 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -194,16 +194,11 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor void AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map); Corpse* ConvertCorpseForPlayer(uint64 player_guid); - bool ActiveObjectsNearGrid(uint32 x,uint32 y,uint32 m_id,uint32 i_id) const; - static void UpdateObject(Object* obj, Player* exceptPlayer); static void _buildUpdateObject(Object* obj, UpdateDataMapType &); static void UpdateObjectVisibility(WorldObject* obj); static void UpdateVisibilityForPlayer(Player* player); - - void AddActiveObject(WorldObject*); - void RemoveActiveObject(WorldObject*); private: struct WorldObjectChangeAccumulator { @@ -228,7 +223,6 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor static void _buildPacket(Player *, Object *, UpdateDataMapType &); void _update(void); std::set<Object *> i_objects; - std::set<WorldObject *> i_activeobjects; LockType i_playerGuard; LockType i_updateGuard; LockType i_corpseGuard; diff --git a/src/game/Player.h b/src/game/Player.h index 87f0ad11ae8..540d569ebbf 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -897,8 +897,6 @@ class TRINITY_DLL_SPEC Player : public Unit void AddToWorld(); void RemoveFromWorld(); - // always active - void setActive(bool) {} void SetViewport(uint64 guid, bool movable); void Possess(Unit *target); |