diff --git a/sql/mangos.sql b/sql/mangos.sql index eece58437..5381bda91 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, - `required_7782_01_mangos_spell_proc_event` bit(1) default NULL + `required_7796_02_mangos_mangos_string` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -323,6 +323,7 @@ INSERT INTO `command` VALUES ('go graveyard',1,'Syntax: .go graveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'), ('go grid',1,'Syntax: .go grid #gridX #gridY [#mapId]\r\n\r\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'), ('go object',1,'Syntax: .go object #object_guid\r\nTeleport your character to gameobject with guid #object_guid'), +('go taxinode',1,'Syntax: .go taxinode #taxinode\r\n\r\nTeleport player to taxinode coordinates. You can look up zone using .lookup taxinode $namepart'), ('go trigger',1,'Syntax: .go trigger #trigger_id\r\n\r\nTeleport your character to areatrigger with id #trigger_id. Character will be teleported to trigger target if selected areatrigger is telporting trigger.'), ('go xy',1,'Syntax: .go xy #x #y [#mapid]\r\n\r\nTeleport player to point with (#x,#y) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), ('go xyz',1,'Syntax: .go xyz #x #y #z [#mapid]\r\n\r\nTeleport player to point with (#x,#y,#z) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), @@ -385,6 +386,7 @@ INSERT INTO `command` VALUES ('lookup quest',3,'Syntax: .lookup quest $namepart\r\n\r\nLooks up a quest by $namepart, and returns all matches with their quest ID\'s.'), ('lookup skill',3,'Syntax: .lookup skill $$namepart\r\n\r\nLooks up a skill by $namepart, and returns all matches with their skill ID\'s.'), ('lookup spell',3,'Syntax: .lookup spell $namepart\r\n\r\nLooks up a spell by $namepart, and returns all matches with their spell ID\'s.'), +('lookup taxinode',3,'Syntax: .lookup taxinode $substring\r\n\r\nSearch and output all taxinodes with provide $substring in name.'), ('lookup tele',1,'Syntax: .lookup tele $substring\r\n\r\nSearch and output all .tele command locations with provide $substring in name.'), ('maxskill',3,'Syntax: .maxskill\r\nSets all skills of the targeted player to their maximum VALUESfor its current level.'), ('modify arena',1,'Syntax: .modify arena #value\r\nAdd $amount arena points to the selected player.'), @@ -2689,6 +2691,7 @@ INSERT INTO `mangos_string` VALUES (344,'You already have pet.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(347,'TaxiNode ID %u not found!',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), @@ -2754,6 +2757,7 @@ INSERT INTO `mangos_string` VALUES (463,'Teleport location added.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (464,'Teleport location NOT added: database error.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (465,'Teleport location deleted.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(466,'No taxinodes found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (467,'Target unit has %d auras:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (468,'id: %d eff: %d type: %d duration: %d maxduration: %d name: %s%s%s caster: %s %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (469,'Target unit has %d auras of type %d:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -3053,6 +3057,8 @@ INSERT INTO `mangos_string` VALUES (1125,'Your pet learned all talents',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1126,'Your pet talents have been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1127,'Talents of %s\'s pet reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1128,'%d - |cffffffff|Htaxinode:%u|h[%s %s]|h|r (Map:%u X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1129,'%d - %s %s (Map:%u X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1200,'You try to view cinemitic %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1201,'You try to view movie %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; diff --git a/sql/updates/7796_01_mangos_command.sql b/sql/updates/7796_01_mangos_command.sql new file mode 100644 index 000000000..0a5c7c342 --- /dev/null +++ b/sql/updates/7796_01_mangos_command.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_7782_01_mangos_spell_proc_event required_7796_01_mangos_command bit; + +DELETE FROM `command` WHERE `name` IN ('go taxinode','lookup taxinode'); + +INSERT INTO `command` VALUES +('go taxinode',1,'Syntax: .go taxinode #taxinode\r\n\r\nTeleport player to taxinode coordinates. You can look up zone using .lookup taxinode $namepart'), +('lookup taxinode',3,'Syntax: .lookup taxinode $substring\r\n\r\nSearch and output all taxinodes with provide $substring in name.'); diff --git a/sql/updates/7796_02_mangos_mangos_string.sql b/sql/updates/7796_02_mangos_mangos_string.sql new file mode 100644 index 000000000..ae47b9803 --- /dev/null +++ b/sql/updates/7796_02_mangos_mangos_string.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_7796_01_mangos_command required_7796_02_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN(347,466,1128,1129); +INSERT INTO mangos_string VALUES +(347,'TaxiNode ID %u not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(466,'No taxinodes found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1128,'%d - |cffffffff|Htaxinode:%u|h[%s %s]|h|r (Map:%u X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1129,'%d - %s %s (Map:%u X:%f Y:%f Z:%f)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 1973ed5de..c7e40654d 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -180,6 +180,8 @@ pkgdata_DATA = \ 7776_01_mangos_npc_spellclick_spells.sql \ 7777_01_mangos_spell_proc_event.sql \ 7782_01_mangos_spell_proc_event.sql \ + 7796_01_mangos_command.sql \ + 7796_02_mangos_mangos_string.sql \ README ## Additional files to include when running 'make dist' @@ -340,4 +342,6 @@ EXTRA_DIST = \ 7776_01_mangos_npc_spellclick_spells.sql \ 7777_01_mangos_spell_proc_event.sql \ 7782_01_mangos_spell_proc_event.sql \ + 7796_01_mangos_command.sql \ + 7796_02_mangos_mangos_string.sql \ README diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 361a31eaf..aac2fdcfa 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -752,7 +752,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { sLog.outDebug( "WORLD: Restart character %u taxi flight", pCurrChar->GetGUIDLow() ); - uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam()); + uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam(),true); uint32 path = pCurrChar->m_taxi.GetCurrentTaxiPath(); // search appropriate start path node diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index d48de4acb..92cc520b3 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -46,6 +46,7 @@ // |color|Hskill:skill_id|h[name]|h|r // |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click // |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click +// |color|Htaxinode:id|h[name]|h|r // |color|Htele:id|h[name]|h|r // |color|Htrade:spell_id,cur_value,max_value,unk3int,unk3str|h[name]|h|r - client, spellbook profession icon shift-click @@ -186,6 +187,7 @@ ChatCommand * ChatHandler::getCommandTable() { "graveyard", SEC_MODERATOR, false, &ChatHandler::HandleGoGraveyardCommand, "", NULL }, { "grid", SEC_MODERATOR, false, &ChatHandler::HandleGoGridCommand, "", NULL }, { "object", SEC_MODERATOR, false, &ChatHandler::HandleGoObjectCommand, "", NULL }, + { "taxinode", SEC_MODERATOR, false, &ChatHandler::HandleGoTaxinodeCommand, "", NULL }, { "trigger", SEC_MODERATOR, false, &ChatHandler::HandleGoTriggerCommand, "", NULL }, { "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL }, { "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL }, @@ -279,6 +281,7 @@ ChatCommand * ChatHandler::getCommandTable() { "player", SEC_GAMEMASTER, true, NULL, "", lookupPlayerCommandTable }, { "skill", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSkillCommand, "", NULL }, { "spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSpellCommand, "", NULL }, + { "taxinode", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupTaxiNodeCommand, "", NULL }, { "tele", SEC_MODERATOR, true, &ChatHandler::HandleLookupTeleCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; diff --git a/src/game/Chat.h b/src/game/Chat.h index 6e4a28261..43d2eb8a3 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -173,6 +173,7 @@ class ChatHandler bool HandleGoGraveyardCommand(const char* args); bool HandleGoGridCommand(const char* args); bool HandleGoObjectCommand(const char* args); + bool HandleGoTaxinodeCommand(const char* args); bool HandleGoTriggerCommand(const char* args); bool HandleGoXYCommand(const char* args); bool HandleGoXYZCommand(const char* args); @@ -223,6 +224,7 @@ class ChatHandler bool HandleLookupQuestCommand(const char* args); bool HandleLookupSkillCommand(const char* args); bool HandleLookupSpellCommand(const char* args); + bool HandleLookupTaxiNodeCommand(const char * args); bool HandleLookupTeleCommand(const char * args); bool HandleModifyKnownTitlesCommand(const char* args); diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 0b5f5a710..59f72ad86 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1510,7 +1510,7 @@ struct TaxiNodesEntry float x; // 2 m_x float y; // 3 m_y float z; // 4 m_z - //char* name[16]; // 5-21 m_Name_lang + char* name[16]; // 5-21 m_Name_lang // 22 string flags uint32 MountCreatureID[2]; // 23-24 m_MountCreatureID[2] }; diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index f4464e178..c2782f890 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -94,7 +94,7 @@ const char StableSlotPricesfmt[] = "ni"; //const char SummonPropertiesfmt[] = "niiiii"; const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; -const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii"; +const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii"; const char TaxiPathEntryfmt[]="niii"; const char TaxiPathNodeEntryfmt[]="diiifffiixx"; const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; diff --git a/src/game/Language.h b/src/game/Language.h index b08eff7c4..5b64cf570 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -332,7 +332,8 @@ enum MangosStrings LANG_YOU_ALREADY_HAVE_PET = 344, LANG_CUSTOMIZE_PLAYER = 345, LANG_CUSTOMIZE_PLAYER_GUID = 346, - // Room for more level 2 345-399 not used + LANG_COMMAND_GOTAXINODENOTFOUND = 347, + // Room for more level 2 348-399 not used // level 3 chat LANG_SCRIPTS_RELOADED = 400, @@ -407,8 +408,7 @@ enum MangosStrings LANG_COMMAND_TP_ADDED = 463, LANG_COMMAND_TP_ADDEDERR = 464, LANG_COMMAND_TP_DELETED = 465, - // 466, // not used - + LANG_COMMAND_NOTAXINODEFOUND = 466, LANG_COMMAND_TARGET_LISTAURAS = 467, LANG_COMMAND_TARGET_AURADETAIL = 468, LANG_COMMAND_TARGET_LISTAURATYPE = 469, @@ -764,7 +764,9 @@ enum MangosStrings LANG_COMMAND_LEARN_PET_TALENTS = 1125, LANG_RESET_PET_TALENTS = 1126, LANG_RESET_PET_TALENTS_ONLINE = 1127, - // Room for more level 3 1128-1199 not used + LANG_TAXINODE_ENTRY_LIST_CHAT = 1128, + LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129, + // Room for more level 3 1130-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 75a891abd..0d7e44510 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -2319,6 +2319,51 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) return true; } +bool ChatHandler::HandleGoTaxinodeCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char* cNodeId = extractKeyFromLink((char*)args,"Htaxinode"); + if (!cNodeId) + return false; + + int32 i_nodeId = atoi(cNodeId); + if (!i_nodeId) + return false; + + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i_nodeId); + if (!node) + { + PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND,i_nodeId); + SetSentErrorMessage(true); + return false; + } + + if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f || + !MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation()); + return true; +} + //teleport at coordinates bool ChatHandler::HandleGoXYCommand(const char* args) { diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 04e1e08d2..2cccc2e56 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3085,6 +3085,68 @@ bool ChatHandler::HandleLookupObjectCommand(const char* args) return true; } +bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) +{ + if(!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if(!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower( wnamepart ); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in TaxiNodes.dbc + for (uint32 id = 0; id < sTaxiNodesStore.GetNumRows(); id++) + { + TaxiNodesEntry const *nodeEntry = sTaxiNodesStore.LookupEntry(id); + if(nodeEntry) + { + int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + std::string name = nodeEntry->name[loc]; + if(name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for(; loc < MAX_LOCALE; ++loc) + { + if(m_session && loc==m_session->GetSessionDbcLocale()) + continue; + + name = nodeEntry->name[loc]; + if(name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if(loc < MAX_LOCALE) + { + // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format + if (m_session) + PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(),localeNames[loc], + nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); + else + PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), localeNames[loc], + nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOSPELLFOUND); + return true; +} + /** \brief GM command level 3 - Create a guild. * * This command allows a GM (level 3) to create a guild. diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 292acd88a..ab7017411 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4640,7 +4640,7 @@ void ObjectMgr::GetTaxiPath( uint32 source, uint32 destination, uint32 &path, ui path = dest_i->second.ID; } -uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) +uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team, bool allowed_alt_team /* = false */) { uint16 mount_entry = 0; uint16 mount_id = 0; @@ -4651,6 +4651,9 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) if (team == ALLIANCE) { mount_entry = node->MountCreatureID[1]; + if(!mount_entry && allowed_alt_team) + mount_entry = node->MountCreatureID[0]; + CreatureInfo const *ci = GetCreatureTemplate(mount_entry); if(ci) mount_id = ci->DisplayID_A; @@ -4658,6 +4661,10 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) if (team == HORDE) { mount_entry = node->MountCreatureID[0]; + + if(!mount_entry && allowed_alt_team) + mount_entry = node->MountCreatureID[1]; + CreatureInfo const *ci = GetCreatureTemplate(mount_entry); if(ci) mount_id = ci->DisplayID_H; diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index e28b5419e..4e4947ef0 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -398,7 +398,7 @@ class ObjectMgr uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team ); void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost); - uint16 GetTaxiMount( uint32 id, uint32 team ); + uint16 GetTaxiMount( uint32 id, uint32 team, bool allowed_alt_team = false); void GetTaxiPathNodes( uint32 path, Path &pathnodes, std::vector& mapIds ); void GetTransportPathNodes( uint32 path, TransportPath &pathnodes ); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 1fb45f80d..8010486d2 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -181,10 +181,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return true; } - if (getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)) - m_charmInfo->SetPetNumber(pet_number, true); - else - m_charmInfo->SetPetNumber(pet_number, false); + m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner)); SetOwnerGUID(owner->GetGUID()); SetDisplayId(fields[3].GetUInt32()); @@ -1744,6 +1741,27 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) } } +bool Pet::IsPermanentPetFor(Player* owner) +{ + switch(getPetType()) + { + case SUMMON_PET: + switch(owner->getClass()) + { + case CLASS_WARLOCK: + return GetCreatureInfo()->type == CREATURE_TYPE_DEMON; + case CLASS_DEATH_KNIGHT: + return GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD; + default: + return false; + } + case HUNTER_PET: + return true; + default: + return false; + } +} + bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) { SetMapId(map->GetId()); @@ -1794,10 +1812,10 @@ void Pet::LearnPetPassives() void Pet::CastPetAuras(bool current) { Unit* owner = GetOwner(); - if(!owner) + if(!owner || owner->GetTypeId()!=TYPEID_PLAYER) return; - if(getPetType() != HUNTER_PET && (getPetType() != SUMMON_PET || owner->getClass() != CLASS_WARLOCK)) + if(!IsPermanentPetFor((Player*)owner)) return; for(PetAuraSet::const_iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();) diff --git a/src/game/Pet.h b/src/game/Pet.h index e3be2c4ed..e88576438 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -119,6 +119,8 @@ typedef std::vector AutoSpellList; #define PET_FOLLOW_DIST 1 #define PET_FOLLOW_ANGLE (M_PI/2) +class Player; + class Pet : public Creature { public: @@ -133,6 +135,8 @@ class Pet : public Creature bool isControlled() const { return getPetType()==SUMMON_PET || getPetType()==HUNTER_PET; } bool isTemporarySummoned() const { return m_duration > 0; } + bool IsPermanentPetFor(Player* owner); // pet have tab in character windows and set UNIT_FIELD_PETNUMBER + bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number); bool CreateBaseAtCreature(Creature* creature); bool LoadPetFromDB( Player* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false ); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f74cf85f3..c21167126 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -223,7 +223,7 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values, uint } // can't load taxi path without mount set (quest taxi path?) - if(!objmgr.GetTaxiMount(GetTaxiSource(),team)) + if(!objmgr.GetTaxiMount(GetTaxiSource(),team,true)) return false; return true; @@ -1454,7 +1454,7 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) uint32 petFamily = 0; // show pet at selection character in character list only for non-ghost character - if(result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER)) + if (result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT)) { uint32 entry = fields[10].GetUInt32(); CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); @@ -16270,7 +16270,7 @@ void Player::PetSpellInitialize() uint8 addlist = 0; data << uint8(addlist); // placeholder - if(pet->isControlled() && ((pet->getPetType() == HUNTER_PET) || ((pet->GetCreatureInfo()->type == CREATURE_TYPE_DEMON) && (getClass() == CLASS_WARLOCK)))) + if (pet->IsPermanentPetFor(this)) { // spells loop for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) @@ -16643,34 +16643,13 @@ void Player::HandleStealthedUnitsDetection() } } -bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_id, Creature* npc) +bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc /*= NULL*/, uint32 spellid /*= 0*/) { if(nodes.size() < 2) return false; - // not let cheating with start flight mounted - if(IsMounted()) - { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIPLAYERALREADYMOUNTED); - GetSession()->SendPacket(&data); - return false; - } - - if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW ) - { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIPLAYERSHAPESHIFTED); - GetSession()->SendPacket(&data); - return false; - } - // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi - if(GetSession()->isLogingOut() || - (!m_currentSpells[CURRENT_GENERIC_SPELL] || - m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Effect[0] != SPELL_EFFECT_SEND_TAXI)&& - IsNonMeleeSpellCasted(false) || - isInCombat()) + if(GetSession()->isLogingOut() || isInCombat()) { WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); data << uint32(ERR_TAXIPLAYERBUSY); @@ -16681,6 +16660,52 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_i if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) return false; + // taximaster case + if(npc) + { + // not let cheating with start flight mounted + if(IsMounted()) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIPLAYERALREADYMOUNTED); + GetSession()->SendPacket(&data); + return false; + } + + if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW ) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIPLAYERSHAPESHIFTED); + GetSession()->SendPacket(&data); + return false; + } + + // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi + if(IsNonMeleeSpellCasted(false)) + { + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(ERR_TAXIPLAYERBUSY); + GetSession()->SendPacket(&data); + return false; + } + } + // cast case or scripted call case + else + { + RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW ) + RemoveAurasDueToSpell(m_ShapeShiftFormSpellId); + + if(m_currentSpells[CURRENT_GENERIC_SPELL] && m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id != spellid) + InterruptSpell(CURRENT_GENERIC_SPELL,false); + + InterruptSpell(CURRENT_AUTOREPEAT_SPELL,false); + + if(m_currentSpells[CURRENT_CHANNELED_SPELL] && m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id != spellid) + InterruptSpell(CURRENT_CHANNELED_SPELL,true); + } + uint32 sourcenode = nodes[0]; // starting node too far away (cheat?) @@ -16708,8 +16733,8 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_i return false; } } - // node must have pos if not spell case (npc!=0) - else if(npc) + // node must have pos if taxi master case (npc != NULL) + else if (npc) { WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); @@ -16761,10 +16786,11 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_i prevnode = lastnode; } - if(!mount_id) // if not provide then attempt use default. - mount_id = objmgr.GetTaxiMount(sourcenode, GetTeam()); + // get mount model (in case non taximaster (npc==NULL) allow more wide lookup) + uint16 mount_id = objmgr.GetTaxiMount(sourcenode, GetTeam(), npc == NULL); - if (mount_id == 0 || sourcepath == 0) + // in spell case allow 0 model + if (mount_id == 0 && spellid == 0 || sourcepath == 0) { WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); @@ -16806,6 +16832,21 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_i return true; } +bool Player::ActivateTaxiPathTo( uint32 taxi_path_id, uint32 spellid /*= 0*/ ) +{ + TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(taxi_path_id); + if(!entry) + return false; + + std::vector nodes; + + nodes.resize(2); + nodes[0] = entry->from; + nodes[1] = entry->to; + + return ActivateTaxiPathTo(nodes,NULL,spellid); +} + void Player::ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ) { // last check 2.0.10 diff --git a/src/game/Player.h b/src/game/Player.h index d30c2be6e..4fcd662af 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -912,7 +912,8 @@ class MANGOS_DLL_SPEC Player : public Unit PlayerTaxi m_taxi; void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); } - bool ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_id = 0 , Creature* npc = NULL); + bool ActivateTaxiPathTo(std::vector const& nodes, Creature* npc = NULL, uint32 spellid = 0); + bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0); // mount_id can be used in scripting calls bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); } void SetAcceptTicket(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_GM_ACCEPT_TICKETS; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_ACCEPT_TICKETS; } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 296fe6a4a..eaf50a2cb 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1058,9 +1058,10 @@ enum SpellHitType { SPELL_HIT_TYPE_UNK1 = 0x00001, SPELL_HIT_TYPE_CRIT = 0x00002, - SPELL_HIT_TYPE_UNK2 = 0x00004, - SPELL_HIT_TYPE_UNK3 = 0x00008, - SPELL_HIT_TYPE_UNK4 = 0x00020 + SPELL_HIT_TYPE_UNK3 = 0x00004, + SPELL_HIT_TYPE_UNK4 = 0x00008, + SPELL_HIT_TYPE_UNK5 = 0x00010, // replace caster? + SPELL_HIT_TYPE_UNK6 = 0x00020 }; enum SpellDmgClass diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 40af5ed29..12b7ebfb9 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -613,6 +613,7 @@ void Spell::FillTargetMap() case SPELL_EFFECT_SUMMON_OBJECT_WILD: case SPELL_EFFECT_SELF_RESURRECT: case SPELL_EFFECT_REPUTATION: + case SPELL_EFFECT_SEND_TAXI: if(m_targets.getUnitTarget()) tmpUnitMap.push_back(m_targets.getUnitTarget()); // Triggered spells have additional spell targets - cast them even if no explicit unit target is given (required for spell 50516 for example) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 52fbf1644..09f28fe29 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -194,7 +194,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE - &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes + &Aura::HandleAuraSafeFall, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY @@ -6834,3 +6834,12 @@ void Aura::UnregisterSingleCastAura() m_isSingleTargetAura = false; } } + +void Aura::HandleAuraSafeFall( bool Apply, bool Real ) +{ + // implemented in WorldSession::HandleMovementOpcodes + + // only special case + if(Apply && Real && GetId()==32474 && m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->ActivateTaxiPathTo(506,GetId()); +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index da920425c..a691c7535 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -104,6 +104,7 @@ class MANGOS_DLL_SPEC Aura void HandlePeriodicTriggerSpellWithValue(bool apply, bool Real); void HandlePeriodicEnergize(bool Apply, bool Real); void HandleAuraModResistanceExclusive(bool Apply, bool Real); + void HandleAuraSafeFall(bool Apply, bool Real); void HandleAuraModPetTalentsPoints(bool Apply, bool Real); void HandleModStealth(bool Apply, bool Real); void HandleInvisibility(bool Apply, bool Real); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index fc794a57e..9f15c3e0d 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -6045,43 +6045,7 @@ void Spell::EffectSendTaxi(uint32 i) if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]); - if(!entry) - return; - - std::vector nodes; - - nodes.resize(2); - nodes[0] = entry->from; - nodes[1] = entry->to; - - uint32 mountid = 0; - switch(m_spellInfo->Id) - { - case 31606: //Stormcrow Amulet - mountid = 17447; - break; - case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run - case 45113: //Quest - Sunwell Daily - Ship Bombing Run - case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return - mountid = 22840; - break; - case 34905: //Stealth Flight - mountid = 6851; - break; - case 45883: //Amber Ledge to Beryl Point - mountid = 23524; - break; - case 46064: //Amber Ledge to Coldarra - mountid = 6371; - break; - case 53335: //Stormwind Harbor Flight - Peaceful - mountid = 6852; - break; - } - - ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid); - + ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id); } void Spell::EffectPlayerPull(uint32 i) @@ -6635,4 +6599,4 @@ void Spell::EffectRenamePet(uint32 /*eff_idx*/) return; unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); -} +} \ No newline at end of file diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 4fedb5afc..0450ccb52 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -126,7 +126,8 @@ void WorldSession::SendDoFlight( uint16 MountId, uint32 path, uint32 pathNode ) while(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) GetPlayer()->GetMotionMaster()->MovementExpired(false); - GetPlayer()->Mount( MountId ); + if (MountId) + GetPlayer()->Mount( MountId ); GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path,pathNode); } @@ -188,7 +189,7 @@ void WorldSession::HandleActivateTaxiFarOpcode ( WorldPacket & recv_data ) sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d" ,nodes.front(),nodes.back()); - GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc); + GetPlayer()->ActivateTaxiPathTo(nodes, npc); } void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& /*recv_data*/) @@ -273,5 +274,5 @@ void WorldSession::HandleActivateTaxiOpcode( WorldPacket & recv_data ) return; } - GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc); + GetPlayer()->ActivateTaxiPathTo(nodes, npc); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index ba593a931..0ecec6272 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4205,37 +4205,31 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log) data.append(log->target->GetPackGUID()); data.append(log->attacker->GetPackGUID()); data << uint32(log->SpellID); - data << uint32(log->damage); //damage amount - data << uint32(0); - data << uint8 (log->schoolMask); //damage school - data << uint32(log->absorb); //AbsorbedDamage - data << uint32(log->resist); //resist - data << uint8 (log->phusicalLog); // damsge type? flag - data << uint8 (log->unused); //unused - data << uint32(log->blocked); //blocked + data << uint32(log->damage); // damage amount + data << uint32(log->overkill); // overkill + data << uint8 (log->schoolMask); // damage school + data << uint32(log->absorb); // AbsorbedDamage + data << uint32(log->resist); // resist + data << uint8 (log->physicalLog); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name + data << uint8 (log->unused); // unused + data << uint32(log->blocked); // blocked data << uint32(log->HitInfo); - data << uint8 (0); // flag to use extend data + data << uint8 (0); // flag to use extend data SendMessageToSet( &data, true ); } void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit) { - sLog.outDebug("Sending: SMSG_SPELLNONMELEEDAMAGELOG"); - WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16+4+4+1+4+4+1+1+4+4+1)); // we guess size - data.append(target->GetPackGUID()); - data.append(GetPackGUID()); - data << uint32(SpellID); - data << uint32(Damage-AbsorbedDamage-Resist-Blocked); - data << uint32(0); // wotlk - data << uint8(damageSchoolMask); // spell school - data << uint32(AbsorbedDamage); // AbsorbedDamage - data << uint32(Resist); // resist - data << uint8(PhysicalDamage); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name - data << uint8(0); // unk isFromAura - data << uint32(Blocked); // blocked - data << uint32(CriticalHit ? 0x27 : 0x25); // hitType, flags: 0x2 - SPELL_HIT_TYPE_CRIT, 0x10 - replace caster? - data << uint8(0); // isDebug? - SendMessageToSet( &data, true ); + SpellNonMeleeDamage log(this,target,SpellID,damageSchoolMask); + log.damage = Damage-AbsorbedDamage-Resist-Blocked; + log.absorb = AbsorbedDamage; + log.resist = Resist; + log.physicalLog = PhysicalDamage; + log.blocked = Blocked; + log.HitInfo = SPELL_HIT_TYPE_UNK1 | SPELL_HIT_TYPE_UNK3 | SPELL_HIT_TYPE_UNK6; + if(CriticalHit) + log.HitInfo |= SPELL_HIT_TYPE_CRIT; + SendSpellNonMeleeDamageLog(&log); } void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellEntry const *procSpell) diff --git a/src/game/Unit.h b/src/game/Unit.h index 0652f5269..597933fb3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -691,24 +691,25 @@ struct CalcDamageInfo // Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode struct SpellNonMeleeDamage{ - SpellNonMeleeDamage(Unit *_attacker, Unit *_target, uint32 _SpellID, uint32 _schoolMask) - : target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), schoolMask(_schoolMask), - absorb(0), resist(0), phusicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0) - {} + SpellNonMeleeDamage(Unit *_attacker, Unit *_target, uint32 _SpellID, uint32 _schoolMask) + : target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(0), schoolMask(_schoolMask), + absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0) + {} - Unit *target; - Unit *attacker; - uint32 SpellID; - uint32 damage; - uint32 schoolMask; - uint32 absorb; - uint32 resist; - bool phusicalLog; - bool unused; - uint32 blocked; - uint32 HitInfo; - // Used for help - uint32 cleanDamage; + Unit *target; + Unit *attacker; + uint32 SpellID; + uint32 damage; + uint32 overkill; + uint32 schoolMask; + uint32 absorb; + uint32 resist; + bool physicalLog; + bool unused; + uint32 blocked; + uint32 HitInfo; + // Used for help + uint32 cleanDamage; }; uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition); diff --git a/src/shared/Common.h b/src/shared/Common.h index c18f854ee..4b72cc81a 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -55,24 +55,16 @@ #include "Platform/Define.h" #if COMPILER == COMPILER_MICROSOFT - -#pragma warning(disable:4996) - +# pragma warning(disable:4996) // 'function': was declared deprecated #ifndef __SHOW_STUPID_WARNINGS__ - -#pragma warning(disable:4244) - -#pragma warning(disable:4267) - -#pragma warning(disable:4800) - -#pragma warning(disable:4018) - -#pragma warning(disable:4311) - -#pragma warning(disable:4305) - -#pragma warning(disable:4005) +# pragma warning(disable:4005) // 'identifier' : macro redefinition +# pragma warning(disable:4018) // 'expression' : signed/unsigned mismatch +# pragma warning(disable:4244) // 'argument' : conversion from 'type1' to 'type2', possible loss of data +# pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data +# pragma warning(disable:4305) // 'identifier' : truncation from 'type1' to 'type2' +# pragma warning(disable:4311) // 'variable' : pointer truncation from 'type' to 'type' +# pragma warning(disable:4355) // 'this' : used in base member initializer list +# pragma warning(disable:4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning) #endif // __SHOW_STUPID_WARNINGS__ #endif // __GNUC__ diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a3c68c1a2..a8f60cc0f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7793" + #define REVISION_NR "7800" #endif // __REVISION_NR_H__