Merged commit 269 (5f0e38da128a).

--HG--
branch : trunk
This commit is contained in:
gvcoman
2008-11-21 14:34:05 -05:00
403 changed files with 4898 additions and 3946 deletions
+6 -6
View File
@@ -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 "WorldPacket.h"
@@ -89,8 +89,8 @@ bool WorldSession::SendAuctionInfo(WorldPacket & data, AuctionEntry* auction)
sLog.outError("auction to item, that doesn't exist !!!!");
return false;
}
data << auction->Id;
data << pItem->GetUInt32Value(OBJECT_FIELD_ENTRY);
data << (uint32) auction->Id;
data << (uint32) pItem->GetEntry();
for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; i++)
{
@@ -245,7 +245,7 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
return;
}
// prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to auction)
// prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction)
if(!it)
{
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND);
@@ -716,7 +716,7 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
ItemLocale const *il = objmgr.GetItemLocale(proto->ItemId);
if (il)
{
if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty())
if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
name = il->Name[loc_idx];
}
}
+7 -6
View File
@@ -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"
@@ -41,7 +41,7 @@ Bag::~Bag()
{
for(int i = 0; i < MAX_BAG_SIZE; ++i)
if (m_bagslot[i])
delete m_bagslot[i];
delete m_bagslot[i];
}
void Bag::AddToWorld()
@@ -71,7 +71,7 @@ bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner)
Object::_Create( guidlow, 0, HIGHGUID_CONTAINER );
SetUInt32Value(OBJECT_FIELD_ENTRY, itemid);
SetEntry(itemid);
SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0);
@@ -85,7 +85,7 @@ bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner)
// Setting the number of Slots the Container has
SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->ContainerSlots);
// Cleanning 20 slots
// Cleaning 20 slots
for (uint8 i = 0; i < MAX_BAG_SIZE; i++)
{
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0);
@@ -213,6 +213,7 @@ uint8 Bag::GetSlotByItemGUID(uint64 guid) const
if(m_bagslot[i] != 0)
if(m_bagslot[i]->GetGUID() == guid)
return i;
return NULL_SLOT;
}
@@ -220,6 +221,6 @@ Item* Bag::GetItemByPos( uint8 slot ) const
{
if( slot < GetBagSize() )
return m_bagslot[slot];
return NULL;
}
+4 -4
View File
@@ -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
+35 -31
View File
@@ -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"
@@ -64,7 +64,7 @@ bool LoginQueryHolder::Initialize()
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,slot,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid));
@@ -180,6 +180,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
std::string name;
uint8 race_,class_;
recv_data >> name;
// recheck with known string size
@@ -214,6 +215,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_);
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_);
if( !classEntry || !raceEntry )
{
data << (uint8)CHAR_CREATE_FAILED;
@@ -607,7 +609,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
pCurrChar->SetRank(0);
}
if (!MapManager::Instance().GetMap(pCurrChar->GetMapId(), pCurrChar)->Add(pCurrChar))
if (!pCurrChar->GetMap()->Add(pCurrChar))
{
AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId());
if(at)
@@ -999,35 +1001,35 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data)
{
uint64 guid;
CHECK_PACKET_SIZE(recv_data, 8+6);
CHECK_PACKET_SIZE(recv_data, 8);
recv_data >> guid;
// not accept declined names for unsupported languages
std::string name;
if(!objmgr.GetPlayerNameByGUID(guid,name))
if(!objmgr.GetPlayerNameByGUID(guid, name))
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)1;
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
data << uint64(guid);
SendPacket(&data);
return;
}
std::wstring wname;
if(!Utf8toWStr(name,wname))
if(!Utf8toWStr(name, wname))
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)1;
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
data << uint64(guid);
SendPacket(&data);
return;
}
if(!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)1;
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1035,35 +1037,37 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data)
std::string name2;
DeclinedName declinedname;
CHECK_PACKET_SIZE(recv_data, recv_data.rpos() + 1);
recv_data >> name2;
if(name2!=name) // character have different name
if(name2 != name) // character have different name
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)1;
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
data << uint64(guid);
SendPacket(&data);
return;
}
for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
{
CHECK_PACKET_SIZE(recv_data, recv_data.rpos() + 1);
recv_data >> declinedname.name[i];
if(!normalizePlayerName(declinedname.name[i]))
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)1;
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
data << uint64(guid);
SendPacket(&data);
return;
}
}
if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname))
if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname))
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)1;
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1074,11 +1078,11 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data)
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid));
CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')",
GUID_LOPART(guid), declinedname.name[0].c_str(),declinedname.name[1].c_str(),declinedname.name[2].c_str(),declinedname.name[3].c_str(),declinedname.name[4].c_str());
GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str());
CharacterDatabase.CommitTransaction();
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT,4+8);
data << (uint32)0; // OK
data << guid;
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(0); // OK
data << uint64(guid);
SendPacket(&data);
}
+32 -4
View File
@@ -63,16 +63,44 @@ ChatCommand * ChatHandler::getCommandTable()
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand serverIdleRestartCommandTable[] =
{
{ "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
{ "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleRestartCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand serverIdleShutdownCommandTable[] =
{
{ "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
{ "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleShutDownCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand serverRestartCommandTable[] =
{
{ "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
{ "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerRestartCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand serverShutdownCommandTable[] =
{
{ "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
{ "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand serverCommandTable[] =
{
{ "corpses", SEC_GAMEMASTER, true, &ChatHandler::HandleServerCorpsesCommand, "", NULL },
{ "exit", SEC_CONSOLE, true, &ChatHandler::HandleServerExitCommand, "", NULL },
{ "idlerestart", SEC_ADMINISTRATOR, true, &ChatHandler::HandleIdleRestartCommand, "", NULL },
{ "idleshutdown", SEC_ADMINISTRATOR, true, &ChatHandler::HandleIdleShutDownCommand, "", NULL },
{ "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable },
{ "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable },
{ "info", SEC_PLAYER, true, &ChatHandler::HandleServerInfoCommand, "", NULL },
{ "motd", SEC_PLAYER, true, &ChatHandler::HandleServerMotdCommand, "", NULL },
{ "restart", SEC_ADMINISTRATOR, true, &ChatHandler::HandleRestartCommand, "", NULL },
{ "shutdown", SEC_ADMINISTRATOR, true, &ChatHandler::HandleShutDownCommand, "", NULL },
{ "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable },
{ "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable },
{ "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable },
{ NULL, 0, false, NULL, "", NULL }
};
+8 -6
View File
@@ -175,6 +175,7 @@ class ChatHandler
bool HandleModifyHonorCommand (const char* args);
bool HandleModifyRepCommand(const char* args);
bool HandleModifyArenaCommand(const char* args);
bool HandleModifyGenderCommand(const char* args);
bool HandleNpcAddCommand(const char* args);
bool HandleNpcAddMoveCommand(const char* args);
@@ -191,6 +192,7 @@ class ChatHandler
bool HandleNpcSetMoveTypeCommand(const char* args);
bool HandleNpcSpawnDistCommand(const char* args);
bool HandleNpcSpawnTimeCommand(const char* args);
bool HandleNpcTameCommand(const char* args);
bool HandleNpcTextEmoteCommand(const char* args);
bool HandleNpcUnFollowCommand(const char* args);
bool HandleNpcWhisperCommand(const char* args);
@@ -215,6 +217,7 @@ class ChatHandler
bool HandleReloadCommandCommand(const char* args);
bool HandleReloadCreatureQuestRelationsCommand(const char* args);
bool HandleReloadCreatureQuestInvRelationsCommand(const char* args);
bool HandleReloadDbScriptStringCommand(const char* args);
bool HandleReloadGameGraveyardZoneCommand(const char* args);
bool HandleReloadGameObjectScriptsCommand(const char* args);
bool HandleReloadGameTeleCommand(const char* args);
@@ -270,10 +273,15 @@ class ChatHandler
bool HandleServerCorpsesCommand(const char* args);
bool HandleServerExitCommand(const char* args);
bool HandleServerIdleRestartCommand(const char* args);
bool HandleServerIdleShutDownCommand(const char* args);
bool HandleServerInfoCommand(const char* args);
bool HandleServerMotdCommand(const char* args);
bool HandleServerRestartCommand(const char* args);
bool HandleServerSetMotdCommand(const char* args);
bool HandleServerSetLogLevelCommand(const char* args);
bool HandleServerShutDownCommand(const char* args);
bool HandleServerShutDownCancelCommand(const char* args);
bool HandleAddHonorCommand(const char* args);
bool HandleHonorAddKillCommand(const char* args);
@@ -327,11 +335,6 @@ class ChatHandler
bool HandleBanListAccountCommand(const char* args);
bool HandleBanListCharacterCommand(const char* args);
bool HandleBanListIPCommand(const char* args);
bool HandleIdleRestartCommand(const char* args);
bool HandleIdleShutDownCommand(const char* args);
bool HandleShutDownCommand(const char* args);
bool HandleRestartCommand(const char* args);
bool HandleSecurityCommand(const char* args);
bool HandleGoXYCommand(const char* args);
bool HandleGoXYZCommand(const char* args);
bool HandleGoZoneXYCommand(const char* args);
@@ -365,7 +368,6 @@ class ChatHandler
bool HandleHideAreaCommand(const char* args);
bool HandleAddItemCommand(const char* args);
bool HandleAddItemSetCommand(const char* args);
bool HandleModifyGenderCommand(const char* args);
bool HandlePetTpCommand(const char* args);
bool HandlePetUnlearnCommand(const char* args);
bool HandlePetLearnCommand(const char* args);
+58 -11
View File
@@ -122,7 +122,7 @@ Unit(), i_AI(NULL), i_AI_possessed(NULL),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false),
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_isAggressive(true),
m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0)
@@ -181,7 +181,7 @@ void Creature::RemoveCorpse()
float x,y,z,o;
GetRespawnCoord(x, y, z, &o);
MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation(this,x,y,z,o);
GetMap()->CreatureRelocation(this,x,y,z,o);
}
/**
@@ -213,7 +213,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data )
}
}
SetUInt32Value(OBJECT_FIELD_ENTRY, Entry); // normal entry always
SetEntry(Entry); // normal entry always
m_creatureInfo = cinfo; // map mode related always
// Cancel load if no model defined
@@ -297,6 +297,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
SetUInt32Value(UNIT_FIELD_FLAGS,GetCreatureInfo()->unit_flags);
SetUInt32Value(UNIT_DYNAMIC_FLAGS,GetCreatureInfo()->dynamicflags);
SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool));
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->armor));
SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(GetCreatureInfo()->resistance1));
SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(GetCreatureInfo()->resistance2));
@@ -327,6 +328,12 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
if(isTotem() || isCivilian() || GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER
|| GetCreatureType() == CREATURE_TYPE_CRITTER)
m_isAggressive = false;
else
m_isAggressive = true;
return true;
}
@@ -356,7 +363,7 @@ void Creature::Update(uint32 diff)
lootForPickPocketed = false;
lootForBody = false;
if(m_originalEntry != GetUInt32Value(OBJECT_FIELD_ENTRY))
if(m_originalEntry != GetEntry())
UpdateEntry(m_originalEntry);
CreatureInfo const *cinfo = GetCreatureInfo();
@@ -375,9 +382,9 @@ void Creature::Update(uint32 diff)
setDeathState( JUST_ALIVED );
//Call AI respawn virtual function
AI()->JustRespawned();
i_AI->JustRespawned();
MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
GetMap()->Add(this);
}
break;
}
@@ -439,7 +446,7 @@ void Creature::Update(uint32 diff)
{
// do not allow the AI to be changed during update
m_AI_locked = true;
AI()->UpdateAI(diff);
i_AI->UpdateAI(diff);
m_AI_locked = false;
}
@@ -1411,8 +1418,6 @@ bool Creature::LoadFromDB(uint32 guid, Map *map)
SetHealth(m_deathState == ALIVE ? curhealth : 0);
SetPower(POWER_MANA,data->curmana);
SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool));
// checked at creature_template loading
m_defaultMovementType = MovementGeneratorType(data->movementType);
@@ -1539,6 +1544,19 @@ bool Creature::IsWithinSightDist(Unit const* u) const
return IsWithinDistInMap(u, sWorld.getConfig(CONFIG_SIGHT_MONSTER));
}
bool Creature::canStartAttack(Unit const* who) const
{
if(!who->isInAccessiblePlaceFor(this)
|| !canFly() && GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE
|| !IsWithinDistInMap(who, GetAttackDistance(who)))
return false;
if(!canAttack(who))
return false;
return IsWithinLOSInMap(who);
}
float Creature::GetAttackDistance(Unit const* pl) const
{
float aggroRate = sWorld.getRate(RATE_CREATURE_AGGRO);
@@ -1818,6 +1836,30 @@ void Creature::DoFleeToGetAssistance(float radius) // Optional parameter
}
}
Unit* Creature::SelectNearestTarget(float dist) const
{
CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
Unit *target = NULL;
{
Trinity::NearestHostileUnitInAttackDistanceCheck u_check(this, dist);
Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(target, u_check);
TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
}
return target;
}
void Creature::CallAssistence()
{
if( !m_AlreadyCallAssistence && getVictim() && !isPet() && !isCharmed())
@@ -2097,9 +2139,14 @@ uint32 Creature::getLevelForTarget( Unit const* target ) const
return level;
}
char const* Creature::GetScriptName() const
std::string Creature::GetScriptName()
{
return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptName;
return objmgr.GetScriptName(GetScriptId());
}
uint32 Creature::GetScriptId()
{
return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptID;
}
VendorItemData const* Creature::GetVendorItems() const
+15 -7
View File
@@ -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 TRINITYCORE_CREATURE_H
@@ -205,10 +205,11 @@ struct CreatureInfo
uint32 equipmentId;
uint32 MechanicImmuneMask;
uint32 flags_extra;
char const* ScriptName;
uint32 ScriptID;
uint32 GetRandomValidModelId() const;
uint32 GetFirstValidModelId() const;
// helpers
SkillType GetRequiredLootSkill() const
{
if(type_flags & CREATURE_TYPEFLAGS_HERBLOOT)
@@ -218,7 +219,7 @@ struct CreatureInfo
else
return SKILL_SKINNING; // normal case
}
bool isTameable() const
{
return type == CREATURE_TYPE_BEAST && family != 0 && (type_flags & CREATURE_TYPEFLAGS_TAMEBLE);
@@ -425,6 +426,8 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool canWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; }
bool canSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
bool canFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; }
bool isAggressive() const { return m_isAggressive; }
void SetAggressive(bool agg) { m_isAggressive = agg; }
///// TODO RENAME THIS!!!!!
bool isCanTrainingOf(Player* player, bool msg) const;
bool isCanIneractWithBattleMaster(Player* player, bool msg) const;
@@ -498,7 +501,9 @@ class TRINITY_DLL_SPEC Creature : public Unit
CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; }
CreatureDataAddon const* GetCreatureAddon() const;
char const* GetScriptName() const;
std::string GetScriptName();
uint32 GetScriptId();
void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 );
void sendPreparedGossip( Player* player );
@@ -524,7 +529,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
// overwrite WorldObject function for proper name localization
const char* GetNameForLocaleIdx(int32 locale_idx) const;
void setDeathState(DeathState s); // overwrite virtual Unit::setDeathState
bool LoadFromDB(uint32 guid, Map *map);
@@ -552,8 +557,10 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
bool IsWithinSightDist(Unit const* u) const;
bool canStartAttack(Unit const* u) const;
float GetAttackDistance(Unit const* pl) const;
Unit* SelectNearestTarget(float dist = 0) const;
void CallAssistence();
void SetNoCallAssistence(bool val) { m_AlreadyCallAssistence = val; }
void DoFleeToGetAssistance(float radius = 50);
@@ -633,6 +640,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
uint8 m_emoteState;
bool m_isPet; // set only in Pet::Pet
bool m_isTotem; // set only in Totem::Totem
bool m_isAggressive;
void RegenerateMana();
void RegenerateHealth();
uint32 m_regenTimer;
+2 -2
View File
@@ -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 "CreatureAI.h"
+2 -2
View File
@@ -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 CREATUREAIIMPL_H
#define CREATUREAIIMPL_H
+2 -2
View File
@@ -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 "CreatureAIRegistry.h"
+2 -2
View File
@@ -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 "Creature.h"
+4 -3
View File
@@ -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_FORMULAS_H
@@ -29,7 +29,7 @@ namespace Trinity
{
inline uint32 hk_honor_at_level(uint32 level, uint32 count=1)
{
return (uint32) ceil(count*(-0.53177f + 0.59357f * exp((level +23.54042f) / 26.07859f )));
return (uint32)ceil(count*(-0.53177f + 0.59357f * exp((level +23.54042f) / 26.07859f )));
}
}
namespace XP
@@ -80,6 +80,7 @@ namespace Trinity
inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content)
{
//TODO: need modifier for CONTENT_71_80 different from CONTENT_61_70?
const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235;
if( mob_level >= pl_level )
{
+3 -7
View File
@@ -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"
@@ -66,8 +66,6 @@ void WorldSession::HandleGMTicketUpdateTextOpcode( WorldPacket & recv_data )
std::string ticketText;
recv_data >> ticketText;
CharacterDatabase.escape_string(ticketText);
if(GMTicket* ticket = ticketmgr.GetGMTicket(GetPlayer()->GetGUIDLow()))
ticket->SetText(ticketText.c_str());
else
@@ -105,9 +103,7 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s, unk1 %u, unk2 %u", map, x, y, z, ticketText.c_str(), unk1, unk2);
CharacterDatabase.escape_string(ticketText);
if(GMTicket* ticket = ticketmgr.GetGMTicket(GetPlayer()->GetGUIDLow()))
if(ticketmgr.GetGMTicket(GetPlayer()->GetGUIDLow()))
{
WorldPacket data( SMSG_GMTICKET_CREATE, 4 );
data << uint32(1);
+10 -3
View File
@@ -50,7 +50,10 @@ class GMTicket
{
m_text = text ? text : "";
m_lastUpdate = time(NULL);
CharacterDatabase.PExecute("UPDATE character_ticket SET ticket_text = '%s' WHERE guid = '%u'", m_text.c_str(), m_guid);
std::string escapedString = m_text;
CharacterDatabase.escape_string(escapedString);
CharacterDatabase.PExecute("UPDATE character_ticket SET ticket_text = '%s' WHERE guid = '%u'", escapedString.c_str(), m_guid);
}
void DeleteFromDB() const
@@ -62,7 +65,11 @@ class GMTicket
{
CharacterDatabase.BeginTransaction();
DeleteFromDB();
CharacterDatabase.PExecute("INSERT INTO character_ticket (guid, ticket_text) VALUES ('%u', '%s')", m_guid, GetText());
std::string escapedString = m_text;
CharacterDatabase.escape_string(escapedString);
CharacterDatabase.PExecute("INSERT INTO character_ticket (guid, ticket_text) VALUES ('%u', '%s')", m_guid, escapedString.c_str());
CharacterDatabase.CommitTransaction();
}
private:
@@ -115,4 +122,4 @@ class GMTicketMgr
};
#define ticketmgr Trinity::Singleton<GMTicketMgr>::Instance()
#endif
#endif
+1 -1
View File
@@ -1503,7 +1503,7 @@ void GameEvent::SaveWorldEventStateToDB(uint16 event_id)
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM game_event_save WHERE event_id = '%u'",event_id);
if(mGameEvent[event_id].nextstart)
CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u',FROM_UNIXTIME("I64FMTD"))",event_id,mGameEvent[event_id].state,mGameEvent[event_id].nextstart);
CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u',FROM_UNIXTIME("I64FMTD"))",event_id,mGameEvent[event_id].state,(uint64)(mGameEvent[event_id].nextstart));
else
CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u','0000-00-00 00:00:00')",event_id,mGameEvent[event_id].state);
CharacterDatabase.CommitTransaction();
+1 -1
View File
@@ -1280,7 +1280,7 @@ void GameObject::CastSpell(Unit* target, uint32 spell)
else
{
trigger->setFaction(14);
trigger->CastSpell(target, spell, true);
trigger->CastSpell(target, spell, true, 0, 0, target->GetGUID());
}
//trigger->setDeathState(JUST_DIED);
//trigger->RemoveCorpse();
+3 -3
View File
@@ -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 TRINITYCORE_GAMEOBJECT_H
@@ -357,7 +357,7 @@ struct GameObjectInfo
uint32 data[24];
} raw;
};
char *ScriptName;
uint32 ScriptId;
};
struct GameObjectLocale
+29 -8
View File
@@ -698,19 +698,40 @@ namespace Trinity
// Creature checks
class InAttackDistanceFromAnyHostileCreatureCheck
class NearestHostileUnitInAttackDistanceCheck
{
public:
explicit InAttackDistanceFromAnyHostileCreatureCheck(Unit* funit) : i_funit(funit) {}
bool operator()(Creature* u)
explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : m_creature(creature)
{
if(u->isAlive() && u->IsHostileTo(i_funit) && i_funit->IsWithinDistInMap(u, u->GetAttackDistance(i_funit)))
return true;
return false;
m_range = (dist == 0 ? 9999 : dist);
m_force = (dist == 0 ? false : true);
}
bool operator()(Unit* u)
{
// TODO: addthreat for every enemy in range?
if(!m_creature->IsWithinDistInMap(u, m_range))
return false;
if(m_force)
{
if(!m_creature->canAttack(u))
return false;
}
else
{
if(!m_creature->canStartAttack(u))
return false;
}
m_range = m_creature->GetDistance(u);
return true;
}
float GetLastRange() const { return m_range; }
private:
Unit* const i_funit;
Creature const *m_creature;
float m_range;
bool m_force;
NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&);
};
class NearestAssistCreatureInCreatureRangeCheck
+3 -3
View File
@@ -72,7 +72,7 @@ inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c)
pl->UpdateVisibilityOf(c);
// Creature AI reaction
if(!c->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
if(c->isAggressive() && !c->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
{
if( c->AI() && c->IsWithinSightDist(pl) /*c->AI()->IsVisible(pl)*/ && !c->IsInEvadeMode() )
c->AI()->MoveInLineOfSight(pl);
@@ -81,13 +81,13 @@ inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c)
inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2)
{
if(!c1->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
if(c1->isAggressive() && !c1->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
{
if( c1->AI() && c1->IsWithinSightDist(c2) /*c1->AI()->IsVisible(c2)*/ && !c1->IsInEvadeMode() )
c1->AI()->MoveInLineOfSight(c2);
}
if(!c2->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
if(c2->isAggressive() && !c2->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
{
if( c2->AI() && c1->IsWithinSightDist(c2) /*c2->AI()->IsVisible(c1)*/ && !c2->IsInEvadeMode() )
c2->AI()->MoveInLineOfSight(c1);
+13 -12
View File
@@ -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"
@@ -179,7 +179,7 @@ bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProt
case ITEM_SUBCLASS_CONTAINER:
return true;
case ITEM_SUBCLASS_SOUL_CONTAINER:
if(!(pProto->BagFamily & BAG_FAMILY_MASK_SHARDS))
if(!(pProto->BagFamily & BAG_FAMILY_MASK_SOUL_SHARDS))
return false;
return true;
case ITEM_SUBCLASS_HERB_CONTAINER:
@@ -247,7 +247,7 @@ bool Item::Create( uint32 guidlow, uint32 itemid, Player const* owner)
{
Object::_Create( guidlow, 0, HIGHGUID_ITEM );
SetUInt32Value(OBJECT_FIELD_ENTRY, itemid);
SetEntry(itemid);
SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0);
@@ -429,7 +429,7 @@ void Item::DeleteFromInventoryDB()
ItemPrototype const *Item::GetProto() const
{
return objmgr.GetItemPrototype(GetUInt32Value(OBJECT_FIELD_ENTRY));
return objmgr.GetItemPrototype(GetEntry());
}
Player* Item::GetOwner()const
@@ -762,9 +762,7 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges)
{
// Better lost small time at check in comparison lost time at item save to DB.
if( GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET)==id &&
GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET)==duration &&
GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET)==charges )
if((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
return;
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
@@ -775,7 +773,7 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint
void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
{
if(GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET)==duration)
if(GetEnchantmentDuration(slot) == duration)
return;
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
@@ -784,17 +782,20 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
{
if(GetEnchantmentCharges(slot) == charges)
return;
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
SetState(ITEM_CHANGED);
}
void Item::ClearEnchantment(EnchantmentSlot slot)
{
if(!GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET))
if(!GetEnchantmentId(slot))
return;
for(int x=0;x<3;x++)
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x,0);
for(uint8 x = 0; x < 3; ++x)
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
SetState(ITEM_CHANGED);
}
+2 -3
View File
@@ -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 TRINITYCORE_ITEM_H
@@ -228,7 +228,6 @@ class TRINITY_DLL_SPEC Item : public Object
bool IsLimitedToAnotherMapOrZone( uint32 cur_mapId, uint32 cur_zoneId) const;
bool GemsFitSockets() const;
uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
uint32 GetCount() const { return GetUInt32Value (ITEM_FIELD_STACK_COUNT); }
void SetCount(uint32 value) { SetUInt32Value (ITEM_FIELD_STACK_COUNT, value); }
uint32 GetMaxStackCount() const { return GetProto()->Stackable; }
+2 -2
View File
@@ -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 <stdlib.h>
+2 -2
View File
@@ -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 _ITEM_ENCHANTMENT_MGR_H
+17 -14
View File
@@ -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"
@@ -313,9 +313,9 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
if (il)
{
if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty())
if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
Name = il->Name[loc_idx];
if (il->Description.size() > loc_idx && !il->Description[loc_idx].empty())
if (il->Description.size() > size_t(loc_idx) && !il->Description[loc_idx].empty())
Description = il->Description[loc_idx];
}
}
@@ -360,6 +360,8 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->Damage[i].DamageMax;
data << pProto->Damage[i].DamageType;
}
// resistances (7)
data << pProto->Armor;
data << pProto->HolyRes;
data << pProto->FireRes;
@@ -367,10 +369,11 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->FrostRes;
data << pProto->ShadowRes;
data << pProto->ArcaneRes;
data << pProto->Delay;
data << pProto->Ammo_type;
data << pProto->RangedModRange;
data << (float)pProto->RangedModRange;
for(int s = 0; s < 5; s++)
{
// send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
@@ -976,7 +979,7 @@ void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data)
ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
if (il)
{
if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty())
if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
Name = il->Name[loc_idx];
}
}
@@ -1027,7 +1030,7 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data)
return;
}
if(item==gift) // not possible with pacjket from real client
if(item==gift) // not possable with pacjket from real client
{
_player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
return;
@@ -1072,16 +1075,16 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data)
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS));
item->SetUInt32Value(OBJECT_FIELD_ENTRY, gift->GetUInt32Value(OBJECT_FIELD_ENTRY));
item->SetEntry(gift->GetEntry());
switch (item->GetEntry())
{
case 5042: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 5043); break;
case 5048: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 5044); break;
case 17303: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17302); break;
case 17304: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17305); break;
case 17307: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17308); break;
case 21830: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 21831); break;
case 5042: item->SetEntry( 5043); break;
case 5048: item->SetEntry( 5044); break;
case 17303: item->SetEntry(17302); break;
case 17304: item->SetEntry(17305); break;
case 17307: item->SetEntry(17308); break;
case 21830: item->SetEntry(21831); break;
}
item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
+29 -13
View File
@@ -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 _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
@@ -99,16 +99,18 @@ enum ITEM_FLAGS
ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000,
ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000,
ITEM_FLAGS_THROWABLE = 0x00400000, // not used in game for check trow possibility, only for item in game tooltip
ITEM_FLAGS_SPECIALUSE = 0x00800000 // last used flag in 2.3.0
ITEM_FLAGS_SPECIALUSE = 0x00800000, // last used flag in 2.3.0
ITEM_FLAGS_BOA = 0x08000000, // bind on account
ITEM_FLAGS_MILLABLE = 0x20000000
};
enum BAG_FAMILY_MASK
{
BAG_FAMILY_MASK_ARROWS = 0x00000001,
BAG_FAMILY_MASK_BULLETS = 0x00000002,
BAG_FAMILY_MASK_SHARDS = 0x00000004,
BAG_FAMILY_MASK_SOUL_SHARDS = 0x00000004,
BAG_FAMILY_MASK_LEATHERWORKING_SUPP = 0x00000008,
BAG_FAMILY_MASK_UNUSED = 0x00000010, // not used currently
BAG_FAMILY_MASK_INSCRIPTION_SUPP = 0x00000010,
BAG_FAMILY_MASK_HERBS = 0x00000020,
BAG_FAMILY_MASK_ENCHANTING_SUPP = 0x00000040,
BAG_FAMILY_MASK_ENGINEERING_SUPP = 0x00000080,
@@ -116,13 +118,11 @@ enum BAG_FAMILY_MASK
BAG_FAMILY_MASK_GEMS = 0x00000200,
BAG_FAMILY_MASK_MINING_SUPP = 0x00000400,
BAG_FAMILY_MASK_SOULBOUND_EQUIPMENT = 0x00000800,
BAG_FAMILY_MASK_VANITY_PETS = 0x00001000
BAG_FAMILY_MASK_VANITY_PETS = 0x00001000,
BAG_FAMILY_MASK_CURRENCY_TOKENS = 0x00002000,
BAG_FAMILY_MASK_QUEST_ITEMS = 0x00004000
};
/* TODO: Not entirely positive on need for this??
enum SOCKET_CONTENT ();
*/
enum SocketColor
{
SOCKET_COLOR_META = 1,
@@ -275,7 +275,7 @@ enum ItemSubclassArmor
ITEM_SUBCLASS_ARMOR_TOTEM = 9
};
#define MAX_ITEM_SUBCLASS_ARMOR 10
#define MAX_ITEM_SUBCLASS_ARMOR 10
enum ItemSubclassReagent
{
@@ -390,6 +390,22 @@ enum ItemSubclassJunk
#define MAX_ITEM_SUBCLASS_JUNK 6
enum ItemSubclassGlyph
{
ITEM_SUBCLASS_GLYPH_WARRIOR = 1,
ITEM_SUBCLASS_GLYPH_PALADIN = 2,
ITEM_SUBCLASS_GLYPH_HUNTER = 3,
ITEM_SUBCLASS_GLYPH_ROGUE = 4,
ITEM_SUBCLASS_GLYPH_PRIEST = 5,
ITEM_SUBCLASS_GLYPH_DEATH_KNIGHT = 6,
ITEM_SUBCLASS_GLYPH_SHAMAN = 7,
ITEM_SUBCLASS_GLYPH_MAGE = 8,
ITEM_SUBCLASS_GLYPH_WARLOCK = 9,
ITEM_SUBCLASS_GLYPH_DRUID = 11
};
#define MAX_ITEM_SUBCLASS_GLYPH 12
const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] =
{
MAX_ITEM_SUBCLASS_CONSUMABLE,
@@ -524,7 +540,7 @@ struct ItemPrototype
uint32 GemProperties; // id from GemProperties.dbc
uint32 RequiredDisenchantSkill;
float ArmorDamageModifier;
char* ScriptName;
uint32 ScriptId;
uint32 DisenchantID;
uint32 FoodType;
uint32 MinMoneyLoot;
+24 -72
View File
@@ -2361,8 +2361,8 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
std::string show = show_str;
// Check
// Remember: "show" must also be the name of a column!
if( (show != "emote") && (show != "spell") && (show != "text1") && (show != "text2")
&& (show != "text3") && (show != "text4") && (show != "text5")
if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
&& (show != "textid3") && (show != "textid4") && (show != "textid5")
&& (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
&& (show != "model1") && (show != "model2") && (show != "orientation"))
{
@@ -2705,6 +2705,13 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
return false;
}
// set in game textids not supported
if( show == "textid1" || show == "textid2" || show == "textid3" ||
show == "textid4" || show == "textid5" )
{
return false;
}
WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
@@ -2842,7 +2849,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
//pCreature->GetPositionX();
QueryResult *result =
WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u",
WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
target->GetGUIDLow() );
if(!result)
{
@@ -2854,7 +2861,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
const char* maxDIFF = "0.01";
PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
if(!result)
{
@@ -2871,11 +2878,9 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
int waittime = fields[2].GetUInt32();
uint32 emote = fields[3].GetUInt32();
uint32 spell = fields[4].GetUInt32();
const char * text1 = fields[5].GetString();
const char * text2 = fields[6].GetString();
const char * text3 = fields[7].GetString();
const char * text4 = fields[8].GetString();
const char * text5 = fields[9].GetString();
uint32 textid[MAX_WAYPOINT_TEXT];
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
textid[i] = fields[5+i].GetUInt32();
uint32 model1 = fields[10].GetUInt32();
uint32 model2 = fields[11].GetUInt32();
@@ -2888,11 +2893,8 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1);
PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2);
PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3);
PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4);
PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5);
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetTrinityString(textid[i]) : ""));
}while( result->NextRow() );
// Cleanup memory
@@ -3213,8 +3215,8 @@ bool ChatHandler::HandleWpExportCommand(const char *args)
PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
QueryResult *result = WorldDatabase.PQuery(
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
"SELECT point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid );
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
"SELECT point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid );
if (!result)
{
@@ -3231,7 +3233,7 @@ bool ChatHandler::HandleWpExportCommand(const char *args)
Field *fields = result->Fetch();
outfile << "INSERT INTO creature_movement ";
outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5 ) VALUES ";
outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
outfile << "( ";
outfile << fields[15].GetUInt32(); // id
@@ -3256,65 +3258,15 @@ bool ChatHandler::HandleWpExportCommand(const char *args)
outfile << ", ";
outfile << fields[9].GetUInt32(); // spell
outfile << ", ";
const char *tmpChar = fields[10].GetString();
if( !tmpChar )
{
outfile << "NULL"; // text1
}
else
{
outfile << "'";
outfile << tmpChar; // text1
outfile << "'";
}
outfile << fields[10].GetUInt32(); // textid1
outfile << ", ";
tmpChar = fields[11].GetString();
if( !tmpChar )
{
outfile << "NULL"; // text2
}
else
{
outfile << "'";
outfile << tmpChar; // text2
outfile << "'";
}
outfile << fields[11].GetUInt32(); // textid2
outfile << ", ";
tmpChar = fields[12].GetString();
if( !tmpChar )
{
outfile << "NULL"; // text3
}
else
{
outfile << "'";
outfile << tmpChar; // text3
outfile << "'";
}
outfile << fields[12].GetUInt32(); // textid3
outfile << ", ";
tmpChar = fields[13].GetString();
if( !tmpChar )
{
outfile << "NULL"; // text4
}
else
{
outfile << "'";
outfile << tmpChar; // text4
outfile << "'";
}
outfile << fields[13].GetUInt32(); // textid4
outfile << ", ";
tmpChar = fields[14].GetString();
if( !tmpChar )
{
outfile << "NULL"; // text5
}
else
{
outfile << "'";
outfile << tmpChar; // text5
outfile << "'";
}
outfile << fields[14].GetUInt32(); // textid5
outfile << ");\n ";
} while( result->NextRow() );
+120 -52
View File
@@ -135,6 +135,7 @@ bool ChatHandler::HandleReloadAllScriptsCommand(const char*)
HandleReloadQuestStartScriptsCommand("a");
HandleReloadSpellScriptsCommand("a");
SendGlobalSysMessage("DB tables `*_scripts` reloaded.");
HandleReloadDbScriptStringCommand("a");
return true;
}
@@ -601,6 +602,14 @@ bool ChatHandler::HandleReloadSpellScriptsCommand(const char* arg)
return true;
}
bool ChatHandler::HandleReloadDbScriptStringCommand(const char* arg)
{
sLog.outString( "Re-Loading Script strings from `db_script_string`...");
objmgr.LoadDbScriptStrings();
SendGlobalSysMessage("DB table `db_script_string` reloaded.");
return true;
}
bool ChatHandler::HandleReloadGameGraveyardZoneCommand(const char* /*arg*/)
{
sLog.outString( "Re-Loading Graveyard-zone links...");
@@ -1767,7 +1776,8 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/)
// search highest talent rank
uint32 spellid = 0;
for(int rank = 4; rank >= 0; --rank)
int rank = 4;
for(; rank >= 0; --rank)
{
if(talentInfo->RankID[rank]!=0)
{
@@ -4645,91 +4655,149 @@ bool ChatHandler::HandleResetAllCommand(const char * args)
return true;
}
bool ChatHandler::HandleShutDownCommand(const char* args)
bool ChatHandler::HandleServerShutDownCancelCommand(const char* args)
{
if(!*args)
return false;
if(std::string(args)=="cancel")
{
sWorld.ShutdownCancel();
}
else
{
int32 time = atoi(args);
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0)
return false;
sWorld.ShutdownServ(time);
}
sWorld.ShutdownCancel();
return true;
}
bool ChatHandler::HandleRestartCommand(const char* args)
bool ChatHandler::HandleServerShutDownCommand(const char* args)
{
if(!*args)
return false;
if(std::string(args)=="cancel")
{
sWorld.ShutdownCancel();
}
else
{
int32 time = atoi(args);
char* time_str = strtok ((char*) args, " ");
char* exitcode_str = strtok (NULL, "");
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0)
int32 time = atoi (time_str);
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0)
return false;
if (exitcode_str)
{
int32 exitcode = atoi (exitcode_str);
// Handle atoi() errors
if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0'))
return false;
sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART);
// Exit code should be in range of 0-125, 126-255 is used
// in many shells for their own return codes and code > 255
// is not supported in many others
if (exitcode < 0 || exitcode > 125)
return false;
sWorld.ShutdownServ (time, 0, exitcode);
}
else
sWorld.ShutdownServ(time,0,SHUTDOWN_EXIT_CODE);
return true;
}
bool ChatHandler::HandleIdleRestartCommand(const char* args)
bool ChatHandler::HandleServerRestartCommand(const char* args)
{
if(!*args)
return false;
if(std::string(args)=="cancel")
{
sWorld.ShutdownCancel();
}
else
{
int32 time = atoi(args);
char* time_str = strtok ((char*) args, " ");
char* exitcode_str = strtok (NULL, "");
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0)
int32 time = atoi (time_str);
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0)
return false;
if (exitcode_str)
{
int32 exitcode = atoi (exitcode_str);
// Handle atoi() errors
if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0'))
return false;
sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART+SHUTDOWN_MASK_IDLE);
// Exit code should be in range of 0-125, 126-255 is used
// in many shells for their own return codes and code > 255
// is not supported in many others
if (exitcode < 0 || exitcode > 125)
return false;
sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART, exitcode);
}
else
sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE);
return true;
}
bool ChatHandler::HandleIdleShutDownCommand(const char* args)
bool ChatHandler::HandleServerIdleRestartCommand(const char* args)
{
if(!*args)
return false;
if(std::string(args)=="cancel")
{
sWorld.ShutdownCancel();
}
else
{
int32 time = atoi(args);
char* time_str = strtok ((char*) args, " ");
char* exitcode_str = strtok (NULL, "");
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0)
int32 time = atoi (time_str);
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0)
return false;
if (exitcode_str)
{
int32 exitcode = atoi (exitcode_str);
// Handle atoi() errors
if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0'))
return false;
sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE);
// Exit code should be in range of 0-125, 126-255 is used
// in many shells for their own return codes and code > 255
// is not supported in many others
if (exitcode < 0 || exitcode > 125)
return false;
sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, exitcode);
}
else
sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE,RESTART_EXIT_CODE);
return true;
}
bool ChatHandler::HandleServerIdleShutDownCommand(const char* args)
{
if(!*args)
return false;
char* time_str = strtok ((char*) args, " ");
char* exitcode_str = strtok (NULL, "");
int32 time = atoi (time_str);
///- Prevent interpret wrong arg value as 0 secs shutdown time
if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0)
return false;
if (exitcode_str)
{
int32 exitcode = atoi (exitcode_str);
// Handle atoi() errors
if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0'))
return false;
// Exit code should be in range of 0-125, 126-255 is used
// in many shells for their own return codes and code > 255
// is not supported in many others
if (exitcode < 0 || exitcode > 125)
return false;
sWorld.ShutdownServ (time, SHUTDOWN_MASK_IDLE, exitcode);
}
else
sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE,SHUTDOWN_EXIT_CODE);
return true;
}
+7 -8
View File
@@ -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 "Mail.h"
@@ -187,18 +187,17 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);
return;
}
if (mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || mailItem.item->GetUInt32Value(ITEM_FIELD_DURATION))
{
pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);
return;
}
if(COD && mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))
{
pl->SendMailResult(0, 0, MAIL_ERR_CANT_SEND_WRAPPED_COD);
return;
}
if(COD && mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))
{
pl->SendMailResult(0, 0, MAIL_ERR_CANT_SEND_WRAPPED_COD);
return;
}
}
}
pl->SendMailResult(0, 0, MAIL_OK);
+133 -60
View File
@@ -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,56 @@ bool Map::loaded(const GridPair &p) const
void Map::Update(const uint32 &t_diff)
{
// TODO: need have an active object list for every map
/*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 +663,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 +963,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 +1472,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 +1544,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 +1661,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 +1685,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);
}
@@ -1624,7 +1714,7 @@ void InstanceMap::CreateInstanceData(bool load)
InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(GetId());
if (mInstance)
{
i_script = mInstance->script;
i_script_id = mInstance->script_id;
i_data = Script->CreateInstanceData(this);
}
@@ -1641,7 +1731,7 @@ void InstanceMap::CreateInstanceData(bool load)
const char* data = fields[0].GetString();
if(data)
{
sLog.outDebug("Loading instance data for `%s` with id %u", i_script.c_str(), i_InstanceId);
sLog.outDebug("Loading instance data for `%s` with id %u", objmgr.GetScriptName(i_script_id), i_InstanceId);
i_data->Load(data);
}
delete result;
@@ -1649,7 +1739,7 @@ void InstanceMap::CreateInstanceData(bool load)
}
else
{
sLog.outDebug("New instance data, \"%s\" ,initialized!",i_script.c_str());
sLog.outDebug("New instance data, \"%s\" ,initialized!", objmgr.GetScriptName(i_script_id));
i_data->Initialize();
}
}
@@ -1662,21 +1752,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 +1782,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 +1796,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 +1824,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 +1840,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 +1851,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 +1859,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 +1872,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 +1893,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 +1902,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 +1912,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);
+17 -19
View File
@@ -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>
@@ -104,7 +105,7 @@ struct InstanceTemplate
float startLocY;
float startLocZ;
float startLocO;
char const* script;
uint32 script_id;
};
enum LevelRequirementVsMode
@@ -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 *);
@@ -334,33 +343,24 @@ class TRINITY_DLL_SPEC InstanceMap : public Map
void Update(const uint32&);
void CreateInstanceData(bool load);
bool Reset(uint8 method);
std::string GetScript() { return i_script; }
uint32 GetScriptId() { return i_script_id; }
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;
bool m_unloadWhenEmpty;
InstanceData* i_data;
std::string i_script;
// only online players that are inside the instance currently
// TODO ? - use the grid instead to access the players
PlayerList i_Players;
uint32 i_script_id;
};
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 +369,6 @@ class TRINITY_DLL_SPEC BattleGroundMap : public Map
bool CanEnter(Player* player);
void SetUnload();
void UnloadAll(bool pForce);
private:
PlayerList i_Players;
};
/*inline
+3 -4
View File
@@ -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++);
}
+3 -3
View File
@@ -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
+7 -5
View File
@@ -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
{
@@ -222,7 +222,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
return true;
}
void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId, uint8 mode)
void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId)
{
Map *m = _GetBaseMap(mapid);
if (m && m->Instanceable())
@@ -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;
}
+4 -3
View File
@@ -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_MAPMANAGER_H
@@ -27,6 +27,7 @@
#include "Common.h"
#include "Map.h"
#include "GridStates.h"
class Transport;
class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinity::ClassLevelLockable<MapManager, ZThread::Mutex> >
@@ -44,7 +45,7 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit
// only const version for outer users
Map const* GetBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_GetBaseMap(id); }
void DeleteInstance(uint32 mapid, uint32 instanceId, uint8 mode);
void DeleteInstance(uint32 mapid, uint32 instanceId);
inline uint16 GetAreaFlag(uint32 mapid, float x, float y) const
{
+44
View File
@@ -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
+50
View File
@@ -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
+5 -7
View File
@@ -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);
+47 -32
View File
@@ -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;
}
@@ -247,32 +255,6 @@ ObjectAccessor::SaveAllPlayers()
itr->second->SaveToDB();
}
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)
{
@@ -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,7 +501,10 @@ ObjectAccessor::RemoveActiveObject( WorldObject * obj )
void
ObjectAccessor::Update(uint32 diff)
{
{
//Player update now in MapManager -> UpdatePlayers
/*
// player update might remove the player from grid, and that causes crashes. We HAVE to update players first, and then the active objects.
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
@@ -528,8 +513,9 @@ ObjectAccessor::Update(uint32 diff)
{
iter->second->Update(diff);
}
}
}*/
// TODO: move this to Map::Update
// clone the active object list, because update might remove from it
std::set<WorldObject *> activeobjects(i_activeobjects);
@@ -590,7 +576,36 @@ ObjectAccessor::Update(uint32 diff)
}
}
_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::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 +692,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);
+3 -2
View File
@@ -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);
+288 -144
View File
@@ -10,17 +10,18 @@
*
* 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"
#include "Database/DatabaseEnv.h"
#include "Database/SQLStorage.h"
#include "Database/SQLStorageImpl.h"
#include "Log.h"
#include "MapManager.h"
@@ -116,8 +117,12 @@ ObjectMgr::ObjectMgr()
m_hiGoGuid = 1;
m_hiDoGuid = 1;
m_hiCorpseGuid = 1;
m_hiPetNumber = 1;
m_ItemTextId = 1;
m_mailid = 1;
m_auctionid = 1;
m_guildId = 1;
m_arenaTeamId = 1;
mGuildBankTabPrice.resize(GUILD_BANK_MAX_TABS);
mGuildBankTabPrice[0] = 100;
@@ -415,7 +420,7 @@ void ObjectMgr::SendAuctionWonMail( AuctionEntry *auction )
sLog.outDebug( "AuctionWon body string : %s", msgAuctionWonBody.str().c_str() );
//prepare mail data... :
uint32 itemTextId = this->CreateItemText( msgAuctionWonBody.str() );
uint32 itemTextId = CreateItemText( msgAuctionWonBody.str() );
// set owner to bidder (to prevent delete item with sender char deleting)
// owner in `data` will set at mail receive and item extracting
@@ -466,7 +471,7 @@ void ObjectMgr::SendAuctionSalePendingMail( AuctionEntry * auction )
sLog.outDebug("AuctionSalePending body string : %s", msgAuctionSalePendingBody.str().c_str());
uint32 itemTextId = this->CreateItemText( msgAuctionSalePendingBody.str() );
uint32 itemTextId = CreateItemText( msgAuctionSalePendingBody.str() );
WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->owner, msgAuctionSalePendingSubject.str(), itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_AUCTION);
}
@@ -498,7 +503,7 @@ void ObjectMgr::SendAuctionSuccessfulMail( AuctionEntry * auction )
sLog.outDebug("AuctionSuccessful body string : %s", auctionSuccessfulBody.str().c_str());
uint32 itemTextId = this->CreateItemText( auctionSuccessfulBody.str() );
uint32 itemTextId = CreateItemText( auctionSuccessfulBody.str() );
uint32 profit = auction->bid + auction->deposit - auctionCut;
@@ -545,7 +550,6 @@ void ObjectMgr::SendAuctionExpiredMail( AuctionEntry * auction )
// will delete item or place to receiver mail list
WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, GUID_LOPART(owner_guid), subject.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
}
// owner not found
else
@@ -563,8 +567,8 @@ CreatureInfo const* ObjectMgr::GetCreatureTemplate(uint32 id)
void ObjectMgr::LoadCreatureLocales()
{
mCreatureLocaleMap.clear();
mCreatureLocaleMap.clear(); // need for reload case
QueryResult *result = WorldDatabase.Query("SELECT entry,name_loc1,subname_loc1,name_loc2,subname_loc2,name_loc3,subname_loc3,name_loc4,subname_loc4,name_loc5,subname_loc5,name_loc6,subname_loc6,name_loc7,subname_loc7,name_loc8,subname_loc8 FROM locales_creature");
if(!result)
@@ -623,7 +627,7 @@ void ObjectMgr::LoadCreatureLocales()
sLog.outString();
sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() );
}
void ObjectMgr::LoadNpcOptionLocales()
{
mNpcOptionLocaleMap.clear(); // need for reload case
@@ -692,9 +696,19 @@ void ObjectMgr::LoadNpcOptionLocales()
sLog.outString( ">> Loaded %u npc_option locale strings", mNpcOptionLocaleMap.size() );
}
struct SQLCreatureLoader : public SQLStorageLoaderBase<SQLCreatureLoader>
{
template<class D>
void convert_from_str(uint32 field_pos, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
};
void ObjectMgr::LoadCreatureTemplates()
{
sCreatureStorage.Load();
SQLCreatureLoader loader;
loader.Load(sCreatureStorage);
sLog.outString( ">> Loaded %u creature definitions", sCreatureStorage.RecordCount );
sLog.outString();
@@ -1512,7 +1526,7 @@ void ObjectMgr::LoadAuctions()
aItem->deposit = fields[10].GetUInt32();
aItem->location = fields[11].GetUInt8();
//check if sold item exists
if ( this->GetAItem( aItem->item_guidlow ) )
if ( GetAItem( aItem->item_guidlow ) )
{
GetAuctionsMap( aItem->location )->AddAuction(aItem);
}
@@ -1532,8 +1546,8 @@ void ObjectMgr::LoadAuctions()
void ObjectMgr::LoadItemLocales()
{
mItemLocaleMap.clear();
mItemLocaleMap.clear(); // need for reload case
QueryResult *result = WorldDatabase.Query("SELECT entry,name_loc1,description_loc1,name_loc2,description_loc2,name_loc3,description_loc3,name_loc4,description_loc4,name_loc5,description_loc5,name_loc6,description_loc6,name_loc7,description_loc7,name_loc8,description_loc8 FROM locales_item");
if(!result)
@@ -1594,9 +1608,19 @@ void ObjectMgr::LoadItemLocales()
sLog.outString( ">> Loaded %u Item locale strings", mItemLocaleMap.size() );
}
struct SQLItemLoader : public SQLStorageLoaderBase<SQLItemLoader>
{
template<class D>
void convert_from_str(uint32 field_pos, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
};
void ObjectMgr::LoadItemPrototypes()
{
sItemStorage.Load ();
SQLItemLoader loader;
loader.Load(sItemStorage);
sLog.outString( ">> Loaded %u item prototypes", sItemStorage.RecordCount );
sLog.outString();
@@ -2506,7 +2530,7 @@ void ObjectMgr::LoadPlayerInfo()
// skip expansion races if not playing with expansion
if (sWorld.getConfig(CONFIG_EXPANSION) < 1 && (race == RACE_BLOODELF || race == RACE_DRAENEI))
continue;
// skip expansion classes if not playing with expansion
if (sWorld.getConfig(CONFIG_EXPANSION) < 2 && class_ == CLASS_DEATH_KNIGHT)
continue;
@@ -3555,7 +3579,7 @@ void ObjectMgr::LoadQuests()
void ObjectMgr::LoadQuestLocales()
{
mQuestLocaleMap.clear();
mQuestLocaleMap.clear(); // need for reload case
QueryResult *result = WorldDatabase.Query("SELECT entry,"
"Title_loc1,Details_loc1,Objectives_loc1,OfferRewardText_loc1,RequestItemsText_loc1,EndText_loc1,ObjectiveText1_loc1,ObjectiveText2_loc1,ObjectiveText3_loc1,ObjectiveText4_loc1,"
@@ -3749,7 +3773,7 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
scripts.clear(); // need for reload support
QueryResult *result = WorldDatabase.PQuery( "SELECT id,delay,command,datalong,datalong2,datatext, x, y, z, o FROM %s", tablename );
QueryResult *result = WorldDatabase.PQuery( "SELECT id,delay,command,datalong,datalong2,dataint, x, y, z, o FROM %s", tablename );
uint32 count = 0;
@@ -3771,16 +3795,16 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
Field *fields = result->Fetch();
ScriptInfo tmp;
tmp.id = fields[0].GetUInt32();
tmp.delay = fields[1].GetUInt32();
tmp.command = fields[2].GetUInt32();
tmp.datalong = fields[3].GetUInt32();
tmp.id = fields[0].GetUInt32();
tmp.delay = fields[1].GetUInt32();
tmp.command = fields[2].GetUInt32();
tmp.datalong = fields[3].GetUInt32();
tmp.datalong2 = fields[4].GetUInt32();
tmp.datatext = fields[5].GetCppString();
tmp.x = fields[6].GetFloat();
tmp.y = fields[7].GetFloat();
tmp.z = fields[8].GetFloat();
tmp.o = fields[9].GetFloat();
tmp.dataint = fields[5].GetInt32();
tmp.x = fields[6].GetFloat();
tmp.y = fields[7].GetFloat();
tmp.z = fields[8].GetFloat();
tmp.o = fields[9].GetFloat();
// generic command args check
switch(tmp.command)
@@ -3792,6 +3816,18 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
sLog.outErrorDb("Table `%s` has invalid talk type (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.datalong,tmp.id);
continue;
}
if(tmp.dataint==0)
{
sLog.outErrorDb("Table `%s` has invalid talk text id (dataint = %i) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,tmp.id);
continue;
}
if(tmp.dataint < MIN_DB_SCRIPT_STRING_ID || tmp.dataint >= MAX_DB_SCRIPT_STRING_ID)
{
sLog.outErrorDb("Table `%s` has out of range text id (dataint = %i expected %u-%u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID,tmp.id);
continue;
}
// if(!objmgr.GetMangosStringLocale(tmp.dataint)) will checked after db_script_string loading
break;
}
@@ -4156,8 +4192,8 @@ void ObjectMgr::LoadPageTexts()
void ObjectMgr::LoadPageTextLocales()
{
mPageTextLocaleMap.clear();
mPageTextLocaleMap.clear(); // need for reload case
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)
@@ -4206,9 +4242,19 @@ void ObjectMgr::LoadPageTextLocales()
sLog.outString( ">> Loaded %u PageText locale strings", mPageTextLocaleMap.size() );
}
struct SQLInstanceLoader : public SQLStorageLoaderBase<SQLInstanceLoader>
{
template<class D>
void convert_from_str(uint32 field_pos, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
};
void ObjectMgr::LoadInstanceTemplate()
{
sInstanceTemplate.Load();
SQLInstanceLoader loader;
loader.Load(sInstanceTemplate);
for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
{
@@ -4324,8 +4370,8 @@ void ObjectMgr::LoadGossipText()
void ObjectMgr::LoadNpcTextLocales()
{
mNpcTextLocaleMap.clear();
mNpcTextLocaleMap.clear(); // need for reload case
QueryResult *result = WorldDatabase.Query("SELECT entry,"
"Text0_0_loc1,Text0_1_loc1,Text1_0_loc1,Text1_1_loc1,Text2_0_loc1,Text2_1_loc1,Text3_0_loc1,Text3_1_loc1,Text4_0_loc1,Text4_1_loc1,Text5_0_loc1,Text5_1_loc1,Text6_0_loc1,Text6_1_loc1,Text7_0_loc1,Text7_1_loc1,"
"Text0_0_loc2,Text0_1_loc2,Text1_0_loc2,Text1_1_loc2,Text2_0_loc2,Text2_1_loc2,Text3_0_loc2,Text3_1_loc1,Text4_0_loc2,Text4_1_loc2,Text5_0_loc2,Text5_1_loc2,Text6_0_loc2,Text6_1_loc2,Text7_0_loc2,Text7_1_loc2,"
@@ -4622,7 +4668,7 @@ void ObjectMgr::LoadAreaTriggerScripts()
Field *fields = result->Fetch();
uint32 Trigger_ID = fields[0].GetUInt32();
std::string scriptName = fields[1].GetCppString();
const char *scriptName = fields[1].GetString();
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID);
if(!atEntry)
@@ -4630,7 +4676,7 @@ void ObjectMgr::LoadAreaTriggerScripts()
sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID);
continue;
}
mAreaTriggerScripts[Trigger_ID] = scriptName;
mAreaTriggerScripts[Trigger_ID] = GetScriptId(scriptName);
} while( result->NextRow() );
delete result;
@@ -4638,6 +4684,7 @@ void ObjectMgr::LoadAreaTriggerScripts()
sLog.outString();
sLog.outString( ">> Loaded %u areatrigger scripts", count );
}
uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
{
bool found = false;
@@ -4696,11 +4743,11 @@ void ObjectMgr::GetTaxiPath( uint32 source, uint32 destination, uint32 &path, ui
uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
{
uint32 mount_entry = 0;
uint32 mount_id = 0;
uint16 mount_entry = 0;
uint16 mount_id = 0;
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
if (node)
if(node)
{
if (team == ALLIANCE) mount_entry = node->alliance_mount_type;
else mount_entry = node->horde_mount_type;
@@ -4939,7 +4986,6 @@ WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float
}
}
// find now nearest graveyard at same map
if(entryNear)
return entryNear;
@@ -5180,7 +5226,6 @@ void ObjectMgr::SetHighestGuids()
if( result )
{
m_hiCharGuid = (*result)[0].GetUInt32()+1;
delete result;
}
@@ -5188,23 +5233,16 @@ void ObjectMgr::SetHighestGuids()
if( result )
{
m_hiCreatureGuid = (*result)[0].GetUInt32()+1;
delete result;
}
result = CharacterDatabase.Query( "SELECT MAX(id) FROM character_pet" );
if( result )
{
m_hiPetGuid = (*result)[0].GetUInt32()+1;
delete result;
}
// pet guids are not saved to DB, set to 0 (pet guid != pet id)
m_hiPetGuid = 0;
result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" );
if( result )
{
m_hiItemGuid = (*result)[0].GetUInt32()+1;
delete result;
}
@@ -5218,7 +5256,6 @@ void ObjectMgr::SetHighestGuids()
if( result )
{
m_hiGoGuid = (*result)[0].GetUInt32()+1;
delete result;
}
@@ -5226,74 +5263,93 @@ void ObjectMgr::SetHighestGuids()
if( result )
{
m_auctionid = (*result)[0].GetUInt32()+1;
delete result;
}
else
{
m_auctionid = 0;
}
result = CharacterDatabase.Query( "SELECT MAX(id) FROM mail" );
if( result )
{
m_mailid = (*result)[0].GetUInt32()+1;
delete result;
}
else
{
m_mailid = 0;
}
result = CharacterDatabase.Query( "SELECT MAX(id) FROM item_text" );
if( result )
{
m_ItemTextId = (*result)[0].GetUInt32();
m_ItemTextId = (*result)[0].GetUInt32()+1;
delete result;
}
else
m_ItemTextId = 0;
result = CharacterDatabase.Query( "SELECT MAX(guid) FROM corpse" );
if( result )
{
m_hiCorpseGuid = (*result)[0].GetUInt32()+1;
delete result;
}
result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team");
if (result)
{
m_arenaTeamId = (*result)[0].GetUInt32()+1;
delete result;
}
result = CharacterDatabase.Query( "SELECT MAX(guildid) FROM guild" );
if (result)
{
m_guildId = (*result)[0].GetUInt32()+1;
delete result;
}
}
uint32 ObjectMgr::GenerateArenaTeamId()
{
if(m_arenaTeamId>=0xFFFFFFFE)
{
sLog.outError("Arena team ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
return m_arenaTeamId++;
}
uint32 ObjectMgr::GenerateGuildId()
{
if(m_guildId>=0xFFFFFFFE)
{
sLog.outError("Guild ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
return m_guildId++;
}
uint32 ObjectMgr::GenerateAuctionID()
{
++m_auctionid;
if(m_auctionid>=0xFFFFFFFF)
if(m_auctionid>=0xFFFFFFFE)
{
sLog.outError("Auctions ids overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_auctionid;
return m_auctionid++;
}
uint32 ObjectMgr::GenerateMailID()
{
++m_mailid;
if(m_mailid>=0xFFFFFFFF)
if(m_mailid>=0xFFFFFFFE)
{
sLog.outError("Mail ids overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_mailid;
return m_mailid++;
}
uint32 ObjectMgr::GenerateItemTextID()
{
++m_ItemTextId;
if(m_ItemTextId>=0xFFFFFFFF)
if(m_ItemTextId>=0xFFFFFFFE)
{
sLog.outError("Item text ids overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_ItemTextId;
return m_ItemTextId++;
}
uint32 ObjectMgr::CreateItemText(std::string text)
@@ -5315,61 +5371,54 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
switch(guidhigh)
{
case HIGHGUID_ITEM:
++m_hiItemGuid;
if(m_hiItemGuid>=0xFFFFFFFF)
if(m_hiItemGuid>=0xFFFFFFFE)
{
sLog.outError("Item guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiItemGuid;
return m_hiItemGuid++;
case HIGHGUID_UNIT:
++m_hiCreatureGuid;
if(m_hiCreatureGuid>=0x00FFFFFF)
if(m_hiCreatureGuid>=0x00FFFFFE)
{
sLog.outError("Creature guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiCreatureGuid;
return m_hiCreatureGuid++;
case HIGHGUID_PET:
++m_hiPetGuid;
if(m_hiPetGuid>=0x00FFFFFF)
if(m_hiPetGuid>=0x00FFFFFE)
{
sLog.outError("Pet guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiPetGuid;
return m_hiPetGuid++;
case HIGHGUID_PLAYER:
++m_hiCharGuid;
if(m_hiCharGuid>=0xFFFFFFFF)
if(m_hiCharGuid>=0xFFFFFFFE)
{
sLog.outError("Players guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiCharGuid;
return m_hiCharGuid++;
case HIGHGUID_GAMEOBJECT:
++m_hiGoGuid;
if(m_hiGoGuid>=0x00FFFFFF)
if(m_hiGoGuid>=0x00FFFFFE)
{
sLog.outError("Gameobject guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiGoGuid;
return m_hiGoGuid++;
case HIGHGUID_CORPSE:
++m_hiCorpseGuid;
if(m_hiCorpseGuid>=0xFFFFFFFF)
if(m_hiCorpseGuid>=0xFFFFFFFE)
{
sLog.outError("Corpse guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiCorpseGuid;
return m_hiCorpseGuid++;
case HIGHGUID_DYNAMICOBJECT:
++m_hiDoGuid;
if(m_hiDoGuid>=0xFFFFFFFF)
if(m_hiDoGuid>=0xFFFFFFFE)
{
sLog.outError("DynamicObject guid overflow!! Can't continue, shutting down server. ");
sWorld.m_stopEvent = true;
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiDoGuid;
return m_hiDoGuid++;
default:
ASSERT(0);
}
@@ -5380,8 +5429,8 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
void ObjectMgr::LoadGameObjectLocales()
{
mGameObjectLocaleMap.clear();
mGameObjectLocaleMap.clear(); // need for reload case
QueryResult *result = WorldDatabase.Query("SELECT entry,"
"name_loc1,name_loc2,name_loc3,name_loc4,name_loc5,name_loc6,name_loc7,name_loc8,"
"castbarcaption_loc1,castbarcaption_loc2,castbarcaption_loc3,castbarcaption_loc4,"
@@ -5449,9 +5498,19 @@ void ObjectMgr::LoadGameObjectLocales()
sLog.outString( ">> Loaded %u gameobject locale strings", mGameObjectLocaleMap.size() );
}
struct SQLGameObjectLoader : public SQLStorageLoaderBase<SQLGameObjectLoader>
{
template<class D>
void convert_from_str(uint32 field_pos, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
};
void ObjectMgr::LoadGameobjectInfo()
{
sGOStorage.Load();
SQLGameObjectLoader loader;
loader.Load(sGOStorage);
// some checks
for(uint32 id = 1; id < sGOStorage.MaxEntry; id++)
@@ -6624,12 +6683,12 @@ bool ObjectMgr::CheckDeclinedNames( std::wstring mainpart, DeclinedName const& n
return true;
}
const char* ObjectMgr::GetAreaTriggerScriptName(uint32 id)
uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id)
{
AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(id);
AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(trigger_id);
if(i!= mAreaTriggerScripts.end())
return i->second.c_str();
return "";
return i->second;
return 0;
}
// Checks if player meets the condition
@@ -6674,10 +6733,10 @@ bool PlayerCondition::Meets(Player const * player) const
return true;
return false;
}
case CONDITION_NO_AURA:
return !player->HasAura(value1, value2);
case CONDITION_ACTIVE_EVENT:
return gameeventmgr.IsActiveEvent(value1);
case CONDITION_NO_AURA:
return !player->HasAura(value1, value2);
case CONDITION_ACTIVE_EVENT:
return gameeventmgr.IsActiveEvent(value1);
default:
return false;
}
@@ -6798,30 +6857,30 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", value2);
break;
}
case CONDITION_NO_AURA:
{
if(!sSpellStore.LookupEntry(value1))
{
sLog.outErrorDb("Aura condition requires to have non existing spell (Id: %d), skipped", value1);
return false;
}
if(value2 > 2)
{
sLog.outErrorDb("Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped", value2);
return false;
}
break;
}
case CONDITION_ACTIVE_EVENT:
{
GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(value1 >=events.size() || !events[value1].isValid())
{
sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1);
return false;
}
break;
}
case CONDITION_NO_AURA:
{
if(!sSpellStore.LookupEntry(value1))
{
sLog.outErrorDb("Aura condition requires to have non existing spell (Id: %d), skipped", value1);
return false;
}
if(value2 > 2)
{
sLog.outErrorDb("Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped", value2);
return false;
}
break;
}
case CONDITION_ACTIVE_EVENT:
{
GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(value1 >=events.size() || !events[value1].isValid())
{
sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1);
return false;
}
break;
}
}
return true;
}
@@ -6951,7 +7010,7 @@ bool ObjectMgr::AddGameTele(GameTele& tele)
for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr)
if(itr->first > new_id)
new_id = itr->first;
// use next
++new_id;
@@ -6991,7 +7050,7 @@ bool ObjectMgr::DeleteGameTele(std::string name)
void ObjectMgr::LoadTrainerSpell()
{
// For reload case
// For reload case
for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr)
itr->second.Clear();
m_mCacheTrainerSpellMap.clear();
@@ -7082,7 +7141,7 @@ void ObjectMgr::LoadTrainerSpell()
void ObjectMgr::LoadVendors()
{
// For reload case
// For reload case
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
itr->second.Clear();
m_mCacheVendorItemMap.clear();
@@ -7189,6 +7248,7 @@ void ObjectMgr::LoadNpcOptions()
// 0 1 2 3 4 5 6 7 8
"SELECT id,gossip_id,npcflag,icon,action,box_money,coded,option_text,box_text "
"FROM npc_option");
if( !result )
{
barGoLink bar( 1 );
@@ -7341,10 +7401,84 @@ bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 m
return true;
}
// Functions for scripting access
const char* GetAreaTriggerScriptNameById(uint32 id)
void ObjectMgr::LoadScriptNames()
{
return objmgr.GetAreaTriggerScriptName(id);
m_scriptNames.push_back("");
QueryResult *result = WorldDatabase.Query(
"SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''");
if(result)
{
do
{
m_scriptNames.push_back((*result)[0].GetString());
} while (result->NextRow());
delete result;
}
std::sort(m_scriptNames.begin(), m_scriptNames.end());
}
uint32 ObjectMgr::GetScriptId(const char *name)
{
// use binary search to find the script name in the sorted vector
// assume "" is the first element
if(!name) return 0;
ScriptNameMap::const_iterator itr =
std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name);
if(itr == m_scriptNames.end()) return 0;
return itr - m_scriptNames.begin();
}
void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set<int32>& ids)
{
for(ScriptMapMap::const_iterator itrMM = scripts.begin(); itrMM != scripts.end(); ++itrMM)
{
for(ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM)
{
if(itrM->second.dataint)
{
if(!GetTrinityStringLocale (itrM->second.dataint))
sLog.outErrorDb( "Table `db_script_string` has not existed string id %u", *itrM);
if(ids.count(itrM->second.dataint))
ids.erase(itrM->second.dataint);
}
}
}
}
void ObjectMgr::LoadDbScriptStrings()
{
LoadTrinityStrings(WorldDatabase,"db_script_string",MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID);
std::set<int32> ids;
for(int32 i = MIN_DB_SCRIPT_STRING_ID; i < MAX_DB_SCRIPT_STRING_ID; ++i)
if(GetTrinityStringLocale(i))
ids.insert(i);
CheckScripts(sQuestEndScripts,ids);
CheckScripts(sQuestStartScripts,ids);
CheckScripts(sSpellScripts,ids);
CheckScripts(sGameObjectScripts,ids);
CheckScripts(sEventScripts,ids);
for(std::set<int32>::const_iterator itr = ids.begin(); itr != ids.end(); ++itr)
sLog.outErrorDb( "Table `db_script_string` has unused string id %u", *itr);
}
// Functions for scripting access
uint32 GetAreaTriggerScriptId(uint32 trigger_id)
{
return objmgr.GetAreaTriggerScriptId(trigger_id);
}
bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value)
@@ -7359,3 +7493,13 @@ bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value, i
// for scripting localized strings allowed use _only_ negative entries
return objmgr.LoadTrinityStrings(db,table,end_value,start_value);
}
uint32 TRINITY_DLL_SPEC GetScriptId(const char *name)
{
return objmgr.GetScriptId(name);
}
ObjectMgr::ScriptNameMap & GetScriptNames()
{
return objmgr.GetScriptNames();
}
+47 -22
View File
@@ -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 _OBJECTMGR_H
@@ -84,7 +84,7 @@ struct ScriptInfo
uint32 command;
uint32 datalong;
uint32 datalong2;
std::string datatext;
int32 dataint;
float x;
float y;
float z;
@@ -128,6 +128,13 @@ typedef UNORDERED_MAP<uint32/*(mapid,spawnMode) pair*/,CellObjectGuidsMap> MapOb
typedef UNORDERED_MAP<uint64/*(instance,guid) pair*/,time_t> RespawnTimes;
// mangos string ranges
#define MIN_TRINITY_STRING_ID 1
#define MAX_TRINITY_STRING_ID 2000000000
#define MIN_DB_SCRIPT_STRING_ID MAX_TRINITY_STRING_ID
#define MAX_DB_SCRIPT_STRING_ID 2000010000
struct TrinityStringLocale
{
std::vector<std::string> Content; // 0 -> default, i -> i-1 locale index
@@ -207,8 +214,8 @@ enum ConditionType
CONDITION_QUESTREWARDED = 8, // quest_id 0
CONDITION_QUESTTAKEN = 9, // quest_id 0, for condition true while quest active.
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD ñommission aura active
CONDITION_NO_AURA = 11, // spell_id effindex
CONDITION_ACTIVE_EVENT = 12, // event_id
CONDITION_NO_AURA = 11, // spell_id effindex
CONDITION_ACTIVE_EVENT = 12, // event_id
};
#define MAX_CONDITION 13 // maximum value in ConditionType enum
@@ -250,7 +257,7 @@ struct PlayerCondition
// NPC gossip text id
typedef UNORDERED_MAP<uint32, uint32> CacheNpcTextIdMap;
typedef std::list<GossipOption> CacheNpcOptionList;
typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap;
typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap;
@@ -299,9 +306,10 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, Quest*> QuestMap;
typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerMap;
typedef UNORDERED_MAP<uint32, std::string> AreaTriggerScriptMap;
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap;
typedef UNORDERED_MAP<uint32, ReputationOnKillEntry> RepOnKillMap;
@@ -309,6 +317,8 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, PetCreateSpellEntry> PetCreateSpellMap;
typedef std::vector<std::string> ScriptNameMap;
Player* GetPlayer(const char* name) const { return ObjectAccessor::Instance().FindPlayerByName(name);}
Player* GetPlayer(uint64 guid) const { return ObjectAccessor::FindPlayer(guid); }
@@ -476,7 +486,7 @@ class ObjectMgr
AreaTrigger const* GetGoBackTrigger(uint32 Map) const;
const char* GetAreaTriggerScriptName(uint32 id);
uint32 GetAreaTriggerScriptId(uint32 trigger_id);
ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const
{
@@ -522,7 +532,8 @@ class ObjectMgr
void LoadSpellScripts();
bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value);
bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",1,std::numeric_limits<int32>::max()); }
bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); }
void LoadDbScriptStrings();
void LoadPetCreateSpells();
void LoadCreatureLocales();
void LoadCreatureTemplates();
@@ -592,6 +603,8 @@ class ObjectMgr
uint32 GenerateMailID();
uint32 GenerateItemTextID();
uint32 GeneratePetNumber();
uint32 GenerateArenaTeamId();
uint32 GenerateGuildId();
void LoadPlayerInfoInCache();
PCachePlayerInfo GetPlayerInfoFromCache(uint32 unPlayerGuid) const;
@@ -668,7 +681,6 @@ class ObjectMgr
if(itr==mPageTextLocaleMap.end()) return NULL;
return &itr->second;
}
NpcOptionLocale const* GetNpcOptionLocale(uint32 entry) const
{
NpcOptionLocaleMap::const_iterator itr = mNpcOptionLocaleMap.find(entry);
@@ -693,7 +705,7 @@ class ObjectMgr
}
const char *GetTrinityString(int32 entry, int locale_idx) const;
const char *GetTrinityStringForDBCLocale(int32 entry) const { return GetTrinityString(entry,DBCLocaleIndex); }
int32 GetDBCLocaleIndex() const { return DBCLocaleIndex; }
int32 GetDBCLocaleIndex() const { return DBCLocaleIndex; }
void SetDBCLocaleIndex(uint32 lang) { DBCLocaleIndex = GetIndexForLocale(LocaleConstant(lang)); }
void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance);
@@ -732,7 +744,7 @@ class ObjectMgr
int GetIndexForLocale(LocaleConstant loc);
LocaleConstant GetLocaleForIndex(int i);
// guild bank tabs
const uint32 GetGuildBankTabPrice(uint8 Index) { return Index < GUILD_BANK_MAX_TABS ? mGuildBankTabPrice[Index] : 0; }
uint32 GetGuildBankTabPrice(uint8 Index) const { return Index < GUILD_BANK_MAX_TABS ? mGuildBankTabPrice[Index] : 0; }
uint16 GetConditionId(ConditionType condition, uint32 value1, uint32 value2);
bool IsPlayerMeetToCondition(Player const* player, uint16 condition_id) const
@@ -753,7 +765,7 @@ class ObjectMgr
GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; }
bool AddGameTele(GameTele& data);
bool DeleteGameTele(std::string name);
CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; }
uint32 GetNpcGossip(uint32 entry) const
@@ -761,7 +773,7 @@ class ObjectMgr
CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry);
if(iter == m_mCacheNpcTextIdMap.end())
return 0;
return iter->second;
}
@@ -782,15 +794,25 @@ class ObjectMgr
return &iter->second;
}
void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, bool savetodb = true);
bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true);
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, bool savetodb = true); // for event
bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true); // for event
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0 ) const;
void LoadScriptNames();
ScriptNameMap &GetScriptNames() { return m_scriptNames; }
const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; }
uint32 GetScriptId(const char *name);
protected:
// first free id for selected id type
uint32 m_auctionid;
uint32 m_mailid;
uint32 m_ItemTextId;
uint32 m_arenaTeamId;
uint32 m_guildId;
uint32 m_hiPetNumber;
// first free low guid for seelcted guid type
uint32 m_hiCharGuid;
uint32 m_hiCreatureGuid;
uint32 m_hiPetGuid;
@@ -799,9 +821,7 @@ class ObjectMgr
uint32 m_hiDoGuid;
uint32 m_hiCorpseGuid;
uint32 m_hiPetNumber;
QuestMap mQuestTemplates;
QuestMap mQuestTemplates;
typedef UNORDERED_MAP<uint32, GossipText*> GossipTextMap;
typedef UNORDERED_MAP<uint32, uint32> QuestAreaTriggerMap;
@@ -848,6 +868,8 @@ class ObjectMgr
GameTeleMap m_GameTeleMap;
ScriptNameMap m_scriptNames;
typedef std::vector<LocaleConstant> LocalForIndex;
LocalForIndex m_LocalForIndex;
int GetOrNewIndexForLocale(LocaleConstant loc);
@@ -855,6 +877,7 @@ class ObjectMgr
int DBCLocaleIndex;
private:
void LoadScripts(ScriptMapMap& scripts, char const* tablename);
void CheckScripts(ScriptMapMap const& scripts,std::set<int32>& ids);
void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr);
void LoadQuestRelationsHelper(QuestRelations& map,char const* table);
@@ -907,7 +930,9 @@ class ObjectMgr
#define objmgr Trinity::Singleton<ObjectMgr>::Instance()
// scripting access functions
bool TRINITY_DLL_SPEC LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits<int32>::min());
TRINITY_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id);
TRINITY_DLL_SPEC bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits<int32>::min());
TRINITY_DLL_SPEC uint32 GetAreaTriggerScriptId(uint32 trigger_id);
TRINITY_DLL_SPEC uint32 GetScriptId(const char *name);
TRINITY_DLL_SPEC ObjectMgr::ScriptNameMap& GetScriptNames();
#endif
+71 -36
View File
@@ -286,6 +286,11 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
m_charmInfo->GetActionBarEntry(index)->Type = atol((*iter).c_str());
++iter;
m_charmInfo->GetActionBarEntry(index)->SpellOrAction = atol((*iter).c_str());
// patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
// so overwrite old state
SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction);
if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_CAST;
}
//init teach spells
@@ -1322,7 +1327,7 @@ void Pet::_LoadAuras(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 pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
if(result)
{
@@ -1332,10 +1337,11 @@ void Pet::_LoadAuras(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)
@@ -1372,12 +1378,15 @@ void Pet::_LoadAuras(uint32 timediff)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
continue;
Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL);
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);
if(!damage)
damage = aura->GetModifier()->m_amount;
aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges);
AddAura(aura);
}
}
while( result->NextRow() );
@@ -1390,30 +1399,52 @@ void Pet::_SaveAuras()
CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
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)
{
// skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras.
SpellEntry const *spellInfo = itr->second->GetSpellProto();
uint8 i;
for (i = 0; i < 3; i++)
if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET )
if(itr == auras.end() || lastEffectPair != itr->first)
{
AuraMap::const_iterator itr2 = itr;
// save previous spellEffectPair to db
itr2--;
SpellEntry const *spellInfo = itr2->second->GetSpellProto();
/// do not save single target auras (unless they were cast by the player)
if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo)))
{
if(!itr2->second->IsPassive())
{
// skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras.
uint8 i;
for (i = 0; i < 3; i++)
if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET )
break;
if (i == 3)
{
CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" I64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d')",
m_charmInfo->GetPetNumber(), 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));
}
}
}
if(itr == auras.end())
break;
}
if (i != 3)
continue;
if(itr->second->IsPassive())
continue;
/// do not save single target auras (unless they were cast by the player)
if (itr->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo))
continue;
CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" I64FMTD "', '%u', '%u', '%d', '%d', '%d', '%d')",
m_charmInfo->GetPetNumber(), 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));
if (lastEffectPair == itr->first)
stackCounter++;
else
{
lastEffectPair = itr->first;
stackCounter = 1;
}
}
}
@@ -1434,6 +1465,10 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
return false;
}
// same spells don't have autocast option
if (spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
active = ACT_CAST;
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
{
@@ -1508,7 +1543,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
if (IsPassiveSpell(spell_id))
CastSpell(this, spell_id, true);
else if(state == PETSPELL_NEW)
m_charmInfo->AddSpellToAB(oldspell_id, spell_id);
m_charmInfo->AddSpellToAB(oldspell_id, spell_id, (ActiveStates)active);
if(newspell->active == ACT_ENABLED)
ToggleAutocast(spell_id, true);
@@ -1658,10 +1693,10 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
if(IsPassiveSpell(spellid))
return;
if(const SpellEntry *tempSpell = GetSpellStore()->LookupEntry(spellid))
if(tempSpell->EffectImplicitTargetA[0] != TARGET_ALL_AROUND_CASTER
&& tempSpell->EffectImplicitTargetA[0] != TARGET_CHAIN_DAMAGE)
return;
//if(const SpellEntry *tempSpell = GetSpellStore()->LookupEntry(spellid))
// if(tempSpell->EffectImplicitTargetA[0] != TARGET_ALL_AROUND_CASTER
// && tempSpell->EffectImplicitTargetA[0] != TARGET_CHAIN_DAMAGE)
// return;
PetSpellMap::const_iterator itr = m_spells.find((uint16)spellid);
+90 -59
View File
@@ -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();
//skip all auras from spells that are passive or need a shapeshift
if (itr->second->IsPassive() || itr->second->IsRemovedOnShapeLost())
continue;
//do not save single target auras (unless they were cast by the player)
if (itr->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo))
continue;
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;
if (i == 3)
if(itr == auras.end() || lastEffectPair != itr->first)
{
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));
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 (!(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;
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));
}
}
}
if(itr == auras.end())
break;
}
if (lastEffectPair == itr->first)
stackCounter++;
else
{
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,6 +18688,18 @@ void Player::SetCanBlock( bool value )
UpdateBlockPercentage();
}
bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
{
for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr)
if(itr->pos == pos)
return true;
return false;
}
//***********************************
//-------------TRINITY---------------
//***********************************
void Player::HandleFallDamage(MovementInfo& movementInfo)
{
//Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored
@@ -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);
+18 -15
View File
@@ -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);
+45 -48
View File
@@ -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"
@@ -277,7 +277,7 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
// for guid set stop if set is empty
if(guids && guids->empty())
return; // nothing to do
return; // nothing to do
// setup for guids case start position
GUIDs::const_iterator guids_itr;
@@ -343,7 +343,7 @@ DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid)
{
FILE *fout = fopen(file.c_str(), "w");
if (!fout)
return DUMP_FILE_OPEN_ERROR;
return DUMP_FILE_OPEN_ERROR;
std::string dump = GetDump(guid);
@@ -371,9 +371,10 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
return DUMP_TOO_MANY_CHARS;
}
}
FILE *fin = fopen(file.c_str(), "r");
if(!fin)
return DUMP_FILE_OPEN_ERROR;
return DUMP_FILE_OPEN_ERROR;
QueryResult * result = NULL;
char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20];
@@ -390,7 +391,8 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
}
else incHighest = false;
}
else guid = objmgr.m_hiCharGuid;
else
guid = objmgr.m_hiCharGuid;
// normalize the name if specified and check if it exists
if(!normalizePlayerName(name))
@@ -468,29 +470,25 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
{
case DTT_CHAR_TABLE:
if(!changenth(line, 1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
break;
case DTT_CHARACTER: // character t.
{
if(!changenth(line, 1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
// guid, data field:guid, items
if(!changenth(line, 2, chraccount))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
std::string vals = getnth(line, 3);
if(!changetoknth(vals, OBJECT_FIELD_GUID+1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
for(uint16 field = PLAYER_FIELD_INV_SLOT_HEAD; field < PLAYER_FARSIGHT; field++)
if(!changetokGuid(vals, field+1, items, objmgr.m_hiItemGuid, true))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, vals.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if (name == "")
{
// check if the original name already exists
@@ -503,50 +501,49 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
delete result;
// rename on login: `at_login` field 30 in raw field list
if(!changenth(line, 30, "1"))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
}
}
else if(!changenth(line, 4, name.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_INVENTORY: // character_inventory t.
{
if(!changenth(line, 1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
// bag, item
if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid, true))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changeGuid(line, 4, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changeGuid(line, 4, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_ITEM: // item_instance t.
{
// item, owner, data field:item, owner guid
if(!changeGuid(line, 1, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 2, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 2, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
std::string vals = getnth(line,3);
if(!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, vals.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, vals.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_ITEM_GIFT: // character_gift
{
// guid,item_guid,
if(!changenth(line, 1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_PET: // character_pet t
@@ -569,9 +566,9 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
// item, entry, owner, ...
if(!changenth(line, 1, newpetid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
@@ -582,12 +579,12 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
// lookup currpetid and match to new inserted pet id
std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
if(petids_iter == petids.end()) // couldn't find new inserted id
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
snprintf(newpetid, 20, "%d", petids_iter->second);
if(!changenth(line, 1, newpetid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
@@ -595,20 +592,20 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
{
// id,messageType,stationery,sender,receiver
if(!changeGuid(line, 1, mails, objmgr.m_mailid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 5, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 5, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
case DTT_MAIL_ITEM: // mail_items
{
// mail_id,item_guid,item_template,receiver
if(!changeGuid(line, 1, mails, objmgr.m_mailid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 4, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 4, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
default:
@@ -617,7 +614,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::str
}
if(!CharacterDatabase.Execute(line.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
ROLLBACK(DUMP_FILE_BROKEN);
}
CharacterDatabase.CommitTransaction();
+1 -1
View File
@@ -248,7 +248,7 @@ enum ItemQualities
#define SPELL_ATTR_EX_UNK14 0x00004000 // 14
#define SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY 0x00008000 // 15 remove auras on immunity
#define SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE 0x00010000 // 16 unaffected by school immunity
#define SPELL_ATTR_EX_UNK17 0x00020000 // 17
#define SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET 0x00020000 // 17
#define SPELL_ATTR_EX_UNK18 0x00040000 // 18
#define SPELL_ATTR_EX_UNK19 0x00080000 // 19
#define SPELL_ATTR_EX_REQ_COMBO_POINTS1 0x00100000 // 20 Req combo points on target
+3
View File
@@ -996,6 +996,9 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
//TODO: find a better way to judge CC auras
if(m_spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
}
else
{
+40 -68
View File
@@ -169,10 +169,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
@@ -190,7 +190,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
@@ -219,7 +219,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
@@ -1998,6 +1998,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)
{
@@ -2286,6 +2296,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);
@@ -2685,7 +2699,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())
@@ -3581,7 +3597,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)
@@ -3590,7 +3606,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)
@@ -3629,7 +3645,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)
@@ -3638,7 +3654,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)
@@ -3649,7 +3665,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)
@@ -4334,7 +4350,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;
@@ -4345,7 +4361,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;
@@ -4363,7 +4379,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;
@@ -4374,7 +4390,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;
@@ -4383,7 +4399,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;
@@ -4423,7 +4439,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;
@@ -4558,7 +4574,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)
@@ -4572,7 +4588,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)
@@ -4659,7 +4675,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;
@@ -4667,7 +4683,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;
@@ -4676,7 +4692,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;
@@ -4685,7 +4701,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)
@@ -4753,7 +4769,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)
@@ -4835,39 +4851,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
@@ -5315,7 +5298,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;
@@ -5340,17 +5323,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;
+3 -6
View File
@@ -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);
}
+43 -29
View File
@@ -333,13 +333,26 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
damage = 200;
break;
}
// must only affect demons
// must only affect demons (also undead?)
case 45072:
{
if(unitTarget->GetCreatureType() != CREATURE_TYPE_DEMON)
if(unitTarget->GetCreatureType() != CREATURE_TYPE_DEMON
|| unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
return;
break;
}
// gruul's shatter
case 33671:
{
// don't damage self and only players
if(unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0]));
if(!radius) return;
float distance = m_caster->GetDistance2d(unitTarget);
damage = (distance > radius ) ? 0 : (int32)(m_spellInfo->EffectBasePoints[0]*((radius - distance)/radius));
}break;
}
break;
}
@@ -1158,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
@@ -1261,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;
}
@@ -2237,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);
}
}
@@ -2253,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 :
@@ -2266,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 :
@@ -2277,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:
@@ -2637,6 +2650,7 @@ void Spell::EffectPersistentAA(uint32 i)
{
float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
if(!caster) return;
if(Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
@@ -2666,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;
@@ -3745,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)
@@ -3766,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*/)
@@ -3987,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());
@@ -4017,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() )
{
@@ -4107,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());
@@ -4432,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))
{
@@ -4439,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)
{
@@ -5434,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;
@@ -5655,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);
@@ -5682,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))
@@ -6118,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
{
+12 -6
View File
@@ -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"
@@ -55,6 +55,12 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
return;
}
if(pItem->GetGUID() != item_guid)
{
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size());
ItemPrototype const *proto = pItem->GetProto();
@@ -238,7 +244,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
uint32 flags = fields[1].GetUInt32();
pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0);
pItem->SetUInt32Value(OBJECT_FIELD_ENTRY, entry);
pItem->SetEntry(entry);
pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags);
pItem->SetState(ITEM_CHANGED, pUser);
delete result;
@@ -260,7 +266,6 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
CHECK_PACKET_SIZE(recv_data,8);
uint64 guid;
uint32 spellId = OPEN_CHEST;
recv_data >> guid;
@@ -323,7 +328,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
}
Spell *spell = new Spell(_player, spellInfo, false);
spell->m_cast_count = cast_count; //set count of casts
spell->m_cast_count = cast_count; // set count of casts
spell->prepare(&targets);
}
@@ -364,10 +369,11 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM ||
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_BIND_SIGHT)
{
// Fix me: creature may be killed during player aura cancel
_player->RemoveAurasDueToSpellByCancel(spellId);
if (_player->GetCharm())
_player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId);
else if (_player->GetFarsightTarget()->GetTypeId() != TYPEID_DYNAMICOBJECT)
else if (_player->GetFarsightTarget() && _player->GetFarsightTarget()->GetTypeId() != TYPEID_DYNAMICOBJECT)
((Unit*)_player->GetFarsightTarget())->RemoveAurasDueToSpellByCancel(spellId);
return;
}
+66 -13
View File
@@ -99,7 +99,7 @@ bool IsPassiveSpell(uint32 spellId)
return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
/*bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
{
SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
@@ -113,7 +113,7 @@ bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_
return false;
return true;
}
}*/
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
{
@@ -244,14 +244,24 @@ bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2)
case SPELL_STING:
case SPELL_CURSE:
case SPELL_ASPECT:
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_WARLOCK_CORRUPTION:
return spellSpec1==spellSpec2;
default:
return false;
}
}
bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1,uint32 spellSpec2)
{
switch(spellSpec1)
{
case SPELL_TRACKER:
case SPELL_WARLOCK_ARMOR:
case SPELL_MAGE_ARMOR:
case SPELL_ELEMENTAL_SHIELD:
case SPELL_MAGE_POLYMORPH:
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_WARLOCK_CORRUPTION:
return spellSpec1==spellSpec2;
case SPELL_BATTLE_ELIXIR:
return spellSpec2==SPELL_BATTLE_ELIXIR
@@ -1030,10 +1040,10 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
return true;
}
bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const
bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool sameCaster) const
{
if(spellId_1 == spellId_2) // auras due to the same spell
return false;
//if(spellId_1 == spellId_2) // auras due to the same spell
// return false;
SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
@@ -1041,22 +1051,65 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
if(!spellInfo_1 || !spellInfo_2)
return false;
SpellSpecific spellId_spec_1 = GetSpellSpecific(spellId_1);
SpellSpecific spellId_spec_2 = GetSpellSpecific(spellId_2);
if (spellId_spec_1 && spellId_spec_2)
if (IsSingleFromSpellSpecificPerTarget(spellId_spec_1, spellId_spec_2)
||(IsSingleFromSpellSpecificPerCaster(spellId_spec_1, spellId_spec_2) && sameCaster))
return true;
if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
return false;
if(!spellInfo_1->SpellFamilyName) // generic spells
// generic spells
if(!spellInfo_1->SpellFamilyName)
{
if(!spellInfo_1->SpellIconID
|| spellInfo_1->SpellIconID != spellInfo_2->SpellIconID)
return false;
}
else if (spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags)
return false;
// if both elixirs are not battle/guardian/potions/flasks then always stack
else if(spellInfo_1->SpellFamilyName == SPELLFAMILY_POTION)
{
if(spellId_spec_1 || spellId_spec_2)
return false;
}
// check for class spells
else
{
if (spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags)
return false;
}
for(uint32 i = 0; i < 3; ++i)
{
if(spellInfo_1->Effect[i] != spellInfo_2->Effect[i]
|| spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i])
return false;
|| spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i]
|| spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura
return false; // need itemtype check? need an example to add that check
if(spellInfo_1->EffectApplyAuraName[i] // both spell has the same auras
&& !sameCaster
&& spellInfo_1->Effect[i] != SPELL_EFFECT_APPLY_AREA_AURA_PARTY) // not area auras (shaman totem)
// a better check may be effect == SPELL_EFFECT_APPLY_AURA
{
switch(spellInfo_1->EffectApplyAuraName[i])
{
// DOT or HOT from different casters will stack
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
case SPELL_AURA_PERIODIC_ENERGIZE:
case SPELL_AURA_PERIODIC_MANA_LEECH:
case SPELL_AURA_PERIODIC_LEECH:
return false;
default:
break;
}
}
}
return true;
}
+4 -3
View File
@@ -284,7 +284,7 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
return false;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
//bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
inline bool IsSealSpell(SpellEntry const *spellInfo)
{
@@ -300,7 +300,8 @@ inline bool IsElementalShield(SpellEntry const *spellInfo)
}
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2);
bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1, uint32 spellSpec2);
bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1, uint32 spellSpec2);
bool IsPassiveSpell(uint32 spellId);
inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo)
@@ -768,7 +769,7 @@ class SpellMgr
bool IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const;
static bool canStackSpellRanks(SpellEntry const *spellInfo);
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const;
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool sameCaster) const;
SpellEntry const* SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const;
+1 -1
View File
@@ -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;
+3
View File
@@ -97,6 +97,9 @@ void Totem::Summon(Unit* owner)
case TOTEM_STATUE: CastSpell(GetOwner(), GetSpell(), true); break;
default: break;
}
if(GetEntry() == SENTRY_TOTEM_ENTRY)
SetAggressive(true);
}
void Totem::UnSummon()
+248 -235
View File
@@ -1149,8 +1149,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);
@@ -1435,7 +1433,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);
@@ -3798,7 +3796,6 @@ bool Unit::AddAura(Aura *Aur)
if(Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
{
m_ccAuras.push_back(Aur);
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
}
}
@@ -3914,16 +3911,17 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
if(!is_triggered_by_spell)
{
SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID();
if( spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster) )
{
// cannot remove higher rank
if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
return false;
//some spells should be not removed by lower rank of them
// what is this spell?
if (!sameCaster
&&(spellProto->Effect[effIndex]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
&&(spellProto->DurationIndex==21)
&&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
&&(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0))
return false;
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
@@ -3938,39 +3936,6 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
else
next = m_Auras.begin();
}
else if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
{
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
{
sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex());
continue;
}
RemoveAurasDueToSpell(i_spellId);
if( m_Auras.empty() )
break;
else
next = m_Auras.begin();
}
// Potions stack aura by aura (elixirs/flask already checked)
else if( spellProto->SpellFamilyName == SPELLFAMILY_POTION && i_spellProto->SpellFamilyName == SPELLFAMILY_POTION )
{
if (IsNoStackAuraDueToAura(spellId, effIndex, i_spellId, i_effIndex))
{
if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
return false; // cannot remove higher rank
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
{
sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex());
continue;
}
RemoveAura(i);
next = i;
}
}
}
}
return true;
@@ -4144,12 +4109,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
{
@@ -4158,7 +4128,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)
@@ -4170,8 +4141,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
@@ -4179,13 +4148,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))
{
@@ -4203,6 +4181,9 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
Aur->_RemoveAura();
delete Aur;
if(caster_channeled)
RemoveAurasAtChanneledTarget (AurSpellInfo);
if(statue)
statue->UnSummon();
@@ -4628,8 +4609,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;
@@ -4689,8 +4672,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;
@@ -6278,7 +6264,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:
@@ -6308,7 +6293,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:
@@ -6508,8 +6492,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;
@@ -7275,7 +7261,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());
@@ -7375,7 +7361,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 *)
@@ -8223,7 +8209,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;
@@ -8291,7 +8277,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;
@@ -8521,7 +8507,8 @@ void Unit::CombatStart(Unit* target)
if(!target->IsStandState() && !target->hasUnitState(UNIT_STAT_STUNNED))
target->SetStandState(PLAYER_STATE_NONE);
if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER && ((Creature*)target)->AI())
if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER
&& ((Creature*)target)->isAggressive() && ((Creature*)target)->AI())
((Creature*)target)->AI()->AttackStart(this);
SetInCombatWith(target);
@@ -8571,6 +8558,9 @@ bool Unit::canAttack(Unit const* target) const
{
assert(target);
if(!IsHostileTo(target))
return false;
if(!target->isAttackableByAOE() || target->hasUnitState(UNIT_STAT_DIED))
return false;
@@ -8746,7 +8736,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());
@@ -9155,6 +9145,13 @@ bool Unit::SelectHostilTarget()
}
}
// search nearby enemy before enter evade mode
if(Unit *target = ((Creature*)this)->SelectNearestTarget())
{
((Creature*)this)->AI()->AttackStart(target);
return true;
}
// enter in evade mode in other case
((Creature*)this)->AI()->EnterEvadeMode();
@@ -9808,8 +9805,6 @@ void Unit::CleanupsBeforeDelete()
RemoveFromWorld();
}
CharmInfo* Unit::InitCharmInfo(Unit *charm)
{
if(!m_charmInfo)
@@ -9984,17 +9979,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;
@@ -10011,87 +10004,13 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
{
next = i; ++next;
SpellEntry const *spellProto = (*i)->GetSpellProto();
if(!spellProto)
Aura* i_aura = *i;
uint32 cooldown; // returned at next line
if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,cooldown))
continue;
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))
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
@@ -10124,106 +10043,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());
sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
(isVictim?"a victim's":"an attacker's"),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);
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:
@@ -10234,27 +10118,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;
@@ -10367,7 +10251,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());
@@ -10577,7 +10461,7 @@ void Unit::UpdateReactives( uint32 p_time )
}
}
Unit* Unit::SelectNearbyTarget() const
Unit* Unit::SelectNearbyTarget(float dist) const
{
CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
@@ -10587,7 +10471,7 @@ Unit* Unit::SelectNearbyTarget() const
std::list<Unit *> targets;
{
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, ATTACK_DISTANCE);
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, dist);
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
@@ -10851,9 +10735,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()))
@@ -10871,3 +10755,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;
}
}
+10 -7
View File
@@ -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
@@ -763,7 +763,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
Unit* getVictim() const { return m_attacking; }
void CombatStop(bool cast = false);
void CombatStopWithPets(bool cast = false);
Unit* SelectNearbyTarget() const;
Unit* SelectNearbyTarget(float dist = ATTACK_DISTANCE) const;
void addUnitState(uint32 f) { m_state |= f; }
bool hasUnitState(const uint32 f) const { return (m_state & f); }
@@ -934,7 +934,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);
@@ -1040,6 +1040,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);
@@ -1371,10 +1372,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;
+50 -18
View File
@@ -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 "Database/DatabaseEnv.h"
@@ -24,20 +24,30 @@
#include "WaypointManager.h"
#include "ProgressBar.h"
#include "MapManager.h"
#include "ObjectMgr.h"
INSTANTIATE_SINGLETON_1(WaypointManager);
bool WaypointBehavior::isEmpty()
{
return emote == 0 && spell == 0 && model1 == 0 && model2 == 0 && text[0].empty() &&
text[1].empty() && text[2].empty() && text[3].empty() && text[4].empty();
if (emote || spell || model1 || model2)
return false;
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
if(textid[i])
return false;
return true;
}
WaypointBehavior::WaypointBehavior(const WaypointBehavior &b)
{
emote = b.emote; spell = b.spell; model1 = b.model1; model2 = b.model2;
text[0] = b.text[0]; text[1] = b.text[1]; text[2] = b.text[2];
text[3] = b.text[3]; text[4] = b.text[4];
emote = b.emote;
spell = b.spell;
model1 = b.model1;
model2 = b.model2;
for(int i=0; i < MAX_WAYPOINT_TEXT; ++i)
textid[i] = b.textid[i];
}
void WaypointManager::Load()
@@ -66,7 +76,7 @@ void WaypointManager::Load()
delete result;
}
result = WorldDatabase.Query("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, id, point FROM creature_movement");
result = WorldDatabase.Query("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, id, point FROM creature_movement");
if(result)
{
barGoLink bar( result->GetRowCount() );
@@ -113,11 +123,33 @@ void WaypointManager::Load()
be.model2 = fields[5].GetUInt32();
be.emote = fields[7].GetUInt32();
be.spell = fields[8].GetUInt32();
be.text[0] = fields[9].GetCppString();
be.text[1] = fields[10].GetCppString();
be.text[2] = fields[11].GetCppString();
be.text[3] = fields[12].GetCppString();
be.text[4] = fields[13].GetCppString();
// load and store without holes in array
int j = 0;
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
{
be.textid[j] = fields[9+i].GetUInt32();
if(be.textid[j])
{
if (be.textid[j] < MIN_DB_SCRIPT_STRING_ID || be.textid[j] >= MAX_DB_SCRIPT_STRING_ID)
{
sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[j]);
continue;
}
if (!objmgr.GetTrinityStringLocale (be.textid[j]))
{
sLog.outErrorDb("ERROR: Waypoint path %d (point %d), have invalid text id (%i) in `textid%d, ignored.",
id, point, be.textid[j], i+1);
continue;
}
++j; // to next internal field
}
}
// fill array tail
for(; j < MAX_WAYPOINT_TEXT; ++j)
be.textid[j] = 0;
// save memory by not storing empty behaviors
if(!be.isEmpty())
@@ -265,11 +297,11 @@ void WaypointManager::SetNodeText(uint32 id, uint32 point, const char *text_fiel
WaypointNode &node = itr->second[point-1];
if(!node.behavior) node.behavior = new WaypointBehavior();
if(field == "text1") node.behavior->text[0] = text ? text : "";
if(field == "text2") node.behavior->text[1] = text ? text : "";
if(field == "text3") node.behavior->text[2] = text ? text : "";
if(field == "text4") node.behavior->text[3] = text ? text : "";
if(field == "text5") node.behavior->text[4] = text ? text : "";
// if(field == "text1") node.behavior->text[0] = text ? text : "";
// if(field == "text2") node.behavior->text[1] = text ? text : "";
// if(field == "text3") node.behavior->text[2] = text ? text : "";
// if(field == "text4") node.behavior->text[3] = text ? text : "";
// if(field == "text5") node.behavior->text[4] = text ? text : "";
if(field == "emote") node.behavior->emote = text ? atoi(text) : 0;
if(field == "spell") node.behavior->spell = text ? atoi(text) : 0;
if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0;
+2 -1
View File
@@ -25,11 +25,12 @@
#include <string>
#include "Utilities/UnorderedMap.h"
#define MAX_WAYPOINT_TEXT 5
struct WaypointBehavior
{
uint32 emote;
uint32 spell;
std::string text[5];
int32 textid[MAX_WAYPOINT_TEXT];
uint32 model1;
uint32 model2;
+12 -13
View File
@@ -21,11 +21,11 @@
/*
creature_movement Table
alter table creature_movement add `text1` varchar(255) default NULL;
alter table creature_movement add `text2` varchar(255) default NULL;
alter table creature_movement add `text3` varchar(255) default NULL;
alter table creature_movement add `text4` varchar(255) default NULL;
alter table creature_movement add `text5` varchar(255) default NULL;
alter table creature_movement add `textid1` int(11) NOT NULL default '0';
alter table creature_movement add `textid2` int(11) NOT NULL default '0';
alter table creature_movement add `textid3` int(11) NOT NULL default '0';
alter table creature_movement add `textid4` int(11) NOT NULL default '0';
alter table creature_movement add `textid5` int(11) NOT NULL default '0';
alter table creature_movement add `emote` int(10) unsigned default '0';
alter table creature_movement add `spell` int(5) unsigned default '0';
alter table creature_movement add `wpguid` int(11) default '0';
@@ -148,22 +148,21 @@ WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &di
creature.CastSpell(&creature,behavior->spell, false);
if(behavior->model1 != 0)
creature.SetDisplayId(behavior->model1);
if(!behavior->text[0].empty())
if(behavior->textid[0])
{
// Only one text is set
if( !behavior->text[1].empty() )
// Not only one text is set
if( behavior->textid[1] )
{
// Select one from max 5 texts (0 and 1 already checked)
int i = 2;
for( ; i < 5; ++i )
if( behavior->text[i].empty() )
for( ; i < MAX_WAYPOINT_TEXT; ++i )
if( !behavior->textid[i] )
break;
creature.Say(behavior->text[rand() % i].c_str(), 0, 0);
creature.Say(behavior->textid[rand() % i], 0, 0);
}
else
creature.Say(behavior->text[0].c_str(), 0, 0);
creature.Say(behavior->textid[0], 0, 0);
}
} // wpBehaviour found
i_hasDone[idx] = true;
+41 -22
View File
@@ -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
*/
/** \file
@@ -66,6 +66,7 @@
INSTANTIATE_SINGLETON_1( World );
volatile bool World::m_stopEvent = false;
uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
volatile uint32 World::m_worldLoopCounter = 0;
float World::m_MaxVisibleDistanceForCreature = DEFAULT_VISIBILITY_DISTANCE;
@@ -542,7 +543,6 @@ void World::LoadConfigSettings(bool reload)
else
m_configs[CONFIG_SOCKET_SELECTTIME] = sConfig.GetIntDefault("SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME);
m_configs[CONFIG_GROUP_XP_DISTANCE] = sConfig.GetIntDefault("MaxGroupXPDistance", 74);
/// \todo Add MonsterSight and GuarderSight (with meaning) in Trinityd.conf or put them as define
m_configs[CONFIG_SIGHT_MONSTER] = sConfig.GetIntDefault("MonsterSight", 50);
@@ -605,7 +605,6 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_SKIP_CINEMATICS] = 0;
}
if(reload)
{
uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", 60);
@@ -769,8 +768,8 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 100);
// always use declined names in the Russian client
m_configs[CONFIG_DECLINED_NAMES_USED] =
// always use declined names in the russian client
m_configs[CONFIG_DECLINED_NAMES_USED] =
(m_configs[CONFIG_REALM_ZONE] == REALM_ZONE_RUSSIAN) ? true : sConfig.GetBoolDefault("DeclinedNames", false);
m_configs[CONFIG_LISTEN_RANGE_SAY] = sConfig.GetIntDefault("ListenRange.Say", 25);
@@ -965,6 +964,9 @@ void World::SetInitialWorldSettings()
LoadDBCStores(m_dataPath);
DetectDBCLang();
sLog.outString( "Loading Script Names...");
objmgr.LoadScriptNames();
sLog.outString( "Loading InstanceTemplate" );
objmgr.LoadInstanceTemplate();
@@ -1080,11 +1082,10 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Tavern Area Triggers..." );
objmgr.LoadTavernAreaTriggers();
sLog.outString( "Loading AreaTrigger script names..." );
objmgr.LoadAreaTriggerScripts();
sLog.outString( "Loading Graveyard-zone links...");
objmgr.LoadGraveyardZones();
@@ -1164,7 +1165,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Npc Text Id..." );
objmgr.LoadNpcTextId(); // must be after load Creature and NpcText
sLog.outString( "Loading Npc Options..." );
objmgr.LoadNpcOptions();
@@ -1192,6 +1193,9 @@ void World::SetInitialWorldSettings()
objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
objmgr.LoadDbScriptStrings();
sLog.outString( "Initializing Scripts..." );
if(!LoadScriptingModule())
exit(1);
@@ -1262,6 +1266,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "WORLD: World initialized" );
}
void World::DetectDBCLang()
{
uint32 m_lang_confid = sConfig.GetIntDefault("DBC.Locale", 255);
@@ -1462,7 +1467,9 @@ void World::Update(time_t diff)
m_timers[WUPDATE_EVENTS].Reset();
}
MapManager::Instance().DoDelayedMovesAndRemoves(); ///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
/// </ul>
///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
MapManager::Instance().DoDelayedMovesAndRemoves();
// update the instance reset times
sInstanceSaveManager.Update();
@@ -1582,6 +1589,8 @@ void World::ScriptsProcess()
}
}
//if(source && !source->IsInWorld()) source = NULL;
Object* target = NULL;
if(step.targetGUID)
@@ -1609,6 +1618,8 @@ void World::ScriptsProcess()
}
}
//if(target && !target->IsInWorld()) target = NULL;
switch (step.script->command)
{
case SCRIPT_COMMAND_TALK:
@@ -1636,7 +1647,7 @@ void World::ScriptsProcess()
switch(step.script->datalong)
{
case 0: // Say
((Creature *)source)->Say(step.script->datatext.c_str(), LANG_UNIVERSAL, unit_target);
((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target);
break;
case 1: // Whisper
if(!unit_target)
@@ -1644,13 +1655,13 @@ void World::ScriptsProcess()
sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong);
break;
}
((Creature *)source)->Whisper(step.script->datatext.c_str(),unit_target);
((Creature *)source)->Whisper(step.script->dataint,unit_target);
break;
case 2: // Yell
((Creature *)source)->Yell(step.script->datatext.c_str(), LANG_UNIVERSAL, unit_target);
((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target);
break;
case 3: // Emote text
((Creature *)source)->TextEmote(step.script->datatext.c_str(), unit_target);
((Creature *)source)->TextEmote(step.script->dataint, unit_target);
break;
default:
break; // must be already checked at load
@@ -1701,7 +1712,7 @@ void World::ScriptsProcess()
break;
}
((Unit *)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, ((Unit *)source)->GetUnitMovementFlags(), step.script->datalong2 );
MapManager::Instance().GetMap(((Unit *)source)->GetMapId(), ((Unit *)source))->CreatureRelocation(((Creature *)source), step.script->x, step.script->y, step.script->z, 0);
((Unit *)source)->GetMap()->CreatureRelocation(((Creature *)source), step.script->x, step.script->y, step.script->z, 0);
break;
case SCRIPT_COMMAND_FLAG_SET:
if(!source)
@@ -1851,7 +1862,7 @@ void World::ScriptsProcess()
go->SetLootState(GO_READY);
go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds
MapManager::Instance().GetMap(go->GetMapId(), go)->Add(go);
go->GetMap()->Add(go);
break;
}
case SCRIPT_COMMAND_OPEN_DOOR:
@@ -2373,13 +2384,13 @@ void World::_UpdateGameTime()
m_gameTime = thisTime;
///- if there is a shutdown timer
if(m_ShutdownTimer > 0 && elapsed > 0)
if(!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0)
{
///- ... and it is overdue, stop the world (set m_stopEvent)
if( m_ShutdownTimer <= elapsed )
{
if(!(m_ShutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0)
m_stopEvent = true;
m_stopEvent = true; // exist code already set
else
m_ShutdownTimer = 1; // minimum timer value to wait idle state
}
@@ -2394,15 +2405,20 @@ void World::_UpdateGameTime()
}
/// Shutdown the server
void World::ShutdownServ(uint32 time, uint32 options)
void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
{
// ignore if server shutdown at next tick
if(m_stopEvent)
return;
m_ShutdownMask = options;
m_ExitCode = exitcode;
///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions)
if(time==0)
{
if(!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0)
m_stopEvent = true;
m_stopEvent = true; // exist code already set
else
m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick
}
@@ -2447,16 +2463,18 @@ void World::ShutdownMsg(bool show, Player* player)
/// Cancel a planned server shutdown
void World::ShutdownCancel()
{
if(!m_ShutdownTimer)
// nothing cancel or too later
if(!m_ShutdownTimer || m_stopEvent)
return;
uint32 msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED;
m_ShutdownMask = 0;
m_ShutdownTimer = 0;
m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value
SendServerMessage(msgid);
DEBUG_LOG("Server %s canceled.",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"));
DEBUG_LOG("Server %s cancelled.",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"));
}
/// Send a server message to the user(s)
@@ -2501,6 +2519,7 @@ void World::UpdateSessions( time_t diff )
///- and remove not active sessions from the list
if(!itr->second->Update(diff)) // As interval = 0
{
RemoveQueuedPlayer (itr->second);
delete itr->second;
m_sessions.erase(itr);
}
+45 -34
View File
@@ -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
*/
/// \addtogroup world The World
@@ -51,6 +51,13 @@ enum ShutdownMask
SHUTDOWN_MASK_IDLE = 2,
};
enum ShutdownExitCode
{
SHUTDOWN_EXIT_CODE = 0,
ERROR_EXIT_CODE = 1,
RESTART_EXIT_CODE = 2,
};
/// Timers for different object refresh rates
enum WorldTimers
{
@@ -61,8 +68,7 @@ enum WorldTimers
WUPDATE_UPTIME = 4,
WUPDATE_CORPSES = 5,
WUPDATE_EVENTS = 6,
WUPDATE_COUNT = 7,
WUPDATE_COUNT = 7
};
/// Configuration elements
@@ -105,6 +111,8 @@ enum WorldConfigs
CONFIG_INSTANCE_IGNORE_LEVEL,
CONFIG_INSTANCE_IGNORE_RAID,
CONFIG_BATTLEGROUND_CAST_DESERTER,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_INSTANCE_RESET_TIME_HOUR,
CONFIG_INSTANCE_UNLOAD_DELAY,
CONFIG_CAST_UNSTUCK,
@@ -143,6 +151,7 @@ enum WorldConfigs
CONFIG_WORLD_BOSS_LEVEL_DIFF,
CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF,
CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF,
CONFIG_DETECT_POS_COLLISION,
CONFIG_RESTRICTED_LFG_CHANNEL,
CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL,
CONFIG_TALENTS_INSPECTING,
@@ -316,27 +325,26 @@ enum RealmZone
/// Storage class for commands issued for delayed execution
struct CliCommandHolder
{
typedef void Print(const char*);
typedef void Print(const char*);
char *m_command;
Print* m_print;
char *m_command;
Print* m_print;
CliCommandHolder(const char *command, Print* zprint)
: m_print(zprint)
{
size_t len = strlen(command)+1;
m_command = new char[len];
memcpy(m_command, command, len);
}
CliCommandHolder(const char *command, Print* zprint)
: m_print(zprint)
{
size_t len = strlen(command)+1;
m_command = new char[len];
memcpy(m_command, command, len);
}
~CliCommandHolder() { delete[] m_command; }
~CliCommandHolder() { delete[] m_command; }
};
/// The World
class World
{
public:
static volatile bool m_stopEvent;
static volatile uint32 m_worldLoopCounter;
World();
@@ -344,7 +352,6 @@ class World
WorldSession* FindSession(uint32 id) const;
void AddSession(WorldSession *s);
bool RemoveSession(uint32 id);
/// Get the number of current active sessions
void UpdateMaxSessionCounters();
@@ -407,18 +414,20 @@ class World
void SetInitialWorldSettings();
void LoadConfigSettings(bool reload = false);
void SendWorldText(int32 string_id, ...);
void SendWorldText(int32 string_id, ...);
void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0);
void SendServerMessage(uint32 type, const char *text = "", Player* player = NULL);
/// Are we in the middle of a shutdown?
uint32 GetShutdownMask() const { return m_ShutdownMask; }
bool IsShutdowning() const { return m_ShutdownTimer > 0; }
void ShutdownServ(uint32 time, uint32 options = 0);
void ShutdownServ(uint32 time, uint32 options, uint8 exitcode);
void ShutdownCancel();
void ShutdownMsg(bool show = false, Player* player = NULL);
static uint8 GetExitCode() { return m_ExitCode; }
static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; }
static bool IsStopped() { return m_stopEvent; }
void Update(time_t diff);
@@ -453,7 +462,7 @@ class World
void KickAllLess(AccountTypes sec);
void KickAllQueued();
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author);
bool RemoveBanAccount(BanMode mode, std::string nameOrIP);
bool RemoveBanAccount(BanMode mode, std::string nameOrIP);
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target);
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
@@ -481,13 +490,13 @@ class World
LocaleConstant GetAvailableDbcLocale(LocaleConstant locale) const { if(m_availableDbcLocaleMask & (1 << locale)) return locale; else return m_defaultDbcLocale; }
//used World DB version
void LoadDBVersion();
char const* GetDBVersion() { return m_DBVersion.c_str(); }
//used World DB version
void LoadDBVersion();
char const* GetDBVersion() { return m_DBVersion.c_str(); }
//used Script version
void SetScriptsVersion(char const* version) { m_ScriptsVersion = version ? version : "unknown scripting library"; }
char const* GetScriptsVersion() { return m_ScriptsVersion.c_str(); }
//used Script version
void SetScriptsVersion(char const* version) { m_ScriptsVersion = version ? version : "unknown scripting library"; }
char const* GetScriptsVersion() { return m_ScriptsVersion.c_str(); }
protected:
void _UpdateGameTime();
@@ -498,6 +507,11 @@ class World
void InitDailyQuestResetTime();
void ResetDailyQuests();
private:
static volatile bool m_stopEvent;
static uint8 m_ExitCode;
uint32 m_ShutdownTimer;
uint32 m_ShutdownMask;
time_t m_startTime;
time_t m_gameTime;
IntervalTimer m_timers[WUPDATE_COUNT];
@@ -525,9 +539,6 @@ class World
std::string m_dataPath;
std::set<uint32> m_forbiddenMapIds;
uint32 m_ShutdownTimer;
uint32 m_ShutdownMask;
// for max speed access
static float m_MaxVisibleDistanceForCreature;
static float m_MaxVisibleDistanceForPlayer;
@@ -545,14 +556,14 @@ class World
//Player Queue
Queue m_QueuedPlayer;
//sessions that are added async
void AddSession_(WorldSession* s);
ZThread::LockedQueue<WorldSession*, ZThread::FastMutex> addSessQueue;
//used versions
std::string m_DBVersion;
std::string m_ScriptsVersion;
//used versions
std::string m_DBVersion;
std::string m_ScriptsVersion;
};
extern uint32 realmID;