[GM Commands] Split GM Commands Into Separate Files (#1766)

* Split GM commands into their own files

* Code cleanup
This commit is contained in:
Chris Miles 2021-11-14 22:48:47 -06:00 committed by GitHub
parent 293361a1f7
commit 0550fcfd3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
291 changed files with 19224 additions and 15798 deletions

2
.gitignore vendored
View File

@ -54,3 +54,5 @@ bin/
/Win32 /Win32
/x64 /x64
/client_files/**/CMakeFiles/ /client_files/**/CMakeFiles/
.idea

View File

@ -65,3 +65,8 @@ void FileUtil::mkdir(const std::string& directory_name)
::mkdir(directory_name.c_str(), 0755); ::mkdir(directory_name.c_str(), 0755);
#endif #endif
} }
bool file_exists(const std::string& name) {
std::ifstream f(name.c_str());
return f.good();
}

View File

@ -28,5 +28,6 @@ public:
static void mkdir(const std::string& directory_name); static void mkdir(const std::string& directory_name);
}; };
bool file_exists(const std::string& name);
#endif //EQEMU_FILE_UTIL_H #endif //EQEMU_FILE_UTIL_H

View File

@ -1633,3 +1633,41 @@ uint32 GetProcLimitTimer(int32 spell_id, int proc_type) {
} }
return 0; return 0;
} }
bool CastRestrictedSpell(int spellid)
{
switch (spellid) {
case SPELL_TOUCH_OF_VINITRAS:
case SPELL_DESPERATE_HOPE:
case SPELL_CHARM:
case SPELL_METAMORPHOSIS65:
case SPELL_JT_BUFF:
case SPELL_CAN_O_WHOOP_ASS:
case SPELL_PHOENIX_CHARM:
case SPELL_CAZIC_TOUCH:
case SPELL_AVATAR_KNOCKBACK:
case SPELL_SHAPECHANGE65:
case SPELL_SUNSET_HOME1218:
case SPELL_SUNSET_HOME819:
case SPELL_SHAPECHANGE75:
case SPELL_SHAPECHANGE80:
case SPELL_SHAPECHANGE85:
case SPELL_SHAPECHANGE90:
case SPELL_SHAPECHANGE95:
case SPELL_SHAPECHANGE100:
case SPELL_SHAPECHANGE25:
case SPELL_SHAPECHANGE30:
case SPELL_SHAPECHANGE35:
case SPELL_SHAPECHANGE40:
case SPELL_SHAPECHANGE45:
case SPELL_SHAPECHANGE50:
case SPELL_NPC_AEGOLISM:
case SPELL_SHAPECHANGE55:
case SPELL_SHAPECHANGE60:
case SPELL_COMMAND_OF_DRUZZIL:
case SPELL_SHAPECHANGE70:
return true;
default:
return false;
}
}

View File

@ -1531,5 +1531,6 @@ bool IsShortDurationBuff(uint16 spell_id);
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type); bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
const char *GetSpellName(uint16 spell_id); const char *GetSpellName(uint16 spell_id);
int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot = 0); int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot = 0);
bool CastRestrictedSpell(int spellid);
#endif #endif

183
utils/gm_commands/main.go Normal file
View File

@ -0,0 +1,183 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"sort"
"strings"
)
func main() {
// zone/command.cpp
commands, err := os.ReadFile("./zone/command.cpp")
if err != nil {
log.Fatal(err)
}
commandsString := string(commands)
s := strings.Split(commandsString, "void command_")
commandFiles := []string{}
if len(s) > 1 {
startListing := false
for i, chunk := range s {
if strings.Contains(chunk, "logcommand(Client *c") {
startListing = true
}
// get function name
functionName := ""
nameSplit := strings.Split(chunk, "(Client")
if len(nameSplit) > 0 {
functionName = strings.TrimSpace(nameSplit[0])
}
if startListing &&
len(s[i-1]) > 0 &&
!strings.Contains(s[i-1], "#ifdef") &&
!strings.Contains(chunk, "#ifdef") &&
!strings.Contains(chunk, "#ifdef BOTS") &&
!strings.Contains(chunk, "#ifdef EQPROFILE") &&
!strings.Contains(functionName, "bot") &&
!strings.Contains(functionName, "help") &&
!strings.Contains(functionName, "findaliases") {
fmt.Println(functionName)
// build command file name
commandFile := fmt.Sprintf("zone/gm_commands/%v.cpp", functionName)
// append command file nam eto list
commandFiles = append(commandFiles, commandFile)
includes := ""
if strings.Contains(chunk, "Client") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../client.h\"")
}
if strings.Contains(chunk, "parse->") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../quest_parser_collection.h\"")
}
if strings.Contains(chunk, "worldserver.") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../worldserver.h\"")
includes = fmt.Sprintf("%v%v\n", includes, "extern WorldServer worldserver;")
}
if strings.Contains(chunk, "RegionType") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../water_map.h\"")
}
if strings.Contains(chunk, "Corpse") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../corpse.h\"")
}
if strings.Contains(chunk, "Object") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../object.h\"")
}
if strings.Contains(chunk, "DoorManipulation") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"door_manipulation.h\"")
}
if strings.Contains(chunk, "Group") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../groups.h\"")
}
if strings.Contains(chunk, "httplib") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/http/httplib.h\"")
}
if strings.Contains(chunk, "guild_mgr") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../guild_mgr.h\"")
}
if strings.Contains(chunk, "expedition") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../expedition.h\"")
}
if strings.Contains(chunk, "DataBucket::") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../data_bucket.h\"")
}
if strings.Contains(chunk, "file_exists") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/file_util.h\"")
}
if strings.Contains(chunk, "std::thread") {
includes = fmt.Sprintf("%v%v\n", includes, "#include <thread>")
}
if strings.Contains(chunk, "Door") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../doors.h\"")
}
if strings.Contains(chunk, "NOW_INVISIBLE") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../string_ids.h\"")
}
if strings.Contains(chunk, "Expansion::") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/content/world_content_service.h\"")
}
if strings.Contains(chunk, "MobMovementManager::") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../mob_movement_manager.h\"")
}
if strings.Contains(chunk, "MobStuckBehavior::") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../mob_movement_manager.h\"")
}
if strings.Contains(chunk, "ReloadAllPatches") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/patches/patches.h\"")
}
if strings.Contains(chunk, "ProfanityManager") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/profanity_manager.h\"")
}
if strings.Contains(chunk, "npc_scale_manager") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../npc_scale_manager.h\"")
}
if strings.Contains(chunk, "g_Math") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../fastmath.h\"")
includes = fmt.Sprintf("%v%v\n", includes, "extern FastMath g_Math;")
}
if strings.Contains(chunk, "raid") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../raids.h\"")
}
if strings.Contains(chunk, "Raid") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../raids.h\"")
}
if strings.Contains(chunk, "GetOS") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/serverinfo.h\"")
}
if strings.Contains(chunk, "LANG_") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/languages.h\"")
}
if strings.Contains(chunk, "ServerOP_Shared") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/shared_tasks.h\"")
}
if strings.Contains(chunk, "title_manager") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../titles.h\"")
}
if strings.Contains(chunk, "CatchSignal") {
includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../world/main.h\"")
}
// build the contents of the command file
commandString := fmt.Sprintf("%v\nvoid command_%v", includes, chunk)
//write file contents
err := ioutil.WriteFile(commandFile, []byte(commandString), 0777)
if err != nil {
fmt.Println(err)
}
commandOnly := fmt.Sprintf("void command_%v", chunk)
commandsString = strings.ReplaceAll(commandsString, commandOnly, "")
}
}
// rewrite commands.cpp with functions removed
err := ioutil.WriteFile("zone/command.cpp", []byte(commandsString), 0777)
if err != nil {
fmt.Println(err)
}
fmt.Println("# CmakeLists")
// sort a-z
sort.Slice(commandFiles, func(i, j int) bool {
return commandFiles[i] < commandFiles[j]
})
for _, file := range commandFiles {
file = strings.ReplaceAll(file, "zone/", "")
fmt.Println(file)
}
}
//fmt.Print(string(commands))
}

View File

@ -287,7 +287,290 @@ SET(zone_headers
zone_store.h zone_store.h
) )
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers}) SET(gm_commands
gm_commands/acceptrules.cpp
gm_commands/advnpcspawn.cpp
gm_commands/aggro.cpp
gm_commands/aggrozone.cpp
gm_commands/ai.cpp
gm_commands/appearance.cpp
gm_commands/attack.cpp
gm_commands/augmentitem.cpp
gm_commands/ban.cpp
gm_commands/beard.cpp
gm_commands/beardcolor.cpp
gm_commands/bestz.cpp
gm_commands/bind.cpp
gm_commands/camerashake.cpp
gm_commands/castspell.cpp
gm_commands/chat.cpp
gm_commands/checklos.cpp
gm_commands/copycharacter.cpp
gm_commands/corpse.cpp
gm_commands/corpsefix.cpp
gm_commands/cvs.cpp
gm_commands/damage.cpp
gm_commands/databuckets.cpp
gm_commands/date.cpp
gm_commands/dbspawn2.cpp
gm_commands/delacct.cpp
gm_commands/deletegraveyard.cpp
gm_commands/delpetition.cpp
gm_commands/depop.cpp
gm_commands/depopzone.cpp
gm_commands/details.cpp
gm_commands/devtools.cpp
gm_commands/disablerecipe.cpp
gm_commands/disarmtrap.cpp
gm_commands/distance.cpp
gm_commands/doanim.cpp
gm_commands/door.cpp
gm_commands/dye.cpp
gm_commands/dz.cpp
gm_commands/dzkickplayers.cpp
gm_commands/editmassrespawn.cpp
gm_commands/emote.cpp
gm_commands/emotesearch.cpp
gm_commands/emoteview.cpp
gm_commands/enablerecipe.cpp
gm_commands/endurance.cpp
gm_commands/equipitem.cpp
gm_commands/face.cpp
gm_commands/faction.cpp
gm_commands/findclass.cpp
gm_commands/findfaction.cpp
gm_commands/findnpctype.cpp
gm_commands/findrace.cpp
gm_commands/findskill.cpp
gm_commands/findspell.cpp
gm_commands/findtask.cpp
gm_commands/findzone.cpp
gm_commands/fixmob.cpp
gm_commands/flag.cpp
gm_commands/flagedit.cpp
gm_commands/flags.cpp
gm_commands/flymode.cpp
gm_commands/fov.cpp
gm_commands/freeze.cpp
gm_commands/gassign.cpp
gm_commands/gearup.cpp
gm_commands/gender.cpp
gm_commands/getplayerburiedcorpsecount.cpp
gm_commands/getvariable.cpp
gm_commands/ginfo.cpp
gm_commands/giveitem.cpp
gm_commands/givemoney.cpp
gm_commands/globalview.cpp
gm_commands/gm.cpp
gm_commands/gmspeed.cpp
gm_commands/gmzone.cpp
gm_commands/goto.cpp
gm_commands/grid.cpp
gm_commands/guild.cpp
gm_commands/guildapprove.cpp
gm_commands/guildcreate.cpp
gm_commands/guildlist.cpp
gm_commands/hair.cpp
gm_commands/haircolor.cpp
gm_commands/haste.cpp
gm_commands/hatelist.cpp
gm_commands/heal.cpp
gm_commands/helm.cpp
gm_commands/heritage.cpp
gm_commands/heromodel.cpp
gm_commands/hideme.cpp
gm_commands/hp.cpp
gm_commands/incstat.cpp
gm_commands/instance.cpp
gm_commands/interrogateinv.cpp
gm_commands/interrupt.cpp
gm_commands/invsnapshot.cpp
gm_commands/invul.cpp
gm_commands/ipban.cpp
gm_commands/iplookup.cpp
gm_commands/iteminfo.cpp
gm_commands/itemsearch.cpp
gm_commands/kick.cpp
gm_commands/kill.cpp
gm_commands/killallnpcs.cpp
gm_commands/lastname.cpp
gm_commands/list.cpp
gm_commands/listpetition.cpp
gm_commands/loc.cpp
gm_commands/lock.cpp
gm_commands/logcommand.cpp
gm_commands/logs.cpp
gm_commands/makepet.cpp
gm_commands/mana.cpp
gm_commands/max_all_skills.cpp
gm_commands/memspell.cpp
gm_commands/merchantcloseshop.cpp
gm_commands/merchantopenshop.cpp
gm_commands/modifynpcstat.cpp
gm_commands/motd.cpp
gm_commands/movechar.cpp
gm_commands/movement.cpp
gm_commands/myskills.cpp
gm_commands/mysql.cpp
gm_commands/mystats.cpp
gm_commands/name.cpp
gm_commands/netstats.cpp
gm_commands/network.cpp
gm_commands/npccast.cpp
gm_commands/npcedit.cpp
gm_commands/npceditmass.cpp
gm_commands/npcemote.cpp
gm_commands/npcloot.cpp
gm_commands/npcsay.cpp
gm_commands/npcshout.cpp
gm_commands/npcspawn.cpp
gm_commands/npcspecialattk.cpp
gm_commands/npcstats.cpp
gm_commands/npctype_cache.cpp
gm_commands/npctypespawn.cpp
gm_commands/nudge.cpp
gm_commands/nukebuffs.cpp
gm_commands/nukeitem.cpp
gm_commands/object.cpp
gm_commands/oocmute.cpp
gm_commands/opcode.cpp
gm_commands/path.cpp
gm_commands/peekinv.cpp
gm_commands/peqzone.cpp
gm_commands/permaclass.cpp
gm_commands/permagender.cpp
gm_commands/permarace.cpp
gm_commands/petitioninfo.cpp
gm_commands/petname.cpp
gm_commands/pf.cpp
gm_commands/picklock.cpp
gm_commands/profanity.cpp
gm_commands/proximity.cpp
gm_commands/push.cpp
gm_commands/pvp.cpp
gm_commands/qglobal.cpp
gm_commands/questerrors.cpp
gm_commands/race.cpp
gm_commands/raidloot.cpp
gm_commands/randomfeatures.cpp
gm_commands/refreshgroup.cpp
gm_commands/reloadaa.cpp
gm_commands/reloadallrules.cpp
gm_commands/reloademote.cpp
gm_commands/reloadlevelmods.cpp
gm_commands/reloadmerchants.cpp
gm_commands/reloadperlexportsettings.cpp
gm_commands/reloadqst.cpp
gm_commands/reloadstatic.cpp
gm_commands/reloadtitles.cpp
gm_commands/reloadtraps.cpp
gm_commands/reloadworld.cpp
gm_commands/reloadworldrules.cpp
gm_commands/reloadzps.cpp
gm_commands/repop.cpp
gm_commands/resetaa.cpp
gm_commands/resetaa_timer.cpp
gm_commands/resetdisc_timer.cpp
gm_commands/revoke.cpp
gm_commands/roambox.cpp
gm_commands/rules.cpp
gm_commands/save.cpp
gm_commands/scale.cpp
gm_commands/scribespell.cpp
gm_commands/scribespells.cpp
gm_commands/sendzonespawns.cpp
gm_commands/sensetrap.cpp
gm_commands/serverinfo.cpp
gm_commands/serverrules.cpp
gm_commands/set_adventure_points.cpp
gm_commands/setaapts.cpp
gm_commands/setaaxp.cpp
gm_commands/setanim.cpp
gm_commands/setcrystals.cpp
gm_commands/setfaction.cpp
gm_commands/setgraveyard.cpp
gm_commands/setlanguage.cpp
gm_commands/setlsinfo.cpp
gm_commands/setpass.cpp
gm_commands/setpvppoints.cpp
gm_commands/setskill.cpp
gm_commands/setskillall.cpp
gm_commands/setstartzone.cpp
gm_commands/setstat.cpp
gm_commands/setxp.cpp
gm_commands/showbonusstats.cpp
gm_commands/showbuffs.cpp
gm_commands/shownpcgloballoot.cpp
gm_commands/shownumhits.cpp
gm_commands/showskills.cpp
gm_commands/showspellslist.cpp
gm_commands/showstats.cpp
gm_commands/showzonegloballoot.cpp
gm_commands/showzonepoints.cpp
gm_commands/shutdown.cpp
gm_commands/size.cpp
gm_commands/spawn.cpp
gm_commands/spawnfix.cpp
gm_commands/spawnstatus.cpp
gm_commands/spellinfo.cpp
gm_commands/stun.cpp
gm_commands/summon.cpp
gm_commands/summonburiedplayercorpse.cpp
gm_commands/summonitem.cpp
gm_commands/suspend.cpp
gm_commands/task.cpp
gm_commands/tattoo.cpp
gm_commands/tempname.cpp
gm_commands/texture.cpp
gm_commands/time.cpp
gm_commands/timers.cpp
gm_commands/timezone.cpp
gm_commands/title.cpp
gm_commands/titlesuffix.cpp
gm_commands/traindisc.cpp
gm_commands/trapinfo.cpp
gm_commands/tune.cpp
gm_commands/ucs.cpp
gm_commands/undye.cpp
gm_commands/undyeme.cpp
gm_commands/unfreeze.cpp
gm_commands/unlock.cpp
gm_commands/unscribespell.cpp
gm_commands/unscribespells.cpp
gm_commands/untraindisc.cpp
gm_commands/untraindiscs.cpp
gm_commands/uptime.cpp
gm_commands/version.cpp
gm_commands/viewnpctype.cpp
gm_commands/viewpetition.cpp
gm_commands/viewzoneloot.cpp
gm_commands/wc.cpp
gm_commands/weather.cpp
gm_commands/who.cpp
gm_commands/worldshutdown.cpp
gm_commands/worldwide.cpp
gm_commands/wp.cpp
gm_commands/wpadd.cpp
gm_commands/wpinfo.cpp
gm_commands/xtargets.cpp
gm_commands/zclip.cpp
gm_commands/zcolor.cpp
gm_commands/zheader.cpp
gm_commands/zonebootup.cpp
gm_commands/zonelock.cpp
gm_commands/zoneshutdown.cpp
gm_commands/zonespawn.cpp
gm_commands/zonestatus.cpp
gm_commands/zopp.cpp
gm_commands/zsafecoords.cpp
gm_commands/zsave.cpp
gm_commands/zsky.cpp
gm_commands/zstats.cpp
gm_commands/zunderworld.cpp
gm_commands/zuwcoords.cpp
)
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers} ${gm_commands})
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,3 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMMAND_H #ifndef COMMAND_H
#define COMMAND_H #define COMMAND_H
@ -199,6 +180,8 @@ void command_nukeitem(Client *c, const Seperator *sep);
void command_object(Client *c, const Seperator *sep); void command_object(Client *c, const Seperator *sep);
void command_oocmute(Client *c, const Seperator *sep); void command_oocmute(Client *c, const Seperator *sep);
void command_opcode(Client *c, const Seperator *sep); void command_opcode(Client *c, const Seperator *sep);
void command_bestz(Client *c, const Seperator *message);
void command_pf(Client *c, const Seperator *message);
#ifdef PACKET_PROFILER #ifdef PACKET_PROFILER
void command_packetprofile(Client *c, const Seperator *sep); void command_packetprofile(Client *c, const Seperator *sep);

View File

@ -0,0 +1,11 @@
#include "../client.h"
void command_acceptrules(Client *c, const Seperator *sep)
{
if (!database.GetAgreementFlag(c->AccountID())) {
database.SetAgreementFlag(c->AccountID());
c->SendAppearancePacket(AT_Anim, ANIM_STAND);
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
}
}

534
zone/gm_commands/advnpcspawn.cpp Executable file
View File

@ -0,0 +1,534 @@
#include "../client.h"
#include "../groups.h"
void command_advnpcspawn(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (!arguments) {
c->Message(
Chat::White,
"Usage: #advnpcspawn addentry [Spawngroup ID] [NPC ID] [Spawn Chance] - Adds a new Spawngroup Entry"
);
c->Message(
Chat::White,
"Usage: #advnpcspawn addspawn [Spawngroup ID] - Adds a new Spawngroup Entry from an existing Spawngroup"
);
c->Message(Chat::White, "Usage: #advnpcspawn clearbox [Spawngroup ID] - Clears the roambox of a Spawngroup");
c->Message(Chat::White, "Usage: #advnpcspawn deletespawn - Deletes a Spawngroup");
c->Message(
Chat::White,
"Usage: #advnpcspawn editbox [Spawngroup ID] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay] - Edit the roambox of a Spawngroup"
);
c->Message(
Chat::White,
"Usage: #advnpcspawn editrespawn [Respawn Timer] [Variance] - Edit the Respawn Timer of a Spawngroup"
);
c->Message(
Chat::White,
"Usage: #advnpcspawn makegroup [Spawn Group Name] [Spawn Limit] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay] - Makes a new Spawngroup"
);
c->Message(Chat::White, "Usage: #advnpcspawn makenpc - Makes a new NPC");
c->Message(Chat::White, "Usage: #advnpcspawn movespawn - Moves a Spawngroup to your current location");
c->Message(Chat::White, "Usage: #advnpcspawn setversion [Version] - Sets a Spawngroup's Version");
return;
}
std::string spawn_command = str_tolower(sep->arg[1]);
bool is_add_entry = spawn_command.find("addentry") != std::string::npos;
bool is_add_spawn = spawn_command.find("addspawn") != std::string::npos;
bool is_clear_box = spawn_command.find("clearbox") != std::string::npos;
bool is_delete_spawn = spawn_command.find("deletespawn") != std::string::npos;
bool is_edit_box = spawn_command.find("editgroup") != std::string::npos;
bool is_edit_respawn = spawn_command.find("editrespawn") != std::string::npos;
bool is_make_group = spawn_command.find("makegroup") != std::string::npos;
bool is_make_npc = spawn_command.find("makenpc") != std::string::npos;
bool is_move_spawn = spawn_command.find("movespawn") != std::string::npos;
bool is_set_version = spawn_command.find("setversion") != std::string::npos;
if (
!is_add_entry &&
!is_add_spawn &&
!is_clear_box &&
!is_delete_spawn &&
!is_edit_box &&
!is_edit_respawn &&
!is_make_group &&
!is_make_npc &&
!is_move_spawn &&
!is_set_version
) {
c->Message(
Chat::White,
"Usage: #advnpcspawn addentry [Spawngroup ID] [NPC ID] [Spawn Chance] - Adds a new Spawngroup Entry"
);
c->Message(
Chat::White,
"Usage: #advnpcspawn addspawn [Spawngroup ID] - Adds a new Spawngroup Entry from an existing Spawngroup"
);
c->Message(Chat::White, "Usage: #advnpcspawn clearbox [Spawngroup ID] - Clears the roambox of a Spawngroup");
c->Message(Chat::White, "Usage: #advnpcspawn deletespawn - Deletes a Spawngroup");
c->Message(
Chat::White,
"Usage: #advnpcspawn editbox [Spawngroup ID] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay] - Edit the roambox of a Spawngroup"
);
c->Message(
Chat::White,
"Usage: #advnpcspawn editrespawn [Respawn Timer] [Variance] - Edit the Respawn Timer of a Spawngroup"
);
c->Message(
Chat::White,
"Usage: #advnpcspawn makegroup [Spawn Group Name] [Spawn Limit] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay] - Makes a new Spawngroup"
);
c->Message(Chat::White, "Usage: #advnpcspawn makenpc - Makes a new NPC");
c->Message(Chat::White, "Usage: #advnpcspawn movespawn - Moves a Spawngroup to your current location");
c->Message(Chat::White, "Usage: #advnpcspawn setversion [Version] - Sets a Spawngroup's Version");
return;
}
if (is_add_entry) {
if (arguments < 4) {
c->Message(Chat::White, "Usage: #advnpcspawn addentry [Spawngroup ID] [NPC ID] [Spawn Chance]");
return;
}
auto spawngroup_id = std::stoi(sep->arg[2]);
auto npc_id = std::stoi(sep->arg[2]);
auto spawn_chance = std::stoi(sep->arg[2]);
std::string query = fmt::format(
SQL(
INSERT INTO spawnentry(spawngroupID, npcID, chance)
VALUES({}, {}, {})
),
spawngroup_id,
npc_id,
spawn_chance
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to add entry to Spawngroup.");
return;
}
c->Message(
Chat::White,
fmt::format(
"{} ({}) added to Spawngroup {}, its spawn chance is {}%%.",
database.GetCleanNPCNameByID(npc_id),
npc_id,
spawngroup_id,
spawn_chance
).c_str()
);
return;
}
else if (is_add_spawn) {
content_db.NPCSpawnDB(
NPCSpawnTypes::AddSpawnFromSpawngroup,
zone->GetShortName(),
zone->GetInstanceVersion(),
c,
0,
std::stoi(sep->arg[2])
);
c->Message(
Chat::White,
fmt::format(
"Spawn Added | Added spawn from Spawngroup ID {}.",
std::stoi(sep->arg[2])
).c_str()
);
return;
}
else if (is_clear_box) {
if (arguments != 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #advnpcspawn clearbox [Spawngroup ID]");
return;
}
std::string query = fmt::format(
"UPDATE spawngroup SET dist = 0, min_x = 0, max_x = 0, min_y = 0, max_y = 0, delay = 0 WHERE id = {}",
std::stoi(sep->arg[2])
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to clear Spawngroup box.");
return;
}
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Roambox Cleared | Delay: 0 Distance: 0.00",
std::stoi(sep->arg[2])
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Roambox Cleared | Minimum X: 0.00 Maximum X: 0.00",
std::stoi(sep->arg[2])
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Roambox Cleared | Minimum Y: 0.00 Maximum Y: 0.00",
std::stoi(sep->arg[2])
).c_str()
);
return;
}
else if (is_delete_spawn) {
if (!c->GetTarget() || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "You must target an NPC to use this command.");
return;
}
NPC *target = c->GetTarget()->CastToNPC();
Spawn2 *spawn2 = target->respawn2;
if (!spawn2) {
c->Message(Chat::White, "Failed to delete spawn because NPC has no Spawn2.");
return;
}
auto spawn2_id = spawn2->GetID();
std::string query = fmt::format(
"DELETE FROM spawn2 WHERE id = {}",
spawn2_id
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to delete spawn.");
return;
}
c->Message(
Chat::White,
fmt::format(
"Spawn2 {} Deleted | Name: {} ({})",
spawn2_id,
target->GetCleanName(),
target->GetID()
).c_str()
);
target->Depop(false);
return;
}
else if (is_edit_box) {
if (
arguments != 8 ||
!sep->IsNumber(3) ||
!sep->IsNumber(4) ||
!sep->IsNumber(5) ||
!sep->IsNumber(6) ||
!sep->IsNumber(7) ||
!sep->IsNumber(8)
) {
c->Message(
Chat::White,
"Usage: #advnpcspawn editbox [Spawngroup ID] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay]"
);
return;
}
auto spawngroup_id = std::stoi(sep->arg[2]);
auto distance = std::stof(sep->arg[3]);
auto minimum_x = std::stof(sep->arg[4]);
auto maximum_x = std::stof(sep->arg[5]);
auto minimum_y = std::stof(sep->arg[6]);
auto maximum_y = std::stof(sep->arg[7]);
auto delay = std::stoi(sep->arg[8]);
std::string query = fmt::format(
"UPDATE spawngroup SET dist = {:.2f}, min_x = {:.2f}, max_x = {:.2f}, max_y = {:.2f}, min_y = {:.2f}, delay = {} WHERE id = {}",
distance,
minimum_x,
maximum_x,
minimum_y,
maximum_y,
delay,
spawngroup_id
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to edit Spawngroup box.");
return;
}
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Roambox Edited | Delay: {} Distance: {:.2f}",
spawngroup_id,
delay,
distance
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Roambox Edited | Minimum X: {:.2f} Maximum X: {:.2f}",
spawngroup_id,
minimum_x,
maximum_x
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Roambox Edited | Minimum Y: {:.2f} Maximum Y: {:.2f}",
spawngroup_id,
minimum_y,
maximum_y
).c_str()
);
return;
}
else if (is_edit_respawn) {
if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #advnpcspawn editrespawn [Respawn Timer] [Variance]");
return;
}
if (!c->GetTarget() || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "You must target an NPC to use this command.");
return;
}
NPC *target = c->GetTarget()->CastToNPC();
Spawn2 *spawn2 = target->respawn2;
if (!spawn2) {
c->Message(Chat::White, "Failed to edit respawn because NPC has no Spawn2.");
return;
}
auto spawn2_id = spawn2->GetID();
uint32 respawn_timer = std::stoi(sep->arg[2]);
uint32 variance = (
sep->IsNumber(3) ?
std::stoi(sep->arg[3]) :
spawn2->GetVariance()
);
std::string query = fmt::format(
"UPDATE spawn2 SET respawntime = {}, variance = {} WHERE id = {}",
respawn_timer,
variance,
spawn2_id
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to edit respawn.");
return;
}
c->Message(
Chat::White,
fmt::format(
"Spawn2 {} Respawn Modified | Name: {} ({}) Respawn Timer: {} Variance: {}",
spawn2_id,
target->GetCleanName(),
target->GetID(),
respawn_timer,
variance
).c_str()
);
spawn2->SetRespawnTimer(respawn_timer);
spawn2->SetVariance(variance);
return;
}
else if (is_make_group) {
if (
arguments != 9 ||
!sep->IsNumber(3) ||
!sep->IsNumber(4) ||
!sep->IsNumber(5) ||
!sep->IsNumber(6) ||
!sep->IsNumber(7) ||
!sep->IsNumber(8) ||
!sep->IsNumber(9)
) {
c->Message(
Chat::White,
"Usage: #advncspawn makegroup [Spawn Group Name] [Spawn Limit] [Distance] [Minimum X] [Maximum X] [Minimum Y] [Maximum Y] [Delay]"
);
return;
}
std::string spawngroup_name = sep->arg[2];
auto spawn_limit = std::stoi(sep->arg[3]);
auto distance = std::stof(sep->arg[4]);
auto minimum_x = std::stof(sep->arg[5]);
auto maximum_x = std::stof(sep->arg[6]);
auto minimum_y = std::stof(sep->arg[7]);
auto maximum_y = std::stof(sep->arg[8]);
auto delay = std::stoi(sep->arg[9]);
std::string query = fmt::format(
"INSERT INTO spawngroup"
"(name, spawn_limit, dist, min_x, max_x, min_y, max_y, delay)"
"VALUES ('{}', {}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {})",
spawngroup_name,
spawn_limit,
distance,
minimum_x,
maximum_x,
minimum_y,
maximum_y,
delay
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to make Spawngroup.");
return;
}
auto spawngroup_id = results.LastInsertedID();
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Created | Name: {} Spawn Limit: {}",
spawngroup_id,
spawngroup_name,
spawn_limit
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Created | Delay: {} Distance: {:.2f}",
spawngroup_id,
delay,
distance
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Created | Minimum X: {:.2f} Maximum X: {:.2f}",
spawngroup_id,
minimum_x,
maximum_x
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Created | Minimum Y: {:.2f} Maximum Y: {:.2f}",
spawngroup_id,
minimum_y,
maximum_y
).c_str()
);
return;
}
else if (is_make_npc) {
if (!c->GetTarget() || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "You must target an NPC to use this command.");
return;
}
NPC *target = c->GetTarget()->CastToNPC();
content_db.NPCSpawnDB(
NPCSpawnTypes::CreateNewNPC,
zone->GetShortName(),
zone->GetInstanceVersion(),
c,
target
);
return;
}
else if (is_move_spawn) {
if (!c->GetTarget() || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "You must target an NPC to use this command.");
return;
}
NPC *target = c->GetTarget()->CastToNPC();
Spawn2 *spawn2 = target->respawn2;
if (!spawn2) {
c->Message(Chat::White, "Failed to move spawn because NPC has no Spawn2.");
return;
}
auto client_position = c->GetPosition();
auto spawn2_id = spawn2->GetID();
std::string query = fmt::format(
"UPDATE spawn2 SET x = {:.2f}, y = {:.2f}, z = {:.2f}, heading = {:.2f} WHERE id = {}",
client_position.x,
client_position.y,
client_position.z,
client_position.w,
spawn2_id
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to move spawn.");
return;
}
c->Message(
Chat::White,
fmt::format(
"Spawn2 {} Moved | Name: {} ({})",
spawn2_id,
target->GetCleanName(),
target->GetID()
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Spawn2 {} Moved | XYZ: {}, {}, {} Heading: {}",
spawn2_id,
client_position.x,
client_position.y,
client_position.z,
client_position.w
).c_str()
);
target->GMMove(
client_position.x,
client_position.y,
client_position.z,
client_position.w
);
return;
}
else if (is_set_version) {
if (arguments != 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #advnpcspawn setversion [Version]");
return;
}
if (!c->GetTarget() || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "You must target an NPC to use this command.");
return;
}
NPC *target = c->GetTarget()->CastToNPC();
auto version = std::stoi(sep->arg[2]);
std::string query = fmt::format(
"UPDATE spawn2 SET version = {} WHERE spawngroupID = {}",
version,
target->GetSpawnGroupId()
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Failed to set version.");
return;
}
c->Message(
Chat::White,
fmt::format(
"Spawngroup {} Version Modified | Name: {} ({}) Version: {}",
target->GetSpawnGroupId(),
target->GetCleanName(),
target->GetID(),
version
).c_str()
);
target->Depop(false);
return;
}
}

21
zone/gm_commands/aggro.cpp Executable file
View File

@ -0,0 +1,21 @@
#include "../client.h"
void command_aggro(Client *c, const Seperator *sep)
{
if (c->GetTarget() == nullptr || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "Error: you must have an NPC target.");
return;
}
float d = atof(sep->arg[1]);
if (d == 0.0f) {
c->Message(Chat::Red, "Error: distance argument required.");
return;
}
bool verbose = false;
if (sep->arg[2][0] == '-' && sep->arg[2][1] == 'v' && sep->arg[2][2] == '\0') {
verbose = true;
}
entity_list.DescribeAggro(c, c->GetTarget()->CastToNPC(), d, verbose);
}

19
zone/gm_commands/aggrozone.cpp Executable file
View File

@ -0,0 +1,19 @@
#include "../client.h"
void command_aggrozone(Client *c, const Seperator *sep)
{
if (!c) {
return;
}
Mob *m = c->CastToMob();
if (!m) {
return;
}
uint32 hate = atoi(sep->arg[1]); //should default to 0 if we don't enter anything
entity_list.AggroZone(m, hate);
c->Message(Chat::White, "Train to you! Last chance to go invulnerable...");
}

139
zone/gm_commands/ai.cpp Executable file
View File

@ -0,0 +1,139 @@
#include "../client.h"
void command_ai(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (strcasecmp(sep->arg[1], "factionid") == 0) {
if (target && sep->IsNumber(2)) {
if (target->IsNPC()) {
target->CastToNPC()->SetNPCFactionID(atoi(sep->arg[2]));
}
else {
c->Message(Chat::White, "%s is not an NPC.", target->GetName());
}
}
else {
c->Message(Chat::White, "Usage: (targeted) #ai factionid [factionid]");
}
}
else if (strcasecmp(sep->arg[1], "spellslist") == 0) {
if (target && sep->IsNumber(2) && atoi(sep->arg[2]) >= 0) {
if (target->IsNPC()) {
target->CastToNPC()->AI_AddNPCSpells(atoi(sep->arg[2]));
}
else {
c->Message(Chat::White, "%s is not an NPC.", target->GetName());
}
}
else {
c->Message(Chat::White, "Usage: (targeted) #ai spellslist [npc_spells_id]");
}
}
else if (strcasecmp(sep->arg[1], "con") == 0) {
if (target && sep->arg[2][0] != 0) {
Mob *tar2 = entity_list.GetMob(sep->arg[2]);
if (tar2) {
c->Message(
Chat::White,
"%s considering %s: %i",
target->GetName(),
tar2->GetName(),
tar2->GetReverseFactionCon(target));
}
else {
c->Message(Chat::White, "Error: %s not found.", sep->arg[2]);
}
}
else {
c->Message(Chat::White, "Usage: (targeted) #ai con [mob name]");
}
}
else if (strcasecmp(sep->arg[1], "guard") == 0) {
if (target && target->IsNPC()) {
target->CastToNPC()->SaveGuardSpot(target->GetPosition());
}
else {
c->Message(
Chat::White,
"Usage: (targeted) #ai guard - sets npc to guard the current location (use #summon to move)"
);
}
}
else if (strcasecmp(sep->arg[1], "roambox") == 0) {
if (target && target->IsAIControlled() && target->IsNPC()) {
if ((sep->argnum == 6 || sep->argnum == 7 || sep->argnum == 8) && sep->IsNumber(2) && sep->IsNumber(3) &&
sep->IsNumber(4) && sep->IsNumber(5) && sep->IsNumber(6)) {
uint32 tmp = 2500;
uint32 tmp2 = 2500;
if (sep->IsNumber(7)) {
tmp = atoi(sep->arg[7]);
}
if (sep->IsNumber(8)) {
tmp2 = atoi(sep->arg[8]);
}
target->CastToNPC()->AI_SetRoambox(
atof(sep->arg[2]),
atof(sep->arg[3]),
atof(sep->arg[4]),
atof(sep->arg[5]),
atof(sep->arg[6]),
tmp,
tmp2
);
}
else if ((sep->argnum == 3 || sep->argnum == 4) && sep->IsNumber(2) && sep->IsNumber(3)) {
uint32 tmp = 2500;
uint32 tmp2 = 2500;
if (sep->IsNumber(4)) {
tmp = atoi(sep->arg[4]);
}
if (sep->IsNumber(5)) {
tmp2 = atoi(sep->arg[5]);
}
target->CastToNPC()->AI_SetRoambox(atof(sep->arg[2]), atof(sep->arg[3]), tmp, tmp2);
}
else {
c->Message(Chat::White, "Usage: #ai roambox dist max_x min_x max_y min_y [delay] [mindelay]");
c->Message(Chat::White, "Usage: #ai roambox dist roamdist [delay] [mindelay]");
}
}
else {
c->Message(Chat::White, "You need a AI NPC targeted");
}
}
else if (strcasecmp(sep->arg[1], "stop") == 0 && c->Admin() >= commandToggleAI) {
if (target) {
if (target->IsAIControlled()) {
target->AI_Stop();
}
else {
c->Message(Chat::White, "Error: Target is not AI controlled");
}
}
else {
c->Message(Chat::White, "Usage: Target a Mob with AI enabled and use this to turn off their AI.");
}
}
else if (strcasecmp(sep->arg[1], "start") == 0 && c->Admin() >= commandToggleAI) {
if (target) {
if (!target->IsAIControlled()) {
target->AI_Start();
}
else {
c->Message(Chat::White, "Error: Target is already AI controlled");
}
}
else {
c->Message(Chat::White, "Usage: Target a Mob with AI disabled and use this to turn on their AI.");
}
}
else {
c->Message(Chat::White, "#AI Sub-commands");
c->Message(Chat::White, " factionid");
c->Message(Chat::White, " spellslist");
c->Message(Chat::White, " con");
c->Message(Chat::White, " guard");
}
}

26
zone/gm_commands/appearance.cpp Executable file
View File

@ -0,0 +1,26 @@
#include "../client.h"
void command_appearance(Client *c, const Seperator *sep)
{
Mob *t = c->CastToMob();
// sends any appearance packet
// Dev debug command, for appearance types
if (sep->arg[2][0] == 0) {
c->Message(Chat::White, "Usage: #appearance type value");
}
else {
if ((c->GetTarget())) {
t = c->GetTarget();
}
t->SendAppearancePacket(atoi(sep->arg[1]), atoi(sep->arg[2]));
c->Message(
Chat::White,
"Sending appearance packet: target=%s, type=%s, value=%s",
t->GetName(),
sep->arg[1],
sep->arg[2]
);
}
}

18
zone/gm_commands/attack.cpp Executable file
View File

@ -0,0 +1,18 @@
#include "../client.h"
void command_attack(Client *c, const Seperator *sep)
{
if (c->GetTarget() && c->GetTarget()->IsNPC() && sep->arg[1] != 0) {
Mob *sictar = entity_list.GetMob(sep->argplus[1]);
if (sictar) {
c->GetTarget()->CastToNPC()->AddToHateList(sictar, 1, 0);
}
else {
c->Message(Chat::White, "Error: %s not found", sep->arg[1]);
}
}
else {
c->Message(Chat::White, "Usage: (needs NPC targeted) #attack targetname");
}
}

View File

@ -0,0 +1,18 @@
#include "../client.h"
#include "../object.h"
void command_augmentitem(Client *c, const Seperator *sep)
{
if (!c) {
return;
}
auto in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)];
in_augment->container_slot = 1000; // <watch>
in_augment->augment_slot = -1;
if (c->GetTradeskillObject() != nullptr) {
Object::HandleAugmentation(c, in_augment, c->GetTradeskillObject());
}
safe_delete_array(in_augment);
}

72
zone/gm_commands/ban.cpp Executable file
View File

@ -0,0 +1,72 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
void command_ban(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0 || sep->arg[2][0] == 0) {
c->Message(Chat::White, "Usage: #ban <charname> <message>");
return;
}
auto account_id = database.GetAccountIDByChar(sep->arg[1]);
std::string message;
int i = 2;
while (1) {
if (sep->arg[i][0] == 0) {
break;
}
if (message.length() > 0) {
message.push_back(' ');
}
message += sep->arg[i];
++i;
}
if (message.length() == 0) {
c->Message(Chat::White, "Usage: #ban <charname> <message>");
return;
}
if (account_id == 0) {
c->Message(Chat::Red, "Character does not exist.");
return;
}
std::string query = StringFormat(
"UPDATE account SET status = -2, ban_reason = '%s' "
"WHERE id = %i", EscapeString(message).c_str(), account_id
);
auto results = database.QueryDatabase(query);
c->Message(
Chat::Red,
"Account number %i with the character %s has been banned with message: \"%s\"",
account_id,
sep->arg[1],
message.c_str());
ServerPacket flagUpdatePack(ServerOP_FlagUpdate, 6);
*((uint32 *) &flagUpdatePack.pBuffer[0]) = account_id;
*((int16 *) &flagUpdatePack.pBuffer[4]) = -2;
worldserver.SendPacket(&flagUpdatePack);
Client *client = nullptr;
client = entity_list.GetClientByName(sep->arg[1]);
if (client) {
client->WorldKick();
return;
}
ServerPacket kickPlayerPack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct *skp = (ServerKickPlayer_Struct *) kickPlayerPack.pBuffer;
strcpy(skp->adminname, c->GetName());
strcpy(skp->name, sep->arg[1]);
skp->adminrank = c->Admin();
worldserver.SendPacket(&kickPlayerPack);
}

37
zone/gm_commands/beard.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_beard(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #beard [number of beard style]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = atoi(sep->arg[1]);
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Beard = %i", atoi(sep->arg[1]));
}
}

