mirror of
https://github.com/mangosfour/server.git
synced 2025-12-31 22:37:05 +00:00
Merge commit 'origin/master' into 303
Conflicts: src/game/SpellEffects.cpp src/game/World.cpp
This commit is contained in:
commit
cffc766fb6
31 changed files with 415 additions and 168 deletions
|
|
@ -130,9 +130,10 @@ void WorldSession::HandleCharEnum(QueryResult * result)
|
|||
Player *plr = new Player(this);
|
||||
do
|
||||
{
|
||||
sLog.outDetail("Loading char guid %u from account %u.",(*result)[0].GetUInt32(),GetAccountId());
|
||||
uint32 guidlow = (*result)[0].GetUInt32();
|
||||
sLog.outDetail("Loading char guid %u from account %u.",guidlow,GetAccountId());
|
||||
|
||||
if(plr->MinimalLoadFromDB( result, (*result)[0].GetUInt32() ))
|
||||
if(plr->MinimalLoadFromDB( result, guidlow ))
|
||||
{
|
||||
plr->BuildEnumData( result, &data );
|
||||
++num;
|
||||
|
|
@ -155,18 +156,18 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
|
|||
CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(),
|
||||
!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ?
|
||||
// ------- Query Without Declined Names --------
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
"SELECT characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, characters.at_login, "
|
||||
// 9 10 11
|
||||
"character_pet.entry, character_pet.modelid, character_pet.level "
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
|
||||
// 9 10 11 12
|
||||
"characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level "
|
||||
"FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='0' "
|
||||
"WHERE characters.account = '%u' ORDER BY characters.guid"
|
||||
:
|
||||
// --------- Query With Declined Names ---------
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
"SELECT characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, characters.at_login, "
|
||||
// 9 10 11 12
|
||||
"character_pet.entry, character_pet.modelid, character_pet.level, genitive "
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
|
||||
// 9 10 11 12 13
|
||||
"characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, genitive "
|
||||
"FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='0' "
|
||||
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
|
||||
"WHERE characters.account = '%u' ORDER BY characters.guid",
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "drunk", SEC_MODERATOR, false, &ChatHandler::HandleDrunkCommand, "", NULL },
|
||||
{ "standstate", SEC_GAMEMASTER, false, &ChatHandler::HandleStandStateCommand, "", NULL },
|
||||
{ "morph", SEC_GAMEMASTER, false, &ChatHandler::HandleMorphCommand, "", NULL },
|
||||
{ "gender", SEC_ADMINISTRATOR, false, &ChatHandler::HandleModifyGenderCommand, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
|
|
@ -379,6 +380,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL },
|
||||
{ "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL },
|
||||
{ "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL },
|
||||
{ "tame", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcTameCommand, "", NULL },
|
||||
|
||||
//{ TODO: fix or remove this commands
|
||||
{ "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNameCommand, "", NULL },
|
||||
|
|
|
|||
|
|
@ -170,6 +170,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);
|
||||
|
|
@ -186,6 +187,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);
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
|
|||
SetAttackTime(OFF_ATTACK, GetCreatureInfo()->baseattacktime);
|
||||
SetAttackTime(RANGED_ATTACK,GetCreatureInfo()->rangeattacktime);
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS,GetCreatureInfo()->Flags);
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS,GetCreatureInfo()->unit_flags);
|
||||
SetUInt32Value(UNIT_DYNAMIC_FLAGS,GetCreatureInfo()->dynamicflags);
|
||||
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->armor));
|
||||
|
|
|
|||
|
|
@ -165,9 +165,9 @@ struct CreatureInfo
|
|||
uint32 attackpower;
|
||||
uint32 baseattacktime;
|
||||
uint32 rangeattacktime;
|
||||
uint32 Flags;
|
||||
uint32 unit_flags; // enum UnitFlags mask values
|
||||
uint32 dynamicflags;
|
||||
uint32 family;
|
||||
uint32 family; // enum CreatureFamily values for type==CREATURE_TYPE_BEAST, or 0 in another cases
|
||||
uint32 trainer_type;
|
||||
uint32 trainer_spell;
|
||||
uint32 classNum;
|
||||
|
|
@ -175,8 +175,8 @@ struct CreatureInfo
|
|||
float minrangedmg;
|
||||
float maxrangedmg;
|
||||
uint32 rangedattackpower;
|
||||
uint32 type;
|
||||
uint32 flag1;
|
||||
uint32 type; // enum CreatureType values
|
||||
uint32 type_flags; // enum CreatureTypeFlags mask values
|
||||
uint32 lootid;
|
||||
uint32 pickpocketLootId;
|
||||
uint32 SkinLootId;
|
||||
|
|
@ -202,6 +202,22 @@ struct CreatureInfo
|
|||
uint32 MechanicImmuneMask;
|
||||
uint32 flags_extra;
|
||||
char const* ScriptName;
|
||||
|
||||
// helpers
|
||||
SkillType GetRequiredLootSkill() const
|
||||
{
|
||||
if(type_flags & CREATURE_TYPEFLAGS_HERBLOOT)
|
||||
return SKILL_HERBALISM;
|
||||
else if(type_flags & CREATURE_TYPEFLAGS_MININGLOOT)
|
||||
return SKILL_MINING;
|
||||
else
|
||||
return SKILL_SKINNING; // normal case
|
||||
}
|
||||
|
||||
bool isTameable() const
|
||||
{
|
||||
return type == CREATURE_TYPE_BEAST && family != 0 && (type_flags & CREATURE_TYPEFLAGS_TAMEBLE);
|
||||
}
|
||||
};
|
||||
|
||||
struct CreatureLocale
|
||||
|
|
|
|||
|
|
@ -324,7 +324,9 @@ enum MangosStrings
|
|||
LANG_CREATURE_FOLLOW_YOU_NOW = 340,
|
||||
LANG_CREATURE_NOT_FOLLOW_YOU = 341,
|
||||
LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342,
|
||||
// Room for more level 2 343-399 not used
|
||||
LANG_CREATURE_NON_TAMEABLE = 343,
|
||||
LANG_YOU_ALREADY_HAVE_PET = 344,
|
||||
// Room for more level 2 345-399 not used
|
||||
|
||||
// level 3 chat
|
||||
LANG_SCRIPTS_RELOADED = 400,
|
||||
|
|
@ -674,8 +676,8 @@ enum MangosStrings
|
|||
// Room for more level 4 1012-1099 not used
|
||||
|
||||
// Level 3 (continue)
|
||||
LANG_MOTD_NEW = 1100,
|
||||
LANG_ACCOUNT_SETADDON = 1101,
|
||||
LANG_ACCOUNT_SETADDON = 1100,
|
||||
LANG_MOTD_NEW = 1101,
|
||||
LANG_SENDMESSAGE = 1102,
|
||||
LANG_EVENT_ENTRY_LIST_CONSOLE = 1103,
|
||||
LANG_CREATURE_ENTRY_LIST_CONSOLE = 1104,
|
||||
|
|
@ -693,7 +695,10 @@ enum MangosStrings
|
|||
LANG_INVALID_CHARACTER_GUID = 1116,
|
||||
LANG_CHARACTER_GUID_IN_USE = 1117,
|
||||
LANG_ITEMLIST_GUILD = 1118,
|
||||
// Room for more level 3 1119-1199 not used
|
||||
LANG_MUST_MALE_OR_FEMALE = 1119,
|
||||
LANG_YOU_CHANGE_GENDER = 1120,
|
||||
LANG_YOUR_GENDER_CHANGED = 1121,
|
||||
// Room for more level 3 1122-1199 not used
|
||||
|
||||
// FREE IDS 1200-9999
|
||||
|
||||
|
|
|
|||
|
|
@ -1794,7 +1794,8 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
|
|||
else
|
||||
{
|
||||
accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
|
||||
Player plr(m_session); // use current session for temporary load
|
||||
WorldSession session(0,NULL,SEC_PLAYER,0,0,LOCALE_enUS);
|
||||
Player plr(&session); // use fake session for temporary load
|
||||
plr.MinimalLoadFromDB(NULL, targetGUID);
|
||||
money = plr.GetMoney();
|
||||
total_player_time = plr.GetTotalPlayedTime();
|
||||
|
|
@ -4155,3 +4156,67 @@ bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
|
|||
PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleNpcTameCommand(const char* args)
|
||||
{
|
||||
Creature *creatureTarget = getSelectedCreature ();
|
||||
if (!creatureTarget || creatureTarget->isPet ())
|
||||
{
|
||||
PSendSysMessage (LANG_SELECT_CREATURE);
|
||||
SetSentErrorMessage (true);
|
||||
return false;
|
||||
}
|
||||
|
||||
Player *player = m_session->GetPlayer ();
|
||||
|
||||
if(player->GetPetGUID ())
|
||||
{
|
||||
SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
|
||||
SetSentErrorMessage (true);
|
||||
return false;
|
||||
}
|
||||
|
||||
CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
|
||||
|
||||
if (!cInfo->isTameable ())
|
||||
{
|
||||
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
|
||||
SetSentErrorMessage (true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything looks OK, create new pet
|
||||
Pet* pet = player->CreateTamedPetFrom (creatureTarget);
|
||||
if (!pet)
|
||||
{
|
||||
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
|
||||
SetSentErrorMessage (true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// place pet before player
|
||||
float x,y,z;
|
||||
player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
|
||||
pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
|
||||
|
||||
// set pet to defensive mode by default (some classes can't control contolled pets in fact).
|
||||
pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
|
||||
|
||||
|
||||
// prepare visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
|
||||
|
||||
// add to world
|
||||
MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
|
||||
|
||||
// visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
|
||||
|
||||
// caster have pet now
|
||||
player->SetPet(pet);
|
||||
|
||||
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||
player->PetSpellInitialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5317,9 +5317,11 @@ bool ChatHandler::HandleBanListIPCommand(const char* args)
|
|||
|
||||
bool ChatHandler::HandleRespawnCommand(const char* /*args*/)
|
||||
{
|
||||
Unit* target = getSelectedUnit();
|
||||
Player* pl = m_session->GetPlayer();
|
||||
|
||||
if(target)
|
||||
// accept only explictly selected target (not implicitly self targeting case)
|
||||
Unit* target = getSelectedUnit();
|
||||
if(pl->GetSelection() && target)
|
||||
{
|
||||
if(target->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
|
|
@ -5333,8 +5335,6 @@ bool ChatHandler::HandleRespawnCommand(const char* /*args*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
Player* pl = m_session->GetPlayer();
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
|
@ -6157,3 +6157,63 @@ bool ChatHandler::HandleSendMessageCommand(const char* args)
|
|||
PSendSysMessage(LANG_SENDMESSAGE,name.c_str(),msg_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleModifyGenderCommand(const char *args)
|
||||
{
|
||||
if(!*args)
|
||||
return false;
|
||||
|
||||
Player *player = getSelectedPlayer();
|
||||
|
||||
if(!player)
|
||||
{
|
||||
PSendSysMessage(LANG_NO_PLAYER);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
char const* gender_str = (char*)args;
|
||||
int gender_len = strlen(gender_str);
|
||||
|
||||
uint32 displayId = player->GetNativeDisplayId();
|
||||
char const* gender_full = NULL;
|
||||
uint32 new_displayId = displayId;
|
||||
Gender gender;
|
||||
|
||||
if(!strncmp(gender_str,"male",gender_len)) // MALE
|
||||
{
|
||||
if(player->getGender() == GENDER_MALE)
|
||||
return true;
|
||||
|
||||
gender_full = "male";
|
||||
new_displayId = player->getRace() == RACE_BLOODELF ? displayId+1 : displayId-1;
|
||||
gender = GENDER_MALE;
|
||||
}
|
||||
else if (!strncmp(gender_str,"female",gender_len)) // FEMALE
|
||||
{
|
||||
if(player->getGender() == GENDER_FEMALE)
|
||||
return true;
|
||||
|
||||
gender_full = "female";
|
||||
new_displayId = player->getRace() == RACE_BLOODELF ? displayId-1 : displayId+1;
|
||||
gender = GENDER_FEMALE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendSysMessage(LANG_MUST_MALE_OR_FEMALE);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set gender
|
||||
player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender);
|
||||
|
||||
// Change display ID
|
||||
player->SetDisplayId(new_displayId);
|
||||
player->SetNativeDisplayId(new_displayId);
|
||||
|
||||
PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(),gender_full);
|
||||
if (needReportToTarget(player))
|
||||
ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full,GetName());
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1311,7 +1311,7 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
|
|||
char_flags |= CHARACTER_FLAG_RENAME;
|
||||
// always send the flag if declined names aren't used
|
||||
// to let the client select a default method of declining the name
|
||||
if(!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) || (result && result->Fetch()[12].GetCppString() != ""))
|
||||
if(!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) || (result && result->Fetch()[13].GetCppString() != ""))
|
||||
char_flags |= CHARACTER_FLAG_DECLINED;
|
||||
|
||||
*p_data << (uint32)char_flags; // character flags
|
||||
|
|
@ -1329,12 +1329,12 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
|
|||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 entry = fields[9].GetUInt32();
|
||||
uint32 entry = fields[10].GetUInt32();
|
||||
CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(entry);
|
||||
if(cInfo)
|
||||
{
|
||||
petDisplayId = fields[10].GetUInt32();
|
||||
petLevel = fields[11].GetUInt32();
|
||||
petDisplayId = fields[11].GetUInt32();
|
||||
petLevel = fields[12].GetUInt32();
|
||||
petFamily = cInfo->family;
|
||||
}
|
||||
}
|
||||
|
|
@ -13506,15 +13506,15 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )
|
|||
bool delete_result = true;
|
||||
if(!result)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
result = CharacterDatabase.PQuery("SELECT data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login FROM characters WHERE guid = '%u'",guid);
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
result = CharacterDatabase.PQuery("SELECT guid, data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login FROM characters WHERE guid = '%u'",guid);
|
||||
if(!result) return false;
|
||||
}
|
||||
else delete_result = false;
|
||||
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
if(!LoadValues( fields[0].GetString()))
|
||||
if(!LoadValues( fields[1].GetString()))
|
||||
{
|
||||
sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid));
|
||||
if(delete_result) delete result;
|
||||
|
|
@ -13524,16 +13524,16 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )
|
|||
// overwrite possible wrong/corrupted guid
|
||||
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
|
||||
|
||||
m_name = fields[1].GetCppString();
|
||||
m_name = fields[2].GetCppString();
|
||||
|
||||
Relocate(fields[2].GetFloat(),fields[3].GetFloat(),fields[4].GetFloat());
|
||||
SetMapId(fields[5].GetUInt32());
|
||||
Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat());
|
||||
SetMapId(fields[6].GetUInt32());
|
||||
// the instance id is not needed at character enum
|
||||
|
||||
m_Played_time[0] = fields[6].GetUInt32();
|
||||
m_Played_time[1] = fields[7].GetUInt32();
|
||||
m_Played_time[0] = fields[7].GetUInt32();
|
||||
m_Played_time[1] = fields[8].GetUInt32();
|
||||
|
||||
m_atLoginFlags = fields[8].GetUInt32();
|
||||
m_atLoginFlags = fields[9].GetUInt32();
|
||||
|
||||
// I don't see these used anywhere ..
|
||||
/*_LoadGroup();
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
|
|||
data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
|
||||
data << SubName;
|
||||
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
|
||||
data << (uint32)ci->flag1; // flags wdbFeild7=wad flags1
|
||||
data << (uint32)ci->type_flags; // flags wdbFeild7=wad flags1
|
||||
data << (uint32)ci->type;
|
||||
data << (uint32)ci->family; // family wdbFeild9
|
||||
data << (uint32)ci->rank; // rank wdbFeild10
|
||||
|
|
|
|||
|
|
@ -1553,6 +1553,13 @@ enum CreatureFamily
|
|||
CREATURE_FAMILY_SPIRIT_BEAST = 46
|
||||
};
|
||||
|
||||
enum CreatureTypeFlags
|
||||
{
|
||||
CREATURE_TYPEFLAGS_TAMEBLE = 0x0001,
|
||||
CREATURE_TYPEFLAGS_HERBLOOT = 0x0100,
|
||||
CREATURE_TYPEFLAGS_MININGLOOT = 0x0200,
|
||||
};
|
||||
|
||||
enum CreatureEliteType
|
||||
{
|
||||
CREATURE_ELITE_NORMAL = 0,
|
||||
|
|
|
|||
|
|
@ -3569,12 +3569,8 @@ uint8 Spell::CanCast(bool strict)
|
|||
if (m_targets.getUnitTarget()->getLevel() > m_caster->getLevel())
|
||||
return SPELL_FAILED_HIGHLEVEL;
|
||||
|
||||
CreatureInfo const *cinfo = ((Creature*)m_targets.getUnitTarget())->GetCreatureInfo();
|
||||
if( cinfo->type != CREATURE_TYPE_BEAST )
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
// use SMSG_PET_TAME_FAILURE?
|
||||
if( !(cinfo->flag1 & 1) || !(cinfo->family) )
|
||||
if (!((Creature*)m_targets.getUnitTarget())->GetCreatureInfo()->isTameable ())
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
if(m_caster->GetPetGUID())
|
||||
|
|
@ -3674,13 +3670,7 @@ uint8 Spell::CanCast(bool strict)
|
|||
return SPELL_FAILED_TARGET_NOT_LOOTED;
|
||||
}
|
||||
|
||||
uint32 skill;
|
||||
if(creature->GetCreatureInfo()->flag1 & 256)
|
||||
skill = SKILL_HERBALISM; // special case
|
||||
else if(creature->GetCreatureInfo()->flag1 & 512)
|
||||
skill = SKILL_MINING; // special case
|
||||
else
|
||||
skill = SKILL_SKINNING; // normal case
|
||||
uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
|
||||
|
||||
int32 skillValue = ((Player*)m_caster)->GetSkillValue(skill);
|
||||
int32 TargetLevel = m_targets.getUnitTarget()->getLevel();
|
||||
|
|
|
|||
|
|
@ -3890,59 +3890,38 @@ void Spell::EffectTameCreature(uint32 /*i*/)
|
|||
if(creatureTarget->isPet())
|
||||
return;
|
||||
|
||||
if(m_caster->getClass() == CLASS_HUNTER)
|
||||
if(m_caster->getClass() != CLASS_HUNTER)
|
||||
return;
|
||||
|
||||
// cast finish successfully
|
||||
//SendChannelUpdate(0);
|
||||
finish();
|
||||
|
||||
Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
|
||||
|
||||
// kill original creature
|
||||
creatureTarget->setDeathState(JUST_DIED);
|
||||
creatureTarget->RemoveCorpse();
|
||||
creatureTarget->SetHealth(0); // just for nice GM-mode view
|
||||
|
||||
uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
|
||||
|
||||
// prepare visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
|
||||
|
||||
// add to world
|
||||
MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
|
||||
|
||||
// visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
|
||||
|
||||
// caster have pet now
|
||||
m_caster->SetPet(pet);
|
||||
|
||||
if(m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
// cast finish successfully
|
||||
//SendChannelUpdate(0);
|
||||
finish();
|
||||
|
||||
Pet* pet = new Pet(HUNTER_PET);
|
||||
|
||||
if(!pet->CreateBaseAtCreature(creatureTarget))
|
||||
{
|
||||
delete pet;
|
||||
return;
|
||||
}
|
||||
|
||||
creatureTarget->setDeathState(JUST_DIED);
|
||||
creatureTarget->RemoveCorpse();
|
||||
creatureTarget->SetHealth(0); // just for nice GM-mode view
|
||||
|
||||
pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
|
||||
pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
|
||||
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
|
||||
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
|
||||
uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
|
||||
pet->SetFreeTalentPoints(pet->GetMaxTalentPointsForLevel(level));
|
||||
|
||||
if(!pet->InitStatsForLevel(level))
|
||||
{
|
||||
sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted.");
|
||||
delete pet;
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
|
||||
|
||||
pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
|
||||
// this enables pet details window (Shift+P)
|
||||
pet->AIM_Initialize();
|
||||
pet->InitPetCreateSpells();
|
||||
pet->SetHealth(pet->GetMaxHealth());
|
||||
|
||||
MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
|
||||
|
||||
// visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
|
||||
|
||||
if(m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
m_caster->SetPet(pet);
|
||||
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||
((Player*)m_caster)->PetSpellInitialize();
|
||||
}
|
||||
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||
((Player*)m_caster)->PetSpellInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5584,13 +5563,7 @@ void Spell::EffectSkinning(uint32 /*i*/)
|
|||
Creature* creature = (Creature*) unitTarget;
|
||||
int32 targetLevel = creature->getLevel();
|
||||
|
||||
uint32 skill;
|
||||
if(creature->GetCreatureInfo()->flag1 & 256)
|
||||
skill = SKILL_HERBALISM; // special case
|
||||
else if(creature->GetCreatureInfo()->flag1 & 512)
|
||||
skill = SKILL_MINING; // special case
|
||||
else
|
||||
skill = SKILL_SKINNING; // normal case
|
||||
uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
|
||||
|
||||
((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
|
||||
creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
|
|
|
|||
|
|
@ -10863,3 +10863,37 @@ void Unit::RemovePetAura(PetAura const* petSpell)
|
|||
if(Pet* pet = GetPet())
|
||||
pet->RemoveAurasDueToSpell(petSpell->GetAura(pet->GetEntry()));
|
||||
}
|
||||
|
||||
Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
|
||||
{
|
||||
Pet* pet = new Pet(HUNTER_PET);
|
||||
|
||||
if(!pet->CreateBaseAtCreature(creatureTarget))
|
||||
{
|
||||
delete pet;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, this->GetGUID());
|
||||
pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, this->GetGUID());
|
||||
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,this->getFaction());
|
||||
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id);
|
||||
|
||||
uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
|
||||
pet->SetFreeTalentPoints(pet->GetMaxTalentPointsForLevel(level));
|
||||
|
||||
if(!pet->InitStatsForLevel(level))
|
||||
{
|
||||
sLog.outError("ERROR: Pet::InitStatsForLevel() failed for creature (Entry: %u)!",creatureTarget->GetEntry());
|
||||
delete pet;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
|
||||
// this enables pet details window (Shift+P)
|
||||
pet->AIM_Initialize();
|
||||
pet->InitPetCreateSpells();
|
||||
pet->SetHealth(pet->GetMaxHealth());
|
||||
|
||||
return pet;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1003,6 +1003,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
CharmInfo* GetCharmInfo() { return m_charmInfo; }
|
||||
CharmInfo* InitCharmInfo(Unit* charm);
|
||||
|
||||
Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0);
|
||||
|
||||
bool AddAura(Aura *aur);
|
||||
|
||||
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
||||
|
|
|
|||
|
|
@ -184,61 +184,61 @@ void World::AddSession(WorldSession* s)
|
|||
void
|
||||
World::AddSession_ (WorldSession* s)
|
||||
{
|
||||
ASSERT (s);
|
||||
ASSERT (s);
|
||||
|
||||
//NOTE - Still there is race condition in WorldSession* being used in the Sockets
|
||||
//NOTE - Still there is race condition in WorldSession* being used in the Sockets
|
||||
|
||||
///- kick already loaded player with same account (if any) and remove session
|
||||
///- if player is in loading and want to load again, return
|
||||
if (!RemoveSession (s->GetAccountId ()))
|
||||
///- kick already loaded player with same account (if any) and remove session
|
||||
///- if player is in loading and want to load again, return
|
||||
if (!RemoveSession (s->GetAccountId ()))
|
||||
{
|
||||
s->KickPlayer ();
|
||||
m_kicked_sessions.insert (s);
|
||||
return;
|
||||
s->KickPlayer ();
|
||||
m_kicked_sessions.insert (s);
|
||||
return;
|
||||
}
|
||||
|
||||
WorldSession* old = m_sessions[s->GetAccountId ()];
|
||||
m_sessions[s->GetAccountId ()] = s;
|
||||
WorldSession* old = m_sessions[s->GetAccountId ()];
|
||||
m_sessions[s->GetAccountId ()] = s;
|
||||
|
||||
// if session already exist, prepare to it deleting at next world update
|
||||
// NOTE - KickPlayer() should be called on "old" in RemoveSession()
|
||||
if (old)
|
||||
m_kicked_sessions.insert (old);
|
||||
// if session already exist, prepare to it deleting at next world update
|
||||
// NOTE - KickPlayer() should be called on "old" in RemoveSession()
|
||||
if (old)
|
||||
m_kicked_sessions.insert (old);
|
||||
|
||||
uint32 Sessions = GetActiveAndQueuedSessionCount ();
|
||||
uint32 pLimit = GetPlayerAmountLimit ();
|
||||
uint32 QueueSize = GetQueueSize (); //number of players in the queue
|
||||
bool inQueue = false;
|
||||
//so we don't count the user trying to
|
||||
//login as a session and queue the socket that we are using
|
||||
--Sessions;
|
||||
uint32 Sessions = GetActiveAndQueuedSessionCount ();
|
||||
uint32 pLimit = GetPlayerAmountLimit ();
|
||||
uint32 QueueSize = GetQueueSize (); //number of players in the queue
|
||||
bool inQueue = false;
|
||||
//so we don't count the user trying to
|
||||
//login as a session and queue the socket that we are using
|
||||
--Sessions;
|
||||
|
||||
if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
|
||||
if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
|
||||
{
|
||||
AddQueuedPlayer (s);
|
||||
UpdateMaxSessionCounters ();
|
||||
sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
|
||||
return;
|
||||
AddQueuedPlayer (s);
|
||||
UpdateMaxSessionCounters ();
|
||||
sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
|
||||
packet << uint8 (AUTH_OK);
|
||||
packet << uint32 (0); // unknown random value...
|
||||
packet << uint8 (0);
|
||||
packet << uint32 (0);
|
||||
packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
|
||||
s->SendPacket (&packet);
|
||||
WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
|
||||
packet << uint8 (AUTH_OK);
|
||||
packet << uint32 (0); // unknown random value...
|
||||
packet << uint8 (0);
|
||||
packet << uint32 (0);
|
||||
packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
|
||||
s->SendPacket (&packet);
|
||||
|
||||
UpdateMaxSessionCounters ();
|
||||
UpdateMaxSessionCounters ();
|
||||
|
||||
// Updates the population
|
||||
if (pLimit > 0)
|
||||
// Updates the population
|
||||
if (pLimit > 0)
|
||||
{
|
||||
float popu = GetActiveSessionCount (); // updated number of users on the server
|
||||
popu /= pLimit;
|
||||
popu *= 2;
|
||||
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
sLog.outDetail ("Server Population (%f).", popu);
|
||||
float popu = GetActiveSessionCount (); //updated number of users on the server
|
||||
popu /= pLimit;
|
||||
popu *= 2;
|
||||
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
sLog.outDetail ("Server Population (%f).", popu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2420,7 +2420,10 @@ void World::UpdateSessions( time_t diff )
|
|||
|
||||
///- Delete kicked sessions at add new session
|
||||
for (std::set<WorldSession*>::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr)
|
||||
{
|
||||
RemoveQueuedPlayer (*itr);
|
||||
delete *itr;
|
||||
}
|
||||
m_kicked_sessions.clear();
|
||||
|
||||
///- Then send an update signal to remaining ones
|
||||
|
|
|
|||
|
|
@ -58,25 +58,23 @@ _logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyL
|
|||
WorldSession::~WorldSession()
|
||||
{
|
||||
///- unload player if not unloaded
|
||||
if(_player)
|
||||
LogoutPlayer(true);
|
||||
if (_player)
|
||||
LogoutPlayer (true);
|
||||
|
||||
/// - If have unclosed socket, close it
|
||||
if (m_Socket)
|
||||
if (m_Socket)
|
||||
{
|
||||
m_Socket->CloseSocket ();
|
||||
m_Socket->RemoveReference ();
|
||||
m_Socket = NULL;
|
||||
m_Socket->CloseSocket ();
|
||||
m_Socket->RemoveReference ();
|
||||
m_Socket = NULL;
|
||||
}
|
||||
|
||||
///- empty incoming packet queue
|
||||
while(!_recvQueue.empty())
|
||||
{
|
||||
WorldPacket *packet = _recvQueue.next();
|
||||
WorldPacket *packet = _recvQueue.next ();
|
||||
delete packet;
|
||||
}
|
||||
|
||||
sWorld.RemoveQueuedPlayer(this);
|
||||
}
|
||||
|
||||
void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue