mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-20 17:27:36 +01:00
Scripts/Commands: Add .go boss, and do a usability pass over .go instance to match it.
This commit is contained in:
30
sql/updates/world/3.3.5/2019_08_06_05_world.sql
Normal file
30
sql/updates/world/3.3.5/2019_08_06_05_world.sql
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
--
|
||||||
|
DELETE FROM `trinity_string` WHERE `entry` BETWEEN 1205 AND 1211;
|
||||||
|
INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES
|
||||||
|
(1205, 'No bosses were found matching your input.'),
|
||||||
|
(1206, 'Multiple bosses match your input - please be more specific:'),
|
||||||
|
(1207, '|- #%05u \'%s\' (%s)'),
|
||||||
|
(1208, 'Multiple spawn points exist for boss \'%s\' (creature #%05u) - go to one using .go creature:'),
|
||||||
|
(1209, '|- %06u (map #%03u \'%s\' at %s)'),
|
||||||
|
(1210, 'Failed to teleport you to spawn point %u for boss \'%s\' (creature #%05u) - are you missing an attunement for map \'%s\'?'),
|
||||||
|
(1211, 'Teleported you to spawn point for boss \'%s\' (creature #%05u, spawnid %u)');
|
||||||
|
|
||||||
|
DELETE FROM `trinity_string` WHERE `entry` BETWEEN 1189 AND 1198;
|
||||||
|
INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES
|
||||||
|
(1189, 'No instances were found matching your input.'),
|
||||||
|
(1190, 'Multiple instances match your input - please be more specific:'),
|
||||||
|
(1191,'|- \'%s\' (map #%03u, %s)'),
|
||||||
|
-- 1192 is newly unused
|
||||||
|
(1193,'Could not find entrance portal for map \'%s\' (map #%03u)'),
|
||||||
|
(1194,'Could not find exit portal for map \'%s\' (map #%03u)'),
|
||||||
|
(1195,'Teleported you to the entrance of \'%s\' (map #%03u)'),
|
||||||
|
(1196,'Teleported you to the start of \'%s\' (map #%03u)'),
|
||||||
|
(1197,'Failed to teleport you to the entrance of \'%s\' (map #%03u) - are you missing an attunement for map \'%s\' (#%03u)?'),
|
||||||
|
(1198,'Failed to teleport you to the start of \'%s\' (map #%03u) - are you missing an attunement for the instance?');
|
||||||
|
|
||||||
|
DELETE FROM `command` WHERE `name` IN ('go boss','go instance');
|
||||||
|
INSERT INTO `command` (`name`,`permission`,`help`) VALUES
|
||||||
|
('go instance', 377, 'Syntax: .go instance <part(s) of name>
|
||||||
|
Teleport yourself to the instance whose name and/or script name best matches the specified search string(s).'),
|
||||||
|
('go boss', 377, 'Syntax: .go boss <part(s) of name>
|
||||||
|
Teleport yourself to the dungeon boss whose name and/or script name best matches the specified search string(s).');
|
||||||
@@ -915,7 +915,7 @@ enum TrinityStrings
|
|||||||
LANG_COMMAND_NO_INSTANCES_MATCH = 1189,
|
LANG_COMMAND_NO_INSTANCES_MATCH = 1189,
|
||||||
LANG_COMMAND_MULTIPLE_INSTANCES_MATCH = 1190,
|
LANG_COMMAND_MULTIPLE_INSTANCES_MATCH = 1190,
|
||||||
LANG_COMMAND_MULTIPLE_INSTANCES_ENTRY = 1191,
|
LANG_COMMAND_MULTIPLE_INSTANCES_ENTRY = 1191,
|
||||||
LANG_COMMAND_MAP_NOT_INSTANCE = 1192,
|
// 1192 unused
|
||||||
LANG_COMMAND_INSTANCE_NO_ENTRANCE = 1193,
|
LANG_COMMAND_INSTANCE_NO_ENTRANCE = 1193,
|
||||||
LANG_COMMAND_INSTANCE_NO_EXIT = 1194,
|
LANG_COMMAND_INSTANCE_NO_EXIT = 1194,
|
||||||
LANG_COMMAND_WENT_TO_INSTANCE_GATE = 1195,
|
LANG_COMMAND_WENT_TO_INSTANCE_GATE = 1195,
|
||||||
@@ -931,7 +931,15 @@ enum TrinityStrings
|
|||||||
LANG_DEBUG_AREATRIGGER_OFF = 1203,
|
LANG_DEBUG_AREATRIGGER_OFF = 1203,
|
||||||
LANG_DEBUG_AREATRIGGER_REACHED = 1204,
|
LANG_DEBUG_AREATRIGGER_REACHED = 1204,
|
||||||
|
|
||||||
// 1205-1998 - free
|
LANG_COMMAND_NO_BOSSES_MATCH = 1205,
|
||||||
|
LANG_COMMAND_MULTIPLE_BOSSES_MATCH = 1206,
|
||||||
|
LANG_COMMAND_MULTIPLE_BOSSES_ENTRY = 1207,
|
||||||
|
LANG_COMMAND_BOSS_MULTIPLE_SPAWNS = 1208,
|
||||||
|
LANG_COMMAND_BOSS_MULTIPLE_SPAWN_ETY = 1209,
|
||||||
|
LANG_COMMAND_GO_BOSS_FAILED = 1210,
|
||||||
|
LANG_COMMAND_WENT_TO_BOSS = 1211,
|
||||||
|
|
||||||
|
// 1212-1998 - free
|
||||||
LANG_DO_NOT_USE_6X_DEBUG_AREATRIGGER_LEFT = 1999,
|
LANG_DO_NOT_USE_6X_DEBUG_AREATRIGGER_LEFT = 1999,
|
||||||
// Ticket Strings 2000-2030
|
// Ticket Strings 2000-2030
|
||||||
LANG_COMMAND_TICKETNEW = 2000,
|
LANG_COMMAND_TICKETNEW = 2000,
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ public:
|
|||||||
{ "xyz", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoXYZCommand, "" },
|
{ "xyz", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoXYZCommand, "" },
|
||||||
{ "ticket", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoTicketCommand, "" },
|
{ "ticket", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoTicketCommand, "" },
|
||||||
{ "offset", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoOffsetCommand, "" },
|
{ "offset", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoOffsetCommand, "" },
|
||||||
{ "instance", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoInstanceCommand, "" }
|
{ "instance", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoInstanceCommand, "" },
|
||||||
|
{ "boss", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoBossCommand, "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<ChatCommand> commandTable =
|
static std::vector<ChatCommand> commandTable =
|
||||||
@@ -389,19 +390,22 @@ public:
|
|||||||
|
|
||||||
static bool HandleGoInstanceCommand(ChatHandler* handler, std::vector<std::string> const& labels)
|
static bool HandleGoInstanceCommand(ChatHandler* handler, std::vector<std::string> const& labels)
|
||||||
{
|
{
|
||||||
uint32 mapid = 0;
|
if (labels.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
std::multimap<uint32, std::pair<uint16, std::string>> matches;
|
// #matched labels -> (mapid, scriptname)
|
||||||
|
std::multimap<uint32, std::tuple<uint16, char const*, char const*>> matches;
|
||||||
for (auto const& pair : sObjectMgr->GetInstanceTemplates())
|
for (auto const& pair : sObjectMgr->GetInstanceTemplates())
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
std::string const& scriptName = sObjectMgr->GetScriptName(pair.second.ScriptId);
|
std::string const& scriptName = sObjectMgr->GetScriptName(pair.second.ScriptId);
|
||||||
|
char const* mapName = ASSERT_NOTNULL(sMapStore.LookupEntry(pair.first))->name[handler->GetSessionDbcLocale()];
|
||||||
for (auto const& label : labels)
|
for (auto const& label : labels)
|
||||||
if (StringContainsStringI(scriptName, label))
|
if (StringContainsStringI(scriptName, label))
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
matches.emplace(count, decltype(matches)::mapped_type({ pair.first, scriptName }));
|
matches.emplace(count, decltype(matches)::mapped_type({ pair.first, mapName, scriptName.c_str() }));
|
||||||
}
|
}
|
||||||
if (matches.empty())
|
if (matches.empty())
|
||||||
{
|
{
|
||||||
@@ -409,30 +413,23 @@ public:
|
|||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto it = matches.rbegin();
|
|
||||||
uint32 maxCount = it->first;
|
auto it = matches.crbegin(), end = matches.crend();
|
||||||
mapid = it->second.first;
|
uint32 const maxCount = it->first;
|
||||||
if (++it != matches.rend() && it->first == maxCount)
|
if ((++it) != end && it->first == maxCount)
|
||||||
{
|
{
|
||||||
handler->SendSysMessage(LANG_COMMAND_MULTIPLE_INSTANCES_MATCH);
|
handler->SendSysMessage(LANG_COMMAND_MULTIPLE_INSTANCES_MATCH);
|
||||||
--it;
|
--it;
|
||||||
do
|
do
|
||||||
handler->PSendSysMessage(LANG_COMMAND_MULTIPLE_INSTANCES_ENTRY, it->second.first, it->second.second);
|
handler->PSendSysMessage(LANG_COMMAND_MULTIPLE_INSTANCES_ENTRY, std::get<1>(it->second), std::get<0>(it->second), std::get<2>(it->second));
|
||||||
while (++it != matches.rend() && it->first == maxCount);
|
while (((++it) != end) && (it->first == maxCount));
|
||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(mapid);
|
it = matches.crbegin();
|
||||||
|
uint32 const mapId = std::get<0>(it->second);
|
||||||
InstanceTemplate const* temp = sObjectMgr->GetInstanceTemplate(mapid);
|
char const* const mapName = std::get<1>(it->second);
|
||||||
if (!temp)
|
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_COMMAND_MAP_NOT_INSTANCE, mapid);
|
|
||||||
handler->SetSentErrorMessage(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::string const& scriptname = sObjectMgr->GetScriptName(temp->ScriptId);
|
|
||||||
|
|
||||||
Player* player = handler->GetSession()->GetPlayer();
|
Player* player = handler->GetSession()->GetPlayer();
|
||||||
if (player->IsInFlight())
|
if (player->IsInFlight())
|
||||||
@@ -441,36 +438,142 @@ public:
|
|||||||
player->SaveRecallPosition();
|
player->SaveRecallPosition();
|
||||||
|
|
||||||
// try going to entrance
|
// try going to entrance
|
||||||
if (AreaTrigger const* exit = sObjectMgr->GetGoBackTrigger(mapid))
|
if (AreaTrigger const* exit = sObjectMgr->GetGoBackTrigger(mapId))
|
||||||
{
|
{
|
||||||
if (player->TeleportTo(exit->target_mapId, exit->target_X, exit->target_Y, exit->target_Z, exit->target_Orientation + M_PI))
|
if (player->TeleportTo(exit->target_mapId, exit->target_X, exit->target_Y, exit->target_Z, exit->target_Orientation + M_PI))
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage(LANG_COMMAND_WENT_TO_INSTANCE_GATE, mapid, scriptname);
|
handler->PSendSysMessage(LANG_COMMAND_WENT_TO_INSTANCE_GATE, mapName, mapId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
handler->PSendSysMessage(LANG_COMMAND_GO_INSTANCE_GATE_FAILED, mapid, scriptname, exit->target_mapId);
|
{
|
||||||
|
uint32 const parentMapId = exit->target_mapId;
|
||||||
|
char const* const parentMapName = ASSERT_NOTNULL(sMapStore.LookupEntry(parentMapId))->name[handler->GetSessionDbcLocale()];
|
||||||
|
handler->PSendSysMessage(LANG_COMMAND_GO_INSTANCE_GATE_FAILED, mapName, mapId, parentMapName, parentMapId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
handler->PSendSysMessage(LANG_COMMAND_INSTANCE_NO_EXIT, mapid, scriptname);
|
handler->PSendSysMessage(LANG_COMMAND_INSTANCE_NO_EXIT, mapName, mapId);
|
||||||
|
|
||||||
// try going to start
|
// try going to start
|
||||||
if (AreaTrigger const* entrance = sObjectMgr->GetMapEntranceTrigger(mapid))
|
if (AreaTrigger const* entrance = sObjectMgr->GetMapEntranceTrigger(mapId))
|
||||||
{
|
{
|
||||||
if (player->TeleportTo(entrance->target_mapId, entrance->target_X, entrance->target_Y, entrance->target_Z, entrance->target_Orientation))
|
if (player->TeleportTo(entrance->target_mapId, entrance->target_X, entrance->target_Y, entrance->target_Z, entrance->target_Orientation))
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage(LANG_COMMAND_WENT_TO_INSTANCE_START, mapid, scriptname);
|
handler->PSendSysMessage(LANG_COMMAND_WENT_TO_INSTANCE_START, mapName, mapId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
handler->PSendSysMessage(LANG_COMMAND_GO_INSTANCE_START_FAILED, mapid, scriptname);
|
handler->PSendSysMessage(LANG_COMMAND_GO_INSTANCE_START_FAILED, mapName, mapId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
handler->PSendSysMessage(LANG_COMMAND_INSTANCE_NO_ENTRANCE, mapid, scriptname);
|
handler->PSendSysMessage(LANG_COMMAND_INSTANCE_NO_ENTRANCE, mapName, mapId);
|
||||||
|
|
||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool HandleGoBossCommand(ChatHandler* handler, std::vector<std::string> const& needles)
|
||||||
|
{
|
||||||
|
if (needles.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::multimap<uint32, CreatureTemplate const*> matches;
|
||||||
|
std::unordered_map<uint32, std::vector<CreatureData const*>> spawnLookup;
|
||||||
|
|
||||||
|
// find all boss flagged mobs that match our needles
|
||||||
|
for (auto const& pair : sObjectMgr->GetCreatureTemplates())
|
||||||
|
{
|
||||||
|
CreatureTemplate const& data = pair.second;
|
||||||
|
if (!(data.flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32 count = 0;
|
||||||
|
std::string const& scriptName = sObjectMgr->GetScriptName(data.ScriptID);
|
||||||
|
for (auto const& label : needles)
|
||||||
|
if (StringContainsStringI(scriptName, label) || StringContainsStringI(data.Name, label))
|
||||||
|
++count;
|
||||||
|
|
||||||
|
if (count)
|
||||||
|
{
|
||||||
|
matches.emplace(count, &data);
|
||||||
|
(void)spawnLookup[data.Entry]; // inserts default-constructed vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matches.empty())
|
||||||
|
{
|
||||||
|
// find the spawn points of any matches
|
||||||
|
for (auto const& pair : sObjectMgr->GetAllCreatureData())
|
||||||
|
{
|
||||||
|
CreatureData const& data = pair.second;
|
||||||
|
auto it = spawnLookup.find(data.id);
|
||||||
|
if (it != spawnLookup.end())
|
||||||
|
it->second.push_back(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove any matches without spawns
|
||||||
|
Trinity::Containers::EraseIf(matches, [&spawnLookup](decltype(matches)::value_type const& pair) { return spawnLookup[pair.second->Entry].empty(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we even have any matches left
|
||||||
|
if (matches.empty())
|
||||||
|
{
|
||||||
|
handler->SendSysMessage(LANG_COMMAND_NO_BOSSES_MATCH);
|
||||||
|
handler->SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if we have multiple equal matches left
|
||||||
|
auto it = matches.crbegin(), end = matches.crend();
|
||||||
|
uint32 const maxCount = it->first;
|
||||||
|
if ((++it) != end && it->first == maxCount)
|
||||||
|
{
|
||||||
|
handler->SendSysMessage(LANG_COMMAND_MULTIPLE_BOSSES_MATCH);
|
||||||
|
--it;
|
||||||
|
do
|
||||||
|
handler->PSendSysMessage(LANG_COMMAND_MULTIPLE_BOSSES_ENTRY, it->second->Entry, it->second->Name.c_str(), sObjectMgr->GetScriptName(it->second->ScriptID).c_str());
|
||||||
|
while (((++it) != end) && (it->first == maxCount));
|
||||||
|
handler->SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureTemplate const* const boss = matches.crbegin()->second;
|
||||||
|
std::vector<CreatureData const*> const& spawns = spawnLookup[boss->Entry];
|
||||||
|
ASSERT(!spawns.empty());
|
||||||
|
|
||||||
|
if (spawns.size() > 1)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage(LANG_COMMAND_BOSS_MULTIPLE_SPAWNS, boss->Name.c_str(), boss->Entry);
|
||||||
|
for (CreatureData const* spawn : spawns)
|
||||||
|
{
|
||||||
|
uint32 const mapId = spawn->spawnPoint.GetMapId();
|
||||||
|
MapEntry const* const map = ASSERT_NOTNULL(sMapStore.LookupEntry(mapId));
|
||||||
|
handler->PSendSysMessage(LANG_COMMAND_BOSS_MULTIPLE_SPAWN_ETY, spawn->spawnId, mapId, map->name[handler->GetSessionDbcLocale()], spawn->spawnPoint.GetPosition().ToString().c_str());
|
||||||
|
}
|
||||||
|
handler->SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player* player = handler->GetSession()->GetPlayer();
|
||||||
|
if (player->IsInFlight())
|
||||||
|
player->FinishTaxiFlight();
|
||||||
|
else
|
||||||
|
player->SaveRecallPosition();
|
||||||
|
|
||||||
|
CreatureData const* const spawn = spawns.front();
|
||||||
|
uint32 const mapId = spawn->spawnPoint.GetMapId();
|
||||||
|
if (!player->TeleportTo(spawn->spawnPoint))
|
||||||
|
{
|
||||||
|
char const* const mapName = ASSERT_NOTNULL(sMapStore.LookupEntry(mapId))->name[handler->GetSessionDbcLocale()];
|
||||||
|
handler->PSendSysMessage(LANG_COMMAND_GO_BOSS_FAILED, spawn->spawnId, boss->Name.c_str(), boss->Entry, mapName);
|
||||||
|
handler->SetSentErrorMessage(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->PSendSysMessage(LANG_COMMAND_WENT_TO_BOSS, boss->Name.c_str(), boss->Entry, spawn->spawnId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_go_commandscript()
|
void AddSC_go_commandscript()
|
||||||
|
|||||||
Reference in New Issue
Block a user