37
zone/gm_commands/beardcolor.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_beardcolor(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #beardcolor [number of beard color]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = atoi(sep->arg[1]);
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Beard Color = %i", atoi(sep->arg[1]));
}
}

89
zone/gm_commands/bestz.cpp Executable file
View File

@ -0,0 +1,89 @@
#include "../client.h"
#include "../water_map.h"
void command_bestz(Client *c, const Seperator *sep)
{
if (zone->zonemap == nullptr) {
c->Message(Chat::White, "Map not loaded for this zone");
}
else {
glm::vec3 me;
me.x = c->GetX();
me.y = c->GetY();
me.z = c->GetZ() + (c->GetSize() == 0.0 ? 6 : c->GetSize()) * HEAD_POSITION;
glm::vec3 hit;
glm::vec3 bme(me);
bme.z -= 500;
float best_z = zone->zonemap->FindBestZ(me, &hit);
if (best_z != BEST_Z_INVALID) {
c->Message(Chat::White, "Z is %.3f at (%.3f, %.3f).", best_z, me.x, me.y);
}
else {
c->Message(Chat::White, "Found no Z.");
}
}
if (zone->watermap == nullptr) {
c->Message(Chat::White, "Water Region Map not loaded for this zone");
}
else {
WaterRegionType RegionType;
float z;
if (c->GetTarget()) {
z = c->GetTarget()->GetZ();
auto position = glm::vec3(c->GetTarget()->GetX(), c->GetTarget()->GetY(), z);
RegionType = zone->watermap->ReturnRegionType(position);
c->Message(Chat::White, "InWater returns %d", zone->watermap->InWater(position));
c->Message(Chat::White, "InLava returns %d", zone->watermap->InLava(position));
}
else {
z = c->GetZ();
auto position = glm::vec3(c->GetX(), c->GetY(), z);
RegionType = zone->watermap->ReturnRegionType(position);
c->Message(Chat::White, "InWater returns %d", zone->watermap->InWater(position));
c->Message(Chat::White, "InLava returns %d", zone->watermap->InLava(position));
}
switch (RegionType) {
case RegionTypeNormal: {
c->Message(Chat::White, "There is nothing special about the region you are in!");
break;
}
case RegionTypeWater: {
c->Message(Chat::White, "You/your target are in Water.");
break;
}
case RegionTypeLava: {
c->Message(Chat::White, "You/your target are in Lava.");
break;
}
case RegionTypeVWater: {
c->Message(Chat::White, "You/your target are in VWater (Icy Water?).");
break;
}
case RegionTypePVP: {
c->Message(Chat::White, "You/your target are in a pvp enabled area.");
break;
}
case RegionTypeSlime: {
c->Message(Chat::White, "You/your target are in slime.");
break;
}
case RegionTypeIce: {
c->Message(Chat::White, "You/your target are in ice.");
break;
}
default:
c->Message(Chat::White, "You/your target are in an unknown region type.");
}
}
}

17
zone/gm_commands/bind.cpp Executable file
View File

@ -0,0 +1,17 @@
#include "../client.h"
void command_bind(Client *c, const Seperator *sep)
{
if (c->GetTarget() != 0) {
if (c->GetTarget()->IsClient()) {
c->GetTarget()->CastToClient()->SetBindPoint();
}
else {
c->Message(Chat::White, "Error: target not a Player");
}
}
else {
c->SetBindPoint();
}
}

View File

@ -0,0 +1,24 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
void command_camerashake(Client *c, const Seperator *sep)
{
if (c) {
if (sep->arg[1][0] && sep->arg[2][0]) {
auto pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct));
ServerCameraShake_Struct *scss = (ServerCameraShake_Struct *) pack->pBuffer;
scss->duration = atoi(sep->arg[1]);
scss->intensity = atoi(sep->arg[2]);
worldserver.SendPacket(pack);
c->Message(Chat::Red, "Successfully sent the packet to world! Shake it, world, shake it!");
safe_delete(pack);
}
else {
c->Message(Chat::Red, "Usage -- #camerashake [duration], [intensity [1-10])");
}
}
return;
}

77
zone/gm_commands/castspell.cpp Executable file
View File

@ -0,0 +1,77 @@
#include "../client.h"
void command_castspell(Client *c, const Seperator *sep)
{
if (SPDAT_RECORDS <= 0) {
c->Message(Chat::White, "Spells not loaded.");
return;
}
Mob *target = c;
if (c->GetTarget()) {
target = c->GetTarget();
}
if (!sep->IsNumber(1)) {
c->Message(
Chat::White,
"Usage: #castspell [Spell ID] [Instant (0 = False, 1 = True, Default is 1 if Unused)]"
);
}
else {
uint16 spell_id = std::stoul(sep->arg[1]);
if (CastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) {
c->Message(Chat::Red, "Unable to cast spell.");
}
else if (spell_id >= SPDAT_RECORDS) {
c->Message(Chat::White, "Invalid Spell ID.");
}
else {
bool instant_cast = (c->Admin() >= commandInstacast ? true : false);
if (instant_cast && sep->IsNumber(2)) {
instant_cast = std::stoi(sep->arg[2]) ? true : false;
c->Message(Chat::White, fmt::format("{}", std::stoi(sep->arg[2])).c_str());
}
if (c->Admin() >= commandInstacast && instant_cast) {
c->SpellFinished(
spell_id,
target,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty
);
}
else {
c->CastSpell(spell_id, target->GetID(), EQ::spells::CastingSlot::Item, spells[spell_id].cast_time);
}
if (c != target) {
c->Message(
Chat::White,
fmt::format(
"Cast {} ({}) on {}{}.",
GetSpellName(spell_id),
spell_id,
target->GetCleanName(),
instant_cast ? " instantly" : ""
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Cast {} ({}) on yourself{}.",
GetSpellName(spell_id),
spell_id,
instant_cast ? " instantly" : ""
).c_str()
);
}
}
}
}

15
zone/gm_commands/chat.cpp Executable file
View File

@ -0,0 +1,15 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
void command_chat(Client *c, const Seperator *sep)
{
if (sep->arg[2][0] == 0) {
c->Message(Chat::White, "Usage: #chat [channum] [message]");
}
else if (!worldserver.SendChannelMessage(0, 0, (uint8) atoi(sep->arg[1]), 0, 0, 100, sep->argplus[2])) {
c->Message(Chat::White, "Error: World server disconnected");
}
}

20
zone/gm_commands/checklos.cpp Executable file
View File

@ -0,0 +1,20 @@
#include "../client.h"
void command_checklos(Client *c, const Seperator *sep)
{
if (!c->GetTarget()) {
c->Message(Chat::White, "You must have a target to use this command.");
}
bool has_los = c->CheckLosFN(c->GetTarget());
c->Message(
Chat::White,
fmt::format(
"You {}have line of sight to {} ({}).",
has_los ? "" : "do not ",
c->GetTarget()->GetCleanName(),
c->GetTarget()->GetID()
).c_str()
);
}

View File

@ -0,0 +1,34 @@
#include "../client.h"
void command_copycharacter(Client *c, const Seperator *sep)
{
if (sep->argnum < 3) {
c->Message(
Chat::White,
"Usage: [source_character_name] [destination_character_name] [destination_account_name]"
);
return;
}
std::string source_character_name = sep->arg[1];
std::string destination_character_name = sep->arg[2];
std::string destination_account_name = sep->arg[3];
bool result = database.CopyCharacter(
source_character_name,
destination_character_name,
destination_account_name
);
c->Message(
Chat::Yellow,
fmt::format(
"Character Copy [{}] to [{}] via account [{}] [{}]",
source_character_name,
destination_character_name,
destination_account_name,
result ? "Success" : "Failed"
).c_str()
);
}

168
zone/gm_commands/corpse.cpp Executable file
View File

@ -0,0 +1,168 @@
#include "../client.h"
#include "../corpse.h"
void command_corpse(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (strcasecmp(sep->arg[1], "DeletePlayerCorpses") == 0 && c->Admin() >= commandEditPlayerCorpses) {
int32 tmp = entity_list.DeletePlayerCorpses();
if (tmp >= 0) {
c->Message(Chat::White, "%i corpses deleted.", tmp);
}
else {
c->Message(Chat::White, "DeletePlayerCorpses Error #%i", tmp);
}
}
else if (strcasecmp(sep->arg[1], "delete") == 0) {
if (target == 0 || !target->IsCorpse()) {
c->Message(Chat::White, "Error: Target the corpse you wish to delete");
}
else if (target->IsNPCCorpse()) {
c->Message(Chat::White, "Depoping %s.", target->GetName());
target->CastToCorpse()->Delete();
}
else if (c->Admin() >= commandEditPlayerCorpses) {
c->Message(Chat::White, "Deleting %s.", target->GetName());
target->CastToCorpse()->Delete();
}
else {
c->Message(Chat::White, "Insufficient status to delete player corpse.");
}
}
else if (strcasecmp(sep->arg[1], "ListNPC") == 0) {
entity_list.ListNPCCorpses(c);
}
else if (strcasecmp(sep->arg[1], "ListPlayer") == 0) {
entity_list.ListPlayerCorpses(c);
}
else if (strcasecmp(sep->arg[1], "DeleteNPCCorpses") == 0) {
int32 tmp = entity_list.DeleteNPCCorpses();
if (tmp >= 0) {
c->Message(Chat::White, "%d corpses deleted.", tmp);
}
else {
c->Message(Chat::White, "DeletePlayerCorpses Error #%d", tmp);
}
}
else if (strcasecmp(sep->arg[1], "charid") == 0 && c->Admin() >= commandEditPlayerCorpses) {
if (target == 0 || !target->IsPlayerCorpse()) {
c->Message(Chat::White, "Error: Target must be a player corpse.");
}
else if (!sep->IsNumber(2)) {
c->Message(Chat::White, "Error: charid must be a number.");
}
else {
c->Message(
Chat::White,
"Setting CharID=%u on PlayerCorpse '%s'",
target->CastToCorpse()->SetCharID(atoi(sep->arg[2])),
target->GetName());
}
}
else if (strcasecmp(sep->arg[1], "ResetLooter") == 0) {
if (target == 0 || !target->IsCorpse()) {
c->Message(Chat::White, "Error: Target the corpse you wish to reset");
}
else {
target->CastToCorpse()->ResetLooter();
}
}
else if (strcasecmp(sep->arg[1], "RemoveCash") == 0) {
if (target == 0 || !target->IsCorpse()) {
c->Message(Chat::White, "Error: Target the corpse you wish to remove the cash from");
}
else if (!target->IsPlayerCorpse() || c->Admin() >= commandEditPlayerCorpses) {
c->Message(Chat::White, "Removing Cash from %s.", target->GetName());
target->CastToCorpse()->RemoveCash();
}
else {
c->Message(Chat::White, "Insufficient status to modify player corpse.");
}
}
else if (strcasecmp(sep->arg[1], "InspectLoot") == 0) {
if (target == 0 || !target->IsCorpse()) {
c->Message(Chat::White, "Error: Target must be a corpse.");
}
else {
target->CastToCorpse()->QueryLoot(c);
}
}
else if (strcasecmp(sep->arg[1], "lock") == 0) {
if (target == 0 || !target->IsCorpse()) {
c->Message(Chat::White, "Error: Target must be a corpse.");
}
else {
target->CastToCorpse()->Lock();
c->Message(Chat::White, "Locking %s...", target->GetName());
}
}
else if (strcasecmp(sep->arg[1], "unlock") == 0) {
if (target == 0 || !target->IsCorpse()) {
c->Message(Chat::White, "Error: Target must be a corpse.");
}
else {
target->CastToCorpse()->UnLock();
c->Message(Chat::White, "Unlocking %s...", target->GetName());
}
}
else if (strcasecmp(sep->arg[1], "depop") == 0) {
if (target == 0 || !target->IsPlayerCorpse()) {
c->Message(Chat::White, "Error: Target must be a player corpse.");
}
else if (c->Admin() >= commandEditPlayerCorpses && target->IsPlayerCorpse()) {
c->Message(Chat::White, "Depoping %s.", target->GetName());
target->CastToCorpse()->DepopPlayerCorpse();
if (!sep->arg[2][0] || atoi(sep->arg[2]) != 0) {
target->CastToCorpse()->Bury();
}
}
else {
c->Message(Chat::White, "Insufficient status to depop player corpse.");
}
}
else if (strcasecmp(sep->arg[1], "depopall") == 0) {
if (target == 0 || !target->IsClient()) {
c->Message(Chat::White, "Error: Target must be a player.");
}
else if (c->Admin() >= commandEditPlayerCorpses && target->IsClient()) {
c->Message(Chat::White, "Depoping %s\'s corpses.", target->GetName());
target->CastToClient()->DepopAllCorpses();
if (!sep->arg[2][0] || atoi(sep->arg[2]) != 0) {
target->CastToClient()->BuryPlayerCorpses();
}
}
else {
c->Message(Chat::White, "Insufficient status to depop player corpse.");
}
}
else if (strcasecmp(sep->arg[1], "moveallgraveyard") == 0) {
int count = entity_list.MovePlayerCorpsesToGraveyard(true);
c->Message(Chat::White, "Moved [%d] player corpse(s) to zone graveyard", count);
}
else if (sep->arg[1][0] == 0 || strcasecmp(sep->arg[1], "help") == 0) {
c->Message(Chat::White, "#Corpse Sub-Commands:");
c->Message(Chat::White, " DeleteNPCCorpses");
c->Message(Chat::White, " Delete - Delete targetted corpse");
c->Message(Chat::White, " ListNPC");
c->Message(Chat::White, " ListPlayer");
c->Message(Chat::White, " Lock - GM locks the corpse - cannot be looted by non-GM");
c->Message(Chat::White, " MoveAllGraveyard - move all player corpses to zone's graveyard or non-instance");
c->Message(Chat::White, " UnLock");
c->Message(Chat::White, " RemoveCash");
c->Message(Chat::White, " InspectLoot");
c->Message(Chat::White, " [to remove items from corpses, loot them]");
c->Message(Chat::White, "Lead-GM status required to delete/modify player corpses");
c->Message(Chat::White, " DeletePlayerCorpses");
c->Message(Chat::White, " CharID [charid] - change player corpse's owner");
c->Message(Chat::White, " Depop [bury] - Depops single target corpse.");
c->Message(Chat::White, " Depopall [bury] - Depops all target player's corpses.");
c->Message(Chat::White, "Set bury to 0 to skip burying the corpses.");
}
else {
c->Message(Chat::White, "Error, #corpse sub-command not found");
}
}

8
zone/gm_commands/corpsefix.cpp Executable file
View File

@ -0,0 +1,8 @@
#include "../client.h"
#include "../corpse.h"
void command_corpsefix(Client *c, const Seperator *sep)
{
entity_list.CorpseFix(c);
}

17
zone/gm_commands/cvs.cpp Executable file
View File

@ -0,0 +1,17 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
void command_cvs(Client *c, const Seperator *sep)
{
auto pack = new ServerPacket(
ServerOP_ClientVersionSummary,
sizeof(ServerRequestClientVersionSummary_Struct)
);
auto srcvss = (ServerRequestClientVersionSummary_Struct *) pack->pBuffer;
strn0cpy(srcvss->Name, c->GetName(), sizeof(srcvss->Name));
worldserver.SendPacket(pack);
safe_delete(pack);
}

21
zone/gm_commands/damage.cpp Executable file
View File

@ -0,0 +1,21 @@
#include "../client.h"
void command_damage(Client *c, const Seperator *sep)
{
if (c->GetTarget() == 0) {
c->Message(Chat::White, "Error: #Damage: No Target.");
}
else if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #damage x");
}
else {
int32 nkdmg = atoi(sep->arg[1]);
if (nkdmg > 2100000000) {
c->Message(Chat::White, "Enter a value less then 2,100,000,000.");
}
else {
c->GetTarget()->Damage(c, nkdmg, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand, false);
}
}
}

View File

@ -0,0 +1,92 @@
#include "../client.h"
#include "../data_bucket.h"
void command_databuckets(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0) {
c->Message(Chat::Yellow, "Usage: #databuckets view (partial key)|(limit) OR #databuckets delete (key)");
return;
}
if (strcasecmp(sep->arg[1], "view") == 0) {
std::string key_filter;
uint8 limit = 50;
for (int i = 2; i < 4; i++) {
if (sep->arg[i][0] == '\0') {
break;
}
if (strcasecmp(sep->arg[i], "limit") == 0) {
limit = (uint8) atoi(sep->arg[i + 1]);
continue;
}
}
if (sep->arg[2]) {
key_filter = str_tolower(sep->arg[2]);
}
std::string query = "SELECT `id`, `key`, `value`, `expires` FROM data_buckets";
if (!key_filter.empty()) { query += StringFormat(" WHERE `key` LIKE '%%%s%%'", key_filter.c_str()); }
query += StringFormat(" LIMIT %u", limit);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() == 0) {
c->Message(Chat::Yellow, "No data_buckets found");
return;
}
int _ctr = 0;
// put in window for easier readability in case want command line for something else
std::string window_title = "Data Buckets";
std::string window_text =
"<table>"
"<tr>"
"<td>ID</td>"
"<td>Expires</td>"
"<td>Key</td>"
"<td>Value</td>"
"</tr>";
for (auto row = results.begin(); row != results.end(); ++row) {
auto id = static_cast<uint32>(atoi(row[0]));
std::string key = row[1];
std::string value = row[2];
std::string expires = row[3];
window_text.append(
StringFormat(
"<tr>"
"<td>%u</td>"
"<td>%s</td>"
"<td>%s</td>"
"<td>%s</td>"
"</tr>",
id,
expires.c_str(),
key.c_str(),
value.c_str()
));
_ctr++;
std::string del_saylink = StringFormat("#databuckets delete %s", key.c_str());
c->Message(
Chat::White,
"%s : %s",
EQ::SayLinkEngine::GenerateQuestSaylink(del_saylink, false, "Delete").c_str(),
key.c_str(),
" Value: ",
value.c_str());
}
window_text.append("</table>");
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
std::string response = _ctr > 0 ? StringFormat("Found %i matching data buckets", _ctr).c_str()
: "No Databuckets found.";
c->Message(Chat::Yellow, response.c_str());
}
else if (strcasecmp(sep->arg[1], "delete") == 0) {
if (DataBucket::DeleteData(sep->argplus[2])) {
c->Message(Chat::Yellow, "data bucket %s deleted.", sep->argplus[2]);
}
else {
c->Message(Chat::Red, "An error occurred deleting data bucket %s", sep->argplus[2]);
}
return;
}
}

29
zone/gm_commands/date.cpp Executable file
View File

@ -0,0 +1,29 @@
#include "../client.h"
void command_date(Client *c, const Seperator *sep)
{
//yyyy mm dd hh mm local
if (sep->arg[3][0] == 0 || !sep->IsNumber(1) || !sep->IsNumber(2) || !sep->IsNumber(3)) {
c->Message(Chat::Red, "Usage: #date yyyy mm dd [HH MM]");
}
else {
int h = 0, m = 0;
TimeOfDay_Struct eqTime;
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime);
if (!sep->IsNumber(4)) {
h = eqTime.hour;
}
else {
h = atoi(sep->arg[4]);
}
if (!sep->IsNumber(5)) {
m = eqTime.minute;
}
else {
m = atoi(sep->arg[5]);
}
c->Message(Chat::Red, "Setting world time to %s-%s-%s %i:%i...", sep->arg[1], sep->arg[2], sep->arg[3], h, m);
zone->SetDate(atoi(sep->arg[1]), atoi(sep->arg[2]), atoi(sep->arg[3]), h, m);
}
}

31
zone/gm_commands/dbspawn2.cpp Executable file
View File

@ -0,0 +1,31 @@
#include "../client.h"
void command_dbspawn2(Client *c, const Seperator *sep)
{
if (sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)) {
LogInfo("Spawning database spawn");
uint16 cond = 0;
int16 cond_min = 0;
if (sep->IsNumber(4)) {
cond = atoi(sep->arg[4]);
if (sep->IsNumber(5)) {
cond_min = atoi(sep->arg[5]);
}
}
database.CreateSpawn2(
c,
atoi(sep->arg[1]),
zone->GetShortName(),
c->GetPosition(),
atoi(sep->arg[2]),
atoi(sep->arg[3]),
cond,
cond_min
);
}
else {
c->Message(Chat::White, "Usage: #dbspawn2 spawngroup respawn variance [condition_id] [condition_min]");
}
}

21
zone/gm_commands/delacct.cpp Executable file
View File

@ -0,0 +1,21 @@
#include "../client.h"
void command_delacct(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0) {
c->Message(Chat::White, "Format: #delacct accountname");
}
else {
std::string user;
std::string loginserver;
ParseAccountString(sep->arg[1], user, loginserver);
if (database.DeleteAccount(user.c_str(), loginserver.c_str())) {
c->Message(Chat::White, "The account was deleted.");
}
else {
c->Message(Chat::White, "Unable to delete account.");
}
}
}

View File

@ -0,0 +1,35 @@
#include "../client.h"
void command_deletegraveyard(Client *c, const Seperator *sep)
{
uint32 zoneid = 0;
uint32 graveyard_id = 0;
if (!sep->arg[1][0]) {
c->Message(Chat::White, "Usage: #deletegraveyard [zonename]");
return;
}
zoneid = ZoneID(sep->arg[1]);
graveyard_id = content_db.GetZoneGraveyardID(zoneid, 0);
if (zoneid > 0 && graveyard_id > 0) {
if (content_db.DeleteGraveyard(zoneid, graveyard_id)) {
c->Message(Chat::White, "Successfuly deleted graveyard %u for zone %s.", graveyard_id, sep->arg[1]);
}
else {
c->Message(Chat::White, "Unable to delete graveyard %u for zone %s.", graveyard_id, sep->arg[1]);
}
}
else {
if (zoneid <= 0) {
c->Message(Chat::White, "Unable to retrieve a ZoneID for the zone: %s", sep->arg[1]);
}
else if (graveyard_id <= 0) {
c->Message(Chat::White, "Unable to retrieve a valid GraveyardID for the zone: %s", sep->arg[1]);
}
}
return;
}

View File

@ -0,0 +1,20 @@
#include "../client.h"
void command_delpetition(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0 || strcasecmp(sep->arg[1], "*") == 0) {
c->Message(Chat::White, "Usage: #delpetition (petition number) Type #listpetition for a list");
return;
}
c->Message(Chat::Red, "Attempting to delete petition number: %i", atoi(sep->argplus[1]));
std::string query = StringFormat("DELETE FROM petitions WHERE petid = %i", atoi(sep->argplus[1]));
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
LogInfo("Delete petition request from [{}], petition number:", c->GetName(), atoi(sep->argplus[1]));
}

14
zone/gm_commands/depop.cpp Executable file
View File

@ -0,0 +1,14 @@
#include "../client.h"
#include "../corpse.h"
void command_depop(Client *c, const Seperator *sep)
{
if (c->GetTarget() == 0 || !(c->GetTarget()->IsNPC() || c->GetTarget()->IsNPCCorpse())) {
c->Message(Chat::White, "You must have a NPC target for this command. (maybe you meant #depopzone?)");
}
else {
c->Message(Chat::White, "Depoping '%s'.", c->GetTarget()->GetName());
c->GetTarget()->Depop();
}
}

8
zone/gm_commands/depopzone.cpp Executable file
View File

@ -0,0 +1,8 @@
#include "../client.h"
void command_depopzone(Client *c, const Seperator *sep)
{
zone->Depop();
c->Message(Chat::White, "Zone depoped.");
}

37
zone/gm_commands/details.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_details(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #details [number of drakkin detail]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = atoi(sep->arg[1]);
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Details = %i", atoi(sep->arg[1]));
}
}

22
zone/gm_commands/devtools.cpp Executable file
View File

@ -0,0 +1,22 @@
#include "../client.h"
#include "../data_bucket.h"
void command_devtools(Client *c, const Seperator *sep)
{
std::string dev_tools_key = StringFormat("%i-dev-tools-disabled", c->AccountID());
/**
* Handle window toggle
*/
if (strcasecmp(sep->arg[1], "disable") == 0) {
DataBucket::SetData(dev_tools_key, "true");
c->SetDevToolsEnabled(false);
}
if (strcasecmp(sep->arg[1], "enable") == 0) {
DataBucket::DeleteData(dev_tools_key);
c->SetDevToolsEnabled(true);
}
c->ShowDevToolsMenu();
}

View File

@ -0,0 +1,29 @@
#include "../client.h"
void command_disablerecipe(Client *c, const Seperator *sep)
{
uint32 recipe_id = 0;
bool success = false;
if (c) {
if (sep->argnum == 1) {
recipe_id = atoi(sep->arg[1]);
}
else {
c->Message(Chat::White, "Invalid number of arguments.\nUsage: #disablerecipe recipe_id");
return;
}
if (recipe_id > 0) {
success = content_db.DisableRecipe(recipe_id);
if (success) {
c->Message(Chat::White, "Recipe disabled.");
}
else {
c->Message(Chat::White, "Recipe not disabled.");
}
}
else {
c->Message(Chat::White, "Invalid recipe id.\nUsage: #disablerecipe recipe_id");
}
}
}

25
zone/gm_commands/disarmtrap.cpp Executable file
View File

@ -0,0 +1,25 @@
#include "../client.h"
void command_disarmtrap(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!target) {
c->Message(Chat::Red, "You must have a target.");
return;
}
if (target->IsNPC()) {
if (c->HasSkill(EQ::skills::SkillDisarmTraps)) {
if (DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
c->Message(Chat::Red, "%s is too far away.", target->GetCleanName());
return;
}
c->HandleLDoNDisarm(target->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
}
else {
c->Message(Chat::Red, "You do not have the disarm trap skill.");
}
}
}

23
zone/gm_commands/distance.cpp Executable file
View File

@ -0,0 +1,23 @@
#include "../client.h"
void command_distance(Client *c, const Seperator *sep)
{
if (c->GetTarget()) {
Mob *target = c->GetTarget();
if (c != target) {
c->Message(
Chat::White,
fmt::format(
"{} ({}) is {:.2f} units from you.",
target->GetCleanName(),
target->GetID(),
Distance(
c->GetPosition(),
target->GetPosition()
)
).c_str()
);
}
}
}

20
zone/gm_commands/doanim.cpp Executable file
View File

@ -0,0 +1,20 @@
#include "../client.h"
void command_doanim(Client *c, const Seperator *sep)
{
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #DoAnim [number]");
}
else if (c->Admin() >= commandDoAnimOthers) {
if (c->GetTarget() == 0) {
c->Message(Chat::White, "Error: You need a target.");
}
else {
c->GetTarget()->DoAnim(atoi(sep->arg[1]), atoi(sep->arg[2]));
}
}
else {
c->DoAnim(atoi(sep->arg[1]), atoi(sep->arg[2]));
}
}

9
zone/gm_commands/door.cpp Executable file
View File

@ -0,0 +1,9 @@
#include "../client.h"
#include "door_manipulation.h"
#include "../doors.h"
void command_door(Client *c, const Seperator *sep)
{
DoorManipulation::CommandHandler(c, sep);
}

View File

@ -37,7 +37,10 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
// option // option
if (arg1.empty()) { if (arg1.empty()) {
DoorManipulation::CommandHeader(c); DoorManipulation::CommandHeader(c);
c->Message(Chat::White, "#door create <modelname> | Creates a door from a model. (Example IT78 creates a campfire)"); c->Message(
Chat::White,
"#door create <modelname> | Creates a door from a model. (Example IT78 creates a campfire)"
);
c->Message(Chat::White, "#door setinvertstate [0|1] | Sets selected door invert state"); c->Message(Chat::White, "#door setinvertstate [0|1] | Sets selected door invert state");
c->Message(Chat::White, "#door setincline <incline> | Sets selected door incline"); c->Message(Chat::White, "#door setincline <incline> | Sets selected door incline");
c->Message(Chat::White, "#door opentype <opentype> | Sets selected door opentype"); c->Message(Chat::White, "#door opentype <opentype> | Sets selected door opentype");

87
zone/gm_commands/dye.cpp Executable file
View File

@ -0,0 +1,87 @@
#include "../client.h"
void command_dye(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #dye help | #dye [slot] [red] [green] [blue] [use_tint]");
return;
}
uint8 slot = 0;
uint8 red = 255;
uint8 green = 255;
uint8 blue = 255;
uint8 use_tint = 255;
std::vector<std::string> dye_slots = {
"Helmet",
"Chest",
"Arms",
"Wrist",
"Hands",
"Legs",
"Feet"
};
if (arguments == 1 && !strcasecmp(sep->arg[1], "help")) {
int slot_id = 0;
std::vector<std::string> slot_messages;
c->Message(Chat::White, "Command Syntax: #dye help | #dye [slot] [red] [green] [blue] [use_tint]");
c->Message(Chat::White, "Red, Green, and Blue go from 0 to 255.");
for (const auto &slot : dye_slots) {
slot_messages.push_back(fmt::format("({}) {}", slot_id, slot));
slot_id++;
}
c->Message(
Chat::White,
fmt::format(
"{} {}",
"Slots are as follows:",
implode(", ", slot_messages)
).c_str()
);
return;
}
if (arguments >= 1 && sep->IsNumber(1)) {
slot = atoi(sep->arg[1]);
}
if (arguments >= 2 && sep->IsNumber(2)) {
red = atoi(sep->arg[2]);
}
if (arguments >= 3 && sep->IsNumber(3)) {
green = atoi(sep->arg[3]);
}
if (arguments >= 4 && sep->IsNumber(4)) {
blue = atoi(sep->arg[4]);
}
if (arguments >= 5 && sep->IsNumber(5)) {
use_tint = atoi(sep->arg[5]);
}
if (RuleB(Command, DyeCommandRequiresDyes)) {
uint32 dye_item_id = 32557;
if (c->CountItem(dye_item_id) >= 1) {
c->RemoveItem(dye_item_id);
}
else {
EQ::SayLinkEngine linker;
linker.SetLinkType(EQ::saylink::SayLinkItemData);
const EQ::ItemData *dye_item = database.GetItem(dye_item_id);
linker.SetItemData(dye_item);
c->Message(Chat::White, fmt::format("This command requires a {} to use.", linker.GenerateLink()).c_str());
return;
}
}
c->DyeArmorBySlot(slot, red, green, blue, use_tint);
}

244
zone/gm_commands/dz.cpp Executable file
View File

@ -0,0 +1,244 @@
#include "../client.h"
#include "../expedition.h"
void command_dz(Client *c, const Seperator *sep)
{
if (!c || !zone) {
return;
}
if (strcasecmp(sep->arg[1], "cache") == 0) {
if (strcasecmp(sep->arg[2], "reload") == 0) {
DynamicZone::CacheAllFromDatabase();
Expedition::CacheAllFromDatabase();
c->Message(
Chat::White, fmt::format(
"Reloaded [{}] dynamic zone(s) and [{}] expedition(s) from database",
zone->dynamic_zone_cache.size(), zone->expedition_cache.size()
).c_str());
}
}
else if (strcasecmp(sep->arg[1], "expedition") == 0) {
if (strcasecmp(sep->arg[2], "list") == 0) {
std::vector<Expedition *> expeditions;
for (const auto &expedition : zone->expedition_cache) {
expeditions.emplace_back(expedition.second.get());
}
std::sort(
expeditions.begin(), expeditions.end(),
[](const Expedition *lhs, const Expedition *rhs) {
return lhs->GetID() < rhs->GetID();
}
);
c->Message(Chat::White, fmt::format("Total Active Expeditions: [{}]", expeditions.size()).c_str());
for (const auto &expedition : expeditions) {
auto dz = expedition->GetDynamicZone();
if (!dz) {
LogExpeditions("Expedition [{}] has an invalid dz [{}] in cache",
expedition->GetID(),
expedition->GetDynamicZoneID());
continue;
}
auto leader_saylink = EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format(
"#goto {}", expedition->GetLeaderName()), false, expedition->GetLeaderName());
auto zone_saylink = EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format(
"#zoneinstance {}", dz->GetInstanceID()), false, "zone"
);
auto seconds = dz->GetSecondsRemaining();
c->Message(
Chat::White, fmt::format(
"expedition id: [{}] dz id: [{}] name: [{}] leader: [{}] {}: [{}]:[{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
expedition->GetID(),
expedition->GetDynamicZoneID(),
expedition->GetName(),
leader_saylink,
zone_saylink,
ZoneName(dz->GetZoneID()),
dz->GetZoneID(),
dz->GetInstanceID(),
dz->GetZoneVersion(),
dz->GetMemberCount(),
seconds / 3600, // hours
(seconds / 60) % 60, // minutes
seconds % 60 // seconds
).c_str());
}
}
else if (strcasecmp(sep->arg[2], "reload") == 0) {
Expedition::CacheAllFromDatabase();
c->Message(
Chat::White, fmt::format(
"Reloaded [{}] expeditions to cache from database.", zone->expedition_cache.size()
).c_str());
}
else if (strcasecmp(sep->arg[2], "destroy") == 0 && sep->IsNumber(3)) {
auto expedition_id = std::strtoul(sep->arg[3], nullptr, 10);
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
if (expedition) {
c->Message(
Chat::White, fmt::format(
"Destroying expedition [{}] ({})",
expedition_id, expedition->GetName()).c_str());
expedition->GetDynamicZone()->RemoveAllMembers();
}
else {
c->Message(Chat::Red, fmt::format("Failed to destroy expedition [{}]", sep->arg[3]).c_str());
}
}
else if (strcasecmp(sep->arg[2], "unlock") == 0 && sep->IsNumber(3)) {
auto expedition_id = std::strtoul(sep->arg[3], nullptr, 10);
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
if (expedition) {
c->Message(Chat::White, fmt::format("Unlocking expedition [{}]", expedition_id).c_str());
expedition->SetLocked(false, ExpeditionLockMessage::None, true);
}
else {
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", sep->arg[3]).c_str());
}
}
}
else if (strcasecmp(sep->arg[1], "list") == 0) {
c->Message(
Chat::White,
fmt::format("Total Dynamic Zones (cache): [{}]", zone->dynamic_zone_cache.size()).c_str());
std::vector<DynamicZone *> dynamic_zones;
for (const auto &dz : zone->dynamic_zone_cache) {
dynamic_zones.emplace_back(dz.second.get());
}
std::sort(
dynamic_zones.begin(), dynamic_zones.end(),
[](const DynamicZone *lhs, const DynamicZone *rhs) {
return lhs->GetID() < rhs->GetID();
}
);
for (const auto &dz : dynamic_zones) {
auto seconds = dz->GetSecondsRemaining();
auto zone_saylink = EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format("#zoneinstance {}", dz->GetInstanceID()), false, "zone"
);
std::string aligned_type = fmt::format(
"[{}]",
DynamicZone::GetDynamicZoneTypeName(static_cast<DynamicZoneType>(dz->GetType())));
c->Message(
Chat::White, fmt::format(
"id: [{}] type: {:>10} {}: [{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
dz->GetID(),
aligned_type,
zone_saylink,
dz->GetZoneID(),
dz->GetInstanceID(),
dz->GetZoneVersion(),
dz->GetMemberCount(),
seconds / 3600, // hours
(seconds / 60) % 60, // minutes
seconds % 60 // seconds
).c_str());
}
}
else if (strcasecmp(sep->arg[1], "listdb") == 0) {
auto dz_list = DynamicZonesRepository::AllDzInstancePlayerCounts(database);
c->Message(Chat::White, fmt::format("Total Dynamic Zones (database): [{}]", dz_list.size()).c_str());
auto now = std::chrono::system_clock::now();
for (const auto &dz : dz_list) {
auto expire_time = std::chrono::system_clock::from_time_t(dz.start_time + dz.duration);
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(expire_time - now);
auto seconds = std::max(0, static_cast<int>(remaining.count()));
bool is_expired = now > expire_time;
if (!is_expired || strcasecmp(sep->arg[2], "all") == 0) {
auto zone_saylink = is_expired ? "zone" : EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format("#zoneinstance {}", dz.instance), false, "zone"
);
c->Message(
Chat::White, fmt::format(
"id: [{}] type: [{}] {}: [{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
dz.id,
DynamicZone::GetDynamicZoneTypeName(static_cast<DynamicZoneType>(dz.type)),
zone_saylink,
dz.zone,
dz.instance,
dz.version,
dz.member_count,
seconds / 3600, // hours
(seconds / 60) % 60, // minutes
seconds % 60 // seconds
).c_str());
}
}
}
else if (strcasecmp(sep->arg[1], "lockouts") == 0) {
if (strcasecmp(sep->arg[2], "remove") == 0 && sep->arg[3][0] != '\0') {
if (sep->arg[5][0] == '\0') {
c->Message(
Chat::White, fmt::format(
"Removing [{}] lockouts on [{}].", sep->arg[4][0] ? sep->arg[4] : "all", sep->arg[3]
).c_str());
}
else {
c->Message(
Chat::White, fmt::format(
"Removing [{}]:[{}] lockout on [{}].", sep->arg[4], sep->arg[5], sep->arg[3]
).c_str());
}
Expedition::RemoveLockoutsByCharacterName(sep->arg[3], sep->arg[4], sep->arg[5]);
}
}
else if (strcasecmp(sep->arg[1], "makeleader") == 0 && sep->IsNumber(2) && sep->arg[3][0] != '\0') {
auto expedition_id = std::strtoul(sep->arg[2], nullptr, 10);
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
if (expedition) {
auto char_name = FormatName(sep->arg[3]);
c->Message(
Chat::White,
fmt::format("Setting expedition [{}] leader to [{}]", expedition_id, char_name).c_str());
expedition->SendWorldMakeLeaderRequest(c->CharacterID(), char_name);
}
else {
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", expedition_id).c_str());
}
}
else {
c->Message(Chat::White, "#dz usage:");
c->Message(
Chat::White,
"#dz cache reload - reload the current zone cache from db (also reloads expedition cache dependency)"
);
c->Message(Chat::White, "#dz expedition list - list expeditions in current zone cache");
c->Message(Chat::White, "#dz expedition reload - reload expedition zone cache from database");
c->Message(
Chat::White,
"#dz expedition destroy <expedition_id> - destroy expedition globally (must be in cache)"
);
c->Message(Chat::White, "#dz expedition unlock <expedition_id> - unlock expedition");
c->Message(Chat::White, "#dz list - list all dynamic zone instances from current zone cache");
c->Message(
Chat::White,
"#dz listdb [all] - list dynamic zone instances from database -- 'all' includes expired"
);
c->Message(Chat::White, "#dz lockouts remove <char_name> - delete all of character's expedition lockouts");
c->Message(
Chat::White,
"#dz lockouts remove <char_name> \"<expedition_name>\" - delete lockouts by expedition"
);
c->Message(
Chat::White,
"#dz lockouts remove <char_name> \"<expedition_name>\" \"<event_name>\" - delete lockout by expedition event"
);
c->Message(Chat::White, "#dz makeleader <expedition_id> <character_name> - set new expedition leader");
}
}

View File

@ -0,0 +1,13 @@
#include "../client.h"
#include "../expedition.h"
void command_dzkickplayers(Client *c, const Seperator *sep)
{
if (c) {
auto expedition = c->GetExpedition();
if (expedition) {
expedition->DzKickPlayers(c);
}
}
}

View File

@ -0,0 +1,140 @@
#include "../client.h"
void command_editmassrespawn(Client *c, const Seperator *sep)
{
if (strcasecmp(sep->arg[1], "usage") == 0) {
c->Message(Chat::White, "#editmassrespawn [exact_match: =]npc_type_name new_respawn_seconds (apply)");
return;
}
std::string search_npc_type;
if (sep->arg[1]) {
search_npc_type = sep->arg[1];
}
int change_respawn_seconds = 0;
if (sep->arg[2] && sep->IsNumber(2)) {
change_respawn_seconds = atoi(sep->arg[2]);
}
bool change_apply = false;
if (sep->arg[3] && strcasecmp(sep->arg[3], "apply") == 0) {
change_apply = true;
}
std::string search_encapsulator = "%";
if (search_npc_type[0] == '=') {
search_npc_type = search_npc_type.substr(1);
search_encapsulator = "";
}
std::string query = fmt::format(
SQL(
SELECT npc_types.id, spawn2.spawngroupID, spawn2.id, npc_types.name, spawn2.respawntime
FROM spawn2
INNER JOIN spawnentry ON spawn2.spawngroupID = spawnentry.spawngroupID
INNER JOIN npc_types ON spawnentry.npcID = npc_types.id
WHERE spawn2.zone LIKE '{}'
AND spawn2.version = '{}'
AND npc_types.name LIKE '{}{}{}'
ORDER BY npc_types.id, spawn2.spawngroupID, spawn2.id
),
zone->GetShortName(),
zone->GetInstanceVersion(),
search_encapsulator,
search_npc_type,
search_encapsulator
);
std::string status = "(Searching)";
if (change_apply) {
status = "(Applying)";
}
int results_count = 0;
auto results = content_db.QueryDatabase(query);
if (results.Success() && results.RowCount()) {
results_count = results.RowCount();
for (auto row : results) {
c->Message(
Chat::Yellow,
fmt::format(
"NPC (npcid:{}) (sgid:{}) (s2id:{}) [{}] Respawn: Current [{}] New [{}] {}",
row[0],
row[1],
row[2],
row[3],
row[4],
change_respawn_seconds,
status
).c_str()
);
}
c->Message(Chat::Yellow, "Found (%i) NPC's that match this search...", results_count);
if (change_respawn_seconds > 0) {
if (change_apply) {
results = content_db.QueryDatabase(
fmt::format(
SQL(
UPDATE spawn2
SET respawntime = '{}'
WHERE id IN(
SELECT spawn2.id
FROM spawn2
INNER JOIN spawnentry ON spawn2.spawngroupID = spawnentry.spawngroupID
INNER JOIN npc_types ON spawnentry.npcID = npc_types.id
WHERE spawn2.zone LIKE '{}'
AND spawn2.version = '{}'
AND npc_types.name LIKE '{}{}{}'
)
),
change_respawn_seconds,
zone->GetShortName(),
zone->GetInstanceVersion(),
search_encapsulator,
search_npc_type,
search_encapsulator
)
);
if (results.Success()) {
c->Message(Chat::Yellow, "Changes applied to (%i) NPC 'Spawn2' entries", results_count);
zone->Repop();
}
else {
c->Message(Chat::Yellow, "Found (0) NPC's that match this search...");
}
}
else {
std::string saylink = fmt::format(
"#editmassrespawn {}{} {} apply",
(search_encapsulator.empty() ? "=" : ""),
search_npc_type,
change_respawn_seconds
);
c->Message(
Chat::Yellow, "To apply these changes, click <%s> or type [%s]",
EQ::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(),
saylink.c_str()
);
}
}
}
else {
c->Message(Chat::Yellow, "Found (0) NPC's that match this search...");
}
}

