Command code cleaning (refer to topic:169759)

* separated the execution part of command code into interface part and internal part to better see which checks are done and when (fixes problem where 'nocommand' mapflag blocked server npcs)
 * moved the internal commands list (array) to the end of the file, this let me discard that long block of ACMD_FUNC() declarations
 * removed enum AtCommandType from command headers and commands array; its purpose was perhaps to identify aliased commands, but apparently it was never finished because the rest of the code doesn't use it (also doing aliases like this is not a very good idea)
 * internally, commands are now referenced to using their function name
 * removed the @/# symbols from the command lists; all lookup functions will now properly deal with strings with- and without a command symbol (commands interface still requires the symbol tho', so TODO for later)
 * removed several unneeded commands (*id2 code, dmalloc debug commands)
 * reverted atcommand config from alphabetically-sorted to how it was before (with additional fixes; see /conf changelog)
 * added missing code for #dropall / #storeall
 * added a warning when trying to set gm level of an undefined command

The structure of the commands table has changed, please adjust docs/guides to match the new format (sorry for the inconvenience).


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11607 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-10-29 09:16:39 +00:00
parent 82a3432bd4
commit fc9d14b1bd
12 changed files with 1488 additions and 2257 deletions

View File

@ -3,6 +3,28 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/10/29
* command code cleaning (refer to topic:169759) [ultramage]
- separated the execution part of command code into interface part
and internal part to better see which checks are done and when
(fixes problem where 'nocommand' mapflag blocked server npcs)
- moved the internal commands list (array) to the end of the file,
this let me discard that long block of ACMD_FUNC() declarations
- removed enum AtCommandType from command headers and commands array;
its purpose was perhaps to identify aliased commands, but apparently
it was never finished because the rest of the code doesn't use it
(also doing aliases like this is not a very good idea)
- internally, commands are now referenced to using their function name
- removed the @/# symbols from the command lists; all lookup functions
will now properly deal with strings with- and without a command symbol
(commands interface still requires the symbol tho', so TODO for later)
- removed several unneeded commands (*id2 code, dmalloc debug commands)
- reverted atcommand config from alphabetically-sorted to how it was
before (with additional fixes; see /conf changelog)
- added missing code for #dropall / #storeall
- added a warning when trying to set gm level of an undefined command
* The structure of the commands table has changed, please adjust
docs/guides to match the new format (sorry for the inconvenience)
2007/10/28
* Minor adjustment to take into account the end of line.
* Fixed the line count in the new error message of npc_parse_function.

View File

@ -1,5 +1,13 @@
Date Added
2007/10/29
* Removed petid command (not needed because commands understand names)
* Removed *id2 commands (messy, useless and redundant)
* Added missing @misceffect, @feelreset and #dropall/#storeall setting
* AGAIN added conf entries for @whozeny, @kamic, @tonpc, @identify,
@adopt, @trade, @changelook, @send, @displayskill
* Reverted atcommand conf (alphabetically-sorted = failure) [ultramage]
2007/10/26
* Removed the config setting firewall_hits_on_undead setting. The code
handles this now using the delay defined in skill_unit_db. [Skotlex]

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,12 @@
// Athena charcommand Configuration file.
// Translated by Peter Kieser <pfak@telus.net>
//--------------------------------------------------------------
// eAthena charcommand configuration file.
// Originally translated by Peter Kieser <pfak@telus.net>
//--------------------------------------------------------------
// The symbol that will be used to recognize commands.
// You can set any one character, except control-characters (0x00-0x1f),
// You can set any one character except control-characters (0x00-0x1f),
// '%', '$' (party/guild chat speaking) and '/' (standard client commands).
// The symbol must be different from from the standard GM command symbol.
// The symbol must also be different from from the GM atcommand symbol.
command_symbol: #
@ -21,6 +23,9 @@ command_symbol: #
//----------------------
// 20: Mediator commands
// Displays helpfile in eAthena base directory
help: 20
//--------------------
// 40: Sub-GM commands
@ -120,6 +125,12 @@ delitem: 60
disguise: 60
undisguise: 60
// Drop a players possessions on the ground
dropall: 60
// Put a players possessions in storage
storeall: 60
// Resets another character's designated maps
feelreset: 60

File diff suppressed because it is too large Load Diff

View File

@ -4,297 +4,42 @@
#ifndef _ATCOMMAND_H_
#define _ATCOMMAND_H_
//#include "map.h"
struct map_session_data;
//This is the distance at which @autoloot works,
//if the item drops farther from the player than this,
//it will not be autolooted. [Skotlex]
//Note: The range is unlimited unless this define is set.
//#define AUTOLOOT_DISTANCE AREA_SIZE
//#include "map.h"
struct map_session_data;
extern char atcommand_symbol;
typedef int (*AtCommandFunc)(const int fd, struct map_session_data* sd, const char* command, const char* message);
enum AtCommandType {
AtCommand_None = -1,
AtCommand_Broadcast = 0,
AtCommand_LocalBroadcast,
AtCommand_MapMove,
AtCommand_ResetState,
AtCommand_RuraP,
AtCommand_Rura,
AtCommand_Warp,
AtCommand_Where,
AtCommand_JumpTo,
AtCommand_Jump,
AtCommand_Who,
AtCommand_Who2,
AtCommand_Who3,
AtCommand_WhoMap,
AtCommand_WhoMap2,
AtCommand_WhoMap3,
AtCommand_WhoGM,
AtCommand_Save,
AtCommand_Load,
AtCommand_Speed,
AtCommand_CharSpeed,
AtCommand_Storage,
AtCommand_GuildStorage,
AtCommand_Option,
AtCommand_Hide,
AtCommand_JobChange,
AtCommand_JobChange2,
AtCommand_JobChange3,
AtCommand_Die,
AtCommand_Kill,
AtCommand_Alive,
AtCommand_Kami,
AtCommand_KamiB,
AtCommand_KamiC, //LuzZza
AtCommand_Heal,
AtCommand_Item,
AtCommand_Item2,
AtCommand_ItemReset,
AtCommand_BaseLevelUp,
AtCommand_JobLevelUp,
AtCommand_H,
AtCommand_Help,
AtCommand_H2,
AtCommand_Help2,
AtCommand_GM,
AtCommand_PvPOff,
AtCommand_PvPOn,
AtCommand_GvGOff,
AtCommand_GvGOn,
AtCommand_Model,
AtCommand_Go,
AtCommand_Spawn,
AtCommand_MonsterSmall,
AtCommand_MonsterBig,
AtCommand_KillMonster,
AtCommand_KillMonster2,
AtCommand_Refine,
AtCommand_Produce,
AtCommand_Memo,
AtCommand_GAT,
AtCommand_DisplayStatus,
AtCommand_StatusPoint,
AtCommand_SkillPoint,
AtCommand_Zeny,
AtCommand_Param,
AtCommand_Strength,
AtCommand_Agility,
AtCommand_Vitality,
AtCommand_Intelligence,
AtCommand_Dexterity,
AtCommand_Luck,
AtCommand_GuildLevelUp,
AtCommand_MakeEgg,
AtCommand_PetFriendly,
AtCommand_PetHungry,
AtCommand_PetRename,
AtCommand_Recall,
AtCommand_Night,
AtCommand_Day,
AtCommand_Doom,
AtCommand_DoomMap,
AtCommand_Raise,
AtCommand_RaiseMap,
AtCommand_Kick,
AtCommand_KickAll,
AtCommand_AllSkill,
AtCommand_QuestSkill,
AtCommand_LostSkill,
AtCommand_SpiritBall,
AtCommand_Party,
AtCommand_Guild,
AtCommand_AgitStart,
AtCommand_AgitEnd,
AtCommand_MapExit,
AtCommand_IDSearch,
AtCommand_RecallAll,
AtCommand_ReloadItemDB,
AtCommand_ReloadMobDB,
AtCommand_ReloadSkillDB,
AtCommand_ReloadScript,
AtCommand_ReloadGMDB,
AtCommand_ReloadAtcommand,
AtCommand_ReloadBattleConf,
AtCommand_ReloadStatusDB,
AtCommand_ReloadPcDB,
AtCommand_ReloadMOTD, // [Valaris]
AtCommand_MapInfo,
AtCommand_Dye,
AtCommand_Hstyle,
AtCommand_Hcolor,
AtCommand_StatAll,
AtCommand_CharBlock, // by Yor
AtCommand_CharBan, // by Yor
AtCommand_CharUnBlock, // by Yor
AtCommand_CharUnBan, // by Yor
AtCommand_MountPeco, // by Valaris
AtCommand_GuildSpy, // [Syrus22]
AtCommand_PartySpy, // [Syrus22]
AtCommand_RepairAll, // [Valaris]
AtCommand_GuildRecall, // by Yor
AtCommand_PartyRecall, // by Yor
AtCommand_Nuke, // [Valaris]
AtCommand_Shownpc,
AtCommand_Hidenpc,
AtCommand_Loadnpc,
AtCommand_Unloadnpc,
AtCommand_ServerTime, // by Yor
AtCommand_Jail, // by Yor
AtCommand_UnJail, // by Yor
AtCommand_JailFor, // Meruru
AtCommand_JailTime, // Coltaro
AtCommand_Disguise, // [Valaris]
AtCommand_UnDisguise, // by Yor
AtCommand_EMail, // by Yor
AtCommand_Hatch,
AtCommand_Effect, // by Apple
AtCommand_AddWarp, // by MouseJstr
AtCommand_Follow, // by MouseJstr
AtCommand_SkillOn, // by MouseJstr
AtCommand_SkillOff, // by MouseJstr
AtCommand_Killer, // by MouseJstr
AtCommand_NpcMove, // by MouseJstr
AtCommand_Killable, // by MouseJstr
AtCommand_Dropall, // by MouseJstr
AtCommand_Storeall, // by MouseJstr
AtCommand_Skillid, // by MouseJstr
AtCommand_Useskill, // by MouseJstr
AtCommand_DisplaySkill,
AtCommand_Summon,
AtCommand_Rain,
AtCommand_Snow,
AtCommand_Sakura,
AtCommand_Clouds,
AtCommand_Clouds2, // [Valaris]
AtCommand_Fog,
AtCommand_Fireworks,
AtCommand_Leaves,
AtCommand_AdjGmLvl, // MouseJstr
AtCommand_AdjCmdLvl, // MouseJstr
AtCommand_Trade, // MouseJstr
AtCommand_Send,
AtCommand_SetBattleFlag,
AtCommand_UnMute,
AtCommand_Clearweather, // by Dexity
AtCommand_UpTime, // by MC Cameri
AtCommand_ChangeSex, // by MC Cameri
AtCommand_Mute, // [celest]
AtCommand_WhoZeny, // [Valaris] <-- LOL...(MC Cameri) worth it.
AtCommand_Refresh, // by MC Cameri
AtCommand_PetId, // by MC Cameri
AtCommand_Identify, // by MC Cameri
AtCommand_Gmotd, // Added by MC Cameri, created by davidsiaw
AtCommand_MiscEffect, // by MC Cameri
AtCommand_MobSearch,
AtCommand_CleanMap,
AtCommand_NpcTalk,
AtCommand_PetTalk,
AtCommand_Users,
AtCommand_SkillTree, // by MouseJstr
AtCommand_Marry, // by MouseJstr
AtCommand_Divorce, // by MouseJstr
AtCommand_Me, //added by massdriller, code by lordalfa
AtCommand_DMStart, // by MouseJstr
AtCommand_DMTick, // by MouseJstr
AtCommand_JumpToId2, // by Dino9021
AtCommand_RecallId2, // by Dino9021
AtCommand_KickId2, // by Dino9021
AtCommand_ReviveId2, // by Dino9021
AtCommand_KillId2, // by Dino9021
AtCommand_Sound,
AtCommand_UndisguiseAll,
AtCommand_DisguiseAll,
AtCommand_ChangeLook,
AtCommand_AutoLoot, //by Upa-Kun
AtCommand_MobInfo, //by Lupus
AtCommand_Exp, // by Skotlex
AtCommand_Adopt, // by Veider
AtCommand_Version, // by Ancyker
AtCommand_MuteArea, // MouseJstr
AtCommand_Rates, // MouseJstr
AtCommand_ItemInfo, // Lupus
AtCommand_WhoDrops, // Skotlex
AtCommand_WhereIs, // Skotlex
AtCommand_MapFlag, // Lupus
AtCommand_MonsterIgnore, // [Valaris]
AtCommand_FakeName, // [Valaris]
AtCommand_Size, // [Valaris]
AtCommand_ShowDelay,
AtCommand_ShowExp,
AtCommand_ShowZeny,
AtCommand_AutoTrade,//durf
AtCommand_ChangeGM,//durf
AtCommand_ChangeLeader,
AtCommand_PartyOption,
AtCommand_Invite, // By LuzZza
AtCommand_Duel, // By LuzZza
AtCommand_Leave, // By LuzZza
AtCommand_Accept, // By LuzZza
AtCommand_Reject, // By LuzZza
AtCommand_Away, // LuzZza
AtCommand_Main, // LuzZza
AtCommand_Clone, // [Valaris]
AtCommand_ToNPC, // LuzZza
AtCommand_Commands, // [Skotlex]
AtCommand_NoAsk, // [LuzZza]
AtCommand_Request, // [Skotlex]
AtCommand_HomLevel, //[orn]
AtCommand_HomEvolution, //[orn]
AtCommand_MakeHomun, //[orn]
AtCommand_HomFriendly, //[orn]
AtCommand_HomHungry, //[orn]
AtCommand_HomTalk, //[orn]
AtCommand_HomInfo, //[Toms]
AtCommand_HomStats, //[Skotlex]
AtCommand_HomShuffle, //[Skotlex]
AtCommand_ShowMobs, //KarLaeda
AtCommand_FeelReset, //[HiddenDragon]
AtCommand_HappyHappyJoyJoy,
// SQL-only commands start
#ifndef TXT_ONLY
AtCommand_Mail, // [Mail System]
AtCommand_RefreshOnline, // [Valaris]
// SQL-only commands end
#endif
// No more commands after this line
AtCommand_Unknown,
AtCommand_MAX
};
typedef enum AtCommandType AtCommandType;
typedef struct AtCommandInfo {
AtCommandType type;
const char* command;
int level;
int (*proc)(const int fd, struct map_session_data* sd, const char* command, const char* message);
} AtCommandInfo;
AtCommandType is_atcommand(const int fd, struct map_session_data* sd, const char* message);
AtCommandType is_atcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl);
AtCommandType atcommand(struct map_session_data *sd, const int level, const char* message, AtCommandInfo* info);
int get_atcommand_level(const AtCommandType type);
char* msg_txt(int msg_number); // [Yor]
bool is_atcommand(const int fd, struct map_session_data* sd, const char* message);
bool is_atcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl);
int get_atcommand_level(const AtCommandFunc func);
void do_init_atcommand(void);
void do_final_atcommand(void);
int atcommand_item(const int fd, struct map_session_data* sd,const char* command, const char* message); // [Valaris]
int atcommand_rura(const int fd, struct map_session_data* sd,const char* command, const char* message); // [Yor]
int atcommand_jumpto(const int fd, struct map_session_data* sd, const char* command, const char* message); // [Yor]
int atcommand_recall(const int fd, struct map_session_data* sd, const char* command, const char* message); // [Yor]
int atcommand_monster(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_config_read(const char *cfgName);
int msg_config_read(const char *cfgName);
void do_final_msg(void);
extern char atcommand_symbol;
int atcommand_item(const int fd, struct map_session_data* sd,const char* command, const char* message);
int atcommand_mapmove(const int fd, struct map_session_data* sd,const char* command, const char* message);
int atcommand_monster(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_jumpto(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_recall(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_hide(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_mute(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_kick(const int fd, struct map_session_data* sd, const char* command, const char* message);
int atcommand_broadcast(const int fd, struct map_session_data* sd,const char* command, const char* message);
int atcommand_localbroadcast(const int fd, struct map_session_data* sd,const char* command, const char* message);
int atcommand_reset(const int fd, struct map_session_data* sd,const char* command, const char* message);
#define MAX_MSG 1000
extern char* msg_table[MAX_MSG];
char* msg_txt(int msg_number);
int msg_config_read(const char* cfgName);
void do_final_msg(void);
#endif /* _ATCOMMAND_H_ */

View File

@ -1,32 +1,31 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include "../common/cbasetypes.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/nullpo.h"
#include "../common/showmsg.h"
#include "../common/strlib.h"
#include "../common/utils.h"
#include "log.h"
#include "atcommand.h" // msg_txt()
#include "charcommand.h"
#include "battle.h"
#include "clif.h"
#include "chrif.h"
#include "intif.h"
#include "itemdb.h"
#include "log.h"
#include "map.h"
#include "pc.h"
#include "status.h"
#include "skill.h"
#include "mob.h"
#include "npc.h"
#include "pet.h"
#include "mercenary.h" //[orn]
#include "battle.h"
#include "charcommand.h"
#include "atcommand.h"
#include "mercenary.h"
#include "party.h"
#include "guild.h"
#include "script.h"
#include "npc.h"
#include "trade.h"
#include "unit.h"
@ -40,379 +39,16 @@ char charcommand_symbol = '#';
extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
#define CCMD_FUNC(x) int charcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
CCMD_FUNC(jobchange);
CCMD_FUNC(petrename);
CCMD_FUNC(petfriendly);
CCMD_FUNC(stats);
CCMD_FUNC(option);
CCMD_FUNC(save);
CCMD_FUNC(stats_all);
CCMD_FUNC(reset);
CCMD_FUNC(spiritball);
CCMD_FUNC(itemlist);
CCMD_FUNC(effect);
CCMD_FUNC(storagelist);
CCMD_FUNC(item);
CCMD_FUNC(warp);
CCMD_FUNC(zeny);
CCMD_FUNC(fakename);
CCMD_FUNC(baselevel);
CCMD_FUNC(joblevel);
CCMD_FUNC(questskill);
CCMD_FUNC(lostskill);
CCMD_FUNC(skreset);
CCMD_FUNC(streset);
CCMD_FUNC(model);
CCMD_FUNC(stpoint);
CCMD_FUNC(skpoint);
CCMD_FUNC(changesex);
CCMD_FUNC(feelreset);
CCMD_FUNC(help);
CCMD_FUNC(load);
CCMD_FUNC(speed);
CCMD_FUNC(storage);
CCMD_FUNC(guildstorage);
CCMD_FUNC(hide);
CCMD_FUNC(alive);
CCMD_FUNC(heal);
CCMD_FUNC(item2);
CCMD_FUNC(itemreset);
CCMD_FUNC(refine);
CCMD_FUNC(produce);
CCMD_FUNC(param);
CCMD_FUNC(guildlevelup);
CCMD_FUNC(hatch);
CCMD_FUNC(pethungry);
CCMD_FUNC(allskill);
CCMD_FUNC(dye);
CCMD_FUNC(hair_style);
CCMD_FUNC(hair_color);
CCMD_FUNC(allstats);
CCMD_FUNC(mount_peco);
CCMD_FUNC(delitem);
CCMD_FUNC(jailtime);
CCMD_FUNC(disguise);
CCMD_FUNC(undisguise);
CCMD_FUNC(cart_list);
CCMD_FUNC(killer);
CCMD_FUNC(killable);
CCMD_FUNC(refresh);
CCMD_FUNC(exp);
CCMD_FUNC(monsterignore);
CCMD_FUNC(size);
CCMD_FUNC(homlevel);
CCMD_FUNC(homevolution);
CCMD_FUNC(homfriendly);
CCMD_FUNC(homhungry);
CCMD_FUNC(hominfo);
/*==========================================
*CharCommandInfo charcommand_info[]
*------------------------------------------*/
typedef struct CharCommandInfo {
const char* command;
int level;
CharCommandFunc func;
} CharCommandInfo;
// First char of commands is configured in charcommand_athena.conf. Leave # in this list for default value.
// to set default level, read charcommand_athena.conf first please.
static CharCommandInfo charcommand_info[] = {
{ CharCommandJobChange, "#job", 60, charcommand_jobchange },
{ CharCommandJobChange, "#jobchange", 60, charcommand_jobchange },
{ CharCommandPetRename, "#petrename", 50, charcommand_petrename },
{ CharCommandPetFriendly, "#petfriendly", 50, charcommand_petfriendly },
{ CharCommandStats, "#stats", 40, charcommand_stats },
{ CharCommandOption, "#option", 60, charcommand_option },
{ CharCommandReset, "#reset", 60, charcommand_reset },
{ CharCommandSave, "#save", 60, charcommand_save },
{ CharCommandSpiritball, "#spiritball", 40, charcommand_spiritball },
{ CharCommandItemList, "#itemlist", 40, charcommand_itemlist },
{ CharCommandEffect, "#effect", 40, charcommand_effect },
{ CharCommandStorageList, "#storagelist", 40, charcommand_storagelist },
{ CharCommandItem, "#item", 60, charcommand_item },
{ CharCommandWarp, "#warp", 60, charcommand_warp },
{ CharCommandWarp, "#rura", 60, charcommand_warp },
{ CharCommandWarp, "#rura+", 60, charcommand_warp },
{ CharCommandZeny, "#zeny", 60, charcommand_zeny },
{ CharCommandFakeName, "#fakename", 50, charcommand_fakename},
{ CharCommandBaseLevel, "#baselvl", 60, charcommand_baselevel},
{ CharCommandBaseLevel, "#baselevel", 60, charcommand_baselevel},
{ CharCommandBaseLevel, "#blvl", 60, charcommand_baselevel},
{ CharCommandBaseLevel, "#blevel", 60, charcommand_baselevel},
{ CharCommandJobLevel, "#joblvl", 60, charcommand_joblevel},
{ CharCommandJobLevel, "#joblevel", 60, charcommand_joblevel},
{ CharCommandJobLevel, "#jlvl", 60, charcommand_joblevel},
{ CharCommandJobLevel, "#jlevel", 60, charcommand_joblevel},
{ CharCommandQuestSkill, "#questskill", 60, charcommand_questskill },
{ CharCommandLostSkill, "#lostskill", 60, charcommand_lostskill },
{ CharCommandSkReset, "#skreset", 60, charcommand_skreset },
{ CharCommandStReset, "#streset", 60, charcommand_streset },
{ CharCommandModel, "#model", 50, charcommand_model },
{ CharCommandSKPoint, "#skpoint", 60, charcommand_skpoint },
{ CharCommandSTPoint, "#stpoint", 60, charcommand_stpoint },
{ CharCommandChangeSex, "#changesex", 60, charcommand_changesex },
{ CharCommandFeelReset, "#feelreset", 60, charcommand_feelreset },
{ CharCommandHelp, "#help", 20, charcommand_help },
{ CharCommandLoad, "#load", 60, charcommand_load },
{ CharCommandSpeed, "#speed", 60, charcommand_speed },
{ CharCommandStorage, "#storage", 60, charcommand_storage },
{ CharCommandGStorage, "#gstorage", 60, charcommand_guildstorage },
{ CharCommandHide, "#hide", 60, charcommand_hide },
{ CharCommandAlive, "#alive", 60, charcommand_alive },
{ CharCommandHeal, "#heal", 60, charcommand_heal },
{ CharCommandItem2, "#item2", 60, charcommand_item2 },
{ CharCommandItemReset, "#itemreset", 60, charcommand_itemreset },
{ CharCommandRefine, "#refine", 60, charcommand_refine },
{ CharCommandProduce, "#produce", 60, charcommand_produce },
{ CharCommandStrength, "#str", 60, charcommand_param },
{ CharCommandAgility, "#agi", 60, charcommand_param },
{ CharCommandVitality, "#vit", 60, charcommand_param },
{ CharCommandIntelligence, "#int", 60, charcommand_param },
{ CharCommandDexterity, "#dex", 60, charcommand_param },
{ CharCommandLuck, "#luk", 60, charcommand_param },
{ CharCommandGuildLevelUp, "#glvl", 60, charcommand_guildlevelup },
{ CharCommandGuildLevelUp, "#glevel", 60, charcommand_guildlevelup },
{ CharCommandGuildLevelUp, "#guildlvl", 60, charcommand_guildlevelup },
{ CharCommandGuildLevelUp, "#guildlevel", 60, charcommand_guildlevelup },
{ CharCommandHatch, "#hatch", 50, charcommand_hatch },
{ CharCommandPetHungry, "#pethungry", 60, charcommand_pethungry },
{ CharCommandAllSkill, "#allskill", 60, charcommand_allskill },
{ CharCommandAllSkill, "#allskills", 60, charcommand_allskill },
{ CharCommandAllSkill, "#skillall", 60, charcommand_allskill },
{ CharCommandAllSkill, "#skillsall", 60, charcommand_allskill },
{ CharCommandDye, "#dye", 50, charcommand_dye },
{ CharCommandHStyle, "#hairstyle", 50, charcommand_hair_style },
{ CharCommandHStyle, "#hstyle", 50, charcommand_hair_style },
{ CharCommandHColor, "#haircolor", 50, charcommand_hair_color },
{ CharCommandHColor, "#hcolor", 50, charcommand_hair_color },
{ CharCommandAllStats, "#allstat", 60, charcommand_allstats },
{ CharCommandAllStats, "#allstats", 60, charcommand_allstats },
{ CharCommandAllStats, "#statall", 60, charcommand_allstats },
{ CharCommandAllStats, "#statsall", 60, charcommand_allstats },
{ CharCommandMountPeco, "#mount", 50, charcommand_mount_peco },
{ CharCommandMountPeco, "#mountpeco", 50, charcommand_mount_peco },
{ CharCommandDelItem, "#delitem", 60, charcommand_delitem },
{ CharCommandJailTime, "#jailtime", 40, charcommand_jailtime },
{ CharCommandDisguie, "#disguise", 60, charcommand_disguise },
{ CharCommandUnDisguise, "#undisguise", 60, charcommand_undisguise },
{ CharCommandCartList, "#cartlist", 40, charcommand_cart_list },
{ CharCommandKiller, "#killer", 60, charcommand_killer },
{ CharCommandKillable, "#killable", 60, charcommand_killable },
{ CharCommandRefresh, "#refresh", 40, charcommand_refresh },
{ CharCommandExp, "#exp", 1, charcommand_exp },
{ CharCommandMonsterIgnore, "#monsterignore", 60, charcommand_monsterignore },
{ CharCommandSize, "#size", 50, charcommand_size },
{ CharCommandHomLevel, "#hlvl", 60, charcommand_homlevel },
{ CharCommandHomLevel, "#hlevel", 60, charcommand_homlevel },
{ CharCommandHomLevel, "#homlvl", 60, charcommand_homlevel },
{ CharCommandHomLevel, "#homlevel", 60, charcommand_homlevel },
{ CharCommandHomEvolve, "#homevolve", 60, charcommand_homevolution },
{ CharCommandHomEvolve, "#homevolvution", 60, charcommand_homevolution },
{ CharCommandHomFriendly, "#homfriendly", 60, charcommand_homfriendly },
{ CharCommandHomHungry, "#homhungry", 60, charcommand_homhungry },
{ CharCommandHomInfo, "#hominfo", 40, charcommand_hominfo },
// add new commands before this line
{ CharCommand_Unknown, NULL, 1, NULL }
};
static CharCommandInfo* get_charcommandinfo_byname(const char* name);
static CharCommandInfo* get_charcommandinfo_byfunc(const CharCommandFunc func);
int get_charcommand_level(const CharCommandType type)
{
int i;
for (i = 0; charcommand_info[i].type != CharCommand_None; i++)
if (charcommand_info[i].type == type)
return charcommand_info[i].level;
return 100; // 100: command can not be used
}
CharCommandType is_charcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl)
{
CharCommandInfo info;
CharCommandType type;
memset(&info, 0, sizeof(info));
type = charcommand(sd, gmlvl, str, &info);
if (type != CharCommand_None) {
char command[100];
char output[200];
const char* p = str;
if (map[sd->bl.m].nocommand &&
gmlvl < map[sd->bl.m].nocommand)
{ //Command not allowed on this map.
sprintf(output, msg_txt(143));
clif_displaymessage(fd, output);
return AtCommand_None;
}
memset(command, '\0', sizeof(command));
memset(output, '\0', sizeof(output));
while (*p && !ISSPACE(*p))
p++;
if (p - str >= sizeof(command)) // too long
return CharCommand_Unknown;
strncpy(command, str, p - str);
while (ISSPACE(*p))
p++;
if (type == CharCommand_Unknown || info.proc == NULL) {
snprintf(output, sizeof(output),msg_txt(153), command); // %s is Unknown Command.
clif_displaymessage(fd, output);
} else {
if (info.proc(fd, sd, command, p) != 0) {
// Command can not be executed
snprintf(output, sizeof(output), msg_txt(154), command); // %s failed.
clif_displaymessage(fd, output);
}
}
return info.type;
}
return CharCommand_None;
}
/*==========================================
*is_charcommand @
*------------------------------------------*/
CharCommandType is_charcommand(const int fd, struct map_session_data* sd, const char* message)
{
const char* str = message;
int s_flag = 0;
nullpo_retr(CharCommand_None, sd);
if (sd->sc.count && sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCOMMAND)
return CharCommand_None;
if (!message || !*message)
return CharCommand_None;
// temporary compatibility layer for previous implementation
if( *message != charcommand_symbol )
{
str += strlen(sd->status.name);
while (*str && (ISSPACE(*str) || (s_flag == 0 && *str == ':'))) {
if (*str == ':')
s_flag = 1;
str++;
}
}
if (!*str)
return CharCommand_None;
if(str[0] == '|' && strlen(str) >= 4 && str[3] == charcommand_symbol)
str += 3; // skip 10/11-langtype's codepage indicator, if detected
return is_charcommand_sub(fd,sd,str,pc_isGM(sd));
}
/*==========================================
*
*------------------------------------------*/
CharCommandType charcommand(struct map_session_data* sd, const int level, const char* message, CharCommandInfo* info)
{
char* p = (char *)message;
if (!info)
return CharCommand_None;
if (battle_config.atc_gmonly != 0 && !level) // level = pc_isGM(sd)
return CharCommand_None;
if (!p || !*p) {
ShowError("char command message is empty\n");
return CharCommand_None;
}
if (*p == charcommand_symbol) { // check first char
char command[101];
int i = 0;
memset(info, 0, sizeof(CharCommandInfo));
sscanf(p, "%100s", command);
command[100] = '\0';
while (charcommand_info[i].type != CharCommand_Unknown) {
if (strcmpi(command+1, charcommand_info[i].command+1) == 0 && level >= charcommand_info[i].level) {
p[0] = charcommand_info[i].command[0]; // set correct first symbol for after.
break;
}
i++;
}
if (charcommand_info[i].type == CharCommand_Unknown) {
// doesn't return Unknown if player is normal player (display the text, not display: unknown command)
if (level == 0)
return CharCommand_None;
else
return CharCommand_Unknown;
} else if((log_config.gm) && (charcommand_info[i].level >= log_config.gm)) {
log_atcommand(sd, message);
}
memcpy(info, &charcommand_info[i], sizeof charcommand_info[i]);
} else {
return CharCommand_None;
}
return info->type;
}
/*==========================================
*
*------------------------------------------*/
static CharCommandInfo* get_charcommandinfo_byname(const char* name)
{
int i;
for (i = 0; charcommand_info[i].type != CharCommand_Unknown; i++)
if (strcmpi(charcommand_info[i].command + 1, name) == 0)
return &charcommand_info[i];
return NULL;
}
/*==========================================
*
*------------------------------------------*/
int charcommand_config_read(const char *cfgName)
{
char line[1024], w1[1024], w2[1024];
CharCommandInfo* p;
FILE* fp;
if ((fp = fopen(cfgName, "r")) == NULL) {
ShowError("CharCommands configuration file not found: %s\n", cfgName);
return 1;
}
while (fgets(line, sizeof(line), fp))
{
if (line[0] == '/' && line[1] == '/')
continue;
if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2)
continue;
p = get_charcommandinfo_byname(w1);
if (p != NULL) {
p->level = atoi(w2);
if (p->level > 100)
p->level = 100;
else if (p->level < 0)
p->level = 0;
}
if (strcmpi(w1, "import") == 0)
charcommand_config_read(w2);
else if (strcmpi(w1, "command_symbol") == 0 && w2[0] > 31 &&
w2[0] != '/' && // symbol of standard ragnarok GM commands
w2[0] != '%' && // symbol of party chat speaking
w2[0] != '$' && // symbol of guild chat speaking
w2[0] != '@') // symbol of atcommand
charcommand_symbol = w2[0];
}
fclose(fp);
return 0;
}
/*==========================================
* upper指定で転生や養子も可能
@ -1558,9 +1194,9 @@ int charcommand_lostskill(const int fd, struct map_session_data* sd, const char*
}
if (skill_id < 0 && skill_id >= MAX_SKILL) {
clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist.
return -1;
}
clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist.
return -1;
}
if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) {
clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill.
return -1;
@ -3497,6 +3133,78 @@ int charcommand_killable(const int fd, struct map_session_data* sd, const char*
return 0;
}
/*==========================================
* Drop all of the target's possessions on the ground
*------------------------------------------*/
int charcommand_dropall(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
int i;
struct map_session_data *pl_sd = NULL;
nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
if((pl_sd=map_nick2sd((char *) message)) == NULL)
return -1;
for (i = 0; i < MAX_INVENTORY; i++) {
if (pl_sd->status.inventory[i].amount) {
if(pl_sd->status.inventory[i].equip != 0)
pc_unequipitem(pl_sd, i, 3);
pc_dropitem(pl_sd, i, pl_sd->status.inventory[i].amount);
}
}
clif_displaymessage(pl_sd->fd, "All items dropped");
clif_displaymessage(fd, "It is done");
return 0;
}
/*==========================================
* Put all of the target's possessions into storage
*------------------------------------------*/
int charcommand_storeall(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
int i;
struct map_session_data *pl_sd = NULL;
nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
if((pl_sd=map_nick2sd((char *) message)) == NULL)
return -1;
if (pl_sd->state.storage_flag != 1)
{ //Open storage.
switch (storage_storageopen(pl_sd)) {
case 2: //Try again
clif_displaymessage(fd, "Had to open the characters storage window...");
clif_displaymessage(fd, "run this command again..");
return 0;
case 1: //Failure
clif_displaymessage(fd, "The character currently can't use the storage.");
return 1;
}
}
for (i = 0; i < MAX_INVENTORY; i++) {
if (pl_sd->status.inventory[i].amount) {
if(pl_sd->status.inventory[i].equip != 0)
pc_unequipitem(pl_sd, i, 3);
storage_storageadd(pl_sd, i, sd->status.inventory[i].amount);
}
}
storage_storageclose(pl_sd);
clif_displaymessage(pl_sd->fd, "Everything you own has been put away for safe keeping.");
clif_displaymessage(pl_sd->fd, "go to the nearest kafka to retrieve it..");
clif_displaymessage(pl_sd->fd, " -- the management");
clif_displaymessage(fd, "It is done");
return 0;
}
/*==========================================
* Refreshes target [HiddenDragon]
*------------------------------------------*/
@ -3734,7 +3442,7 @@ int charcommand_homevolution(const int fd, struct map_session_data* sd, const ch
clif_displaymessage(fd, "Please, enter a player name (usage: #homevolution <player>).");
return -1;
}
if ( (pl_sd = map_nick2sd(character)) == NULL )
{
clif_displaymessage(fd, msg_txt(3)); // Character not found.
@ -3746,7 +3454,7 @@ int charcommand_homevolution(const int fd, struct map_session_data* sd, const ch
clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
return -1;
}
if ( !merc_is_hom_active(pl_sd->hd) ) {
clif_displaymessage(fd, "Target player does not have a homunculus.");
return -1;
@ -3961,3 +3669,261 @@ int charcommand_hominfo(const int fd, struct map_session_data* sd, const char* c
return 0;
}
/*==========================================
* charcommand_info[] structure definition
*------------------------------------------*/
CharCommandInfo charcommand_info[] = {
{ "job", 60, charcommand_jobchange },
{ "jobchange", 60, charcommand_jobchange },
{ "petrename", 50, charcommand_petrename },
{ "petfriendly", 50, charcommand_petfriendly },
{ "stats", 40, charcommand_stats },
{ "option", 60, charcommand_option },
{ "reset", 60, charcommand_reset },
{ "save", 60, charcommand_save },
{ "spiritball", 40, charcommand_spiritball },
{ "itemlist", 40, charcommand_itemlist },
{ "effect", 40, charcommand_effect },
{ "storagelist", 40, charcommand_storagelist },
{ "item", 60, charcommand_item },
{ "warp", 60, charcommand_warp },
{ "rura", 60, charcommand_warp },
{ "rura+", 60, charcommand_warp },
{ "zeny", 60, charcommand_zeny },
{ "fakename", 50, charcommand_fakename },
{ "baselvl", 60, charcommand_baselevel },
{ "baselevel", 60, charcommand_baselevel },
{ "blvl", 60, charcommand_baselevel },
{ "blevel", 60, charcommand_baselevel },
{ "joblvl", 60, charcommand_joblevel },
{ "joblevel", 60, charcommand_joblevel },
{ "jlvl", 60, charcommand_joblevel },
{ "jlevel", 60, charcommand_joblevel },
{ "questskill", 60, charcommand_questskill },
{ "lostskill", 60, charcommand_lostskill },
{ "skreset", 60, charcommand_skreset },
{ "streset", 60, charcommand_streset },
{ "model", 50, charcommand_model },
{ "skpoint", 60, charcommand_skpoint },
{ "stpoint", 60, charcommand_stpoint },
{ "changesex", 60, charcommand_changesex },
{ "feelreset", 60, charcommand_feelreset },
{ "help", 20, charcommand_help },
{ "load", 60, charcommand_load },
{ "speed", 60, charcommand_speed },
{ "storage", 60, charcommand_storage },
{ "gstorage", 60, charcommand_guildstorage },
{ "hide", 60, charcommand_hide },
{ "alive", 60, charcommand_alive },
{ "revive", 60, charcommand_alive },
{ "heal", 60, charcommand_heal },
{ "item2", 60, charcommand_item2 },
{ "itemreset", 60, charcommand_itemreset },
{ "refine", 60, charcommand_refine },
{ "produce", 60, charcommand_produce },
{ "str", 60, charcommand_param },
{ "agi", 60, charcommand_param },
{ "vit", 60, charcommand_param },
{ "int", 60, charcommand_param },
{ "dex", 60, charcommand_param },
{ "luk", 60, charcommand_param },
{ "glvl", 60, charcommand_guildlevelup },
{ "glevel", 60, charcommand_guildlevelup },
{ "guildlvl", 60, charcommand_guildlevelup },
{ "guildlevel", 60, charcommand_guildlevelup },
{ "hatch", 50, charcommand_hatch },
{ "pethungry", 60, charcommand_pethungry },
{ "allskill", 60, charcommand_allskill },
{ "allskills", 60, charcommand_allskill },
{ "skillall", 60, charcommand_allskill },
{ "skillsall", 60, charcommand_allskill },
{ "dye", 50, charcommand_dye },
{ "hairstyle", 50, charcommand_hair_style },
{ "hstyle", 50, charcommand_hair_style },
{ "haircolor", 50, charcommand_hair_color },
{ "hcolor", 50, charcommand_hair_color },
{ "allstat", 60, charcommand_allstats },
{ "allstats", 60, charcommand_allstats },
{ "statall", 60, charcommand_allstats },
{ "statsall", 60, charcommand_allstats },
{ "mount", 50, charcommand_mount_peco },
{ "mountpeco", 50, charcommand_mount_peco },
{ "delitem", 60, charcommand_delitem },
{ "jailtime", 40, charcommand_jailtime },
{ "disguise", 60, charcommand_disguise },
{ "undisguise", 60, charcommand_undisguise },
{ "cartlist", 40, charcommand_cart_list },
{ "killer", 60, charcommand_killer },
{ "killable", 60, charcommand_killable },
{ "dropall", 60, charcommand_dropall },
{ "storeall", 60, charcommand_storeall },
{ "refresh", 40, charcommand_refresh },
{ "exp", 1, charcommand_exp },
{ "monsterignore", 60, charcommand_monsterignore },
{ "size", 50, charcommand_size },
{ "hlvl", 60, charcommand_homlevel },
{ "hlevel", 60, charcommand_homlevel },
{ "homlvl", 60, charcommand_homlevel },
{ "homlevel", 60, charcommand_homlevel },
{ "homevolve", 60, charcommand_homevolution },
{ "homevolution", 60, charcommand_homevolution },
{ "homfriendly", 60, charcommand_homfriendly },
{ "homhungry", 60, charcommand_homhungry },
{ "hominfo", 40, charcommand_hominfo },
};
/*==========================================
* Command lookup functions
*------------------------------------------*/
static CharCommandInfo* get_charcommandinfo_byname(const char* name)
{
int i;
if( *name == charcommand_symbol ) name++; // for backwards compatibility
ARR_FIND( 0, ARRAYLENGTH(charcommand_info), i, strcmpi(charcommand_info[i].command, name) == 0 );
return ( i != ARRAYLENGTH(charcommand_info) ) ? &charcommand_info[i] : NULL;
}
static CharCommandInfo* get_charcommandinfo_byfunc(const CharCommandFunc func)
{
int i;
ARR_FIND( 0, ARRAYLENGTH(charcommand_info), i, charcommand_info[i].func == func );
return ( i != ARRAYLENGTH(charcommand_info) ) ? &charcommand_info[i] : NULL;
}
/*==========================================
* Retrieve the command's required gm level
*------------------------------------------*/
int get_charcommand_level(const CharCommandFunc func)
{
CharCommandInfo* info = get_charcommandinfo_byfunc(func);
return ( info != NULL ) ? info->level : 100; // 100: command can not be used
}
/// Executes a char-command.
/// To be called by internal server code (bypasses various restrictions).
bool is_charcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl)
{
CharCommandInfo* info;
char command[100];
char args[100];
char output[200];
if( !str || !*str )
return false;
if( *str != charcommand_symbol ) // check first char
return false;
if( sscanf(str, "%99s %99[^\n]", command, args) < 2 )
args[0] = '\0';
info = get_charcommandinfo_byname(command);
if( info == NULL || info->func == NULL || gmlvl < info->level )
{
if( gmlvl == 0 )
return false; // will just display as normal text
else
{
sprintf(output, msg_txt(153), command); // "%s is Unknown Command."
clif_displaymessage(fd, output);
return true;
}
}
if( log_config.gm && info->level >= log_config.gm )
log_atcommand(sd, str);
if( info->func(fd, sd, command, args) != 0 )
{
sprintf(output, msg_txt(154), command); // "%s failed."
clif_displaymessage(fd, output);
}
return true;
}
/// Executes a char-command.
/// To be used by player-invoked code (restrictions will be applied)
bool is_charcommand(const int fd, struct map_session_data* sd, const char* message)
{
int gmlvl = pc_isGM(sd);
int s_flag = 0;
nullpo_retr(false, sd);
if( !message || !*message )
return false;
if( sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCOMMAND )
return true;
if( battle_config.atc_gmonly != 0 && gmlvl == 0 )
return false;
if( map[sd->bl.m].nocommand && gmlvl < map[sd->bl.m].nocommand )
{
clif_displaymessage(fd, msg_txt(143)); // "Commands are disabled on this map."
return false;
}
// skip 10/11-langtype's codepage indicator, if detected
if( message[0] == '|' && strlen(message) >= 4 && message[3] == charcommand_symbol )
message += 3;
return is_atcommand_sub(fd,sd,message,gmlvl);
}
/*==========================================
*
*------------------------------------------*/
int charcommand_config_read(const char* cfgName)
{
char line[1024], w1[1024], w2[1024];
CharCommandInfo* p;
FILE* fp;
if( (fp = fopen(cfgName, "r")) == NULL )
{
ShowError("CharCommand configuration file not found: %s\n", cfgName);
return 1;
}
while( fgets(line, sizeof(line), fp) )
{
if( line[0] == '/' && line[1] == '/' )
continue;
if( sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2 )
continue;
p = get_charcommandinfo_byname(w1);
if( p != NULL )
{
p->level = atoi(w2);
p->level = cap_value(p->level, 0, 100);
}
else
if( strcmpi(w1, "import") == 0 )
charcommand_config_read(w2);
else
if( strcmpi(w1, "command_symbol") == 0 &&
w2[0] > 31 && // control characters
w2[0] != '/' && // symbol of standard ragnarok GM commands
w2[0] != '%' && // symbol of party chat speaking
w2[0] != '$' && // symbol of guild chat speaking
w2[0] != '@' ) // symbol of atcommand
charcommand_symbol = w2[0];
else
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}
fclose(fp);
return 0;
}

View File

@ -4,101 +4,16 @@
#ifndef _CHARCOMMAND_H_
#define _CHARCOMMAND_H_
enum CharCommandType {
CharCommand_None = -1,
CharCommandJobChange,
CharCommandPetRename,
CharCommandPetFriendly,
CharCommandReset,
CharCommandStats,
CharCommandOption,
CharCommandSave,
CharCommandSpiritball,
CharCommandItemList,
CharCommandEffect,
CharCommandStorageList,
CharCommandItem, // by MC Cameri
CharCommandWarp,
CharCommandZeny,
CharCommandFakeName,
CharCommandBaseLevel,
CharCommandJobLevel,
CharCommandQuestSkill,
CharCommandLostSkill,
CharCommandSkReset,
CharCommandStReset,
CharCommandModel,
CharCommandSKPoint,
CharCommandSTPoint,
CharCommandChangeSex,
CharCommandFeelReset, // Komurka
CharCommandHelp,
CharCommandLoad,
CharCommandSpeed,
CharCommandStorage,
CharCommandGStorage,
CharCommandHide,
CharCommandAlive,
CharCommandHeal,
CharCommandItem2,
CharCommandItemReset,
CharCommandRefine,
CharCommandProduce,
CharCommandStrength,
CharCommandAgility,
CharCommandVitality,
CharCommandIntelligence,
CharCommandDexterity,
CharCommandLuck,
CharCommandGuildLevelUp,
CharCommandHatch,
CharCommandPetHungry,
CharCommandAllSkill,
CharCommandDye,
CharCommandHStyle,
CharCommandHColor,
CharCommandAllStats,
CharCommandMountPeco,
CharCommandDelItem,
CharCommandJailTime,
CharCommandDisguie,
CharCommandUnDisguise,
CharCommandCartList,
CharCommandKiller,
CharCommandKillable,
CharCommandRefresh,
CharCommandExp,
CharCommandMonsterIgnore,
CharCommandSize,
CharCommandHomLevel,
CharCommandHomEvolve,
CharCommandHomFriendly,
CharCommandHomHungry,
CharCommandHomInfo,
// No more commands after this line
CharCommand_Unknown,
CharCommand_MAX
};
//#include "map.h"
struct map_session_data;
typedef enum CharCommandType CharCommandType;
typedef struct CharCommandInfo {
CharCommandType type;
const char* command;
int level;
int (*proc)(const int, struct map_session_data*,
const char* command, const char* message);
} CharCommandInfo;
CharCommandType
is_charcommand(const int fd, struct map_session_data* sd, const char* message);
CharCommandType
is_charcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl);
CharCommandType charcommand(
struct map_session_data* sd, const int level, const char* message, CharCommandInfo* info);
int get_charcommand_level(const CharCommandType type);
int charcommand_config_read(const char *cfgName);
extern char charcommand_symbol;
typedef int (*CharCommandFunc)(const int fd, struct map_session_data* sd, const char* command, const char* message);
bool is_charcommand(const int fd, struct map_session_data* sd, const char* message);
bool is_charcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl);
int get_charcommand_level(const CharCommandFunc func);
int charcommand_config_read(const char* cfgName);
#endif /* _CHARCOMMAND_H_ */

View File

@ -8248,7 +8248,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
if( is_atcommand(fd, sd, message) != AtCommand_None || is_charcommand(fd, sd, message) != CharCommand_None )
if( is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) )
return;
if( sd->sc.data[SC_BERSERK].timer != -1 || (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) )
@ -8331,14 +8331,14 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd)
if (battle_config.atc_gmonly && !pc_isGM(sd))
return;
if(pc_isGM(sd) < get_atcommand_level(AtCommand_MapMove))
if(pc_isGM(sd) < get_atcommand_level(atcommand_mapmove))
return;
map_name = (char*)RFIFOP(fd,2);
map_name[MAP_NAME_LENGTH_EXT-1]='\0';
sprintf(output, "%s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20));
atcommand_rura(fd, sd, "@rura", output);
if(log_config.gm && get_atcommand_level(AtCommand_MapMove) >= log_config.gm)
atcommand_mapmove(fd, sd, "@mapmove", output);
if( log_config.gm && get_atcommand_level(atcommand_mapmove) >= log_config.gm )
{
sprintf(message, "/mm %s", output);
log_atcommand(sd, message);
@ -8559,7 +8559,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
if( !clif_process_message(sd, 1, &target, &namelen, &message, &messagelen) )
return;
if (is_atcommand(fd, sd, message) != AtCommand_None || is_charcommand(fd, sd, message) != CharCommand_None )
if (is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) )
return;
if (sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))
@ -8694,9 +8694,9 @@ void clif_parse_GMmessage(int fd, struct map_session_data* sd)
unsigned int len = RFIFOW(fd,2)-4;
int lv;
if (battle_config.atc_gmonly && !pc_isGM(sd))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_Broadcast)))
if( pc_isGM(sd) < (lv=get_atcommand_level(atcommand_broadcast)) )
return;
// as the length varies depending on the command used, just block unreasonably long strings
@ -9674,17 +9674,18 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_ResetChar(int fd, struct map_session_data *sd)
{
if (battle_config.atc_gmonly && !pc_isGM(sd))
return;
if (pc_isGM(sd) < get_atcommand_level(AtCommand_ResetState))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (RFIFOW(fd,2))
if( pc_isGM(sd) < get_atcommand_level(atcommand_reset) )
return;
if( RFIFOW(fd,2) )
pc_resetskill(sd,1);
else
pc_resetstate(sd);
if(log_config.gm && get_atcommand_level(AtCommand_ResetState >= log_config.gm))
if( log_config.gm && get_atcommand_level(atcommand_reset) >= log_config.gm )
log_atcommand(sd, RFIFOW(fd,2) ? "/resetskill" : "/resetstate");
}
@ -9698,9 +9699,10 @@ void clif_parse_LGMmessage(int fd, struct map_session_data* sd)
unsigned int len = RFIFOW(fd,2)-4;
int lv;
if (battle_config.atc_gmonly && !pc_isGM(sd))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_LocalBroadcast)))
if( pc_isGM(sd) < (lv=get_atcommand_level(atcommand_localbroadcast)) )
return;
// as the length varies depending on the command used, just block unreasonably long strings
@ -9708,7 +9710,7 @@ void clif_parse_LGMmessage(int fd, struct map_session_data* sd)
clif_GMmessage(&sd->bl, msg, len, 1);
if(log_config.gm && lv >= log_config.gm) {
if( log_config.gm && lv >= log_config.gm ) {
char logmsg[CHAT_SIZE_MAX+5];
sprintf(logmsg, "/lb %s", msg);
log_atcommand(sd, logmsg);
@ -9963,13 +9965,13 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
if (is_charcommand(fd, sd, message) != CharCommand_None || is_atcommand(fd, sd, message) != AtCommand_None)
if( is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) )
return;
if (sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))
if( sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) )
return;
if (battle_config.min_chat_delay)
if( battle_config.min_chat_delay )
{ //[Skotlex]
if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0)
return;
@ -10236,13 +10238,13 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
if (is_charcommand(fd, sd, message) != CharCommand_None || is_atcommand(fd, sd, message) != AtCommand_None)
if( is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) )
return;
if (sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))
if( sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) )
return;
if (battle_config.min_chat_delay)
if( battle_config.min_chat_delay )
{ //[Skotlex]
if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0)
return;
@ -10379,10 +10381,10 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
struct block_list *target;
int tid,lv;
if (battle_config.atc_gmonly && !pc_isGM(sd))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_Kick)))
if( pc_isGM(sd) < (lv=get_atcommand_level(atcommand_kick)) )
return;
tid = RFIFOL(fd,2);
@ -10429,15 +10431,15 @@ void clif_parse_Shift(int fd, struct map_session_data *sd)
char *player_name;
int lv;
if (battle_config.atc_gmonly && !pc_isGM(sd))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_JumpTo)))
if( pc_isGM(sd) < (lv=get_atcommand_level(atcommand_jumpto)) )
return;
player_name = (char*)RFIFOP(fd,2);
player_name[NAME_LENGTH-1] = '\0';
atcommand_jumpto(fd, sd, "@jumpto", player_name); // as @jumpto
if(log_config.gm && lv >= log_config.gm) {
if( log_config.gm && lv >= log_config.gm ) {
char message[NAME_LENGTH+7];
sprintf(message, "/shift %s", player_name);
log_atcommand(sd, message);
@ -10453,16 +10455,16 @@ void clif_parse_Recall(int fd, struct map_session_data *sd)
char *player_name;
int lv;
if (battle_config.atc_gmonly && !pc_isGM(sd))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_Recall)))
if( pc_isGM(sd) < (lv=get_atcommand_level(atcommand_recall)) )
return;
player_name = (char*)RFIFOP(fd,2);
player_name[NAME_LENGTH-1] = '\0';
atcommand_recall(fd, sd, "@recall", player_name); // as @recall
if(log_config.gm && lv >= log_config.gm) {
if( log_config.gm && lv >= log_config.gm ) {
char message[NAME_LENGTH+8];
sprintf(message, "/recall %s", player_name);
log_atcommand(sd, message);
@ -10479,29 +10481,29 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
char message[NAME_LENGTH+10]; //For logging.
int level;
if (battle_config.atc_gmonly && !pc_isGM(sd))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
monster_item_name = (char*)RFIFOP(fd,2);
monster_item_name[NAME_LENGTH-1] = '\0';
if (mobdb_searchname(monster_item_name)) {
if (pc_isGM(sd) < (level=get_atcommand_level(AtCommand_Spawn)))
if( mobdb_searchname(monster_item_name) ) {
if( pc_isGM(sd) < (level=get_atcommand_level(atcommand_monster)) )
return;
atcommand_monster(fd, sd, "@spawn", monster_item_name); // as @spawn
if(log_config.gm && level >= log_config.gm)
atcommand_monster(fd, sd, "@monster", monster_item_name); // as @monster
if( log_config.gm && level >= log_config.gm )
{ //Log action. [Skotlex]
snprintf(message, sizeof(message)-1, "@spawn %s", monster_item_name);
log_atcommand(sd, message);
}
return;
}
if (itemdb_searchname(monster_item_name) == NULL)
if( itemdb_searchname(monster_item_name) == NULL )
return;
if (pc_isGM(sd) < (level = get_atcommand_level(AtCommand_Item)))
if( pc_isGM(sd) < (level = get_atcommand_level(atcommand_item)) )
return;
atcommand_item(fd, sd, "@item", monster_item_name); // as @item
if(log_config.gm && level >= log_config.gm)
if( log_config.gm && level >= log_config.gm )
{ //Log action. [Skotlex]
sprintf(message, "@item %s", monster_item_name);
log_atcommand(sd, message);
@ -10513,12 +10515,13 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_GMHide(int fd, struct map_session_data *sd)
{
if (battle_config.atc_gmonly && !pc_isGM(sd))
return;
if (pc_isGM(sd) < get_atcommand_level(AtCommand_Hide))
if( battle_config.atc_gmonly && !pc_isGM(sd) )
return;
if (sd->sc.option & OPTION_INVISIBLE) {
if( pc_isGM(sd) < get_atcommand_level(atcommand_hide) )
return;
if( sd->sc.option & OPTION_INVISIBLE ) {
sd->sc.option &= ~OPTION_INVISIBLE;
if (sd->disguise)
status_set_viewdata(&sd->bl, sd->disguise);
@ -10529,7 +10532,7 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd)
sd->sc.option |= OPTION_INVISIBLE;
sd->vd.class_ = INVISIBLE_CLASS;
clif_displaymessage(fd, "Invisible: On.");
if(log_config.gm && get_atcommand_level(AtCommand_Hide) >= log_config.gm)
if( log_config.gm && get_atcommand_level(atcommand_hide) >= log_config.gm )
log_atcommand(sd, "/hide");
}
clif_changeoption(&sd->bl);
@ -10560,7 +10563,7 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd)
return;
if (
((level = pc_isGM(sd)) > pc_isGM(dstsd) && level >= get_atcommand_level(AtCommand_Mute))
((level = pc_isGM(sd)) > pc_isGM(dstsd) && level >= get_atcommand_level(atcommand_mute))
|| (type == 2 && !level))
{
clif_GM_silence(sd, dstsd, ((type == 2) ? 1 : type));

View File

@ -2691,7 +2691,7 @@ int parse_console(char* buf)
ShowInfo("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y);
if( n == 5 && strcmpi("admin",type) == 0 ){
if( is_atcommand_sub(sd.fd,&sd,command,99) == AtCommand_None )
if( !is_atcommand_sub(sd.fd,&sd,command,99) )
printf("Console: not atcommand\n");
} else if( n == 2 && strcmpi("server",type) == 0 ){
if( strcmpi("shutdown",command) == 0 ||

View File

@ -666,7 +666,7 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
pc_checkitem(sd);
status_change_init(&sd->bl);
if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(AtCommand_Hide)))
if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(atcommand_hide)))
sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE);
else
sd->status.option &= OPTION_MASK;

View File

@ -11006,80 +11006,82 @@ BUILDIN_FUNC(nude)
*------------------------------------------*/
BUILDIN_FUNC(atcommand)
{
TBL_PC *sd=NULL;
const char *cmd;
TBL_PC dummy_sd;
TBL_PC* sd;
int fd;
const char* cmd;
cmd = script_getstr(st,2);
if (st->rid)
sd = script_rid2sd(st);
if (sd){
if(cmd[0] != atcommand_symbol){
cmd += strlen(sd->status.name);
while(*cmd != atcommand_symbol && *cmd != 0)
cmd++;
}
is_atcommand_sub(sd->fd, sd, cmd, 99);
if (st->rid) {
sd = script_rid2sd(st);
fd = sd->fd;
} else { //Use a dummy character.
TBL_PC dummy_sd;
struct block_list *bl = NULL;
sd = &dummy_sd;
fd = 0;
memset(&dummy_sd, 0, sizeof(TBL_PC));
if (st->oid) bl = map_id2bl(st->oid);
if (bl) {
if (st->oid)
{
struct block_list* bl = map_id2bl(st->oid);
memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
if (bl->type == BL_NPC)
strncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
}
if(cmd[0] != atcommand_symbol){
cmd += strlen(dummy_sd.status.name);
while(*cmd != atcommand_symbol && *cmd != 0)
cmd++;
}
is_atcommand_sub(0, &dummy_sd, cmd, 99);
}
// compatibility with previous implementation (deprecated!)
if(cmd[0] != atcommand_symbol)
{
cmd += strlen(sd->status.name);
while(*cmd != atcommand_symbol && *cmd != 0)
cmd++;
}
is_atcommand_sub(fd, sd, cmd, 99);
return 0;
}
BUILDIN_FUNC(charcommand)
{
TBL_PC *sd=NULL;
const char *cmd;
TBL_PC dummy_sd;
TBL_PC* sd;
int fd;
const char* cmd;
cmd = script_getstr(st,2);
if (st->rid)
if (st->rid) {
sd = script_rid2sd(st);
if (sd){
if(cmd[0] != charcommand_symbol){
cmd += strlen(sd->status.name);
while(*cmd != charcommand_symbol && *cmd != 0)
cmd++;
}
is_charcommand_sub(sd->fd, sd, cmd,99);
fd = sd->fd;
} else { //Use a dummy character.
TBL_PC dummy_sd;
struct block_list *bl = NULL;
sd = &dummy_sd;
fd = 0;
memset(&dummy_sd, 0, sizeof(TBL_PC));
if (st->oid) bl = map_id2bl(st->oid);
if (bl) {
if (st->oid)
{
struct block_list* bl = map_id2bl(st->oid);
memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
if (bl->type == BL_NPC)
strncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
}
if(cmd[0] != charcommand_symbol){
cmd += strlen(dummy_sd.status.name);
while(*cmd != charcommand_symbol && *cmd != 0)
cmd++;
}
is_charcommand_sub(0, &dummy_sd, cmd, 99);
}
// compatibility with previous implementation (deprecated!)
if(cmd[0] != charcommand_symbol)
{
cmd += strlen(sd->status.name);
while(*cmd != charcommand_symbol && *cmd != 0)
cmd++;
}
is_charcommand_sub(fd, sd, cmd, 99);
return 0;
}
/*==========================================
* Displays a message for the player only (like system messages like "you got an apple" )
*------------------------------------------*/