diff --git a/sql/mangos.sql b/sql/mangos.sql index 6451c9815..e9874df24 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_7830_01_mangos_spell_chain` bit(1) default NULL + `required_7855_01_mangos_pools` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -271,9 +271,9 @@ INSERT INTO `command` VALUES ('ban account',3,'Syntax: .ban account $Name $bantime $reason\r\nBan account kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), ('ban character',3,'Syntax: .ban character $Name $bantime $reason\r\nBan account and kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), ('ban ip',3,'Syntax: .ban ip $Ip $bantime $reason\r\nBan IP.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), -('baninfo account',3,'Syntax: .baninfo account\r\nWatch full information about a specific ban.'), -('baninfo character',3,'Syntax: .baninfo character\r\nWatch full information about a specific ban.'), -('baninfo ip',3,'Syntax: .baninfo ip\r\nWatch full information about a specific ban.'), +('baninfo account',3,'Syntax: .baninfo account $accountid\r\nWatch full information about a specific ban.'), +('baninfo character',3,'Syntax: .baninfo character $charactername \r\nWatch full information about a specific ban.'), +('baninfo ip',3,'Syntax: .baninfo ip $ip\r\nWatch full information about a specific ban.'), ('bank',3,'Syntax: .bank\r\n\r\nShow your bank inventory.'), ('banlist account',3,'Syntax: .banlist account [$Name]\r\nSearches the banlist for a account name pattern or show full list account bans.'), ('banlist character',3,'Syntax: .banlist character $Name\r\nSearches the banlist for a character name pattern. Pattern required.'), @@ -287,6 +287,7 @@ INSERT INTO `command` VALUES ('character delete',4,'Syntax: .character delete $name\r\n\r\nDelete character $name.'), ('character level',3,'Syntax: .character level [$playername] [#level]\r\n\r\nSet the level of character with $playername (or the selected if not name provided) by #numberoflevels Or +1 if no #numberoflevels provided). If #numberoflevels is omitted, the level will be increase by 1. If #numberoflevels is 0, the same level will be restarted. If no character is selected and name not provided, increase your level. Command can be used for offline character. All stats and dependent values recalculated. At level decrease talents can be reset if need. Also at level decrease equipped items with greater level requirement can be lost.'), ('character rename',2,'Syntax: .character rename [$name]\r\n\r\nMark selected in game or by $name in command character for rename at next login.'), +('character reputation',2,'Syntax: .character reputation [$player_name]\r\n\r\nShow reputation information for selected player or player find by $player_name.'), ('combatstop',2,'Syntax: .combatstop [$playername]\r\nStop combat for selected character. If selected non-player then command applied to self. If $playername provided then attempt applied to online player $playername.'), ('commands',0,'Syntax: .commands\r\n\r\nDisplay a list of available commands for your account level.'), ('cooldown',3,'Syntax: .cooldown [#spell_id]\r\n\r\nRemove all (if spell_id not provided) or #spel_id spell cooldown from selected character or you (if no selection).'), @@ -335,15 +336,15 @@ INSERT INTO `command` VALUES ('gobject setphase',2,'Syntax: .gobject setphase #guid #phasemask\r\n\r\nGameobject with DB guid #guid phasemask changed to #phasemask with related world vision update for players. Gameobject state saved to DB and persistent.'), ('gobject turn',2,'Syntax: .gobject turn #goguid \r\n\r\nSet for gameobject #goguid orientation same as current character orientation.'), ('gobject target',2,'Syntax: .gobject target [#go_id|#go_name_part]\r\n\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'), -('goname',1,'Syntax: .goname $charactername\r\n\r\nTeleport to the given character. Either specify the character name or click on the character\'s portrait, e.g. when you are in a group.'), +('goname',1,'Syntax: .goname [$charactername]\r\n\r\nTeleport to the given character. Either specify the character name or click on the character\'s portrait, e.g. when you are in a group. Character can be offline.'), ('gps',1,'Syntax: .gps [$name|$shift-link]\r\n\r\nDisplay the position information for a selected character or creature (also if player name $name provided then for named player, or if creature/gameobject shift-link provided then pointed creature/gameobject if it loaded). Position information includes X, Y, Z, and orientation, map Id and zone Id'), -('groupgo',1,'Syntax: .groupgo $charactername\r\n\r\nTeleport the given character and his group to you.'), +('groupgo',1,'Syntax: .groupgo [$charactername]\r\n\r\nTeleport the given character and his group to you. Teleported only online characters but original selected group member can be offline.'), ('guid',2,'Syntax: .guid\r\n\r\nDisplay the GUID for the selected character.'), -('guild create',2,'Syntax: .guild create $GuildLeaderName $GuildName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName as leader.'), +('guild create',2,'Syntax: .guild create [$GuildLeaderName] $GuildName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName (or selected) as leader.'), ('guild delete',2,'Syntax: .guild delete $GuildName\r\n\r\nDelete guild $GuildName.'), -('guild invite',2,'Syntax: .guild invite $CharacterName $GuildName\r\n\r\nAdd $CharacterName into a guild $GuildName.'), +('guild invite',2,'Syntax: .guild invite [$CharacterName] $GuildName\r\n\r\nAdd player $CharacterName (or selected) into a guild $GuildName.'), ('guild rank',2,'Syntax: .guild rank $CharacterName #Rank\r\n\r\nSet for $CharacterName rank #Rank in a guild.'), -('guild uninvite',2,'Syntax: .guild uninvite $CharacterName\r\n\r\nRemove $CharacterName from a guild.'), +('guild uninvite',2,'Syntax: .guild uninvite [$CharacterName]\r\n\r\nRemove player $CharacterName (or selected) from a guild.'), ('help',0,'Syntax: .help [$command]\r\n\r\nDisplay usage instructions for the given $command. If no $command provided show list available commands.'), ('hidearea',3,'Syntax: .hidearea #areaid\r\n\r\nHide the area of #areaid to the selected character. If no character is selected, hide this area to you.'), ('honor add',2,'Syntax: .honor add $amount\r\n\r\nAdd a certain amount of honor (gained today) to the selected player.'), @@ -414,8 +415,8 @@ INSERT INTO `command` VALUES ('modify swim',1,'Syntax: .modify swim #rate\r\n\r\nModify the swim speed of the selected player to \"normal swim speed\"*rate. If no player is selected, modify your speed.\r\n\r\n #rate may range from 0.1 to 10.'), ('modify titles',1,'Syntax: .modify titles #mask\r\n\r\nAllows user to use all titles from #mask.\r\n\r\n #mask=0 disables the title-choose-field'), ('movegens',3,'Syntax: .movegens\r\n Show movement generators stack for selected creature or player.'), -('mute',1,'Syntax: .mute $playerName $timeInMinutes\r\n\r\nDisible chat messaging for any character from account of character $playerName at $timeInMinutes minutes.'), -('namego',1,'Syntax: .namego $charactername\r\n\r\nTeleport the given character to you.'), +('mute',1,'Syntax: .mute [$playerName] $timeInMinutes\r\n\r\nDisible chat messaging for any character from account of character $playerName (or currently selected) at $timeInMinutes minutes. Player can be offline.'), +('namego',1,'Syntax: .namego [$charactername]\r\n\r\nTeleport the given character to you. Character can be offline.'), ('neargrave',3,'Syntax: .neargrave [alliance|horde]\r\n\r\nFind nearest graveyard linked to zone (or only nearest from accepts alliance or horde faction ghosts).'), ('notify',1,'Syntax: .notify $MessageToBroadcast\r\n\r\nSend a global message to all players online in screen.'), ('npc add',2,'Syntax: .npc add #creatureid\r\n\r\nSpawn a creature by the given template id of #creatureid.'), @@ -446,7 +447,7 @@ INSERT INTO `command` VALUES ('npc unfollow',2,'Syntax: .npc unfollow\r\n\r\nSelected creature (non pet) stop follow you.'), ('pdump write',3,'Syntax: .pdump write $filename $playerNameOrGUID\r\nWrite character dump with name/guid $playerNameOrGUID to file $filename.'), ('pdump load',3,'Syntax: .pdump load $filename $account [$newname] [$newguid]\r\nLoad character dump from dump file into character list of $account with saved or $newname, with saved (or first free) or $newguid guid.'), -('pinfo',2,'Syntax: .pinfo [$player_name] [rep]\r\n\r\nOutput account information for selected player or player find by $player_name. If \"rep\" parameter provided show reputation information for player.'), +('pinfo',2,'Syntax: .pinfo [$player_name]\r\n\r\nOutput account information for selected player or player find by $player_name.'), ('quest add',3,'Syntax: .quest add #quest_id\r\n\r\nAdd to character quest log quest #quest_id. Quest started from item can\'t be added by this command but correct .additem call provided in command output.'), ('quest complete',3,'Syntax: .quest complete #questid\r\nMark all quest objectives as completed for target character active quest. After this target character can go and get quest reward.'), ('quest remove',3,'Syntax: .quest remove #quest_id\r\n\r\nSet quest #quest_id state to not completed and not active (and remove from active quest list) for selected player.'), @@ -497,7 +498,7 @@ INSERT INTO `command` VALUES ('tele add',3,'Syntax: .tele add $name\r\n\r\nAdd current your position to .tele command target locations list with name $name.'), ('tele del',3,'Syntax: .tele del $name\r\n\r\nRemove location with name $name for .tele command locations list.'), ('tele group',1,'Syntax: .tele group#location\r\n\r\nTeleport a selected player and his group members to a given location.'), -('tele name',1,'Syntax: .tele name #playername #location\r\n\r\nTeleport a player to a given location.'), +('tele name',1,'Syntax: .tele name [#playername] #location\r\n\r\nTeleport the given character to a given location. Character can be offline.'), ('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'), ('unaura',3,'Syntax: .unaura #spellid\r\n\r\nRemove aura due to spell #spellid from the selected Unit.'), ('unban account',3,'Syntax: .unban account $Name\r\nUnban accounts for account name pattern.'), @@ -2540,6 +2541,7 @@ INSERT INTO `mangos_string` VALUES (168,'Locations found are:\n %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (169,'Mail sent to %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (170,'You try to hear sound %u but it doesn\'t exist.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(171,'You can\'t teleport self to self!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (172,'server console command',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (173,'You changed runic power of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (174,'%s changed your runic power to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -2627,7 +2629,6 @@ INSERT INTO `mangos_string` VALUES (280,'Vendor has too many items (max 128)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (281,'You can\'t kick self, logout instead',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (282,'Player %s kicked.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(283,'Player %s not found.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (284,'Accepting Whisper: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (285,'Accepting Whisper: ON',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (286,'Accepting Whisper: OFF',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -12959,6 +12960,7 @@ CREATE TABLE `pool_creature` ( `guid` int(10) unsigned NOT NULL default '0', `pool_entry` mediumint(8) unsigned NOT NULL default '0', `chance` float unsigned NOT NULL default '0', + `description` varchar(255) NOT NULL, PRIMARY KEY (`pool_entry`,`guid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -12981,6 +12983,7 @@ CREATE TABLE `pool_gameobject` ( `guid` int(10) unsigned NOT NULL default '0', `pool_entry` mediumint(8) unsigned NOT NULL default '0', `chance` float unsigned NOT NULL default '0', + `description` varchar(255) NOT NULL, PRIMARY KEY (`guid`,`pool_entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -13002,6 +13005,7 @@ CREATE TABLE `pool_pool` ( `pool_id` mediumint(8) unsigned NOT NULL default '0', `mother_pool` mediumint(8) unsigned NOT NULL default '0', `chance` float NOT NULL default '0', + `description` varchar(255) NOT NULL, PRIMARY KEY (`pool_id`,`mother_pool`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -13022,6 +13026,7 @@ DROP TABLE IF EXISTS `pool_template`; CREATE TABLE `pool_template` ( `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Pool entry', `max_limit` int(10) unsigned NOT NULL default '0' COMMENT 'Max number of objects (0) is no limit', + `description` varchar(255) NOT NULL, PRIMARY KEY (`entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/7839_01_mangos_mangos_string.sql b/sql/updates/7839_01_mangos_mangos_string.sql new file mode 100644 index 000000000..1474a2f8e --- /dev/null +++ b/sql/updates/7839_01_mangos_mangos_string.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_7830_01_mangos_spell_chain required_7839_01_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN(171,283); + +INSERT INTO mangos_string VALUES +(171,'You can\'t teleport self to self!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/7839_02_mangos_command.sql b/sql/updates/7839_02_mangos_command.sql new file mode 100644 index 000000000..a83d279c8 --- /dev/null +++ b/sql/updates/7839_02_mangos_command.sql @@ -0,0 +1,22 @@ +ALTER TABLE db_version CHANGE COLUMN required_7839_01_mangos_mangos_string required_7839_02_mangos_command bit; + +DELETE FROM `command` WHERE `name` IN ( + 'baninfo account','baninfo character','baninfo ip','goname','groupgo', + 'guild create','guild invite','guild rank','guild uninvite','mute', + 'namego','tele name','unmute' +); + +INSERT INTO `command` VALUES +('baninfo account',3,'Syntax: .baninfo account $accountid\r\nWatch full information about a specific ban.'), +('baninfo character',3,'Syntax: .baninfo character $charactername \r\nWatch full information about a specific ban.'), +('baninfo ip',3,'Syntax: .baninfo ip $ip\r\nWatch full information about a specific ban.'), +('goname',1,'Syntax: .goname [$charactername]\r\n\r\nTeleport to the given character. Either specify the character name or click on the character\'s portrait, e.g. when you are in a group. Character can be offline.'), +('groupgo',1,'Syntax: .groupgo [$charactername]\r\n\r\nTeleport the given character and his group to you. Teleported only online characters but original selected group member can be offline.'), +('guild create',2,'Syntax: .guild create [$GuildLeaderName] $GuildName\r\n\r\nCreate a guild named $GuildName with the player $GuildLeaderName (or selected) as leader.'), +('guild invite',2,'Syntax: .guild invite [$CharacterName] $GuildName\r\n\r\nAdd player $CharacterName (or selected) into a guild $GuildName.'), +('guild rank',2,'Syntax: .guild rank [$CharacterName] #Rank\r\n\r\nSet for player $CharacterName (or selected) rank #Rank in a guild.'), +('guild uninvite',2,'Syntax: .guild uninvite [$CharacterName]\r\n\r\nRemove player $CharacterName (or selected) from a guild.'), +('mute',1,'Syntax: .mute [$playerName] $timeInMinutes\r\n\r\nDisible chat messaging for any character from account of character $playerName (or currently selected) at $timeInMinutes minutes. Player can be offline.'), +('namego',1,'Syntax: .namego [$charactername]\r\n\r\nTeleport the given character to you. Character can be offline.'), +('tele name',1,'Syntax: .tele name [#playername] #location\r\n\r\nTeleport the given character to a given location. Character can be offline.'), +('unmute',1,'Syntax: .unmute [$playerName]\r\n\r\nRestore chat messaging for any character from account of character $playerName (or selected). Character can be ofline.'); diff --git a/sql/updates/7850_01_mangos_command.sql b/sql/updates/7850_01_mangos_command.sql new file mode 100644 index 000000000..5dd0274bc --- /dev/null +++ b/sql/updates/7850_01_mangos_command.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_7839_02_mangos_command required_7850_01_mangos_command bit; + +DELETE FROM `command` WHERE `name` IN ('character reputation','pinfo'); + +INSERT INTO `command` VALUES +('pinfo',2,'Syntax: .pinfo [$player_name]\r\n\r\nOutput account information for selected player or player find by $player_name.'), +('character reputation',2,'Syntax: .character reputation [$player_name]\r\n\r\nShow reputation information for selected player or player find by $player_name.'); diff --git a/sql/updates/7855_01_mangos_pools.sql b/sql/updates/7855_01_mangos_pools.sql new file mode 100644 index 000000000..b5ac676c3 --- /dev/null +++ b/sql/updates/7855_01_mangos_pools.sql @@ -0,0 +1,13 @@ +ALTER TABLE db_version CHANGE COLUMN required_7850_01_mangos_command required_7855_01_mangos_pools bit; + +ALTER TABLE pool_creature + ADD COLUMN description varchar(255) NOT NULL AFTER chance; + +ALTER TABLE pool_gameobject + ADD COLUMN description varchar(255) NOT NULL AFTER chance; + +ALTER TABLE pool_pool + ADD COLUMN description varchar(255) NOT NULL AFTER chance; + +ALTER TABLE pool_template + ADD COLUMN description varchar(255) NOT NULL AFTER max_limit; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index d20edfdf0..decb87867 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -186,6 +186,10 @@ pkgdata_DATA = \ 7802_02_characters_character_achievement_progress.sql \ 7823_01_mangos_item_template.sql \ 7830_01_mangos_spell_chain.sql \ + 7839_01_mangos_mangos_string.sql \ + 7839_02_mangos_command.sql \ + 7850_01_mangos_command.sql \ + 7855_01_mangos_pools.sql \ README ## Additional files to include when running 'make dist' @@ -352,4 +356,8 @@ EXTRA_DIST = \ 7802_02_characters_character_achievement_progress.sql \ 7823_01_mangos_item_template.sql \ 7830_01_mangos_spell_chain.sql \ + 7839_01_mangos_mangos_string.sql \ + 7839_02_mangos_command.sql \ + 7850_01_mangos_command.sql \ + 7855_01_mangos_pools.sql \ README diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 491c7a7ca..602656abe 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -159,8 +159,8 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ ) // ------- Query Without Declined Names -------- // 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, guild_member.guildid " + // 9 10 11 12 13 14 + "characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid " "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' " "LEFT JOIN guild_member ON characters.guid = guild_member.guid " "WHERE characters.account = '%u' ORDER BY characters.guid" @@ -168,8 +168,8 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ ) // --------- Query With Declined Names --------- // 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 14 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive " + // 9 10 11 12 13 14 15 + "characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive " "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " "LEFT JOIN guild_member ON characters.guid = guild_member.guid " diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 92cc520b3..e779c7edb 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -114,6 +114,7 @@ ChatCommand * ChatHandler::getCommandTable() { "delete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL }, { "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterLevelCommand, "", NULL }, { "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterRenameCommand, "", NULL }, + { "reputation", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterReputationCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -375,28 +376,32 @@ ChatCommand * ChatHandler::getCommandTable() { "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllCommand, "", NULL }, { "all_achievement",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAchievementCommand,"", NULL }, { "all_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAreaCommand, "", NULL }, + { "all_eventai", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllEventAICommand, "", NULL }, + { "all_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllItemCommand, "", NULL }, + { "all_locales", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLocalesCommand, "", NULL }, { "all_loot", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLootCommand, "", NULL }, { "all_npc", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllNpcCommand, "", NULL }, { "all_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllQuestCommand, "", NULL }, { "all_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllScriptsCommand, "", NULL }, { "all_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllSpellCommand, "", NULL }, - { "all_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllItemCommand, "", NULL }, - { "all_locales", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLocalesCommand, "", NULL }, { "config", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConfigCommand, "", NULL }, { "achievement_criteria_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementCriteriaDataCommand, "", NULL }, { "achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementRewardCommand, "", NULL }, + { "areatrigger_involvedrelation",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL }, { "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL }, { "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL }, - { "areatrigger_involvedrelation",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL }, - { "event_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventScriptsCommand, "", NULL }, { "command", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommandCommand, "", NULL }, + { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL }, + { "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL }, + { "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL }, { "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand,"",NULL }, { "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL }, { "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL }, { "db_script_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDbScriptStringCommand, "", NULL }, { "disenchant_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesDisenchantCommand, "", NULL }, + { "event_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventScriptsCommand, "", NULL }, { "fishing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesFishingCommand, "", NULL }, { "game_graveyard_zone", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameGraveyardZoneCommand, "", NULL }, { "game_tele", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameTeleCommand, "", NULL }, @@ -418,15 +423,15 @@ ChatCommand * ChatHandler::getCommandTable() { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL }, { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL }, { "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL }, + { "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL}, { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, { "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL }, { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, { "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL}, { "points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPointsOfInterestCommand, "",NULL}, - { "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL}, { "prospecting_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesProspectingCommand,"", NULL }, - { "quest_mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesQuestMailCommand, "", NULL }, { "quest_end_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestEndScriptsCommand, "", NULL }, + { "quest_mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesQuestMailCommand, "", NULL }, { "quest_start_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestStartScriptsCommand, "", NULL }, { "quest_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestTemplateCommand, "", NULL }, { "reference_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesReferenceCommand, "", NULL }, @@ -437,13 +442,13 @@ ChatCommand * ChatHandler::getCommandTable() { "skinning_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL }, { "spell_affect", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAffectCommand, "", NULL }, { "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAreaCommand, "", NULL }, + { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL }, { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL }, { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, - { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL }, { "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, { "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, @@ -454,13 +459,13 @@ ChatCommand * ChatHandler::getCommandTable() static ChatCommand resetCommandTable[] = { - { "achievements", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetAchievementsCommand, "", NULL }, - { "honor", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetHonorCommand, "", NULL }, - { "level", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetLevelCommand, "", NULL }, - { "spells", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetSpellsCommand, "", NULL }, - { "stats", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetStatsCommand, "", NULL }, - { "talents", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetTalentsCommand, "", NULL }, - { "all", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetAllCommand, "", NULL }, + { "achievements", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetAchievementsCommand, "", NULL }, + { "honor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetHonorCommand, "", NULL }, + { "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetLevelCommand, "", NULL }, + { "spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetSpellsCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetStatsCommand, "", NULL }, + { "talents", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetTalentsCommand, "", NULL }, + { "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetAllCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -573,7 +578,7 @@ ChatCommand * ChatHandler::getCommandTable() { "pdump", SEC_ADMINISTRATOR, true, NULL, "", pdumpCommandTable }, { "guild", SEC_ADMINISTRATOR, true, NULL, "", guildCommandTable }, { "cast", SEC_ADMINISTRATOR, false, NULL, "", castCommandTable }, - { "reset", SEC_ADMINISTRATOR, false, NULL, "", resetCommandTable }, + { "reset", SEC_ADMINISTRATOR, true, NULL, "", resetCommandTable }, { "instance", SEC_ADMINISTRATOR, true, NULL, "", instanceCommandTable }, { "server", SEC_ADMINISTRATOR, true, NULL, "", serverCommandTable }, @@ -633,7 +638,7 @@ ChatCommand * ChatHandler::getCommandTable() { "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL }, { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL }, { "flusharenapoints",SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL }, - { "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL }, + { "repairitems", SEC_GAMEMASTER, true, &ChatHandler::HandleRepairitemsCommand, "", NULL }, { "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } @@ -1220,7 +1225,7 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** s *something1 = strtok(NULL, ":|"); // extract something strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces - strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after retturn from function + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function return cKey; } @@ -1498,12 +1503,93 @@ std::string ChatHandler::extractPlayerNameFromLink(char* text) return name; } +bool ChatHandler::extractPlayerTarget(char* args, Player** player, uint64* player_guid /*=NULL*/,std::string* player_name /*= NULL*/) +{ + if (args && *args) + { + std::string name = extractPlayerNameFromLink(args); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player* pl = objmgr.GetPlayer(name.c_str()); + + // if allowed player pointer + if(player) + *player = pl; + + // if need guid value from DB (in name case for check player existence) + uint64 guid = !pl && (player_guid || player_name) ? objmgr.GetPlayerGUIDByName(name) : 0; + + // if allowed player guid (if no then only online players allowed) + if(player_guid) + *player_guid = pl ? pl->GetGUID() : guid; + + if(player_name) + *player_name = pl || guid ? name : ""; + } + else + { + Player* pl = getSelectedPlayer(); + // if allowed player pointer + if(player) + *player = pl; + // if allowed player guid (if no then only online players allowed) + if(player_guid) + *player_guid = pl ? pl->GetGUID() : 0; + + if(player_name) + *player_name = pl ? pl->GetName() : ""; + } + + // some from req. data must be provided (note: name is empty if player not exist) + if((!player || !*player) && (!player_guid || !*player_guid) && (!player_name || player_name->empty())) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2) +{ + char* p1 = strtok(args, " "); + char* p2 = strtok(NULL, " "); + + if(!p2) + { + p2 = p1; + p1 = NULL; + } + + if(arg1) + *arg1 = p1; + + if(arg2) + *arg2 = p2; +} + bool ChatHandler::needReportToTarget(Player* chr) const { Player* pl = m_session->GetPlayer(); return pl != chr && pl->IsVisibleGloballyFor(chr); } +LocaleConstant ChatHandler::GetSessionDbcLocale() const +{ + return m_session->GetSessionDbcLocale(); +} + +int ChatHandler::GetSessionDbLocaleIndex() const +{ + return m_session->GetSessionDbLocaleIndex(); +} + const char *CliHandler::GetMangosString(int32 entry) const { return objmgr.GetMangosStringForDBCLocale(entry); @@ -1531,3 +1617,12 @@ bool CliHandler::needReportToTarget(Player* /*chr*/) const return true; } +LocaleConstant CliHandler::GetSessionDbcLocale() const +{ + return sWorld.GetDefaultDbcLocale(); +} + +int CliHandler::GetSessionDbLocaleIndex() const +{ + return objmgr.GetDBCLocaleIndex(); +} diff --git a/src/game/Chat.h b/src/game/Chat.h index 43d2eb8a3..9f7370401 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -60,9 +60,10 @@ class ChatHandler static char* LineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; } + // function with different implementation for chat/console virtual const char *GetMangosString(int32 entry) const; - virtual void SendSysMessage( const char *str); + void SendSysMessage( int32 entry); void PSendSysMessage( const char *format, ...) ATTR_PRINTF(2,3); void PSendSysMessage( int32 entry, ... ); @@ -73,8 +74,13 @@ class ChatHandler bool hasStringAbbr(const char* name, const char* part); + // function with different implementation for chat/console virtual bool isAvailable(ChatCommand const& cmd) const; + virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); } virtual bool needReportToTarget(Player* chr) const; + virtual LocaleConstant GetSessionDbcLocale() const; + virtual int GetSessionDbLocaleIndex() const; + bool HasLowerSecurity(Player* target, uint64 guid, bool strong = false); bool HasLowerSecurityAccount(WorldSession* target, uint32 account, bool strong = false); @@ -115,8 +121,9 @@ class ChatHandler bool HandleCharacterCustomizeCommand(const char * args); bool HandleCharacterDeleteCommand(const char* args); - bool HandleCharacterRenameCommand(const char * args); bool HandleCharacterLevelCommand(const char* args); + bool HandleCharacterRenameCommand(const char * args); + bool HandleCharacterReputationCommand(const char* args); bool HandleDebugAnimCommand(const char* args); bool HandleDebugArenaCommand(const char * args); @@ -300,6 +307,7 @@ class ChatHandler bool HandleReloadAllNpcCommand(const char* args); bool HandleReloadAllQuestCommand(const char* args); bool HandleReloadAllScriptsCommand(const char* args); + bool HandleReloadAllEventAICommand(const char* args); bool HandleReloadAllSpellCommand(const char* args); bool HandleReloadAllLocalesCommand(const char* args); @@ -310,6 +318,9 @@ class ChatHandler bool HandleReloadAreaTriggerTavernCommand(const char* args); bool HandleReloadAreaTriggerTeleportCommand(const char* args); bool HandleReloadEventScriptsCommand(const char* args); + bool HandleReloadEventAITextsCommand(const char* args); + bool HandleReloadEventAISummonsCommand(const char* args); + bool HandleReloadEventAIScriptsCommand(const char* args); bool HandleReloadCommandCommand(const char* args); bool HandleReloadCreatureQuestRelationsCommand(const char* args); bool HandleReloadCreatureQuestInvRelationsCommand(const char* args); @@ -484,13 +495,17 @@ class ChatHandler char* extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL); char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL); + // if args have single value then it return in arg2 and arg1 == NULL + void extractOptFirstArg(char* args, char** arg1, char** arg2); + uint32 extractSpellIdFromLink(char* text); uint64 extractGuidFromLink(char* text); GameTele const* extractGameTeleFromLink(char* text); std::string extractPlayerNameFromLink(char* text); + // select by arg (name/link) or in-game selection online/offline player + bool extractPlayerTarget(char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL); std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; } - virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); } std::string GetNameLink(Player* chr) const { return playerLink(chr->GetName()); } GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry); @@ -525,6 +540,8 @@ class CliHandler : public ChatHandler void SendSysMessage(const char *str); std::string GetNameLink() const; bool needReportToTarget(Player* chr) const; + LocaleConstant GetSessionDbcLocale() const; + int GetSessionDbLocaleIndex() const; private: Print* m_print; diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 10addd297..9e663107f 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -30,6 +30,22 @@ #include "WorldPacket.h" #include "InstanceData.h" +bool CreatureEventAIHolder::UpdateRepeatTimer( Creature* creature, uint32 repeatMin, uint32 repeatMax ) +{ + if (repeatMin == repeatMax) + Time = repeatMin; + else if (repeatMax > repeatMin) + Time = urand(repeatMin, repeatMax); + else + { + sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", creature->GetEntry(), Event.event_id, Event.event_type); + Enabled = false; + return false; + } + + return true; +} + int CreatureEventAI::Permissible(const Creature *creature) { if( creature->GetAIName() == "EventAI" ) @@ -39,6 +55,7 @@ int CreatureEventAI::Permissible(const Creature *creature) CreatureEventAI::CreatureEventAI(Creature *c ) : CreatureAI(c) { + // Need make copy for filter unneeded steps and safe in case table reload CreatureEventAI_Event_Map::const_iterator CreatureEvents = CreatureEAI_Mgr.GetCreatureEventAIMap().find(m_creature->GetEntry()); if (CreatureEvents != CreatureEAI_Mgr.GetCreatureEventAIMap().end()) { @@ -105,53 +122,25 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction if (pHolder.Event.event_chance <= rnd % 100) return false; - uint32 param1 = pHolder.Event.event_param1; - uint32 param2 = pHolder.Event.event_param2; - uint32 param3 = pHolder.Event.event_param3; - uint32 param4 = pHolder.Event.event_param4; + CreatureEventAI_Event const& event = pHolder.Event; //Check event conditions based on the event type, also reset events - switch (pHolder.Event.event_type) + switch (event.event_type) { case EVENT_T_TIMER: - { if (!m_creature->isInCombat()) return false; //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } - break; + pHolder.UpdateRepeatTimer(m_creature,event.timer.repeatMin,event.timer.repeatMax); + break; case EVENT_T_TIMER_OOC: - { if (m_creature->isInCombat()) return false; //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } - break; + pHolder.UpdateRepeatTimer(m_creature,event.timer.repeatMin,event.timer.repeatMax); + break; case EVENT_T_HP: { if (!m_creature->isInCombat() || !m_creature->GetMaxHealth()) @@ -159,24 +148,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction uint32 perc = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth(); - if (perc > param1 || perc < param2) + if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax); + break; } - break; case EVENT_T_MANA: { if (!m_creature->isInCombat() || !m_creature->GetMaxPower(POWER_MANA)) @@ -184,109 +162,38 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction uint32 perc = (m_creature->GetPower(POWER_MANA)*100) / m_creature->GetMaxPower(POWER_MANA); - if (perc > param1 || perc < param2) + if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax); + break; } - break; case EVENT_T_AGGRO: - { - } - break; + break; case EVENT_T_KILL: - { //Repeat Timers - if (param1 == param2) - { - pHolder.Time = param1; - - }else if (param2 > param1) - pHolder.Time = urand(param1, param2); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } + pHolder.UpdateRepeatTimer(m_creature,event.kill.repeatMin,event.kill.repeatMax); + break; case EVENT_T_DEATH: - { - } - break; case EVENT_T_EVADE: - { - } - break; + break; case EVENT_T_SPELLHIT: - { //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } - break; + pHolder.UpdateRepeatTimer(m_creature,event.spell_hit.repeatMin,event.spell_hit.repeatMax); + break; case EVENT_T_RANGE: - { //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } - break; + pHolder.UpdateRepeatTimer(m_creature,event.range.repeatMin,event.range.repeatMax); + break; case EVENT_T_OOC_LOS: - { //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } - break; + pHolder.UpdateRepeatTimer(m_creature,event.ooc_los.repeatMin,event.ooc_los.repeatMax); + break; case EVENT_T_SPAWNED: - { - } - break; + break; case EVENT_T_TARGET_HP: { if (!m_creature->isInCombat() || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth()) @@ -294,78 +201,42 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth(); - if (perc > param1 || perc < param2) + if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax); + break; } - break; case EVENT_T_TARGET_CASTING: - { if (!m_creature->isInCombat() || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true)) return false; //Repeat Timers - if (param1 == param2) - { - pHolder.Time = param1; - - }else if (param2 > param1) - pHolder.Time = urand(param1, param2); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } - } - break; + pHolder.UpdateRepeatTimer(m_creature,event.target_casting.repeatMin,event.target_casting.repeatMax); + break; case EVENT_T_FRIENDLY_HP: { if (!m_creature->isInCombat()) return false; - Unit* pUnit = DoSelectLowestHpFriendly(param2, param1); - + Unit* pUnit = DoSelectLowestHpFriendly(event.friendly_hp.radius, event.friendly_hp.hpDeficit); if (!pUnit) return false; pActionInvoker = pUnit; //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.friendly_hp.repeatMin,event.friendly_hp.repeatMax); + break; } - break; case EVENT_T_FRIENDLY_IS_CC: { if (!m_creature->isInCombat()) return false; std::list pList; - DoFindFriendlyCC(pList, param2); + DoFindFriendlyCC(pList, event.friendly_is_cc.radius); //List is empty if (pList.empty()) @@ -375,23 +246,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction pActionInvoker = *(pList.begin()); //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.friendly_is_cc.repeatMin,event.friendly_is_cc.repeatMax); + break; } - break; case EVENT_T_FRIENDLY_MISSING_BUFF: { std::list pList; - DoFindFriendlyMissingBuff(pList, param2, param1); + DoFindFriendlyMissingBuff(pList, event.friendly_buff.radius, event.friendly_buff.spellId); //List is empty if (pList.empty()) @@ -401,20 +262,9 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction pActionInvoker = *(pList.begin()); //Repeat Timers - if (param3 == param4) - { - pHolder.Time = param3; - - }else if (param4 > param3) - pHolder.Time = urand(param3, param4); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.friendly_buff.repeatMin,event.friendly_buff.repeatMax); + break; } - break; case EVENT_T_SUMMONED_UNIT: { //Prevent event from occuring on no unit or non creatures @@ -422,34 +272,31 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction return false; //Creature id doesn't match up - if (param1 && ((Creature*)pActionInvoker)->GetEntry() != param1) + if (((Creature*)pActionInvoker)->GetEntry() != event.summon_unit.creatureId) return false; //Repeat Timers - if (param2 == param3) - { - pHolder.Time = param2; - - }else if (param3 > param2) - pHolder.Time = urand(param2, param3); - else - { - - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); - pHolder.Enabled = false; - } + pHolder.UpdateRepeatTimer(m_creature,event.summon_unit.repeatMin,event.summon_unit.repeatMax); } break; + case EVENT_T_TARGET_MANA: + { + if (!m_creature->isInCombat() || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxPower(POWER_MANA)) + return false; + + uint32 perc = (m_creature->getVictim()->GetPower(POWER_MANA)*100) / m_creature->getVictim()->GetMaxPower(POWER_MANA); + + if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) + return false; + + //Repeat Timers + pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax); + break; + } case EVENT_T_REACHED_HOME: - { - } - break; case EVENT_T_RECEIVE_EMOTE: - { - } - break; + break; default: - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type); break; } @@ -460,37 +307,35 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction //Process actions for (uint32 j = 0; j < MAX_ACTIONS; j++) - ProcessAction(pHolder.Event.action[j].type, pHolder.Event.action[j].param1, pHolder.Event.action[j].param2, pHolder.Event.action[j].param3, rnd, pHolder.Event.event_id, pActionInvoker); + ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker); return true; } -void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker) +void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker) { - switch (type) + switch (action.type) { case ACTION_T_TEXT: { - if (!param1) + if (!action.text.TextId1) return; - uint32 temp = 0; + int32 temp = 0; - if (param2 && param3) + if (action.text.TextId2 && action.text.TextId3) { switch( rand()%3 ) { - case 0: temp = param1; break; - case 2: temp = param2; break; - case 3: temp = param3; break; + case 0: temp = action.text.TextId1; break; + case 1: temp = action.text.TextId2; break; + case 2: temp = action.text.TextId3; break; } - }else if ( param2 && urand(0,1) ) - { - temp = param2; - }else - { - temp = param1; } + else if (action.text.TextId2 && urand(0,1)) + temp = action.text.TextId2; + else + temp = action.text.TextId1; if (temp) { @@ -516,12 +361,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u DoScriptText(temp, m_creature, target); } + break; } - break; case ACTION_T_SET_FACTION: { - if (param1) - m_creature->setFaction(param1); + if (action.set_faction.factionId) + m_creature->setFaction(action.set_faction.factionId); else { if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature->GetEntry())) @@ -531,16 +376,16 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u m_creature->setFaction(ci->faction_A); } } + break; } - break; case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: { - if (param1 || param2) + if (action.morph.creatireId || action.morph.modelId) { //set model based on entry from creature_template - if (param1) + if (action.morph.creatireId) { - if (CreatureInfo const* ci = GetCreatureTemplateStore(param1)) + if (CreatureInfo const* ci = GetCreatureTemplateStore(action.morph.creatireId)) { //use default display if (ci->DisplayID_A) @@ -549,73 +394,67 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u } //if no param1, then use value from param2 (modelId) else - m_creature->SetDisplayId(param2); + m_creature->SetDisplayId(action.morph.modelId); } else m_creature->DeMorph(); + break; } - break; case ACTION_T_SOUND: - m_creature->PlayDirectSound(param1); + m_creature->PlayDirectSound(action.sound.soundId); break; case ACTION_T_EMOTE: - m_creature->HandleEmoteCommand(param1); + m_creature->HandleEmoteCommand(action.emote.emoteId); break; case ACTION_T_RANDOM_SOUND: { - uint32 temp = GetRandActionParam(rnd, param1, param2, param3); - - if (temp != uint32(0xffffffff)) - m_creature->PlayDirectSound( temp ); + int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3); + if (temp >= 0) + m_creature->PlayDirectSound(temp); + break; } - break; case ACTION_T_RANDOM_EMOTE: { - uint32 temp = GetRandActionParam(rnd, param1, param2, param3); - - if (temp != uint32(0xffffffff)) + int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3); + if (temp >= 0) m_creature->HandleEmoteCommand(temp); + break; } - break; case ACTION_T_CAST: { - Unit* target = GetTargetByType(param2, pActionInvoker); + Unit* target = GetTargetByType(action.cast.target, pActionInvoker); Unit* caster = m_creature; if (!target) return; - //Cast is always triggered if target is forced to cast on self - if (param3 & CAST_FORCE_TARGET_SELF) - { - param3 |= CAST_TRIGGERED; + if (action.cast.castFlags & CAST_FORCE_TARGET_SELF) caster = target; - } //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered - bool canCast = !caster->IsNonMeleeSpellCasted(false) || (param3 & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS)); + bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS)); // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them - if(param3 & CAST_AURA_NOT_PRESENT) + if(action.cast.castFlags & CAST_AURA_NOT_PRESENT) { for(uint8 i = 0; i < 3; ++i) - if(target->HasAura(param1, i)) + if(target->HasAura(action.cast.spellId, i)) return; } if (canCast) { - const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1); + const SpellEntry* tSpell = GetSpellStore()->LookupEntry(action.cast.spellId); //Verify that spell exists if (tSpell) { //Check if cannot cast spell - if (!(param3 & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) && - !CanCast(target, tSpell, (param3 & CAST_TRIGGERED))) + if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) && + !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED))) { //Melee current victim if flag not set - if (!(param3 & CAST_NO_MELEE_IF_OOM)) + if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM)) { if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) { @@ -631,111 +470,83 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u else { //Interrupt any previous spell - if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS) + if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTURRUPT_PREVIOUS) caster->InterruptNonMeleeSpells(false); - caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED)); + caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED)); } - }else - sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1); + } + else + sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), action.cast.spellId); } + break; } - break; case ACTION_T_SUMMON: { - Unit* target = GetTargetByType(param2, pActionInvoker); + Unit* target = GetTargetByType(action.summon.target, pActionInvoker); Creature* pCreature = NULL; - if (param3) - pCreature = m_creature->SummonCreature(param1, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3); + if (action.summon.duration) + pCreature = m_creature->SummonCreature(action.summon.creatured, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, action.summon.duration); else - pCreature = m_creature->SummonCreature(param1, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + pCreature = m_creature->SummonCreature(action.summon.creatured, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); if (!pCreature) - { - - sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry()); - } - else if (param2 != TARGET_T_SELF && target) + sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", action.summon.creatured, EventId, m_creature->GetEntry()); + else if (action.summon.target != TARGET_T_SELF && target) pCreature->AI()->AttackStart(target); + break; } - break; case ACTION_T_THREAT_SINGLE_PCT: - { - Unit* target = GetTargetByType(param2, pActionInvoker); - - if (target) - m_creature->getThreatManager().modifyThreatPercent(target, param1); - } - break; + if (Unit* target = GetTargetByType(action.threat_single_pct.target, pActionInvoker)) + m_creature->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent); + break; case ACTION_T_THREAT_ALL_PCT: { - Unit* Temp = NULL; - - std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); - for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) - { - Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); - if (Temp) - m_creature->getThreatManager().modifyThreatPercent(Temp, param1); - } + std::list& threatList = m_creature->getThreatManager().getThreatList(); + for (std::list::iterator i = threatList.begin(); i != threatList.end(); ++i) + if(Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid())) + m_creature->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent); + break; } - break; case ACTION_T_QUEST_EVENT: - { - Unit* target = GetTargetByType(param2, pActionInvoker); - - if (target && target->GetTypeId() == TYPEID_PLAYER) - ((Player*)target)->AreaExploredOrEventHappens(param1); - } - break; - case ACTION_T_CASTCREATUREGO: - { - Unit* target = GetTargetByType(param3, pActionInvoker); - - if (target && target->GetTypeId() == TYPEID_PLAYER) - ((Player*)target)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2); - } - break; + if (Unit* target = GetTargetByType(action.quest_event.target, pActionInvoker)) + if (target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->AreaExploredOrEventHappens(action.quest_event.questId); + break; + case ACTION_T_CAST_EVENT: + if (Unit* target = GetTargetByType(action.cast_event.target, pActionInvoker)) + if (target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->CastedCreatureOrGO(action.cast_event.creatureId, m_creature->GetGUID(), action.cast_event.spellId); + break; case ACTION_T_SET_UNIT_FIELD: { - Unit* target = GetTargetByType(param3, pActionInvoker); + Unit* target = GetTargetByType(action.set_unit_field.target, pActionInvoker); - if (param1 < OBJECT_END || param1 >= UNIT_END) + // not allow modify important for integrity object fields + if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END) return; if (target) - target->SetUInt32Value(param1, param2); + target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value); + + break; } - break; case ACTION_T_SET_UNIT_FLAG: - { - Unit* target = GetTargetByType(param2, pActionInvoker); - - if (target) - target->SetFlag(UNIT_FIELD_FLAGS, param1); - } - break; + if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker)) + target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value); + break; case ACTION_T_REMOVE_UNIT_FLAG: - { - Unit* target = GetTargetByType(param2, pActionInvoker); - - if (target) - target->RemoveFlag(UNIT_FIELD_FLAGS, param1); - } - break; + if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker)) + target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value); + break; case ACTION_T_AUTO_ATTACK: - { - if (param1) - MeleeEnabled = true; - else MeleeEnabled = false; - } - break; + MeleeEnabled = action.auto_attack.state != 0; + break; case ACTION_T_COMBAT_MOVEMENT: - { - CombatMovementEnabled = param1; + CombatMovementEnabled = action.combat_movement.state != 0; //Allow movement (create new targeted movement gen only if idle) if (CombatMovementEnabled) @@ -753,69 +564,59 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u m_creature->GetMotionMaster()->MoveIdle(); m_creature->StopMoving(); } - } - break; + break; case ACTION_T_SET_PHASE: - { - Phase = param1; - } - break; + Phase = action.set_phase.phase; + break; case ACTION_T_INC_PHASE: { - Phase += param1; + int32 new_phase = int32(Phase)+action.set_inc_phase.step; + if (new_phase < 0) + { + sLog.outErrorDb( "CreatureEventAI: Event %d decrease Phase under 0. CreatureEntry = %d", EventId, m_creature->GetEntry()); + Phase = 0; + } + else if (new_phase >= MAX_PHASE) + { + sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above %u. Phase mask cannot be used with phases past %u. CreatureEntry = %d", EventId, MAX_PHASE-1, MAX_PHASE-1, m_creature->GetEntry()); + Phase = MAX_PHASE-1; + } + else + Phase = new_phase; - if (Phase > 31) - - sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature->GetEntry()); + break; } - break; case ACTION_T_EVADE: - { EnterEvadeMode(); - } - break; + break; case ACTION_T_FLEE: - { //TODO: Replace with Flee movement generator m_creature->CastSpell(m_creature, SPELL_RUN_AWAY, true); - } - break; + break; case ACTION_T_QUEST_EVENT_ALL: - { - Unit* Temp = NULL; - if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER ) + if (pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER) { - Temp = Unit::GetUnit(*m_creature,pActionInvoker->GetGUID()); - if( Temp ) - ((Player*)Temp)->GroupEventHappens(param1,m_creature); + if (Unit* Temp = Unit::GetUnit(*m_creature,pActionInvoker->GetGUID())) + if (Temp->GetTypeId() == TYPEID_PLAYER) + ((Player*)Temp)->GroupEventHappens(action.quest_event_all.questId,m_creature); } - } - break; - case ACTION_T_CASTCREATUREGO_ALL: + break; + case ACTION_T_CAST_EVENT_ALL: { - Unit* Temp = NULL; - - std::list::iterator i = m_creature->getThreatManager().getThreatList().begin(); - for (; i != m_creature->getThreatManager().getThreatList().end(); ++i) - { - Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); - if (Temp && Temp->GetTypeId() == TYPEID_PLAYER) - ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2); - } + std::list& threatList = m_creature->getThreatManager().getThreatList(); + for (std::list::iterator i = threatList.begin(); i != threatList.end(); ++i) + if (Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid())) + if (Temp->GetTypeId() == TYPEID_PLAYER) + ((Player*)Temp)->CastedCreatureOrGO(action.cast_event_all.creatureId, m_creature->GetGUID(), action.cast_event_all.spellId); + break; } - break; case ACTION_T_REMOVEAURASFROMSPELL: - { - Unit* target = GetTargetByType(param1, pActionInvoker); - - if (target) - target->RemoveAurasDueToSpell(param2); - } - break; + if (Unit* target = GetTargetByType(action.remove_aura.target, pActionInvoker)) + target->RemoveAurasDueToSpell(action.remove_aura.spellId); + break; case ACTION_T_RANGED_MOVEMENT: - { - AttackDistance = param1; - AttackAngle = ((float)param2/180)*M_PI; + AttackDistance = action.ranged_movement.distance; + AttackAngle = ((float)action.ranged_movement.angle/180)*M_PI; if (CombatMovementEnabled) { @@ -826,69 +627,52 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); } } - } - break; + break; case ACTION_T_RANDOM_PHASE: - { - uint32 temp = GetRandActionParam(rnd, param1, param2, param3); - - Phase = temp; - } - break; + Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3); + break; case ACTION_T_RANDOM_PHASE_RANGE: - { - if (param2 > param1) - { - Phase = param1 + (rnd % (param2 - param1)); - } + if (action.random_phase_range.phaseMax > action.random_phase_range.phaseMin) + Phase = action.random_phase_range.phaseMin + (rnd % (action.random_phase_range.phaseMax - action.random_phase_range.phaseMin)); else sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature->GetEntry()); - } - break; + break; case ACTION_T_SUMMON_ID: { - Unit* target = GetTargetByType(param2, pActionInvoker); + Unit* target = GetTargetByType(action.summon_id.target, pActionInvoker); - //Duration - Creature* pCreature = NULL; - - CreatureEventAI_Summon_Map::const_iterator i = CreatureEAI_Mgr.GetCreatureEventAISummonMap().find(param3); + CreatureEventAI_Summon_Map::const_iterator i = CreatureEAI_Mgr.GetCreatureEventAISummonMap().find(action.summon_id.spawnId); if (i == CreatureEAI_Mgr.GetCreatureEventAISummonMap().end()) { - - sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature->GetEntry()); + sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_id.creatureId, action.summon_id.spawnId, EventId, m_creature->GetEntry()); return; } + Creature* pCreature = NULL; if ((*i).second.SpawnTimeSecs) - pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); - else pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + pCreature = m_creature->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); + else + pCreature = m_creature->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); if (!pCreature) - { - - sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature->GetEntry()); - } - else if (param2 != TARGET_T_SELF && target) + sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, EventId, m_creature->GetEntry()); + else if (action.summon_id.target != TARGET_T_SELF && target) pCreature->AI()->AttackStart(target); + + break; } - break; case ACTION_T_KILLED_MONSTER: - { //first attempt player who tapped creature if (Player* pPlayer = m_creature->GetLootRecipient()) - pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature); + pPlayer->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, m_creature); else { //if not available, use pActionInvoker - if (Unit* pTarget = GetTargetByType(param2, pActionInvoker)) - { + if (Unit* pTarget = GetTargetByType(action.killed_monster.target, pActionInvoker)) if (Player* pPlayer2 = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer2->RewardPlayerAndGroupAtEvent(param1, m_creature); - } + pPlayer2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, m_creature); } - } - break; + break; case ACTION_T_SET_INST_DATA: { InstanceData* pInst = (InstanceData*)m_creature->GetInstanceData(); @@ -898,12 +682,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u return; } - pInst->SetData(param1, param2); + pInst->SetData(action.set_inst_data.field, action.set_inst_data.value); + break; } - break; case ACTION_T_SET_INST_DATA64: { - Unit* target = GetTargetByType(param2, pActionInvoker); + Unit* target = GetTargetByType(action.set_inst_data64.target, pActionInvoker); if (!target) { sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry()); @@ -917,19 +701,19 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u return; } - pInst->SetData64(param1, target->GetGUID()); + pInst->SetData64(action.set_inst_data64.field, target->GetGUID()); + break; } - break; case ACTION_T_UPDATE_TEMPLATE: { - if (m_creature->GetEntry() == param1) + if (m_creature->GetEntry() == action.update_template.creatureId) { sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature->GetEntry()); return; } - m_creature->UpdateEntry(param1, param2 ? HORDE : ALLIANCE); + m_creature->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE); } break; case ACTION_T_DIE: @@ -984,25 +768,16 @@ void CreatureEventAI::Reset() //Reset all events to enabled for (std::list::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i) { - switch ((*i).Event.event_type) + CreatureEventAI_Event const& event = (*i).Event; + switch (event.event_type) { //Reset all out of combat timers case EVENT_T_TIMER_OOC: { - if ((*i).Event.event_param2 == (*i).Event.event_param1) - { - (*i).Time = (*i).Event.event_param1; + if ((*i).UpdateRepeatTimer(m_creature,event.timer.initialMin,event.timer.initialMax)) (*i).Enabled = true; - } - else if ((*i).Event.event_param2 > (*i).Event.event_param1) - { - (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2); - (*i).Enabled = true; - } - else - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type); + break; } - break; //default: //TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void Aggro() //(*i).Enabled = true; @@ -1096,7 +871,8 @@ void CreatureEventAI::EnterCombat(Unit *enemy) { for (std::list::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i) { - switch ((*i).Event.event_type) + CreatureEventAI_Event const& event = (*i).Event; + switch (event.event_type) { case EVENT_T_AGGRO: (*i).Enabled = true; @@ -1104,18 +880,8 @@ void CreatureEventAI::EnterCombat(Unit *enemy) break; //Reset all in combat timers case EVENT_T_TIMER: - if ((*i).Event.event_param2 == (*i).Event.event_param1) - { - (*i).Time = (*i).Event.event_param1; + if ((*i).UpdateRepeatTimer(m_creature,event.timer.initialMin,event.timer.initialMax)) (*i).Enabled = true; - } - else if ((*i).Event.event_param2 > (*i).Event.event_param1) - { - (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2); - (*i).Enabled = true; - } - else - sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type); break; //All normal events need to be re-enabled and their time set to 0 default: @@ -1166,14 +932,14 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who) if ((*itr).Event.event_type == EVENT_T_OOC_LOS) { //can trigger if closer than fMaxAllowedRange - float fMaxAllowedRange = (*itr).Event.event_param2; + float fMaxAllowedRange = (*itr).Event.ooc_los.maxRange; //if range is ok and we are actually in LOS if (m_creature->IsWithinDistInMap(who, fMaxAllowedRange) && m_creature->IsWithinLOSInMap(who)) { //if friendly event&&who is not hostile OR hostile event&&who is hostile - if (((*itr).Event.event_param1 && !m_creature->IsHostileTo(who)) || - ((!(*itr).Event.event_param1) && m_creature->IsHostileTo(who))) + if (((*itr).Event.ooc_los.noHostile && !m_creature->IsHostileTo(who)) || + ((!(*itr).Event.ooc_los.noHostile) && m_creature->IsHostileTo(who))) ProcessEvent(*itr, who); } } @@ -1213,17 +979,11 @@ void CreatureEventAI::SpellHit(Unit* pUnit, const SpellEntry* pSpell) return; for (std::list::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i) - { if ((*i).Event.event_type == EVENT_T_SPELLHIT) - { //If spell id matches (or no spell id) & if spell school matches (or no spell school) - if (!(*i).Event.event_param1 || pSpell->Id == (*i).Event.event_param1) - { - if ((*i).Event.event_param2_s == -1 || pSpell->SchoolMask == (*i).Event.event_param2) + if (!(*i).Event.spell_hit.spellId || pSpell->Id == (*i).Event.spell_hit.spellId) + if (pSpell->SchoolMask & (*i).Event.spell_hit.schoolMask) ProcessEvent(*i, pUnit); - } - } - } } void CreatureEventAI::UpdateAI(const uint32 diff) @@ -1278,8 +1038,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff) case EVENT_T_RANGE: if (Combat) if (m_creature->IsInMap(m_creature->getVictim())) - if (m_creature->IsInRange(m_creature->getVictim(), - (float)(*i).Event.event_param1,(float)(*i).Event.event_param2)) + if (m_creature->IsInRange(m_creature->getVictim(),(float)(*i).Event.range.minDist,(float)(*i).Event.range.maxDist)) ProcessEvent(*i); break; } @@ -1341,15 +1100,20 @@ inline uint32 CreatureEventAI::GetRandActionParam(uint32 rnd, uint32 param1, uin { switch (rnd % 3) { - case 0: - return param1; - break; - case 1: - return param2; - break; - case 2: - return param3; - break; + case 0: return param1; + case 1: return param2; + case 2: return param3; + } + return 0; +} + +inline int32 CreatureEventAI::GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3) +{ + switch (rnd % 3) + { + case 0: return param1; + case 1: return param2; + case 2: return param3; } return 0; } @@ -1360,28 +1124,20 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke { case TARGET_T_SELF: return m_creature; - break; case TARGET_T_HOSTILE: return m_creature->getVictim(); - break; case TARGET_T_HOSTILE_SECOND_AGGRO: return SelectUnit(ATTACKING_TARGET_TOPAGGRO,1); - break; case TARGET_T_HOSTILE_LAST_AGGRO: return SelectUnit(ATTACKING_TARGET_BOTTOMAGGRO,0); - break; case TARGET_T_HOSTILE_RANDOM: return SelectUnit(ATTACKING_TARGET_RANDOM,0); - break; case TARGET_T_HOSTILE_RANDOM_NOT_TOP: return SelectUnit(ATTACKING_TARGET_RANDOM,1); - break; case TARGET_T_ACTION_INVOKER: return pActionInvoker; - break; default: return NULL; - break; }; } @@ -1581,7 +1337,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge return false; //Unit is out of range of this spell - if (!m_creature->IsInRange(Target,TempRange->minRange,TempRange->minRange)) + if (!m_creature->IsInRange(Target,TempRange->minRange,TempRange->maxRange)) return false; return true; @@ -1596,60 +1352,11 @@ void CreatureEventAI::ReceiveEmote(Player* pPlayer, uint32 text_emote) { if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE) { - if ((*itr).Event.event_param1 != text_emote) + if ((*itr).Event.receive_emote.emoteId != text_emote) return; - bool bProcess = false; - - switch((*itr).Event.event_param2) - { - //enum ConditionType - case CONDITION_NONE: // 0 0 - bProcess = true; - break; - case CONDITION_AURA: // spell_id effindex - if (pPlayer->HasAura((*itr).Event.event_param3,(*itr).Event.event_param4)) - bProcess = true; - break; - case CONDITION_ITEM: // item_id count - if (pPlayer->HasItemCount((*itr).Event.event_param3,(*itr).Event.event_param4)) - bProcess = true; - break; - case CONDITION_ITEM_EQUIPPED: // item_id count - if (pPlayer->HasItemOrGemWithIdEquipped((*itr).Event.event_param3,(*itr).Event.event_param4)) - bProcess = true; - break; - case CONDITION_ZONEID: // zone_id 0 - if (pPlayer->GetZoneId() == (*itr).Event.event_param3) - bProcess = true; - break; - case CONDITION_REPUTATION_RANK: // faction_id min_rank - if (pPlayer->GetReputationRank((*itr).Event.event_param3) >= (*itr).Event.event_param4) - bProcess = true; - break; - case CONDITION_TEAM: // player_team 0, (469 - Alliance 67 - Horde) - if (pPlayer->GetTeam() == (*itr).Event.event_param3) - bProcess = true; - break; - case CONDITION_SKILL: // skill_id min skill_value - if (pPlayer->HasSkill((*itr).Event.event_param3) && pPlayer->GetSkillValue((*itr).Event.event_param3) >= (*itr).Event.event_param4) - bProcess = true; - break; - case CONDITION_QUESTREWARDED: // quest_id 0 - if (pPlayer->GetQuestRewardStatus((*itr).Event.event_param3)) - bProcess = true; - break; - case CONDITION_QUESTTAKEN: // quest_id 0, for condition true while quest active. - if (pPlayer->GetQuestStatus((*itr).Event.event_param3) == QUEST_STATUS_INCOMPLETE) - bProcess = true; - break; - case CONDITION_ACTIVE_EVENT: // event_id 0 - if (IsHolidayActive(HolidayIds((*itr).Event.event_param3))) - bProcess = true; - break; - } - - if (bProcess) + PlayerCondition pcon((*itr).Event.receive_emote.condition,(*itr).Event.receive_emote.conditionValue1,(*itr).Event.receive_emote.conditionValue2); + if (pcon.Meets(pPlayer)) { sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing"); ProcessEvent(*itr, pPlayer); diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 771d582ef..d357e5829 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -30,6 +30,7 @@ class WorldObject; #define EVENT_UPDATE_TIME 500 #define SPELL_RUN_AWAY 8225 #define MAX_ACTIONS 3 +#define MAX_PHASE 32 enum EventAI_Type { @@ -43,7 +44,7 @@ enum EventAI_Type EVENT_T_EVADE = 7, // NONE EVENT_T_SPELLHIT = 8, // SpellID, School, RepeatMin, RepeatMax EVENT_T_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax - EVENT_T_OOC_LOS = 10, // NoHostile, NoFriendly, RepeatMin, RepeatMax + EVENT_T_OOC_LOS = 10, // NoHostile, MaxRnage, RepeatMin, RepeatMax EVENT_T_SPAWNED = 11, // NONE EVENT_T_TARGET_HP = 12, // HPMax%, HPMin%, RepeatMin, RepeatMax EVENT_T_TARGET_CASTING = 13, // RepeatMin, RepeatMax @@ -78,7 +79,7 @@ enum EventAI_ActionType ACTION_T_THREAT_SINGLE_PCT = 13, //*Threat%, Target ACTION_T_THREAT_ALL_PCT = 14, //Threat% ACTION_T_QUEST_EVENT = 15, //*QuestID, Target - ACTION_T_CASTCREATUREGO = 16, //*QuestID, SpellId, Target + ACTION_T_CAST_EVENT = 16, //*QuestID, SpellId, Target - must be removed as hack? ACTION_T_SET_UNIT_FIELD = 17, //*Field_Number, Value, Target ACTION_T_SET_UNIT_FLAG = 18, //*Flags (may be more than one field OR'd together), Target ACTION_T_REMOVE_UNIT_FLAG = 19, //*Flags (may be more than one field OR'd together), Target @@ -89,7 +90,7 @@ enum EventAI_ActionType ACTION_T_EVADE = 24, //No Params ACTION_T_FLEE = 25, //No Params ACTION_T_QUEST_EVENT_ALL = 26, //*QuestID - ACTION_T_CASTCREATUREGO_ALL = 27, //*QuestId, SpellId + ACTION_T_CAST_EVENT_ALL = 27, //*QuestId, SpellId ACTION_T_REMOVEAURASFROMSPELL = 28, //*Target, Spellid ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3 @@ -165,6 +166,202 @@ struct StringTextData // Text Maps typedef UNORDERED_MAP CreatureEventAI_TextMap; +struct CreatureEventAI_Action +{ + EventAI_ActionType type: 16; + union + { + // ACTION_T_TEXT = 1 + struct + { + int32 TextId1; + int32 TextId2; + int32 TextId3; + } text; + // ACTION_T_SET_FACTION = 2 + struct + { + uint32 factionId; // faction or 0 for default) + } set_faction; + // ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3 + struct + { + uint32 creatireId; // set one from fields (or 0 for both to demorph) + uint32 modelId; + } morph; + // ACTION_T_SOUND = 4 + struct + { + uint32 soundId; + } sound; + // ACTION_T_EMOTE = 5 + struct + { + uint32 emoteId; + } emote; + // ACTION_T_RANDOM_SOUND = 9 + struct + { + int32 soundId1; // (-1 in any field means no output if randomed that field) + int32 soundId2; + int32 soundId3; + } random_sound; + // ACTION_T_RANDOM_EMOTE = 10 + struct + { + int32 emoteId1; // (-1 in any field means no output if randomed that field) + int32 emoteId2; + int32 emoteId3; + } random_emote; + // ACTION_T_CAST = 11 + struct + { + uint32 spellId; + uint32 target; + uint32 castFlags; + } cast; + // ACTION_T_SUMMON = 12 + struct + { + uint32 creatured; + uint32 target; + uint32 duration; + } summon; + // ACTION_T_THREAT_SINGLE_PCT = 13 + struct + { + int32 percent; + uint32 target; + } threat_single_pct; + // ACTION_T_THREAT_ALL_PCT = 14 + struct + { + int32 percent; + } threat_all_pct; + // ACTION_T_QUEST_EVENT = 15 + struct + { + uint32 questId; + uint32 target; + } quest_event; + // ACTION_T_CAST_EVENT = 16 + struct + { + uint32 creatureId; + uint32 spellId; + uint32 target; + } cast_event; + // ACTION_T_SET_UNIT_FIELD = 17 + struct + { + uint32 field; + uint32 value; + uint32 target; + } set_unit_field; + // ACTION_T_SET_UNIT_FLAG = 18, // value provided mask bits that will be set + // ACTION_T_REMOVE_UNIT_FLAG = 19, // value provided mask bits that will be clear + struct + { + uint32 value; + uint32 target; + } unit_flag; + // ACTION_T_AUTO_ATTACK = 20 + struct + { + uint32 state; // 0 = stop attack, anything else means continue attacking + } auto_attack; + // ACTION_T_COMBAT_MOVEMENT = 21 + struct + { + uint32 state; // 0 = stop combat based movement, anything else continue attacking + } combat_movement; + // ACTION_T_SET_PHASE = 22 + struct + { + uint32 phase; + } set_phase; + // ACTION_T_INC_PHASE = 23 + struct + { + int32 step; + } set_inc_phase; + // ACTION_T_QUEST_EVENT_ALL = 26 + struct + { + uint32 questId; + } quest_event_all; + // ACTION_T_CAST_EVENT_ALL = 27 + struct + { + uint32 creatureId; + uint32 spellId; + } cast_event_all; + // ACTION_T_REMOVEAURASFROMSPELL = 28 + struct + { + uint32 target; + uint32 spellId; + } remove_aura; + // ACTION_T_RANGED_MOVEMENT = 29 + struct + { + uint32 distance; + int32 angle; + } ranged_movement; + // ACTION_T_RANDOM_PHASE = 30 + struct + { + uint32 phase1; + uint32 phase2; + uint32 phase3; + } random_phase; + // ACTION_T_RANDOM_PHASE_RANGE = 31 + struct + { + uint32 phaseMin; + uint32 phaseMax; + } random_phase_range; + // ACTION_T_SUMMON_ID = 32 + struct + { + uint32 creatureId; + uint32 target; + uint32 spawnId; + } summon_id; + // ACTION_T_KILLED_MONSTER = 33 + struct + { + uint32 creatureId; + uint32 target; + } killed_monster; + // ACTION_T_SET_INST_DATA = 34 + struct + { + uint32 field; + uint32 value; + } set_inst_data; + // ACTION_T_SET_INST_DATA64 = 35 + struct + { + uint32 field; + uint32 target; + } set_inst_data64; + // ACTION_T_UPDATE_TEMPLATE = 36, //*Entry, Team + struct + { + uint32 creatureId; + uint32 team; + } update_template; + // RAW + struct + { + uint32 param1; + uint32 param2; + uint32 param3; + } raw; + }; +}; + struct CreatureEventAI_Event { uint32 event_id; @@ -179,44 +376,119 @@ struct CreatureEventAI_Event union { - uint32 event_param1; - int32 event_param1_s; - }; - union - { - uint32 event_param2; - int32 event_param2_s; - }; - union - { - uint32 event_param3; - int32 event_param3_s; - }; - union - { - uint32 event_param4; - int32 event_param4_s; - }; + // EVENT_T_TIMER = 0 + // EVENT_T_TIMER_OOC = 1 + struct + { + uint32 initialMin; + uint32 initialMax; + uint32 repeatMin; + uint32 repeatMax; + } timer; + // EVENT_T_HP = 2 + // EVENT_T_MANA = 3 + // EVENT_T_TARGET_HP = 12 + // EVENT_T_TARGET_MANA = 18 + struct + { + uint32 percentMax; + uint32 percentMin; + uint32 repeatMin; + uint32 repeatMax; + } percent_range; + // EVENT_T_KILL = 5 + struct + { + uint32 repeatMin; + uint32 repeatMax; + } kill; + // EVENT_T_SPELLHIT = 8 + struct + { + uint32 spellId; + uint32 schoolMask; // -1 (==0xffffffff) is ok value for full mask, or must be more limited mask like (0 < 1) = 1 for normal/physical school + uint32 repeatMin; + uint32 repeatMax; + } spell_hit; + // EVENT_T_RANGE = 9 + struct + { + uint32 minDist; + uint32 maxDist; + uint32 repeatMin; + uint32 repeatMax; + } range; + // EVENT_T_OOC_LOS = 10 + struct + { + uint32 noHostile; + uint32 maxRange; + uint32 repeatMin; + uint32 repeatMax; + } ooc_los; + // EVENT_T_TARGET_CASTING = 13 + struct + { + uint32 repeatMin; + uint32 repeatMax; + } target_casting; + // EVENT_T_FRIENDLY_HP = 14 + struct + { + uint32 hpDeficit; + uint32 radius; + uint32 repeatMin; + uint32 repeatMax; + } friendly_hp; + // EVENT_T_FRIENDLY_IS_CC = 15 + struct + { + uint32 dispelType; // unused ? + uint32 radius; + uint32 repeatMin; + uint32 repeatMax; + } friendly_is_cc; + // EVENT_T_FRIENDLY_MISSING_BUFF = 16 + struct + { + uint32 spellId; + uint32 radius; + uint32 repeatMin; + uint32 repeatMax; + } friendly_buff; + // EVENT_T_SUMMONED_UNIT = 17 + struct + { + uint32 creatureId; + uint32 repeatMin; + uint32 repeatMax; + } summon_unit; + // EVENT_T_QUEST_ACCEPT = 19 + // EVENT_T_QUEST_COMPLETE = 20 + struct + { + uint32 questId; + } quest; + // EVENT_T_RECEIVE_EMOTE = 22 + struct + { + uint32 emoteId; + uint32 condition; + uint32 conditionValue1; + uint32 conditionValue2; + } receive_emote; - struct _action - { - EventAI_ActionType type: 16; - union + // RAW + struct { uint32 param1; - int32 param1_s; - }; - union - { uint32 param2; - int32 param2_s; - }; - union - { uint32 param3; - int32 param3_s; - }; - }action[MAX_ACTIONS]; + uint32 param4; + } raw; + }; + + CreatureEventAI_Action action[MAX_ACTIONS]; }; //Event_Map typedef UNORDERED_MAP > CreatureEventAI_Event_Map; @@ -242,6 +514,9 @@ struct CreatureEventAIHolder CreatureEventAI_Event Event; uint32 Time; bool Enabled; + + // helper + bool UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax); }; class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI @@ -270,8 +545,9 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI static int Permissible(const Creature *); bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL); - void ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker); + void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker); inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3); + inline int32 GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3); inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker); inline Unit* SelectUnit(AttackingTarget target, uint32 position); diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index bd3631a75..b870ff4e4 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -205,10 +205,10 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() temp.event_inverse_phase_mask = fields[3].GetUInt32(); temp.event_chance = fields[4].GetUInt8(); temp.event_flags = fields[5].GetUInt8(); - temp.event_param1 = fields[6].GetUInt32(); - temp.event_param2 = fields[7].GetUInt32(); - temp.event_param3 = fields[8].GetUInt32(); - temp.event_param4 = fields[9].GetUInt32(); + temp.raw.param1 = fields[6].GetUInt32(); + temp.raw.param2 = fields[7].GetUInt32(); + temp.raw.param3 = fields[8].GetUInt32(); + temp.raw.param4 = fields[9].GetUInt32(); //Creature does not exist in database if (!sCreatureStorage.LookupEntry(temp.creature_id)) @@ -232,87 +232,97 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() { case EVENT_T_TIMER: case EVENT_T_TIMER_OOC: - { - if (temp.event_param2 < temp.event_param1) + if (temp.timer.initialMax < temp.timer.initialMin) sLog.outErrorDb("CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); - - if (temp.event_param4 < temp.event_param3) + if (temp.timer.repeatMax < temp.timer.repeatMin) sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - } - case EVENT_T_HP: case EVENT_T_MANA: case EVENT_T_TARGET_HP: - { - if (temp.event_param2 > 100) + case EVENT_T_TARGET_MANA: + if (temp.percent_range.percentMax > 100) sLog.outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i); - if (temp.event_param1 <= temp.event_param2) + if (temp.percent_range.percentMax <= temp.percent_range.percentMin) sLog.outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i); - if (temp.event_flags & EFLAG_REPEATABLE && !temp.event_param3 && !temp.event_param4) + if (temp.event_flags & EFLAG_REPEATABLE && !temp.percent_range.repeatMin && !temp.percent_range.repeatMax) { sLog.outErrorDb("CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i); temp.event_flags &= ~EFLAG_REPEATABLE; } break; - } - case EVENT_T_SPELLHIT: - { - if (temp.event_param1) + if (temp.spell_hit.spellId) { - SpellEntry const* pSpell = sSpellStore.LookupEntry(temp.event_param1); + SpellEntry const* pSpell = sSpellStore.LookupEntry(temp.spell_hit.spellId); if (!pSpell) { - sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i); + sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); continue; } - if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask) - sLog.outErrorDb("CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i); + if ((temp.spell_hit.schoolMask & pSpell->SchoolMask) != pSpell->SchoolMask) + sLog.outErrorDb("CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.spell_hit.schoolMask, i); } - //TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0 - //SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit() - if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL) - sLog.outErrorDb("CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i); + if (!temp.spell_hit.schoolMask) + sLog.outErrorDb("CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.spell_hit.schoolMask, i); - if (temp.event_param4 < temp.event_param3) + if (temp.spell_hit.repeatMax < temp.spell_hit.repeatMin) sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; - } - case EVENT_T_RANGE: + if (temp.range.maxDist < temp.range.minDist) + sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (MaxDist < MinDist). Event will never repeat.", temp.creature_id, i); + if (temp.range.repeatMax < temp.range.repeatMin) + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; case EVENT_T_OOC_LOS: + if (temp.ooc_los.repeatMax < temp.ooc_los.repeatMin) + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; case EVENT_T_FRIENDLY_HP: + if (temp.friendly_hp.repeatMax < temp.friendly_hp.repeatMin) + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; case EVENT_T_FRIENDLY_IS_CC: + if (temp.friendly_is_cc.repeatMax < temp.friendly_is_cc.repeatMin) + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; case EVENT_T_FRIENDLY_MISSING_BUFF: { - //Disabled check for now. Check code related to events and adjust accordingly before enable. - //Events should have min/max or alternative set to a static value. - /*if (!temp.event_param3 && !temp.event_param4) + SpellEntry const* pSpell = sSpellStore.LookupEntry(temp.spell_hit.spellId); + if (!pSpell) { - sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) without param3/param4 (RepeatMin/RepeatMax). Using minimum values.", temp.creature_id, i); - temp.event_param3 = 2500; - temp.event_param4 = 2500; - }*/ - - if (temp.event_param4 < temp.event_param3) + sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); + continue; + } + if (temp.friendly_buff.repeatMax < temp.friendly_buff.repeatMin) sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; } - case EVENT_T_KILL: - case EVENT_T_TARGET_CASTING: - { - if (temp.event_param2 < temp.event_param1) + if (temp.kill.repeatMax < temp.kill.repeatMin) sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - } + case EVENT_T_TARGET_CASTING: + if (temp.target_casting.repeatMax < temp.target_casting.repeatMin) + sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; + case EVENT_T_SUMMONED_UNIT: + if (!sCreatureStorage.LookupEntry(temp.summon_unit.creatureId)) + sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.summon_unit.creatureId); + if (temp.summon_unit.repeatMax < temp.summon_unit.repeatMin) + sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; + case EVENT_T_QUEST_ACCEPT: + case EVENT_T_QUEST_COMPLETE: + if (!objmgr.GetQuestTemplate(temp.quest.questId)) + sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with not existed qyest id (%u) in param1, skipped.", temp.creature_id, i, temp.quest.questId); + sLog.outErrorDb("CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i); + continue; case EVENT_T_AGGRO: case EVENT_T_DEATH: @@ -331,21 +341,15 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() case EVENT_T_RECEIVE_EMOTE: { - if (!sEmotesTextStore.LookupEntry(temp.event_param1)) + if (!sEmotesTextStore.LookupEntry(temp.receive_emote.emoteId)) { - sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.",temp.creature_id, i, temp.event_param1); + sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.",temp.creature_id, i, temp.receive_emote.emoteId); continue; } - if (temp.event_param2 == CONDITION_AD_COMMISSION_AURA || temp.event_param2 == CONDITION_NO_AURA) + if (!PlayerCondition::IsValid(ConditionType(temp.receive_emote.condition), temp.receive_emote.conditionValue1, temp.receive_emote.conditionValue2)) { - sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not implemented for EventAI.",temp.creature_id, i, temp.event_param2); - continue; - } - - if (!PlayerCondition::IsValid(ConditionType(temp.event_param2), temp.event_param3, temp.event_param4)) - { - sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.",temp.creature_id, i, temp.event_param2); + sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.",temp.creature_id, i, temp.receive_emote.condition); continue; } @@ -358,21 +362,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() break; } - case EVENT_T_SUMMONED_UNIT: - { - if (!sCreatureStorage.LookupEntry(temp.event_param1)) - sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.event_param1); - - if (temp.event_param3 < temp.event_param2) - sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param3 < param2 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - - break; - } - - case EVENT_T_QUEST_ACCEPT: - case EVENT_T_QUEST_COMPLETE: - sLog.outErrorDb("CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i); - continue; default: sLog.outErrorDb("CreatureEventAI: Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i); break; @@ -388,251 +377,254 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() continue; } - temp.action[j].type = EventAI_ActionType(action_type); - temp.action[j].param1 = fields[11+(j*4)].GetUInt32(); - temp.action[j].param2 = fields[12+(j*4)].GetUInt32(); - temp.action[j].param3 = fields[13+(j*4)].GetUInt32(); + CreatureEventAI_Action& action = temp.action[j]; + + action.type = EventAI_ActionType(action_type); + action.raw.param1 = fields[11+(j*4)].GetUInt32(); + action.raw.param2 = fields[12+(j*4)].GetUInt32(); + action.raw.param3 = fields[13+(j*4)].GetUInt32(); //Report any errors in actions - switch (temp.action[j].type) + switch (action.type) { case ACTION_T_NONE: break; case ACTION_T_TEXT: { - if (temp.action[j].param1_s < 0) + if (action.text.TextId1 < 0) { - if (m_CreatureEventAI_TextMap.find(temp.action[j].param1_s) == m_CreatureEventAI_TextMap.end()) + if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end()) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1); } - if (temp.action[j].param2_s < 0) + if (action.text.TextId2 < 0) { - if (m_CreatureEventAI_TextMap.find(temp.action[j].param2_s) == m_CreatureEventAI_TextMap.end()) + if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end()) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1); - if (!temp.action[j].param1_s) + if (!action.text.TextId1) sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1); } - if (temp.action[j].param3_s < 0) + if (action.text.TextId3 < 0) { - if (m_CreatureEventAI_TextMap.find(temp.action[j].param3_s) == m_CreatureEventAI_TextMap.end()) + if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end()) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1); - if (!temp.action[j].param1_s || !temp.action[j].param2_s) + if (!action.text.TextId1 || !action.text.TextId2) sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1); } break; } case ACTION_T_SET_FACTION: - if (temp.action[j].param1 !=0 && !sFactionStore.LookupEntry(temp.action[j].param1)) + if (action.set_faction.factionId !=0 && !sFactionStore.LookupEntry(action.set_faction.factionId)) { - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1); - temp.action[j].param1 = 0; + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent FactionId %u.", i, j+1, action.set_faction.factionId); + action.set_faction.factionId = 0; } break; case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: - if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0) + if (action.morph.creatireId !=0 || action.morph.modelId !=0) { - if (temp.action[j].param1 && !sCreatureStorage.LookupEntry(temp.action[j].param1)) + if (action.morph.creatireId && !sCreatureStorage.LookupEntry(action.morph.creatireId)) { - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, temp.action[j].param1); - temp.action[j].param1 = 0; + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, action.morph.creatireId); + action.morph.creatireId = 0; } - if (temp.action[j].param2 && !sCreatureDisplayInfoStore.LookupEntry(temp.action[j].param2)) + if (action.morph.modelId) { - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2); - temp.action[j].param2 = 0; + if (action.morph.creatireId) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.morph.modelId,action.morph.creatireId); + action.morph.modelId = 0; + } + else if (!sCreatureDisplayInfoStore.LookupEntry(action.morph.modelId)) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, action.morph.modelId); + action.morph.modelId = 0; + } } + + break; } - break; case ACTION_T_SOUND: - if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1); - break; - case ACTION_T_RANDOM_SOUND: - if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, temp.action[j].param1); - if (temp.action[j].param2_s >= 0 && !sSoundEntriesStore.LookupEntry(temp.action[j].param2)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, temp.action[j].param2); - if (temp.action[j].param3_s >= 0 && !sSoundEntriesStore.LookupEntry(temp.action[j].param3)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3); + if (!sSoundEntriesStore.LookupEntry(action.sound.soundId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId); break; case ACTION_T_EMOTE: - if (!sEmotesStore.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1); + if (!sEmotesStore.LookupEntry(action.emote.emoteId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.emote.emoteId); + break; + case ACTION_T_RANDOM_SOUND: + if (!sSoundEntriesStore.LookupEntry(action.random_sound.soundId1)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId1); + if (action.random_sound.soundId2 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId2)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId2); + if (action.random_sound.soundId3 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId3)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId3); break; case ACTION_T_RANDOM_EMOTE: - if (!sEmotesStore.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1); - if (temp.action[j].param2_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param2)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param2); - if (temp.action[j].param3_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param3)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param3); + if (!sEmotesStore.LookupEntry(action.random_emote.emoteId1)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId1); + if (action.random_emote.emoteId2 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId2)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId2); + if (action.random_emote.emoteId3 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId3)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId3); break; case ACTION_T_CAST: { - const SpellEntry *spell = sSpellStore.LookupEntry(temp.action[j].param1); + const SpellEntry *spell = sSpellStore.LookupEntry(action.cast.spellId); if (!spell) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1); + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast.spellId); + /* FIXME: temp.raw.param3 not have event tipes with recovery time in it.... else { if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE) { //output as debug for now, also because there's no general rule all spells have RecoveryTime if (temp.event_param3 < spell->RecoveryTime) - sLog.outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,temp.action[j].param1, spell->RecoveryTime, temp.event_param3); + sLog.outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,action.cast.spellId, spell->RecoveryTime, temp.event_param3); } } + */ - if (temp.action[j].param2 >= TARGET_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - } - case ACTION_T_REMOVEAURASFROMSPELL: - { - if (!sSpellStore.LookupEntry(temp.action[j].param2)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); + //Cast is always triggered if target is forced to cast on self + if (action.cast.castFlags & CAST_FORCE_TARGET_SELF) + action.cast.castFlags |= CAST_TRIGGERED; - if (temp.action[j].param1 >= TARGET_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - } - case ACTION_T_QUEST_EVENT: - { - if (Quest const* qid = objmgr.GetQuestTemplate(temp.action[j].param1)) - { - if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1); - } - else - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1); - - if (temp.action[j].param2 >= TARGET_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - - break; - } - case ACTION_T_QUEST_EVENT_ALL: - { - if (Quest const* qid = objmgr.GetQuestTemplate(temp.action[j].param1)) - { - if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1); - } - else - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1); - break; - } - case ACTION_T_CASTCREATUREGO: - { - if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); - - if (!sSpellStore.LookupEntry(temp.action[j].param2)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); - - if (temp.action[j].param3 >= TARGET_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - } - case ACTION_T_CASTCREATUREGO_ALL: - { - if (!objmgr.GetQuestTemplate(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1); - - if (!sSpellStore.LookupEntry(temp.action[j].param2)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); - break; - } - - //2nd param target - case ACTION_T_SUMMON_ID: - { - if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); - - if (m_CreatureEventAI_Summon_Map.find(temp.action[j].param3) == m_CreatureEventAI_Summon_Map.end()) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, temp.action[j].param3); - - if (temp.action[j].param2 >= TARGET_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - } - case ACTION_T_KILLED_MONSTER: - { - if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); - - if (temp.action[j].param2 >= TARGET_T_END) + if (action.cast.target >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; } case ACTION_T_SUMMON: - { - if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); + if (!sCreatureStorage.LookupEntry(action.summon.creatured)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.summon.creatured); - if (temp.action[j].param2 >= TARGET_T_END) + if (action.summon.target >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; - } case ACTION_T_THREAT_SINGLE_PCT: + if (std::abs(action.threat_single_pct.percent) > 100) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_single_pct.percent); + if (action.threat_single_pct.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; + case ACTION_T_THREAT_ALL_PCT: + if (std::abs(action.threat_all_pct.percent) > 100) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_all_pct.percent); + break; + case ACTION_T_QUEST_EVENT: + if (Quest const* qid = objmgr.GetQuestTemplate(action.quest_event.questId)) + { + if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event.questId); + } + else + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event.questId); + + if (action.quest_event.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + + break; + case ACTION_T_CAST_EVENT: + if (!sCreatureStorage.LookupEntry(action.cast_event.creatureId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event.creatureId); + if (!sSpellStore.LookupEntry(action.cast_event.spellId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event.spellId); + if (action.cast_event.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; + case ACTION_T_SET_UNIT_FIELD: + if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1); + if (action.set_unit_field.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; case ACTION_T_SET_UNIT_FLAG: case ACTION_T_REMOVE_UNIT_FLAG: - if (temp.action[j].param2 >= TARGET_T_END) + if (action.unit_flag.target >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; - //3rd param target - case ACTION_T_SET_UNIT_FIELD: - if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1); - if (temp.action[j].param3 >= TARGET_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_SET_PHASE: - if (temp.action[j].param1 > 31) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1); + if (action.set_phase.phase >= MAX_PHASE) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); break; - case ACTION_T_INC_PHASE: - if (!temp.action[j].param1) + if (action.set_inc_phase.step == 0) sLog.outErrorDb("CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1); + else if (std::abs(action.set_inc_phase.step) > MAX_PHASE-1) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u is change phase by too large for any use %i.", i, j+1, action.set_inc_phase.step); break; - - case ACTION_T_SET_INST_DATA: - { - if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1); - - if (temp.action[j].param2 > 4/*SPECIAL*/) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1); - + case ACTION_T_QUEST_EVENT_ALL: + if (Quest const* qid = objmgr.GetQuestTemplate(action.quest_event_all.questId)) + { + if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event_all.questId); + } + else + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event_all.questId); break; - } - case ACTION_T_SET_INST_DATA64: - { - if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1); - - if (temp.action[j].param2 >= TARGET_T_END) + case ACTION_T_CAST_EVENT_ALL: + if (!sCreatureStorage.LookupEntry(action.cast_event_all.creatureId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event_all.creatureId); + if (!sSpellStore.LookupEntry(action.cast_event_all.spellId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event_all.spellId); + break; + case ACTION_T_REMOVEAURASFROMSPELL: + if (!sSpellStore.LookupEntry(action.remove_aura.spellId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.remove_aura.spellId); + if (action.remove_aura.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; + case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3 + if (action.random_phase.phase1 >= MAX_PHASE) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase1 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); + if (action.random_phase.phase2 >= MAX_PHASE) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase2 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); + if (action.random_phase.phase3 >= MAX_PHASE) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase3 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); + break; + case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax + if (action.random_phase_range.phaseMin >= MAX_PHASE) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMin >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); + if (action.random_phase_range.phaseMin >= MAX_PHASE) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMax >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); + if (action.random_phase_range.phaseMin >= action.random_phase_range.phaseMax) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMax <= phaseMin.", i, j+1); + std::swap(action.random_phase_range.phaseMin,action.random_phase_range.phaseMax); + // equal case processed at call + } + break; + case ACTION_T_SUMMON_ID: + if (!sCreatureStorage.LookupEntry(action.summon_id.creatureId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.summon_id.creatureId); + if (action.summon_id.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + if (m_CreatureEventAI_Summon_Map.find(action.summon_id.spawnId) == m_CreatureEventAI_Summon_Map.end()) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, action.summon_id.spawnId); + break; + case ACTION_T_KILLED_MONSTER: + if (!sCreatureStorage.LookupEntry(action.killed_monster.creatureId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.killed_monster.creatureId); + if (action.killed_monster.target >= TARGET_T_END) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; + case ACTION_T_SET_INST_DATA: + if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1); + if (action.set_inst_data.value > 4/*SPECIAL*/) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1); + break; + case ACTION_T_SET_INST_DATA64: + if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1); + if (action.set_inst_data64.target >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - } case ACTION_T_UPDATE_TEMPLATE: - { - if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); + if (!sCreatureStorage.LookupEntry(action.update_template.creatureId)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId); break; - } - - case ACTION_T_THREAT_ALL_PCT: - if (abs(temp.action[j].param1_s) > 100) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, temp.action[j].param1); - break; - case ACTION_T_EVADE: //No Params case ACTION_T_FLEE: //No Params case ACTION_T_DIE: //No Params @@ -642,11 +634,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() case ACTION_T_RANGED_MOVEMENT: //Distance, Angle break; - case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3 - case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax - // check not implemented - break; - case ACTION_T_RANDOM_SAY: case ACTION_T_RANDOM_YELL: case ACTION_T_RANDOM_TEXTEMOTE: diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index ce8bf7498..f3ea8f36d 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -104,4 +104,4 @@ const char WorldMapAreaEntryfmt[]="xinxffffix"; const char WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx"; const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; -#endif \ No newline at end of file +#endif diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 75d1ef9c9..583732a65 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -540,7 +540,7 @@ void MaNGOS::PlayerSearcher::Visit(PlayerMapType &m) template void MaNGOS::LocalizedPacketDo::operator()( Player* p ) { - uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); uint32 cache_idx = loc_idx+1; WorldPacket* data; @@ -565,7 +565,7 @@ void MaNGOS::LocalizedPacketDo::operator()( Player* p ) template void MaNGOS::LocalizedPacketListDo::operator()( Player* p ) { - uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); uint32 cache_idx = loc_idx+1; WorldPacketList* data_list; diff --git a/src/game/Language.h b/src/game/Language.h index 5b64cf570..e1c15fb01 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -94,7 +94,6 @@ enum MangosStrings LANG_CANNOT_GO_TO_INST_GM = 105, LANG_CANNOT_GO_INST_INST = 106, LANG_CANNOT_SUMMON_INST_INST = 107, - LANG_SUMMONING = 108, LANG_SUMMONED_BY = 109, LANG_TELEPORTING_TO = 110, @@ -102,7 +101,6 @@ enum MangosStrings LANG_NO_PLAYER = 112, LANG_APPEARING_AT = 113, LANG_APPEARING_TO = 114, - LANG_BAD_VALUE = 115, LANG_NO_CHAR_SELECTED = 116, LANG_NOT_IN_GROUP = 117, @@ -167,7 +165,7 @@ enum MangosStrings LANG_MAIL_SENT = 169, LANG_SOUND_NOT_EXIST = 170, - // 171, // not used + LANG_CANT_TELEPORT_SELF = 171, LANG_CONSOLE_COMMAND = 172, LANG_YOU_CHANGE_RUNIC_POWER = 173, LANG_YOURS_RUNIC_POWER_CHANGED = 174, @@ -266,7 +264,7 @@ enum MangosStrings LANG_COMMAND_ADDVENDORITEMITEMS = 280, LANG_COMMAND_KICKSELF = 281, LANG_COMMAND_KICKMESSAGE = 282, - LANG_COMMAND_KICKNOTFOUNDPLAYER = 283, + // 283, not used LANG_COMMAND_WHISPERACCEPTING = 284, LANG_COMMAND_WHISPERON = 285, LANG_COMMAND_WHISPEROFF = 286, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index e8c9e973e..591f7b447 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -309,9 +309,9 @@ bool ChatHandler::HandleGPSCommand(const char* args) uint32 have_vmap = Map::ExistVMap(obj->GetMapId(),gx,gy) ? 1 : 0; PSendSysMessage(LANG_MAP_POSITION, - obj->GetMapId(), (mapEntry ? mapEntry->name[m_session->GetSessionDbcLocale()] : "" ), - zone_id, (zoneEntry ? zoneEntry->area_name[m_session->GetSessionDbcLocale()] : "" ), - area_id, (areaEntry ? areaEntry->area_name[m_session->GetSessionDbcLocale()] : "" ), + obj->GetMapId(), (mapEntry ? mapEntry->name[GetSessionDbcLocale()] : "" ), + zone_id, (zoneEntry ? zoneEntry->area_name[GetSessionDbcLocale()] : "" ), + area_id, (areaEntry ? areaEntry->area_name[GetSessionDbcLocale()] : "" ), obj->GetPhaseMask(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), @@ -343,26 +343,28 @@ bool ChatHandler::HandleGPSCommand(const char* args) //Summon Player bool ChatHandler::HandleNamegoCommand(const char* args) { - if(!*args) + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) + Player* _player = m_session->GetPlayer(); + if (target == _player || target_guid == _player->GetGUID()) { - SendSysMessage(LANG_PLAYER_NOT_FOUND); + PSendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); return false; } - Player *chr = objmgr.GetPlayer(name.c_str()); - if (chr) + if (target) { - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); // check online security - if (HasLowerSecurity(chr, 0)) + if (HasLowerSecurity(target, 0)) return false; - if(chr->IsBeingTeleported()) + if (target->IsBeingTeleported()) { PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); SetSentErrorMessage(true); @@ -371,32 +373,32 @@ bool ChatHandler::HandleNamegoCommand(const char* args) Map* pMap = m_session->GetPlayer()->GetMap(); - if(pMap->IsBattleGroundOrArena()) + if (pMap->IsBattleGroundOrArena()) { // only allow if gm mode is on - if (!chr->isGameMaster()) + if (!target->isGameMaster()) { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName()); + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,nameLink.c_str()); SetSentErrorMessage(true); return false; } // if both players are in different bgs - else if (chr->GetBattleGroundId() && m_session->GetPlayer()->GetBattleGroundId() != chr->GetBattleGroundId()) + else if (target->GetBattleGroundId() && m_session->GetPlayer()->GetBattleGroundId() != target->GetBattleGroundId()) { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName()); + PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,nameLink.c_str()); SetSentErrorMessage(true); return false; } // all's well, set bg id // when porting out from the bg, it will be reset to 0 - chr->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId(), m_session->GetPlayer()->GetBattleGroundTypeId()); + target->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId(), m_session->GetPlayer()->GetBattleGroundTypeId()); // remember current position as entry point for return at bg end teleportation - chr->SetBattleGroundEntryPoint(chr->GetMapId(),chr->GetPositionX(),chr->GetPositionY(),chr->GetPositionZ(),chr->GetOrientation()); + target->SetBattleGroundEntryPoint(target->GetMapId(),target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),target->GetOrientation()); } - else if(pMap->IsDungeon()) + else if (pMap->IsDungeon()) { - Map* cMap = chr->GetMap(); - if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() ) + Map* cMap = target->GetMap(); + if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId()) { // cannot summon from instance to instance PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); @@ -405,9 +407,9 @@ bool ChatHandler::HandleNamegoCommand(const char* args) } // we are in instance, and can summon only player in our group with us as lead - if ( !m_session->GetPlayer()->GetGroup() || !chr->GetGroup() || - (chr->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || - (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) ) + if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || + (target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())) // the last check is a bit excessive, but let it be, just in case { PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); @@ -417,31 +419,31 @@ bool ChatHandler::HandleNamegoCommand(const char* args) } PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),""); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); // stop flight if need - if(chr->isInFlight()) + if (target->isInFlight()) { - chr->GetMotionMaster()->MovementExpired(); - chr->m_taxi.ClearTaxiDestinations(); + target->GetMotionMaster()->MovementExpired(); + target->m_taxi.ClearTaxiDestinations(); } // save only in non-flight case else - chr->SaveRecallPosition(); + target->SaveRecallPosition(); // before GM float x,y,z; - m_session->GetPlayer()->GetClosePoint(x,y,z,chr->GetObjectSize()); - chr->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,chr->GetOrientation()); + m_session->GetPlayer()->GetClosePoint(x,y,z,target->GetObjectSize()); + target->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,target->GetOrientation()); } - else if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) + else { // check offline security - if (HasLowerSecurity(NULL, guid)) + if (HasLowerSecurity(NULL, target_guid)) return false; - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),GetMangosString(LANG_OFFLINE)); @@ -452,12 +454,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args) m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetOrientation(), m_session->GetPlayer()->GetZoneId(), - guid); - } - else - { - PSendSysMessage(LANG_NO_PLAYER, args); - SetSentErrorMessage(true); + target_guid); } return true; @@ -466,30 +463,31 @@ bool ChatHandler::HandleNamegoCommand(const char* args) //Teleport to Player bool ChatHandler::HandleGonameCommand(const char* args) { - if(!*args) + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; Player* _player = m_session->GetPlayer(); - - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) + if (target == _player || target_guid == _player->GetGUID()) { - SendSysMessage(LANG_PLAYER_NOT_FOUND); + SendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); return false; } - Player *chr = objmgr.GetPlayer(name.c_str()); - if (chr) + + if (target) { // check online security - if (HasLowerSecurity(chr, 0)) + if (HasLowerSecurity(target, 0)) return false; - std::string chrNameLink = playerLink(name); + std::string chrNameLink = playerLink(target_name); - Map* cMap = chr->GetMap(); - if(cMap->IsBattleGroundOrArena()) + Map* cMap = target->GetMap(); + if (cMap->IsBattleGroundOrArena()) { // only allow if gm mode is on if (!_player->isGameMaster()) @@ -499,7 +497,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) return false; } // if both players are in different bgs - else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != chr->GetBattleGroundId()) + else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != target->GetBattleGroundId()) { PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chrNameLink.c_str()); SetSentErrorMessage(true); @@ -507,7 +505,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) } // all's well, set bg id // when porting out from the bg, it will be reset to 0 - _player->SetBattleGroundId(chr->GetBattleGroundId(), chr->GetBattleGroundTypeId()); + _player->SetBattleGroundId(target->GetBattleGroundId(), target->GetBattleGroundTypeId()); // remember current position as entry point for return at bg end teleportation _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); } @@ -519,7 +517,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) if (_player->GetGroup()) { // we are in group, we can go only if we are in the player group - if (_player->GetGroup() != chr->GetGroup()) + if (_player->GetGroup() != target->GetGroup()) { PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chrNameLink.c_str()); SetSentErrorMessage(true); @@ -539,28 +537,27 @@ bool ChatHandler::HandleGonameCommand(const char* args) // if the player or the player's group is bound to another instance // the player will not be bound to another one - InstancePlayerBind *pBind = _player->GetBoundInstance(chr->GetMapId(), chr->GetDifficulty()); - if(!pBind) + InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty()); + if (!pBind) { Group *group = _player->GetGroup(); - InstanceGroupBind *gBind = group ? group->GetBoundInstance(chr->GetMapId(), chr->GetDifficulty()) : NULL; - if(!gBind) - { - // if no bind exists, create a solo bind - InstanceSave *save = sInstanceSaveManager.GetInstanceSave(chr->GetInstanceId()); - if(save) _player->BindToInstance(save, !save->CanReset()); - } + // if no bind exists, create a solo bind + InstanceGroupBind *gBind = group ? group->GetBoundInstance(target->GetMapId(), target->GetDifficulty()) : NULL; + // if no bind exists, create a solo bind + if (!gBind) + if (InstanceSave *save = sInstanceSaveManager.GetInstanceSave(target->GetInstanceId())) + _player->BindToInstance(save, !save->CanReset()); } - _player->SetDifficulty(chr->GetDifficulty()); + _player->SetDifficulty(target->GetDifficulty()); } PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); - if (_player->IsVisibleGloballyFor(chr)) - ChatHandler(chr).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); // stop flight if need - if(_player->isInFlight()) + if (_player->isInFlight()) { _player->GetMotionMaster()->MovementExpired(); _player->m_taxi.ClearTaxiDestinations(); @@ -571,20 +568,17 @@ bool ChatHandler::HandleGonameCommand(const char* args) // to point to see at target with same orientation float x,y,z; - chr->GetContactPoint(m_session->GetPlayer(),x,y,z); + target->GetContactPoint(_player,x,y,z); - _player->TeleportTo(chr->GetMapId(), x, y, z, _player->GetAngle( chr ), TELE_TO_GM_MODE); - - return true; + _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); } - - if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) + else { // check offline security - if (HasLowerSecurity(NULL, guid)) + if (HasLowerSecurity(NULL, target_guid)) return false; - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); @@ -592,83 +586,51 @@ bool ChatHandler::HandleGonameCommand(const char* args) float x,y,z,o; uint32 map; bool in_flight; - if(Player::LoadPositionFromDB(map,x,y,z,o,in_flight,guid)) - { - // stop flight if need - if(_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); + if (!Player::LoadPositionFromDB(map,x,y,z,o,in_flight,target_guid)) + return false; - _player->TeleportTo(map, x, y, z,_player->GetOrientation()); - return true; + // 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(map, x, y, z,_player->GetOrientation()); } - PSendSysMessage(LANG_NO_PLAYER, args); - - SetSentErrorMessage(true); - return false; + return true; } // Teleport player to last position bool ChatHandler::HandleRecallCommand(const char* args) { - Player* chr = NULL; + Player* target; + if(!extractPlayerTarget((char*)args,&target)) + return false; - if(!*args) + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + if (target->IsBeingTeleported()) { - chr = getSelectedPlayer(); - if(!chr) - chr = m_session->GetPlayer(); - - // check online security - else if (HasLowerSecurity(chr, 0)) - return false; - } - else - { - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - chr = objmgr.GetPlayer(name.c_str()); - - if(!chr) - { - PSendSysMessage(LANG_NO_PLAYER, args); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - } - - if(chr->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(chr).c_str()); + PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str()); SetSentErrorMessage(true); return false; } // stop flight if need - if(chr->isInFlight()) + if(target->isInFlight()) { - chr->GetMotionMaster()->MovementExpired(); - chr->m_taxi.ClearTaxiDestinations(); + target->GetMotionMaster()->MovementExpired(); + target->m_taxi.ClearTaxiDestinations(); } - chr->TeleportTo(chr->m_recallMap, chr->m_recallX, chr->m_recallY, chr->m_recallZ, chr->m_recallO); + target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); return true; } @@ -1856,7 +1818,7 @@ bool ChatHandler::HandleLookupAreaCommand(const char* args) AreaTableEntry const *areaEntry = sAreaStore.LookupEntry (areaflag); if (areaEntry) { - int loc = m_session ? m_session->GetSessionDbcLocale () : sWorld.GetDefaultDbcLocale(); + int loc = GetSessionDbcLocale (); std::string name = areaEntry->area_name[loc]; if (name.empty()) continue; @@ -1866,7 +1828,7 @@ bool ChatHandler::HandleLookupAreaCommand(const char* args) loc = 0; for(; loc < MAX_LOCALE; ++loc) { - if (m_session && loc==m_session->GetSessionDbcLocale ()) + if (loc==GetSessionDbcLocale ()) continue; name = areaEntry->area_name[loc]; @@ -1989,18 +1951,12 @@ bool ChatHandler::HandleSaveAllCommand(const char* /*args*/) //Send mail by command bool ChatHandler::HandleSendMailCommand(const char* args) { - if(!*args) - return false; - // format: name "subject text" "mail text" - - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - } char* tail1 = strtok(NULL, ""); if(!tail1) @@ -2042,14 +1998,6 @@ bool ChatHandler::HandleSendMailCommand(const char* args) std::string subject = msgSubject; std::string text = msgText; - uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); - if(!receiver_guid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - // from console show not existed sender uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0; @@ -2057,11 +2005,9 @@ bool ChatHandler::HandleSendMailCommand(const char* args) uint32 stationery = MAIL_STATIONERY_GM; uint32 itemTextId = !text.empty() ? objmgr.CreateItemText( text ) : 0; - Player *receiver = objmgr.GetPlayer(receiver_guid); + WorldSession::SendMailTo(target,messagetype, stationery, sender_guidlo, GUID_LOPART(target_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE); - WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE); - - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; } @@ -2069,23 +2015,20 @@ bool ChatHandler::HandleSendMailCommand(const char* args) // teleport player to given game_tele.entry bool ChatHandler::HandleTeleNameCommand(const char * args) { - if(!*args) + char* nameStr; + char* teleStr; + extractOptFirstArg((char*)args,&nameStr,&teleStr); + if(!teleStr) return false; - - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - char* tail = strtok(NULL, ""); - if(!tail) + + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) return false; // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = extractGameTeleFromLink(tail); + GameTele const* tele = extractGameTeleFromLink(teleStr); if(!tele) { SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); @@ -2093,16 +2036,15 @@ bool ChatHandler::HandleTeleNameCommand(const char * args) return false; } - Player *chr = objmgr.GetPlayer(name.c_str()); - if (chr) + if (target) { // check online security - if (HasLowerSecurity(chr, 0)) + if (HasLowerSecurity(target, 0)) return false; - std::string chrNameLink = playerLink(name); + std::string chrNameLink = playerLink(target_name); - if(chr->IsBeingTeleported()==true) + if(target->IsBeingTeleported()==true) { PSendSysMessage(LANG_IS_TELEPORTED, chrNameLink.c_str()); SetSentErrorMessage(true); @@ -2110,35 +2052,33 @@ bool ChatHandler::HandleTeleNameCommand(const char * args) } PSendSysMessage(LANG_TELEPORTING_TO, chrNameLink.c_str(),"", tele->name.c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); // stop flight if need - if(chr->isInFlight()) + if(target->isInFlight()) { - chr->GetMotionMaster()->MovementExpired(); - chr->m_taxi.ClearTaxiDestinations(); + target->GetMotionMaster()->MovementExpired(); + target->m_taxi.ClearTaxiDestinations(); } // save only in non-flight case else - chr->SaveRecallPosition(); + target->SaveRecallPosition(); - chr->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); + target->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); } - else if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) + else { // check offline security - if (HasLowerSecurity(NULL, guid)) + if (HasLowerSecurity(NULL, target_guid)) return false; - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str()); Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation, - MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),guid); + MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),target_guid); } - else - PSendSysMessage(LANG_NO_PLAYER, name.c_str()); return true; } @@ -2222,32 +2162,17 @@ bool ChatHandler::HandleTeleGroupCommand(const char * args) //Summon group of player bool ChatHandler::HandleGroupgoCommand(const char* args) { - if(!*args) + Player* target; + if(!extractPlayerTarget((char*)args,&target)) return false; - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - Player *player = objmgr.GetPlayer(name.c_str()); - if (!player) - { - PSendSysMessage(LANG_NO_PLAYER, args); - SetSentErrorMessage(true); - return false; - } - // check online security - if (HasLowerSecurity(player, 0)) + if (HasLowerSecurity(target, 0)) return false; - Group *grp = player->GetGroup(); + Group *grp = target->GetGroup(); - std::string nameLink = playerLink(name); + std::string nameLink = GetNameLink(target); if(!grp) { @@ -2281,7 +2206,7 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) if (HasLowerSecurity(pl, 0)) return false; - std::string plNameLink = playerLink(name); + std::string plNameLink = GetNameLink(pl); if(pl->IsBeingTeleported()==true) { @@ -2507,7 +2432,7 @@ bool ChatHandler::HandleGoZoneXYCommand(const char* args) if(map->Instanceable()) { - PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[m_session->GetSessionDbcLocale()],map->GetId(),map->GetMapName()); + PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName()); SetSentErrorMessage(true); return false; } diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 78d4f7c7a..9282ccdb4 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -52,104 +52,89 @@ static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] = //mute player for some times bool ChatHandler::HandleMuteCommand(const char* args) { - if (!*args) + char* nameStr; + char* delayStr; + extractOptFirstArg((char*)args,&nameStr,&delayStr); + if(!delayStr) return false; - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) return false; + + uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + // find only player from same account if any + if(!target) + { + if(WorldSession* session = sWorld.FindSession(account_id)) + target = session->GetPlayer(); } - char *timetonotspeak = strtok(NULL, " "); - if(!timetonotspeak) - return false; - - uint32 notspeaktime = (uint32) atoi(timetonotspeak); - - uint64 guid = objmgr.GetPlayerGUIDByName(name); - if(!guid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - Player *chr = objmgr.GetPlayer(guid); + uint32 notspeaktime = (uint32) atoi(delayStr); // must have strong lesser security level - if(HasLowerSecurity (chr,guid,true)) + if(HasLowerSecurity (target,target_guid,true)) return false; - uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid); - time_t mutetime = time(NULL) + notspeaktime*60; - if (chr) - chr->GetSession()->m_muteTime = mutetime; + if (target) + target->GetSession()->m_muteTime = mutetime; loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id ); - if(chr) - ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime); + if(target) + ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime); - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime); - return true; } //unmute player bool ChatHandler::HandleUnmuteCommand(const char* args) { - if (!*args) + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) + uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + // find only player from same account if any + if(!target) { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; + if(WorldSession* session = sWorld.FindSession(account_id)) + target = session->GetPlayer(); } - uint64 guid = objmgr.GetPlayerGUIDByName(name); - if(!guid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - Player *chr = objmgr.GetPlayer(guid); - // must have strong lesser security level - if(HasLowerSecurity (chr,guid,true)) + if(HasLowerSecurity (target,target_guid,true)) return false; - uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid); - - if (chr) + if (target) { - if(chr->CanSpeak()) + if(target->CanSpeak()) { SendSysMessage(LANG_CHAT_ALREADY_ENABLED); SetSentErrorMessage(true); return false; } - chr->GetSession()->m_muteTime = 0; + target->GetSession()->m_muteTime = 0; } loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id ); - if(chr) - ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); + if(target) + ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str()); return true; @@ -889,7 +874,7 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args) { FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; - int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + int loc = GetSessionDbcLocale(); std::string name = factionEntry->name[loc]; if(name.empty()) continue; @@ -899,7 +884,7 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args) loc = 0; for(; loc < MAX_LOCALE; ++loc) { - if(m_session && loc==m_session->GetSessionDbcLocale()) + if(loc==GetSessionDbcLocale()) continue; name = factionEntry->name[loc]; @@ -1044,13 +1029,13 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) if (factionEntry->reputationListID < 0) { - PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId); + PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId); SetSentErrorMessage(true); return false; } target->GetReputationMgr().SetReputation(factionEntry,amount); - PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, + PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId, GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry)); return true; } @@ -2071,62 +2056,24 @@ bool ChatHandler::HandleModifyMorphCommand(const char* args) //kick player bool ChatHandler::HandleKickPlayerCommand(const char *args) { - if (!*args) + Player* target; + if(!extractPlayerTarget((char*)args,&target)) + return false; + + if (m_session && target==m_session->GetPlayer()) { - Player* player = getSelectedPlayer(); - - if(!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if(player==m_session->GetPlayer()) - { - SendSysMessage(LANG_COMMAND_KICKSELF); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(player, 0)) - return false; - - player->GetSession()->KickPlayer(); - } - else - { - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - if(m_session && name==m_session->GetPlayer()->GetName()) - { - SendSysMessage(LANG_COMMAND_KICKSELF); - SetSentErrorMessage(true); - return false; - } - - // check online security - Player* player = ObjectAccessor::Instance().FindPlayerByName(name.c_str()); - if (player && HasLowerSecurity(player, 0)) - return false; - - std::string nameLink = playerLink(name); - - if(sWorld.KickPlayer(name)) - { - PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str()); - } - else - PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str()); + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; } + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + // send before target pointer invalidate + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str()); + target->GetSession()->KickPlayer(); return true; } @@ -2154,48 +2101,11 @@ bool ChatHandler::HandleModifyPhaseCommand(const char* args) //show info of player bool ChatHandler::HandlePInfoCommand(const char* args) { - Player* target = NULL; - uint64 targetGUID = 0; - - char* px = strtok((char*)args, " "); - char* py = NULL; - - std::string name; - - if (px) - { - name = extractPlayerNameFromLink(px); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - target = objmgr.GetPlayer(name.c_str()); - if (target) - py = strtok(NULL, " "); - else - { - targetGUID = objmgr.GetPlayerGUIDByName(name); - if(targetGUID) - py = strtok(NULL, " "); - else - py = px; - } - } - - if(!target && !targetGUID) - { - target = getSelectedPlayer(); - } - - if(!target && !targetGUID) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - } uint32 accId = 0; uint32 money = 0; @@ -2210,8 +2120,6 @@ bool ChatHandler::HandlePInfoCommand(const char* args) if (HasLowerSecurity(target, 0)) return false; - targetGUID = target->GetGUID(); - name = target->GetName(); // re-read for case getSelectedPlayer() target accId = target->GetSession()->GetAccountId(); money = target->GetMoney(); total_player_time = target->GetTotalPlayedTime(); @@ -2222,33 +2130,25 @@ bool ChatHandler::HandlePInfoCommand(const char* args) else { // check offline security - if (HasLowerSecurity(NULL, targetGUID)) + if (HasLowerSecurity(NULL, target_guid)) return false; // 0 - QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID)); + QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid)); if (!result) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); return false; - } + Field *fields = result->Fetch(); total_player_time = fields[0].GetUInt32(); delete result; Tokens data; - if (!Player::LoadValuesArrayFromDB(data,targetGUID)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + if (!Player::LoadValuesArrayFromDB(data,target_guid)) return false; - } money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE); level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL); - - accId = objmgr.GetPlayerAccountIdByGUID(targetGUID); + accId = objmgr.GetPlayerAccountIdByGUID(target_guid); } std::string username = GetMangosString(LANG_ERROR); @@ -2277,9 +2177,9 @@ bool ChatHandler::HandlePInfoCommand(const char* args) delete result; } - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency); + PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency); std::string timeStr = secsToTimeString(total_player_time,true,true); uint32 gold = money /GOLD; @@ -2287,43 +2187,6 @@ bool ChatHandler::HandlePInfoCommand(const char* args) uint32 copp = (money % GOLD) % SILVER; PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp ); - if ( py && strncmp(py, "rep", 3) == 0 ) - { - if(!target) - { - // rep option not implemented for offline case - SendSysMessage(LANG_PINFO_NO_REP); - SetSentErrorMessage(true); - return false; - } - - FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); - for(FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) - { - FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); - char const* factionName = factionEntry ? factionEntry->name[m_session->GetSessionDbcLocale()] : "#Not found#"; - ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); - std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); - std::ostringstream ss; - ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << "]|h|r " << rankName << "|h|r (" - << target->GetReputationMgr().GetReputation(factionEntry) << ")"; - - if(itr->second.Flags & FACTION_FLAG_VISIBLE) - ss << GetMangosString(LANG_FACTION_VISIBLE); - if(itr->second.Flags & FACTION_FLAG_AT_WAR) - ss << GetMangosString(LANG_FACTION_ATWAR); - if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED) - ss << GetMangosString(LANG_FACTION_PEACE_FORCED); - if(itr->second.Flags & FACTION_FLAG_HIDDEN) - ss << GetMangosString(LANG_FACTION_HIDDEN); - if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) - ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED); - if(itr->second.Flags & FACTION_FLAG_INACTIVE) - ss << GetMangosString(LANG_FACTION_INACTIVE); - - SendSysMessage(ss.str().c_str()); - } - } return true; } @@ -2416,27 +2279,18 @@ bool ChatHandler::HandleTicketCommand(const char* args) return true; } - std::string name = extractPlayerNameFromLink(px); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = objmgr.GetPlayerGUIDByName(name); - - if(!guid) + uint64 target_guid; + if(!extractPlayerTarget(px,NULL,&target_guid)) return false; // ticket $char_name - GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid)); + GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(target_guid)); if(!ticket) return false; std::string time = TimeToTimestampStr(ticket->GetLastUpdate()); - ShowTicket(guid, ticket->GetText(), time.c_str()); + ShowTicket(target_guid, ticket->GetText(), time.c_str()); return true; } @@ -2486,27 +2340,20 @@ bool ChatHandler::HandleDelTicketCommand(const char *args) return true; } - std::string name = extractPlayerNameFromLink(px); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = objmgr.GetPlayerGUIDByName(name); - - if(!guid) + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget(px,&target,&target_guid,&target_name)) return false; // delticket $char_name - ticketmgr.Delete(GUID_LOPART(guid)); + ticketmgr.Delete(GUID_LOPART(target_guid)); // notify players about ticket deleting - if(Player* sender = objmgr.GetPlayer(guid)) - sender->GetSession()->SendGMTicketGetTicket(0x0A,0); + if(target) + target->GetSession()->SendGMTicketGetTicket(0x0A,0); - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str()); return true; @@ -3657,39 +3504,11 @@ bool ChatHandler::HandleWpImportCommand(const char *args) //rename characters bool ChatHandler::HandleCharacterRenameCommand(const char* args) { - Player* target = NULL; - uint64 targetGUID = 0; - std::string oldname; - - char* px = strtok((char*)args, " "); - - if(px) - { - oldname = extractPlayerNameFromLink(px); - if(oldname.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - target = objmgr.GetPlayer(oldname.c_str()); - - if (!target) - targetGUID = objmgr.GetPlayerGUIDByName(oldname); - } - - if(!target && !targetGUID) - { - target = getSelectedPlayer(); - } - - if(!target && !targetGUID) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - } if(target) { @@ -3704,13 +3523,13 @@ bool ChatHandler::HandleCharacterRenameCommand(const char* args) else { // check offline security - if (HasLowerSecurity(NULL, targetGUID)) + if (HasLowerSecurity(NULL, target_guid)) return false; - std::string oldNameLink = playerLink(oldname); + std::string oldNameLink = playerLink(target_name); - PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID)); - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID)); + PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid)); } return true; @@ -3719,39 +3538,11 @@ bool ChatHandler::HandleCharacterRenameCommand(const char* args) // customize characters bool ChatHandler::HandleCharacterCustomizeCommand(const char* args) { - Player* target = NULL; - uint64 targetGUID = 0; - std::string oldname; - - char* px = strtok((char*)args, " "); - - if(px) - { - oldname = extractPlayerNameFromLink(px); - if(oldname.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - target = objmgr.GetPlayer(oldname.c_str()); - - if (!target) - targetGUID = objmgr.GetPlayerGUIDByName(oldname); - } - - if(!target && !targetGUID) - { - target = getSelectedPlayer(); - } - - if(!target && !targetGUID) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - } if(target) { @@ -3761,15 +3552,56 @@ bool ChatHandler::HandleCharacterCustomizeCommand(const char* args) } else { - std::string oldNameLink = playerLink(oldname); + std::string oldNameLink = playerLink(target_name); - PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID)); - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID)); + PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid)); } return true; } +bool ChatHandler::HandleCharacterReputationCommand(const char* args) +{ + Player* target; + if(!extractPlayerTarget((char*)args,&target)) + return false; + + LocaleConstant loc = GetSessionDbcLocale(); + + FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); + for(FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); + char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#"; + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); + std::ostringstream ss; + if (m_session) + ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r"; + else + ss << itr->second.ID << " - " << factionName << " " << localeNames[loc]; + + ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; + + if(itr->second.Flags & FACTION_FLAG_VISIBLE) + ss << GetMangosString(LANG_FACTION_VISIBLE); + if(itr->second.Flags & FACTION_FLAG_AT_WAR) + ss << GetMangosString(LANG_FACTION_ATWAR); + if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetMangosString(LANG_FACTION_PEACE_FORCED); + if(itr->second.Flags & FACTION_FLAG_HIDDEN) + ss << GetMangosString(LANG_FACTION_HIDDEN); + if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED); + if(itr->second.Flags & FACTION_FLAG_INACTIVE) + ss << GetMangosString(LANG_FACTION_INACTIVE); + + SendSysMessage(ss.str().c_str()); + } + return true; +} + //change standstate bool ChatHandler::HandleModifyStandStateCommand(const char* args) { @@ -4048,41 +3880,16 @@ bool ChatHandler::HandleEventStopCommand(const char* args) bool ChatHandler::HandleCombatStopCommand(const char* args) { - Player *player; - - if(*args) - { - std::string playername = extractPlayerNameFromLink((char*)args); - if(playername.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - player = objmgr.GetPlayer(playername.c_str()); - - if(!player) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - } - else - { - player = getSelectedPlayer(); - - if (!player) - player = m_session->GetPlayer(); - } - - // check online security - if (HasLowerSecurity(player, 0)) + Player* target; + if(!extractPlayerTarget((char*)args,&target)) return false; - player->CombatStop(); - player->getHostilRefManager().deleteReferences(); + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + target->CombatStop(); + target->getHostilRefManager().deleteReferences(); return true; } @@ -4163,7 +3970,7 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) skillInfo->categoryId != SKILL_CATEGORY_SECONDARY ) continue; - int loc = m_session->GetSessionDbcLocale(); + int loc = GetSessionDbcLocale(); std::string name = skillInfo->name[loc]; if(Utf8FitTo(name, wnamepart)) @@ -4314,16 +4121,11 @@ bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/) return true; } -bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/) +bool ChatHandler::HandleRepairitemsCommand(const char* args) { - Player *target = getSelectedPlayer(); - - if(!target) - { - PSendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); + Player* target; + if(!extractPlayerTarget((char*)args,&target)) return false; - } // check online security if (HasLowerSecurity(target, 0)) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 2da83263e..61469006f 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -49,6 +49,7 @@ #include "BattleGroundMgr.h" #include "InstanceSaveMgr.h" #include "InstanceData.h" +#include "CreatureEventAIMgr.h" //reload commands bool ChatHandler::HandleReloadAllCommand(const char*) @@ -57,6 +58,7 @@ bool ChatHandler::HandleReloadAllCommand(const char*) HandleReloadAllAchievementCommand(""); HandleReloadAllAreaCommand(""); + HandleReloadAllEventAICommand(""); HandleReloadAllLootCommand(""); HandleReloadAllNpcCommand(""); HandleReloadAllQuestCommand(""); @@ -137,6 +139,14 @@ bool ChatHandler::HandleReloadAllScriptsCommand(const char*) return true; } +bool ChatHandler::HandleReloadAllEventAICommand(const char*) +{ + HandleReloadEventAITextsCommand("a"); + HandleReloadEventAISummonsCommand("a"); + HandleReloadEventAIScriptsCommand("a"); + return true; +} + bool ChatHandler::HandleReloadAllSpellCommand(const char*) { HandleReloadSkillDiscoveryTemplateCommand("a"); @@ -614,6 +624,31 @@ bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg) return true; } +bool ChatHandler::HandleReloadEventAITextsCommand(const char* arg) +{ + + sLog.outString( "Re-Loading Texts from `creature_ai_texts`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Texts(); + SendGlobalSysMessage("DB table `creature_ai_texts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadEventAISummonsCommand(const char* arg) +{ + sLog.outString( "Re-Loading Summons from `creature_ai_summons`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Summons(); + SendGlobalSysMessage("DB table `creature_ai_summons` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadEventAIScriptsCommand(const char* arg) +{ + sLog.outString( "Re-Loading Scripts from `creature_ai_scripts`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Scripts(); + SendGlobalSysMessage("DB table `creature_ai_scripts` reloaded."); + return true; +} + bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg) { if(sWorld.IsScriptScheduled()) @@ -1919,33 +1954,14 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) bool ChatHandler::HandleLearnAllDefaultCommand(const char* args) { - Player *player = NULL; - if (*args) - { - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - player = objmgr.GetPlayer(name.c_str()); - } - else - player = getSelectedPlayer(); - - if(!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); + Player* target; + if(!extractPlayerTarget((char*)args,&target)) return false; - } - player->learnDefaultSpells(); - player->learnQuestRewardedSpells(); + target->learnDefaultSpells(); + target->learnQuestRewardedSpells(); - PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(player).c_str()); + PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(target).c_str()); return true; } @@ -2568,7 +2584,7 @@ bool ChatHandler::HandleLookupItemCommand(const char* args) if(!pProto) continue; - int loc_idx = m_session ? m_session->GetSessionDbLocaleIndex() : objmgr.GetDBCLocaleIndex(); + int loc_idx = GetSessionDbLocaleIndex(); if ( loc_idx >= 0 ) { ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); @@ -2633,7 +2649,7 @@ bool ChatHandler::HandleLookupItemSetCommand(const char* args) ItemSetEntry const *set = sItemSetStore.LookupEntry(id); if(set) { - int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + int loc = GetSessionDbcLocale(); std::string name = set->name[loc]; if(name.empty()) continue; @@ -2643,7 +2659,7 @@ bool ChatHandler::HandleLookupItemSetCommand(const char* args) loc = 0; for(; loc < MAX_LOCALE; ++loc) { - if(m_session && loc==m_session->GetSessionDbcLocale()) + if(loc==GetSessionDbcLocale()) continue; name = set->name[loc]; @@ -2696,7 +2712,7 @@ bool ChatHandler::HandleLookupSkillCommand(const char* args) SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id); if(skillInfo) { - int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + int loc = GetSessionDbcLocale(); std::string name = skillInfo->name[loc]; if(name.empty()) continue; @@ -2706,7 +2722,7 @@ bool ChatHandler::HandleLookupSkillCommand(const char* args) loc = 0; for(; loc < MAX_LOCALE; ++loc) { - if(m_session && loc==m_session->GetSessionDbcLocale()) + if(loc==GetSessionDbcLocale()) continue; name = skillInfo->name[loc]; @@ -2774,7 +2790,7 @@ bool ChatHandler::HandleLookupSpellCommand(const char* args) SpellEntry const *spellInfo = sSpellStore.LookupEntry(id); if(spellInfo) { - int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + int loc = GetSessionDbcLocale(); std::string name = spellInfo->SpellName[loc]; if(name.empty()) continue; @@ -2784,7 +2800,7 @@ bool ChatHandler::HandleLookupSpellCommand(const char* args) loc = 0; for(; loc < MAX_LOCALE; ++loc) { - if(m_session && loc==m_session->GetSessionDbcLocale()) + if(loc==GetSessionDbcLocale()) continue; name = spellInfo->SpellName[loc]; @@ -2873,7 +2889,7 @@ bool ChatHandler::HandleLookupQuestCommand(const char* args) { Quest * qinfo = iter->second; - int loc_idx = m_session ? m_session->GetSessionDbLocaleIndex() : objmgr.GetDBCLocaleIndex(); + int loc_idx = GetSessionDbLocaleIndex(); if ( loc_idx >= 0 ) { QuestLocale const *il = objmgr.GetQuestLocale(qinfo->GetQuestId()); @@ -2973,7 +2989,7 @@ bool ChatHandler::HandleLookupCreatureCommand(const char* args) if(!cInfo) continue; - int loc_idx = m_session ? m_session->GetSessionDbLocaleIndex() : objmgr.GetDBCLocaleIndex(); + int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { CreatureLocale const *cl = objmgr.GetCreatureLocale (id); @@ -3038,7 +3054,7 @@ bool ChatHandler::HandleLookupObjectCommand(const char* args) if(!gInfo) continue; - int loc_idx = m_session ? m_session->GetSessionDbLocaleIndex() : objmgr.GetDBCLocaleIndex(); + int loc_idx = GetSessionDbLocaleIndex(); if ( loc_idx >= 0 ) { GameObjectLocale const *gl = objmgr.GetGameObjectLocale(id); @@ -3103,7 +3119,7 @@ bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) TaxiNodesEntry const *nodeEntry = sTaxiNodesStore.LookupEntry(id); if(nodeEntry) { - int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + int loc = GetSessionDbcLocale(); std::string name = nodeEntry->name[loc]; if(name.empty()) continue; @@ -3113,7 +3129,7 @@ bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) loc = 0; for(; loc < MAX_LOCALE; ++loc) { - if(m_session && loc==m_session->GetSessionDbcLocale()) + if(loc==GetSessionDbcLocale()) continue; name = nodeEntry->name[loc]; @@ -3153,41 +3169,26 @@ bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) */ bool ChatHandler::HandleGuildCreateCommand(const char* args) { - - if (!*args) + char* nameStr; + char* guildStr; + extractOptFirstArg((char*)args,&nameStr,&guildStr); + if(!guildStr) return false; - char *lname = strtok ((char*)args, " "); - char *gname = strtok (NULL, ""); - - if (!lname) + Player* target; + if(!extractPlayerTarget(nameStr,&target)) return false; - if (!gname) - { - SendSysMessage (LANG_INSERT_GUILD_NAME); - SetSentErrorMessage (true); - return false; - } + std::string guildname = guildStr; - std::string guildname = gname; - - Player* player = ObjectAccessor::Instance ().FindPlayerByName (lname); - if (!player) - { - SendSysMessage (LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage (true); - return false; - } - - if (player->GetGuildId()) + if (target->GetGuildId()) { SendSysMessage (LANG_PLAYER_IN_GUILD); return true; } Guild *guild = new Guild; - if (!guild->create (player,guildname)) + if (!guild->create (target,guildname)) { delete guild; SendSysMessage (LANG_GUILD_NOT_CREATED); @@ -3201,38 +3202,23 @@ bool ChatHandler::HandleGuildCreateCommand(const char* args) bool ChatHandler::HandleGuildInviteCommand(const char *args) { - if (!*args) + char* nameStr; + char* guildNameStr; + extractOptFirstArg((char*)args,&nameStr,&guildNameStr); + if(!guildNameStr) return false; - char* par1 = strtok ((char*)args, " "); - char* par2 = strtok (NULL, ""); - if(!par1 || !par2) + uint64 target_guid; + if(!extractPlayerTarget(nameStr,NULL,&target_guid)) return false; - std::string glName = par2; + std::string glName = guildNameStr; Guild* targetGuild = objmgr.GetGuildByName (glName); if (!targetGuild) return false; - std::string plName = extractPlayerNameFromLink(par1); - if(plName.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 plGuid = 0; - if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ())) - plGuid = targetPlayer->GetGUID (); - else - plGuid = objmgr.GetPlayerGUIDByName (plName); - - if (!plGuid) - return false; - // player's guild membership checked in AddMember before add - if (!targetGuild->AddMember (plGuid,targetGuild->GetLowestRank ())) + if (!targetGuild->AddMember (target_guid,targetGuild->GetLowestRank ())) return false; return true; @@ -3240,91 +3226,50 @@ bool ChatHandler::HandleGuildInviteCommand(const char *args) bool ChatHandler::HandleGuildUninviteCommand(const char *args) { - if (!*args) + Player* target; + uint64 target_guid; + if(!extractPlayerTarget((char*)args,&target,&target_guid)) return false; - char* par1 = strtok ((char*)args, " "); - if(!par1) - return false; - - std::string plName = extractPlayerNameFromLink(par1); - if(plName.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 plGuid = 0; - uint32 glId = 0; - if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ())) - { - plGuid = targetPlayer->GetGUID (); - glId = targetPlayer->GetGuildId (); - } - else - { - plGuid = objmgr.GetPlayerGUIDByName (plName); - glId = Player::GetGuildIdFromDB (plGuid); - } - - if (!plGuid || !glId) + uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); + if (!glId) return false; Guild* targetGuild = objmgr.GetGuildById (glId); if (!targetGuild) return false; - targetGuild->DelMember (plGuid); - + targetGuild->DelMember (target_guid); return true; } bool ChatHandler::HandleGuildRankCommand(const char *args) { - if (!*args) + char* nameStr; + char* rankStr; + extractOptFirstArg((char*)args,&nameStr,&rankStr); + if(!rankStr) return false; - char* par1 = strtok ((char*)args, " "); - char* par2 = strtok (NULL, " "); - if (!par1 || !par2) + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) return false; - std::string plName = extractPlayerNameFromLink(par1); - if(plName.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - - uint64 plGuid = 0; - uint32 glId = 0; - if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ())) - { - plGuid = targetPlayer->GetGUID (); - glId = targetPlayer->GetGuildId (); - } - else - { - plGuid = objmgr.GetPlayerGUIDByName (plName); - glId = Player::GetGuildIdFromDB (plGuid); - } - - if (!plGuid || !glId) + uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); + if (!glId) return false; Guild* targetGuild = objmgr.GetGuildById (glId); if (!targetGuild) return false; - uint32 newrank = uint32 (atoi (par2)); + uint32 newrank = uint32 (atoi (rankStr)); if (newrank > targetGuild->GetLowestRank ()) return false; - targetGuild->ChangeRank (plGuid,newrank); - + targetGuild->ChangeRank (target_guid,newrank); return true; } @@ -3510,43 +3455,20 @@ bool ChatHandler::HandleModifyArenaCommand(const char * args) bool ChatHandler::HandleReviveCommand(const char* args) { - Player* player = NULL; - uint64 player_guid = 0; - - if (*args) - { - std::string name = extractPlayerNameFromLink((char*)args); - if (name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - player = objmgr.GetPlayer(name.c_str()); - if (!player) - player_guid = objmgr.GetPlayerGUIDByName(name); - } - else - player = getSelectedPlayer(); - - if (player) - { - player->ResurrectPlayer(0.5f); - player->SpawnCorpseBones(); - player->SaveToDB(); - } - else if (player_guid) - { - // will resurrected at login without corpse - ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid); - } - else - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + if(!extractPlayerTarget((char*)args,&target,&target_guid)) return false; + + if (target) + { + target->ResurrectPlayer(0.5f); + target->SpawnCorpseBones(); + target->SaveToDB(); } + else + // will resurrected at login without corpse + ObjectAccessor::Instance().ConvertCorpseForPlayer(target_guid); return true; } @@ -3998,26 +3920,27 @@ void ChatHandler::HandleCharacterLevel(Player* player, uint64 player_guid, uint3 bool ChatHandler::HandleCharacterLevelCommand(const char* args) { - char* px = strtok((char*)args, " "); - char* py = strtok((char*)NULL, " "); + char* nameStr; + char* levelStr; + extractOptFirstArg((char*)args,&nameStr,&levelStr); + if(!levelStr) + return false; - // command format parsing - char* pname = (char*)NULL; - int32 newlevel = 0; + // exception opt second arg: .character level $name + if(isalpha(levelStr[0])) + { + nameStr = levelStr; + levelStr = NULL; // current level will used + } - if(px && py) // .character level $name #level - { - newlevel = atoi(py); - pname = px; - } - else if(px && !py) // .character level $name OR .character level #level - { - if(isalpha(px[0])) // .character level $name - pname = px; - else // .character level #level - newlevel = atoi(px); - } - // // .character level - progress reset + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + int32 oldlevel = target ? target->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,target_guid); + int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; if(newlevel < 1) return false; // invalid level @@ -4025,60 +3948,11 @@ bool ChatHandler::HandleCharacterLevelCommand(const char* args) if(newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level newlevel = STRONG_MAX_LEVEL; - // player - Player *chr = NULL; - uint64 chr_guid = 0; + HandleCharacterLevel(target,target_guid,oldlevel,newlevel); - std::string name; - - if(pname) // player by name + if(!m_session || m_session->GetPlayer() != target) // including player==NULL { - name = extractPlayerNameFromLink(pname); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - chr = objmgr.GetPlayer(name.c_str()); - if(!chr) // not in game - { - chr_guid = objmgr.GetPlayerGUIDByName(name); - if (chr_guid == 0) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - } - } - else // player by selection - { - chr = getSelectedPlayer(); - - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - name = chr->GetName(); - } - - assert(chr || chr_guid); - - int32 oldlevel = chr ? chr->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,chr_guid); - - if(!px && !py) // .character level - progress reset - newlevel = oldlevel; - - HandleCharacterLevel(chr,chr_guid,oldlevel,newlevel); - - if(m_session && m_session->GetPlayer() != chr) // including player==NULL - { - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); } @@ -4087,83 +3961,38 @@ bool ChatHandler::HandleCharacterLevelCommand(const char* args) bool ChatHandler::HandleLevelUpCommand(const char* args) { - char* px = strtok((char*)args, " "); - char* py = strtok((char*)NULL, " "); + char* nameStr; + char* levelStr; + extractOptFirstArg((char*)args,&nameStr,&levelStr); - // command format parsing - char* pname = (char*)NULL; - int addlevel = 1; - - if(px && py) // .levelup name level + // exception opt second arg: .character level $name + if(levelStr && isalpha(levelStr[0])) { - addlevel = atoi(py); - pname = px; - } - else if(px && !py) // .levelup name OR .levelup level - { - if(isalpha(px[0])) // .levelup name - pname = px; - else // .levelup level - addlevel = atoi(px); - } - // else .levelup - nothing do for preparing - - // player - Player *chr = NULL; - uint64 chr_guid = 0; - - std::string name; - - if(pname) // player by name - { - name = extractPlayerNameFromLink(pname); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - chr = objmgr.GetPlayer(name.c_str()); - if(!chr) // not in game - { - chr_guid = objmgr.GetPlayerGUIDByName(name); - if (chr_guid == 0) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - } - } - else // player by selection - { - chr = getSelectedPlayer(); - - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - name = chr->GetName(); + nameStr = levelStr; + levelStr = NULL; // current level will used } - assert(chr || chr_guid); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; - int32 oldlevel = chr ? chr->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,chr_guid); + int32 oldlevel = target ? target->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,target_guid); + int32 addlevel = levelStr ? atoi(levelStr) : 1; int32 newlevel = oldlevel + addlevel; + if(newlevel < 1) newlevel = 1; + if(newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level newlevel = STRONG_MAX_LEVEL; - HandleCharacterLevel(chr,chr_guid,oldlevel,newlevel); + HandleCharacterLevel(target,target_guid,oldlevel,newlevel); - if(m_session && m_session->GetPlayer() != chr) // including chr==NULL + if(!m_session || m_session->GetPlayer() != target) // including chr==NULL { - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); } @@ -4565,7 +4394,7 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/) { bool talent = GetTalentSpellCost(itr->second->GetId()) > 0; - char const* name = itr->second->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()]; + char const* name = itr->second->GetSpellProto()->SpellName[GetSessionDbcLocale()]; if (m_session) { @@ -4596,7 +4425,7 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/) { bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; - char const* name = (*itr)->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()]; + char const* name = (*itr)->GetSpellProto()->SpellName[GetSessionDbcLocale()]; if (m_session) { @@ -4620,76 +4449,31 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/) bool ChatHandler::HandleResetAchievementsCommand (const char * args) { - char* pName = strtok((char*)args, ""); - Player *player = NULL; - uint64 guid = 0; - if (pName) - { - std::string name = extractPlayerNameFromLink(pName); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; - guid = objmgr.GetPlayerGUIDByName(name); - player = objmgr.GetPlayer(guid); - } + if(target) + target->GetAchievementMgr().Reset(); else - { - player = getSelectedPlayer(); - if(player) - guid = player->GetGUID(); - } - - if(!player && !guid) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - return true; - } - - if(player) - player->GetAchievementMgr().Reset(); - else if(guid) - AchievementMgr::DeleteFromDB(GUID_LOPART(guid)); + AchievementMgr::DeleteFromDB(GUID_LOPART(target_guid)); return true; } bool ChatHandler::HandleResetHonorCommand (const char * args) { - char* pName = strtok((char*)args, ""); - Player *player = NULL; - if (pName) - { - std::string name = extractPlayerNameFromLink(pName); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; - uint64 guid = objmgr.GetPlayerGUIDByName(name); - player = objmgr.GetPlayer(guid); - } - else - player = getSelectedPlayer(); - - if(!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - return true; - } - - player->SetUInt32Value(PLAYER_FIELD_KILLS, 0); - player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); - player->SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, 0); - player->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - player->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); - - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); + target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, 0); + target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); return true; } @@ -4751,137 +4535,71 @@ static bool HandleResetStatsOrLevelHelper(Player* player) bool ChatHandler::HandleResetLevelCommand(const char * args) { - char* pName = strtok((char*)args, ""); - Player *player = NULL; - if (pName) - { - std::string name = extractPlayerNameFromLink(pName); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = objmgr.GetPlayerGUIDByName(name); - player = objmgr.GetPlayer(guid); - } - else - player = getSelectedPlayer(); - - if(!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); + Player* target; + if(!extractPlayerTarget((char*)args,&target)) return false; - } - if(!HandleResetStatsOrLevelHelper(player)) + if(!HandleResetStatsOrLevelHelper(target)) return false; // set starting level - uint32 start_level = player->getClass() != CLASS_DEATH_KNIGHT + uint32 start_level = target->getClass() != CLASS_DEATH_KNIGHT ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); - player->SetLevel(start_level); - player->InitRunes(); - player->InitStatsForLevel(true); - player->InitTaxiNodesForLevel(); - player->InitGlyphsForLevel(); - player->InitTalentForLevel(); - player->SetUInt32Value(PLAYER_XP,0); + target->SetLevel(start_level); + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + target->SetUInt32Value(PLAYER_XP,0); + + // reset level for pet + if(Pet* pet = target->GetPet()) + pet->SynchronizeLevelWithOwner(); - // reset level to summoned pet - Pet* pet = player->GetPet(); - if(pet && pet->getPetType()==SUMMON_PET) - { - pet->InitStatsForLevel(1); - pet->InitTalentForLevel(); - } return true; } bool ChatHandler::HandleResetStatsCommand(const char * args) { - char* pName = strtok((char*)args, ""); - Player *player = NULL; - if (pName) - { - std::string name = extractPlayerNameFromLink(pName); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = objmgr.GetPlayerGUIDByName(name); - player = objmgr.GetPlayer(guid); - } - else - player = getSelectedPlayer(); - - if(!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if(!HandleResetStatsOrLevelHelper(player)) + Player* target; + if (!extractPlayerTarget((char*)args,&target)) return false; - player->InitRunes(); - player->InitStatsForLevel(true); - player->InitTaxiNodesForLevel(); - player->InitGlyphsForLevel(); - player->InitTalentForLevel(); + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); return true; } bool ChatHandler::HandleResetSpellsCommand(const char * args) { - char* pName = strtok((char*)args, ""); - Player *player = NULL; - uint64 playerGUID = 0; - if (pName) - { - std::string name = extractPlayerNameFromLink(pName); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - player = objmgr.GetPlayer(name.c_str()); - if(!player) - playerGUID = objmgr.GetPlayerGUIDByName(name); - } - else - player = getSelectedPlayer(); - - if(!player && !playerGUID) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); + Player* target; + uint64 target_guid; + std::string target_name; + if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) return false; - } - if(player) + if(target) { - player->resetSpells(); + target->resetSpells(); - ChatHandler(player).SendSysMessage(LANG_RESET_SPELLS); - if(m_session->GetPlayer()!=player) - PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(player).c_str()); + ChatHandler(target).SendSysMessage(LANG_RESET_SPELLS); + if(!m_session || m_session->GetPlayer()!=target) + PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(target).c_str()); } else { - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_SPELLS), GUID_LOPART(playerGUID)); - PSendSysMessage(LANG_RESET_SPELLS_OFFLINE,pName); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_SPELLS), GUID_LOPART(target_guid)); + PSendSysMessage(LANG_RESET_SPELLS_OFFLINE,target_name); } return true; @@ -4889,43 +4607,30 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args) bool ChatHandler::HandleResetTalentsCommand(const char * args) { - char* pName = strtok((char*)args, ""); - Player *player = NULL; - uint64 playerGUID = 0; - if (pName) + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) { - std::string name = extractPlayerNameFromLink(pName); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } + target->resetTalents(true); - player = objmgr.GetPlayer(name.c_str()); - if(!player) - playerGUID = objmgr.GetPlayerGUIDByName(name); - } - else - player = getSelectedPlayer(); - - if(player) - { - player->resetTalents(true); - - ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS); - if(m_session->GetPlayer()!=player) - PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(player).c_str()); + ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); + if (!m_session || m_session->GetPlayer()!=target) + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(target).c_str()); return true; } - else if (playerGUID) + else if (target_guid) { - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_TALENTS), GUID_LOPART(playerGUID) ); - std::string nameLink = playerLink(pName); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_TALENTS), GUID_LOPART(target_guid) ); + std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,nameLink.c_str()); return true; } + // Try reset talenents as Hunter Pet Creature* creature = getSelectedCreature(); if (creature && creature->isPet() && ((Pet *)creature)->getPetType() == HUNTER_PET) @@ -4934,10 +4639,10 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args) Unit *owner = creature->GetOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) { - player = (Player *)owner; - ChatHandler(player).SendSysMessage(LANG_RESET_PET_TALENTS); - if(m_session->GetPlayer()!=player) - PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE,GetNameLink(player).c_str()); + Player* owner_player = (Player *)owner; + ChatHandler(owner_player).SendSysMessage(LANG_RESET_PET_TALENTS); + if(!m_session || m_session->GetPlayer()!=owner_player) + PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE,GetNameLink(owner_player).c_str()); } return true; } @@ -4961,11 +4666,15 @@ bool ChatHandler::HandleResetAllCommand(const char * args) { atLogin = AT_LOGIN_RESET_SPELLS; sWorld.SendWorldText(LANG_RESETALL_SPELLS); + if(!m_session) + SendSysMessage(LANG_RESETALL_SPELLS); } else if(casename=="talents") { atLogin = AT_LOGIN_RESET_TALENTS; sWorld.SendWorldText(LANG_RESETALL_TALENTS); + if(!m_session) + SendSysMessage(LANG_RESETALL_TALENTS); } else { @@ -5496,24 +5205,12 @@ bool ChatHandler::HandleBanInfoAccountCommand(const char* args) bool ChatHandler::HandleBanInfoCharacterCommand(const char* args) { - if (!*args) + Player* target; + uint64 target_guid; + if(!extractPlayerTarget((char*)args,&target,&target_guid)) return false; - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint32 accountid = objmgr.GetPlayerAccountIdByPlayerName(name); - if(!accountid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } + uint32 accountid = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); std::string accountname; if(!accmgr.GetName(accountid,accountname)) @@ -6588,18 +6285,12 @@ bool ChatHandler::HandleAccountSetAddonCommand(const char* args) //Send items by mail bool ChatHandler::HandleSendItemsCommand(const char* args) { - if(!*args) - return false; - // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* receiver; + uint64 receiver_guid; + std::string receiver_name; + if(!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) return false; - } char* tail1 = strtok(NULL, ""); if(!tail1) @@ -6695,14 +6386,6 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) } } - uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); - if(!receiver_guid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - // from console show not existed sender uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0; @@ -6710,8 +6393,6 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) uint32 stationery = MAIL_STATIONERY_GM; uint32 itemTextId = !text.empty() ? objmgr.CreateItemText( text ) : 0; - Player *receiver = objmgr.GetPlayer(receiver_guid); - // fill mail MailItemsInfo mi; // item list preparing @@ -6726,7 +6407,7 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_NONE); - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(receiver_name); PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; } @@ -6734,18 +6415,13 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) ///Send money by mail bool ChatHandler::HandleSendMoneyCommand(const char* args) { - if (!*args) - return false; - /// format: name "subject text" "mail text" money - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + Player* receiver; + uint64 receiver_guid; + std::string receiver_name; + if(!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) return false; - } char* tail1 = strtok(NULL, ""); if (!tail1) @@ -6792,14 +6468,6 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) std::string subject = msgSubject; std::string text = msgText; - uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); - if (!receiver_guid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - // from console show not existed sender uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0; @@ -6807,11 +6475,9 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) uint32 stationery = MAIL_STATIONERY_GM; uint32 itemTextId = !text.empty() ? objmgr.CreateItemText( text ) : 0; - Player *receiver = objmgr.GetPlayer(receiver_guid); - WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, money, 0, MAIL_CHECK_MASK_NONE); - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(receiver_name); PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; } @@ -6819,28 +6485,17 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) /// Send a message to a player in game bool ChatHandler::HandleSendMessageCommand(const char* args) { - ///- Get the command line arguments - std::string name = extractPlayerNameFromLink((char*)args); - if(name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); + ///- Find the player + Player *rPlayer; + std::string rName; + if(!extractPlayerTarget((char*)args,&rPlayer,NULL,&rName)) return false; - } char* msg_str = strtok(NULL, ""); if(!msg_str) return false; - ///- Find the player and check that he is not logging out. - Player *rPlayer = objmgr.GetPlayer(name.c_str()); - if(!rPlayer) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - + ///- Check that he is not logging out. if(rPlayer->GetSession()->isLogingOut()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -6854,7 +6509,7 @@ bool ChatHandler::HandleSendMessageCommand(const char* args) rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); //Confirmation message - std::string nameLink = playerLink(name); + std::string nameLink = playerLink(rName); PSendSysMessage(LANG_SENDMESSAGE,nameLink.c_str(),msg_str); return true; } diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 004c3a501..dceb72df9 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1227,9 +1227,13 @@ bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRan float sizefactor = GetObjectSize() + obj->GetObjectSize(); - float mindist = minRange + sizefactor; - if(distsq < mindist * mindist) - return false; + // check only for real range + if(minRange > 0.0f) + { + float mindist = minRange + sizefactor; + if(distsq < mindist * mindist) + return false; + } float maxdist = maxRange + sizefactor; return distsq < maxdist * maxdist; @@ -1243,9 +1247,13 @@ bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) float sizefactor = GetObjectSize(); - float mindist = minRange + sizefactor; - if(distsq < mindist * mindist) - return false; + // check only for real range + if(minRange > 0.0f) + { + float mindist = minRange + sizefactor; + if(distsq < mindist * mindist) + return false; + } float maxdist = maxRange + sizefactor; return distsq < maxdist * maxdist; @@ -1260,9 +1268,13 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m float sizefactor = GetObjectSize(); - float mindist = minRange + sizefactor; - if(distsq < mindist * mindist) - return false; + // check only for real range + if(minRange > 0.0f) + { + float mindist = minRange + sizefactor; + if(distsq < mindist * mindist) + return false; + } float maxdist = maxRange + sizefactor; return distsq < maxdist * maxdist; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index a7cb84961..9cf387907 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6571,11 +6571,7 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min for(MangosStringLocaleMap::iterator itr = mMangosStringLocaleMap.begin(); itr != mMangosStringLocaleMap.end();) { if (itr->first >= start_value && itr->first < end_value) - { - MangosStringLocaleMap::iterator itr2 = itr; - ++itr; - mMangosStringLocaleMap.erase(itr2); - } + mMangosStringLocaleMap.erase(itr++); else ++itr; } diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 5e15b5b15..c50d1198f 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -156,7 +156,7 @@ typedef UNORDERED_MAP ItemLocaleMap; typedef UNORDERED_MAP QuestLocaleMap; typedef UNORDERED_MAP NpcTextLocaleMap; typedef UNORDERED_MAP PageTextLocaleMap; -typedef UNORDERED_MAP MangosStringLocaleMap; +typedef UNORDERED_MAP MangosStringLocaleMap; typedef UNORDERED_MAP NpcOptionLocaleMap; typedef UNORDERED_MAP PointOfInterestLocaleMap; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 527c495a2..db2f3d574 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -340,6 +340,8 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool } } + InitLevelupSpellsForLevel(); + m_loading = false; SynchronizeLevelWithOwner(); @@ -653,6 +655,9 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { + if(itr->second.state == PETSPELL_REMOVED) + continue; + if(IsPassiveSpell(itr->first)) continue; @@ -746,6 +751,7 @@ void Pet::GivePetLevel(uint32 level) return; InitStatsForLevel(level); + InitLevelupSpellsForLevel(); InitTalentForLevel(); } @@ -847,7 +853,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel) else if (getLevel() <= cFamily->minScaleLevel) scale = cFamily->minScale; else - scale = cFamily->minScale + (getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); + scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } @@ -994,9 +1000,6 @@ bool Pet::InitStatsForLevel(uint32 petlevel) for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i])); - if(cinfo->family) - learnLevelupSpells(); - UpdateAllStats(); SetHealth(GetMaxHealth()); @@ -1118,7 +1121,7 @@ void Pet::_LoadSpells() { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt32(), fields[1].GetUInt16(), PETSPELL_UNCHANGED); + addSpell(fields[0].GetUInt32(), ActiveStates(fields[1].GetUInt16()), PETSPELL_UNCHANGED); } while( result->NextRow() ); @@ -1284,7 +1287,7 @@ void Pet::_SaveAuras() } } -bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/) +bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); if (!spellInfo) @@ -1356,26 +1359,33 @@ bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState // skip unknown ranks if(!HasSpell(rankSpellId)) continue; - removeSpell(rankSpellId); + removeSpell(rankSpellId,false); } } } - else if(uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id)) + else if(spellmgr.GetSpellRank(spell_id)!=0) { for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) { if(itr2->second.state == PETSPELL_REMOVED) continue; - if(spellmgr.GetFirstSpellInChain(itr2->first) == chainstart) + if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first) ) { - newspell.active = itr2->second.active; + // replace by new high rank + if(spellmgr.IsHighRankOfSpell(spell_id,itr2->first)) + { + newspell.active = itr2->second.active; - if(newspell.active == ACT_ENABLED) - ToggleAutocast(itr2->first, false); + if(newspell.active == ACT_ENABLED) + ToggleAutocast(itr2->first, false); - oldspell_id = itr2->first; - unlearnSpell(itr2->first); - break; + oldspell_id = itr2->first; + unlearnSpell(itr2->first,false); + break; + } + // ignore new lesser rank + else if(spellmgr.IsHighRankOfSpell(itr2->first,spell_id)) + return false; } } } @@ -1384,7 +1394,7 @@ bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState if (IsPassiveSpell(spell_id)) CastSpell(this, spell_id, true); - else if(state == PETSPELL_NEW) + else m_charmInfo->AddSpellToAB(oldspell_id, spell_id); if(newspell.active == ACT_ENABLED) @@ -1422,26 +1432,33 @@ bool Pet::learnSpell(uint32 spell_id) return true; } -void Pet::learnLevelupSpells() +void Pet::InitLevelupSpellsForLevel() { - PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); + uint32 family = GetCreatureInfo()->family; + if(!family) + return; + + PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(family); if(!levelupSpells) return; uint32 level = getLevel(); - for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + // PetLevelupSpellSet ordered by levels, process in reversed order + for(PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr) { - if(itr->first <= level) - learnSpell(itr->second); + // will called first if level down + if(itr->first > level) + unlearnSpell(itr->second,true); // will learn prev rank if any + // will called if level up else - unlearnSpell(itr->second); + learnSpell(itr->second); // will unlearn prev rank if any } } -bool Pet::unlearnSpell(uint32 spell_id) +bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev) { - if(removeSpell(spell_id)) + if(removeSpell(spell_id,learn_prev)) { if(GetOwner()->GetTypeId() == TYPEID_PLAYER) { @@ -1457,7 +1474,7 @@ bool Pet::unlearnSpell(uint32 spell_id) return false; } -bool Pet::removeSpell(uint32 spell_id) +bool Pet::removeSpell(uint32 spell_id, bool learn_prev) { PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr == m_spells.end()) @@ -1485,6 +1502,27 @@ bool Pet::removeSpell(uint32 spell_id) SetFreeTalentPoints(free_points > 0 ? free_points : 0); } + if (learn_prev) + { + if (uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id)) + { + // replace to next spell + if(!talentCost && !IsPassiveSpell(prev_id)) + m_charmInfo->AddSpellToAB(spell_id, prev_id); + + learnSpell(prev_id); + } + else + { + m_charmInfo->AddSpellToAB(spell_id, 0); + + // need update action bar for last removed rank + if (Unit* owner = GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) + ((Player*)owner)->PetSpellInitialize(); + } + } + return true; } @@ -1620,7 +1658,7 @@ bool Pet::resetTalents(bool no_cost) // unlearn if first rank is talent or learned by talent if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) { - removeSpell(itr->first); + removeSpell(itr->first,false); itr = m_spells.begin(); continue; } diff --git a/src/game/Pet.h b/src/game/Pet.h index 07e1036ce..c16a4a550 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -69,7 +69,7 @@ enum PetSpellType struct PetSpell { - uint16 active; + ActiveStates active : 16; PetSpellState state : 8; PetSpellType type : 8; @@ -196,12 +196,12 @@ class Pet : public Creature void _LoadSpells(); void _SaveSpells(); - bool addSpell(uint32 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL); + bool addSpell(uint32 spell_id,ActiveStates active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL); bool learnSpell(uint32 spell_id); void learnSpellHighRank(uint32 spellid); - void learnLevelupSpells(); - bool unlearnSpell(uint32 spell_id); - bool removeSpell(uint32 spell_id); + void InitLevelupSpellsForLevel(); + bool unlearnSpell(uint32 spell_id, bool learn_prev); + bool removeSpell(uint32 spell_id, bool learn_prev); PetSpellMap m_spells; TeachSpellMap m_teachspells; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ac64b0c85..3ce6649c2 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1421,8 +1421,8 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) *p_data << uint8(getLevel()); // player level // do not use GetMap! it will spawn a new instance since the bound instances are not loaded - uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY(),GetPositionZ()); - sLog.outDebug("Player::BuildEnumData: m:%u, x:%f, y:%f, z:%f zone:%u", GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), zoneId); + uint32 zoneId = fields[10].GetUInt32(); + sLog.outDebug("Player::BuildEnumData: map:%u, x:%f, y:%f, z:%f zone:%u", GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), zoneId); *p_data << uint32(zoneId); *p_data << uint32(GetMapId()); @@ -1431,7 +1431,7 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) *p_data << GetPositionZ(); // guild id - *p_data << (result ? fields[13].GetUInt32() : 0); + *p_data << uint32(fields[14].GetUInt32()); uint32 char_flags = 0; if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) @@ -1444,7 +1444,7 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) char_flags |= CHARACTER_FLAG_RENAME; if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED)) { - if(!fields[14].GetCppString().empty()) + if(!fields[15].GetCppString().empty()) char_flags |= CHARACTER_FLAG_DECLINED; } else @@ -1464,12 +1464,12 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) // show pet at selection character in character list only for non-ghost character if (result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT)) { - uint32 entry = fields[10].GetUInt32(); + uint32 entry = fields[11].GetUInt32(); CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); if(cInfo) { - petDisplayId = fields[11].GetUInt32(); - petLevel = fields[12].GetUInt32(); + petDisplayId = fields[12].GetUInt32(); + petLevel = fields[13].GetUInt32(); petFamily = cInfo->family; } } @@ -2070,11 +2070,17 @@ void Player::SetGameMaster(bool on) setFaction(35); SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); + if (Pet* pet = GetPet()) + { + pet->setFaction(35); + pet->getHostilRefManager().setOnlineOfflineState(false); + } + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); ResetContestedPvP(); getHostilRefManager().setOnlineOfflineState(false); - CombatStop(); + CombatStopWithPets(); SetPhaseMask(PHASEMASK_ANYWHERE,false); // see and visible in all phases } @@ -2088,6 +2094,12 @@ void Player::SetGameMaster(bool on) setFactionForRace(getRace()); RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); + if (Pet* pet = GetPet()) + { + pet->setFaction(getFaction()); + pet->getHostilRefManager().setOnlineOfflineState(true); + } + // restore FFA PvP Server state if(sWorld.IsFFAPvPRealm()) SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); @@ -11583,6 +11595,14 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot, bool apply, bool sLog.outDebug("Adding %u to stat nb %u",enchant_amount,enchant_spell_id); switch (enchant_spell_id) { + case ITEM_MOD_MANA: + sLog.outDebug("+ %u MANA",enchant_amount); + HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); + break; + case ITEM_MOD_HEALTH: + sLog.outDebug("+ %u HEALTH",enchant_amount); + HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); + break; case ITEM_MOD_AGILITY: sLog.outDebug("+ %u AGILITY",enchant_amount); HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); @@ -13632,20 +13652,23 @@ void Player::SendQuestUpdateAddCreatureOrGo( Quest const* pQuest, uint64 guid, u bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) { bool delete_result = true; - if(!result) + if (!result) { - // 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; + // 0 1 2 3 4 5 6 7 8 9 10 + result = CharacterDatabase.PQuery("SELECT guid, data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login, zone FROM characters WHERE guid = '%u'",guid); + if (!result) + return false; } - else delete_result = false; + else + delete_result = false; Field *fields = result->Fetch(); - if(!LoadValues( fields[1].GetString())) + if (!LoadValues( fields[1].GetString())) { sLog.outError("Player #%d have broken data in `data` field. Can't be loaded for character list.",GUID_LOPART(guid)); - if(delete_result) delete result; + if (delete_result) + delete result; return false; } @@ -13668,12 +13691,13 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) _LoadBoundInstances();*/ - if (delete_result) delete result; + if (delete_result) + delete result; for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i) m_items[i] = NULL; - if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) + if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) m_deathState = DEAD; return true; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 6703ebe6d..47695b530 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2417,18 +2417,19 @@ void Spell::cast(bool skipCheck) ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id); } + FillTargetMap(); + + if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in FillTargetMap + { + SetExecutedCurrently(false); + return; + } + // CAST SPELL SendSpellCooldown(); TakePower(); TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot - FillTargetMap(); - - if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap - { - SetExecutedCurrently(false); - return; - } SendCastResult(castResult); SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()... diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 679c1923b..34d0bd167 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1081,6 +1081,7 @@ void Aura::_RemoveAura() m_target->ModifyAuraState(AURA_STATE_ENRAGE, false); uint32 removeState = 0; + uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags; switch(m_spellProto->SpellFamilyName) { case SPELLFAMILY_PALADIN: @@ -1095,7 +1096,10 @@ void Aura::_RemoveAura() if(m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions) else if(m_spellProto->SpellFamilyFlags & 0x50) + { + removeFamilyFlag = 0x50; removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state + } break; case SPELLFAMILY_WARRIOR: if(m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) @@ -1119,7 +1123,7 @@ void Aura::_RemoveAura() { SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto(); if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName && - auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags ) + auraSpellInfo->SpellFamilyFlags & removeFamilyFlag) { found = true; break; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2e7623f3a..1b4a5d07c 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3262,6 +3262,7 @@ void Spell::EffectSummon(uint32 i) spawnCreature->AIM_Initialize(); spawnCreature->InitPetCreateSpells(); + spawnCreature->InitLevelupSpellsForLevel(); spawnCreature->SetHealth(spawnCreature->GetMaxHealth()); spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA)); @@ -4174,6 +4175,7 @@ void Spell::EffectSummonPet(uint32 i) NewSummon->InitStatsForLevel(petlevel); NewSummon->InitPetCreateSpells(); + NewSummon->InitLevelupSpellsForLevel(); NewSummon->InitTalentForLevel(); if(NewSummon->getPetType()==SUMMON_PET) @@ -5971,6 +5973,7 @@ void Spell::EffectSummonCritter(uint32 i) critter->AIM_Initialize(); critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter... + //critter->InitLevelupSpellsForLevel(); // none? critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag); // some mini-pets have quests diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 687786800..b2ba8a4b5 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -5949,7 +5949,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu default: return false; } - CastSpell(this, spell, true, castItem, triggeredByAura); + CastSpell(target, spell, true, castItem, triggeredByAura); if ((*itr)->DropAuraCharge()) RemoveAurasDueToSpell((*itr)->GetId()); return true; @@ -10403,20 +10403,30 @@ void CharmInfo::InitCharmCreateSpells() bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate) { + // new spell already listed for example in case prepered switch to lesser rank in Pet::removeSpell + for(uint8 i = 0; i < 10; ++i) + if (PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) + if (newid && PetActionBar[i].SpellOrAction == newid) + return true; + + // old spell can be leasted for example in case learn high rank for(uint8 i = 0; i < 10; ++i) { - if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) && PetActionBar[i].SpellOrAction == oldid) + if (PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) { - PetActionBar[i].SpellOrAction = newid; - if(!oldid) + if (PetActionBar[i].SpellOrAction == oldid) { - if(newstate == ACT_DECIDE) - PetActionBar[i].Type = ACT_DISABLED; - else - PetActionBar[i].Type = newstate; - } + PetActionBar[i].SpellOrAction = newid; + if (!oldid) + { + if (newstate == ACT_DECIDE) + PetActionBar[i].Type = ACT_DISABLED; + else + PetActionBar[i].Type = newstate; + } - return true; + return true; + } } } return false; @@ -11406,6 +11416,7 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) // this enables pet details window (Shift+P) pet->AIM_Initialize(); pet->InitPetCreateSpells(); + pet->InitLevelupSpellsForLevel(); pet->InitTalentForLevel(); pet->SetHealth(pet->GetMaxHealth()); diff --git a/src/game/World.cpp b/src/game/World.cpp index 5548c3551..324cc3671 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -2454,31 +2454,6 @@ void World::KickAllLess(AccountTypes sec) itr->second->KickPlayer(); } -/// Kick (and save) the designated player -bool World::KickPlayer(const std::string& playerName) -{ - SessionMap::const_iterator itr; - - // session not removed at kick and will removed in next update tick - for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - { - if(!itr->second) - continue; - Player *player = itr->second->GetPlayer(); - if(!player) - continue; - if( player->IsInWorld() ) - { - if (playerName == player->GetName()) - { - itr->second->KickPlayer(); - return true; - } - } - } - return false; -} - /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author) { diff --git a/src/game/World.h b/src/game/World.h index 0fd19e9b8..048973a01 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -406,7 +406,7 @@ class World /// Get the current Message of the Day const char* GetMotd() const { return m_motd.c_str(); } - uint32 GetDefaultDbcLocale() const { return m_defaultDbcLocale; } + LocaleConstant GetDefaultDbcLocale() const { return m_defaultDbcLocale; } /// Get the path where data (dbc, maps) are stored on disk std::string GetDataPath() const { return m_dataPath; } @@ -472,7 +472,6 @@ class World bool IsPvPRealm() { return (getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP); } bool IsFFAPvPRealm() { return getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; } - bool KickPlayer(const std::string& playerName); void KickAll(); void KickAllLess(AccountTypes sec); BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); diff --git a/src/shared/Util.h b/src/shared/Util.h index 8fa4faacf..121bbc292 100644 --- a/src/shared/Util.h +++ b/src/shared/Util.h @@ -90,7 +90,7 @@ inline void ApplyModFloatVar(float& var, float val, bool apply) inline void ApplyPercentModFloatVar(float& var, float val, bool apply) { - if (!apply && val == -100.0f) + if (val == -100.0f) // prevent set var to zero val = -99.99f; var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 13bd699da..0f17c3c58 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 "7835" + #define REVISION_NR "7856" #endif // __REVISION_NR_H__