45
zone/gm_commands/emote.cpp Executable file
View File

@ -0,0 +1,45 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
void command_emote(Client *c, const Seperator *sep)
{
if (sep->arg[3][0] == 0) {
c->Message(Chat::White, "Usage: #emote [name | world | zone] type# message");
}
else {
if (strcasecmp(sep->arg[1], "zone") == 0) {
char *newmessage = 0;
if (strstr(sep->arg[3], "^") == 0) {
entity_list.Message(0, atoi(sep->arg[2]), sep->argplus[3]);
}
else {
for (newmessage = strtok((char *) sep->arg[3], "^");
newmessage != nullptr;
newmessage = strtok(nullptr, "^"))
entity_list.Message(0, atoi(sep->arg[2]), newmessage);
}
}
else if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server disconnected");
}
else if (!strcasecmp(sep->arg[1], "world")) {
worldserver.SendEmoteMessage(
0,
0,
atoi(sep->arg[2]),
sep->argplus[3]
);
}
else {
worldserver.SendEmoteMessage(
sep->arg[1],
0,
atoi(sep->arg[2]),
sep->argplus[3]
);
}
}
}

View File

@ -0,0 +1,78 @@
#include "../client.h"
void command_emotesearch(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0) {
c->Message(Chat::White, "Usage: #emotesearch [search string or emoteid]");
}
else {
const char *search_criteria = sep->argplus[1];
int count = 0;
if (Seperator::IsNumber(search_criteria)) {
uint16 emoteid = atoi(search_criteria);
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
NPC_Emote_Struct *nes = iterator.GetData();
if (emoteid == nes->emoteid) {
c->Message(
Chat::White,
"EmoteID: %i Event: %i Type: %i Text: %s",
nes->emoteid,
nes->event_,
nes->type,
nes->text
);
count++;
}
iterator.Advance();
}
if (count == 0) {
c->Message(Chat::White, "No emotes found.");
}
else {
c->Message(Chat::White, "%i emote(s) found", count);
}
}
else {
char sText[64];
char sCriteria[515];
strn0cpy(sCriteria, search_criteria, sizeof(sCriteria));
strupr(sCriteria);
char *pdest;
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
NPC_Emote_Struct *nes = iterator.GetData();
strn0cpy(sText, nes->text, sizeof(sText));
strupr(sText);
pdest = strstr(sText, sCriteria);
if (pdest != nullptr) {
c->Message(
Chat::White,
"EmoteID: %i Event: %i Type: %i Text: %s",
nes->emoteid,
nes->event_,
nes->type,
nes->text
);
count++;
}
if (count == 50) {
break;
}
iterator.Advance();
}
if (count == 50) {
c->Message(Chat::White, "50 emotes shown...too many results.");
}
else {
c->Message(Chat::White, "%i emote(s) found", count);
}
}
}
}

39
zone/gm_commands/emoteview.cpp Executable file
View File

@ -0,0 +1,39 @@
#include "../client.h"
void command_emoteview(Client *c, const Seperator *sep)
{
if (!c->GetTarget() || !c->GetTarget()->IsNPC()) {
c->Message(Chat::White, "You must target a NPC to view their emotes.");
return;
}
if (c->GetTarget() && c->GetTarget()->IsNPC()) {
int count = 0;
int emoteid = c->GetTarget()->CastToNPC()->GetEmoteID();
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
NPC_Emote_Struct *nes = iterator.GetData();
if (emoteid == nes->emoteid) {
c->Message(
Chat::White,
"EmoteID: %i Event: %i Type: %i Text: %s",
nes->emoteid,
nes->event_,
nes->type,
nes->text
);
count++;
}
iterator.Advance();
}
if (count == 0) {
c->Message(Chat::White, "No emotes found.");
}
else {
c->Message(Chat::White, "%i emote(s) found", count);
}
}
}

View File

@ -0,0 +1,29 @@
#include "../client.h"
void command_enablerecipe(Client *c, const Seperator *sep)
{
uint32 recipe_id = 0;
bool success = false;
if (c) {
if (sep->argnum == 1) {
recipe_id = atoi(sep->arg[1]);
}
else {
c->Message(Chat::White, "Invalid number of arguments.\nUsage: #enablerecipe recipe_id");
return;
}
if (recipe_id > 0) {
success = content_db.EnableRecipe(recipe_id);
if (success) {
c->Message(Chat::White, "Recipe enabled.");
}
else {
c->Message(Chat::White, "Recipe not enabled.");
}
}
else {
c->Message(Chat::White, "Invalid recipe id.\nUsage: #enablerecipe recipe_id");
}
}
}

27
zone/gm_commands/endurance.cpp Executable file
View File

@ -0,0 +1,27 @@
#include "../client.h"
void command_endurance(Client *c, const Seperator *sep)
{
auto target = c->GetTarget() ? c->GetTarget() : c;
if (target->IsClient()) {
target->CastToClient()->SetEndurance(target->CastToClient()->GetMaxEndurance());
}
else {
target->SetEndurance(target->GetMaxEndurance());
}
if (c != target) {
c->Message(
Chat::White,
fmt::format(
"Set {} ({}) to full Endurance.",
target->GetCleanName(),
target->GetID()
).c_str()
);
}
else {
c->Message(Chat::White, "Restored your Endurance to full.");
}
}

82
zone/gm_commands/equipitem.cpp Executable file
View File

@ -0,0 +1,82 @@
#include "../client.h"
void command_equipitem(Client *c, const Seperator *sep)
{
uint32 slot_id = atoi(sep->arg[1]);
if (sep->IsNumber(1) && (slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <= EQ::invslot::EQUIPMENT_END)) {
const EQ::ItemInstance *from_inst = c->GetInv().GetItem(EQ::invslot::slotCursor);
const EQ::ItemInstance *to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack)
bool partialmove = false;
int16 movecount;
if (from_inst && from_inst->IsClassCommon()) {
auto outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
MoveItem_Struct *mi = (MoveItem_Struct *) outapp->pBuffer;
mi->from_slot = EQ::invslot::slotCursor;
mi->to_slot = slot_id;
// mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking
// crude stackable check to only 'move' the difference count on client instead of entire stack when applicable
if (to_inst && to_inst->IsStackable() &&
(to_inst->GetItem()->ID == from_inst->GetItem()->ID) &&
(to_inst->GetCharges() < to_inst->GetItem()->StackSize) &&
(from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) {
movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges();
mi->number_in_stack = (uint32) movecount;
partialmove = true;
}
else {
mi->number_in_stack = from_inst->GetCharges();
}
// Save move changes
// Added conditional check to packet send..would have sent change even on a swap failure..whoops!
if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below
// mi->number_in_stack is always from_inst->GetCharges() when partialmove is false
c->Message(Chat::Red, "Error: Partial stack added to existing stack exceeds allowable stacksize");
safe_delete(outapp);
return;
}
else if (c->SwapItem(mi)) {
c->FastQueuePacket(&outapp);
// if the below code is still needed..just send an an item trade packet to each slot..it should overwrite the client instance
// below code has proper logic, but client does not like to have cursor charges changed
// (we could delete the cursor item and resend, but issues would arise if there are queued items)
//if (partialmove) {
// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
// DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer;
// di->from_slot = SLOT_CURSOR;
// di->to_slot = 0xFFFFFFFF;
// di->number_in_stack = 0xFFFFFFFF;
// c->Message(Chat::White, "Deleting %i charges from stack", movecount); // debug line..delete
// for (int16 deletecount=0; deletecount < movecount; deletecount++)
// have to use 'movecount' because mi->number_in_stack is 'ENCODED' at this point (i.e., 99 charges returns 22...)
// c->QueuePacket(outapp2);
// safe_delete(outapp2);
//}
}
else {
c->Message(Chat::Red, "Error: Unable to equip current item");
}
safe_delete(outapp);
// also send out a wear change packet?
}
else if (from_inst == nullptr) {
c->Message(Chat::Red, "Error: There is no item on your cursor");
}
else {
c->Message(Chat::Red, "Error: Item on your cursor cannot be equipped");
}
}
else {
c->Message(Chat::White, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position");
}
}

37
zone/gm_commands/face.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_face(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #face [number of face]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = atoi(sep->arg[1]);
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Face = %i", atoi(sep->arg[1]));
}
}

174
zone/gm_commands/faction.cpp Executable file
View File

@ -0,0 +1,174 @@
#include "../client.h"
void command_faction(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (!arguments) {
c->Message(
Chat::White,
"Usage: #faction review [Search Criteria | All] - Review Targeted Player's Faction Hits"
);
c->Message(
Chat::White,
"Usage: #faction reset [Faction ID] - Reset Targeted Player's Faction to Base Faction Value"
);
c->Message(Chat::White, "Usage: #faction view - Displays Target NPC's Primary Faction");
return;
}
std::string faction_filter;
if (sep->arg[2]) {
faction_filter = str_tolower(sep->arg[2]);
}
if (!strcasecmp(sep->arg[1], "review")) {
if (!(c->GetTarget() && c->GetTarget()->IsClient())) {
c->Message(Chat::Red, "Player Target Required for faction review");
return;
}
Client *target = c->GetTarget()->CastToClient();
uint32 character_id = target->CharacterID();
std::string query;
if (!strcasecmp(faction_filter.c_str(), "all")) {
query = fmt::format(
"SELECT id, `name`, current_value FROM faction_list INNER JOIN faction_values ON faction_list.id = faction_values.faction_id WHERE char_id = {}",
character_id
);
}
else {
query = fmt::format(
"SELECT id, `name`, current_value FROM faction_list INNER JOIN faction_values ON faction_list.id = faction_values.faction_id WHERE `name` like '%{}%' and char_id = {}",
faction_filter.c_str(),
character_id
);
}
auto results = content_db.QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
c->Message(Chat::Yellow, "No faction hits found. All are at base level.");
return;
}
uint32 found_count = 0;
for (auto row : results) {
uint32 faction_number = (found_count + 1);
auto faction_id = std::stoul(row[0]);
std::string faction_name = row[1];
std::string faction_value = row[2];
std::string reset_link = EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format("#faction reset {}", faction_id),
false,
"Reset"
);
c->Message(
Chat::White,
fmt::format(
"Faction {} | Name: {} ({}) Value: {} [{}]",
faction_number,
faction_name,
faction_id,
faction_value,
reset_link
).c_str()
);
found_count++;
}
auto faction_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Faction was" :
fmt::format("{} Factions were", found_count)
) :
"No Factions were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
faction_message
).c_str()
);
}
else if (!strcasecmp(sep->arg[1], "reset")) {
if (strlen(faction_filter.c_str()) > 0) {
if (c->GetTarget() && c->GetTarget()->IsClient()) {
Client *target = c->GetTarget()->CastToClient();
if (
(
!c->GetFeigned() &&
c->GetAggroCount() == 0
) ||
(
!target->GetFeigned() &&
target->GetAggroCount() == 0
)
) {
uint32 character_id = target->CharacterID();
uint32 faction_id = std::stoul(faction_filter.c_str());
if (target->ReloadCharacterFaction(target, faction_id, character_id)) {
c->Message(
Chat::White,
fmt::format(
"Faction Reset | {} ({}) was reset for {}.",
content_db.GetFactionName(faction_id),
faction_id,
target->GetCleanName()
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Faction Reset Failed | {} ({}) was unable to be reset for {}.",
content_db.GetFactionName(faction_id),
faction_id,
target->GetCleanName()
).c_str()
);
}
}
else {
c->Message(
Chat::White,
"You cannot reset factions while you or your target is in combat or feigned."
);
return;
}
}
else {
c->Message(Chat::White, "You must target a PC for this command.");
return;
}
}
else {
c->Message(
Chat::White,
"Usage: #faction reset [Faction ID] - Reset Targeted Player's Faction to Base Faction Value"
);
}
}
else if (!strcasecmp(sep->arg[1], "view")) {
if (c->GetTarget() && c->GetTarget()->IsNPC()) {
Mob *target = c->GetTarget();
uint32 npc_id = target->GetNPCTypeID();
uint32 npc_faction_id = target->CastToNPC()->GetPrimaryFaction();
std::string npc_name = target->GetCleanName();
c->Message(
Chat::White,
fmt::format(
"{} ({}) has a Primary Faction of {} ({}).",
npc_name,
npc_id,
content_db.GetFactionName(npc_faction_id),
npc_faction_id
).c_str()
);
}
}
}

84
zone/gm_commands/findclass.cpp Executable file
View File

@ -0,0 +1,84 @@
#include "../client.h"
void command_findclass(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #findclass [search criteria]");
return;
}
if (sep->IsNumber(1)) {
int class_id = std::stoi(sep->arg[1]);
if (class_id >= WARRIOR && class_id <= MERCERNARY_MASTER) {
std::string class_name = GetClassIDName(class_id);
c->Message(
Chat::White,
fmt::format(
"Class {}: {}",
class_id,
class_name
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Class ID {} was not found.",
class_id
).c_str()
);
}
}
else {
std::string search_criteria = str_tolower(sep->argplus[1]);
int found_count = 0;
for (int class_id = WARRIOR; class_id <= MERCERNARY_MASTER; class_id++) {
std::string class_name = GetClassIDName(class_id);
std::string class_name_lower = str_tolower(class_name);
if (search_criteria.length() > 0 && class_name_lower.find(search_criteria) == std::string::npos) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Class {}: {}",
class_id,
class_name
).c_str()
);
found_count++;
if (found_count == 20) {
break;
}
}
if (found_count == 20) {
c->Message(Chat::White, "20 Classes found... max reached.");
}
else {
auto class_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Class was" :
fmt::format("{} Classes were", found_count)
) :
"No Classes were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
class_message
).c_str()
);
}
}
}

View File

@ -0,0 +1,89 @@
#include "../client.h"
void command_findfaction(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #findfaction [search criteria]");
return;
}
if (sep->IsNumber(1)) {
int faction_id = std::stoi(sep->arg[1]);
auto faction_name = content_db.GetFactionName(faction_id);
if (!faction_name.empty()) {
c->Message(
Chat::White,
fmt::format(
"Faction {}: {}",
faction_id,
faction_name
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Faction ID {} was not found.",
faction_id
).c_str()
);
}
}
else {
std::string search_criteria = str_tolower(sep->argplus[1]);
int found_count = 0;
int max_faction_id = content_db.GetMaxFaction();
for (int faction_id = 0; faction_id < max_faction_id; faction_id++) {
std::string faction_name = content_db.GetFactionName(faction_id);
std::string faction_name_lower = str_tolower(faction_name);
if (faction_name.empty()) {
continue;
}
if (faction_name.find(search_criteria) == std::string::npos) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Faction {}: {}",
faction_id,
faction_name
).c_str()
);
found_count++;
if (found_count == 20) {
break;
}
}
if (found_count == 20) {
c->Message(Chat::White, "20 Factions found... max reached.");
}
else {
auto faction_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Faction was" :
fmt::format("{} Factions were", found_count)
) :
"No Factions were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
faction_message
).c_str()
);
}
}
}

View File

@ -0,0 +1,77 @@
#include "../client.h"
void command_findnpctype(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #findnpctype [Search Criteria]");
return;
}
std::string query;
std::string search_criteria = sep->arg[1];
if (sep->IsNumber(1)) {
query = fmt::format(
"SELECT id, name FROM npc_types WHERE id = {}",
search_criteria
);
}
else {
query = fmt::format(
"SELECT id, name FROM npc_types WHERE name LIKE '%%{}%%'",
search_criteria
);
}
auto results = content_db.QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
c->Message(
Chat::White,
fmt::format(
"No matches found for '{}'.",
search_criteria
).c_str()
);
return;
}
int found_count = 0;
for (auto row : results) {
int found_number = (found_count + 1);
if (found_count == 20) {
break;
}
c->Message(
Chat::White,
fmt::format(
"NPC {} | {} ({})",
found_number,
row[1],
row[0]
).c_str()
);
found_count++;
}
if (found_count == 20) {
c->Message(Chat::White, "20 NPCs were found, max reached.");
}
else {
auto npc_message = (
found_count == 1 ?
"An NPC was" :
fmt::format("{} NPCs were", found_count)
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
npc_message
).c_str()
);
}
}

84
zone/gm_commands/findrace.cpp Executable file
View File

@ -0,0 +1,84 @@
#include "../client.h"
void command_findrace(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #findrace [search criteria]");
return;
}
if (sep->IsNumber(1)) {
int race_id = std::stoi(sep->arg[1]);
std::string race_name = GetRaceIDName(race_id);
if (race_id >= RACE_HUMAN_1 && race_id <= RACE_PEGASUS_732) {
c->Message(
Chat::White,
fmt::format(
"Race {}: {}",
race_id,
race_name
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Race ID {} was not found.",
race_id
).c_str()
);
}
}
else {
std::string search_criteria = str_tolower(sep->argplus[1]);
int found_count = 0;
for (int race_id = RACE_HUMAN_1; race_id <= RACE_PEGASUS_732; race_id++) {
std::string race_name = GetRaceIDName(race_id);
std::string race_name_lower = str_tolower(race_name);
if (search_criteria.length() > 0 && race_name_lower.find(search_criteria) == std::string::npos) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Race {}: {}",
race_id,
race_name
).c_str()
);
found_count++;
if (found_count == 20) {
break;
}
}
if (found_count == 20) {
c->Message(Chat::White, "20 Races found... max reached.");
}
else {
auto race_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Race was" :
fmt::format("{} Races were", found_count)
) :
"No Races were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
race_message
).c_str()
);
}
}
}

90
zone/gm_commands/findskill.cpp Executable file
View File

@ -0,0 +1,90 @@
#include "../client.h"
void command_findskill(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #findskill [search criteria]");
return;
}
std::map<EQ::skills::SkillType, std::string> skills = EQ::skills::GetSkillTypeMap();
if (sep->IsNumber(1)) {
int skill_id = std::stoi(sep->arg[1]);
if (skill_id >= EQ::skills::Skill1HBlunt && skill_id < EQ::skills::SkillCount) {
for (auto skill : skills) {
if (skill_id == skill.first) {
c->Message(
Chat::White,
fmt::format(
"Skill {}: {}",
skill.first,
skill.second
).c_str()
);
break;
}
}
}
else {
c->Message(
Chat::White,
fmt::format(
"Skill ID {} was not found.",
skill_id
).c_str()
);
}
}
else {
std::string search_criteria = str_tolower(sep->argplus[1]);
if (!search_criteria.empty()) {
int found_count = 0;
for (auto skill : skills) {
std::string skill_name_lower = str_tolower(skill.second);
if (skill_name_lower.find(search_criteria) == std::string::npos) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Skill {}: {}",
skill.first,
skill.second
).c_str()
);
found_count++;
if (found_count == 20) {
break;
}
}
if (found_count == 20) {
c->Message(Chat::White, "20 Skills were found, max reached.");
}
else {
auto skill_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Skill was" :
fmt::format("{} Skills were", found_count)
) :
"No Skills were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
skill_message
).c_str()
);
}
}
}
}

129
zone/gm_commands/findspell.cpp Executable file
View File

@ -0,0 +1,129 @@
#include "../client.h"
void command_findspell(Client *c, const Seperator *sep)
{
if (SPDAT_RECORDS <= 0) {
c->Message(Chat::White, "Spells not loaded");
return;
}
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #findspell [search criteria]");
return;
}
if (sep->IsNumber(1)) {
int spell_id = std::stoi(sep->arg[1]);
if (!IsValidSpell(spell_id)) {
c->Message(
Chat::White,
fmt::format(
"Spell ID {} was not found.",
spell_id
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Spell {}: {}",
spell_id,
spells[spell_id].name
).c_str()
);
}
}
else {
std::string search_criteria = str_tolower(sep->argplus[1]);
int found_count = 0;
for (int spell_id = 0; spell_id < SPDAT_RECORDS; spell_id++) {
auto current_spell = spells[spell_id];
if (current_spell.name[0] != 0) {
std::string spell_name = current_spell.name;
std::string spell_name_lower = str_tolower(spell_name);
if (search_criteria.length() > 0 && spell_name_lower.find(search_criteria) == std::string::npos) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Spell {}: {}",
spell_id,
spell_name
).c_str()
);
found_count++;
if (found_count == 20) {
break;
}
}
}
if (found_count == 20) {
c->Message(Chat::White, "20 Spells found... max reached.");
}
else {
auto spell_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Spell was" :
fmt::format("{} Spells were", found_count)
) :
"No Spells were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
spell_message
).c_str()
);
}
}
}
inline bool CastRestrictedSpell(int spellid)
{
switch (spellid) {
case SPELL_TOUCH_OF_VINITRAS:
case SPELL_DESPERATE_HOPE:
case SPELL_CHARM:
case SPELL_METAMORPHOSIS65:
case SPELL_JT_BUFF:
case SPELL_CAN_O_WHOOP_ASS:
case SPELL_PHOENIX_CHARM:
case SPELL_CAZIC_TOUCH:
case SPELL_AVATAR_KNOCKBACK:
case SPELL_SHAPECHANGE65:
case SPELL_SUNSET_HOME1218:
case SPELL_SUNSET_HOME819:
case SPELL_SHAPECHANGE75:
case SPELL_SHAPECHANGE80:
case SPELL_SHAPECHANGE85:
case SPELL_SHAPECHANGE90:
case SPELL_SHAPECHANGE95:
case SPELL_SHAPECHANGE100:
case SPELL_SHAPECHANGE25:
case SPELL_SHAPECHANGE30:
case SPELL_SHAPECHANGE35:
case SPELL_SHAPECHANGE40:
case SPELL_SHAPECHANGE45:
case SPELL_SHAPECHANGE50:
case SPELL_NPC_AEGOLISM:
case SPELL_SHAPECHANGE55:
case SPELL_SHAPECHANGE60:
case SPELL_COMMAND_OF_DRUZZIL:
case SPELL_SHAPECHANGE70:
return true;
default:
return false;
}
}

