diff --git a/src/framework/Utilities/EventProcessor.cpp b/src/framework/Utilities/EventProcessor.cpp index 65de7c1aa..2bcf6a46a 100644 --- a/src/framework/Utilities/EventProcessor.cpp +++ b/src/framework/Utilities/EventProcessor.cpp @@ -26,7 +26,7 @@ EventProcessor::EventProcessor() EventProcessor::~EventProcessor() { - KillAllEvents(); + KillAllEvents(true); } void EventProcessor::Update(uint32 p_time) @@ -58,21 +58,31 @@ void EventProcessor::Update(uint32 p_time) } } -void EventProcessor::KillAllEvents() +void EventProcessor::KillAllEvents(bool force) { // prevent event insertions m_aborting = true; // first, abort all existing events - for (EventList::iterator i = m_events.begin(); i != m_events.end(); ++i) + for (EventList::iterator i = m_events.begin(); i != m_events.end();) { - i->second->to_Abort = true; - i->second->Abort(m_time); - delete i->second; + EventList::iterator i_old = i; + ++i; + + i_old->second->to_Abort = true; + i_old->second->Abort(m_time); + if(force || i_old->second->IsDeletable()) + { + delete i_old->second; + + if(!force) // need per-element cleanup + m_events.erase (i_old); + } } - // clear event list - m_events.clear(); + // fast clear event list (in force case) + if(force) + m_events.clear(); } void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) diff --git a/src/framework/Utilities/EventProcessor.h b/src/framework/Utilities/EventProcessor.h index 5d83c02a2..350db5bb5 100644 --- a/src/framework/Utilities/EventProcessor.h +++ b/src/framework/Utilities/EventProcessor.h @@ -38,6 +38,8 @@ class BasicEvent // e_time is execution time, p_time is update interval virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } + virtual bool IsDeletable() const { return true; } // this event can be safely deleted + virtual void Abort(uint64 /*e_time*/) {} // this method executes when the event is aborted bool to_Abort; // set by externals when the event is aborted, aborted events don't execute @@ -57,7 +59,7 @@ class EventProcessor ~EventProcessor(); void Update(uint32 p_time); - void KillAllEvents(); + void KillAllEvents(bool force); void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); uint64 CalculateTime(uint64 t_offset); protected: diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 36ae28165..b8796f61a 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -88,40 +88,45 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid) std::string plName; uint8 plClass; + // arena team is full (can't have more than type * 2 players!) if(GetMembersSize() >= GetType() * 2) - { - // arena team is full (can't have more than type * 2 players!) - // return false return false; - } - if(!objmgr.GetPlayerNameByGUID(PlayerGuid, plName)) // player doesnt exist - return false; - // player already in arenateam of that size - if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0) + Player *pl = objmgr.GetPlayer(PlayerGuid); + if(pl) { - sLog.outError("Arena::AddMember() : player already in this sized team"); - return false; + if(pl->GetArenaTeamId(GetType())) + { + sLog.outError("Arena::AddMember() : player already in this sized team"); + return false; + } + + plClass = (uint8)pl->getClass(); + plName = pl->GetName(); + } + else + { + // 0 1 + QueryResult *result = CharacterDatabase.PQuery("SELECT name, class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid)); + if(!result) + return false; + + plName = (*result)[0].GetCppString(); + plClass = (*result)[1].GetUInt8(); + delete result; + + // check if player already in arenateam of that size + if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0) + { + sLog.outError("Arena::AddMember() : player already in this sized team"); + return false; + } } // remove all player signs from another petitions // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(PlayerGuid, GetType()); - Player *pl = objmgr.GetPlayer(PlayerGuid); - if(pl) - { - plClass = (uint8)pl->getClass(); - } - else - { - QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid)); - if(!result) - return false; - plClass = (*result)[0].GetUInt8(); - delete result; - } - ArenaTeamMember newmember; newmember.name = plName; newmember.guid = PlayerGuid; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 286b94553..2c3df86b0 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -643,7 +643,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) } // friend status - sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), "", true); + sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index 21aff8093..1debe2491 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -268,7 +268,7 @@ void InstanceSaveManager::CleanupInstances() // creature_respawn and gameobject_respawn are in another database // first, obtain total instance set std::set< uint32 > InstanceSet; - QueryResult *result = CharacterDatabase.PQuery("SELECT id FROM instance"); + QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance"); if( result ) { do @@ -281,7 +281,7 @@ void InstanceSaveManager::CleanupInstances() } // creature_respawn - result = WorldDatabase.PQuery("SELECT DISTINCT(instance) FROM creature_respawn WHERE instance <> 0"); + result = WorldDatabase.Query("SELECT DISTINCT(instance) FROM creature_respawn WHERE instance <> 0"); if( result ) { do @@ -295,7 +295,7 @@ void InstanceSaveManager::CleanupInstances() } // gameobject_respawn - result = WorldDatabase.PQuery("SELECT DISTINCT(instance) FROM gameobject_respawn WHERE instance <> 0"); + result = WorldDatabase.Query("SELECT DISTINCT(instance) FROM gameobject_respawn WHERE instance <> 0"); if( result ) { do @@ -324,7 +324,7 @@ void InstanceSaveManager::PackInstances() // all valid ids are in the instance table // any associations to ids not in this table are assumed to be // cleaned already in CleanupInstances - QueryResult *result = CharacterDatabase.PQuery("SELECT id FROM instance"); + QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance"); if( result ) { do @@ -374,7 +374,7 @@ void InstanceSaveManager::LoadResetTimes() // resettime = 0 in the DB for raid/heroic instances so those are skipped typedef std::map > ResetTimeMapType; ResetTimeMapType InstResetTime; - QueryResult *result = CharacterDatabase.PQuery("SELECT id, map, resettime FROM instance WHERE resettime > 0"); + QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0"); if( result ) { do @@ -390,7 +390,7 @@ void InstanceSaveManager::LoadResetTimes() delete result; // update reset time for normal instances with the max creature respawn time + X hours - result = WorldDatabase.PQuery("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); + result = WorldDatabase.Query("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); if( result ) { do diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 2a872f378..9a0e20386 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4220,6 +4220,7 @@ bool ChatHandler::HandleNpcTameCommand(const char* args) // set pet to defensive mode by default (some classes can't control controlled pets in fact). pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); + // calculate proper level uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); // prepare visual effect for levelup diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 7590c21f6..25f616e83 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1355,6 +1355,9 @@ void Map::RemoveAllObjectsInRemoveList() Remove((GameObject*)obj,true); break; case TYPEID_UNIT: + // in case triggred sequence some spell can continue casting after prev CleanupsBeforeDelete call + // make sure that like sources auras/etc removed before destructor start + ((Creature*)obj)->CleanupsBeforeDelete (); Remove((Creature*)obj,true); break; default: diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 9deb8582e..29bb37bc1 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "Language.h" #include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" #include "WorldPacket.h" #include "Opcodes.h" #include "Log.h" @@ -643,11 +644,8 @@ void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: Received CMSG_ADD_FRIEND" ); - std::string friendName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); + std::string friendName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); std::string friendNote; - FriendsResult friendResult = FRIEND_NOT_FOUND; - Player *pFriend = NULL; - uint64 friendGuid = 0; recv_data >> friendName; @@ -664,50 +662,51 @@ void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName(), friendName.c_str() ); - friendGuid = objmgr.GetPlayerGUIDByName(friendName); + CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race FROM characters WHERE name = '%s'", friendName.c_str()); +} +void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult *result, uint32 accountId, std::string friendNote) +{ + if(!result) + return; + + uint64 friendGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + uint32 team = Player::TeamForRace((*result)[1].GetUInt8()); + + delete result; + + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + return; + + FriendsResult friendResult = FRIEND_NOT_FOUND; if(friendGuid) { - pFriend = ObjectAccessor::FindPlayer(friendGuid); - if(pFriend==GetPlayer()) + if(friendGuid==session->GetPlayer()->GetGUID()) friendResult = FRIEND_SELF; - else if(GetPlayer()->GetTeam()!=objmgr.GetPlayerTeamByGUID(friendGuid) && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && GetSecurity() < SEC_MODERATOR) + else if(session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR) friendResult = FRIEND_ENEMY; - else if(GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) + else if(session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) friendResult = FRIEND_ALREADY; - } - - if (friendGuid && friendResult==FRIEND_NOT_FOUND) - { - if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer())) - friendResult = FRIEND_ADDED_ONLINE; else - friendResult = FRIEND_ADDED_OFFLINE; - - if(!_player->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) { - friendResult = FRIEND_LIST_FULL; - sLog.outDebug( "WORLD: %s's friend list is full.", GetPlayer()->GetName()); + Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); + if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer())) + friendResult = FRIEND_ADDED_ONLINE; + else + friendResult = FRIEND_ADDED_OFFLINE; + + if(!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) + { + friendResult = FRIEND_LIST_FULL; + sLog.outDebug( "WORLD: %s's friend list is full.", session->GetPlayer()->GetName()); + } + + session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); } - - _player->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); - - sLog.outDebug( "WORLD: %s Guid found '%u'.", friendName.c_str(), GUID_LOPART(friendGuid)); - } - else if(friendResult==FRIEND_ALREADY) - { - sLog.outDebug( "WORLD: %s Guid Already a Friend.", friendName.c_str() ); - } - else if(friendResult==FRIEND_SELF) - { - sLog.outDebug( "WORLD: %s Guid can't add himself.", friendName.c_str() ); - } - else - { - sLog.outDebug( "WORLD: %s Guid not found.", friendName.c_str() ); } - sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), friendName, false); + sSocialMgr.SendFriendStatus(session->GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); } @@ -724,7 +723,7 @@ void WorldSession::HandleDelFriendOpcode( WorldPacket & recv_data ) _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); - sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), "", false); + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); sLog.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" ); } @@ -736,8 +735,6 @@ void WorldSession::HandleAddIgnoreOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: Received CMSG_ADD_IGNORE" ); std::string IgnoreName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); - FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; - uint64 IgnoreGuid = 0; recv_data >> IgnoreName; @@ -749,40 +746,40 @@ void WorldSession::HandleAddIgnoreOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: %s asked to Ignore: '%s'", GetPlayer()->GetName(), IgnoreName.c_str() ); - IgnoreGuid = objmgr.GetPlayerGUIDByName(IgnoreName); + CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddIgnoreOpcodeCallBack, GetAccountId(), "SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str()); +} +void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult *result, uint32 accountId) +{ + if(!result) + return; + + uint64 IgnoreGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + delete result; + + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + return; + + FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; if(IgnoreGuid) { - if(IgnoreGuid==GetPlayer()->GetGUID()) + if(IgnoreGuid==session->GetPlayer()->GetGUID()) //not add yourself ignoreResult = FRIEND_IGNORE_SELF; + else if( session->GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)) ) + ignoreResult = FRIEND_IGNORE_ALREADY; else { - if( GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)) ) - ignoreResult = FRIEND_IGNORE_ALREADY; + ignoreResult = FRIEND_IGNORE_ADDED; + + // ignore list full + if(!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) + ignoreResult = FRIEND_IGNORE_FULL; } } - if (IgnoreGuid && ignoreResult == FRIEND_IGNORE_NOT_FOUND) - { - ignoreResult = FRIEND_IGNORE_ADDED; - - if(!_player->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) - ignoreResult = FRIEND_IGNORE_FULL; - } - else if(ignoreResult==FRIEND_IGNORE_ALREADY) - { - sLog.outDebug( "WORLD: %s Guid Already Ignored.", IgnoreName.c_str() ); - } - else if(ignoreResult==FRIEND_IGNORE_SELF) - { - sLog.outDebug( "WORLD: %s Guid can't add himself.", IgnoreName.c_str() ); - } - else - { - sLog.outDebug( "WORLD: %s Guid not found.", IgnoreName.c_str() ); - } - - sSocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), "", false); + sSocialMgr.SendFriendStatus(session->GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); } @@ -799,7 +796,7 @@ void WorldSession::HandleDelIgnoreOpcode( WorldPacket & recv_data ) _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); - sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), "", false); + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); sLog.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" ); } diff --git a/src/game/Object.h b/src/game/Object.h index ce905cb50..d71da5622 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -30,9 +30,8 @@ #include #define CONTACT_DISTANCE 0.5f -#define INTERACTION_DISTANCE 5 -#define ATTACK_DISTANCE 5 -#define DETECT_DISTANCE 20 // max distance to successful detect stealthed unit +#define INTERACTION_DISTANCE 5.0f +#define ATTACK_DISTANCE 5.0f #define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2.0f) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells) #define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index f17a3899a..a048cab07 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2682,7 +2682,7 @@ void ObjectMgr::LoadGroups() uint64 leaderGuid = 0; uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - QueryResult *result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, leaderGuid FROM groups"); + QueryResult *result = CharacterDatabase.Query("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, leaderGuid FROM groups"); if( !result ) { @@ -2724,7 +2724,7 @@ void ObjectMgr::LoadGroups() group = NULL; leaderGuid = 0; // 0 1 2 3 - result = CharacterDatabase.PQuery("SELECT memberGuid, assistant, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid"); + result = CharacterDatabase.Query("SELECT memberGuid, assistant, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid"); if(!result) { barGoLink bar( 1 ); @@ -2777,7 +2777,7 @@ void ObjectMgr::LoadGroups() count = 0; group = NULL; leaderGuid = 0; - result = CharacterDatabase.PQuery( + result = CharacterDatabase.Query( // 0 1 2 3 4 5 "SELECT leaderGuid, map, instance, permanent, difficulty, resettime, " // 6 @@ -3645,7 +3645,7 @@ void ObjectMgr::LoadQuestLocales() void ObjectMgr::LoadPetCreateSpells() { - QueryResult *result = WorldDatabase.PQuery("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); + QueryResult *result = WorldDatabase.Query("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); if(!result) { barGoLink bar( 1 ); @@ -3854,19 +3854,22 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) if(float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) { - sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u",tablename,tmp.datalong2,tmp.id); + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u", + tablename,tmp.datalong2,tmp.id); continue; } if(tmp.datalong2 && float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) { - sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %u or 0 for disable distance check",tablename,tmp.datalong2,tmp.id,uint32(DEFAULT_VISIBILITY_DISTANCE)); + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %f or 0 for disable distance check", + tablename,tmp.datalong2,tmp.id,DEFAULT_VISIBILITY_DISTANCE); continue; } if(tmp.datalong2 && float(tmp.datalong2) < INTERACTION_DISTANCE) { - sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %u or 0 for disable distance check",tablename,tmp.datalong2,tmp.id,uint32(INTERACTION_DISTANCE)); + sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %f or 0 for disable distance check", + tablename,tmp.datalong2,tmp.id,INTERACTION_DISTANCE); continue; } @@ -3878,7 +3881,8 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) { if(!sSpellStore.LookupEntry(tmp.datalong)) { - sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u",tablename,tmp.datalong,tmp.id); + sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u", + tablename,tmp.datalong,tmp.id); continue; } break; @@ -4025,7 +4029,7 @@ void ObjectMgr::LoadEventScripts() void ObjectMgr::LoadItemTexts() { - QueryResult *result = CharacterDatabase.PQuery("SELECT id, text FROM item_text"); + QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text"); uint32 count = 0; @@ -4108,7 +4112,7 @@ void ObjectMgr::LoadPageTextLocales() { mPageTextLocaleMap.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); + QueryResult *result = WorldDatabase.Query("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); if(!result) { @@ -5619,7 +5623,7 @@ void ObjectMgr::LoadCorpses() { uint32 count = 0; // 0 1 2 3 4 5 6 7 8 10 - QueryResult *result = CharacterDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, guid FROM corpse WHERE corpse_type <> 0"); + QueryResult *result = CharacterDatabase.Query("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, guid FROM corpse WHERE corpse_type <> 0"); if( !result ) { @@ -5983,7 +5987,7 @@ void ObjectMgr::LoadReservedPlayersNames() { m_ReservedNames.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT name FROM reserved_name"); + QueryResult *result = WorldDatabase.Query("SELECT name FROM reserved_name"); uint32 count = 0; @@ -6840,7 +6844,7 @@ void ObjectMgr::LoadTrainerSpell() std::set skip_trainers; - QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); + QueryResult *result = WorldDatabase.Query("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); if( !result ) { @@ -6931,7 +6935,7 @@ void ObjectMgr::LoadVendors() std::set skip_vendors; - QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor"); + QueryResult *result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor"); if( !result ) { barGoLink bar( 1 ); @@ -6977,7 +6981,7 @@ void ObjectMgr::LoadNpcTextId() m_mCacheNpcTextIdMap.clear(); - QueryResult* result = WorldDatabase.PQuery("SELECT npc_guid, textid FROM npc_gossip"); + QueryResult* result = WorldDatabase.Query("SELECT npc_guid, textid FROM npc_gossip"); if( !result ) { barGoLink bar( 1 ); diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 186d179f8..3c368c30b 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -833,8 +833,9 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) for(uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); - sLog.outDebug("PetitionsHandler: adding arena member %u", fields[0].GetUInt64()); - at->AddMember(fields[0].GetUInt64()); + uint64 memberGUID = fields[0].GetUInt64(); + sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID)); + at->AddMember(memberGUID); result->NextRow(); } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 992c73fd8..4c6a4af35 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3977,24 +3977,20 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g uint32 LostDurability = maxDurability - curDurability; if(LostDurability>0) { - ItemPrototype const *ditemProto = sItemStorage.LookupEntry(item->GetEntry()); - if(!ditemProto) - { - sLog.outError("ERROR: RepairDurability: Unknown item id %u", ditemProto); - return TotalCost; - } + ItemPrototype const *ditemProto = item->GetProto(); DurabilityCostsEntry const *dcost = sDurabilityCostsStore.LookupEntry(ditemProto->ItemLevel); if(!dcost) { - sLog.outError("ERROR: RepairDurability: Wrong item lvl %u", dcost); + sLog.outError("ERROR: RepairDurability: Wrong item lvl %u", ditemProto->ItemLevel); return TotalCost; } - DurabilityQualityEntry const *dQualitymodEntry = sDurabilityQualityStore.LookupEntry((ditemProto->Quality+1)*2); + uint32 dQualitymodEntryId = (ditemProto->Quality+1)*2; + DurabilityQualityEntry const *dQualitymodEntry = sDurabilityQualityStore.LookupEntry(dQualitymodEntryId); if(!dQualitymodEntry) { - sLog.outError("ERROR: RepairDurability: Wrong dQualityModEntry %u", dQualitymodEntry); + sLog.outError("ERROR: RepairDurability: Wrong dQualityModEntry %u", dQualitymodEntryId); return TotalCost; } @@ -6054,32 +6050,13 @@ uint32 Player::GetRankFromDB(uint64 guid) uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) { - // need fix it! - QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid FROM arena_team_member WHERE guid='%u'", GUID_LOPART(guid)); - if(result) - { - // init id to 0, check the arena type before assigning a value to id - uint32 id = 0; - do - { - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM arena_team WHERE arenateamid='%u'", id); - if(result2) - { - uint8 dbtype = (*result2)[0].GetUInt32(); - delete result2; - if(dbtype == type) - { - // if the type matches, we've found the id - id = (*result)[0].GetUInt32(); - break; - } - } - } while(result->NextRow()); - delete result; - return id; - } - // no arenateam for the specified guid, return 0 - return 0; + QueryResult *result = CharacterDatabase.PQuery("SELECT arena_team_member.arenateamid FROM arena_team_member JOIN arena_team ON arena_team_member.arenateamid = arena_team.arenateamid WHERE guid='%u' AND type='%u' LIMIT 1", GUID_LOPART(guid), type); + if(!result) + return 0; + + uint32 id = (*result)[0].GetUInt32(); + delete result; + return id; } uint32 Player::GetZoneIdFromDB(uint64 guid) diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 12fc3a8a3..2f553bf3e 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -200,7 +200,8 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: CMSG_CREATURE_QUERY - (%u) NO CREATURE INFO! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); + sLog.outDebug("WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)", + GUID_LOPART(guid), entry); WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 4 ); data << uint32(entry | 0x80000000); SendPacket( &data ); @@ -259,7 +260,8 @@ void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - (%u) Missing gameobject info for (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entryID ); + sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", + GUID_LOPART(guid), entryID ); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 ); data << uint32(entryID | 0x80000000); SendPacket( &data ); diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 0334332a9..5b68829ab 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -85,12 +85,13 @@ void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u",guid ); + sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_NONE); if (!pCreature) { - sLog.outDebug( "WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", + GUID_LOPART(guid)); return; } diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp index 5a1de100f..ccb35ef74 100644 --- a/src/game/SkillDiscovery.cpp +++ b/src/game/SkillDiscovery.cpp @@ -52,7 +52,7 @@ void LoadSkillDiscoveryTable() uint32 count = 0; // 0 1 2 - QueryResult *result = WorldDatabase.PQuery("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); + QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); if (result) { diff --git a/src/game/SkillExtraItems.cpp b/src/game/SkillExtraItems.cpp index c9d5f7e03..eebb443d4 100644 --- a/src/game/SkillExtraItems.cpp +++ b/src/game/SkillExtraItems.cpp @@ -57,7 +57,7 @@ void LoadSkillExtraItemTable() SkillExtraItemStore.clear(); // need for reload // 0 1 2 3 - QueryResult *result = WorldDatabase.PQuery("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template"); + QueryResult *result = WorldDatabase.Query("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template"); if (result) { diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp index cdb2c3919..6973bc352 100644 --- a/src/game/SocialMgr.cpp +++ b/src/game/SocialMgr.cpp @@ -235,7 +235,7 @@ void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldP *data << uint64(guid); } -void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast) +void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, bool broadcast) { FriendInfo fi; diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h index c4a19295a..8c873d8a0 100644 --- a/src/game/SocialMgr.h +++ b/src/game/SocialMgr.h @@ -145,7 +145,7 @@ class SocialMgr void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo); // Packet management void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data); - void SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast); + void SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, bool broadcast); void BroadcastToFriendListers(Player *player, WorldPacket *packet); // Loading PlayerSocial *LoadFromDB(QueryResult *result, uint32 guid); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 0dcab744f..e0bdcc001 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -268,7 +268,8 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_caster = Caster; m_selfContainer = NULL; m_triggeringContainer = triggeringContainer; - m_deletable = true; + m_referencedFromCurrentSpell = false; + m_executedCurrently = false; m_delayAtDamageCount = 0; m_applyMultiplierMask = 0; @@ -2020,6 +2021,8 @@ void Spell::cancel() void Spell::cast(bool skipCheck) { + SetExecutedCurrently(true); + uint8 castResult = 0; // update pointers base at GUIDs to prevent access to non-existed already object @@ -2029,6 +2032,7 @@ void Spell::cast(bool skipCheck) if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID()) { cancel(); + SetExecutedCurrently(false); return; } @@ -2040,6 +2044,7 @@ void Spell::cast(bool skipCheck) { SendCastResult(castResult); finish(false); + SetExecutedCurrently(false); return; } @@ -2051,6 +2056,7 @@ void Spell::cast(bool skipCheck) { SendCastResult(castResult); finish(false); + SetExecutedCurrently(false); return; } } @@ -2083,7 +2089,10 @@ void Spell::cast(bool skipCheck) FillTargetMap(); if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap + { + SetExecutedCurrently(false); return; + } SendCastResult(castResult); SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()... @@ -2115,6 +2124,8 @@ void Spell::cast(bool skipCheck) // Immediate spell, no big deal handle_immediate(); } + + SetExecutedCurrently(false); } void Spell::handle_immediate() @@ -5106,3 +5117,8 @@ void SpellEvent::Abort(uint64 /*e_time*/) if (m_Spell->getState() != SPELL_STATE_FINISHED) m_Spell->cancel(); } + +bool SpellEvent::IsDeletable() const +{ + return m_Spell->IsDeletable(); +} diff --git a/src/game/Spell.h b/src/game/Spell.h index 95c5d856a..f1b997712 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -388,8 +388,9 @@ class Spell bool IsMeleeAttackResetSpell() const { return !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } bool IsRangedAttackResetSpell() const { return !m_IsTriggeredSpell && IsRangedSpell() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } - bool IsDeletable() const { return m_deletable; } - void SetDeletable(bool deletable) { m_deletable = deletable; } + bool IsDeletable() const { return !m_referencedFromCurrentSpell && !m_executedCurrently; } + void SetReferencedFromCurrent(bool yes) { m_referencedFromCurrentSpell = yes; } + void SetExecutedCurrently(bool yes) { m_executedCurrently = yes; } uint64 GetDelayStart() const { return m_delayStart; } void SetDelayStart(uint64 m_time) { m_delayStart = m_time; } uint64 GetDelayMoment() const { return m_delayMoment; } @@ -441,7 +442,8 @@ class Spell bool m_immediateHandled; // were immediate actions handled? (used by delayed spells only) // These vars are used in both delayed spell system and modified immediate spell system - bool m_deletable; // is the spell pending deletion or must be updated till permitted to delete? + bool m_referencedFromCurrentSpell; // mark as references to prevent deleted and access by dead pointers + bool m_executedCurrently; // mark as executed to prevent deleted and access by dead pointers bool m_needSpellLog; // need to send spell log? uint8 m_applyMultiplierMask; // by effect: damage multiplier needed? float m_damageMultipliers[3]; // by effect: damage multiplier @@ -703,6 +705,7 @@ class SpellEvent : public BasicEvent virtual bool Execute(uint64 e_time, uint32 p_time); virtual void Abort(uint64 e_time); + virtual bool IsDeletable() const; protected: Spell* m_Spell; }; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 6b1536855..56867fbe6 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3448,7 +3448,7 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING ) { currentSpell->cancel(); - currentSpell->SetDeletable(true); + currentSpell->SetReferencedFromCurrent(false); m_target->m_currentSpells[i] = NULL; } } @@ -5600,7 +5600,7 @@ void Aura::PeriodicTick() pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size data.append(m_target->GetPackGUID()); @@ -5722,7 +5722,7 @@ void Aura::PeriodicTick() pdamage = uint32(m_target->GetHealth()); sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2ef1da977..35237613a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1876,7 +1876,8 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx) if(!spellInfo) { - sLog.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id); + sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u", + m_spellInfo->Id,effect_idx,triggered_spell_id); return; } @@ -3190,7 +3191,8 @@ void Spell::EffectSummon(uint32 i) if(!spawnCreature->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", + spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); delete spawnCreature; return; } @@ -3620,7 +3622,8 @@ void Spell::EffectSummonGuardian(uint32 i) if(!spawnCreature->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", + spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); delete spawnCreature; return; } @@ -4017,7 +4020,8 @@ void Spell::EffectSummonPet(uint32 i) if(!NewSummon->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", + NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); delete NewSummon; return; } @@ -5649,7 +5653,8 @@ void Spell::EffectSummonCritter(uint32 i) if(!critter->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", + critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); delete critter; return; } diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 5b2609f42..c8f41227d 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -270,7 +270,7 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) recv_data >> guid; - sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", guid); + sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid); if(!obj) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 6fac0888f..6b17a69e4 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1458,7 +1458,7 @@ void SpellMgr::LoadSpellChains() mSpellChains.clear(); // need for reload case mSpellChainsNext.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain"); + QueryResult *result = WorldDatabase.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain"); if(result == NULL) { barGoLink bar( 1 ); @@ -1665,7 +1665,7 @@ void SpellMgr::LoadSpellLearnSpells() { mSpellLearnSpells.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT entry, SpellID FROM spell_learn_spell"); + QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID FROM spell_learn_spell"); if(!result) { barGoLink bar( 1 ); diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 49ab6d22f..375bcc1ad 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -114,7 +114,7 @@ void MapManager::LoadTransports() sLog.outString( ">> Loaded %u transports", count ); // check transport data DB integrity - result = WorldDatabase.PQuery("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); + result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); if(result) // wrong data found { do @@ -146,7 +146,8 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, if(!IsPositionValid()) { - sLog.outError("ERROR: Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",guidlow,x,y); + sLog.outError("ERROR: Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow,x,y); return false; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index cfb0702cd..d4590628d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -235,9 +235,11 @@ Unit::~Unit() // set current spells as deletable for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) { - // spell may be safely deleted now - if (m_currentSpells[i]) m_currentSpells[i]->SetDeletable(true); - m_currentSpells[i] = NULL; + if (m_currentSpells[i]) + { + m_currentSpells[i]->SetReferencedFromCurrent(false); + m_currentSpells[i] = NULL; + } } RemoveAllGameObjects(); @@ -1663,56 +1665,60 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe RemainingDamage -= currentAbsorb; } - AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); - for(AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) + // only split damage if not damaing yourself + if(pVictim != this) { - next = i; ++next; + AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); + for(AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) + { + next = i; ++next; - // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) - continue; + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; - // Damage can be splitted only if aura has an alive caster - Unit *caster = (*i)->GetCaster(); - if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) - continue; + // Damage can be splitted only if aura has an alive caster + Unit *caster = (*i)->GetCaster(); + if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) + continue; - int32 currentAbsorb; - if (RemainingDamage >= (*i)->GetModifier()->m_amount) - currentAbsorb = (*i)->GetModifier()->m_amount; - else - currentAbsorb = RemainingDamage; + int32 currentAbsorb; + if (RemainingDamage >= (*i)->GetModifier()->m_amount) + currentAbsorb = (*i)->GetModifier()->m_amount; + else + currentAbsorb = RemainingDamage; - RemainingDamage -= currentAbsorb; + RemainingDamage -= currentAbsorb; - SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false); + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false); - CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); - } + CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + } - AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); - for(AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) - { - next = i; ++next; + AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); + for(AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) + { + next = i; ++next; - // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) - continue; + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; - // Damage can be splitted only if aura has an alive caster - Unit *caster = (*i)->GetCaster(); - if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) - continue; + // Damage can be splitted only if aura has an alive caster + Unit *caster = (*i)->GetCaster(); + if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) + continue; - int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); + int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); - RemainingDamage -= splitted; + RemainingDamage -= splitted; - SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); - CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + } } *absorb = damage - RemainingDamage - *resist; @@ -3150,7 +3156,7 @@ void Unit::_UpdateSpells( uint32 time ) { if (m_currentSpells[i] && m_currentSpells[i]->getState() == SPELL_STATE_FINISHED) { - m_currentSpells[i]->SetDeletable(true); // spell may be safely deleted now + m_currentSpells[i]->SetReferencedFromCurrent(false); m_currentSpells[i] = NULL; // remove pointer } } @@ -3263,7 +3269,6 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) uint32 CSpellType = pSpell->GetCurrentContainer(); - pSpell->SetDeletable(false); // spell will not be deleted until gone from current pointers if (pSpell == m_currentSpells[CSpellType]) return; // avoid breaking self // break same type spell if it is not delayed @@ -3320,10 +3325,11 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) // current spell (if it is still here) may be safely deleted now if (m_currentSpells[CSpellType]) - m_currentSpells[CSpellType]->SetDeletable(true); + m_currentSpells[CSpellType]->SetReferencedFromCurrent(false); // set new current spell m_currentSpells[CSpellType] = pSpell; + pSpell->SetReferencedFromCurrent(true); } void Unit::InterruptSpell(uint32 spellType, bool withDelayed) @@ -3341,7 +3347,7 @@ void Unit::InterruptSpell(uint32 spellType, bool withDelayed) if (m_currentSpells[spellType]->getState() != SPELL_STATE_FINISHED) m_currentSpells[spellType]->cancel(); - m_currentSpells[spellType]->SetDeletable(true); + m_currentSpells[spellType]->SetReferencedFromCurrent(false); m_currentSpells[spellType] = NULL; } } @@ -3377,7 +3383,7 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) if ( (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) && (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) ) m_currentSpells[CURRENT_GENERIC_SPELL]->cancel(); - m_currentSpells[CURRENT_GENERIC_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_GENERIC_SPELL]->SetReferencedFromCurrent(false); m_currentSpells[CURRENT_GENERIC_SPELL] = NULL; } @@ -3391,7 +3397,7 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) if ( (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_FINISHED) && (withDelayed || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_DELAYED) ) m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->cancel(); - m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->SetReferencedFromCurrent(false); m_currentSpells[CURRENT_AUTOREPEAT_SPELL] = NULL; } @@ -3400,7 +3406,7 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) { if (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel(); - m_currentSpells[CURRENT_CHANNELED_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_CHANNELED_SPELL]->SetReferencedFromCurrent(false); m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL; } } @@ -9839,7 +9845,7 @@ void Unit::CleanupsBeforeDelete() if(m_uint32Values) // only for fully created object { InterruptNonMeleeSpells(true); - m_Events.KillAllEvents(); + m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted ans will deleated at call in Map::RemoveAllObjectsInRemoveList CombatStop(); ClearComboPointHolders(); DeleteThreatList(); diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index f157234fa..b123fe497 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -89,8 +89,12 @@ void WaypointManager::Load() if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation)) { QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id); - if(result1) sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y); - else sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, point, node.x, node.y); + if(result1) + sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %f, Y: %f).", + id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y); + else + sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %f, Y: %f).", + id, point, node.x, node.y); MaNGOS::NormalizeMapCoord(node.x); MaNGOS::NormalizeMapCoord(node.y); diff --git a/src/game/World.cpp b/src/game/World.cpp index 8ecb18551..1e29ffc55 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -480,7 +480,8 @@ void World::LoadConfigSettings(bool reload) } else if(rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > ATTACK_DISTANCE) { - sLog.outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.",rate_values[RATE_TARGET_POS_RECALCULATION_RANGE],ATTACK_DISTANCE,ATTACK_DISTANCE); + sLog.outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.", + rate_values[RATE_TARGET_POS_RECALCULATION_RANGE],ATTACK_DISTANCE,ATTACK_DISTANCE); rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = ATTACK_DISTANCE; } @@ -1159,7 +1160,8 @@ void World::SetInitialWorldSettings() sprintf( isoDate, "%04d-%02d-%02d %02d:%02d:%02d", local.tm_year+1900, local.tm_mon+1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); - WorldDatabase.PExecute("INSERT INTO uptime (startstring, starttime, uptime) VALUES('%s', %ld, 0)", isoDate, m_startTime ); + WorldDatabase.PExecute("INSERT INTO uptime (startstring, starttime, uptime) VALUES('%s', " I64FMTD ", 0)", + isoDate, uint64(m_startTime)); m_timers[WUPDATE_OBJECTS].SetInterval(0); m_timers[WUPDATE_SESSIONS].SetInterval(0); diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 3ce98cc52..b79b13dd3 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -373,7 +373,7 @@ void WorldSession::LogoutPlayer(bool Save) _player->GetGroup()->SendUpdate(); ///- Broadcast a logout message to the player's friends - sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), "", true); + sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); ///- Delete the player object _player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index e63f87b58..949af8703 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -294,8 +294,10 @@ class MANGOS_DLL_SPEC WorldSession void HandleEmoteOpcode(WorldPacket& recvPacket); void HandleFriendListOpcode(WorldPacket& recvPacket); void HandleAddFriendOpcode(WorldPacket& recvPacket); + static void HandleAddFriendOpcodeCallBack(QueryResult *result, uint32 accountId, std::string friendNote); void HandleDelFriendOpcode(WorldPacket& recvPacket); void HandleAddIgnoreOpcode(WorldPacket& recvPacket); + static void HandleAddIgnoreOpcodeCallBack(QueryResult *result, uint32 accountId); void HandleDelIgnoreOpcode(WorldPacket& recvPacket); void HandleSetFriendNoteOpcode(WorldPacket& recvPacket); void HandleBugOpcode(WorldPacket& recvPacket); diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index fdec33473..7751c7a9e 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -59,14 +59,22 @@ class MANGOS_DLL_SPEC Database bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql); template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); + template + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); template bool AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); + template + bool AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); template bool AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); template bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder); template diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index cc8842018..d3eae749a 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -45,6 +45,18 @@ Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamTyp return true; } +template +bool +Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) +{ + if (!sql) return false; + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); + QueryQueues::iterator itr = m_queryQueues.find(queryThread); + if (itr == m_queryQueues.end()) return false; + m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2), itr->second)); + return true; +} + template bool Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql) @@ -57,6 +69,18 @@ Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1 return true; } +template +bool +Database::AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) +{ + if (!sql) return false; + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); + QueryQueues::iterator itr = m_queryQueues.find(queryThread); + if (itr == m_queryQueues.end()) return false; + m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2), itr->second)); + return true; +} + template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) @@ -99,6 +123,27 @@ Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamTy return AsyncQuery(object, method, param1, szQuery); } +template +bool +Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) +{ + if(!format) return false; + + va_list ap; + char szQuery [MAX_QUERY_LEN]; + va_start(ap, format); + int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); + va_end(ap); + + if(res==-1) + { + sLog.outError("SQL Query truncated (and not execute) for format: %s",format); + return false; + } + + return AsyncQuery(object, method, param1, param2, szQuery); +} + template bool Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) @@ -120,6 +165,27 @@ Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param return AsyncQuery(method, param1, szQuery); } +template +bool +Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) +{ + if(!format) return false; + + va_list ap; + char szQuery [MAX_QUERY_LEN]; + va_start(ap, format); + int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); + va_end(ap); + + if(res==-1) + { + sLog.outError("SQL Query truncated (and not execute) for format: %s",format); + return false; + } + + return AsyncQuery(method, param1, param2, szQuery); +} + template bool Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder)