[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

@ -1,293 +1,576 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.2) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(zone_sources SET(zone_sources
aa.cpp aa.cpp
aa_ability.cpp aa_ability.cpp
aggro.cpp aggro.cpp
aggromanager.cpp aggromanager.cpp
api_service.cpp api_service.cpp
attack.cpp attack.cpp
aura.cpp aura.cpp
beacon.cpp beacon.cpp
bonuses.cpp bonuses.cpp
bot.cpp bot.cpp
bot_command.cpp bot_command.cpp
bot_database.cpp bot_database.cpp
botspellsai.cpp botspellsai.cpp
cheat_manager.cpp cheat_manager.cpp
client.cpp client.cpp
client_mods.cpp client_mods.cpp
client_packet.cpp client_packet.cpp
client_process.cpp client_process.cpp
command.cpp command.cpp
corpse.cpp corpse.cpp
data_bucket.cpp data_bucket.cpp
doors.cpp doors.cpp
dialogue_window.cpp dialogue_window.cpp
dynamic_zone.cpp dynamic_zone.cpp
effects.cpp effects.cpp
embparser.cpp embparser.cpp
embparser_api.cpp embparser_api.cpp
embperl.cpp embperl.cpp
embxs.cpp embxs.cpp
encounter.cpp encounter.cpp
entity.cpp entity.cpp
exp.cpp exp.cpp
expedition.cpp expedition.cpp
expedition_database.cpp expedition_database.cpp
expedition_request.cpp expedition_request.cpp
fastmath.cpp fastmath.cpp
fearpath.cpp fearpath.cpp
forage.cpp forage.cpp
groups.cpp groups.cpp
guild.cpp guild.cpp
guild_mgr.cpp guild_mgr.cpp
hate_list.cpp hate_list.cpp
heal_rotation.cpp heal_rotation.cpp
horse.cpp horse.cpp
inventory.cpp inventory.cpp
loottables.cpp loottables.cpp
lua_bot.cpp lua_bot.cpp
lua_bit.cpp lua_bit.cpp
lua_corpse.cpp lua_corpse.cpp
lua_client.cpp lua_client.cpp
lua_door.cpp lua_door.cpp
lua_encounter.cpp lua_encounter.cpp
lua_entity.cpp lua_entity.cpp
lua_entity_list.cpp lua_entity_list.cpp
lua_expedition.cpp lua_expedition.cpp
lua_general.cpp lua_general.cpp
lua_group.cpp lua_group.cpp
lua_hate_list.cpp lua_hate_list.cpp
lua_inventory.cpp lua_inventory.cpp
lua_item.cpp lua_item.cpp
lua_iteminst.cpp lua_iteminst.cpp
lua_mob.cpp lua_mob.cpp
lua_mod.cpp lua_mod.cpp
lua_npc.cpp lua_npc.cpp
lua_object.cpp lua_object.cpp
lua_packet.cpp lua_packet.cpp
lua_parser.cpp lua_parser.cpp
lua_parser_events.cpp lua_parser_events.cpp
lua_raid.cpp lua_raid.cpp
lua_spawn.cpp lua_spawn.cpp
lua_spell.cpp lua_spell.cpp
lua_stat_bonuses.cpp lua_stat_bonuses.cpp
embperl.cpp embperl.cpp
embxs.cpp embxs.cpp
entity.cpp entity.cpp
exp.cpp exp.cpp
fearpath.cpp fearpath.cpp
forage.cpp forage.cpp
global_loot_manager.cpp global_loot_manager.cpp
gm_commands/door_manipulation.cpp gm_commands/door_manipulation.cpp
groups.cpp groups.cpp
guild.cpp guild.cpp
guild_mgr.cpp guild_mgr.cpp
hate_list.cpp hate_list.cpp
horse.cpp horse.cpp
inventory.cpp inventory.cpp
loottables.cpp loottables.cpp
main.cpp main.cpp
map.cpp map.cpp
merc.cpp merc.cpp
mob.cpp mob.cpp
mob_ai.cpp mob_ai.cpp
mob_appearance.cpp mob_appearance.cpp
mob_movement_manager.cpp mob_movement_manager.cpp
mob_info.cpp mob_info.cpp
mod_functions.cpp mod_functions.cpp
npc.cpp npc.cpp
npc_ai.cpp npc_ai.cpp
npc_scale_manager.cpp npc_scale_manager.cpp
object.cpp object.cpp
oriented_bounding_box.cpp oriented_bounding_box.cpp
pathfinder_interface.cpp pathfinder_interface.cpp
pathfinder_nav_mesh.cpp pathfinder_nav_mesh.cpp
pathfinder_null.cpp pathfinder_null.cpp
pathing.cpp pathing.cpp
perl_bot.cpp perl_bot.cpp
perl_client.cpp perl_client.cpp
perl_doors.cpp perl_doors.cpp
perl_entity.cpp perl_entity.cpp
perl_expedition.cpp perl_expedition.cpp
perl_groups.cpp perl_groups.cpp
perl_hateentry.cpp perl_hateentry.cpp
perl_inventory.cpp perl_inventory.cpp
perl_mob.cpp perl_mob.cpp
perl_npc.cpp perl_npc.cpp
perl_object.cpp perl_object.cpp
perl_perlpacket.cpp perl_perlpacket.cpp
perl_player_corpse.cpp perl_player_corpse.cpp
perl_questitem.cpp perl_questitem.cpp
perl_raids.cpp perl_raids.cpp
perl_spell.cpp perl_spell.cpp
perlpacket.cpp perlpacket.cpp
petitions.cpp petitions.cpp
pets.cpp pets.cpp
position.cpp position.cpp
qglobals.cpp qglobals.cpp
queryserv.cpp queryserv.cpp
questmgr.cpp questmgr.cpp
quest_parser_collection.cpp quest_parser_collection.cpp
raids.cpp raids.cpp
raycast_mesh.cpp raycast_mesh.cpp
shared_task_zone_messaging.cpp shared_task_zone_messaging.cpp
spawn2.cpp spawn2.cpp
spawn2.h spawn2.h
spawngroup.cpp spawngroup.cpp
special_attacks.cpp special_attacks.cpp
spell_effects.cpp spell_effects.cpp
spells.cpp spells.cpp
task_client_state.cpp task_client_state.cpp
task_goal_list_manager.cpp task_goal_list_manager.cpp
task_manager.cpp task_manager.cpp
task_proximity_manager.cpp task_proximity_manager.cpp
tasks.cpp tasks.cpp
titles.cpp titles.cpp
tradeskills.cpp tradeskills.cpp
trading.cpp trading.cpp
trap.cpp trap.cpp
tribute.cpp tribute.cpp
tune.cpp tune.cpp
water_map.cpp water_map.cpp
water_map_v1.cpp water_map_v1.cpp
water_map_v2.cpp water_map_v2.cpp
waypoints.cpp waypoints.cpp
worldserver.cpp worldserver.cpp
xtargetautohaters.cpp xtargetautohaters.cpp
zone.cpp zone.cpp
zone_config.cpp zone_config.cpp
zonedb.cpp zonedb.cpp
zone_event_scheduler.cpp zone_event_scheduler.cpp
zone_reload.cpp zone_reload.cpp
zone_store.cpp zone_store.cpp
zoning.cpp zoning.cpp
) )
SET(zone_headers SET(zone_headers
aa.h aa.h
aa_ability.h aa_ability.h
aggromanager.h aggromanager.h
api_service.h api_service.h
aura.h aura.h
basic_functions.h basic_functions.h
beacon.h beacon.h
bot.h bot.h
bot_command.h bot_command.h
bot_database.h bot_database.h
bot_structs.h bot_structs.h
cheat_manager.h cheat_manager.h
client.h client.h
client_packet.h client_packet.h
command.h command.h
common.h common.h
corpse.h corpse.h
data_bucket.h data_bucket.h
doors.h doors.h
dialogue_window.h dialogue_window.h
dynamic_zone.h dynamic_zone.h
embparser.h embparser.h
embperl.h embperl.h
embxs.h embxs.h
encounter.h encounter.h
entity.h entity.h
errmsg.h errmsg.h
event_codes.h event_codes.h
expedition.h expedition.h
expedition_database.h expedition_database.h
expedition_request.h expedition_request.h
fastmath.h fastmath.h
forage.h forage.h
global_loot_manager.h global_loot_manager.h
gm_commands/door_manipulation.h gm_commands/door_manipulation.h
groups.h groups.h
guild_mgr.h guild_mgr.h
hate_list.h hate_list.h
heal_rotation.h heal_rotation.h
horse.h horse.h
lua_bot.h lua_bot.h
lua_bit.h lua_bit.h
lua_client.h lua_client.h
lua_corpse.h lua_corpse.h
lua_door.h lua_door.h
lua_encounter.h lua_encounter.h
lua_entity.h lua_entity.h
lua_entity_list.h lua_entity_list.h
lua_expedition.h lua_expedition.h
lua_general.h lua_general.h
lua_group.h lua_group.h
lua_hate_list.h lua_hate_list.h
lua_inventory.h lua_inventory.h
lua_item.h lua_item.h
lua_iteminst.h lua_iteminst.h
lua_mob.h lua_mob.h
lua_mod.h lua_mod.h
lua_npc.h lua_npc.h
lua_object.h lua_object.h
lua_packet.h lua_packet.h
lua_parser.h lua_parser.h
lua_parser_events.h lua_parser_events.h
lua_ptr.h lua_ptr.h
lua_raid.h lua_raid.h
lua_spawn.h lua_spawn.h
lua_spell.h lua_spell.h
lua_stat_bonuses.h lua_stat_bonuses.h
map.h map.h
masterentity.h masterentity.h
maxskill.h maxskill.h
message.h message.h
merc.h merc.h
mob.h mob.h
mob_movement_manager.h mob_movement_manager.h
npc.h npc.h
npc_ai.h npc_ai.h
npc_scale_manager.h npc_scale_manager.h
object.h object.h
oriented_bounding_box.h oriented_bounding_box.h
pathfinder_interface.h pathfinder_interface.h
pathfinder_nav_mesh.h pathfinder_nav_mesh.h
pathfinder_null.h pathfinder_null.h
perlpacket.h perlpacket.h
petitions.h petitions.h
pets.h pets.h
position.h position.h
qglobals.h qglobals.h
quest_interface.h quest_interface.h
queryserv.h queryserv.h
quest_interface.h quest_interface.h
questmgr.h questmgr.h
quest_parser_collection.h quest_parser_collection.h
raids.h raids.h
raycast_mesh.h raycast_mesh.h
skills.h skills.h
shared_task_zone_messaging.h shared_task_zone_messaging.h
spawn2.cpp spawn2.cpp
spawn2.h spawn2.h
spawngroup.h spawngroup.h
string_ids.h string_ids.h
task_client_state.h task_client_state.h
task_goal_list_manager.h task_goal_list_manager.h
task_manager.h task_manager.h
task_proximity_manager.h task_proximity_manager.h
tasks.h tasks.h
titles.h titles.h
trap.h trap.h
water_map.h water_map.h
water_map_v1.h water_map_v1.h
water_map_v2.h water_map_v2.h
worldserver.h worldserver.h
xtargetautohaters.h xtargetautohaters.h
zone.h zone.h
zone_event_scheduler.h zone_event_scheduler.h
zone_config.h zone_config.h
zonedb.h zonedb.h
zonedump.h zonedump.h
zone_reload.h zone_reload.h
zone_store.h zone_store.h
)
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}) 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
@ -25,18 +6,18 @@ class Seperator;
#include "../common/types.h" #include "../common/types.h"
#define COMMAND_CHAR '#' #define COMMAND_CHAR '#'
typedef void (*CmdFuncPtr)(Client *,const Seperator *); typedef void (*CmdFuncPtr)(Client *, const Seperator *);
typedef struct { typedef struct {
int access; int access;
const char *desc; // description of command const char *desc; // description of command
CmdFuncPtr function; // null means perl function CmdFuncPtr function; // null means perl function
} CommandRecord; } CommandRecord;
extern int (*command_dispatch)(Client *,char const*); extern int (*command_dispatch)(Client *, char const *);
extern int commandcount; // number of commands loaded extern int commandcount; // number of commands loaded
// the command system: // the command system:
int command_init(void); int command_init(void);
@ -59,7 +40,7 @@ void command_augmentitem(Client *c, const Seperator *sep);
void command_ban(Client *c, const Seperator *sep); void command_ban(Client *c, const Seperator *sep);
void command_beard(Client *c, const Seperator *sep); void command_beard(Client *c, const Seperator *sep);
void command_beardcolor(Client *c, const Seperator *sep); void command_beardcolor(Client *c, const Seperator *sep);
void command_bind(Client* c, const Seperator *sep); void command_bind(Client *c, const Seperator *sep);
void command_camerashake(Client *c, const Seperator *sep); void command_camerashake(Client *c, const Seperator *sep);
void command_castspell(Client *c, const Seperator *sep); void command_castspell(Client *c, const Seperator *sep);
void command_chat(Client *c, const Seperator *sep); void command_chat(Client *c, const Seperator *sep);
@ -87,10 +68,10 @@ void command_doanim(Client *c, const Seperator *sep);
void command_dye(Client *c, const Seperator *sep); void command_dye(Client *c, const Seperator *sep);
void command_dz(Client *c, const Seperator *sep); void command_dz(Client *c, const Seperator *sep);
void command_dzkickplayers(Client *c, const Seperator *sep); void command_dzkickplayers(Client *c, const Seperator *sep);
void command_editmassrespawn(Client* c, const Seperator* sep); void command_editmassrespawn(Client *c, const Seperator *sep);
void command_emote(Client *c, const Seperator *sep); void command_emote(Client *c, const Seperator *sep);
void command_emotesearch(Client* c, const Seperator *sep); void command_emotesearch(Client *c, const Seperator *sep);
void command_emoteview(Client* c, const Seperator *sep); void command_emoteview(Client *c, const Seperator *sep);
void command_emptyinventory(Client *c, const Seperator *sep); void command_emptyinventory(Client *c, const Seperator *sep);
void command_enablerecipe(Client *c, const Seperator *sep); void command_enablerecipe(Client *c, const Seperator *sep);
void command_endurance(Client *c, const Seperator *sep); void command_endurance(Client *c, const Seperator *sep);
@ -121,14 +102,14 @@ void command_getvariable(Client *c, const Seperator *sep);
void command_ginfo(Client *c, const Seperator *sep); void command_ginfo(Client *c, const Seperator *sep);
void command_giveitem(Client *c, const Seperator *sep); void command_giveitem(Client *c, const Seperator *sep);
void command_givemoney(Client *c, const Seperator *sep); void command_givemoney(Client *c, const Seperator *sep);
void command_globalview(Client* c, const Seperator *sep); void command_globalview(Client *c, const Seperator *sep);
void command_gm(Client *c, const Seperator *sep); void command_gm(Client *c, const Seperator *sep);
void command_gmspeed(Client *c, const Seperator *sep); void command_gmspeed(Client *c, const Seperator *sep);
void command_gmzone(Client *c, const Seperator *sep); void command_gmzone(Client *c, const Seperator *sep);
void command_goto(Client *c, const Seperator *sep); void command_goto(Client *c, const Seperator *sep);
void command_grid(Client *c, const Seperator *sep); void command_grid(Client *c, const Seperator *sep);
void command_guild(Client *c, const Seperator *sep); void command_guild(Client *c, const Seperator *sep);
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value); bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char *what, const char *value);
void command_guildapprove(Client *c, const Seperator *sep); void command_guildapprove(Client *c, const Seperator *sep);
void command_guildcreate(Client *c, const Seperator *sep); void command_guildcreate(Client *c, const Seperator *sep);
void command_guildlist(Client *c, const Seperator *sep); void command_guildlist(Client *c, const Seperator *sep);
@ -193,12 +174,14 @@ void command_npcspecialattk(Client *c, const Seperator *sep);
void command_npcstats(Client *c, const Seperator *sep); void command_npcstats(Client *c, const Seperator *sep);
void command_npctype_cache(Client *c, const Seperator *sep); void command_npctype_cache(Client *c, const Seperator *sep);
void command_npctypespawn(Client *c, const Seperator *sep); void command_npctypespawn(Client *c, const Seperator *sep);
void command_nudge(Client* c, const Seperator* sep); void command_nudge(Client *c, const Seperator *sep);
void command_nukebuffs(Client *c, const Seperator *sep); void command_nukebuffs(Client *c, const Seperator *sep);
void command_nukeitem(Client *c, const Seperator *sep); 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);
@ -225,24 +208,24 @@ void command_pvp(Client *c, const Seperator *sep);
void command_qglobal(Client *c, const Seperator *sep); void command_qglobal(Client *c, const Seperator *sep);
void command_questerrors(Client *c, const Seperator *sep); void command_questerrors(Client *c, const Seperator *sep);
void command_race(Client *c, const Seperator *sep); void command_race(Client *c, const Seperator *sep);
void command_raidloot(Client* c, const Seperator *sep); void command_raidloot(Client *c, const Seperator *sep);
void command_randomfeatures(Client *c, const Seperator *sep); void command_randomfeatures(Client *c, const Seperator *sep);
void command_refreshgroup(Client *c, const Seperator *sep); void command_refreshgroup(Client *c, const Seperator *sep);
void command_reloadaa(Client *c, const Seperator *sep); void command_reloadaa(Client *c, const Seperator *sep);
void command_reloadallrules(Client *c, const Seperator *sep); void command_reloadallrules(Client *c, const Seperator *sep);
void command_reloademote(Client* c, const Seperator *sep); void command_reloademote(Client *c, const Seperator *sep);
void command_reloadlevelmods(Client *c, const Seperator *sep); void command_reloadlevelmods(Client *c, const Seperator *sep);
void command_reloadmerchants(Client *c, const Seperator *sep); void command_reloadmerchants(Client *c, const Seperator *sep);
void command_reloadperlexportsettings(Client *c, const Seperator *sep); void command_reloadperlexportsettings(Client *c, const Seperator *sep);
void command_reloadqst(Client *c, const Seperator *sep); void command_reloadqst(Client *c, const Seperator *sep);
void command_reloadstatic(Client *c, const Seperator *sep); void command_reloadstatic(Client *c, const Seperator *sep);
void command_reloadtitles(Client *c, const Seperator *sep); void command_reloadtitles(Client *c, const Seperator *sep);
void command_reloadtraps(Client* c, const Seperator *sep); void command_reloadtraps(Client *c, const Seperator *sep);
void command_reloadworld(Client *c, const Seperator *sep); void command_reloadworld(Client *c, const Seperator *sep);
void command_reloadworldrules(Client *c, const Seperator *sep); void command_reloadworldrules(Client *c, const Seperator *sep);
void command_reloadzps(Client *c, const Seperator *sep); void command_reloadzps(Client *c, const Seperator *sep);
void command_repop(Client *c, const Seperator *sep); void command_repop(Client *c, const Seperator *sep);
void command_resetaa(Client* c,const Seperator *sep); void command_resetaa(Client *c, const Seperator *sep);
void command_resetaa_timer(Client *c, const Seperator *sep); void command_resetaa_timer(Client *c, const Seperator *sep);
void command_resetdisc_timer(Client *c, const Seperator *sep); void command_resetdisc_timer(Client *c, const Seperator *sep);
void command_revoke(Client *c, const Seperator *sep); void command_revoke(Client *c, const Seperator *sep);
@ -305,7 +288,7 @@ void command_timezone(Client *c, const Seperator *sep);
void command_title(Client *c, const Seperator *sep); void command_title(Client *c, const Seperator *sep);
void command_titlesuffix(Client *c, const Seperator *sep); void command_titlesuffix(Client *c, const Seperator *sep);
void command_traindisc(Client *c, const Seperator *sep); void command_traindisc(Client *c, const Seperator *sep);
void command_trapinfo(Client* c, const Seperator *sep); void command_trapinfo(Client *c, const Seperator *sep);
void command_tune(Client *c, const Seperator *sep); void command_tune(Client *c, const Seperator *sep);
void command_ucs(Client *c, const Seperator *sep); void command_ucs(Client *c, const Seperator *sep);
void command_undye(Client *c, const Seperator *sep); void command_undye(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");
@ -129,7 +132,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
std::vector<std::string> move_h_options_negative; std::vector<std::string> move_h_options_negative;
std::vector<std::string> set_size_options_positive; std::vector<std::string> set_size_options_positive;
std::vector<std::string> set_size_options_negative; std::vector<std::string> set_size_options_negative;
for (const auto &move_option : move_options) { for (const auto &move_option : move_options) {
if (move_option == move_x_action) { if (move_option == move_x_action) {
move_x_options_positive.emplace_back( move_x_options_positive.emplace_back(
EQ::SayLinkEngine::GenerateQuestSaylink( EQ::SayLinkEngine::GenerateQuestSaylink(
@ -297,10 +300,10 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
// we're passing a move action here // we're passing a move action here
if (!arg3.empty() && StringIsNumber(arg3)) { if (!arg3.empty() && StringIsNumber(arg3)) {
float x_move = 0.0f; float x_move = 0.0f;
float y_move = 0.0f; float y_move = 0.0f;
float z_move = 0.0f; float z_move = 0.0f;
float h_move = 0.0f; float h_move = 0.0f;
float set_size = 0.0f; float set_size = 0.0f;
if (arg2 == move_x_action) { if (arg2 == move_x_action) {

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