89
zone/gm_commands/findtask.cpp Executable file
View File

@ -0,0 +1,89 @@
#include "../client.h"
void command_findtask(Client *c, const Seperator *sep)
{
if (RuleB(TaskSystem, EnableTaskSystem)) {
int arguments = sep->argnum;
if (arguments == 0) {
c->Message(Chat::White, "Command Syntax: #findtask [search criteria]");
return;
}
if (sep->IsNumber(1)) {
auto task_id = std::stoul(sep->arg[1]);
auto task_name = task_manager->GetTaskName(task_id);
auto task_message = (
!task_name.empty() ?
fmt::format(
"Task {}: {}",
task_id,
task_name
).c_str() :
fmt::format(
"Task ID {} was not found.",
task_id
).c_str()
);
c->Message(
Chat::White,
task_message
);
}
else {
std::string search_criteria = str_tolower(sep->argplus[1]);
if (!search_criteria.empty()) {
int found_count = 0;
for (uint32 task_id = 1; task_id <= MAXTASKS; task_id++) {
auto task_name = task_manager->GetTaskName(task_id);
std::string task_name_lower = str_tolower(task_name);
if (task_name_lower.find(search_criteria) == std::string::npos) {
continue;
}
c->Message(
Chat::White,
fmt::format(
"Task {}: {}",
task_id,
task_name
).c_str()
);
found_count++;
if (found_count == 20) {
break;
}
}
if (found_count == 20) {
c->Message(Chat::White, "20 Tasks were found, max reached.");
}
else {
auto task_message = (
found_count > 0 ?
(
found_count == 1 ?
"A Task was" :
fmt::format("{} Tasks were", found_count)
) :
"No Tasks were"
);
c->Message(
Chat::White,
fmt::format(
"{} found.",
task_message
).c_str()
);
}
}
}
}
else {
c->Message(Chat::White, "This command cannot be used while the Task system is disabled.");
}
}

95
zone/gm_commands/findzone.cpp Executable file
View File

@ -0,0 +1,95 @@
#include "../client.h"
void command_findzone(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0) {
c->Message(Chat::White, "Usage: #findzone [search criteria]");
c->Message(Chat::White, "Usage: #findzone expansion [expansion number]");
return;
}
std::string query;
int id = atoi((const char *) sep->arg[1]);
std::string arg1 = sep->arg[1];
if (arg1 == "expansion") {
query = fmt::format(
"SELECT zoneidnumber, short_name, long_name, version FROM zone WHERE expansion = {}",
sep->arg[2]
);
}
else {
/**
* If id evaluates to 0, then search as if user entered a string
*/
if (id == 0) {
query = fmt::format(
"SELECT zoneidnumber, short_name, long_name, version FROM zone WHERE long_name LIKE '%{}%' OR `short_name` LIKE '%{}%'",
EscapeString(sep->arg[1]),
EscapeString(sep->arg[1])
);
}
else {
query = fmt::format(
"SELECT zoneidnumber, short_name, long_name, version FROM zone WHERE zoneidnumber = {}",
id
);
}
}
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Error querying database.");
c->Message(Chat::White, query.c_str());
return;
}
int count = 0;
const int maxrows = 100;
for (auto row = results.begin(); row != results.end(); ++row) {
std::string zone_id = row[0];
std::string short_name = row[1];
std::string long_name = row[2];
int version = atoi(row[3]);
if (++count > maxrows) {
c->Message(Chat::White, "%i zones shown. Too many results.", maxrows);
break;
}
std::string command_zone = EQ::SayLinkEngine::GenerateQuestSaylink("#zone " + short_name, false, "zone");
std::string command_gmzone = EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format("#gmzone {} {}", short_name, version),
false,
"gmzone"
);
c->Message(
Chat::White,
fmt::format(
"[{}] [{}] [{}] ID ({}) Version ({}) [{}]",
(version == 0 ? command_zone : "zone"),
command_gmzone,
short_name,
zone_id,
version,
long_name
).c_str()
);
}
if (count <= maxrows) {
c->Message(
Chat::White,
"Query complete. %i rows shown. %s",
count,
(arg1 == "expansion" ? "(expansion search)" : ""));
}
else if (count == 0) {
c->Message(Chat::White, "No matches found for %s.", sep->arg[1]);
}
}

250
zone/gm_commands/fixmob.cpp Executable file
View File

@ -0,0 +1,250 @@
#include "../client.h"
void command_fixmob(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
const char *Usage = "Usage: #fixmob [race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev]";
if (!sep->arg[1]) {
c->Message(Chat::White, Usage);
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint32 Adjustment = 1; // Previous or Next
char codeMove = 0;
if (sep->arg[2]) {
char *command2 = sep->arg[2];
codeMove = (command2[0] | 0x20); // First character, lower-cased
if (codeMove == 'n') {
Adjustment = 1;
}
else if (codeMove == 'p') {
Adjustment = -1;
}
}
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
const char *ChangeType = nullptr; // If it's still nullptr after processing, they didn't send a valid command
uint32 ChangeSetting;
char *command = sep->arg[1];
if (strcasecmp(command, "race") == 0) {
if (Race == 1 && codeMove == 'p') {
Race = RuleI(NPC, MaxRaceID);
}
else if (Race >= RuleI(NPC, MaxRaceID) && codeMove != 'p') {
Race = 1;
}
else {
Race += Adjustment;
}
ChangeType = "Race";
ChangeSetting = Race;
}
else if (strcasecmp(command, "gender") == 0) {
if (Gender == 0 && codeMove == 'p') {
Gender = 2;
}
else if (Gender >= 2 && codeMove != 'p') {
Gender = 0;
}
else {
Gender += Adjustment;
}
ChangeType = "Gender";
ChangeSetting = Gender;
}
else if (strcasecmp(command, "texture") == 0) {
Texture = target->GetTexture();
if (Texture == 0 && codeMove == 'p') {
Texture = 25;
}
else if (Texture >= 25 && codeMove != 'p') {
Texture = 0;
}
else {
Texture += Adjustment;
}
ChangeType = "Texture";
ChangeSetting = Texture;
}
else if (strcasecmp(command, "helm") == 0) {
HelmTexture = target->GetHelmTexture();
if (HelmTexture == 0 && codeMove == 'p') {
HelmTexture = 25;
}
else if (HelmTexture >= 25 && codeMove != 'p') {
HelmTexture = 0;
}
else {
HelmTexture += Adjustment;
}
ChangeType = "HelmTexture";
ChangeSetting = HelmTexture;
}
else if (strcasecmp(command, "face") == 0) {
if (LuclinFace == 0 && codeMove == 'p') {
LuclinFace = 87;
}
else if (LuclinFace >= 87 && codeMove != 'p') {
LuclinFace = 0;
}
else {
LuclinFace += Adjustment;
}
ChangeType = "LuclinFace";
ChangeSetting = LuclinFace;
}
else if (strcasecmp(command, "hair") == 0) {
if (HairStyle == 0 && codeMove == 'p') {
HairStyle = 8;
}
else if (HairStyle >= 8 && codeMove != 'p') {
HairStyle = 0;
}
else {
HairStyle += Adjustment;
}
ChangeType = "HairStyle";
ChangeSetting = HairStyle;
}
else if (strcasecmp(command, "haircolor") == 0) {
if (HairColor == 0 && codeMove == 'p') {
HairColor = 24;
}
else if (HairColor >= 24 && codeMove != 'p') {
HairColor = 0;
}
else {
HairColor += Adjustment;
}
ChangeType = "HairColor";
ChangeSetting = HairColor;
}
else if (strcasecmp(command, "beard") == 0) {
if (Beard == 0 && codeMove == 'p') {
Beard = 11;
}
else if (Beard >= 11 && codeMove != 'p') {
Beard = 0;
}
else {
Beard += Adjustment;
}
ChangeType = "Beard";
ChangeSetting = Beard;
}
else if (strcasecmp(command, "beardcolor") == 0) {
if (BeardColor == 0 && codeMove == 'p') {
BeardColor = 24;
}
else if (BeardColor >= 24 && codeMove != 'p') {
BeardColor = 0;
}
else {
BeardColor += Adjustment;
}
ChangeType = "BeardColor";
ChangeSetting = BeardColor;
}
else if (strcasecmp(command, "heritage") == 0) {
if (DrakkinHeritage == 0 && codeMove == 'p') {
DrakkinHeritage = 6;
}
else if (DrakkinHeritage >= 6 && codeMove != 'p') {
DrakkinHeritage = 0;
}
else {
DrakkinHeritage += Adjustment;
}
ChangeType = "DrakkinHeritage";
ChangeSetting = DrakkinHeritage;
}
else if (strcasecmp(command, "tattoo") == 0) {
if (DrakkinTattoo == 0 && codeMove == 'p') {
DrakkinTattoo = 8;
}
else if (DrakkinTattoo >= 8 && codeMove != 'p') {
DrakkinTattoo = 0;
}
else {
DrakkinTattoo += Adjustment;
}
ChangeType = "DrakkinTattoo";
ChangeSetting = DrakkinTattoo;
}
else if (strcasecmp(command, "detail") == 0) {
if (DrakkinDetails == 0 && codeMove == 'p') {
DrakkinDetails = 7;
}
else if (DrakkinDetails >= 7 && codeMove != 'p') {
DrakkinDetails = 0;
}
else {
DrakkinDetails += Adjustment;
}
ChangeType = "DrakkinDetails";
ChangeSetting = DrakkinDetails;
}
// Hack to fix some races that base features from face
switch (Race) {
case 2: // Barbarian
if (LuclinFace > 10) {
LuclinFace -= ((DrakkinTattoo - 1) * 10);
}
LuclinFace += (DrakkinTattoo * 10);
break;
case 3: // Erudite
if (LuclinFace > 10) {
LuclinFace -= ((HairStyle - 1) * 10);
}
LuclinFace += (HairStyle * 10);
break;
case 5: // HighElf
case 6: // DarkElf
case 7: // HalfElf
if (LuclinFace > 10) {
LuclinFace -= ((Beard - 1) * 10);
}
LuclinFace += (Beard * 10);
break;
default:
break;
}
if (ChangeType == nullptr) {
c->Message(Chat::White, Usage);
}
else {
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "%s=%i", ChangeType, ChangeSetting);
}
}
}

53
zone/gm_commands/flag.cpp Executable file
View File

@ -0,0 +1,53 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
void command_flag(Client *c, const Seperator *sep)
{
if (sep->arg[2][0] == 0) {
if (!c->GetTarget() || (c->GetTarget() && c->GetTarget() == c)) {
c->UpdateAdmin();
c->Message(Chat::White, "Refreshed your admin flag from DB.");
}
else if (c->GetTarget() && c->GetTarget() != c && c->GetTarget()->IsClient()) {
c->GetTarget()->CastToClient()->UpdateAdmin();
c->Message(Chat::White, "%s's admin flag has been refreshed.", c->GetTarget()->GetName());
c->GetTarget()->Message(Chat::White, "%s refreshed your admin flag.", c->GetName());
}
}
else if (!sep->IsNumber(1) || atoi(sep->arg[1]) < -2 || atoi(sep->arg[1]) > 255 || strlen(sep->arg[2]) == 0) {
c->Message(Chat::White, "Usage: #flag [status] [acctname]");
}
else if (c->Admin() < commandChangeFlags) {
//this check makes banning players by less than this level
//impossible, but i'll leave it in anyways
c->Message(Chat::White, "You may only refresh your own flag, doing so now.");
c->UpdateAdmin();
}
else {
if (atoi(sep->arg[1]) > c->Admin()) {
c->Message(Chat::White, "You cannot set people's status to higher than your own");
}
else if (atoi(sep->arg[1]) < 0 && c->Admin() < commandBanPlayers) {
c->Message(Chat::White, "You have too low of status to suspend/ban");
}
else if (!database.SetAccountStatus(sep->argplus[2], atoi(sep->arg[1]))) {
c->Message(Chat::White, "Unable to set GM Flag.");
}
else {
c->Message(Chat::White, "Set GM Flag on account.");
std::string user;
std::string loginserver;
ParseAccountString(sep->argplus[2], user, loginserver);
ServerPacket pack(ServerOP_FlagUpdate, 6);
*((uint32 *) pack.pBuffer) = database.GetAccountIDByName(user.c_str(), loginserver.c_str());
*((int16 *) &pack.pBuffer[4]) = atoi(sep->arg[1]);
worldserver.SendPacket(&pack);
}
}
}

157
zone/gm_commands/flagedit.cpp Executable file
View File

@ -0,0 +1,157 @@
#include "../client.h"
void command_flagedit(Client *c, const Seperator *sep)
{
//super-command for editing zone flags
if (sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) {
c->Message(Chat::White, "Syntax: #flagedit [lockzone|unlockzone|listzones|give|take].");
c->Message(
Chat::White,
"...lockzone [zone id/short] [flag name] - Set the specified flag name on the zone, locking the zone"
);
c->Message(Chat::White, "...unlockzone [zone id/short] - Removes the flag requirement from the specified zone");
c->Message(Chat::White, "...listzones - List all zones which require a flag, and their flag's name");
c->Message(Chat::White, "...give [zone id/short] - Give your target the zone flag for the specified zone.");
c->Message(
Chat::White,
"...take [zone id/short] - Take the zone flag for the specified zone away from your target"
);
c->Message(Chat::White, "...Note: use #flags to view flags on a person");
return;
}
if (!strcasecmp(sep->arg[1], "lockzone")) {
uint32 zoneid = 0;
if (sep->arg[2][0] != '\0') {
zoneid = atoi(sep->arg[2]);
if (zoneid < 1) {
zoneid = ZoneID(sep->arg[2]);
}
}
if (zoneid < 1) {
c->Message(Chat::Red, "zone required. see help.");
return;
}
char flag_name[128];
if (sep->argplus[3][0] == '\0') {
c->Message(Chat::Red, "flag name required. see help.");
return;
}
database.DoEscapeString(flag_name, sep->argplus[3], 64);
flag_name[127] = '\0';
std::string query = StringFormat(
"UPDATE zone SET flag_needed = '%s' "
"WHERE zoneidnumber = %d AND version = %d",
flag_name, zoneid, zone->GetInstanceVersion());
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::Red, "Error updating zone: %s", results.ErrorMessage().c_str());
return;
}
c->Message(Chat::Yellow, "Success! Zone %s now requires a flag, named %s", ZoneName(zoneid), flag_name);
return;
}
if (!strcasecmp(sep->arg[1], "unlockzone")) {
uint32 zoneid = 0;
if (sep->arg[2][0] != '\0') {
zoneid = atoi(sep->arg[2]);
if (zoneid < 1) {
zoneid = ZoneID(sep->arg[2]);
}
}
if (zoneid < 1) {
c->Message(Chat::Red, "zone required. see help.");
return;
}
std::string query = StringFormat(
"UPDATE zone SET flag_needed = '' "
"WHERE zoneidnumber = %d AND version = %d",
zoneid, zone->GetInstanceVersion());
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::Yellow, "Error updating zone: %s", results.ErrorMessage().c_str());
return;
}
c->Message(Chat::Yellow, "Success! Zone %s no longer requires a flag.", ZoneName(zoneid));
return;
}
if (!strcasecmp(sep->arg[1], "listzones")) {
std::string query = "SELECT zoneidnumber, short_name, long_name, version, flag_needed "
"FROM zone WHERE flag_needed != ''";
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
c->Message(Chat::White, "Zones which require flags:");
for (auto row = results.begin(); row != results.end(); ++row)
c->Message(
Chat::White,
"Zone %s (%s,%s) version %s requires key %s",
row[2],
row[0],
row[1],
row[3],
row[4]
);
return;
}
if (!strcasecmp(sep->arg[1], "give")) {
uint32 zoneid = 0;
if (sep->arg[2][0] != '\0') {
zoneid = atoi(sep->arg[2]);
if (zoneid < 1) {
zoneid = ZoneID(sep->arg[2]);
}
}
if (zoneid < 1) {
c->Message(Chat::Red, "zone required. see help.");
return;
}
Mob *t = c->GetTarget();
if (t == nullptr || !t->IsClient()) {
c->Message(Chat::Red, "client target required");
return;
}
t->CastToClient()->SetZoneFlag(zoneid);
return;
}
if (!strcasecmp(sep->arg[1], "give")) {
uint32 zoneid = 0;
if (sep->arg[2][0] != '\0') {
zoneid = atoi(sep->arg[2]);
if (zoneid < 1) {
zoneid = ZoneID(sep->arg[2]);
}
}
if (zoneid < 1) {
c->Message(Chat::Red, "zone required. see help.");
return;
}
Mob *t = c->GetTarget();
if (t == nullptr || !t->IsClient()) {
c->Message(Chat::Red, "client target required");
return;
}
t->CastToClient()->ClearZoneFlag(zoneid);
return;
}
c->Message(Chat::Yellow, "Invalid action specified. use '#flagedit help' for help");
}

16
zone/gm_commands/flags.cpp Executable file
View File

@ -0,0 +1,16 @@
#include "../client.h"
void command_flags(Client *c, const Seperator *sep)
{
Client *t = c;
if (c->Admin() >= minStatusToSeeOthersZoneFlags) {
Mob *tgt = c->GetTarget();
if (tgt != nullptr && tgt->IsClient()) {
t = tgt->CastToClient();
}
}
t->SendZoneFlagInfo(c);
}

40
zone/gm_commands/flymode.cpp Executable file
View File

@ -0,0 +1,40 @@
#include "../client.h"
void command_flymode(Client *c, const Seperator *sep)
{
Mob *t = c;
if (strlen(sep->arg[1]) == 1 && sep->IsNumber(1) && atoi(sep->arg[1]) >= 0 && atoi(sep->arg[1]) <= 5) {
if (c->GetTarget()) {
t = c->GetTarget();
}
int fm = atoi(sep->arg[1]);
t->SetFlyMode(static_cast<GravityBehavior>(fm));
t->SendAppearancePacket(AT_Levitate, fm);
if (sep->arg[1][0] == '0') {
c->Message(Chat::White, "Setting %s to Grounded", t->GetName());
}
else if (sep->arg[1][0] == '1') {
c->Message(Chat::White, "Setting %s to Flying", t->GetName());
}
else if (sep->arg[1][0] == '2') {
c->Message(Chat::White, "Setting %s to Levitating", t->GetName());
}
else if (sep->arg[1][0] == '3') {
c->Message(Chat::White, "Setting %s to In Water", t->GetName());
}
else if (sep->arg[1][0] == '4') {
c->Message(Chat::White, "Setting %s to Floating(Boat)", t->GetName());
}
else if (sep->arg[1][0] == '5') {
c->Message(Chat::White, "Setting %s to Levitating While Running", t->GetName());
}
}
else {
c->Message(Chat::White, "#flymode [0/1/2/3/4/5]");
}
}

42
zone/gm_commands/fov.cpp Executable file
View File

@ -0,0 +1,42 @@
#include "../client.h"
void command_fov(Client *c, const Seperator *sep)
{
if (c->GetTarget()) {
auto target = c->GetTarget();
std::string behind_message = (
c->BehindMob(
target,
c->GetX(),
c->GetY()
) ?
"behind" :
"not behind"
);
std::string gender_message = (
target->GetGender() == MALE ?
"he" :
(
target->GetGender() == FEMALE ?
"she" :
"it"
)
);
c->Message(
Chat::White,
fmt::format(
"You are {} {} ({}), {} has a heading of {}.",
behind_message,
target->GetCleanName(),
target->GetID(),
gender_message,
target->GetHeading()
).c_str()
);
}
else {
c->Message(Chat::White, "You must have a target to use this command.");
}
}

12
zone/gm_commands/freeze.cpp Executable file
View File

@ -0,0 +1,12 @@
#include "../client.h"
void command_freeze(Client *c, const Seperator *sep)
{
if (c->GetTarget() != 0) {
c->GetTarget()->SendAppearancePacket(AT_Anim, ANIM_FREEZE);
}
else {
c->Message(Chat::White, "ERROR: Freeze requires a target.");
}
}

14
zone/gm_commands/gassign.cpp Executable file
View File

@ -0,0 +1,14 @@
#include "../client.h"
void command_gassign(Client *c, const Seperator *sep)
{
if (sep->IsNumber(1) && c->GetTarget() && c->GetTarget()->IsNPC() &&
c->GetTarget()->CastToNPC()->GetSpawnPointID() > 0) {
int spawn2id = c->GetTarget()->CastToNPC()->GetSpawnPointID();
database.AssignGrid(c, atoi(sep->arg[1]), spawn2id);
}
else {
c->Message(Chat::White, "Usage: #gassign [num] - must have an npc target!");
}
}

181
zone/gm_commands/gearup.cpp Executable file
View File

