diff options
author | megamage <none@none> | 2008-11-18 19:40:06 -0600 |
---|---|---|
committer | megamage <none@none> | 2008-11-18 19:40:06 -0600 |
commit | ea68727d27e699200236b3b7ecbe36b7f7061cfc (patch) | |
tree | efacc175380a18af301a91170bc35cb851a64701 | |
parent | 78f343397c5d5e4cb99e84a9ebecc299e988e13d (diff) |
*Merge from Mangos. Add MapReference. Author: hunuza.
*Also re-commit the patches reverted in 255.
--HG--
branch : trunk
39 files changed, 944 insertions, 755 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index 1ee90c41029..0c946b8f26d 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -679,13 +679,11 @@ void ScriptedAI::DoZoneInCombat(Unit* pUnit) return; } - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; - for (i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if((*i)->isAlive()) - pUnit->AddThreat(*i, 0.0f); - } + Map::PlayerList const &PlayerList = map->GetPlayers();
+ for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ if (Player* i_pl = i->getSource())
+ if (!i_pl->isAlive())
+ pUnit->AddThreat(i_pl, 0.0f); } void ScriptedAI::DoResetThreat() @@ -721,6 +719,20 @@ void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float ((Player*)pUnit)->TeleportTo(pUnit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT); } +void ScriptedAI::DoTeleportAll(float x, float y, float z, float o) +{ + Map *map = m_creature->GetMap(); + if (!map->IsDungeon()) + return; + + Map::PlayerList const &PlayerList = map->GetPlayers();
+ for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ if (Player* i_pl = i->getSource())
+ if (!i_pl->isAlive())
+ i_pl->TeleportTo(m_creature->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT); +} + + Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) { CellPair p(Trinity::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h index 99ca4672f65..c1d7f06f029 100644 --- a/src/bindings/scripts/include/sc_creature.h +++ b/src/bindings/scripts/include/sc_creature.h @@ -146,6 +146,7 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI //Teleports a player without dropping threat (only teleports to same map) void DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o); + void DoTeleportAll(float x, float y, float z, float o); //Returns friendly unit with the most amount of hp missing from max hp Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff = 1); diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp index 16bd012e576..79553b85ff2 100644 --- a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp @@ -220,18 +220,7 @@ struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI if ( DrawnShadows_Timer < diff) { - Map *map = m_creature->GetMap(); - if(map->IsDungeon()) - { - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if((*i)->isAlive()) - { - (*i)->TeleportTo(555,VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0); - } - } - } + DoTeleportAll(VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0); m_creature->Relocate(VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0); DoCast(m_creature,SPELL_DRAWN_SHADOWS,true); diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp index 6adc833e8a8..49f750acb6c 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp @@ -250,12 +250,12 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI { //remove old tainted cores to prevent cheating in phase 2 Map *map = m_creature->GetMap(); - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - for(InstanceMap::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i) + Map::PlayerList const &PlayerList = map->GetPlayers(); + for(Map::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i) { - if((*i)) + if(Player* i_pl = i->getSource()) { - (*i)->DestroyItemCount(31088, 1, true); + i_pl->DestroyItemCount(31088, 1, true); } } } diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp index 53aa7c48d35..913eef3ec4e 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp @@ -754,19 +754,22 @@ struct TRINITY_DLL_DECL mob_greyheart_spellbinderAI : public ScriptedAI if(Earthshock_Timer < diff) { Map *map = m_creature->GetMap(); - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - for(InstanceMap::PlayerList::const_iterator itr = PlayerList.begin();itr != PlayerList.end(); ++itr) + Map::PlayerList const &PlayerList = map->GetPlayers(); + for(Map::PlayerList::const_iterator itr = PlayerList.begin();itr != PlayerList.end(); ++itr) { - bool isCasting = false; - for(uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) - if((*itr)->m_currentSpells[i]) - isCasting = true; - - if(isCasting) - { - DoCast((*itr), SPELL_EARTHSHOCK); - break; - } + if (Player* i_pl = itr->getSource()) + { + bool isCasting = false; + for(uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) + if(i_pl->m_currentSpells[i]) + isCasting = true; + + if(isCasting) + { + DoCast(i_pl, SPELL_EARTHSHOCK); + break; + } + } } Earthshock_Timer = 8000 + rand()%7000; }else Earthshock_Timer -= diff; diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp index 8a6815e068a..d8f598f451e 100644 --- a/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp @@ -118,9 +118,6 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance void SetData(uint32 type, uint32 data) { - Player *player = GetPlayer(); - if(!player) return; - switch(type) { case DATA_MAGTHERIDON_EVENT: @@ -129,7 +126,7 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance RespawnTimer = 10000; if(data != IN_PROGRESS) { - if(GameObject *Door = GameObject::GetGameObject(*player, DoorGUID)) + if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID)) Door->SetGoState(0); } break; @@ -142,7 +139,7 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance Encounters[1] = NOT_STARTED; for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { - if(Creature *Channeler = (Creature*)Unit::GetUnit(*player, *i)) + if(Creature *Channeler = instance->GetCreatureInMap(*i)) { if(Channeler->isAlive()) Channeler->AI()->EnterEvadeMode(); @@ -151,7 +148,7 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance } } CageTimer = 0; - if(GameObject *Door = GameObject::GetGameObject(*player, DoorGUID)) + if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID)) Door->SetGoState(0); }break; case IN_PROGRESS: // Event start. @@ -161,7 +158,7 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance // Let all five channelers aggro. for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { - Creature *Channeler = (Creature*)Unit::GetUnit(*player, *i); + Creature *Channeler = instance->GetCreatureInMap(*i); if(Channeler && Channeler->isAlive()) { //if(Unit *target = Channeler->SelectNearbyTarget()) @@ -170,19 +167,19 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance } } // Release Magtheridon after two minutes. - Creature *Magtheridon = (Creature*)Unit::GetUnit(*player, MagtheridonGUID); + Creature *Magtheridon = instance->GetCreatureInMap(MagtheridonGUID); if(Magtheridon && Magtheridon->isAlive()) { Magtheridon->TextEmote("'s bonds begin to weaken!", 0); CageTimer = 120000; } - if(GameObject *Door = GameObject::GetGameObject(*player, DoorGUID)) + if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID)) Door->SetGoState(1); }break; case DONE: // Add buff and check if all channelers are dead. for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { - Unit *Channeler = Unit::GetUnit(*player, *i); + Creature *Channeler = instance->GetCreatureInMap(*i); if(Channeler && Channeler->isAlive()) { //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); @@ -197,7 +194,7 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance // true - collapse / false - reset for(std::set<uint64>::iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) { - if(GameObject *Column = GameObject::GetGameObject(*player, *i)) + if(GameObject *Column = instance->GetGameObjectInMap(*i)) Column->SetGoState(!data); } break; @@ -213,30 +210,26 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance return 0; } - Player* GetPlayer() - { - if(((InstanceMap*)instance)->GetPlayers().size()) - return ((InstanceMap*)instance)->GetPlayers().front(); - return NULL; - } - void AttackNearestTarget(Creature *creature) { float minRange = 999.0f; float range; Player* target = NULL; - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)instance)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; + Map::PlayerList const &PlayerList = instance->GetPlayers(); + Map::PlayerList::const_iterator i; for(i = PlayerList.begin(); i != PlayerList.end(); ++i) { - if((*i)->isTargetableForAttack()) + if(Player* i_pl = i->getSource()) { - range = (*i)->GetDistance(creature); - if(range < minRange) + if(i_pl->isTargetableForAttack()) { - minRange = range; - target = *i; - } + range = i_pl->GetDistance(creature); + if(range < minRange) + { + minRange = range; + target = i_pl; + } + } } } creature->AI()->AttackStart(target); @@ -248,14 +241,11 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance { if(CageTimer <= diff) { - if(Player *player = GetPlayer()) + Creature *Magtheridon = instance->GetCreatureInMap(MagtheridonGUID); + if(Magtheridon && Magtheridon->isAlive()) { - Creature *Magtheridon = (Creature*)Unit::GetUnit(*player, MagtheridonGUID); - if(Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->clearUnitState(UNIT_STAT_STUNNED); - AttackNearestTarget(Magtheridon); - } + Magtheridon->clearUnitState(UNIT_STAT_STUNNED); + AttackNearestTarget(Magtheridon); } CageTimer = 0; }else CageTimer -= diff; @@ -265,17 +255,14 @@ struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance { if(RespawnTimer <= diff) { - if(Player *player = GetPlayer()) + for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) { - for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + if(Creature *Channeler = instance->GetCreatureInMap(*i)) { - if(Creature *Channeler = (Creature*)Unit::GetUnit(*player, *i)) - { - if(Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } + if(Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); } } RespawnTimer = 0; diff --git a/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp b/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp index b0ab0d86db5..704a142cec9 100644 --- a/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp @@ -285,18 +285,18 @@ struct TRINITY_DLL_DECL npc_barnesAI : public npc_escortAI Map *map = m_creature->GetMap(); if(!map->IsDungeon()) return; - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - if(PlayerList.empty()) + Map::PlayerList const &PlayerList = map->GetPlayers(); + if(PlayerList.isEmpty()) return; RaidWiped = true; - for(InstanceMap::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i) - { - if((*i)->isAlive() && !(*i)->isGameMaster()) - { - RaidWiped = false; - break; - } + for(Map::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i)
+ {
+ if (i->getSource()->isAlive() && !i->getSource()->isGameMaster())
+ {
+ RaidWiped = false;
+ break;
+ }
} if(RaidWiped) diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp index 7a44e04dd6d..6bfb0d6464d 100644 --- a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp @@ -231,17 +231,17 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI float x,y,z; m_creature->Relocate(KaelLocations[0][0], KaelLocations[0][1], LOCATION_Z, 0); Map *map = m_creature->GetMap(); - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; + Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList::const_iterator i; for (i = PlayerList.begin(); i != PlayerList.end(); ++i) { - //if(!(*i)->isGameMaster()) - if((*i) && (*i)->isAlive()) - { - (*i)->CastSpell((*i), SPELL_TELEPORT_CENTER, true); - m_creature->GetNearPoint(m_creature,x,y,z,5,5,0); - (*i)->TeleportTo(m_creature->GetMapId(),x,y,LOCATION_Z,(*i)->GetOrientation()); - } + if (Player* i_pl = i->getSource()) + if(i_pl->isAlive()) + { + i_pl->CastSpell(i_pl, SPELL_TELEPORT_CENTER, true); + m_creature->GetNearPoint(m_creature,x,y,z,5,5,0); + i_pl->TeleportTo(m_creature->GetMapId(),x,y,LOCATION_Z,i_pl->GetOrientation()); + } } DoCast(m_creature, SPELL_TELEPORT_CENTER, true); } @@ -249,34 +249,38 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI void CastGravityLapseKnockUp() { Map *map = m_creature->GetMap(); - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; + Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList::const_iterator i; for (i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if((*i) && (*i)->isAlive()) + { + if (Player* i_pl = i->getSource()) + if(i_pl->isAlive()) // Knockback into the air - (*i)->CastSpell((*i), SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, m_creature->GetGUID()); + i_pl->CastSpell(i_pl, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, m_creature->GetGUID()); } } void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... { Map *map = m_creature->GetMap(); - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; + Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList::const_iterator i; for (i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if((*i) && (*i)->isAlive()) + { + if (Player* i_pl = i->getSource()) { - // Also needs an exception in spell system. - (*i)->CastSpell((*i), SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, m_creature->GetGUID()); - // Use packet hack - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - data.append((*i)->GetPackGUID()); - data << uint32(0); - (*i)->SendMessageToSet(&data, true); - (*i)->SetSpeed(MOVE_FLY, 2.0f); + if(i_pl->isAlive()) + { + // Also needs an exception in spell system. + i_pl->CastSpell(i_pl, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, m_creature->GetGUID()); + // Use packet hack + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(i_pl->GetPackGUID()); + data << uint32(0); + i_pl->SendMessageToSet(&data, true); + i_pl->SetSpeed(MOVE_FLY, 2.0f); + } } } } @@ -284,19 +288,19 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI void RemoveGravityLapse() { Map *map = m_creature->GetMap(); - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; + Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList::const_iterator i; for (i = PlayerList.begin(); i != PlayerList.end(); ++i) { - if((*i)) + if(Player* i_pl = i->getSource()) { - (*i)->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); - (*i)->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); + i_pl->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); + i_pl->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); WorldPacket data(12); data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - data.append((*i)->GetPackGUID()); + data.append(i_pl->GetPackGUID()); data << uint32(0); - (*i)->SendMessageToSet(&data, true); + i_pl->SendMessageToSet(&data, true); } } } diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp index e703b4b6c26..afc95cc8191 100644 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp @@ -295,7 +295,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI Timer[EVENT_FLIGHT_SEQUENCE] = 0; break; case 2: - if(Player* target = SelectRandomPlayer(150)) + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true)) { Creature* Vapor = m_creature->SummonCreature(MOB_VAPOR, target->GetPositionX()-5+rand()%10, target->GetPositionY()-5+rand()%10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); if(Vapor) @@ -311,7 +311,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI case 3: DespawnSummons(MOB_VAPOR_TRAIL); //m_creature->CastSpell(m_creature, SPELL_VAPOR_SELECT); need core support - if(Player* target = SelectRandomPlayer(150)) + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true)) { //target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support Creature* Vapor = m_creature->SummonCreature(MOB_VAPOR, target->GetPositionX()-5+rand()%10, target->GetPositionY()-5+rand()%10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); @@ -330,7 +330,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI Timer[EVENT_FLIGHT_SEQUENCE] = 1; break; case 5: - if(Player* target = SelectRandomPlayer(150)) + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true)) { BreathX = target->GetPositionX(); BreathY = target->GetPositionY(); @@ -433,7 +433,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI Timer[EVENT_GAS_NOVA] = 20000 + rand()%5 * 1000; break; case EVENT_ENCAPSULATE: - if(Unit* target = SelectRandomPlayer(150)) + if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true)) { m_creature->CastSpell(target, SPELL_ENCAPSULATE_CHANNEL, false); target->CastSpell(target, SPELL_ENCAPSULATE_EFFECT, true);// linked aura, need core patch to remove this hack @@ -515,26 +515,6 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI (*i)->RemoveCorpse(); } } - - Player* SelectRandomPlayer(float range = 0.0f) - { - Map *map = m_creature->GetMap(); - if (!map->IsDungeon()) return NULL; - - InstanceMap::PlayerList PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::iterator i; - while(PlayerList.size()) - { - i = PlayerList.begin(); - advance(i, rand()%PlayerList.size()); - if((range == 0.0f || m_creature->IsWithinDistInMap(*i, range)) - && (*i)->isTargetableForAttack()) - return *i; - else - PlayerList.erase(i); - } - return NULL; - } }; struct TRINITY_DLL_DECL mob_felmyst_vaporAI : public ScriptedAI diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp index f3911b9b865..96a79107296 100644 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp @@ -368,13 +368,12 @@ struct TRINITY_DLL_DECL boss_sathrovarrAI : public ScriptedAI { Map *map = m_creature->GetMap(); if(!map->IsDungeon()) return; - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::const_iterator i; - for (i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if((*i)->HasAura(AURA_SPECTRAL_REALM,0)) - (*i)->RemoveAurasDueToSpell(AURA_SPECTRAL_REALM); - } + Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList::const_iterator i; + for(i = PlayerList.begin(); i != PlayerList.end(); ++i) + if(Player* i_pl = i->getSource()) + if(i_pl->HasAura(AURA_SPECTRAL_REALM,0)) + i_pl->RemoveAurasDueToSpell(AURA_SPECTRAL_REALM); } void Enrage(); // demon and dragon should enrage at the same time diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp index 0116947e390..3548cf92566 100644 --- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp @@ -577,20 +577,23 @@ struct TRINITY_DLL_DECL cthunAI : public Scripted_NoMovementAI Map *map = m_creature->GetMap(); if(!map->IsDungeon()) return; - InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); - for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + Map::PlayerList const &PlayerList = map->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - //Play random sound to the zone - switch (rand()%8) + if (Player* i_pl = i->getSource()) { - case 0: (*i)->SendPlaySound(RND_WISPER_1, true); break; - case 1: (*i)->SendPlaySound(RND_WISPER_2, true); break; - case 2: (*i)->SendPlaySound(RND_WISPER_3, true); break; - case 3: (*i)->SendPlaySound(RND_WISPER_4, true); break; - case 4: (*i)->SendPlaySound(RND_WISPER_5, true); break; - case 5: (*i)->SendPlaySound(RND_WISPER_6, true); break; - case 6: (*i)->SendPlaySound(RND_WISPER_7, true); break; - case 7: (*i)->SendPlaySound(RND_WISPER_8, true); break; + //Play random sound to the zone + switch (rand()%8) + { + case 0: i_pl->SendPlaySound(RND_WISPER_1, true); break; + case 1: i_pl->SendPlaySound(RND_WISPER_2, true); break; + case 2: i_pl->SendPlaySound(RND_WISPER_3, true); break; + case 3: i_pl->SendPlaySound(RND_WISPER_4, true); break; + case 4: i_pl->SendPlaySound(RND_WISPER_5, true); break; + case 5: i_pl->SendPlaySound(RND_WISPER_6, true); break; + case 6: i_pl->SendPlaySound(RND_WISPER_7, true); break; + case 7: i_pl->SendPlaySound(RND_WISPER_8, true); break; + } } } diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp index d0a78f3c848..781a0c812ba 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp @@ -371,7 +371,7 @@ struct TRINITY_DLL_DECL boss_hex_lord_malacrassAI : public ScriptedAI if(SiphonSoul_Timer < diff) { - Player* target = SelectRandomPlayer(50); + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 70, true); Unit *trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); if(!target || !trigger) EnterEvadeMode(); else @@ -435,26 +435,6 @@ struct TRINITY_DLL_DECL boss_hex_lord_malacrassAI : public ScriptedAI } m_creature->CastSpell(target, PlayerAbility[PlayerClass][random].spell, false); } - - Player* SelectRandomPlayer(float range = 0.0f, bool alive = true) - { - Map *map = m_creature->GetMap(); - if (!map->IsDungeon()) return NULL; - - InstanceMap::PlayerList PlayerList = ((InstanceMap*)map)->GetPlayers(); - InstanceMap::PlayerList::iterator i; - while(PlayerList.size()) - { - i = PlayerList.begin(); - advance(i, rand()%PlayerList.size()); - if((range == 0.0f || m_creature->IsWithinDistInMap(*i, range)) - && (!alive || (*i)->isAlive())) - return *i; - else - PlayerList.erase(i); - } - return NULL; - } }; #define SPELL_BLOODLUST 43578 diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp index 0b460404f92..8cc7efb233b 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp @@ -397,11 +397,12 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI //Teleport every Player into the middle Map *map = m_creature->GetMap(); if(!map->IsDungeon()) return; - InstanceMap::PlayerList const &PlayerList =((InstanceMap*)map)->GetPlayers(); - for(InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + Map::PlayerList const &PlayerList = map->GetPlayers(); + for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - if((*i)->isAlive()) - DoTeleportPlayer(*i, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); + if (Player* i_pl = i->getSource()) + if(i_pl->isAlive()) + DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); } //m_creature->CastSpell(Temp, SPELL_SUMMON_PLAYERS, true); // core bug, spell does not work if too far return; diff --git a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp index 2e9e481236f..2abf2d8becf 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp @@ -139,21 +139,28 @@ struct TRINITY_DLL_DECL instance_zulaman : public ScriptedInstance void OpenDoor(uint64 DoorGUID, bool open) { - if(((InstanceMap*)instance)->GetPlayers().size()) - if(Player* first = ((InstanceMap*)instance)->GetPlayers().front()) - if(GameObject *Door = GameObject::GetGameObject(*first, DoorGUID)) - Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1); + if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID)) + Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1); } void SummonHostage(uint8 num) { - if(QuestMinute && ((InstanceMap*)instance)->GetPlayers().size()) - if(Player* first = ((InstanceMap*)instance)->GetPlayers().front()) - if(Unit* Hostage = first->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0)) - { - Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } + if(!QuestMinute) + return; +
+ Map::PlayerList const &PlayerList = instance->GetPlayers();
+ if (PlayerList.isEmpty())
+ return;
+
+ Map::PlayerList::const_iterator i = PlayerList.begin(); + if(Player* i_pl = i->getSource()) + { + if(Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + } } void CheckInstanceStatus() diff --git a/src/framework/Utilities/LinkedReference/RefManager.h b/src/framework/Utilities/LinkedReference/RefManager.h index 40b7cade914..599c4efab39 100644 --- a/src/framework/Utilities/LinkedReference/RefManager.h +++ b/src/framework/Utilities/LinkedReference/RefManager.h @@ -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 */ #ifndef _REFMANAGER_H @@ -33,7 +33,9 @@ template <class TO, class FROM> class RefManager : public LinkedListHead virtual ~RefManager() { clearReferences(); } Reference<TO, FROM>* getFirst() { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); } + Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); } Reference<TO, FROM>* getLast() { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); } + Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); } iterator begin() { return iterator(getFirst()); } iterator end() { return iterator(NULL); } diff --git a/src/framework/Utilities/LinkedReference/Reference.h b/src/framework/Utilities/LinkedReference/Reference.h index 8e969669b99..ca837c81f91 100644 --- a/src/framework/Utilities/LinkedReference/Reference.h +++ b/src/framework/Utilities/LinkedReference/Reference.h @@ -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 */ #ifndef _REFERENCE_H @@ -74,6 +74,7 @@ template <class TO, class FROM> class Reference : public LinkedListElement } Reference<TO,FROM>* next() { return((Reference<TO,FROM>*)LinkedListElement::next()); } + Reference<TO,FROM>const* next() const { return((Reference<TO,FROM> const*)LinkedListElement::next()); } Reference<TO,FROM>* prev() { return((Reference<TO,FROM>*)LinkedListElement::prev()); } inline TO* operator ->() const { return iRefTo; } diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 80bd52a14fe..e53ed1d21e6 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -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 */ #ifndef __BATTLEGROUND_H @@ -95,7 +95,8 @@ enum BattleGroundTimeIntervals START_DELAY3 = 15000, // ms used only in arena RESPAWN_ONE_DAY = 86400, // secs RESPAWN_IMMEDIATELY = 0, // secs - BUFF_RESPAWN_TIME = 180 // secs + BUFF_RESPAWN_TIME = 180, // secs + BG_HONOR_SCORE_TICKS = 330 // points }; enum BattleGroundBuffObjects @@ -433,7 +434,6 @@ class BattleGround virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; } virtual void AddPlayer(Player *plr); // must be implemented in BG subclass - virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); // can be extended in in BG subclass diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index 42607095e65..4762bf1e26a 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -78,7 +78,7 @@ enum ItemBondingType { NO_BIND = 0, BIND_WHEN_PICKED_UP = 1, - BIND_WHEN_EQUIPPED = 2, + BIND_WHEN_EQUIPED = 2, BIND_WHEN_USE = 3, BIND_QUEST_ITEM = 4, BIND_QUEST_ITEM1 = 5 // not used in game diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 7b3e40c00b3..ba72775b5cf 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -35,6 +35,7 @@ #include "World.h" #include "ScriptCalls.h" #include "Group.h" +#include "MapRefManager.h" #include "MapInstanced.h" #include "InstanceSaveMgr.h" @@ -449,6 +450,8 @@ Map::LoadGrid(const Cell& cell, bool no_unload) bool Map::Add(Player *player) { + player->GetMapRef().link(this, player); + player->SetInstanceId(GetInstanceId()); // update player state for other player and visa-versa @@ -593,6 +596,55 @@ bool Map::loaded(const GridPair &p) const void Map::Update(const uint32 &t_diff) { + resetMarkedCells(); + + 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 + + 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) + { + // 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); + } + } + } + } + + // 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 if (IsBattleGroundOrArena()) @@ -610,6 +662,7 @@ void Map::Update(const uint32 &t_diff) void Map::Remove(Player *player, bool remove) { + player->GetMapRef().unlink(); CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) { @@ -909,7 +962,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) assert( grid != NULL); { - if(!pForce && ObjectAccessor::Instance().ActiveObjectsNearGrid(x, y, i_id, i_InstanceId) ) + if(!pForce && PlayersNearGrid(x, y) ) return false; DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id); @@ -1418,6 +1471,43 @@ bool Map::CanUnload(const uint32 &diff) return false; } +uint32 Map::GetPlayersCountExceptGMs() const +{ + uint32 count = 0; + for(MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + if(!itr->getSource()->isGameMaster()) + ++count; + return count; +} + +void Map::SendToPlayers(WorldPacket const* data) const +{ + for(MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->GetSession()->SendPacket(data); +} + +bool Map::PlayersNearGrid(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; + } + + return false; +} + template void Map::Add(Corpse *); template void Map::Add(Creature *); template void Map::Add(GameObject *); @@ -1453,7 +1543,7 @@ InstanceMap::~InstanceMap() */ bool InstanceMap::CanEnter(Player *player) { - if(std::find(i_Players.begin(),i_Players.end(),player)!=i_Players.end()) + if(player->GetMapRef().getTarget() == this) { sLog.outError("InstanceMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode()); assert(false); @@ -1570,7 +1660,6 @@ bool InstanceMap::Add(Player *player) if(i_data) i_data->OnPlayerEnter(player); SetResetSchedule(false); - i_Players.push_back(player); player->SendInitWorldStates(); sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName()); // initialize unload state @@ -1595,9 +1684,9 @@ void InstanceMap::Update(const uint32& t_diff) void InstanceMap::Remove(Player *player, bool remove) { sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName()); - i_Players.remove(player); SetResetSchedule(true); - if(!m_unloadTimer && i_Players.empty()) + //if last player set unload timer + if(!m_unloadTimer && m_mapRefManager.getSize() == 1) m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); Map::Remove(player, remove); } @@ -1662,21 +1751,21 @@ bool InstanceMap::Reset(uint8 method) // note: since the map may not be loaded when the instance needs to be reset // the instance must be deleted from the DB by InstanceSaveManager - if(!i_Players.empty()) + if(HavePlayers()) { if(method == INSTANCE_RESET_ALL) { // notify the players to leave the instance so it can be reset - for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) - (*itr)->SendResetFailedNotify(GetId()); + for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->SendResetFailedNotify(GetId()); } else { if(method == INSTANCE_RESET_GLOBAL) { // set the homebind timer for players inside (1 minute) - for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) - (*itr)->m_InstanceValid = false; + for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->m_InstanceValid = false; } // the unload timer is not started @@ -1692,16 +1781,7 @@ bool InstanceMap::Reset(uint8 method) m_resetAfterUnload = true; } - return i_Players.empty(); -} - -uint32 InstanceMap::GetPlayersCountExceptGMs() const -{ - uint32 count = 0; - for(PlayerList::const_iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) - if(!(*itr)->isGameMaster()) - ++count; - return count; + return m_mapRefManager.isEmpty(); } void InstanceMap::PermBindAllPlayers(Player *player) @@ -1715,25 +1795,23 @@ void InstanceMap::PermBindAllPlayers(Player *player) Group *group = player->GetGroup(); // group members outside the instance group don't get bound - for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) + for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) { - if(*itr) + Player* plr = itr->getSource(); + // players inside an instance cannot be bound to other instances + // some players may already be permanently bound, in this case nothing happens + InstancePlayerBind *bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty()); + if(!bind || !bind->perm) { - // players inside an instance cannot be bound to other instances - // some players may already be permanently bound, in this case nothing happens - InstancePlayerBind *bind = (*itr)->GetBoundInstance(save->GetMapId(), save->GetDifficulty()); - if(!bind || !bind->perm) - { - (*itr)->BindToInstance(save, true); - WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); - data << uint32(0); - (*itr)->GetSession()->SendPacket(&data); - } - - // if the leader is not in the instance the group will not get a perm bind - if(group && group->GetLeaderGUID() == (*itr)->GetGUID()) - group->BindToInstance(save, true); + plr->BindToInstance(save, true); + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); + data << uint32(0); + plr->GetSession()->SendPacket(&data); } + + // if the leader is not in the instance the group will not get a perm bind + if(group && group->GetLeaderGUID() == plr->GetGUID()) + group->BindToInstance(save, true); } } @@ -1745,11 +1823,14 @@ time_t InstanceMap::GetResetTime() void InstanceMap::UnloadAll(bool pForce) { - if(!i_Players.empty()) + if(HavePlayers()) { sLog.outError("InstanceMap::UnloadAll: there are still players in the instance at unload, should not happen!"); - for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) - if(*itr) (*itr)->TeleportTo((*itr)->m_homebindMapId, (*itr)->m_homebindX, (*itr)->m_homebindY, (*itr)->m_homebindZ, (*itr)->GetOrientation()); + for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + { + Player* plr = itr->getSource(); + plr->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation()); + } } if(m_resetAfterUnload == true) @@ -1758,10 +1839,10 @@ void InstanceMap::UnloadAll(bool pForce) Map::UnloadAll(pForce); } -void InstanceMap::SendResetWarnings(uint32 timeLeft) +void InstanceMap::SendResetWarnings(uint32 timeLeft) const { - for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) - (*itr)->SendInstanceResetWarning(GetId(), timeLeft); + for(MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->SendInstanceResetWarning(GetId(), timeLeft); } void InstanceMap::SetResetSchedule(bool on) @@ -1769,7 +1850,7 @@ void InstanceMap::SetResetSchedule(bool on) // only for normal instances // the reset time is only scheduled when there are no payers inside // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled - if(i_Players.empty() && !IsRaid() && !IsHeroic()) + if(!HavePlayers() && !IsRaid() && !IsHeroic()) { InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); @@ -1777,12 +1858,6 @@ void InstanceMap::SetResetSchedule(bool on) } } -void InstanceMap::SendToPlayers(WorldPacket const* data) const -{ - for(PlayerList::const_iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr) - (*itr)->GetSession()->SendPacket(data); -} - /* ******* Battleground Instance Maps ******* */ BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId) @@ -1796,7 +1871,7 @@ BattleGroundMap::~BattleGroundMap() bool BattleGroundMap::CanEnter(Player * player) { - if(std::find(i_Players.begin(),i_Players.end(),player)!=i_Players.end()) + if(player->GetMapRef().getTarget() == this) { sLog.outError("BGMap::CanEnter - player %u already in map!", player->GetGUIDLow()); assert(false); @@ -1817,7 +1892,6 @@ bool BattleGroundMap::Add(Player * player) Guard guard(*this); if(!CanEnter(player)) return false; - i_Players.push_back(player); // reset instance validity, battleground maps do not homebind player->m_InstanceValid = true; } @@ -1827,7 +1901,6 @@ bool BattleGroundMap::Add(Player * player) void BattleGroundMap::Remove(Player *player, bool remove) { sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName()); - i_Players.remove(player); Map::Remove(player, remove); } @@ -1838,15 +1911,14 @@ void BattleGroundMap::SetUnload() void BattleGroundMap::UnloadAll(bool pForce) { - while(!i_Players.empty()) + while(HavePlayers()) { - PlayerList::iterator itr = i_Players.begin(); - Player * plr = *itr; - if(plr) (plr)->TeleportTo((*itr)->m_homebindMapId, (*itr)->m_homebindX, (*itr)->m_homebindY, (*itr)->m_homebindZ, (*itr)->GetOrientation()); + Player * plr = m_mapRefManager.getFirst()->getSource(); + if(plr) (plr)->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation()); // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop // note that this remove is not needed if the code works well in other places - i_Players.remove(plr); + plr->GetMapRef().unlink(); } Map::UnloadAll(pForce); diff --git a/src/game/Map.h b/src/game/Map.h index 2ded7cf0975..1765d6d09fa 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -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 */ #ifndef TRINITY_MAP_H @@ -33,6 +33,7 @@ #include "Timer.h" #include "SharedDefines.h" #include "GameSystem/GridRefManager.h" +#include "MapRefManager.h" #include <bitset> #include <list> @@ -126,6 +127,7 @@ typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList; class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::ObjectLevelLockable<Map, ZThread::Mutex> { + friend class MapReference; public: Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); virtual ~Map(); @@ -237,6 +239,14 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O Creature* GetCreatureInMap(uint64 guid); GameObject* GetGameObjectInMap(uint64 guid); + bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } + uint32 GetPlayersCountExceptGMs() const; + bool PlayersNearGrid(uint32 x,uint32 y) const; + + void SendToPlayers(WorldPacket const* data) const; + + typedef MapRefManager PlayerList; + PlayerList const& GetPlayers() const { return m_mapRefManager; } template<class T> void SwitchGridContainers(T* obj, bool active); private: void LoadVMap(int pX, int pY); @@ -286,6 +296,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O uint32 i_InstanceId; uint32 m_unloadTimer; + MapRefManager m_mapRefManager; private: typedef GridReadGuard ReadGuard; typedef GridWriteGuard WriteGuard; @@ -325,8 +336,6 @@ enum InstanceResetMethod class TRINITY_DLL_SPEC InstanceMap : public Map { public: - typedef std::list<Player *> PlayerList; // online players only - InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); ~InstanceMap(); bool Add(Player *); @@ -337,14 +346,10 @@ class TRINITY_DLL_SPEC InstanceMap : public Map std::string GetScript() { return i_script; } InstanceData* GetInstanceData() { return i_data; } void PermBindAllPlayers(Player *player); - PlayerList const& GetPlayers() const { return i_Players;} - void SendToPlayers(WorldPacket const* data) const; time_t GetResetTime(); void UnloadAll(bool pForce); bool CanEnter(Player* player); - uint32 GetPlayersCountExceptGMs() const; - uint32 HavePlayers() const { return !i_Players.empty(); } - void SendResetWarnings(uint32 timeLeft); + void SendResetWarnings(uint32 timeLeft) const; void SetResetSchedule(bool on); private: bool m_resetAfterUnload; @@ -359,8 +364,6 @@ class TRINITY_DLL_SPEC InstanceMap : public Map class TRINITY_DLL_SPEC BattleGroundMap : public Map { public: - typedef std::list<Player *> PlayerList; // online players only - BattleGroundMap(uint32 id, time_t, uint32 InstanceId); ~BattleGroundMap(); @@ -369,8 +372,6 @@ class TRINITY_DLL_SPEC BattleGroundMap : public Map bool CanEnter(Player* player); void SetUnload(); void UnloadAll(bool pForce); - private: - PlayerList i_Players; }; /*inline diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 9a9128363f2..7b8f5fb9b64 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.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 "MapInstanced.h" @@ -26,7 +26,7 @@ #include "InstanceSaveMgr.h" #include "World.h" -MapInstanced::MapInstanced(uint32 id, time_t expiry, uint32 aInstanceId) : Map(id, expiry, 0, 0) +MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, 0) { // initialize instanced maps list m_InstancedMaps.clear(); @@ -261,4 +261,3 @@ void MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) delete itr->second; m_InstancedMaps.erase(itr++); } - diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index 44f39facbfe..cde37f9f3ff 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -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 */ #ifndef TRINITY_MAP_INSTANCED_H @@ -30,7 +30,7 @@ class TRINITY_DLL_DECL MapInstanced : public Map public: typedef UNORDERED_MAP< uint32, Map* > InstancedMaps; - MapInstanced(uint32 id, time_t, uint32 aInstanceId); + MapInstanced(uint32 id, time_t expiry); ~MapInstanced() {} // functions overwrite Map versions diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 86206fef49b..34aefdff074 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.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 "MapManager.h" @@ -111,7 +111,7 @@ MapManager::_GetBaseMap(uint32 id) const MapEntry* entry = sMapStore.LookupEntry(id); if (entry && entry->Instanceable()) { - m = new MapInstanced(id, i_gridCleanUpDelay, 0); + m = new MapInstanced(id, i_gridCleanUpDelay); } else { @@ -246,6 +246,8 @@ MapManager::Update(time_t diff) if( !i_timer.Passed() ) return; + ObjectAccessor::Instance().UpdatePlayers(i_timer.GetCurrent()); + for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) { checkAndCorrectGridStatesArray(); // debugging code, should be deleted some day @@ -336,7 +338,7 @@ uint32 MapManager::GetNumPlayersInInstances() MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); for(MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) if(mitr->second->IsDungeon()) - ret += ((InstanceMap*)mitr->second)->GetPlayers().size(); + ret += ((InstanceMap*)mitr->second)->GetPlayers().getSize(); } return ret; } diff --git a/src/game/MapRefManager.h b/src/game/MapRefManager.h new file mode 100644 index 00000000000..da0c81a9138 --- /dev/null +++ b/src/game/MapRefManager.h @@ -0,0 +1,44 @@ +/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MAPREFMANAGER
+#define _MAPREFMANAGER
+
+#include "Utilities/LinkedReference/RefManager.h"
+
+class MapReference;
+
+class MapRefManager : public RefManager<Map, Player>
+{
+ public:
+ typedef LinkedListHead::Iterator< MapReference > iterator;
+ typedef LinkedListHead::Iterator< MapReference const > const_iterator;
+
+ MapReference* getFirst() { return (MapReference*)RefManager<Map, Player>::getFirst(); }
+ MapReference const* getFirst() const { return (MapReference const*)RefManager<Map, Player>::getFirst(); }
+ MapReference* getLast() { return (MapReference*)RefManager<Map, Player>::getLast(); }
+ MapReference const* getLast() const { return (MapReference const*)RefManager<Map, Player>::getLast(); }
+
+ iterator begin() { return iterator(getFirst()); }
+ iterator end() { return iterator(NULL); }
+ iterator rbegin() { return iterator(getLast()); }
+ iterator rend() { return iterator(NULL); }
+ const_iterator begin() const { return const_iterator(getFirst()); }
+ const_iterator end() const { return const_iterator(getLast()); }
+};
+#endif
diff --git a/src/game/MapReference.h b/src/game/MapReference.h new file mode 100644 index 00000000000..b41796ea91b --- /dev/null +++ b/src/game/MapReference.h @@ -0,0 +1,50 @@ +/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MAPREFERENCE_H
+#define _MAPREFERENCE_H
+
+#include "Utilities/LinkedReference/Reference.h"
+#include "Map.h"
+
+class TRINITY_DLL_SPEC MapReference : public Reference<Map, Player>
+{
+ protected:
+ void targetObjectBuildLink()
+ {
+ // called from link()
+ getTarget()->m_mapRefManager.insertFirst(this);
+ getTarget()->m_mapRefManager.incSize();
+ }
+ void targetObjectDestroyLink()
+ {
+ // called from unlink()
+ if(isValid()) getTarget()->m_mapRefManager.decSize();
+ }
+ void sourceObjectDestroyLink()
+ {
+ // called from invalidate()
+ getTarget()->m_mapRefManager.decSize();
+ }
+ public:
+ MapReference() : Reference<Map, Player>() {}
+ ~MapReference() { unlink(); }
+ MapReference *next() { return (MapReference*)Reference<Map, Player>::next(); }
+ MapReference const *next() const { return (MapReference const*)Reference<Map, Player>::next(); }
+};
+#endif
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 15a77c6c01e..4936e9f0991 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.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 "Common.h" @@ -222,7 +222,7 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) // check present spell in trainer spell list TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if(!trainer_spells) - return; + return; // not found, cheat? TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); @@ -339,15 +339,13 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data ) if(!code.empty()) { - if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str())) unit->OnGossipSelect (_player, option); } else - { if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) - unit->OnGossipSelect (_player, option); + unit->OnGossipSelect (_player, option); } } @@ -377,7 +375,7 @@ void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data ) void WorldSession::SendSpiritResurrect() { - _player->ResurrectPlayer(0.5f,false, true); + _player->ResurrectPlayer(0.5f, true); _player->DurabilityLossAll(0.25f,true); diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index c03dbab09e9..8a7e8fbfa2c 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -142,7 +142,15 @@ Creature* ObjectAccessor::GetCreature(WorldObject const &u, uint64 guid) { Creature * ret = GetObjectInWorld(guid, (Creature*)NULL); - if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + if(!ret) + return NULL; + + if(ret->GetMapId() != u.GetMapId()) + return NULL; + + if(ret->GetInstanceId() != u.GetInstanceId()) + return NULL; + return ret; } @@ -248,32 +256,6 @@ ObjectAccessor::SaveAllPlayers() } void -ObjectAccessor::_update() -{ - UpdateDataMapType update_players; - { - Guard guard(i_updateGuard); - while(!i_objects.empty()) - { - Object* obj = *i_objects.begin(); - i_objects.erase(i_objects.begin()); - if (!obj) - continue; - _buildUpdateObject(obj, update_players); - obj->ClearUpdateMask(false); - } - } - - WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 - for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) - { - iter->second.BuildPacket(&packet); - iter->first->GetSession()->SendPacket(&packet); - packet.clear(); // clean the string - } -} - -void ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer) { UpdateDataMapType update_players; @@ -361,7 +343,7 @@ ObjectAccessor::_buildChangeObjectForPlayer(WorldObject *obj, UpdateDataMapType WorldObjectChangeAccumulator notifier(*obj, update_players); TypeContainerVisitor<WorldObjectChangeAccumulator, WorldTypeMapContainer > player_notifier(notifier); CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(obj->GetMapId(), obj)); + cell_lock->Visit(cell_lock, player_notifier, *obj->GetMap()); } Pet* @@ -519,6 +501,7 @@ ObjectAccessor::RemoveActiveObject( WorldObject * obj ) void ObjectAccessor::Update(uint32 diff) { + { // 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(); @@ -589,8 +572,15 @@ ObjectAccessor::Update(uint32 diff) } } } +} - _update(); +void +ObjectAccessor::UpdatePlayers(uint32 diff) +{ + HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer(); + for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter) + if(iter->second->IsInWorld()) + iter->second->Update(diff); } bool @@ -677,14 +667,14 @@ ObjectAccessor::UpdateObjectVisibility(WorldObject *obj) CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); Cell cell(p); - MapManager::Instance().GetMap(obj->GetMapId(), obj)->UpdateObjectVisibility(obj,cell,p); + obj->GetMap()->UpdateObjectVisibility(obj,cell,p); } void ObjectAccessor::UpdateVisibilityForPlayer( Player* player ) { CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell(p); - Map* m = MapManager::Instance().GetMap(player->GetMapId(),player); + Map* m = player->GetMap(); m->UpdatePlayerVisibility(player,cell,p); m->UpdateObjectsVisibilityFor(player,cell,p); diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index d0007d37f21..89ea6d1e43d 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -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 */ #ifndef TRINITY_OBJECTACCESSOR_H @@ -186,6 +186,7 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor void RemoveUpdateObject(Object *obj); void Update(uint32 diff); + void UpdatePlayers(uint32 diff); Corpse* GetCorpseForPlayerGUID(uint64 guid); void RemoveCorpse(Corpse *corpse); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ec882ef1154..11ffba972a3 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -799,7 +799,7 @@ void Player::StopMirrorTimer(MirrorTimerType Type) GetSession()->SendPacket( &data ); } -void Player::EnvironmentalDamage(uint64 guid, EnvironmentalDamageType type, uint32 damage) +void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 damage) { WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); data << (uint64)guid; @@ -1641,7 +1641,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati else { // far teleport to another map - Map* oldmap = IsInWorld() ? MapManager::Instance().GetMap(GetMapId(), this) : NULL; + Map* oldmap = IsInWorld() ? GetMap() : NULL; // check if we can enter before stopping combat / removing pet / totems / interrupting spells // Check enter rights before map getting to avoid creating instance copy for player @@ -3750,7 +3750,7 @@ void Player::SendDelayResponse(const uint32 ml_seconds) GetSession()->SendPacket( &data ); } -void Player::ResurrectPlayer(float restore_percent, bool updateToWorld, bool applySickness) +void Player::ResurrectPlayer(float restore_percent, bool applySickness) { WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4*4); // remove spirit healer position data << uint32(-1); @@ -4281,7 +4281,7 @@ void Player::UpdateDefense() } } -void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply, bool affectStats) +void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply) { if(modGroup >= BASEMOD_END || modType >= MOD_END) { @@ -5243,7 +5243,7 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele return false; } - Map *m = MapManager::Instance().GetMap(GetMapId(), this); + Map *m = GetMap(); const float old_x = GetPositionX(); const float old_y = GetPositionY(); @@ -5261,7 +5261,7 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele m->PlayerRelocation(this, x, y, z, orientation); // reread after Map::Relocation - m = MapManager::Instance().GetMap(GetMapId(), this); + m = GetMap(); x = GetPositionX(); y = GetPositionY(); z = GetPositionZ(); @@ -6176,7 +6176,9 @@ uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) if(!result) return 0; - return (*result)[0].GetUInt32(); + uint32 id = (*result)[0].GetUInt32(); + delete result; + return id; } uint32 Player::GetZoneIdFromDB(uint64 guid) @@ -6707,7 +6709,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) SetBaseWeaponDamage(attType, MAXDAMAGE, damage); } - if(!IsUseEquippedWeapon(slot==EQUIPMENT_SLOT_MAINHAND)) + if(!IsUseEquipedWeapon(slot==EQUIPMENT_SLOT_MAINHAND)) return; if (proto->Delay) @@ -8485,7 +8487,7 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) cons if(!useable) return item; - if( item->IsBroken() || !IsUseEquippedWeapon(attackType==BASE_ATTACK) ) + if( item->IsBroken() || !IsUseEquipedWeapon(attackType==BASE_ATTACK) ) return NULL; return item; @@ -8640,6 +8642,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot ) return false; } + bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { uint32 tempcount = 0; @@ -10155,7 +10158,7 @@ Item* Player::_StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, boo if( pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM || - pItem->GetProto()->Bonding == BIND_WHEN_EQUIPPED && IsBagPos(pos) ) + pItem->GetProto()->Bonding == BIND_WHEN_EQUIPED && IsBagPos(pos) ) pItem->SetBinding( true ); if( bag == INVENTORY_SLOT_BAG_0 ) @@ -10201,7 +10204,7 @@ Item* Player::_StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, boo { if( pItem2->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem2->GetProto()->Bonding == BIND_QUEST_ITEM || - pItem2->GetProto()->Bonding == BIND_WHEN_EQUIPPED && IsBagPos(pos) ) + pItem2->GetProto()->Bonding == BIND_WHEN_EQUIPED && IsBagPos(pos) ) pItem2->SetBinding( true ); pItem2->SetCount( pItem2->GetCount() + count ); @@ -10403,7 +10406,7 @@ void Player::VisualizeItem( uint8 slot, Item *pItem) return; // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) - if( pItem->GetProto()->Bonding == BIND_WHEN_EQUIPPED || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) + if( pItem->GetProto()->Bonding == BIND_WHEN_EQUIPED || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) pItem->SetBinding( true ); sLog.outDebug( "STORAGE: EquipItem slot = %u, item = %u", slot, pItem->GetEntry()); @@ -10548,8 +10551,6 @@ void Player::DestroyItem( uint8 bag, uint8 slot, bool update ) if(pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED)) CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); - ItemPrototype const *pProto = pItem->GetProto(); - RemoveEnchantmentDurations(pItem); RemoveItemDurations(pItem); @@ -14207,7 +14208,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) SetUInt32Value(i, 0); - //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); + //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); if(result) { @@ -14217,10 +14218,11 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) uint64 caster_guid = fields[0].GetUInt64(); uint32 spellid = fields[1].GetUInt32(); uint32 effindex = fields[2].GetUInt32(); - int32 damage = (int32)fields[3].GetUInt32(); - int32 maxduration = (int32)fields[4].GetUInt32(); - int32 remaintime = (int32)fields[5].GetUInt32(); - int32 remaincharges = (int32)fields[6].GetUInt32(); + uint32 stackcount = fields[3].GetUInt32(); + int32 damage = (int32)fields[4].GetUInt32(); + int32 maxduration = (int32)fields[5].GetUInt32(); + int32 remaintime = (int32)fields[6].GetUInt32(); + int32 remaincharges = (int32)fields[7].GetUInt32(); SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid); if(!spellproto) @@ -14257,11 +14259,15 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto)) continue; - Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL); - if(!damage) - damage = aura->GetModifier()->m_amount; - aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); - AddAura(aura); + for(uint32 i=0; i<stackcount; i++) + { + Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL); + if(!damage) + damage = aura->GetModifier()->m_amount; + aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); + AddAura(aura); + sLog.outString("Added aura spellid %u, effect %u", spellproto->Id, effindex); + } } while( result->NextRow() ); @@ -15320,31 +15326,54 @@ void Player::_SaveAuras() CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",GetGUIDLow()); AuraMap const& auras = GetAuras(); - for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + + if (auras.empty()) + return; + + spellEffectPair lastEffectPair = auras.begin()->first; + uint32 stackCounter = 1; + + for(AuraMap::const_iterator itr = auras.begin(); ; ++itr) { - SpellEntry const *spellInfo = itr->second->GetSpellProto(); + if(itr == auras.end() || lastEffectPair != itr->first) + { + AuraMap::const_iterator itr2 = itr; + // save previous spellEffectPair to db + itr2--; + SpellEntry const *spellInfo = itr2->second->GetSpellProto(); - //skip all auras from spells that are passive or need a shapeshift - if (itr->second->IsPassive() || itr->second->IsRemovedOnShapeLost()) - continue; + //skip all auras from spells that are passive or need a shapeshift + if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost())) + { + //do not save single target auras (unless they were cast by the player) + if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo))) + { + uint8 i; + // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras + for (i = 0; i < 3; i++) + if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT || + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH) + break; - //do not save single target auras (unless they were cast by the player) - if (itr->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo)) - continue; + if (i == 3) + { + CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) " + "VALUES ('%u', '" I64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')", + GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), stackCounter, itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->m_procCharges)); + } + } + } - uint8 i; - // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras - for (i = 0; i < 3; i++) - if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH) + if(itr == auras.end()) break; + } - if (i == 3) + if (lastEffectPair == itr->first) + stackCounter++; + else { - CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u' and spell = '%u' and effect_index= '%u'",GetGUIDLow(),(uint32)(*itr).second->GetId(), (uint32)(*itr).second->GetEffIndex()); - CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges) " - "VALUES ('%u', '" I64FMTD "' ,'%u', '%u', '%d', '%d', '%d', '%d')", - GetGUIDLow(), itr->second->GetCasterGUID(), (uint32)(*itr).second->GetId(), (uint32)(*itr).second->GetEffIndex(), (*itr).second->GetModifier()->m_amount,int((*itr).second->GetAuraMaxDuration()),int((*itr).second->GetAuraDuration()),int((*itr).second->m_procCharges)); + lastEffectPair = itr->first; + stackCounter = 1; } } } @@ -17910,7 +17939,7 @@ void Player::learnSkillRewardedSpells(uint32 skill_id ) if (pAbility->classmask && !(pAbility->classmask & classMask)) continue; - if (SpellEntry const* spellentry = sSpellStore.LookupEntry(pAbility->spellId)) + if (sSpellStore.LookupEntry(pAbility->spellId)) { // Ok need learn spell learnSpell(pAbility->spellId); @@ -18323,7 +18352,6 @@ bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) Player* member_with_max_level = NULL; Player* not_gray_member_with_max_level = NULL; - // gets the max member level of the group, and the max member level that still gets XP pGroup->GetDataForXPAtKill(pVictim,count,sum_level,member_with_max_level,not_gray_member_with_max_level); if(member_with_max_level) @@ -18332,7 +18360,7 @@ bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) // also no XP gained if there is no member below gray level xp = (PvP || !not_gray_member_with_max_level) ? 0 : Trinity::XP::Gain(not_gray_member_with_max_level, pVictim); - // skip in check PvP case (for speed, not used) + /// skip in check PvP case (for speed, not used) bool is_raid = PvP ? false : sMapStore.LookupEntry(GetMapId())->IsRaid() && pGroup->isRaidGroup(); bool is_dungeon = PvP ? false : sMapStore.LookupEntry(GetMapId())->IsDungeon(); float group_rate = Trinity::XP::xp_in_group_rate(count,is_raid); @@ -18660,70 +18688,82 @@ void Player::SetCanBlock( bool value ) UpdateBlockPercentage(); } -void Player::HandleFallDamage(MovementInfo& movementInfo) +bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const { - //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored - if (!isInFlight() && movementInfo.fallTime > 1100 && !isDead() && !isGameMaster() && - !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) && - !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) - { - //Safe fall, fall time reduction - int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); - uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; - - if(fall_time > 1100) //Prevent damage if fall time < 1100 - { - //Fall Damage calculation - float fallperc = float(fall_time)/1100; - uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); - - float height = movementInfo.z; - UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); - - if (damage > 0) - { - //Prevent fall damage from being more than the player maximum health - if (damage > GetMaxHealth()) - damage = GetMaxHealth(); - - // Gust of Wind - if (GetDummyAura(43621)) - damage = GetMaxHealth()/2; - - EnvironmentalDamage(GetGUID(), DAMAGE_FALL, damage); - } - - //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction - DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); - } - } + for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) + if(itr->pos == pos) + return true; + return false; } -void Player::HandleFallUnderMap() -{ - if(InBattleGround() && GetBattleGround() - && GetBattleGround()->HandlePlayerUnderMap(this)) - { - // do nothing, the handle already did if returned true - } - else - { - // NOTE: this is actually called many times while falling - // even after the player has been teleported away - // TODO: discard movement packets after the player is rooted - if(isAlive()) - { - EnvironmentalDamage(GetGUID(),DAMAGE_FALL_TO_VOID, GetMaxHealth()); - // change the death state to CORPSE to prevent the death timer from - // starting in the next player update - KillPlayer(); - BuildPlayerRepop(); - } - - // cancel the death timer here if started - RepopAtGraveyard(); - } -} +//*********************************** +//-------------TRINITY--------------- +//*********************************** + +void Player::HandleFallDamage(MovementInfo& movementInfo)
+{
+ //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored
+ if (!isInFlight() && movementInfo.fallTime > 1100 && !isDead() && !isGameMaster() &&
+ !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) &&
+ !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) )
+ {
+ //Safe fall, fall time reduction
+ int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL);
+ uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0;
+
+ if(fall_time > 1100) //Prevent damage if fall time < 1100
+ {
+ //Fall Damage calculation
+ float fallperc = float(fall_time)/1100;
+ uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL));
+
+ float height = movementInfo.z;
+ UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height);
+
+ if (damage > 0)
+ {
+ //Prevent fall damage from being more than the player maximum health
+ if (damage > GetMaxHealth())
+ damage = GetMaxHealth();
+
+ // Gust of Wind
+ if (GetDummyAura(43621))
+ damage = GetMaxHealth()/2;
+
+ EnvironmentalDamage(GetGUID(), DAMAGE_FALL, damage);
+ }
+
+ //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction
+ DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall);
+ }
+ }
+}
+
+void Player::HandleFallUnderMap()
+{
+ if(InBattleGround() && GetBattleGround()
+ && GetBattleGround()->HandlePlayerUnderMap(this))
+ {
+ // do nothing, the handle already did if returned true
+ }
+ else
+ {
+ // NOTE: this is actually called many times while falling
+ // even after the player has been teleported away
+ // TODO: discard movement packets after the player is rooted
+ if(isAlive())
+ {
+ EnvironmentalDamage(GetGUID(),DAMAGE_FALL_TO_VOID, GetMaxHealth());
+ // change the death state to CORPSE to prevent the death timer from
+ // starting in the next player update
+ KillPlayer();
+ BuildPlayerRepop();
+ }
+
+ // cancel the death timer here if started
+ RepopAtGraveyard();
+ }
+}
void Player::Possess(Unit *target) { @@ -18961,15 +19001,6 @@ bool Player::isAllowUseBattleGroundObject() ); } -bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const -{ - for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) - if(itr->pos == this->pos) - return true; - - return false; -} - bool Player::isTotalImmunity() { AuraList const& immune = GetAurasByType(SPELL_AURA_SCHOOL_IMMUNITY); diff --git a/src/game/Player.h b/src/game/Player.h index 4b92f8316d0..87f0ad11ae8 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -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 */ #ifndef _PLAYER_H @@ -33,6 +33,7 @@ #include "Bag.h" #include "WorldSession.h" #include "Pet.h" +#include "MapReference.h" #include "Util.h" // for Tokens typedef #include<string> @@ -779,7 +780,7 @@ enum TeleportToOptions }; /// Type of environmental damages -enum EnvironmentalDamageType +enum EnviromentalDamage { DAMAGE_EXHAUSTED = 0, DAMAGE_DROWNING = 1, @@ -1124,7 +1125,7 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 GetWeaponProficiency() const { return m_WeaponProficiency; } uint32 GetArmorProficiency() const { return m_ArmorProficiency; } bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; } - bool IsUseEquippedWeapon( bool mainhand ) const + bool IsUseEquipedWeapon( bool mainhand ) const { // disarm applied only to mainhand weapon return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) ); @@ -1306,7 +1307,7 @@ class TRINITY_DLL_SPEC Player : public Unit if(d < 0) SetMoney (GetMoney() > uint32(-d) ? GetMoney() + d : 0); else - SetMoney (GetMoney() < MAX_MONEY_AMOUNT - d ? GetMoney() + d : MAX_MONEY_AMOUNT); + SetMoney (GetMoney() < uint32(MAX_MONEY_AMOUNT - d) ? GetMoney() + d : MAX_MONEY_AMOUNT); // "At Gold Limit" if(GetMoney() >= MAX_MONEY_AMOUNT) @@ -1428,7 +1429,6 @@ class TRINITY_DLL_SPEC Player : public Unit PlayerSpellMap const& GetSpellMap() const { return m_spells; } PlayerSpellMap & GetSpellMap() { return m_spells; } - ActionButtonList const& GetActionButtonList() const { return m_actionButtons; } void AddSpellMod(SpellModifier* mod, bool apply); int32 GetTotalFlatMods(uint32 spellId, SpellModOp op); @@ -1518,8 +1518,8 @@ class TRINITY_DLL_SPEC Player : public Unit void RemoveFromGroup() { RemoveFromGroup(GetGroup(),GetGUID()); } void SendUpdateToOutOfRangeGroupMembers(); - void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); Player::SetUInt32ValueInDB(PLAYER_GUILDID, GuildId, this->GetGUID()); } - void SetRank(uint32 rankId){ SetUInt32Value(PLAYER_GUILDRANK, rankId); Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, rankId, this->GetGUID()); } + void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); Player::SetUInt32ValueInDB(PLAYER_GUILDID, GuildId, GetGUID()); } + void SetRank(uint32 rankId){ SetUInt32Value(PLAYER_GUILDRANK, rankId); Player::SetUInt32ValueInDB(PLAYER_GUILDRANK, rankId, GetGUID()); } void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; } uint32 GetGuildId() { return GetUInt32Value(PLAYER_GUILDID); } static uint32 GetGuildIdFromDB(uint64 guid); @@ -1532,7 +1532,7 @@ class TRINITY_DLL_SPEC Player : public Unit void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot) { SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId); - SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId, this->GetGUID()); + SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId, GetGUID()); } uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); } static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot); @@ -1608,7 +1608,7 @@ class TRINITY_DLL_SPEC Player : public Unit void SendDelayResponse(const uint32); void SendLogXPGain(uint32 GivenXP,Unit* victim,uint32 RestXP); - //Low Level Packets + //Low Level Packets void PlaySound(uint32 Sound, bool OnlySelf); //notifiers void SendAttackSwingCantAttack(); @@ -1640,7 +1640,7 @@ class TRINITY_DLL_SPEC Player : public Unit void CreateCorpse(); void KillPlayer(); uint32 GetResurrectionSpellId(); - void ResurrectPlayer(float restore_percent, bool updateToWorld = true, bool applySickness = false); + void ResurrectPlayer(float restore_percent, bool applySickness = false); void BuildPlayerRepop(); void RepopAtGraveyard(); @@ -1762,14 +1762,14 @@ class TRINITY_DLL_SPEC Player : public Unit void SetRegularAttackTime(); void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; } - void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply, bool affectStats = true); + void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply); float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const; float GetTotalBaseModValue(BaseModGroup modGroup) const; float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; } void _ApplyAllStatBonuses(); void _RemoveAllStatBonuses(); - void _ApplyWeaponDependentAuraMods(Item *item,WeaponAttackType attackType,bool apply); + void _ApplyWeaponDependentAuraMods(Item *item, WeaponAttackType attackType, bool apply); void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply); void _ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply); @@ -1934,10 +1934,10 @@ class TRINITY_DLL_SPEC Player : public Unit void SetRestTime(uint32 v) { m_restTime = v;}; /*********************************************************/ - /*** ENVIRONMENTAL SYSTEM ***/ + /*** ENVIROMENTAL SYSTEM ***/ /*********************************************************/ - void EnvironmentalDamage(uint64 guid, EnvironmentalDamageType type, uint32 damage); + void EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 damage); /*********************************************************/ /*** FLOOD FILTER SYSTEM ***/ @@ -2062,6 +2062,8 @@ class TRINITY_DLL_SPEC Player : public Unit Player* GetNextRandomRaidMember(float radius); GridReference<Player> &GetGridRef() { return m_gridRef; } + MapReference &GetMapRef() { return m_mapRef; } + bool isAllowedToLoot(Creature* creature); WorldLocation& GetTeleportDest() { return m_teleport_dest; } @@ -2307,6 +2309,7 @@ class TRINITY_DLL_SPEC Player : public Unit Item* _StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update ); GridReference<Player> m_gridRef; + MapReference m_mapRef; }; void AddItemsSetItem(Player*player,Item *item); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 37c02fb549d..55203554665 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -170,10 +170,10 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraHealing, //115 SPELL_AURA_MOD_HEALING + &Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleAuraHealingPct, //118 SPELL_AURA_MOD_HEALING_PCT + &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY @@ -191,7 +191,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE - &Aura::HandleAuraHealingPct, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus + &Aura::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION @@ -220,7 +220,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE &Aura::HandleUnused, //164 useless, only one test spell - &Aura::HandleAuraAttackPowerAttacker, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus + &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus @@ -1999,6 +1999,16 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; } + // Waiting to Resurrect + if(GetId()==2584) + { + // Waiting to resurrect spell cancel, we must remove player from resurrect queue + if(m_target->GetTypeId() == TYPEID_PLAYER) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); + return; + } + // Dark Fiend if(GetId()==45934) { @@ -2294,6 +2304,10 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) void Aura::HandleAuraMounted(bool apply, bool Real) { + // only at real add/remove aura + if(!Real) + return; + if(apply) { CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); @@ -2693,7 +2707,9 @@ void Aura::HandleAuraTransform(bool apply, bool Real) } else { - if (uint32 modelid = ci->GetRandomValidModelId()) m_target->SetDisplayId(modelid); + // Will use the default model here + if (uint32 modelid = ci->GetRandomValidModelId()) + m_target->SetDisplayId(modelid); // Dragonmaw Illusion (set mount model also) if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty()) @@ -3589,7 +3605,7 @@ void Aura::HandleModTaunt(bool apply, bool Real) /*********************************************************/ /*** MODIFY SPEED ***/ /*********************************************************/ -void Aura::HandleAuraModIncreaseSpeed(bool apply, bool Real) +void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real) { // all applied/removed only at real aura add/remove if(!Real) @@ -3598,7 +3614,7 @@ void Aura::HandleAuraModIncreaseSpeed(bool apply, bool Real) m_target->UpdateSpeed(MOVE_RUN, true); } -void Aura::HandleAuraModIncreaseMountedSpeed(bool apply, bool Real) +void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real) { // all applied/removed only at real aura add/remove if(!Real) @@ -3637,7 +3653,7 @@ void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) m_target->UpdateSpeed(MOVE_FLY, true); } -void Aura::HandleAuraModIncreaseSwimSpeed(bool apply, bool Real) +void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real) { // all applied/removed only at real aura add/remove if(!Real) @@ -3646,7 +3662,7 @@ void Aura::HandleAuraModIncreaseSwimSpeed(bool apply, bool Real) m_target->UpdateSpeed(MOVE_SWIM, true); } -void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real) +void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real) { // all applied/removed only at real aura add/remove if(!Real) @@ -3657,7 +3673,7 @@ void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real) m_target->UpdateSpeed(MOVE_FLY, true); } -void Aura::HandleAuraModUseNormalSpeed(bool apply, bool Real) +void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real) { // all applied/removed only at real aura add/remove if(!Real) @@ -4342,7 +4358,7 @@ void Aura::HandleModPercentStat(bool apply, bool Real) } } -void Aura::HandleModSpellDamagePercentFromStat(bool apply, bool Real) +void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4353,7 +4369,7 @@ void Aura::HandleModSpellDamagePercentFromStat(bool apply, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModSpellHealingPercentFromStat(bool apply, bool Real) +void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4371,7 +4387,7 @@ void Aura::HandleAuraModDispelResist(bool apply, bool Real) m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID()); } -void Aura::HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real) +void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4382,7 +4398,7 @@ void Aura::HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real) +void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4391,7 +4407,7 @@ void Aura::HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModHealingDone(bool apply, bool Real) +void Aura::HandleModHealingDone(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4431,7 +4447,7 @@ void Aura::HandleModTotalPercentStat(bool apply, bool Real) } } -void Aura::HandleAuraModResistenceOfStatPercent(bool apply, bool Real) +void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4566,7 +4582,7 @@ void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking ((Player*)m_target)->UpdateManaRegen(); } -void Aura::HandleModPowerRegenPCT(bool apply, bool Real) +void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real) { // spells required only Real aura add/remove if(!Real) @@ -4580,7 +4596,7 @@ void Aura::HandleModPowerRegenPCT(bool apply, bool Real) ((Player*)m_target)->UpdateManaRegen(); } -void Aura::HandleModManaRegen(bool apply, bool Real) +void Aura::HandleModManaRegen(bool /*apply*/, bool Real) { // spells required only Real aura add/remove if(!Real) @@ -4667,7 +4683,7 @@ void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real) /*** FIGHT ***/ /********************************/ -void Aura::HandleAuraModParryPercent(bool apply, bool Real) +void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; @@ -4675,7 +4691,7 @@ void Aura::HandleAuraModParryPercent(bool apply, bool Real) ((Player*)m_target)->UpdateParryPercentage(); } -void Aura::HandleAuraModDodgePercent(bool apply, bool Real) +void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; @@ -4684,7 +4700,7 @@ void Aura::HandleAuraModDodgePercent(bool apply, bool Real) //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount)); } -void Aura::HandleAuraModBlockPercent(bool apply, bool Real) +void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; @@ -4693,7 +4709,7 @@ void Aura::HandleAuraModBlockPercent(bool apply, bool Real) //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount)); } -void Aura::HandleAuraModRegenInterrupt(bool apply, bool Real) +void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real) { // spells required only Real aura add/remove if(!Real) @@ -4761,7 +4777,7 @@ void Aura::HandleModSpellCritChance(bool apply, bool Real) } } -void Aura::HandleModSpellCritChanceShool(bool apply, bool Real) +void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real) { // spells required only Real aura add/remove if(!Real) @@ -4843,39 +4859,6 @@ void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real) m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); } -void Aura::HandleAuraAttackPowerAttacker(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - Unit *caster = GetCaster(); - - if (!caster) - return; - - // Hunter's Mark - if (m_spellProto->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) - { - // Check Improved Hunter's Mark bonus on caster - Unit::AuraList const& mOverrideClassScript = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) - { - Modifier* mod = (*i)->GetModifier(); - // mproved Hunter's Mark script from 5236 to 5240 - if (mod->m_miscvalue >= 5236 && mod->m_miscvalue <= 5240) - { - // Get amount of ranged bonus for this spell.. - int32 ranged_bonus = caster->CalculateSpellDamage(m_spellProto, 1, m_spellProto->EffectBasePoints[1], m_target); - // Set melee attack power bonus % from ranged depends from Improved mask aura - m_modifier.m_amount = mod->m_amount * ranged_bonus / 100; - m_currentBasePoints = m_modifier.m_amount; - break; - } - } - return; - } -} - void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real) { //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 @@ -5323,7 +5306,7 @@ void Aura::HandleForceMoveForward(bool apply, bool Real) m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); } -void Aura::HandleAuraModExpertise(bool apply, bool Real) +void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -5348,17 +5331,6 @@ void Aura::HandleModTargetResistance(bool apply, bool Real) m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply); } -//HandleNoImmediateEffect auras implementation to support new stat system -void Aura::HandleAuraHealing(bool apply, bool Real) -{ - //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_VALUE, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraHealingPct(bool apply, bool Real) -{ - //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_PCT, float(m_modifier.m_amount), apply); -} - void Aura::HandleShieldBlockValue(bool apply, bool Real) { BaseModType modType = FLAT_MOD; diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index e4fe29fbc60..d803d9ede13 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -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 */ #ifndef TRINITY_SPELLAURAS_H #define TRINITY_SPELLAURAS_H @@ -185,15 +185,12 @@ class TRINITY_DLL_SPEC Aura void HandleAuraAllowFlight(bool Apply, bool Real); void HandleModRating(bool apply, bool Real); void HandleModTargetResistance(bool apply, bool Real); - void HandleAuraAttackPowerAttacker(bool apply, bool Real); void HandleAuraModAttackPowerPercent(bool apply, bool Real); void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real); void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real); void HandleSpiritOfRedemption(bool apply, bool Real); - void HandleAuraHealingPct(bool apply, bool Real); void HandleModManaRegen(bool apply, bool Real); void HandleComprehendLanguage(bool apply, bool Real); - void HandleAuraHealing(bool apply, bool Real); void HandleShieldBlockValue(bool apply, bool Real); void HandleModSpellCritChanceShool(bool apply, bool Real); void HandleAuraRetainComboPoints(bool apply, bool Real); @@ -253,7 +250,7 @@ class TRINITY_DLL_SPEC Aura { uint8 slot = GetAuraSlot(); - // only aura inslot with charges and without stack limitation + // only aura in slot with charges and without stack limitation if (slot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0) SetAuraApplication(slot, m_procCharges - 1); } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2c663e90212..a492e06f5b1 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1171,7 +1171,7 @@ void Spell::EffectDummy(uint32 i) //Converted Sentry Credit m_caster->CastSpell(m_caster, 45009, true); return; - } + } case 45030: // Impale Emissary { // Emissary of Hate Credit @@ -1274,7 +1274,7 @@ void Spell::EffectDummy(uint32 i) { //Polymorph Cast Visual Rank 1 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820}; - unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true); + unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true); } return; } @@ -2250,7 +2250,7 @@ void Spell::EffectPowerDrain(uint32 i) m_caster->ModifyPower(POWER_MANA,gain); //send log - m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA,false); + m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA); } } @@ -2266,7 +2266,7 @@ void Spell::EffectSendEvent(uint32 EffectIndex) case 23333: // Pickup Horde Flag /*do not uncomment . if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Send Event Horde Flag Picked Up"); break; /* not used : @@ -2279,7 +2279,7 @@ void Spell::EffectSendEvent(uint32 EffectIndex) case 23335: // Pickup Alliance Flag /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Send Event Alliance Flag Picked Up"); break; /* not used : @@ -2290,18 +2290,18 @@ void Spell::EffectSendEvent(uint32 EffectIndex) break; case 23385: // Alliance Flag Returns if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Alliance Flag Returned"); break; case 23386: // Horde Flag Returns if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Horde Flag Returned"); break;*/ case 34976: /* if(bg->GetTypeID()==BATTLEGROUND_EY) - bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); + bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); */ break; default: @@ -2680,24 +2680,24 @@ void Spell::EffectEnergize(uint32 i) return; // Some level depends spells - int multiplier = 0; + int multiplier = 0; int level_diff = 0; switch (m_spellInfo->Id) { // Restore Energy case 9512: level_diff = m_caster->getLevel() - 40; - multiplier = 2; + multiplier = 2; break; // Blood Fury case 24571: level_diff = m_caster->getLevel() - 60; - multiplier = 10; + multiplier = 10; break; // Burst of Energy case 24532: level_diff = m_caster->getLevel() - 60; - multiplier = 4; + multiplier = 4; break; default: break; @@ -3759,7 +3759,7 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i) if(unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); else - MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation()); + m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation()); } void Spell::EffectLearnSkill(uint32 i) @@ -3780,13 +3780,13 @@ void Spell::EffectAddHonor(uint32 /*i*/) if(unitTarget->GetTypeId() != TYPEID_PLAYER) return; - sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, this->damage, ((Player*)unitTarget)->GetGUIDLow()); + sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow()); // TODO: find formula for honor reward based on player's level! // now fixed only for level 70 players: if (((Player*)unitTarget)->getLevel() == 70) - ((Player*)unitTarget)->RewardHonor(NULL, 1, this->damage); + ((Player*)unitTarget)->RewardHonor(NULL, 1, damage); } void Spell::EffectTradeSkill(uint32 /*i*/) @@ -4001,7 +4001,7 @@ void Spell::EffectTameCreature(uint32 /*i*/) pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); // add to world - MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet); + pet->GetMap()->Add((Creature*)pet); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); @@ -4031,14 +4031,14 @@ void Spell::EffectSummonPet(uint32 i) if( OldSummon->isDead() ) return; - MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false); + OldSummon->GetMap()->Remove((Creature*)OldSummon,false); OldSummon->SetMapId(m_caster->GetMapId()); float px, py, pz; m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation()); - MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon); + m_caster->GetMap()->Add((Creature*)OldSummon); if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() ) { @@ -4121,10 +4121,10 @@ void Spell::EffectSummonPet(uint32 i) uint32 faction = m_caster->getFaction(); if(m_caster->GetTypeId() == TYPEID_UNIT) { - if ( ((Creature*)m_caster)->isTotem() ) - NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE); - else - NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); + if ( ((Creature*)m_caster)->isTotem() ) + NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE); + else + NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); } NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); @@ -4446,6 +4446,7 @@ void Spell::EffectWeaponDmg(uint32 i) if(m_caster->GetTypeId()==TYPEID_PLAYER) ((Player*)m_caster)->AddComboPoints(unitTarget, 1); } + // Mangle (Cat): CP if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL)) { @@ -4453,7 +4454,6 @@ void Spell::EffectWeaponDmg(uint32 i) ((Player*)m_caster)->AddComboPoints(unitTarget,1); } - // take ammo if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) { @@ -5448,7 +5448,7 @@ void Spell::EffectSummonObject(uint32 i) m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID(); } -void Spell::EffectResurrect(uint32 i) +void Spell::EffectResurrect(uint32 /*effIndex*/) { if(!unitTarget) return; @@ -5669,7 +5669,7 @@ void Spell::EffectSkinning(uint32 /*i*/) Creature* creature = (Creature*) unitTarget; int32 targetLevel = creature->getLevel(); - uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill(); + uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill(); ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); @@ -5696,7 +5696,7 @@ void Spell::EffectCharge(uint32 /*i*/) m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1); if(m_caster->GetTypeId() != TYPEID_PLAYER) - MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation()); + m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation()); // not all charge effects used in negative spells if ( !IsPositiveSpell(m_spellInfo->Id)) @@ -6132,7 +6132,7 @@ void Spell::EffectTransmitted(uint32 effIndex) linkedGO->SetSpellId(m_spellInfo->Id); linkedGO->SetOwnerGUID(m_caster->GetGUID() ); - MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO); + linkedGO->GetMap()->Add(linkedGO); } else { diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 0e766136696..3533c5c8a02 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -384,7 +384,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, fl weapon_mindamage = lvl*0.85*att_speed; weapon_maxdamage = lvl*1.25*att_speed; } - else if(!IsUseEquippedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) + else if(!IsUseEquipedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) { weapon_mindamage = BASE_MINDAMAGE; weapon_maxdamage = BASE_MAXDAMAGE; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index a6dae99b7ef..a78f1ca2c29 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1148,8 +1148,6 @@ void Unit::DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *da // Physical Damage if ( GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NORMAL ) { - uint32 modDamage=*damage; - // apply spellmod to Done damage if(Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_DAMAGE, *damage); @@ -1434,7 +1432,7 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage { if(!this || !pVictim) return 0; - if(!this->isAlive() || !pVictim->isAlive()) + if(!isAlive() || !pVictim->isAlive()) return 0; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); @@ -4127,12 +4125,17 @@ void Unit::RemoveNotOwnSingleTargetAuras() void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) { - if (IsSingleTargetSpell((*i).second->GetSpellProto())) + Aura* Aur = i->second; + SpellEntry const* AurSpellInfo = Aur->GetSpellProto(); + + Unit* caster = NULL; + if (IsSingleTargetSpell(AurSpellInfo)) { - if(Unit* caster = (*i).second->GetCaster()) + caster = Aur->GetCaster(); + if(caster) { AuraList& scAuras = caster->GetSingleCastAuras(); - scAuras.remove((*i).second); + scAuras.remove(Aur); } else { @@ -4141,7 +4144,8 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) } } - if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS) + // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) + if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) { m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second); if((*i).second->GetSpellProto()->AuraInterruptFlags) @@ -4153,8 +4157,6 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_ccAuras.remove((*i).second); } - // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) - Aura* Aur = i->second; // Set remove mode Aur->SetRemoveMode(mode); // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura @@ -4162,13 +4164,22 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_Auras.erase(i); ++m_removedAuras; // internal count used by unit update - // Status unsummoned at aura remove + // Statue unsummoned at aura remove Totem* statue = NULL; - if(IsChanneledSpell(Aur->GetSpellProto())) - if(Unit* caster = Aur->GetCaster()) + bool caster_channeled = false; + if(IsChanneledSpell(AurSpellInfo)) + { + if(!caster) // can be already located for IsSingleTargetSpell case + caster = Aur->GetCaster(); + + if(caster) + { if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE) statue = ((Totem*)caster); - + else + caster_channeled = caster==this; + } + } if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)Aur->GetSpellProto()->Id)) { @@ -4186,6 +4197,9 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) Aur->_RemoveAura(); delete Aur; + if(caster_channeled) + RemoveAurasAtChanneledTarget (AurSpellInfo); + if(statue) statue->UnSummon(); @@ -4611,8 +4625,10 @@ void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchool ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType); } -bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint32 /*effIndex*/, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 /*procFlag*/, uint32 cooldown) +bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 cooldown) { + SpellEntry const *hasteSpell = triggeredByAura->GetSpellProto(); + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; @@ -4672,8 +4688,11 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint return true; } -bool Unit::HandleDummyAuraProc(Unit *pVictim, SpellEntry const *dummySpell, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown) +bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown) { + SpellEntry const *dummySpell = triggeredByAura->GetSpellProto (); + uint32 effIndex = triggeredByAura->GetEffIndex (); + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; @@ -6261,7 +6280,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB if(!pVictim || !pVictim->isAlive()) return false; - uint32 spell = 0; switch(triggeredByAura->GetSpellProto()->Id) { case 20186: @@ -6291,7 +6309,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return false; // overwrite non existing triggered spell call in spell.dbc - uint32 spell = 0; switch(triggeredByAura->GetSpellProto()->Id) { case 20185: @@ -6491,8 +6508,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return true; } -bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) +bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) { + int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue; + if(!pVictim || !pVictim->isAlive()) return false; @@ -7258,7 +7277,7 @@ void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool c SendMessageToSet(&data, true); } -void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers powertype, bool critical) +void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers powertype) { WorldPacket data(SMSG_SPELLENERGIZELOG, (8+8+4+4+4+1)); data.append(pVictim->GetPackGUID()); @@ -7358,7 +7377,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 // ..taken AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) - if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) + if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; // .. taken pct: scripted (increases damage of * against targets *) @@ -8206,7 +8225,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT int32 TakenFlatBenefit = 0; // ..done (for creature type by mask) in taken - AuraList const& mDamageDoneCreature = this->GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); + AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) DoneFlatBenefit += (*i)->GetModifier()->m_amount; @@ -8274,7 +8293,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT // SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage // SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT included in weapon damage - AuraList const& mDamageDoneVersus = this->GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); + AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; @@ -8729,7 +8748,7 @@ void Unit::SetVisibility(UnitVisibility x) if(IsInWorld()) { - Map *m = MapManager::Instance().GetMap(GetMapId(), this); + Map *m = GetMap(); if(GetTypeId()==TYPEID_PLAYER) m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); @@ -9791,8 +9810,6 @@ void Unit::CleanupsBeforeDelete() RemoveFromWorld(); } - - CharmInfo* Unit::InitCharmInfo(Unit *charm) { if(!m_charmInfo) @@ -9956,17 +9973,15 @@ bool Unit::isFrozen() const struct ProcTriggeredData { - ProcTriggeredData(SpellEntry const * _spellInfo, uint32 _spellParam, Aura* _triggeredByAura, uint32 _cooldown) - : spellInfo(_spellInfo), spellParam(_spellParam), triggeredByAura(_triggeredByAura), + ProcTriggeredData(Aura* _triggeredByAura, uint32 _cooldown) + : triggeredByAura(_triggeredByAura), triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())), cooldown(_cooldown) - {} + {} - SpellEntry const * spellInfo; - uint32 spellParam; - Aura* triggeredByAura; - Unit::spellEffectPair triggeredByAura_SpellPair; - uint32 cooldown; + Aura* triggeredByAura; // triggred aura, can be invalidate at triggered aura proccessing + Unit::spellEffectPair triggeredByAura_SpellPair; // spell pair, used for re-find aura (by pointer comparison in range) + uint32 cooldown; // possible hidden cooldown }; typedef std::list< ProcTriggeredData > ProcTriggeredList; @@ -9983,87 +9998,13 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag { next = i; ++next; - SpellEntry const *spellProto = (*i)->GetSpellProto(); - if(!spellProto) - continue; + Aura* i_aura = *i; - SpellProcEventEntry const *spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id); - if(!spellProcEvent) - { - // used to prevent spam in log about same non-handled spells - static std::set<uint32> nonHandledSpellProcSet; - - if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end()) - { - sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's")); - nonHandledSpellProcSet.insert(spellProto->Id); - } - - // spell.dbc use totally different flags, that only can create problems if used. - continue; - } - - // Check spellProcEvent data requirements - if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag)) + uint32 cooldown; // returned at next line + if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,cooldown)) continue; - // Check if current equipment allows aura to proc - if(!isVictim && GetTypeId() == TYPEID_PLAYER ) - { - if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) - { - Item *item = ((Player*)this)->GetWeaponForAttack(attType,true); - - if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) - continue; - } - else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) - { - // Check if player is wearing shield - Item *item = ((Player*)this)->GetShield(true); - if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) - continue; - } - } - - float chance = (float)spellProto->procChance; - - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance); - - if(!isVictim && spellProcEvent->ppmRate != 0) - { - uint32 WeaponSpeed = GetAttackTime(attType); - chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate); - } - - if(roll_chance_f(chance)) - { - uint32 cooldown = spellProcEvent->cooldown; - - uint32 i_spell_eff = (*i)->GetEffIndex(); - - int32 i_spell_param; - switch(*aur) - { - case SPELL_AURA_PROC_TRIGGER_SPELL: - i_spell_param = procFlag; - break; - case SPELL_AURA_DUMMY: - case SPELL_AURA_PRAYER_OF_MENDING: - case SPELL_AURA_MOD_HASTE: - i_spell_param = i_spell_eff; - break; - case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: - i_spell_param = (*i)->GetModifier()->m_miscvalue; - break; - default: - i_spell_param = (*i)->GetModifier()->m_amount; - break; - } - - procTriggered.push_back( ProcTriggeredData(spellProto,i_spell_param,*i, cooldown) ); - } + procTriggered.push_back( ProcTriggeredData(i_aura, cooldown) ); } // Handle effects proceed this time @@ -10096,106 +10037,71 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag } } - // save charges existence before processing to prevent crash at access to deleted triggered aura after - bool triggeredByAuraWithCharges = i->triggeredByAura->m_procCharges > 0; + /// this is aura triggering code call + Aura* triggeredByAura = i->triggeredByAura; + /// save charges existence before processing to prevent crash at access to deleted triggered aura after + /// used in speedup code check before check aura existance. + bool triggeredByAuraWithCharges = triggeredByAura->m_procCharges > 0; + + /// success in event proccesing + /// used in speedup code check before check aura existance. bool casted = false; + + /// process triggered code switch(*aur) { case SPELL_AURA_PROC_TRIGGER_SPELL: { - sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleProcTriggerSpell(pTarget, damage, i->triggeredByAura, procSpell,i->spellParam,attType,i->cooldown); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s proc aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, attType, i->cooldown); break; } case SPELL_AURA_PROC_TRIGGER_DAMAGE: { - sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", i->spellParam, i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - uint32 damage = i->spellParam; - SpellNonMeleeDamageLog(pTarget, i->spellInfo->Id, damage, true, true); + uint32 triggered_damage = triggeredByAura->GetModifier()->m_amount; + sLog.outDebug("ProcDamageAndSpell: doing %u damage (triggered by %s aura of spell %u)", + triggered_damage, (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + SpellNonMeleeDamageLog(pTarget, triggeredByAura->GetId(), triggered_damage, true, true); casted = true; break; } case SPELL_AURA_DUMMY: { - sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleDummyAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); + uint32 effect = triggeredByAura->GetEffIndex(); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s dummy aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown); break; } case SPELL_AURA_PRAYER_OF_MENDING: { - sLog.outDebug("ProcDamageAndSpell(mending): casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - - // aura can be deleted at casts - int32 heal = i->triggeredByAura->GetModifier()->m_amount; - uint64 caster_guid = i->triggeredByAura->GetCasterGUID(); - - // jumps - int32 jumps = i->triggeredByAura->m_procCharges-1; - - // current aura expire - i->triggeredByAura->m_procCharges = 1; // will removed at next charges decrease - - // next target selection - if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid)) - { - Aura* aura = i->triggeredByAura; - - SpellEntry const* spellProto = aura->GetSpellProto(); - uint32 effIdx = aura->GetEffIndex(); - - float radius; - if (spellProto->EffectRadiusIndex[effIdx]) - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); - else - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); - - if(Player* caster = ((Player*)aura->GetCaster())) - { - caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); + sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius)) - { - // aura will applied from caster, but spell casted from current aura holder - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_CHARGES; - mod->value = jumps-5; // negative - mod->type = SPELLMOD_FLAT; - mod->spellId = spellProto->Id; - mod->effectId = effIdx; - mod->lastAffected = NULL; - mod->mask = spellProto->SpellFamilyFlags; - mod->charges = 0; - - caster->AddSpellMod(mod, true); - CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,aura,caster->GetGUID()); - caster->AddSpellMod(mod, false); - } - } - } - - // heal - CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid); - casted = true; + casted = HandleMeandingAuraProc(triggeredByAura); break; } case SPELL_AURA_MOD_HASTE: { - sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleHasteAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s haste aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown); break; } case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: { // nothing do, just charges counter // but count only in case appropriate school damage - casted = i->triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask; + casted = triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask; break; } case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: { - sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleOverrideClassScriptAuraProc(pTarget, i->spellParam, damage, i->triggeredByAura, procSpell,i->cooldown); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s class script aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleOverrideClassScriptAuraProc(pTarget, triggeredByAura, procSpell,i->cooldown); break; } default: @@ -10206,27 +10112,27 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag } } - // Update charge (aura can be removed by triggers) + /// Update charge (aura can be removed by triggers) if(casted && triggeredByAuraWithCharges) { - // need found aura (can be dropped by triggers) + /// need re-found aura (can be dropped by triggers) AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair); AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair); for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr) { - if(itr->second == i->triggeredByAura) + if(itr->second == triggeredByAura) // pointer still valid { - if(i->triggeredByAura->m_procCharges > 0) - i->triggeredByAura->m_procCharges -= 1; + if(triggeredByAura->m_procCharges > 0) + triggeredByAura->m_procCharges -= 1; - i->triggeredByAura->UpdateAuraCharges(); + triggeredByAura->UpdateAuraCharges(); break; } } } } - // Safely remove auras with zero charges + /// Safely remove auras with zero charges for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next) { next = i; ++next; @@ -10339,7 +10245,7 @@ void Unit::StopMoving() // send explicit stop packet // rely on vmaps here because for example stormwind is in air - float z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true); + //float z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true); //if (fabs(GetPositionZ() - z) < 2.0f) // Relocate(GetPositionX(), GetPositionY(), z); Relocate(GetPositionX(), GetPositionY(),GetPositionZ()); @@ -10823,9 +10729,9 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return NULL; } - pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, this->GetGUID()); - pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, this->GetGUID()); - pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,this->getFaction()); + pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, GetGUID()); + pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, GetGUID()); + pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id); if(!pet->InitStatsForLevel(creatureTarget->getLevel())) @@ -10843,3 +10749,132 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return pet; } + +bool Unit::IsTriggeredAtSpellProcEvent(SpellEntry const* spellProto, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, bool isVictim, uint32& cooldown ) +{ + SpellProcEventEntry const * spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id); + + if(!spellProcEvent) + { + // used to prevent spam in log about same non-handled spells + static std::set<uint32> nonHandledSpellProcSet; + + if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end()) + { + sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's")); + nonHandledSpellProcSet.insert(spellProto->Id); + } + + // spell.dbc use totally different flags, that only can create problems if used. + return false; + } + + // Check spellProcEvent data requirements + if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag)) + return false; + + // Check if current equipment allows aura to proc + if(!isVictim && GetTypeId() == TYPEID_PLAYER ) + { + if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) + { + Item *item = ((Player*)this)->GetWeaponForAttack(attType,true); + + if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) + return false; + } + else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) + { + // Check if player is wearing shield + Item *item = ((Player*)this)->GetShield(true); + if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) + return false; + } + } + + float chance = (float)spellProto->procChance; + + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance); + + if(!isVictim && spellProcEvent && spellProcEvent->ppmRate != 0) + { + uint32 WeaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate); + } + + cooldown = spellProcEvent ? spellProcEvent->cooldown : 0; + return roll_chance_f(chance); +} + +bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura ) +{ + // aura can be deleted at casts + SpellEntry const* spellProto = triggeredByAura->GetSpellProto(); + uint32 effIdx = triggeredByAura->GetEffIndex(); + int32 heal = triggeredByAura->GetModifier()->m_amount; + uint64 caster_guid = triggeredByAura->GetCasterGUID(); + + // jumps + int32 jumps = triggeredByAura->m_procCharges-1; + + // current aura expire + triggeredByAura->m_procCharges = 1; // will removed at next charges decrease + + // next target selection + if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid)) + { + float radius; + if (spellProto->EffectRadiusIndex[effIdx]) + radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); + else + radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); + + if(Player* caster = ((Player*)triggeredByAura->GetCaster())) + { + caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); + + if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius)) + { + // aura will applied from caster, but spell casted from current aura holder + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_CHARGES; + mod->value = jumps-5; // negative + mod->type = SPELLMOD_FLAT; + mod->spellId = spellProto->Id; + mod->effectId = effIdx; + mod->lastAffected = NULL; + mod->mask = spellProto->SpellFamilyFlags; + mod->charges = 0; + + caster->AddSpellMod(mod, true); + CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID()); + caster->AddSpellMod(mod, false); + } + } + } + + // heal + CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid); + return true; +} + +void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo) +{ + uint64 target_guid = GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT); + + if(!IS_UNIT_GUID(target_guid)) + return; + + Unit* target = ObjectAccessor::GetUnit(*this, target_guid); + if(!target) + return; + + for (AuraMap::iterator iter = target->GetAuras().begin(); iter != target->GetAuras().end(); ) + { + if (iter->second->GetId() == spellInfo->Id && iter->second->GetCasterGUID()==GetGUID()) + target->RemoveAura(iter); + else + ++iter; + } +} diff --git a/src/game/Unit.h b/src/game/Unit.h index 028c590c06f..4a5dc7e4bb9 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -15,7 +15,7 @@ * * 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 */ #ifndef __UNIT_H @@ -933,7 +933,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool isInAccessiblePlaceFor(Creature const* c) const; void SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool critical = false); - void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,Powers powertype, bool critical = false); + void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,Powers powertype); uint32 SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell = false, bool useSpellDamage = true); void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); void CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); @@ -1039,6 +1039,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler); void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); void RemoveAurasDueToSpellByCancel(uint32 spellId); + void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo); void RemoveNotOwnSingleTargetAuras(); void RemoveSpellsCausingAura(AuraType auraType); @@ -1370,10 +1371,12 @@ class TRINITY_DLL_SPEC Unit : public WorldObject //void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*) void ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask ); - bool HandleDummyAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); - bool HandleProcTriggerSpell(Unit *pVictim,uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attType,uint32 cooldown); - bool HandleHasteAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); - bool HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell,uint32 cooldown); + bool IsTriggeredAtSpellProcEvent( SpellEntry const* spellProto, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, bool isVictim, uint32& cooldown ); + bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 cooldown); + bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, uint32 cooldown); + bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 cooldown); + bool HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 cooldown); + bool HandleMeandingAuraProc(Aura* triggeredByAura); uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; diff --git a/win/VC71/game.vcproj b/win/VC71/game.vcproj index 6c14ab272d6..722300b9e8a 100644 --- a/win/VC71/game.vcproj +++ b/win/VC71/game.vcproj @@ -337,6 +337,12 @@ RelativePath="..\..\src\game\MapManager.h"> </File> <File + RelativePath="..\..\src\game\MapReference.h"> + </File> + <File + RelativePath="..\..\src\game\MapRefManager.h"> + </File> + <File RelativePath="..\..\src\game\MiscHandler.cpp"> </File> <File diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj index 9ce5146d8b1..d8bd6bf726d 100644 --- a/win/VC80/game.vcproj +++ b/win/VC80/game.vcproj @@ -627,6 +627,14 @@ > </File> <File + RelativePath="..\..\src\game\MapReference.h" + > + </File> + <File + RelativePath="..\..\src\game\MapRefManager.h" + > + </File> + <File RelativePath="..\..\src\game\MiscHandler.cpp" > </File> diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj index 9ca7efc8178..89f4341ebc6 100644 --- a/win/VC90/game.vcproj +++ b/win/VC90/game.vcproj @@ -632,6 +632,14 @@ > </File> <File + RelativePath="..\..\src\game\MapReference.h" + > + </File> + <File + RelativePath="..\..\src\game\MapRefManager.h" + > + </File> + <File RelativePath="..\..\src\game\MiscHandler.cpp" > </File> |