[Commands] Consolidate #set-like commands into a singular #set command (#3486)

* First push

* Final push.

* Consolidate zone commands in to one.

* Update command.cpp

* Remove debug messages.

* Test

* Add support for sub command status levels.

* Update command.cpp

* Update client.cpp

* Update database_update_manifest.cpp

* Update version.h

* Update item.cpp

* Update version.h

* Update database_update_manifest.cpp

* Fix command arguments.

* Help message.

* Update command.cpp

* Do DB injection/deletion

* Indent

* Update server_locked.cpp

* Update set.cpp

* Lock aliases

* Update command_subsettings_repository.h

* Update set.cpp

* Fix

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
Alex King
2023-07-15 01:37:51 -04:00
committed by GitHub
parent e55f9b9d27
commit f25e37d0c5
136 changed files with 3582 additions and 3280 deletions
+69
View File
@@ -0,0 +1,69 @@
#include "../../client.h"
#include "../../groups.h"
#include "../../raids.h"
#include "../../raids.h"
void SetAAEXP(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set aa_exp [aa|group|raid] [Amount]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const std::string& aa_type = Strings::ToLower(sep->arg[2]);
const uint32 aa_experience = Strings::ToUnsignedInt(sep->arg[3]);
std::string group_raid_string;
const bool is_aa = Strings::EqualFold(aa_type, "aa");
const bool is_group = Strings::EqualFold(aa_type, "group");
const bool is_raid = Strings::EqualFold(aa_type, "raid");
if (
!is_aa &&
!is_group &&
!is_raid
) {
c->Message(Chat::White, "Usage: #set aa_exp [aa|group|raid] [Amount]");
return;
}
if (is_aa) {
t->SetEXP(
t->GetEXP(),
aa_experience,
false
);
} else if (is_group) {
group_raid_string = "Group ";
t->SetLeadershipEXP(
aa_experience,
t->GetRaidEXP()
);
} else if (is_raid) {
group_raid_string = "Raid ";
t->SetLeadershipEXP(
t->GetGroupEXP(),
aa_experience
);
}
c->Message(
Chat::White,
fmt::format(
"{} now {} {} {}AA Experience.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
Strings::Commify(aa_experience),
group_raid_string
).c_str()
);
}
+66
View File
@@ -0,0 +1,66 @@
#include "../../client.h"
#include "../../groups.h"
#include "../../raids.h"
#include "../../raids.h"
void SetAAPoints(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set aa_points [aa|group|raid] [Amount]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const std::string& aa_type = Strings::ToLower(sep->arg[2]);
const uint32 aa_points = Strings::ToUnsignedInt(sep->arg[3]);
std::string group_raid_string;
const bool is_aa = Strings::EqualFold(aa_type, "aa");
const bool is_group = Strings::EqualFold(aa_type, "group");
const bool is_raid = Strings::EqualFold(aa_type, "raid");
if (
!is_aa &&
!is_group &&
!is_raid
) {
c->Message(Chat::White, "Usage: #set aa_points [aa|group|raid] [Amount]");
return;
}
if (is_aa) {
t->GetPP().aapoints = aa_points;
t->GetPP().expAA = 0;
t->SendAlternateAdvancementStats();
} else if (is_group || is_raid) {
if (is_group) {
group_raid_string = "Group ";
t->GetPP().group_leadership_points = aa_points;
t->GetPP().group_leadership_exp = 0;
} else if (is_raid) {
group_raid_string = "Raid ";
t->GetPP().raid_leadership_points = aa_points;
t->GetPP().raid_leadership_exp = 0;
}
t->SendLeadershipEXPUpdate();
}
c->Message(
Chat::White,
fmt::format(
"{} now {} {} {}AA Point{}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
Strings::Commify(aa_points),
group_raid_string,
aa_points != 1 ? "s" : ""
).c_str()
);
}
+66
View File
@@ -0,0 +1,66 @@
#include "../../client.h"
#include "../../../common/data_verification.h"
void SetAdventurePoints(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set adventure_points [Theme] [Points]");
c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNThemes::Unused) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {}",
e.first,
e.second
).c_str()
);
}
}
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint32 theme_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint32 points = Strings::ToUnsignedInt(sep->arg[3]);
if (!EQ::ValueWithin(theme_id, LDoNThemes::GUK, LDoNThemes::TAK)) {
c->Message(Chat::White, "Valid themes are as follows:");
for (const auto& e : EQ::constants::GetLDoNThemeMap()) {
if (e.first != LDoNThemes::Unused) {
c->Message(
Chat::White,
fmt::format(
"Theme {} | {}",
e.first,
e.second
).c_str()
);
}
}
return;
}
c->Message(
Chat::White,
fmt::format(
"Set {} Points to {} for {}.",
EQ::constants::GetLDoNThemeName(theme_id),
Strings::Commify(points),
c->GetTargetDescription(t)
).c_str()
);
t->SetLDoNPoints(theme_id, points);
}
@@ -0,0 +1,43 @@
#include "../../client.h"
void SetAlternateCurrency(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set alternate_currency [Currency ID] [Amount]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint32 currency_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint32 currency_item_id = zone->GetCurrencyItemID(currency_id);
const uint32 currency_amount = Strings::ToUnsignedInt(sep->arg[3]);
if (!currency_item_id) {
c->Message(
Chat::White,
fmt::format(
"Currency ID {} could not be found.",
currency_id
).c_str()
);
return;
}
t->SetAlternateCurrencyValue(currency_id, currency_amount);
c->Message(
Chat::White,
fmt::format(
"{} now {} {} {}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
Strings::Commify(currency_amount),
database.CreateItemLink(currency_item_id)
).c_str()
);
}
+63
View File
@@ -0,0 +1,63 @@
#include "../../client.h"
void SetAnimation(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set animation [Animation ID]");
for (const auto& a : EQ::constants::GetSpawnAnimationMap()) {
c->Message(
Chat::White,
fmt::format(
"Animation {} | {}",
a.first,
a.second
).c_str()
);
}
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
const auto animation_id = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[2]));
if (
!EQ::ValueWithin(
animation_id,
static_cast<uint8>(eaStanding),
static_cast<uint8>(eaLooting)
)
) {
c->Message(Chat::White, "Usage: #set animation [Animation ID]");
for (const auto& a : EQ::constants::GetSpawnAnimationMap()) {
c->Message(
Chat::White,
fmt::format(
"Animation {} | {}",
a.first,
a.second
).c_str()
);
}
return;
}
t->SetAppearance(static_cast<EmuAppearance>(animation_id), false);
c->Message(
Chat::White,
fmt::format(
"Set animation to {} ({}) for {}.",
EQ::constants::GetSpawnAnimationName(animation_id),
animation_id,
c->GetTargetDescription(t)
).c_str()
);
}
+105
View File
@@ -0,0 +1,105 @@
#include "../../client.h"
#include "../../../common/repositories/character_data_repository.h"
void SetAnon(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set anon [Anonymous Flag]");
c->Message(Chat::White, "Usage: #set anon [Character ID] [Anonymous Flag]");
c->Message(Chat::White, "Note: 0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying");
return;
}
if (arguments == 2) {
const uint8 anon_flag = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[2]));
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) {
t = c->GetTarget()->CastToClient();
}
std::string anon_setting;
if (anon_flag == Anonymity::NotAnonymous) {
anon_setting = "no longer Anonymous or Roleplaying";
} else if (anon_flag == Anonymity::Anonymous) {
anon_setting = "now Anonymous";
} else if (anon_flag == Anonymity::Roleplaying) {
anon_setting = "now Roleplaying";
} else {
c->Message(Chat::White, "Usage: #set anon [Anonymous Flag]");
c->Message(Chat::White, "Usage: #set anon [Character ID] [Anonymous Flag]");
c->Message(Chat::White, "Note: 0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying");
return;
}
c->SetAnon(anon_flag);
c->Message(
Chat::White,
fmt::format(
"{} {} {}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "are" : "is",
anon_setting
).c_str()
);
} else if (arguments == 3) {
const int character_id = Strings::ToInt(sep->arg[2]);
const uint8 anon_flag = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[3]));
auto e = CharacterDataRepository::FindOne(content_db, character_id);
if (!e.id) {
c->Message(
Chat::White,
fmt::format(
"Character ID {} does not exist or is invalid.",
character_id
).c_str()
);
return;
}
e.anon = anon_flag;
auto updated = CharacterDataRepository::UpdateOne(content_db, e);
if (!updated) {
c->Message(
Chat::White,
fmt::format(
"Failed to change Anonymous Flag for {} ({}).",
e.name,
character_id
).c_str()
);
return;
}
std::string anon_setting;
if (anon_flag == Anonymity::NotAnonymous) {
anon_setting = "no longer Anonymous or Roleplaying";
} else if (anon_flag == Anonymity::Anonymous) {
anon_setting = "now Anonymous";
} else if (anon_flag == Anonymity::Roleplaying) {
anon_setting = "now Roleplaying";
} else {
c->Message(Chat::White, "Usage: #set anon [Anonymous Flag]");
c->Message(Chat::White, "Usage: #set anon [Character ID] [Anonymous Flag]");
c->Message(Chat::White, "Note: 0 = Not Anonymous, 1 = Anonymous, 2 = Roleplaying");
return;
}
c->Message(
Chat::White,
fmt::format(
"{} ({}) is {}.",
e.name,
character_id,
anon_setting
).c_str()
);
}
}
+45
View File
@@ -0,0 +1,45 @@
#include "../../client.h"
void SetBindPoint(Client *c, const Seperator *sep)
{
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool bind_allowed = (
!zone->GetInstanceID() ||
(
zone->GetInstanceID() &&
zone->IsInstancePersistent()
)
);
if (!bind_allowed) {
c->Message(Chat::White, "You cannot bind here.");
return;
}
t->SetBindPoint();
c->Message(
Chat::White,
fmt::format(
"Set Bind Point for {} | Zone: {}",
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
zone->GetZoneDescription()
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Set Bind Point for {} | XYZH: {:.2f}, {:.2f}, {:.2f}, {:.2f}",
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
t->GetX(),
t->GetY(),
t->GetZ(),
t->GetHeading()
).c_str()
);
}
+28
View File
@@ -0,0 +1,28 @@
#include "../../client.h"
#include "../../worldserver.h"
#include "../../../common/repositories/account_repository.h"
extern WorldServer worldserver;
void SetChecksum(Client *c, const Seperator *sep)
{
auto account = AccountRepository::FindOne(database, c->AccountID());
if (!account.id) {
c->Message(Chat::White, "Your account was not found!");
return;
}
database.SetVariable("crc_eqgame", account.crc_eqgame);
database.SetVariable("crc_skillcaps", account.crc_skillcaps);
database.SetVariable("crc_basedata", account.crc_basedata);
c->Message(Chat::White, "Attempting to reload Rules globally.");
auto pack = new ServerPacket(ServerOP_ReloadRules, 0);
worldserver.SendPacket(pack);
safe_delete(pack);
c->Message(Chat::White, "Attempting to reload Variables globally.");
pack = new ServerPacket(ServerOP_ReloadVariables, 0);
worldserver.SendPacket(pack);
safe_delete(pack);
}
+40
View File
@@ -0,0 +1,40 @@
#include "../../client.h"
void SetClassPermanent(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set class_permanent [Class ID]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint32 class_id = Strings::ToUnsignedInt(sep->arg[2]);
LogInfo("Class changed by {} for {} to {} ({}).",
c->GetCleanName(),
c->GetTargetDescription(t),
GetClassIDName(class_id),
class_id
);
t->SetBaseClass(class_id);
t->Save();
t->Kick("Class was changed.");
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"Class changed for {} to {} ({}).",
c->GetTargetDescription(t),
GetClassIDName(class_id),
class_id
).c_str()
);
}
}
+48
View File
@@ -0,0 +1,48 @@
#include "../../client.h"
void SetCrystals(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #setcrystals [ebon|radiant] [Amount]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const std::string& crystal_type = Strings::ToLower(sep->arg[2]);
const uint32 crystal_amount = Strings::ToUnsignedInt(sep->arg[3]);
const bool is_ebon = Strings::EqualFold(crystal_type, "ebon");
const bool is_radiant = Strings::EqualFold(crystal_type, "radiant");
if (!is_ebon && !is_radiant) {
c->Message(Chat::White, "Usage: #setcrystals [ebon|radiant] [Amount]");
return;
}
const uint32 crystal_item_id = (
is_ebon ?
RuleI(Zone, EbonCrystalItemID) :
RuleI(Zone, RadiantCrystalItemID)
);
if (is_radiant) {
t->SetRadiantCrystals(crystal_amount);
} else {
t->SetEbonCrystals(crystal_amount);
}
c->Message(
Chat::White,
fmt::format(
"{} now {} {} {}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
Strings::Commify(crystal_amount),
database.CreateItemLink(crystal_item_id)
).c_str()
);
}
+46
View File
@@ -0,0 +1,46 @@
#include "../../client.h"
void SetDate(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (
arguments < 2 ||
!sep->IsNumber(2) ||
!sep->IsNumber(3) ||
!sep->IsNumber(4)
) {
c->Message(Chat::White, "Usage: #date [Year] [Month] [Day] [Hour] [Minute]");
c->Message(Chat::White, "Hour and Minute are optional");
return;
}
TimeOfDay_Struct eq_time;
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time);
const uint16 year = Strings::ToUnsignedInt(sep->arg[2]);
const uint8 month = Strings::ToUnsignedInt(sep->arg[3]);
const uint8 day = Strings::ToUnsignedInt(sep->arg[4]);
const uint8 hour = !sep->IsNumber(5) ? eq_time.hour : Strings::ToUnsignedInt(sep->arg[5]) + 1;
const uint8 minute = !sep->IsNumber(6) ? eq_time.minute : Strings::ToUnsignedInt(sep->arg[6]);
c->Message(
Chat::White,
fmt::format("Setting world time to {}/{}/{} {}.",
year,
month,
day,
Strings::ZoneTime(hour, minute)
).c_str()
);
zone->SetDate(year, month, day, hour, minute);
LogInfo(
"{} :: Setting world time to {}/{}/{} {}.",
c->GetCleanName(),
year,
month,
day,
Strings::ZoneTime(hour, minute)
);
}
+40
View File
@@ -0,0 +1,40 @@
#include "../../client.h"
void SetEndurance(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set endurance [Endurance]");
return;
}
int endurance = Strings::ToInt(sep->arg[2]);
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
if (t->IsClient()) {
if (endurance >= t->CastToClient()->GetMaxEndurance()) {
endurance = t->CastToClient()->GetMaxEndurance();
}
t->CastToClient()->SetEndurance(endurance);
} else {
if (endurance >= t->GetMaxEndurance()) {
endurance = t->GetMaxEndurance();
}
t->SetEndurance(endurance);
}
c->Message(
Chat::White,
fmt::format(
"Set {} to {} Endurance.",
c->GetTargetDescription(t),
Strings::Commify(endurance)
).c_str()
);
}
+29
View File
@@ -0,0 +1,29 @@
#include "../../client.h"
void SetEnduranceFull(Client *c, const Seperator *sep)
{
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
int endurance;
if (t->IsClient()) {
endurance = t->CastToClient()->GetMaxEndurance();
t->CastToClient()->SetEndurance(endurance);
} else {
endurance = t->GetMaxEndurance();
t->SetEndurance(endurance);
}
c->Message(
Chat::White,
fmt::format(
"Set {} to full Endurance ({}).",
c->GetTargetDescription(t),
Strings::Commify(endurance)
).c_str()
);
}
+49
View File
@@ -0,0 +1,49 @@
#include "../../client.h"
void SetEXP(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set exp [aa|exp] [Amount]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const std::string& type = Strings::ToLower(sep->arg[2]);
const bool is_aa = Strings::EqualFold(type, "aa");
const bool is_exp = Strings::EqualFold(type, "exp");
if (!is_aa && !is_exp) {
c->Message(Chat::White, "Usage: #set exp [aa|exp] [Amount]");
return;
}
const uint32 amount = Strings::ToUnsignedInt(sep->arg[3]);
if (is_aa) {
t->SetEXP(
t->GetEXP(),
amount
);
} else if (is_exp) {
t->SetEXP(
amount,
t->GetAAXP()
);
}
c->Message(
Chat::White,
fmt::format(
"{} now {} {} {}experience.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
Strings::Commify(amount),
is_aa ? "AA " : ""
).c_str()
);
}
+69
View File
@@ -0,0 +1,69 @@
#include "../../client.h"
#include "../../../common/data_verification.h"
void SetFlymode(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set flymode [Flymode ID]");
for (const auto& e : EQ::constants::GetFlyModeMap()) {
c->Message(
Chat::White,
fmt::format(
"Flymode {} | {}",
e.first,
e.second
).c_str()
);
}
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
const int8 flymode_id = Strings::ToInt(sep->arg[2]);
if (
!EQ::ValueWithin(
flymode_id,
EQ::constants::GravityBehavior::Ground,
EQ::constants::GravityBehavior::LevitateWhileRunning
)
) {
c->Message(Chat::White, "Usage: #set flymode [Flymode ID]");
for (const auto& e : EQ::constants::GetFlyModeMap()) {
c->Message(
Chat::White,
fmt::format(
"Flymode {} | {}",
e.first,
e.second
).c_str()
);
}
return;
}
t->SetFlyMode(static_cast<GravityBehavior>(flymode_id));
t->SendAppearancePacket(AT_Levitate, flymode_id);
const uint32 account = c->AccountID();
database.SetGMFlymode(account, flymode_id);
c->Message(
Chat::White,
fmt::format(
"Fly Mode for {} is now {} ({}).",
c->GetTargetDescription(t),
EQ::constants::GetFlyModeName(flymode_id),
flymode_id
).c_str()
);
}
+34
View File
@@ -0,0 +1,34 @@
#include "../../client.h"
void SetFrozen(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set frozen [on|off]");
return;
}
if (!c->GetTarget()) {
c->Message(Chat::White, "You must have a target to use this command.");
return;
}
const bool is_frozen = Strings::ToBool(sep->arg[2]);
auto t = c->GetTarget();
if (c == t) {
c->Message(Chat::White, "You cannot use this command on yourself.");
return;
}
t->SendAppearancePacket(AT_Anim, is_frozen ? ANIM_FREEZE : ANIM_STAND);
c->Message(
Chat::White,
fmt::format(
"You have {}frozen {}.",
!is_frozen ? "un" : "",
c->GetTargetDescription(t)
).c_str()
);
}
+38
View File
@@ -0,0 +1,38 @@
#include "../../client.h"
void SetGender(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set gender [Gender ID]");
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
return;
}
Mob *t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
const uint8 gender_id = Strings::ToUnsignedInt(sep->arg[2]);
if (!EQ::ValueWithin(gender_id, MALE, NEUTER)) {
c->Message(Chat::White, "Usage: #set gender [Gender ID]");
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
return;
}
t->SendIllusionPacket(
t->GetRace(),
gender_id
);
c->Message(
Chat::White,
fmt::format(
"Gender changed for {} to {} ({}).",
c->GetTargetDescription(t),
GetGenderName(gender_id),
gender_id
).c_str()
);
}
+44
View File
@@ -0,0 +1,44 @@
#include "../../client.h"
void SetGenderPermanent(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set gender_permanent [Gender ID]");
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint8 gender_id = Strings::ToInt(sep->arg[2]);
if (!EQ::ValueWithin(gender_id, MALE, NEUTER)) {
c->Message(Chat::White, "Usage: #set gender_permanent [Gender ID]");
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
return;
}
LogInfo("Gender changed by {} for {} to {} ({})",
c->GetCleanName(),
c->GetTargetDescription(t),
GetGenderName(gender_id),
gender_id
);
t->SetBaseGender(gender_id);
t->Save();
t->SendIllusionPacket(t->GetRace(), gender_id);
c->Message(
Chat::White,
fmt::format(
"Gender changed for {} to {} ({}).",
c->GetTargetDescription(t),
GetGenderName(gender_id),
gender_id
).c_str()
);
}
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
void SetGM(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set gm [on|off]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool gm_flag = Strings::ToBool(sep->arg[2]);
t->SetGM(gm_flag);
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"{} is {} flagged as a GM.",
c->GetTargetDescription(t),
gm_flag ? "now" : "no longer"
).c_str()
);
}
}
+39
View File
@@ -0,0 +1,39 @@
#include "../../client.h"
void SetGMSpeed(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set gmspeed [on|off]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool gm_speed = Strings::ToBool(sep->arg[2]);
database.SetGMSpeed(
t->AccountID(),
gm_speed ? 1 : 0
);
c->Message(
Chat::White,
fmt::format(
"Turning GM Speed {} for {}.",
gm_speed ? "on" : "off",
c->GetTargetDescription(t)
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Note: {} must zone for it to take effect.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou)
).c_str()
);
}
+97
View File
@@ -0,0 +1,97 @@
#include "../../client.h"
#include "../../worldserver.h"
extern WorldServer worldserver;
void SetGMStatus(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
c->Message(
Chat::White,
fmt::format(
"Status level has been refreshed for {}.",
c->GetTargetDescription(t)
).c_str()
);
if (t != c) {
t->Message(
Chat::White,
fmt::format(
"Your status level has been refreshed by {}.",
c->GetCleanName()
).c_str()
);
}
t->UpdateAdmin();
return;
}
if (
!sep->IsNumber(2) ||
!strlen(sep->arg[3])
) {
c->Message(Chat::White, "Usage: #set gm_status [Status] [Account Name]");
return;
}
const int gm_status = Strings::ToInt(sep->arg[2]);
if (!EQ::ValueWithin(gm_status, -2, UINT8_MAX)) {
c->Message(Chat::White, "The lowest a status level can go is -2 and the highest a status level can go is 255.");
return;
}
const std::string& account_name = sep->argplus[3];
if (gm_status > c->Admin()) {
c->Message(
Chat::White,
fmt::format(
"You cannot set someone's status level to {} because your status level is only {}.",
gm_status,
c->Admin()
).c_str()
);
} else if (!database.SetAccountStatus(account_name, gm_status)) {
c->Message(
Chat::White,
fmt::format(
"Failed to set status level to {} for account {}.",
gm_status,
account_name
).c_str()
);
} else {
c->Message(
Chat::White,
fmt::format(
"Set GM status to {} on account {}.",
gm_status,
account_name
).c_str()
);
std::string user;
std::string loginserver;
ParseAccountString(account_name, user, loginserver);
const uint32 account_id = database.GetAccountIDByName(account_name, loginserver);
ServerPacket pack(ServerOP_FlagUpdate, sizeof(ServerFlagUpdate_Struct));
auto s = (ServerFlagUpdate_Struct *) pack.pBuffer;
s->account_id = account_id;
s->admin = gm_status;
worldserver.SendPacket(&pack);
}
}
+42
View File
@@ -0,0 +1,42 @@
#include "../../client.h"
#include "../../../common/repositories/account_repository.h"
void SetGodMode(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set god_mode [on|off]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool god_mode = Strings::ToBool(sep->arg[2]);
const uint32 account_id = c->AccountID();
auto a = AccountRepository::FindOne(database, c->AccountID());
if (a.id) {
a.flymode = god_mode ? 1 : 0;
a.gmspeed = god_mode ? 1 : 0;
a.invulnerable = god_mode ? 1 : 0;
a.hideme = god_mode ? 1 : 0;
}
c->SetInvul(god_mode);
c->SendAppearancePacket(AT_Levitate, god_mode);
c->SetHideMe(god_mode);
c->Message(
Chat::White,
fmt::format(
"Turning God Mode {} for {}, zone for GM Speed to take effect.",
god_mode ? "on" : "off",
c->GetTargetDescription(t)
).c_str()
);
AccountRepository::UpdateOne(database, a);
}
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
void SetHaste(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set haste [Percentage] - Set GM Bonus Haste (100 is 100% more Attack Speed)");
return;
}
auto t = c;
if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const int extra_haste = Strings::ToInt(sep->arg[2]);
t->SetExtraHaste(extra_haste);
t->CalcBonuses();
t->SetAttackTimer();
c->Message(
Chat::White,
fmt::format(
"GM Haste Bonus set to {}%% for {}.",
Strings::Commify(extra_haste),
c->GetTargetDescription(t)
).c_str()
);
}
+44
View File
@@ -0,0 +1,44 @@
#include "../../client.h"
void SetHeroModel(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set hero_model [Hero Model]");
c->Message(Chat::White, "Usage: #set hero_model [Hero Model] [Slot]");
c->Message(
Chat::White,
fmt::format(
"Example: {}",
Saylink::Silent("#heromodel 63")
).c_str()
);
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
uint32 hero_forge_model = Strings::ToUnsignedInt(sep->arg[2]);
if (arguments > 2) {
const uint8 slot = Strings::ToUnsignedInt(sep->arg[3]);
c->GetTarget()->SendTextureWC(slot, 0, hero_forge_model, 0, 0, 0);
} else {
if (!hero_forge_model) {
c->Message(Chat::White, "Hero's Forge Model must be greater than 0.");
return;
}
// Conversion to simplify the command arguments
// Hero's Forge model is actually model * 1000 + texture * 100 + wearslot
// Hero's Forge Model slot 7 is actually for Robes, but it still needs to use wearslot 1 in the packet
hero_forge_model *= 100;
for (uint8 slot = 0; slot < 7; slot++) {
c->GetTarget()->SendTextureWC(slot, 0, (hero_forge_model + slot), 0, 0, 0);
}
}
}
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
void SetHideMe(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set hide_me [on|off]");
return;
}
auto t = c;
if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool is_hidden = Strings::ToBool(sep->arg[2]);
t->SetHideMe(is_hidden);
c->Message(
Chat::White,
fmt::format(
"{} {} now {}visible to players below a status level of {}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "are" : "is",
is_hidden ? "in" : "",
t->Admin()
).c_str()
);
}
+33
View File
@@ -0,0 +1,33 @@
#include "../../client.h"
void SetHP(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set hp [Amount]");
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
int64 health = Strings::ToBigInt(sep->arg[2]);
if (health >= t->GetMaxHP()) {
health = t->GetMaxHP();
}
t->SetHP(health);
t->SendHPUpdate();
c->Message(
Chat::White,
fmt::format(
"Set {} to {} Health.",
c->GetTargetDescription(t),
Strings::Commify(health)
).c_str()
);
}
+20
View File
@@ -0,0 +1,20 @@
#include "../../client.h"
void SetHPFull(Client *c, const Seperator *sep)
{
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
t->Heal();
c->Message(
Chat::White,
fmt::format(
"Set {} to full Health ({}).",
c->GetTargetDescription(t),
Strings::Commify(t->GetMaxHP())
).c_str()
);
}
+32
View File
@@ -0,0 +1,32 @@
#include "../../client.h"
void SetInvulnerable(Client *c, const Seperator *sep) {
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set invulnerable [on|off]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool invulnerable = Strings::ToBool(sep->arg[2]);
t->SetInvul(invulnerable);
const uint32 account_id = t->AccountID();
database.SetGMInvul(account_id, invulnerable);
c->Message(
Chat::White,
fmt::format(
"{} {} now {}vulnerable.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "are" : "is",
invulnerable ? "in" : ""
).c_str()
);
}
+54
View File
@@ -0,0 +1,54 @@
#include "../../client.h"
#include "../../../common/languages.h"
#include "../../../common/data_verification.h"
void SetLanguage(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set language [Language ID] [Language Value]");
c->Message(Chat::White, "Language ID = 0 to 27");
c->Message(Chat::White, "Language Value = 0 to 100");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const int language_id = Strings::ToInt(sep->arg[2]);
const int language_value = Strings::ToInt(sep->arg[3]);
if (
!EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN) ||
!EQ::ValueWithin(language_value, 0, MAX_LANGUAGE_SKILL)
) {
c->Message(Chat::White, "Usage: #set language [Language ID] [Language Value]");
c->Message(Chat::White, "Language ID = 0 to 27");
c->Message(Chat::White, "Language Value = 0 to 100");
return;
}
LogInfo(
"Set language request from [{}], Target: [{}] Language ID: [{}] Language Value: [{}]",
c->GetCleanName(),
c->GetTargetDescription(t),
language_id,
language_value
);
t->SetLanguageSkill(language_id, language_value);
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"Set {} ({}) to {} for {}.",
EQ::constants::GetLanguageName(language_id),
language_id,
language_value,
c->GetTargetDescription(t)
).c_str()
);
}
}
+46
View File
@@ -0,0 +1,46 @@
#include "../../client.h"
void SetLastName(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set lastname [Last Name]");
c->Message(Chat::White, "Note: Use \"-1\" to remove last name.");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
LogInfo("#lastname request from [{}] for [{}]", c->GetCleanName(), t->GetCleanName());
const bool is_remove = Strings::EqualFold(sep->argplus[2], "-1");
const std::string& last_name = !is_remove ? sep->argplus[2] : "";
if (last_name.size() > 64) {
c->Message(Chat::White, "Last name must be 64 characters or less.");
return;
}
t->ChangeLastName(last_name);
c->Message(
Chat::White,
fmt::format(
"Last name has been {}{} for {}{}",
is_remove ? "removed" : "changed",
!is_remove ? " and saved" : "",
c->GetTargetDescription(t),
(
is_remove ?
"." :
fmt::format(
" to '{}'.",
last_name
)
)
).c_str()
);
}
+34
View File
@@ -0,0 +1,34 @@
#include "../../bot.h"
#include "../../client.h"
void SetLevel(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set level [Level]");
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
const uint8 max_level = RuleI(Character, MaxLevel);
const uint8 level = Strings::ToUnsignedInt(sep->arg[2]);
if (c != t && c->Admin() < RuleI(GM, MinStatusToLevelTarget)) {
c->Message(Chat::White, "Your status is not high enough to change another person's level.");
return;
}
t->SetLevel(level, true);
if (t->IsClient()) {
t->CastToClient()->SendLevelAppearance();
if (RuleB(Bots, Enabled) && RuleB(Bots, BotLevelsWithOwner)) {
Bot::LevelBotWithClient(t->CastToClient(), level, true);
}
}
}
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
#include "../../worldserver.h"
extern WorldServer worldserver;
void SetLoginserverInfo(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3) {
c->Message(Chat::White, "Usage: #set lsinfo [Email] [Password]");
return;
}
const std::string& email = sep->arg[2];
const std::string& password = sep->arg[3];
auto pack = new ServerPacket(ServerOP_LSAccountUpdate, sizeof(ServerLSAccountUpdate_Struct));
auto s = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
s->useraccountid = c->LSAccountID();
strn0cpy(s->useraccount, c->AccountName(), 30);
strn0cpy(s->user_email, email.c_str(), 100);
strn0cpy(s->userpassword, password.c_str(), 50);
worldserver.SendPacket(pack);
safe_delete(pack);
c->Message(Chat::White, "Your email and local loginserver password have been set.");
}
+41
View File
@@ -0,0 +1,41 @@
#include "../../client.h"
void SetMana(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set mana [Amount]");
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
int64 mana = Strings::ToBigInt(sep->arg[2]);
if (t->IsClient()) {
if (mana >= t->CastToClient()->CalcMaxMana()) {
mana = t->CastToClient()->CalcMaxMana();
}
t->CastToClient()->SetMana(mana);
} else {
if (mana >= t->CalcMaxMana()) {
mana = t->CalcMaxMana();
}
t->SetMana(mana);
}
c->Message(
Chat::White,
fmt::format(
"Set {} to {} Mana.",
c->GetTargetDescription(t),
Strings::Commify(mana)
).c_str()
);
}
+28
View File
@@ -0,0 +1,28 @@
#include "../../client.h"
void SetManaFull(Client *c, const Seperator *sep)
{
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
int64 mana;
if (t->IsClient()) {
mana = t->CastToClient()->CalcMaxMana();
t->CastToClient()->SetMana(mana);
} else {
mana = t->CalcMaxMana();
t->SetMana(mana);
}
c->Message(
Chat::White,
fmt::format(
"Set {} to full Mana ({}).",
c->GetTargetDescription(t),
Strings::Commify(mana)
).c_str()
);
}
+24
View File
@@ -0,0 +1,24 @@
#include "../../client.h"
#include "../../worldserver.h"
extern WorldServer worldserver;
void command_motd(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set motd [Message]");
return;
}
const std::string& message = sep->argplus[2];
auto pack = new ServerPacket(ServerOP_Motd, sizeof(ServerMotd_Struct));
auto m = (ServerMotd_Struct *) pack->pBuffer;
strn0cpy(m->myname, c->GetName(), sizeof(m->myname));
strn0cpy(m->motd, message.c_str(), sizeof(m->motd));
worldserver.SendPacket(pack);
safe_delete(pack);
}
+43
View File
@@ -0,0 +1,43 @@
#include "../../client.h"
void SetName(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set name [Name]");
return;
}
if (c->GetTarget() && c->GetTarget()->IsClient()) {
auto t = c->GetTarget()->CastToClient();
std::string new_name = sep->arg[2];
std::string old_name = t->GetCleanName();
if (t->ChangeFirstName(new_name.c_str(), c->GetCleanName())) {
c->Message(
Chat::White,
fmt::format(
"Successfully renamed {} to {}",
old_name,
new_name
).c_str()
);
c->Message(Chat::White, "Sending player to char select.");
t->Kick("Name was changed");
return;
}
c->Message(
Chat::White,
fmt::format(
"Unable to rename {}. Check that the new name '{}' isn't already taken.",
old_name,
new_name
).c_str()
);
}
}
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
#include "../../worldserver.h"
extern WorldServer worldserver;
void SetOOCMute(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set ooc_mute [on|off]");
return;
}
const bool is_muted = Strings::ToBool(sep->arg[2]);
ServerPacket pack(ServerOP_OOCMute, sizeof(ServerOOCMute_Struct));
auto o = (ServerOOCMute_Struct*) pack.pBuffer;
o->is_muted = is_muted;
worldserver.SendPacket(&pack);
c->Message(
Chat::White,
fmt::format(
"Server OOC is {} muted.",
is_muted ? "now" : "no longer"
).c_str()
);
}
+52
View File
@@ -0,0 +1,52 @@
#include "../../client.h"
void SetPassword(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3) {
c->Message(Chat::White, "Usage: #set password [Account Name] [Password] [Loginserver]");
return;
}
std::string account_name = sep->arg[2];
std::string password = sep->arg[3];
std::string loginserver = arguments >= 4 ? sep->arg[4] : "eqemu";
int16 status = 0;
const uint32 account_id = database.GetAccountIDByName(account_name, loginserver, &status);
if (!account_id) {
c->Message(
Chat::White,
fmt::format(
"Account {} was not found.",
account_name
).c_str()
);
return;
}
if (status > c->Admin()) {
c->Message(
Chat::White,
fmt::format(
"You cannot change the password for Account {} as its status is higher than yours.",
account_name
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Password {} changed for Account {}.",
(
database.SetLocalPassword(account_id, password.c_str()) ?
"successfully" :
"failed"
),
account_name
).c_str()
);
}
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
void SetPVP(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set pvp [on|off]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const bool pvp_state = Strings::ToBool(sep->arg[2]);
t->SetPVP(pvp_state);
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"{} now follows the ways of {}.",
c->GetTargetDescription(t),
pvp_state ? "Discord" : "Order"
).c_str()
);
}
}
+33
View File
@@ -0,0 +1,33 @@
#include "../../client.h"
void SetPVPPoints(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set pvp_points [Amount]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint32 pvp_points = Strings::ToUnsignedInt(sep->arg[2]);
t->SetPVPPoints(pvp_points);
t->Save();
t->SendPVPStats();
c->Message(
Chat::White,
fmt::format(
"{} now {} {} PVP Point{}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
Strings::Commify(pvp_points),
pvp_points != 1 ? "s" : ""
).c_str()
);
}
+52
View File
@@ -0,0 +1,52 @@
#include "../../client.h"
void SetRace(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(
Chat::White,
fmt::format(
"Usage: #set race [0-{}, 2253-2259] (0 for back to normal)",
RuleI(NPC, MaxRaceID)
).c_str()
);
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
const uint16 race_id = Strings::ToUnsignedInt(sep->arg[2]);
if (
!EQ::ValueWithin(race_id, RACE_DOUG_0, RuleI(NPC, MaxRaceID)) &&
!EQ::ValueWithin(race_id, 2253, 2259)
) {
c->Message(
Chat::White,
fmt::format(
"Usage: #race [0-{}, 2253-2259] (0 for back to normal)",
RuleI(NPC, MaxRaceID)
).c_str()
);
return;
}
t->SendIllusionPacket(race_id);
c->Message(
Chat::White,
fmt::format(
"{} {} now temporarily a(n) {} ({}).",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "are" : "is",
GetRaceIDName(race_id),
race_id
).c_str()
);
}
+45
View File
@@ -0,0 +1,45 @@
#include "../../client.h"
void SetRacePermanent(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set race_permanent [Race ID]");
c->Message(
Chat::White,
"NOTE: Not all models are global. If a model is not global, it will appear as a Human on character select and in zones without the model."
);
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint16 race_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint8 gender_id = Mob::GetDefaultGender(race_id, t->GetBaseGender());
LogInfo("Race changed by {} for {} to {} ({})",
c->GetCleanName(),
c->GetTargetDescription(t),
GetRaceIDName(race_id),
race_id
);
t->SetBaseRace(race_id);
t->SetBaseGender(gender_id);
t->Save();
t->SendIllusionPacket(race_id, gender_id);
c->Message(
Chat::White,
fmt::format(
"Race changed for {} to {} ({}).",
c->GetTargetDescription(t),
GetRaceIDName(race_id),
race_id
).c_str()
);
}
+33
View File
@@ -0,0 +1,33 @@
#include "../../client.h"
#include "../../worldserver.h"
extern WorldServer worldserver;
void SetServerLocked(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set server_locked [on|off]");
return;
}
bool is_locked = Strings::ToBool(sep->arg[2]);
if (c->EntityVariableExists("old_command")) {
const std::string& old_command = c->GetEntityVariable("old_command");
if (old_command == "lock" || old_command == "serverlock") {
is_locked = true;
} else if (old_command == "unlock" || old_command == "serverunlock") {
is_locked = false;
}
}
auto pack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct));
auto l = (ServerLock_Struct *) pack->pBuffer;
strn0cpy(l->character_name, c->GetCleanName(), sizeof(l->character_name));
l->is_locked = is_locked;
worldserver.SendPacket(pack);
safe_delete(pack);
}
+44
View File
@@ -0,0 +1,44 @@
#include "../../client.h"
void SetSkill(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set skill [Skill ID] [Skill Value]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint16 skill_id = Strings::ToUnsignedInt(sep->arg[2]);
const uint16 skill_value = Strings::ToUnsignedInt(sep->arg[3]);
if (!EQ::ValueWithin(skill_id, EQ::skills::Skill1HBlunt, EQ::skills::HIGHEST_SKILL)) {
c->Message(Chat::White, "Usage: #set skill [Skill ID] [Skill Value]");
c->Message(Chat::White, fmt::format("Skill ID: 0 to {}", EQ::skills::HIGHEST_SKILL).c_str());
return;
}
const auto skill_type = static_cast<EQ::skills::SkillType>(skill_id);
t->SetSkill(
skill_type,
skill_value > t->MaxSkill(skill_type) ? t->MaxSkill(skill_type) : skill_value
);
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"Set {} ({}) to {} for {}.",
EQ::skills::GetSkillName(skill_type),
skill_id,
skill_value > t->MaxSkill(skill_type) ? t->MaxSkill(skill_type) : skill_value,
c->GetTargetDescription(t)
).c_str()
);
}
}
+39
View File
@@ -0,0 +1,39 @@
#include "../../client.h"
void SetSkillAll(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set skill_all [Skill Level]");
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint16 skill_level = Strings::ToUnsignedInt(sep->arg[2]);
for (const auto& s : EQ::skills::GetSkillTypeMap()) {
if (t->CanHaveSkill(s.first) && t->MaxSkill(s.first)) {
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"Setting {} ({}) to {} for {}.",
s.second,
s.first,
skill_level > t->MaxSkill(s.first) ? t->MaxSkill(s.first) : skill_level,
c->GetTargetDescription(t)
).c_str()
);
}
t->SetSkill(
s.first,
skill_level > t->MaxSkill(s.first) ? t->MaxSkill(s.first) : skill_level
);
}
}
}
+19
View File
@@ -0,0 +1,19 @@
#include "../../client.h"
void SetSkillAllMax(Client *c, const Seperator *sep)
{
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
t->MaxSkills();
c->Message(
Chat::White,
fmt::format(
"Maxed skills for {}.",
c->GetTargetDescription(t)
).c_str()
);
}
+51
View File
@@ -0,0 +1,51 @@
#include "../../client.h"
void SetStartZone(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set start_zone [Zone ID|Zone Short Name]");
c->Message(
Chat::White,
"Optional Usage: Use '#set start_zone reset' or '#set start_zone 0' to clear a starting zone. Player can select a starting zone using /setstartcity"
);
return;
}
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const uint32 zone_id = (
sep->IsNumber(2) ?
Strings::ToUnsignedInt(sep->arg[2]) :
ZoneID(sep->arg[2])
);
t->SetStartZone(zone_id);
const bool is_reset = (
Strings::EqualFold(sep->arg[2], "reset") ||
zone_id == 0
);
c->Message(
Chat::White,
fmt::format(
"Start Zone {} for {} |{}",
is_reset ? "Reset" : "Changed",
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
(
zone_id ?
fmt::format(
" {} ({}) ID: {}",
ZoneLongName(zone_id),
ZoneName(zone_id),
zone_id
) :
""
)
).c_str()
);
}
+38
View File
@@ -0,0 +1,38 @@
#include "../../client.h"
void SetTemporaryName(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set temporary_name [New Name]");
c->Message(Chat::White, "Note: This command requires a target, even if the target is yourself.");
return;
}
if (!c->GetTarget()) {
c->Message(Chat::White, "Usage: #set temporary_name [New Name]");
c->Message(Chat::White, "Note: This command requires a target, even if the target is yourself.");
return;
}
Mob* t = c->GetTarget();
const std::string& temporary_name = strlen(sep->arg[2]) ? sep->arg[2] : "";
t->TempName(temporary_name.c_str());
if (temporary_name.length()) {
const std::string& current_name = t->GetName();
c->Message(
Chat::White,
fmt::format(
"Renamed {} to {} temporarily.",
current_name,
temporary_name
).c_str()
);
} else {
c->Message(Chat::White, "Restored your target's original name.");
}
}
+56
View File
@@ -0,0 +1,56 @@
#include "../../client.h"
void SetTexture(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set texture [Texture] [Helmet Texture]");
return;
}
const uint16 texture = Strings::ToUnsignedInt(sep->arg[2]);
const uint8 helmet_texture = (
sep->IsNumber(3) ?
Strings::ToUnsignedInt(sep->arg[3]) :
0
);
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
if (IsPlayerRace(t->GetModel())) { // Player Races Wear Armor, so Wearchange is sent instead
for (
int texture_slot = EQ::textures::textureBegin;
texture_slot <= EQ::textures::LastTintableTexture;
texture_slot++
) {
t->SendTextureWC(texture_slot, texture);
}
} else { // Non-Player Races only need Illusion Packets to be sent for texture
t->SendIllusionPacket(
t->GetModel(),
t->GetGender(),
texture,
helmet_texture
);
}
c->Message(
Chat::White,
fmt::format(
"Texture Changed for {} | Texture: {}{}",
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
texture,
(
IsPlayerRace(t->GetModel()) ?
"" :
fmt::format(
" Helmet Texture: {}",
helmet_texture
)
)
).c_str()
);
}
+67
View File
@@ -0,0 +1,67 @@
#include "../../client.h"
void SetTime(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set time [Hour] [Minute]");
TimeOfDay_Struct world_time;
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time);
auto time_string = fmt::format(
"{} (Timezone: {})",
Strings::ZoneTime(world_time.hour, world_time.minute),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
);
c->Message(
Chat::White,
fmt::format(
"It is currently {}.",
time_string
).c_str()
);
return;
}
uint8 minutes = 0;
uint8 hours = Strings::ToUnsignedInt(sep->arg[2]) + 1;
if (hours > 24) {
hours = 24;
}
uint8 real_hours = (
(hours - 1) > 0 ?
(hours - 1) :
0
);
if (sep->IsNumber(3)) {
minutes = Strings::ToUnsignedInt(sep->arg[3]);
if (minutes > 59) {
minutes = 59;
}
}
c->Message(
Chat::White,
fmt::format(
"Setting world time to {} (Timezone: {}).",
Strings::ZoneTime(hours, minutes),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
).c_str()
);
zone->SetTime(real_hours, minutes);
LogInfo(
"{} :: Setting world time to {} (Timezone: {})",
c->GetCleanName(),
Strings::ZoneTime(hours, minutes),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
);
}
+58
View File
@@ -0,0 +1,58 @@
#include "../../client.h"
void SetTimeZone(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set time_zone [Hour] [Minute]");
c->Message(
Chat::White,
fmt::format(
"Current time zone is {}.",
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneMin())
).c_str()
);
return;
}
uint8 minutes = 0;
uint8 hours = Strings::ToUnsignedInt(sep->arg[2]);
if (hours > 24) {
hours = 24;
}
uint8 real_hours = (
(hours - 1) > 0 ?
(hours - 1) :
0
);
if (sep->IsNumber(3)) {
minutes = Strings::ToUnsignedInt(sep->arg[3]);
if (minutes > 59) {
minutes = 59;
}
}
c->Message(
Chat::White,
fmt::format(
"Setting timezone to {}.",
Strings::ZoneTime(hours, minutes)
).c_str()
);
const int new_timezone = ((hours * 60) + minutes);
zone->zone_time.setEQTimeZone(new_timezone);
content_db.SetZoneTZ(zone->GetZoneID(), zone->GetInstanceVersion(), new_timezone);
auto outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct));
auto t = (TimeOfDay_Struct *) outapp->pBuffer;
zone->zone_time.GetCurrentEQTimeOfDay(time(0), t);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
}
+55
View File
@@ -0,0 +1,55 @@
#include "../../client.h"
#include "../../titles.h"
void SetTitle(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #set title [Title]");
c->Message(Chat::White, "Note: Use \"-1\" to remove title.");
return;
}
const bool is_remove = Strings::EqualFold(sep->argplus[2], "-1");
std::string title = !is_remove ? sep->argplus[2] : "";
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
if (title.size() > 31) {
c->Message(Chat::White, "Title must be 31 characters or less.");
return;
}
if (!title.empty()) {
Strings::FindReplace(title, "_", " ");
}
if (is_remove) {
t->SetAATitle(title);
} else {
title_manager.CreateNewPlayerTitle(t, title);
}
t->Save();
c->Message(
Chat::White,
fmt::format(
"Title has been {}{} for {}{}",
is_remove ? "removed" : "changed",
!is_remove ? " and saved" : "",
c->GetTargetDescription(t),
(
is_remove ?
"." :
fmt::format(
" to '{}'.",
title
)
)
).c_str()
);
}
+55
View File
@@ -0,0 +1,55 @@
#include "../../client.h"
#include "../../titles.h"
void SetTitleSuffix(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #set title_suffix [Title Suffix]");
c->Message(Chat::White, "Note: Use \"-1\" to remove title.");
return;
}
const bool is_remove = !strcasecmp(sep->argplus[1], "-1");
std::string suffix = is_remove ? "" : sep->argplus[1];
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
if (suffix.size() > 31) {
c->Message(Chat::White, "Title suffix must be 31 characters or less.");
return;
}
if (!suffix.empty()) {
Strings::FindReplace(suffix, "_", " ");
}
if (is_remove) {
t->SetTitleSuffix(suffix);
} else {
title_manager.CreateNewPlayerSuffix(t, suffix);
}
t->Save();
c->Message(
Chat::White,
fmt::format(
"Title suffix has been {}{} for {}{}",
is_remove ? "removed" : "changed",
!is_remove ? " and saved" : "",
c->GetTargetDescription(t),
(
is_remove ?
"." :
fmt::format(
" to '{}'.",
suffix
)
)
).c_str()
);
}
+101
View File
@@ -0,0 +1,101 @@
#include "../../client.h"
void SetWeather(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #weather [0|1|2] - [Off|Rain|Snow]");
c->Message(Chat::White, "Usage: #weather 3 [Type] [Intensity] - Manually set weather type and intensity");
return;
}
if (arguments == 2) {
uint8 new_weather = Strings::ToUnsignedInt(sep->arg[2]);
uint8 new_intensity = 0;
std::string weather_message = "The sky clears.";
if (new_weather == EQ::constants::WeatherTypes::Snowing) {
weather_message = "Snowflakes begin to fall from the sky.";
new_weather = EQ::constants::WeatherTypes::Snowing;
new_intensity = 2;
} else if (new_weather == EQ::constants::WeatherTypes::Raining) {
weather_message = "Raindrops begin to fall from the sky.";
new_weather = EQ::constants::WeatherTypes::Raining;
new_intensity = 1; // This is how it's done in Fear, and you can see a decent distance with it at this value
}
zone->zone_weather = new_weather;
auto outapp = new EQApplicationPacket(OP_Weather, 8);
if (new_weather != EQ::constants::WeatherTypes::None) {
if (new_weather == EQ::constants::WeatherTypes::Snowing) {
outapp->pBuffer[0] = EQ::constants::WeatherTypes::Snowing;
}
outapp->pBuffer[4] = new_intensity;
}
c->Message(Chat::White, weather_message.c_str());
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
} else if (arguments == 4) {
const uint8 command_type = Strings::ToUnsignedInt(sep->arg[2]);
uint8 new_weather = EQ::constants::WeatherTypes::None;
uint8 new_intensity = 0;
std::string weather_message;
if (zone->zone_weather == EQ::constants::WeatherTypes::None) {
if (command_type > EQ::constants::WeatherTypes::Snowing) {
new_weather = Strings::ToUnsignedInt(sep->arg[3]);
new_intensity = Strings::ToUnsignedInt(sep->arg[4]);
weather_message = fmt::format(
"Sending {} ({}) with an intensity of {}.",
EQ::constants::GetWeatherTypeName(new_weather),
new_weather,
new_intensity
);
} else if (command_type == EQ::constants::WeatherTypes::Snowing) {
weather_message = "Snowflakes begin to fall from the sky.";
new_weather = EQ::constants::WeatherTypes::Snowing;
new_intensity = 2;
} else if (command_type == EQ::constants::WeatherTypes::Raining) {
weather_message = "Raindrops begin to fall from the sky.";
new_weather = EQ::constants::WeatherTypes::Raining;
new_intensity = 1; // This is how it's done in Fear, and you can see a decent distance with it at this value
}
zone->zone_weather = new_weather;
auto outapp = new EQApplicationPacket(OP_Weather, 8);
if (new_weather != EQ::constants::WeatherTypes::Raining) {
outapp->pBuffer[0] = new_weather;
}
outapp->pBuffer[4] = new_intensity;
c->Message(Chat::White, weather_message.c_str());
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
} else {
auto outapp = new EQApplicationPacket(OP_Weather, 8);
weather_message = "The sky clears.";
if (zone->zone_weather == EQ::constants::WeatherTypes::Snowing) {
weather_message = "The sky clears as the snow stops falling.";
outapp->pBuffer[0] = 1; // Snow has it's own shutoff packet
} else if (zone->zone_weather == EQ::constants::WeatherTypes::Raining) {
weather_message = "The sky clears as the rain ceases to fall.";
}
zone->zone_weather = EQ::constants::WeatherTypes::None;
c->Message(Chat::White, weather_message.c_str());
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
}
}
}
+455
View File
@@ -0,0 +1,455 @@
#include "../../client.h"
void SetZoneData(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (arguments < 3) {
c->Message(
Chat::White,
"Usage: #set zone clipping [Minimum Clip] [Maximum Clip] [Fog Minimum Clip] [Fog Maximum Clip] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone color [Red] [Green] [Blue] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone header [Zone ID|Zone Short Name] [Version]"
);
c->Message(
Chat::White,
"Usage: #set zone locked [on|off] [Zone ID|Zone Short Name]"
);
c->Message(
Chat::White,
"Usage: #set zone safe_coordinates [X] [Y] [Z] [Heading] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone sky [Sky Type] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone underworld [Z] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
return;
}
const bool is_clipping = Strings::EqualFold(sep->arg[2], "clipping");
const bool is_color = Strings::EqualFold(sep->arg[2], "color");
const bool is_header = Strings::EqualFold(sep->arg[2], "header");
const bool is_locked = Strings::EqualFold(sep->arg[2], "locked");
const bool is_safe_coordinates = Strings::EqualFold(sep->arg[2], "safe_coordinates");
const bool is_sky = Strings::EqualFold(sep->arg[2], "sky");
const bool is_underworld = Strings::EqualFold(sep->arg[2], "underworld");
if (
!is_clipping &&
!is_color &&
!is_header &&
!is_locked &&
!is_safe_coordinates &&
!is_sky &&
!is_underworld
) {
c->Message(
Chat::White,
"Usage: #set zone clipping [Minimum Clip] [Maximum Clip] [Fog Minimum Clip] [Fog Maximum Clip] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone color [Red] [Green] [Blue] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone header [Zone ID|Zone Short Name] [Version]"
);
c->Message(
Chat::White,
"Usage: #set zone locked [on|off] [Zone ID|Zone Short Name]"
);
c->Message(
Chat::White,
"Usage: #set zone safe_coordinates [X] [Y] [Z] [Heading] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone sky [Sky Type] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
c->Message(
Chat::White,
"Usage: #set zone underworld [Z] [Permanent (0 = False, 1 = True)] (Permanent is optional)"
);
return;
}
if (is_clipping) {
const float minimum_clip = sep->arg[3] ? Strings::ToFloat(sep->arg[3]) : 0.0f;
const float maximum_clip = sep->arg[4] ? Strings::ToFloat(sep->arg[4]) : 0.0f;
const float minimum_fog_clip = sep->arg[5] ? Strings::ToFloat(sep->arg[5]) : 0.0f;
const float maximum_fog_clip = sep->arg[6] ? Strings::ToFloat(sep->arg[6]) : 0.0f;
const bool permanent = sep->arg[7] ? Strings::ToBool(sep->arg[7]) : false;
if (minimum_clip < 0.0f || maximum_clip < 0.0f) {
c->Message(Chat::White, "Minimum Clip and Maximum Clip must be greater than or equal 0.0.");
return;
} else if (minimum_clip > maximum_clip) {
c->Message(Chat::White, "Minimum Clip must be less than or equal to Maximum Clip!");
return;
} else {
zone->newzone_data.minclip = minimum_clip;
zone->newzone_data.maxclip = maximum_clip;
if (minimum_fog_clip) {
for (float &fog_index: zone->newzone_data.fog_minclip) {
fog_index = minimum_fog_clip;
}
}
if (maximum_fog_clip) {
for (float &fog_index: zone->newzone_data.fog_maxclip) {
fog_index = maximum_fog_clip;
}
}
if (permanent) {
std::string query = fmt::format(
"UPDATE zone SET minclip = {:.2f}, maxclip = {:.2f} WHERE zoneidnumber = {} AND version = {}",
minimum_clip,
maximum_clip,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
if (minimum_fog_clip) {
query = fmt::format(
"UPDATE zone SET fog_minclip = {:.2f} WHERE zoneidnumber = {} AND version = {}",
minimum_fog_clip,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
}
if (maximum_fog_clip) {
query = fmt::format(
"UPDATE zone SET fog_maxclip = {:.2f} WHERE zoneidnumber = {} AND version = {}",
maximum_fog_clip,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
}
}
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
c->Message(
Chat::White,
fmt::format(
"Clipping Changed | Zone: {} Permanent: {}",
zone->GetZoneDescription(),
permanent ? "Yes" : "No"
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Clipping Changed | Minimum Clip: {:.2f} Maximum Clip: {:.2f}",
minimum_clip,
maximum_clip
).c_str()
);
if (minimum_fog_clip || maximum_fog_clip) {
c->Message(
Chat::White,
fmt::format(
"Clipping Changed | Fog Minimum Clip: {:.2f} Fog Maximum Clip: {:.2f}",
minimum_fog_clip,
maximum_fog_clip
).c_str()
);
}
}
} else if (is_color) {
if (
arguments < 3 ||
!sep->IsNumber(3) ||
!sep->IsNumber(4) ||
!sep->IsNumber(5)
) {
c->Message(Chat::White, "Usage: #set zone color [Red] [Green] [Blue] [Permanent (0 = False, 1 = True)]");
return;
}
const uint8 red = Strings::ToUnsignedInt(sep->arg[3]);
const uint8 green = Strings::ToUnsignedInt(sep->arg[4]);
const uint8 blue = Strings::ToUnsignedInt(sep->arg[5]);
const bool permanent = sep->arg[6] ? Strings::ToBool(sep->arg[6]) : false;
if (
!EQ::ValueWithin(red, 0, UINT8_MAX) ||
!EQ::ValueWithin(green, 0, UINT8_MAX) ||
!EQ::ValueWithin(blue, 0, UINT8_MAX)
) {
c->Message(Chat::White, "Colors cannot be less than 0 or greater than 255.");
return;
}
if (permanent) {
const std::string& query = fmt::format(
"UPDATE zone SET fog_red = {}, fog_green = {}, fog_blue = {} "
"WHERE zoneidnumber = {} AND version = {}",
red,
green,
blue,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
}
for (uint8 fog_index = 0; fog_index < 4; fog_index++) {
zone->newzone_data.fog_red[fog_index] = red;
zone->newzone_data.fog_green[fog_index] = green;
zone->newzone_data.fog_blue[fog_index] = blue;
}
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
c->Message(
Chat::White,
fmt::format(
"Fog Color Changed | Zone: {} Red: {} Green: {} Blue: {} Permanent: {}",
zone->GetZoneDescription(),
red,
green,
blue,
permanent ? "Yes" : "No"
).c_str()
);
} else if (is_header) {
if (arguments < 3) {
c->Message(Chat::White, "Usage: #set zone header [Zone ID|Zone Short Name] [Version]");
return;
}
const auto zone_id = (
sep->IsNumber(3) ?
Strings::ToUnsignedInt(sep->arg[3]) :
ZoneID(sep->arg[3])
);
if (!zone_id) {
c->Message(
Chat::White,
fmt::format(
"Zone ID {} could not be found.",
zone_id
).c_str()
);
return;
}
const std::string& zone_short_name = ZoneName(zone_id);
const std::string& zone_long_name = ZoneLongName(zone_id);
const auto version = (
sep->IsNumber(4) ?
Strings::ToUnsignedInt(sep->arg[4]) :
0
);
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
zone_store.LoadZones(content_db);
c->Message(
Chat::White,
fmt::format(
"Zone Header Load {} | Zone: {} ({}){}",
(
zone->LoadZoneCFG(zone_short_name.c_str(), version) ?
"Succeeded" :
"Failed"
),
zone_long_name,
zone_short_name,
(
version ?
fmt::format(
" Version: {}",
version
) :
""
)
).c_str()
);
} else if (is_locked) {
if (arguments < 4) {
c->Message(Chat::White, "Usage: #set zone locked [on|off] [Zone ID|Zone Short Name]");
return;
}
const bool is_locked = Strings::ToBool(sep->arg[3]);
const uint32 zone_id = (
sep->IsNumber(4) ?
Strings::ToUnsignedInt(sep->arg[4]) :
ZoneID(sep->arg[4])
);
const std::string& zone_short_name = Strings::ToLower(ZoneName(zone_id, true));
const bool is_unknown_zone = Strings::EqualFold(zone_short_name, "unknown");
if (!zone_id || is_unknown_zone) {
c->Message(Chat::White, "Usage: #set zone locked [on|off] [Zone ID|Zone Short Name]");
return;
}
auto pack = new ServerPacket(ServerOP_LockZone, sizeof(ServerLockZone_Struct));
auto l = (ServerLockZone_Struct *) pack->pBuffer;
strn0cpy(l->adminname, c->GetName(), sizeof(l->adminname));
l->op = is_locked ? ServerLockType::Lock : ServerLockType::Unlock;
l->zoneID = zone_id;
worldserver.SendPacket(pack);
safe_delete(pack);
} else if (is_safe_coordinates) {
if (
arguments < 3 ||
!sep->IsNumber(3) ||
!sep->IsNumber(4) ||
!sep->IsNumber(5)
) {
c->Message(Chat::White, "Usage: #set zone safe_coordinates [X] [Y] [Z] [Heading] [Permanent (0 = False, 1 = True)]");
c->Message(Chat::White, "Not sending Heading defaults to current Heading and the change is temporary.");
return;
}
const float x = Strings::ToFloat(sep->arg[3]);
const float y = Strings::ToFloat(sep->arg[4]);
const float z = Strings::ToFloat(sep->arg[5]);
const float heading = sep->arg[6] ? Strings::ToFloat(sep->arg[6]) : c->GetHeading();
const bool permanent = sep->arg[7] ? Strings::ToBool(sep->arg[7]) : false;
if (permanent) {
const std::string& query = fmt::format(
"UPDATE zone SET safe_x = {:.2f}, safe_y = {:.2f}, safe_z = {:.2f}, safe_heading = {:.2f} WHERE zoneidnumber = {} AND version = {}",
x,
y,
z,
heading,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
}
zone->newzone_data.safe_x = x;
zone->newzone_data.safe_y = y;
zone->newzone_data.safe_z = z;
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
c->Message(
Chat::White,
fmt::format(
"Safe Coordinates Changed | Zone: {} XYZ: {:.2f}, {:.2f}, {:.2f} Heading: {:.2f} Permanent: {} ",
zone->GetZoneDescription(),
x,
y,
z,
heading,
permanent ? "Yes" : "No"
).c_str()
);
} else if (is_sky) {
if (arguments < 3 || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set zone sky [Sky Type] [Permanent (0 = False, 1 = True)]");
return;
}
const uint8 sky_type = Strings::ToUnsignedInt(sep->arg[3]);
const bool permanent = sep->arg[4] ? Strings::ToBool(sep->arg[4]) : false;
if (!EQ::ValueWithin(sky_type, 0, UINT8_MAX)) {
c->Message(Chat::White, "Sky Type cannot be less than 0 or greater than 255!");
return;
}
if (permanent) {
const std::string& query = fmt::format(
"UPDATE zone SET sky = {} WHERE zoneidnumber = {} AND version = {}",
sky_type,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
}
zone->newzone_data.sky = sky_type;
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
c->Message(
Chat::White,
fmt::format(
"Sky Changed | Zone: {} Sky Type: {} Permanent: {}",
zone->GetZoneDescription(),
sky_type,
permanent ? "Yes" : "No"
).c_str()
);
} else if (is_underworld) {
if (arguments < 3 || !sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #set zone underworld [Z] [Permanent (0 = False, 1 = True)]");
return;
}
const float z = Strings::ToFloat(sep->arg[3]);
const bool permanent = sep->arg[4] ? Strings::ToBool(sep->arg[4]) : false;
if (permanent) {
auto query = fmt::format(
"UPDATE zone SET underworld = {:.2f} WHERE zoneidnumber = {} AND version = {}",
z,
zone->GetZoneID(),
zone->GetInstanceVersion()
);
database.QueryDatabase(query);
}
zone->newzone_data.underworld = z;
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
entity_list.QueueClients(c, outapp);
safe_delete(outapp);
c->Message(
Chat::White,
fmt::format(
"Underworld Z Changed | Zone: {} Z: {:.2f} Permanent: {}",
zone->GetZoneDescription(),
z,
permanent ? "Yes" : "No"
).c_str()
);
}
}