@ -0,0 +1,181 @@
#include "../client.h"
#include "../../common/http/httplib.h"
#include "../../common/content/world_content_service.h"
void command_gearup(Client *c, const Seperator *sep)
{
std::string tool_table_name = "tool_gearup_armor_sets";
if (!database.DoesTableExist(tool_table_name)) {
c->Message(
Chat::Yellow,
fmt::format(
"Table [{}] does not exist. Downloading from Github and installing...",
tool_table_name
).c_str()
);
// http get request
httplib::Client cli("https://raw.githubusercontent.com");
cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds
int sourced_queries = 0;
std::string url = "/EQEmu/Server/master/utils/sql/git/optional/2020_07_20_tool_gearup_armor_sets.sql";
if (auto res = cli.Get(url.c_str())) {
if (res->status == 200) {
for (auto &s: SplitString(res->body, ';')) {
if (!trim(s).empty()) {
auto results = database.QueryDatabase(s);
if (!results.ErrorMessage().empty()) {
c->Message(
Chat::Yellow,
fmt::format(
"Error sourcing SQL [{}]", results.ErrorMessage()
).c_str()
);
return;
}
sourced_queries++;
}
}
}
}
else {
c->Message(
Chat::Yellow,
fmt::format(
"Error retrieving URL [{}]",
url
).c_str()
);
}
c->Message(
Chat::Yellow,
fmt::format(
"Table [{}] installed. Sourced [{}] queries",
tool_table_name, sourced_queries
).c_str()
);
}
std::string expansion_arg = sep->arg[1];
std::string expansion_filter;
if (expansion_arg.length() > 0) {
expansion_filter = fmt::format("and `expansion` = {}", expansion_arg);
}
auto results = database.QueryDatabase(
fmt::format(
SQL (
select
item_id,
slot
from
{}
where
`class` = {}
and `level` = {}
{}
order by score desc, expansion desc
),
tool_table_name,
c->GetClass(),
c->GetLevel(),
expansion_filter
)
);
int items_equipped = 0;
int items_already_have = 0;
std::set<int> equipped;
for (auto row = results.begin(); row != results.end(); ++row) {
int item_id = atoi(row[0]);
int slot_id = atoi(row[1]);
if (equipped.find(slot_id) != equipped.end()) {
if (slot_id == EQ::invslot::slotEar1) {
slot_id = EQ::invslot::slotEar2;
}
if (slot_id == EQ::invslot::slotFinger1) {
slot_id = EQ::invslot::slotFinger2;
}
if (slot_id == EQ::invslot::slotWrist1) {
slot_id = EQ::invslot::slotWrist2;
}
}
if (equipped.find(slot_id) == equipped.end()) {
const EQ::ItemData *item = database.GetItem(item_id);
bool has_item = (c->GetInv().HasItem(item_id, 1, invWhereWorn) != INVALID_INDEX);
bool can_wear_item = !c->CheckLoreConflict(item) && !has_item;
if (!can_wear_item) {
items_already_have++;
}
if (c->CastToMob()->CanClassEquipItem(item_id) && can_wear_item) {
equipped.insert(slot_id);
c->SummonItem(
item_id,
0, 0, 0, 0, 0, 0, 0, 0,
slot_id
);
items_equipped++;
}
}
}
c->Message(
Chat::White,
fmt::format(
"Equipped items [{}] already had [{}] items equipped",
items_equipped,
items_already_have
).c_str()
);
if (expansion_arg.empty()) {
results = database.QueryDatabase(
fmt::format(
SQL (
select
expansion
from
{}
where
class = {}
and level = {}
group by
expansion;
),
tool_table_name,
c->GetClass(),
c->GetLevel()
)
);
c->Message(Chat::White, "Choose armor from a specific era");
std::string message;
for (auto row = results.begin(); row != results.end(); ++row) {
int expansion = atoi(row[0]);
message += "[" + EQ::SayLinkEngine::GenerateQuestSaylink(
fmt::format("#gearup {}", expansion),
false,
Expansion::ExpansionName[expansion]
) + "] ";
if (message.length() > 2000) {
c->Message(Chat::White, message.c_str());
message = "";
}
}
if (message.length() > 0) {
c->Message(Chat::White, message.c_str());
}
}
}

17
zone/gm_commands/gender.cpp Executable file
View File

@ -0,0 +1,17 @@
#include "../client.h"
void command_gender(Client *c, const Seperator *sep)
{
Mob *t = c->CastToMob();
if (sep->IsNumber(1) && atoi(sep->arg[1]) >= 0 && atoi(sep->arg[1]) <= 500) {
if ((c->GetTarget()) && c->Admin() >= commandGenderOthers) {
t = c->GetTarget();
}
t->SendIllusionPacket(t->GetRace(), atoi(sep->arg[1]));
}
else {
c->Message(Chat::White, "Usage: #gender [0/1/2]");
}
}

View File

@ -0,0 +1,27 @@
#include "../client.h"
#include "../corpse.h"
void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep)
{
Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) {
t = c->GetTarget()->CastToClient();
}
else {
c->Message(Chat::White, "You must first select a target!");
return;
}
uint32 CorpseCount = database.GetCharacterBuriedCorpseCount(t->CharacterID());
if (CorpseCount > 0) {
c->Message(Chat::White, "Your target has a total of %u buried corpses.", CorpseCount);
}
else {
c->Message(Chat::White, "Your target doesn't have any buried corpses.");
}
return;
}

View File

@ -0,0 +1,13 @@
#include "../client.h"
void command_getvariable(Client *c, const Seperator *sep)
{
std::string tmp;
if (database.GetVariable(sep->argplus[1], tmp)) {
c->Message(Chat::White, "%s = %s", sep->argplus[1], tmp.c_str());
}
else {
c->Message(Chat::White, "GetVariable(%s) returned false", sep->argplus[1]);
}
}

52
zone/gm_commands/ginfo.cpp Executable file
View File

@ -0,0 +1,52 @@
#include "../client.h"
#include "../groups.h"
void command_ginfo(Client *c, const Seperator *sep)
{
Client *t;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
else {
t = c;
}
Group *g = t->GetGroup();
if (!g) {
c->Message(Chat::White, "This client is not in a group");
return;
}
c->Message(
Chat::White,
"Player: %s is in Group #%lu: with %i members",
t->GetName(),
(unsigned long) g->GetID(),
g->GroupCount());
uint32 r;
for (r = 0; r < MAX_GROUP_MEMBERS; r++) {
if (g->members[r] == nullptr) {
if (g->membername[r][0] == '\0') {
continue;
}
c->Message(
Chat::White, "...Zoned Member: %s, Roles: %s %s %s", g->membername[r],
(g->MemberRoles[r] & RoleAssist) ? "Assist" : "",
(g->MemberRoles[r] & RoleTank) ? "Tank" : "",
(g->MemberRoles[r] & RolePuller) ? "Puller" : ""
);
}
else {
c->Message(
Chat::White, "...In-Zone Member: %s (0x%x) Roles: %s %s %s", g->membername[r], g->members[r],
(g->MemberRoles[r] & RoleAssist) ? "Assist" : "",
(g->MemberRoles[r] & RoleTank) ? "Tank" : "",
(g->MemberRoles[r] & RolePuller) ? "Puller" : ""
);
}
}
}

111
zone/gm_commands/giveitem.cpp Executable file
View File

@ -0,0 +1,111 @@
#include "../client.h"
void command_giveitem(Client *c, const Seperator *sep)
{
uint32 item_id = 0;
int16 charges = -1;
uint32 augment_one = 0;
uint32 augment_two = 0;
uint32 augment_three = 0;
uint32 augment_four = 0;
uint32 augment_five = 0;
uint32 augment_six = 0;
int arguments = sep->argnum;
std::string cmd_msg = sep->msg;
size_t link_open = cmd_msg.find('\x12');
size_t link_close = cmd_msg.find_last_of('\x12');
if (c->GetTarget()) {
if (!c->GetTarget()->IsClient()) {
c->Message(Chat::Red, "You can only give items to players with this command.");
return;
}
if (link_open != link_close && (cmd_msg.length() - link_open) > EQ::constants::SAY_LINK_BODY_SIZE) {
EQ::SayLinkBody_Struct link_body;
EQ::saylink::DegenerateLinkBody(
link_body,
cmd_msg.substr(link_open + 1, EQ::constants::SAY_LINK_BODY_SIZE));
item_id = link_body.item_id;
augment_one = link_body.augment_1;
augment_two = link_body.augment_2;
augment_three = link_body.augment_3;
augment_four = link_body.augment_4;
augment_five = link_body.augment_5;
augment_six = link_body.augment_6;
}
else if (sep->IsNumber(1)) {
item_id = atoi(sep->arg[1]);
}
else if (!sep->IsNumber(1)) {
c->Message(
Chat::Red,
"Usage: #giveitem [item id | link] [charges] [augment_one_id] [augment_two_id] [augment_three_id] [augment_four_id] [augment_five_id] [augment_six_id] (Charges are optional.)"
);
return;
}
Client *client_target = c->GetTarget()->CastToClient();
uint8 item_status = 0;
uint8 current_status = c->Admin();
const EQ::ItemData *item = database.GetItem(item_id);
if (item) {
item_status = item->MinStatus;
}
if (item_status > current_status) {
c->Message(
Chat::White,
fmt::format(
"Insufficient status to summon this item, current status is {}, required status is {}.",
current_status,
item_status
).c_str()
);
return;
}
if (arguments >= 2 && sep->IsNumber(2)) {
charges = atoi(sep->arg[2]);
}
if (arguments >= 3 && sep->IsNumber(3)) {
augment_one = atoi(sep->arg[3]);
}
if (arguments >= 4 && sep->IsNumber(4)) {
augment_two = atoi(sep->arg[4]);
}
if (arguments >= 5 && sep->IsNumber(5)) {
augment_three = atoi(sep->arg[5]);
}
if (arguments >= 6 && sep->IsNumber(6)) {
augment_four = atoi(sep->arg[6]);
}
if (arguments >= 7 && sep->IsNumber(7)) {
augment_five = atoi(sep->arg[7]);
}
if (arguments == 8 && sep->IsNumber(8)) {
augment_six = atoi(sep->arg[8]);
}
client_target->SummonItem(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
}
else {
c->Message(Chat::Red, "You must target a client to give the item to.");
return;
}
}

33
zone/gm_commands/givemoney.cpp Executable file
View File

@ -0,0 +1,33 @@
#include "../client.h"
void command_givemoney(Client *c, const Seperator *sep)
{
if (!sep->IsNumber(1)) { //as long as the first one is a number, we'll just let atoi convert the rest to 0 or a number
c->Message(Chat::Red, "Usage: #Usage: #givemoney [pp] [gp] [sp] [cp]");
}
else if (c->GetTarget() == nullptr) {
c->Message(Chat::Red, "You must target a player to give money to.");
}
else if (!c->GetTarget()->IsClient()) {
c->Message(Chat::Red, "You can only give money to players with this command.");
}
else {
//TODO: update this to the client, otherwise the client doesn't show any weight change until you zone, move an item, etc
c->GetTarget()->CastToClient()->AddMoneyToPP(
atoi(sep->arg[4]),
atoi(sep->arg[3]),
atoi(sep->arg[2]),
atoi(sep->arg[1]),
true
);
c->Message(
Chat::White,
"Added %i Platinum, %i Gold, %i Silver, and %i Copper to %s's inventory.",
atoi(sep->arg[1]),
atoi(sep->arg[2]),
atoi(sep->arg[3]),
atoi(sep->arg[4]),
c->GetTarget()->GetName());
}
}

80
zone/gm_commands/globalview.cpp Executable file
View File

@ -0,0 +1,80 @@
#include "../client.h"
void command_globalview(Client *c, const Seperator *sep)
{
NPC *npcmob = nullptr;
if (c->GetTarget() && c->GetTarget()->IsNPC()) {
npcmob = c->GetTarget()->CastToNPC();
QGlobalCache *npc_c = nullptr;
QGlobalCache *char_c = nullptr;
QGlobalCache *zone_c = nullptr;
if (npcmob) {
npc_c = npcmob->GetQGlobals();
}
char_c = c->GetQGlobals();
zone_c = zone->GetQGlobals();
std::list<QGlobal> globalMap;
uint32 ntype = 0;
if (npcmob) {
ntype = npcmob->GetNPCTypeID();
}
if (npc_c) {
QGlobalCache::Combine(globalMap, npc_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID());
}
if (char_c) {
QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID());
}
if (zone_c) {
QGlobalCache::Combine(globalMap, zone_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID());
}
auto iter = globalMap.begin();
uint32 gcount = 0;
c->Message(Chat::White, "Name, Value");
while (iter != globalMap.end()) {
c->Message(Chat::White, "%s %s", (*iter).name.c_str(), (*iter).value.c_str());
++iter;
++gcount;
}
c->Message(Chat::White, "%u globals loaded.", gcount);
}
else {
QGlobalCache *char_c = nullptr;
QGlobalCache *zone_c = nullptr;
char_c = c->GetQGlobals();
zone_c = zone->GetQGlobals();
std::list<QGlobal> globalMap;
uint32 ntype = 0;
if (char_c) {
QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID());
}
if (zone_c) {
QGlobalCache::Combine(globalMap, zone_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID());
}
auto iter = globalMap.begin();
uint32 gcount = 0;
c->Message(Chat::White, "Name, Value");
while (iter != globalMap.end()) {
c->Message(Chat::White, "%s %s", (*iter).name.c_str(), (*iter).value.c_str());
++iter;
++gcount;
}
c->Message(Chat::White, "%u globals loaded.", gcount);
}
}

27
zone/gm_commands/gm.cpp Executable file
View File

@ -0,0 +1,27 @@
#include "../client.h"
void command_gm(Client *c, const Seperator *sep)
{
bool state = atobool(sep->arg[1]);
Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
if (sep->arg[1][0] != 0) {
t->SetGM(state);
c->Message(Chat::White, "%s is %s a GM.", t->GetName(), state ? "now" : "no longer");
}
else {
c->Message(Chat::White, "Usage: #gm [on/off]");
}
}
// there's no need for this, as /summon already takes care of it
// this command is here for reference but it is not added to the
// list above
//To whoever wrote the above: And what about /kill, /zone, /zoneserver, etc?
//There is a reason for the # commands: so that admins can specifically enable certain
//commands for their users. Some might want users to #summon but not to /kill. Cant do that if they are a GM

20
zone/gm_commands/gmspeed.cpp Executable file
View File

@ -0,0 +1,20 @@
#include "../client.h"
void command_gmspeed(Client *c, const Seperator *sep)
{
bool state = atobool(sep->arg[1]);
Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
if (sep->arg[1][0] != 0) {
database.SetGMSpeed(t->AccountID(), state ? 1 : 0);
c->Message(Chat::White, "Turning GMSpeed %s for %s (zone to take effect)", state ? "On" : "Off", t->GetName());
}
else {
c->Message(Chat::White, "Usage: #gmspeed [on/off]");
}
}

88
zone/gm_commands/gmzone.cpp Executable file
View File

@ -0,0 +1,88 @@
#include "../client.h"
#include "../data_bucket.h"
void command_gmzone(Client *c, const Seperator *sep)
{
if (!sep->arg[1]) {
c->Message(Chat::White, "Usage");
c->Message(Chat::White, "-------");
c->Message(Chat::White, "#gmzone [zone_short_name] [zone_version=0]");
return;
}
std::string zone_short_name_string = sep->arg[1];
const char *zone_short_name = sep->arg[1];
auto zone_version = static_cast<uint32>(sep->arg[2] ? atoi(sep->arg[2]) : 0);
std::string identifier = "gmzone";
uint32 zone_id = ZoneID(zone_short_name);
uint32 duration = 100000000;
uint16 instance_id = 0;
if (zone_id == 0) {
c->Message(Chat::Red, "Invalid zone specified");
return;
}
if (sep->arg[3] && sep->arg[3][0]) {
identifier = sep->arg[3];
}
std::string bucket_key = StringFormat(
"%s-%s-%u-instance",
zone_short_name,
identifier.c_str(),
zone_version
);
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
if (existing_zone_instance.length() > 0) {
instance_id = std::stoi(existing_zone_instance);
c->Message(Chat::Yellow, "Found already created instance (%s) (%u)", zone_short_name, instance_id);
}
if (instance_id == 0) {
if (!database.GetUnusedInstanceID(instance_id)) {
c->Message(Chat::Red, "Server was unable to find a free instance id.");
return;
}
if (!database.CreateInstance(instance_id, zone_id, zone_version, duration)) {
c->Message(Chat::Red, "Server was unable to create a new instance.");
return;
}
c->Message(
Chat::Yellow,
"New private GM instance %s was created with id %lu.",
zone_short_name,
(unsigned long) instance_id
);
DataBucket::SetData(bucket_key, std::to_string(instance_id));
}
if (instance_id > 0) {
float target_x = -1, target_y = -1, target_z = -1, target_heading = -1;
int16 min_status = AccountStatus::Player;
uint8 min_level = 0;
if (!content_db.GetSafePoints(
zone_short_name,
zone_version,
&target_x,
&target_y,
&target_z,
&target_heading,
&min_status,
&min_level
)) {
c->Message(Chat::Red, "Failed to find safe coordinates for specified zone");
}
c->Message(Chat::Yellow, "Zoning to private GM instance (%s) (%u)", zone_short_name, instance_id);
c->AssignToInstance(instance_id);
c->MovePC(zone_id, instance_id, target_x, target_y, target_z, target_heading, 1);
}
}

63
zone/gm_commands/goto.cpp Executable file
View File

@ -0,0 +1,63 @@
#include "../client.h"
void command_goto(Client *c, const Seperator *sep)
{
std::string arg1 = sep->arg[1];
bool goto_via_target_no_args = sep->arg[1][0] == '\0' && c->GetTarget();
bool goto_via_player_name = !sep->IsNumber(1) && !arg1.empty();
bool goto_via_x_y_z = sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3);
if (goto_via_target_no_args) {
c->MovePC(
zone->GetZoneID(),
zone->GetInstanceID(),
c->GetTarget()->GetX(),
c->GetTarget()->GetY(),
c->GetTarget()->GetZ(),
c->GetTarget()->GetHeading()
);
}
else if (goto_via_player_name) {
/**
* Find them in zone first
*/
const char *player_name = sep->arg[1];
std::string player_name_string = sep->arg[1];
Client *client = entity_list.GetClientByName(player_name);
if (client) {
c->MovePC(
zone->GetZoneID(),
zone->GetInstanceID(),
client->GetX(),
client->GetY(),
client->GetZ(),
client->GetHeading()
);
c->Message(Chat::Yellow, "Goto player '%s' same zone", player_name_string.c_str());
}
else if (c->GotoPlayer(player_name_string)) {
c->Message(Chat::Yellow, "Goto player '%s' different zone", player_name_string.c_str());
}
else {
c->Message(Chat::Yellow, "Player '%s' not found", player_name_string.c_str());
}
}
else if (goto_via_x_y_z) {
c->MovePC(
zone->GetZoneID(),
zone->GetInstanceID(),
atof(sep->arg[1]),
atof(sep->arg[2]),
atof(sep->arg[3]),
(sep->arg[4] ? atof(sep->arg[4]) : c->GetHeading())
);
}
else {
c->Message(Chat::White, "Usage: #goto [x y z] [h]");
c->Message(Chat::White, "Usage: #goto [player_name]");
}
}

143
zone/gm_commands/grid.cpp Executable file
View File

@ -0,0 +1,143 @@
#include "../client.h"
void command_grid(Client *c, const Seperator *sep)
{
auto command_type = sep->arg[1];
auto zone_id = zone->GetZoneID();
if (strcasecmp("max", command_type) == 0) {
c->Message(
Chat::White,
fmt::format(
"Highest grid ID in this zone is {}.",
content_db.GetHighestGrid(zone_id)
).c_str()
);
}
else if (strcasecmp("add", command_type) == 0) {
auto grid_id = atoi(sep->arg[2]);
auto wander_type = atoi(sep->arg[3]);
auto pause_type = atoi(sep->arg[4]);
if (!content_db.GridExistsInZone(zone_id, grid_id)) {
content_db.ModifyGrid(c, false, grid_id, wander_type, pause_type, zone_id);
c->Message(
Chat::White,
fmt::format(
"Grid {} added to zone ID {} with wander type {} and pause type {}.",
grid_id,
zone_id,
wander_type,
pause_type
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"Grid {} already exists in zone ID {}.",
grid_id,
zone_id
).c_str()
);
return;
}
}
else if (strcasecmp("show", command_type) == 0) {
Mob *target = c->GetTarget();
if (!target || !target->IsNPC()) {
c->Message(Chat::White, "You need to target an NPC!");
return;
}
auto grid_id = target->CastToNPC()->GetGrid();
std::string query = fmt::format(
"SELECT `x`, `y`, `z`, `heading`, `number` "
"FROM `grid_entries` "
"WHERE `zoneid` = {} AND `gridid` = {} "
"ORDER BY `number`",
zone_id,
grid_id
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
c->Message(Chat::White, "Error querying database.");
c->Message(Chat::White, query.c_str());
}
if (results.RowCount() == 0) {
c->Message(Chat::White, "No grid found.");
return;
}
// Depop any node npc's already spawned
entity_list.DespawnGridNodes(grid_id);
// Spawn grid nodes
std::map<std::vector<float>, int32> zoffset;
for (auto row : results) {
glm::vec4 node_position = glm::vec4(atof(row[0]), atof(row[1]), atof(row[2]), atof(row[3]));
std::vector<float> node_loc{
node_position.x,
node_position.y,
node_position.z
};
// If we already have a node at this location, set the z offset
// higher from the existing one so we can see it. Adjust so if
// there is another at the same spot we adjust again.
auto search = zoffset.find(node_loc);
if (search != zoffset.end()) {
search->second = search->second + 3;
}
else {
zoffset[node_loc] = 0.0;
}
node_position.z += zoffset[node_loc];
NPC::SpawnGridNodeNPC(node_position, grid_id, atoi(row[4]), zoffset[node_loc]);
}
c->Message(
Chat::White,
fmt::format(
"Spawning nodes for grid {}.",
grid_id
).c_str()
);
}
else if (strcasecmp("hide", command_type) == 0) {
Mob *target = c->GetTarget();
if (!target || !target->IsNPC()) {
c->Message(Chat::White, "You need to target an NPC!");
return;
}
auto grid_id = target->CastToNPC()->GetGrid();
entity_list.DespawnGridNodes(grid_id);
c->Message(
Chat::White,
fmt::format(
"Depawning nodes for grid {}.",
grid_id
).c_str()
);
}
else if (strcasecmp("delete", command_type) == 0) {
auto grid_id = atoi(sep->arg[2]);
content_db.ModifyGrid(c, true, grid_id, 0, 0, zone_id);
c->Message(
Chat::White,
fmt::format(
"Grid {} deleted from zone ID {}.",
grid_id,
zone_id
).c_str()
);
}
else {
c->Message(Chat::White, "Usage: #grid [add|delete] [grid_id] [wander_type] [pause_type]");
c->Message(Chat::White, "Usage: #grid [max] - displays the highest grid ID used in this zone (for add)");
c->Message(Chat::White, "Usage: #grid [show] - displays wp nodes as boxes");
}
}

