Merge commit 'origin/master' into 303

Conflicts:
	src/game/SpellEffects.cpp
	src/game/World.cpp
This commit is contained in:
tomrus88 2008-11-01 08:10:24 +03:00
commit cffc766fb6
31 changed files with 415 additions and 168 deletions

18
contrib/extractor/.gitignore vendored Normal file
View file

@ -0,0 +1,18 @@
#
# NOTE! Don't add files that are generated in specific
# subdirectories here. Add them in the ".gitignore" file
# in that subdirectory instead.
#
# NOTE! Please use 'git-ls-files -i --exclude-standard'
# command after changing this file, to see if there are
# any tracked files which get ignored after the change.
#
# Extractor generated files at Windows build
#
*.bsc
*.ncb
*.suo
debug
release
*.user

View file

@ -49,6 +49,12 @@
#include <io.h>
#endif
#ifdef O_LARGEFILE
#define MPQ_FILE_OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
#else
#define MPQ_FILE_OPEN_FLAGS (O_RDONLY | O_BINARY)
#endif
#ifndef min
#define min(a, b) ((a < b) ? a : b)
#endif

View file

@ -59,7 +59,7 @@ int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
memset(mpq_a->header, 0, sizeof(mpq_header));
/* Check if file exists and is readable */
fd = _open((char *)mpq_filename, O_RDONLY | O_BINARY | O_LARGEFILE);
fd = _open((char *)mpq_filename, MPQ_FILE_OPEN_FLAGS);
if (fd == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}

16
contrib/vmap_extractor_v2/.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
#
# NOTE! Don't add files that are generated in specific
# subdirectories here. Add them in the ".gitignore" file
# in that subdirectory instead.
#
# NOTE! Please use 'git-ls-files -i --exclude-standard'
# command after changing this file, to see if there are
# any tracked files which get ignored after the change.
#
# MaNGOS generated files at Windows build
#
*.ncb
*.suo
*.user
bin

View file

