feat(Core/Command): Deserter Command send feedback (#11958)
* feat(Core/Command): Deserter feedback Part 1 * docs(Core/Command): Deserter RemoveAll Documentation * feat(Core/Command): Deserter feedback Part 2 * fix(Core/Command): Deserter remove all count * feat(Core/Commands): Deserter merge optimizations
This commit is contained in:
@@ -88,9 +88,11 @@ public:
|
|||||||
*
|
*
|
||||||
* Example Usage:
|
* Example Usage:
|
||||||
* @code
|
* @code
|
||||||
* .deserter instance add 1h30m
|
* .deserter instance add 1h30m (using player target or self)
|
||||||
* -or-
|
* -or-
|
||||||
* .deserter bg add 1h30m
|
* .deserter bg add 1h30m (using player target or self)
|
||||||
|
* -or-
|
||||||
|
* .deserter bg add Tester 1h30m (using player of name 'Tester')
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
static bool HandleDeserterAdd(ChatHandler* handler, Optional<std::string> playerName, Optional<std::string> time, bool isInstance)
|
static bool HandleDeserterAdd(ChatHandler* handler, Optional<std::string> playerName, Optional<std::string> time, bool isInstance)
|
||||||
@@ -156,16 +158,18 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 deserterSpell = isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER;
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
Aura* aura = target->GetAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
Aura* aura = target->GetAura(deserterSpell);
|
||||||
if (aura && aura->GetDuration() >= duration * IN_MILLISECONDS)
|
if (aura && aura->GetDuration() >= duration * IN_MILLISECONDS)
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage("Player %s already has a longer %s Deserter active.", handler->playerLink(*playerName), isInstance ? "Instance" : "Battleground");
|
handler->PSendSysMessage("Player %s already has a longer %s Deserter active.", handler->playerLink(*playerName), isInstance ? "Instance" : "Battleground");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
aura = target->AddAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER, target);
|
aura = target->AddAura(deserterSpell, target);
|
||||||
if (!aura)
|
if (!aura)
|
||||||
{
|
{
|
||||||
handler->SendSysMessage(LANG_BAD_VALUE);
|
handler->SendSysMessage(LANG_BAD_VALUE);
|
||||||
@@ -173,44 +177,45 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aura->SetDuration(duration * IN_MILLISECONDS);
|
aura->SetDuration(duration * IN_MILLISECONDS);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
int32 remainTime = 0;
|
|
||||||
if (QueryResult result = CharacterDatabase.Query("SELECT remainTime FROM character_aura WHERE guid = {} AND spell = {}", guid.GetCounter(), isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER))
|
|
||||||
{
|
{
|
||||||
Field* fields = result->Fetch();
|
int32 remainTime = 0;
|
||||||
remainTime = fields[0].Get<int32>();
|
if (QueryResult result = CharacterDatabase.Query("SELECT remainTime FROM character_aura WHERE guid = {} AND spell = {}", guid.GetCounter(), deserterSpell))
|
||||||
|
|
||||||
if (remainTime < 0 || remainTime >= duration * IN_MILLISECONDS)
|
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage("Player %s already has a longer %s Deserter active.", handler->playerLink(*playerName), isInstance ? "Instance" : "Battleground");
|
Field* fields = result->Fetch();
|
||||||
return true;
|
remainTime = fields[0].Get<int32>();
|
||||||
|
|
||||||
|
if (remainTime < 0 || remainTime >= duration * IN_MILLISECONDS)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Player %s already has a longer %s Deserter active.", handler->playerLink(*playerName), isInstance ? "Instance" : "Battleground");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
CharacterDatabase.Query("DELETE FROM character_aura WHERE guid = {} AND spell = {}", guid.GetCounter(), deserterSpell);
|
||||||
}
|
}
|
||||||
CharacterDatabase.Query("DELETE FROM character_aura WHERE guid = {} AND spell = {}", guid.GetCounter(), isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
|
||||||
|
uint8 index = 0;
|
||||||
|
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA);
|
||||||
|
stmt->SetData(index++, guid.GetCounter());
|
||||||
|
stmt->SetData(index++, guid.GetCounter());
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, deserterSpell);
|
||||||
|
stmt->SetData(index++, 1);
|
||||||
|
stmt->SetData(index++, 1);
|
||||||
|
stmt->SetData(index++, 1);
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, 0);
|
||||||
|
stmt->SetData(index++, isInstance ? 1800000 : 900000);
|
||||||
|
stmt->SetData(index++, duration * IN_MILLISECONDS);
|
||||||
|
stmt->SetData(index, 0);
|
||||||
|
CharacterDatabase.Execute(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 index = 0;
|
handler->PSendSysMessage("%s of %s Deserter has been added to player %s.", secsToTimeString(duration), isInstance ? "Instance" : "Battleground", handler->playerLink(*playerName));
|
||||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA);
|
|
||||||
stmt->SetData(index++, guid.GetCounter());
|
|
||||||
stmt->SetData(index++, guid.GetCounter());
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
|
||||||
stmt->SetData(index++, 1);
|
|
||||||
stmt->SetData(index++, 1);
|
|
||||||
stmt->SetData(index++, 1);
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, 0);
|
|
||||||
stmt->SetData(index++, isInstance ? 1800000 : 900000);
|
|
||||||
stmt->SetData(index++, duration * 1000);
|
|
||||||
stmt->SetData(index, 0);
|
|
||||||
CharacterDatabase.Execute(stmt);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +226,7 @@ public:
|
|||||||
* selected player.
|
* selected player.
|
||||||
*
|
*
|
||||||
* @param handler The ChatHandler, passed by the system.
|
* @param handler The ChatHandler, passed by the system.
|
||||||
|
* @param player The target player, either by name, the target or self
|
||||||
* @param isInstance provided by the relaying functions, so we don't have
|
* @param isInstance provided by the relaying functions, so we don't have
|
||||||
* to write that much code :)
|
* to write that much code :)
|
||||||
*
|
*
|
||||||
@@ -228,9 +234,11 @@ public:
|
|||||||
*
|
*
|
||||||
* Example Usage:
|
* Example Usage:
|
||||||
* @code
|
* @code
|
||||||
* .deserter instance remove
|
* .deserter instance remove (using player target or self)
|
||||||
* -or-
|
* -or-
|
||||||
* .deserter bg remove
|
* .deserter bg remove (using player target or self)
|
||||||
|
* -or-
|
||||||
|
* .deserter bg remove Tester (using player of name 'Tester')
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
static bool HandleDeserterRemove(ChatHandler* handler, Optional<PlayerIdentifier> player, bool isInstance)
|
static bool HandleDeserterRemove(ChatHandler* handler, Optional<PlayerIdentifier> player, bool isInstance)
|
||||||
@@ -248,21 +256,75 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Player* target = player->GetConnectedPlayer();
|
Player* target = player->GetConnectedPlayer();
|
||||||
|
uint32 deserterSpell = isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER;
|
||||||
|
int32 duration = 0;
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
target->RemoveAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
if (Aura* aura = target->GetAura(deserterSpell))
|
||||||
|
{
|
||||||
|
duration = aura->GetDuration();
|
||||||
|
target->RemoveAura(deserterSpell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (QueryResult result = CharacterDatabase.Query("SELECT remainTime FROM character_aura WHERE guid = {} AND spell = {}", player->GetGUID().GetCounter(), deserterSpell))
|
||||||
|
{
|
||||||
|
Field* fields = result->Fetch();
|
||||||
|
duration = fields[0].Get<int32>();
|
||||||
|
CharacterDatabase.Execute("DELETE FROM character_aura WHERE guid = {} AND spell = {}", player->GetGUID().GetCounter(), deserterSpell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration == 0)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Player %s does not have %s Deserter.", handler->playerLink(player->GetName()), isInstance ? "Instance" : "Battleground");
|
||||||
|
handler->SetSentErrorMessage(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterDatabase.Query("DELETE FROM character_aura WHERE guid = {} AND spell = {}", player->GetGUID().GetCounter(), isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
if (duration < 0)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Permanent %s Deserter has been removed from player %s (GUID %u).", isInstance ? "Instance" : "Battleground", handler->playerLink(player->GetName()), player->GetGUID().GetCounter());
|
||||||
|
handler->SetSentErrorMessage(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->PSendSysMessage("%s of %s Deserter has been removed from player %s (GUID %u).", secsToTimeString(duration / IN_MILLISECONDS), isInstance ? "Instance" : "Battleground", handler->playerLink(player->GetName()), player->GetGUID().GetCounter());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes the Deserter Debuff from all players
|
||||||
|
*
|
||||||
|
* This function removes a Deserter Debuff of the given type (Instance or BG) from
|
||||||
|
* all players, online or offline.
|
||||||
|
*
|
||||||
|
* @param handler The ChatHandler, passed by the system.
|
||||||
|
* @param isInstance provided by the relaying functions, so we don't have
|
||||||
|
* to write that much code :)
|
||||||
|
* @param maxTime Optional: The maximum remaining time of the Debuff on players to be removed.
|
||||||
|
* Any Player with a Deserter Debuff of this time or less will get their Debuff removed. Use -1 for any.
|
||||||
|
* Default: 15m for BG, 30m for Instance.
|
||||||
|
*
|
||||||
|
* @return true if everything was correct, false if an error occured.
|
||||||
|
*
|
||||||
|
* Example Usage:
|
||||||
|
* @code
|
||||||
|
* .deserter bg remove all
|
||||||
|
* -or-
|
||||||
|
* .deserter bg remove all 30m
|
||||||
|
* -or-
|
||||||
|
* .deserter bg remove all -1
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
static bool HandleDeserterRemoveAll(ChatHandler* handler, bool isInstance, Optional<std::string> maxTime)
|
static bool HandleDeserterRemoveAll(ChatHandler* handler, bool isInstance, Optional<std::string> maxTime)
|
||||||
{
|
{
|
||||||
|
uint32 deserterSpell = isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER;
|
||||||
int32 remainTime = isInstance ? 1800 : 900;
|
int32 remainTime = isInstance ? 1800 : 900;
|
||||||
|
uint64 deserterCount = 0;
|
||||||
|
bool countOnline = true;
|
||||||
|
|
||||||
if (maxTime)
|
if (maxTime)
|
||||||
{
|
{
|
||||||
@@ -273,6 +335,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optimization. Do not execute any further functions or Queries if remainTime is 0.
|
||||||
if (remainTime == 0)
|
if (remainTime == 0)
|
||||||
{
|
{
|
||||||
handler->SendSysMessage(LANG_BAD_VALUE);
|
handler->SendSysMessage(LANG_BAD_VALUE);
|
||||||
@@ -280,13 +343,33 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remainTime < 0)
|
QueryResult result;
|
||||||
|
if (remainTime > 0)
|
||||||
{
|
{
|
||||||
CharacterDatabase.Execute("DELETE FROM character_aura WHERE spell = {}", isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
result = CharacterDatabase.Query("SELECT COUNT(guid) FROM character_aura WHERE spell = {} AND remainTime <= {}", deserterSpell, remainTime * IN_MILLISECONDS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CharacterDatabase.Execute("DELETE FROM character_aura WHERE spell = {} AND remainTime <= {}", isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER, remainTime * IN_MILLISECONDS);
|
result = CharacterDatabase.Query("SELECT COUNT(guid) FROM character_aura WHERE spell = {}", deserterSpell);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
deserterCount = (*result)[0].Get<uint64>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization. Only execute these if there even is a result.
|
||||||
|
if (deserterCount > 0)
|
||||||
|
{
|
||||||
|
countOnline = false;
|
||||||
|
if (remainTime > 0)
|
||||||
|
{
|
||||||
|
CharacterDatabase.Execute("DELETE FROM character_aura WHERE spell = {} AND remainTime <= {}", deserterSpell, remainTime * IN_MILLISECONDS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CharacterDatabase.Execute("DELETE FROM character_aura WHERE spell = {}", deserterSpell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_lock<std::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
|
std::shared_lock<std::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
|
||||||
@@ -294,14 +377,28 @@ public:
|
|||||||
for (HashMapHolder<Player>::MapType::const_iterator itr = onlinePlayerList.begin(); itr != onlinePlayerList.end(); ++itr)
|
for (HashMapHolder<Player>::MapType::const_iterator itr = onlinePlayerList.begin(); itr != onlinePlayerList.end(); ++itr)
|
||||||
{
|
{
|
||||||
Player* player = itr->second;
|
Player* player = itr->second;
|
||||||
Aura* aura = player->GetAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
Aura* aura = player->GetAura(deserterSpell);
|
||||||
if (aura && (remainTime < 0 || aura->GetDuration() <= remainTime * IN_MILLISECONDS))
|
if (aura && (remainTime < 0 || aura->GetDuration() <= remainTime * IN_MILLISECONDS))
|
||||||
{
|
{
|
||||||
player->RemoveAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
if (countOnline)
|
||||||
|
deserterCount++;
|
||||||
|
player->RemoveAura(deserterSpell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->PSendSysMessage("%s Deserter has been removed from all players", isInstance ? "Instance" : "Battleground");
|
std::string remainTimeStr = secsToTimeString(remainTime);
|
||||||
|
if (remainTime < 0)
|
||||||
|
{
|
||||||
|
remainTimeStr = "infinity";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deserterCount == 0)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("No player on this realm has %s Deserter with a duration of %s or less.", isInstance ? "Instance" : "Battleground", remainTimeStr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->PSendSysMessage("%s Deserter has been removed from %u player(s) with a duration of %s or less.", isInstance ? "Instance" : "Battleground", deserterCount, remainTimeStr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user