444
zone/gm_commands/guild.cpp Executable file
View File

@ -0,0 +1,444 @@
#include "../client.h"
#include "../worldserver.h"
extern WorldServer worldserver;
#include "../guild_mgr.h"
#include "../doors.h"
void command_guild(Client *c, const Seperator *sep)
{
int admin = c->Admin();
Mob *target = c->GetTarget();
if (strcasecmp(sep->arg[1], "help") == 0) {
c->Message(Chat::White, "GM Guild commands:");
c->Message(Chat::White, " #guild list - lists all guilds on the server");
c->Message(Chat::White, " #guild create {guildleader charname or CharID} guildname");
c->Message(Chat::White, " #guild delete guildID");
c->Message(Chat::White, " #guild rename guildID newname");
c->Message(Chat::White, " #guild set charname guildID (0=no guild)");
c->Message(Chat::White, " #guild setrank charname rank");
c->Message(Chat::White, " #guild setleader guildID {guildleader charname or CharID}");
}
else if (strcasecmp(sep->arg[1], "status") == 0 || strcasecmp(sep->arg[1], "stat") == 0) {
Client *client = 0;
if (sep->arg[2][0] != 0) {
client = entity_list.GetClientByName(sep->argplus[2]);
}
else if (target != 0 && target->IsClient()) {
client = target->CastToClient();
}
if (client == 0) {
c->Message(Chat::White, "You must target someone or specify a character name");
}
else if ((client->Admin() >= minStatusToEditOtherGuilds && admin < minStatusToEditOtherGuilds) &&
client->GuildID() != c->GuildID()) { // no peeping for GMs, make sure tell message stays the same
c->Message(Chat::White, "You must target someone or specify a character name.");
}
else {
if (client->IsInAGuild()) {
c->Message(Chat::White, "%s is not in a guild.", client->GetName());
}
else if (guild_mgr.IsGuildLeader(client->GuildID(), client->CharacterID())) {
c->Message(
Chat::White,
"%s is the leader of <%s> rank: %s",
client->GetName(),
guild_mgr.GetGuildName(client->GuildID()),
guild_mgr.GetRankName(client->GuildID(), client->GuildRank()));
}
else {
c->Message(
Chat::White,
"%s is a member of <%s> rank: %s",
client->GetName(),
guild_mgr.GetGuildName(client->GuildID()),
guild_mgr.GetRankName(client->GuildID(), client->GuildRank()));
}
}
}
else if (strcasecmp(sep->arg[1], "info") == 0) {
if (sep->arg[2][0] == 0 && c->IsInAGuild()) {
if (admin >= minStatusToEditOtherGuilds) {
c->Message(Chat::White, "Usage: #guildinfo guild_id");
}
else {
c->Message(Chat::White, "You're not in a guild");
}
}
else {
uint32 tmp = GUILD_NONE;
if (sep->arg[2][0] == 0) {
tmp = c->GuildID();
}
else if (admin >= minStatusToEditOtherGuilds) {
tmp = atoi(sep->arg[2]);
}
if (tmp != GUILD_NONE) {
guild_mgr.DescribeGuild(c, tmp);
}
}
}
else if (strcasecmp(sep->arg[1], "set") == 0) {
if (!sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #guild set charname guildgbid (0 = clear guildtag)");
}
else {
uint32 guild_id = atoi(sep->arg[3]);
if (guild_id == 0) {
guild_id = GUILD_NONE;
}
else if (!guild_mgr.GuildExists(guild_id)) {
c->Message(Chat::Red, "Guild %d does not exist.", guild_id);
return;
}
uint32 charid = database.GetCharacterID(sep->arg[2]);
if (charid == 0) {
c->Message(Chat::Red, "Unable to find character '%s'", charid);
return;
}
//we could do the checking we need for guild_mgr.CheckGMStatus, but im lazy right now
if (admin < minStatusToEditOtherGuilds) {
c->Message(Chat::Red, "Access denied.");
return;
}
if (guild_id == GUILD_NONE) {
LogGuilds("[{}]: Removing [{}] ([{}]) from guild with GM command", c->GetName(), sep->arg[2], charid);
}
else {
LogGuilds("[{}]: Putting [{}] ([{}]) into guild [{}] ([{}]) with GM command",
c->GetName(),
sep->arg[2],
charid,
guild_mgr.GetGuildName(guild_id),
guild_id);
}
if (!guild_mgr.SetGuild(charid, guild_id, GUILD_MEMBER)) {
c->Message(Chat::Red, "Error putting '%s' into guild %d", sep->arg[2], guild_id);
}
else {
c->Message(Chat::White, "%s has been put into guild %d", sep->arg[2], guild_id);
}
}
}
/*else if (strcasecmp(sep->arg[1], "setdoor") == 0 && admin >= minStatusToEditOtherGuilds) {
if (!sep->IsNumber(2))
c->Message(Chat::White, "Usage: #guild setdoor guildEQid (0 = delete guilddoor)");
else {
// guild doors
if((!guilds[atoi(sep->arg[2])].databaseID) && (atoi(sep->arg[2])!=0) )
{
c->Message(Chat::White, "These is no guild with this guildEQid");
}
else {
c->SetIsSettingGuildDoor(true);
c->Message(Chat::White, "Click on a door you want to become a guilddoor");
c->SetSetGuildDoorID(atoi(sep->arg[2]));
}
}
}*/
else if (strcasecmp(sep->arg[1], "setrank") == 0) {
int rank = atoi(sep->arg[3]);
if (!sep->IsNumber(3)) {
c->Message(Chat::White, "Usage: #guild setrank charname rank");
}
else if (rank < 0 || rank > GUILD_MAX_RANK) {
c->Message(Chat::White, "Error: invalid rank #.");
}
else {
uint32 charid = database.GetCharacterID(sep->arg[2]);
if (charid == 0) {
c->Message(Chat::Red, "Unable to find character '%s'", charid);
return;
}
//we could do the checking we need for guild_mgr.CheckGMStatus, but im lazy right now
if (admin < minStatusToEditOtherGuilds) {
c->Message(Chat::Red, "Access denied.");
return;
}
LogGuilds("[{}]: Setting [{}] ([{}])'s guild rank to [{}] with GM command",
c->GetName(),
sep->arg[2],
charid,
rank);
if (!guild_mgr.SetGuildRank(charid, rank)) {
c->Message(Chat::Red, "Error while setting rank %d on '%s'.", rank, sep->arg[2]);
}
else {
c->Message(Chat::White, "%s has been set to rank %d", sep->arg[2], rank);
}
}
}
else if (strcasecmp(sep->arg[1], "create") == 0) {
if (sep->arg[3][0] == 0) {
c->Message(Chat::White, "Usage: #guild create {guildleader charname or CharID} guild name");
}
else if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server dirconnected");
}
else {
uint32 leader = 0;
if (sep->IsNumber(2)) {
leader = atoi(sep->arg[2]);
}
else if ((leader = database.GetCharacterID(sep->arg[2])) != 0) {
//got it from the db..
}
else {
c->Message(Chat::Red, "Unable to find char '%s'", sep->arg[2]);
return;
}
if (leader == 0) {
c->Message(Chat::White, "Guild leader not found.");
return;
}
uint32 tmp = guild_mgr.FindGuildByLeader(leader);
if (tmp != GUILD_NONE) {
c->Message(
Chat::White,
"Error: %s already is the leader of DB# %i '%s'.",
sep->arg[2],
tmp,
guild_mgr.GetGuildName(tmp));
}
else {
if (admin < minStatusToEditOtherGuilds) {
c->Message(Chat::Red, "Access denied.");
return;
}
uint32 id = guild_mgr.CreateGuild(sep->argplus[3], leader);
LogGuilds("[{}]: Creating guild [{}] with leader [{}] with GM command. It was given id [{}]",
c->GetName(),
sep->argplus[3],
leader,
(unsigned long) id);
if (id == GUILD_NONE) {
c->Message(Chat::White, "Guild creation failed.");
}
else {
c->Message(Chat::White, "Guild created: Leader: %i, number %i: %s", leader, id, sep->argplus[3]);
if (!guild_mgr.SetGuild(leader, id, GUILD_LEADER)) {
c->Message(
Chat::White,
"Unable to set guild leader's guild in the database. Your going to have to run #guild set"
);
}
}
}
}
}
else if (strcasecmp(sep->arg[1], "delete") == 0) {
if (!sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #guild delete guildID");
}
else if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server dirconnected");
}
else {
uint32 id = atoi(sep->arg[2]);
if (!guild_mgr.GuildExists(id)) {
c->Message(Chat::White, "Guild %d does not exist!", id);
return;
}
if (admin < minStatusToEditOtherGuilds) {
//this person is not allowed to just edit any guild, check this guild's min status.
if (c->GuildID() != id) {
c->Message(Chat::Red, "Access denied to edit other people's guilds");
return;
}
else if (!guild_mgr.CheckGMStatus(id, admin)) {
c->Message(Chat::Red, "Access denied to edit your guild with GM commands.");
return;
}
}
LogGuilds("[{}]: Deleting guild [{}] ([{}]) with GM command", c->GetName(),
guild_mgr.GetGuildName(id), id);
if (!guild_mgr.DeleteGuild(id)) {
c->Message(Chat::White, "Guild delete failed.");
}
else {
c->Message(Chat::White, "Guild %d deleted.", id);
}
}
}
else if (strcasecmp(sep->arg[1], "rename") == 0) {
if ((!sep->IsNumber(2)) || sep->arg[3][0] == 0) {
c->Message(Chat::White, "Usage: #guild rename guildID newname");
}
else if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server dirconnected");
}
else {
uint32 id = atoi(sep->arg[2]);
if (!guild_mgr.GuildExists(id)) {
c->Message(Chat::White, "Guild %d does not exist!", id);
return;
}
if (admin < minStatusToEditOtherGuilds) {
//this person is not allowed to just edit any guild, check this guild's min status.
if (c->GuildID() != id) {
c->Message(Chat::Red, "Access denied to edit other people's guilds");
return;
}
else if (!guild_mgr.CheckGMStatus(id, admin)) {
c->Message(Chat::Red, "Access denied to edit your guild with GM commands.");
return;
}
}
LogGuilds("[{}]: Renaming guild [{}] ([{}]) to [{}] with GM command", c->GetName(),
guild_mgr.GetGuildName(id), id, sep->argplus[3]);
if (!guild_mgr.RenameGuild(id, sep->argplus[3])) {
c->Message(Chat::White, "Guild rename failed.");
}
else {
c->Message(Chat::White, "Guild %d renamed to %s", id, sep->argplus[3]);
}
}
}
else if (strcasecmp(sep->arg[1], "setleader") == 0) {
if (sep->arg[3][0] == 0 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #guild setleader guild_id {guildleader charname or CharID}");
}
else if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server dirconnected");
}
else {
uint32 leader = 0;
if (sep->IsNumber(2)) {
leader = atoi(sep->arg[2]);
}
else if ((leader = database.GetCharacterID(sep->arg[2])) != 0) {
//got it from the db..
}
else {
c->Message(Chat::Red, "Unable to find char '%s'", sep->arg[2]);
return;
}
uint32 tmpdb = guild_mgr.FindGuildByLeader(leader);
if (leader == 0) {
c->Message(Chat::White, "New leader not found.");
}
else if (tmpdb != 0) {
c->Message(Chat::White, "Error: %s already is the leader of guild # %i", sep->arg[2], tmpdb);
}
else {
uint32 id = atoi(sep->arg[2]);
if (!guild_mgr.GuildExists(id)) {
c->Message(Chat::White, "Guild %d does not exist!", id);
return;
}
if (admin < minStatusToEditOtherGuilds) {
//this person is not allowed to just edit any guild, check this guild's min status.
if (c->GuildID() != id) {
c->Message(Chat::Red, "Access denied to edit other people's guilds");
return;
}
else if (!guild_mgr.CheckGMStatus(id, admin)) {
c->Message(Chat::Red, "Access denied to edit your guild with GM commands.");
return;
}
}
LogGuilds("[{}]: Setting leader of guild [{}] ([{}]) to [{}] with GM command", c->GetName(),
guild_mgr.GetGuildName(id), id, leader);
if (!guild_mgr.SetGuildLeader(id, leader)) {
c->Message(Chat::White, "Guild leader change failed.");
}
else {
c->Message(Chat::White, "Guild leader changed: guild # %d, Leader: %s", id, sep->argplus[3]);
}
}
}
}
else if (strcasecmp(sep->arg[1], "list") == 0) {
if (admin < minStatusToEditOtherGuilds) {
c->Message(Chat::Red, "Access denied.");
return;
}
guild_mgr.ListGuilds(c);
}
else {
c->Message(Chat::White, "Unknown guild command, try #guild help");
}
}
/*
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value) {
struct GuildRankLevel_Struct grl;
strcpy(grl.rankname, guild_mgr.GetRankName(eqid, rank));
grl.demote = guilds[eqid].rank[rank].demote;
grl.heargu = guilds[eqid].rank[rank].heargu;
grl.invite = guilds[eqid].rank[rank].invite;
grl.motd = guilds[eqid].rank[rank].motd;
grl.promote = guilds[eqid].rank[rank].promote;
grl.remove = guilds[eqid].rank[rank].remove;
grl.speakgu = guilds[eqid].rank[rank].speakgu;
grl.warpeace = guilds[eqid].rank[rank].warpeace;
if (strcasecmp(what, "title") == 0) {
if (strlen(value) > 100)
c->Message(Chat::White, "Error: Title has a maxium length of 100 characters.");
else
strcpy(grl.rankname, value);
}
else if (rank == 0)
c->Message(Chat::White, "Error: Rank 0's permissions can not be changed.");
else {
if (!(strlen(value) == 1 && (value[0] == '0' || value[0] == '1')))
return false;
if (strcasecmp(what, "demote") == 0)
grl.demote = (value[0] == '1');
else if (strcasecmp(what, "heargu") == 0)
grl.heargu = (value[0] == '1');
else if (strcasecmp(what, "invite") == 0)
grl.invite = (value[0] == '1');
else if (strcasecmp(what, "motd") == 0)
grl.motd = (value[0] == '1');
else if (strcasecmp(what, "promote") == 0)
grl.promote = (value[0] == '1');
else if (strcasecmp(what, "remove") == 0)
grl.remove = (value[0] == '1');
else if (strcasecmp(what, "speakgu") == 0)
grl.speakgu = (value[0] == '1');
else if (strcasecmp(what, "warpeace") == 0)
grl.warpeace = (value[0] == '1');
else
c->Message(Chat::White, "Error: Permission name not recognized.");
}
if (!database.EditGuild(dbid, rank, &grl))
c->Message(Chat::White, "Error: database.EditGuild() failed");
return true;
}*/

View File

@ -0,0 +1,8 @@
#include "../client.h"
#include "../guild_mgr.h"
void command_guildapprove(Client *c, const Seperator *sep)
{
guild_mgr.AddMemberApproval(atoi(sep->arg[1]), c);
}

View File

@ -0,0 +1,13 @@
#include "../client.h"
#include "../guild_mgr.h"
void command_guildcreate(Client *c, const Seperator *sep)
{
if (strlen(sep->argplus[1]) > 4 && strlen(sep->argplus[1]) < 16) {
guild_mgr.AddGuildApproval(sep->argplus[1], c);
}
else {
c->Message(Chat::White, "Guild name must be more than 4 characters and less than 16.");
}
}

14
zone/gm_commands/guildlist.cpp Executable file
View File

@ -0,0 +1,14 @@
#include "../client.h"
#include "../guild_mgr.h"
void command_guildlist(Client *c, const Seperator *sep)
{
GuildApproval *tmp = guild_mgr.FindGuildByIDApproval(atoi(sep->arg[1]));
if (tmp) {
tmp->ApprovedMembers(c);
}
else {
c->Message(Chat::White, "Could not find reference id.");
}
}

37
zone/gm_commands/hair.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_hair(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #hair [number of hair style]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = atoi(sep->arg[1]);
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Hair = %i", atoi(sep->arg[1]));
}
}

37
zone/gm_commands/haircolor.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_haircolor(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #haircolor [number of hair color]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = atoi(sep->arg[1]);
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Hair Color = %i", atoi(sep->arg[1]));
}
}

20
zone/gm_commands/haste.cpp Executable file
View File

@ -0,0 +1,20 @@
#include "../client.h"
void command_haste(Client *c, const Seperator *sep)
{
// #haste command to set client attack speed. Takes a percentage (100 = twice normal attack speed)
if (sep->arg[1][0] != 0) {
uint16 Haste = atoi(sep->arg[1]);
if (Haste > 85) {
Haste = 85;
}
c->SetExtraHaste(Haste);
// SetAttackTimer must be called to make this take effect, so player needs to change
// the primary weapon.
c->Message(Chat::White, "Haste set to %d%% - Need to re-equip primary weapon before it takes effect", Haste);
}
else {
c->Message(Chat::White, "Usage: #haste [percentage]");
}
}

15
zone/gm_commands/hatelist.cpp Executable file
View File

@ -0,0 +1,15 @@
#include "../client.h"
void command_hatelist(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (target == nullptr) {
c->Message(Chat::White, "Error: you must have a target.");
return;
}
c->Message(Chat::White, "Display hate list for %s..", target->GetName());
target->PrintHateListToClient(c);
}

21
zone/gm_commands/heal.cpp Executable file
View File

@ -0,0 +1,21 @@
#include "../client.h"
void command_heal(Client *c, const Seperator *sep)
{
auto target = c->GetTarget() ? c->GetTarget() : c;
target->Heal();
if (c != target) {
c->Message(
Chat::White,
fmt::format(
"Healed {} ({}) to full.",
target->GetCleanName(),
target->GetID()
).c_str()
);
}
else {
c->Message(Chat::White, "Healed yourself to full.");
}
}

37
zone/gm_commands/helm.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_helm(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #helm [number of helm texture]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = atoi(sep->arg[1]);
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Helm = %i", atoi(sep->arg[1]));
}
}

37
zone/gm_commands/heritage.cpp Executable file
View File

@ -0,0 +1,37 @@
#include "../client.h"
void command_heritage(Client *c, const Seperator *sep)
{
Mob *target = c->GetTarget();
if (!sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #heritage [number of Drakkin heritage]");
}
else if (!target) {
c->Message(Chat::White, "Error: this command requires a target");
}
else {
uint16 Race = target->GetRace();
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = target->GetHairColor();
uint8 BeardColor = target->GetBeardColor();
uint8 EyeColor1 = target->GetEyeColor1();
uint8 EyeColor2 = target->GetEyeColor2();
uint8 HairStyle = target->GetHairStyle();
uint8 LuclinFace = target->GetLuclinFace();
uint8 Beard = target->GetBeard();
uint32 DrakkinHeritage = atoi(sep->arg[1]);
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
uint32 DrakkinDetails = target->GetDrakkinDetails();
target->SendIllusionPacket(
Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails
);
c->Message(Chat::White, "Heritage = %i", atoi(sep->arg[1]));
}
}

35
zone/gm_commands/heromodel.cpp Executable file
View File

@ -0,0 +1,35 @@
#include "../client.h"
void command_heromodel(Client *c, const Seperator *sep)
{
if (sep->argnum < 1) {
c->Message(Chat::White, "Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63)");
}
else if (c->GetTarget() == nullptr) {
c->Message(Chat::Red, "You must have a target to do a wear change for Hero's Forge Models.");
}
else {
uint32 hero_forge_model = atoi(sep->arg[1]);
if (sep->argnum > 1) {
uint8 wearslot = (uint8) atoi(sep->arg[2]);
c->GetTarget()->SendTextureWC(wearslot, 0, hero_forge_model, 0, 0, 0);
}
else {
if (hero_forge_model > 0) {
// 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 wearslot = 0; wearslot < 7; wearslot++) {
c->GetTarget()->SendTextureWC(wearslot, 0, (hero_forge_model + wearslot), 0, 0, 0);
}
}
else {
c->Message(Chat::Red, "Hero's Forge Model must be greater than 0.");
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More