@ -303,6 +303,7 @@ INSERT INTO `command` VALUES
('modify drunk',1,'Syntax: .modify drunk #value\r\n Set drunk level to #value (0..100). Value 0 remove drunk state, 100 is max drunked state.'),
('modify energy',1,'Syntax: .modify energy #energy\r\n\r\nModify the energy of the selected player. If no player is selected, modify your energy.'),
('modify faction',1,'Syntax: .modify faction #factionid #flagid #npcflagid #dynamicflagid\r\n\r\nModify the faction and flags of the selected creature. Without arguments, display the faction and flags of the selected creature.'),
('modify gender',2,'Syntax: .modify gender male/female\r\n\r\nChange gender of selected player.'),
('modify honor',1,'Syntax: .modify honor $amount\r\n\r\nAdd $amount honor points to the selected player.'),
('modify hp',1,'Syntax: .modify hp #newhp\r\n\r\nModify the hp of the selected player. If no player is selected, modify your hp.'),
('modify mana',1,'Syntax: .modify mana #newmana\r\n\r\nModify the mana of the selected player. If no player is selected, modify your mana.'),
@ -340,6 +341,7 @@ INSERT INTO `command` VALUES
('npc spawndist',2,'Syntax: .npc spawndist #dist\r\n\r\nAdjust spawndistance of selected creature to dist.'),
('npc spawntime',2,'Syntax: .npc spawntime #time \r\n\r\nAdjust spawntime of selected creature to time.'),
('npc subname',2,'Syntax: .npc subname $Name\r\n\r\nChange the subname of the selected creature or player to $Name.\r\n\r\nCommand disabled.'),
('npc tame',2,'Syntax: .npc tame\r\n\r\nTame selected creature (tameable non pet creature). You don''t must have pet.'),
('npc textemote',3,'Syntax: .npc textemote #emoteid\r\n\r\nMake the selected creature to do textemote with an emote of id #emoteid.'),
('npc whisper',1,'Syntax: .npc whisper #playerguid #text\r\nMake the selected npc whisper #text to #playerguid.'),
('npc unfollow',2,'Syntax: .npc unfollow\r\n\r\nSelected creature (non pet) stop follow you.'),
@ -711,7 +713,7 @@ CREATE TABLE `creature_template` (
`attackpower` int(10) unsigned NOT NULL default '0',
`baseattacktime` int(10) unsigned NOT NULL default '0',
`rangeattacktime` int(10) unsigned NOT NULL default '0',
`flags` int(10) unsigned NOT NULL default '0',
`unit_flags` int(10) unsigned NOT NULL default '0',
`dynamicflags` int(10) unsigned NOT NULL default '0',
`family` tinyint(4) NOT NULL default '0',
`trainer_type` tinyint(4) NOT NULL default '0',
@ -722,7 +724,7 @@ CREATE TABLE `creature_template` (
`maxrangedmg` float NOT NULL default '0',
`rangedattackpower` smallint(5) unsigned NOT NULL default '0',
`type` tinyint(3) unsigned NOT NULL default '0',
`flag1` int(10) unsigned NOT NULL default '0',
`type_flags` int(10) unsigned NOT NULL default '0',
`lootid` mediumint(8) unsigned NOT NULL default '0',
`pickpocketloot` mediumint(8) unsigned NOT NULL default '0',
`skinloot` mediumint(8) unsigned NOT NULL default '0',
@ -2415,6 +2417,8 @@ INSERT INTO `mangos_string` VALUES
(340,'%s is now following you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(341,'%s is not following you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(342,'%s is now not following you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(343,'Creature (Entry: %u) cannot be tamed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(344,'You already have pet.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2704,7 +2708,10 @@ INSERT INTO `mangos_string` VALUES
(1115,'Invalid character name!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1116,'Invalid character guid!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1117,'Character guid %u in use!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1118,'%d - guild: %s (guid: %u) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
(1118,'%d - guild: %s (guid: %u) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1119,'You must use male or female as gender.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1120,'You change gender of %s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
/*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */;
UNLOCK TABLES;

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_2008_10_29_05_mangos_command required_2008_10_31_01_mangos_creature_template bit;
ALTER TABLE `creature_template`
CHANGE COLUMN `flags` `unit_flags` int(10) unsigned NOT NULL default '0',
CHANGE COLUMN `flag1` `type_flags` int(10) unsigned NOT NULL default '0';

View file

@ -0,0 +1,7 @@
ALTER TABLE db_version CHANGE COLUMN required_2008_10_31_01_mangos_creature_template required_2008_10_31_02_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN (343,344);
INSERT INTO mangos_string VALUES
(343,'Creature (Entry: %u) cannot be tamed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(344,'You already have pet.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_2008_10_31_02_mangos_mangos_string required_2008_10_31_03_mangos_command bit;
DELETE FROM command WHERE name IN ('npc tame');
INSERT INTO command VALUES
('npc tame',2,'Syntax: .npc tame\r\n\r\nTame selected creature (tameable non pet creature). You don''t must have pet.');

View file

@ -0,0 +1,8 @@
ALTER TABLE db_version CHANGE COLUMN required_2008_10_31_03_mangos_command required_2008_11_01_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN (1119,1120,1121);
INSERT INTO mangos_string VALUES
(1119,'You must use male or female as gender.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1120,'You change gender of %s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_2008_11_01_01_mangos_mangos_string required_2008_11_01_02_mangos_command bit;
DELETE FROM command WHERE name IN ('modify gender');
INSERT INTO command VALUES
('modify gender',2,'Syntax: .modify gender male/female\r\n\r\nChange gender of selected player.');

View file

@ -107,8 +107,8 @@ pkgdata_DATA = \
2008_10_23_04_mangos_command.sql \
2008_10_23_05_mangos_command.sql \
2008_10_26_01_mangos_mangos_string.sql \
2008_10_27_01_npc_option.sql \
2008_10_27_02_locales_npc_option.sql \
2008_10_27_01_mangos_npc_option.sql \
2008_10_27_02_mangos_locales_npc_option.sql \
2008_10_28_01_mangos_mangos_string.sql \
2008_10_28_02_mangos_mangos_string.sql \
2008_10_28_03_mangos_command.sql \
@ -118,6 +118,11 @@ pkgdata_DATA = \
2008_10_29_03_mangos_db_version.sql \
2008_10_29_04_mangos_mangos_string.sql \
2008_10_29_05_mangos_command.sql \
2008_10_31_01_mangos_creature_template.sql \
2008_10_31_02_mangos_mangos_string.sql \
2008_10_31_03_mangos_command.sql \
2008_11_01_01_mangos_mangos_string.sql \
2008_11_01_02_mangos_command.sql \
README
## Additional files to include when running 'make dist'
@ -206,8 +211,8 @@ EXTRA_DIST = \
2008_10_23_04_mangos_command.sql \
2008_10_23_05_mangos_command.sql \
2008_10_26_01_mangos_mangos_string.sql \
2008_10_27_01_npc_option.sql \
2008_10_27_02_locales_npc_option.sql \
2008_10_27_01_mangos_npc_option.sql \
2008_10_27_02_mangos_locales_npc_option.sql \
2008_10_28_01_mangos_mangos_string.sql \
2008_10_28_02_mangos_mangos_string.sql \
2008_10_28_03_mangos_command.sql \
@ -217,4 +222,9 @@ EXTRA_DIST = \
2008_10_29_03_mangos_db_version.sql \
2008_10_29_04_mangos_mangos_string.sql \
2008_10_29_05_mangos_command.sql \
2008_10_31_01_mangos_creature_template.sql \
2008_10_31_02_mangos_mangos_string.sql \
2008_10_31_03_mangos_command.sql \
2008_11_01_01_mangos_mangos_string.sql \
2008_11_01_02_mangos_command.sql \
README

View file

@ -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",

View file

@ -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 },

View file

@ -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);

View file

@ -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));

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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();

View file

@ -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

View file

@ -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,

View file

@ -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();

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -284,7 +284,7 @@ LogFileLevel = 0
LogFilter_TransportMoves = 1
LogFilter_CreatureMoves = 1
LogFilter_VisibilityChanges = 1
WorldLogFile = "world.log"
WorldLogFile = ""
DBErrorLogFile = "DBErrors.log"
CharLogFile = "Char.log"
CharLogTimestamp = 0