summaryrefslogtreecommitdiff
path: root/src/map/atcommand.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/atcommand.c')
-rw-r--r--src/map/atcommand.c371
1 files changed, 353 insertions, 18 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 2d336ddf9..2e522d541 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -8236,6 +8236,321 @@ int atcommand_allowks(const int fd, struct map_session_data *sd, const char *com
return 0;
}
+int atcommand_resetstat(const int fd, struct map_session_data* sd, const char* command, const char* message)
+{
+ nullpo_retr(-1, sd);
+
+ pc_resetstate(sd);
+ sprintf(atcmd_output, msg_txt(207), sd->status.name);
+ clif_displaymessage(fd, atcmd_output);
+ return 0;
+}
+
+int atcommand_resetskill(const int fd, struct map_session_data* sd, const char* command, const char* message)
+{
+ nullpo_retr(-1,sd);
+
+ pc_resetskill(sd,1);
+ sprintf(atcmd_output, msg_txt(206), sd->status.name);
+ clif_displaymessage(fd, atcmd_output);
+ return 0;
+}
+
+/*==========================================
+ * #storagelist <character>: Displays the items list of a player's storage.
+ *------------------------------------------*/
+int atcommand_storagelist(const int fd, struct map_session_data* sd, const char* command, const char* message)
+{
+ struct item_data *item_data, *item_temp;
+ int i, j, count = 0, counter = 0, counter2 = 0;
+ char character[NAME_LENGTH], output[200], outputtmp[200];
+ nullpo_retr(-1, sd);
+
+ memset(character, '\0', sizeof(character));
+ memset(output, '\0', sizeof(output));
+ memset(outputtmp, '\0', sizeof(outputtmp));
+
+ for (i = 0; i < MAX_STORAGE; i++)
+ {
+ struct item* it = &sd->status.storage.items[i];
+ if( it->nameid > 0 && (item_data = itemdb_search(it->nameid)) != NULL )
+ {
+ counter = counter + it->amount;
+ count++;
+ if (count == 1) {
+ sprintf(output, "------ Storage items list of '%s' ------", sd->status.name);
+ clif_displaymessage(fd, output);
+ }
+ if (it->refine)
+ sprintf(output, "%d %s %+d (%s %+d, id: %d)", it->amount, item_data->name, it->refine, item_data->jname, it->refine, it->nameid);
+ else
+ sprintf(output, "%d %s (%s, id: %d)", it->amount, item_data->name, item_data->jname, it->nameid);
+ clif_displaymessage(fd, output);
+
+ memset(output, '\0', sizeof(output));
+ counter2 = 0;
+ for (j = 0; j < item_data->slot; j++) {
+ if (it->card[j]) {
+ if ((item_temp = itemdb_search(it->card[j])) != NULL) {
+ if (output[0] == '\0')
+ sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ else
+ sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ strcat(output, outputtmp);
+ }
+ }
+ }
+ if (output[0] != '\0') {
+ output[strlen(output) - 2] = ')';
+ output[strlen(output) - 1] = '\0';
+ clif_displaymessage(fd, output);
+ }
+ }
+ }
+
+ if (count == 0)
+ clif_displaymessage(fd, "No item found in the storage of this player.");
+ else {
+ sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
+ clif_displaymessage(fd, output);
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * Displays contents of target's cart [HiddenDragon]
+ *------------------------------------------*/
+int atcommand_cart_list(const int fd, struct map_session_data* sd, const char* command, const char* message)
+{
+ char outputtmp[200];
+ char output[200];
+ char character[NAME_LENGTH];
+ struct item_data *item_data, *item_temp;
+ int i, j, count = 0, counter = 0, counter2;
+ nullpo_retr(-1, sd);
+
+ memset(character, '\0', sizeof(character));
+ memset(output, '\0', sizeof(output));
+ memset(outputtmp, '\0', sizeof(outputtmp));
+
+ for (i = 0; i < MAX_CART; i++) {
+ if (sd->status.cart[i].nameid > 0 && (item_data = itemdb_search(sd->status.cart[i].nameid)) != NULL) {
+ counter = counter + sd->status.cart[i].amount;
+ count++;
+ if (count == 1) {
+ sprintf(output, "------ Cart items list of '%s' ------", sd->status.name);
+ clif_displaymessage(fd, output);
+ }
+ if (sd->status.cart[i].refine)
+ sprintf(output, "%d %s %+d (%s %+d, id: %d)", sd->status.cart[i].amount, item_data->name, sd->status.cart[i].refine, item_data->jname, sd->status.cart[i].refine, sd->status.cart[i].nameid);
+ else
+ sprintf(output, "%d %s (%s, id: %d)", sd->status.cart[i].amount, item_data->name, item_data->jname, sd->status.cart[i].nameid);
+ clif_displaymessage(fd, output);
+ memset(output, '\0', sizeof(output));
+ counter2 = 0;
+ for (j = 0; j < item_data->slot; j++) {
+ if (sd->status.cart[i].card[j]) {
+ if ( (item_temp = itemdb_search(sd->status.cart[i].card[j])) != NULL) {
+ if (output[0] == '\0')
+ sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ else
+ sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ strcat(output, outputtmp);
+ }
+ }
+ }
+ if (output[0] != '\0') {
+ output[strlen(output) - 2] = ')';
+ output[strlen(output) - 1] = '\0';
+ clif_displaymessage(fd, output);
+ }
+ }
+ }
+ if (count == 0)
+ clif_displaymessage(fd, "No item found in the cart of this player.");
+ else {
+ sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
+ clif_displaymessage(fd, output);
+ }
+
+ return 0;
+}
+
+int atcommand_itemlist(const int fd, struct map_session_data* sd, const char* command, const char* message)
+{
+ struct item_data *item_data, *item_temp;
+ int i, j, equip, count, counter, counter2;
+ char character[NAME_LENGTH], output[200], equipstr[100], outputtmp[200];
+ struct item *i_item; //Current inventory item.
+ nullpo_retr(-1, sd);
+
+ memset(character, '\0', sizeof(character));
+ memset(output, '\0', sizeof(output));
+ memset(equipstr, '\0', sizeof(equipstr));
+ memset(outputtmp, '\0', sizeof(outputtmp));
+
+ counter = 0;
+ count = 0;
+ for (i = 0; i < MAX_INVENTORY; i++) {
+ i_item = &sd->status.inventory[i];
+ if (sd->status.inventory[i].nameid > 0 && (item_data = itemdb_exists(i_item->nameid)) != NULL) {
+ counter = counter + i_item->amount;
+ count++;
+ if (count == 1) {
+ sprintf(output, "------ Items list of '%s' ------", sd->status.name);
+ clif_displaymessage(fd, output);
+ }
+ if ((equip = i_item->equip)) {
+ strcpy(equipstr, "| equiped: ");
+ if (equip & EQP_GARMENT)
+ strcat(equipstr, "robe/gargment, ");
+ if (equip & EQP_ACC_L)
+ strcat(equipstr, "left accessory, ");
+ if (equip & EQP_ARMOR)
+ strcat(equipstr, "body/armor, ");
+ if ((equip & EQP_ARMS) == EQP_HAND_R)
+ strcat(equipstr, "right hand, ");
+ if ((equip & EQP_ARMS) == EQP_HAND_L)
+ strcat(equipstr, "left hand, ");
+ if ((equip & EQP_ARMS) == EQP_ARMS)
+ strcat(equipstr, "both hands, ");
+ if (equip & EQP_SHOES)
+ strcat(equipstr, "feet, ");
+ if (equip & EQP_ACC_R)
+ strcat(equipstr, "right accessory, ");
+ if ((equip & EQP_HELM) == EQP_HEAD_LOW)
+ strcat(equipstr, "lower head, ");
+ if ((equip & EQP_HELM) == EQP_HEAD_TOP)
+ strcat(equipstr, "top head, ");
+ if ((equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_TOP))
+ strcat(equipstr, "lower/top head, ");
+ if ((equip & EQP_HELM) == EQP_HEAD_MID)
+ strcat(equipstr, "mid head, ");
+ if ((equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_MID))
+ strcat(equipstr, "lower/mid head, ");
+ if ((equip & EQP_HELM) == EQP_HELM)
+ strcat(equipstr, "lower/mid/top head, ");
+ // remove final ', '
+ equipstr[strlen(equipstr) - 2] = '\0';
+ } else
+ memset(equipstr, '\0', sizeof(equipstr));
+ if (i_item->refine)
+ sprintf(output, "%d %s %+d (%s %+d, id: %d) %s", i_item->amount, item_data->name, i_item->refine, item_data->jname, i_item->refine, i_item->nameid, equipstr);
+ else
+ sprintf(output, "%d %s (%s, id: %d) %s", i_item->amount, item_data->name, item_data->jname, i_item->nameid, equipstr);
+ clif_displaymessage(fd, output);
+ memset(output, '\0', sizeof(output));
+ counter2 = 0;
+
+ if(i_item->card[0]==CARD0_PET) { //pet eggs
+ if (i_item->card[3])
+ sprintf(outputtmp, " -> (pet egg, pet id: %u, named)", (unsigned int)MakeDWord(i_item->card[1], i_item->card[2]));
+ else
+ sprintf(outputtmp, " -> (pet egg, pet id: %u, unnamed)", (unsigned int)MakeDWord(i_item->card[1], i_item->card[2]));
+ strcat(output, outputtmp);
+ } else
+ if(i_item->card[0]==CARD0_FORGE) { //forged items.
+ sprintf(outputtmp, " -> (crafted item, creator id: %u, star crumbs %d, element %d)", (unsigned int)MakeDWord(i_item->card[2], i_item->card[3]), i_item->card[1]>>8, i_item->card[1]&0x0f);
+ } else
+ if(i_item->card[0]==CARD0_CREATE) { //created items.
+ sprintf(outputtmp, " -> (produced item, creator id: %u)", (unsigned int)MakeDWord(i_item->card[2], i_item->card[3]));
+ strcat(output, outputtmp);
+ } else //Normal slots
+ for (j = 0; j < item_data->slot; j++) {
+ if (sd->status.inventory[i].card[j]) {
+ if ((item_temp = itemdb_exists(i_item->card[j])) != NULL) {
+ if (output[0] == '\0')
+ sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ else
+ sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ strcat(output, outputtmp);
+ }
+ }
+ }
+ if (output[0] != '\0') {
+ output[strlen(output) - 2] = ')';
+ output[strlen(output) - 1] = '\0';
+ clif_displaymessage(fd, output);
+ }
+ }
+ }
+ if (count == 0)
+ {
+ clif_displaymessage(fd, "No item found on this player.");
+ return -1;
+ }
+
+ sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
+ clif_displaymessage(fd, output);
+ return 0;
+}
+
+int atcommand_stats(const int fd, struct map_session_data* sd, const char* command, const char* message)
+{
+ char character[NAME_LENGTH];
+ char job_jobname[100];
+ char output[200];
+ int i;
+ struct {
+ const char* format;
+ int value;
+ } output_table[] = {
+ { "Base Level - %d", 0 },
+ { NULL, 0 },
+ { "Hp - %d", 0 },
+ { "MaxHp - %d", 0 },
+ { "Sp - %d", 0 },
+ { "MaxSp - %d", 0 },
+ { "Str - %3d", 0 },
+ { "Agi - %3d", 0 },
+ { "Vit - %3d", 0 },
+ { "Int - %3d", 0 },
+ { "Dex - %3d", 0 },
+ { "Luk - %3d", 0 },
+ { "Zeny - %d", 0 },
+ { "Free SK Points - %d", 0 },
+ { "JobChangeLvl - %d", 0 },
+ { NULL, 0 }
+ };
+
+ memset(character, '\0', sizeof(character));
+ memset(job_jobname, '\0', sizeof(job_jobname));
+ memset(output, '\0', sizeof(output));
+
+ //direct array initialization with variables is not standard C compliant.
+ output_table[0].value = sd->status.base_level;
+ output_table[1].format = job_jobname;
+ output_table[1].value = sd->status.job_level;
+ output_table[2].value = sd->status.hp;
+ output_table[3].value = sd->status.max_hp;
+ output_table[4].value = sd->status.sp;
+ output_table[5].value = sd->status.max_sp;
+ output_table[6].value = sd->status.str;
+ output_table[7].value = sd->status.agi;
+ output_table[8].value = sd->status.vit;
+ output_table[9].value = sd->status.int_;
+ output_table[10].value = sd->status.dex;
+ output_table[11].value = sd->status.luk;
+ output_table[12].value = sd->status.zeny;
+ output_table[13].value = sd->status.skill_point;
+ output_table[14].value = sd->change_level;
+
+ sprintf(job_jobname, "Job - %s %s", job_name(sd->status.class_), "(level %d)");
+ sprintf(output, msg_txt(53), sd->status.name); // '%s' stats:
+
+ clif_displaymessage(fd, output);
+
+ for (i = 0; output_table[i].format != NULL; i++) {
+ sprintf(output, output_table[i].format, output_table[i].value);
+ clif_displaymessage(fd, output);
+ }
+
+ return 0;
+}
+
+
+
/*==========================================
* atcommand_info[] structure definition
*------------------------------------------*/
@@ -8530,6 +8845,12 @@ AtCommandInfo atcommand_info[] = {
{ "points", 60,60, atcommand_cash },
{ "agitstart2", 60,60, atcommand_agitstart2 },
{ "agitend2", 60,60, atcommand_agitend2 },
+ { "skreset", 60,60, atcommand_resetskill },
+ { "streset", 60,60, atcommand_resetstat },
+ { "storagelist", 40,40, atcommand_storagelist },
+ { "cartlist", 40,40, atcommand_cart_list },
+ { "itemlist", 40,40, atcommand_itemlist },
+ { "stats", 40,40, atcommand_stats },
};
@@ -8564,9 +8885,8 @@ int get_atcommand_level(const AtCommandFunc func)
/// Executes an at-command.
/// To be called by internal server code (bypasses various restrictions).
-bool is_atcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl, const char charname[NAME_LENGTH])
+bool is_atcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl)
{
- struct map_session_data* ssd;
AtCommandInfo* info;
char command[100];
char args[100];
@@ -8594,12 +8914,9 @@ bool is_atcommand_sub(const int fd, struct map_session_data* sd, const char* str
}
}
- if( log_config.gm && info->level >= log_config.gm ) {
- if( (ssd = map_nick2sd(charname)) != NULL )
- log_atcommand(ssd, str);
- else
+ //fd will not equal sd->fd if it's a charcommand. Of course, using a charcommand on yourself would make it = sd->fd as well
+ if( log_config.gm && ( info->level >= log_config.gm || info->level2 >= log_config.gm ) && fd == sd->fd)
log_atcommand(sd, str);
- }
if( info->func(fd, sd, command, args) != 0 )
{
@@ -8619,6 +8936,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
char charname[NAME_LENGTH];
char cmd[100];
char param[100];
+ char output[200];
+ char output2[200];
const char* message2;
int gmlvl = pc_isGM(sd);
@@ -8651,22 +8970,22 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
{
if ( (pl_sd = map_nick2sd(charname)) == NULL )
{
- sprintf(atcmd_output, "%s failed. Player %s not found.", cmd, charname);
- clif_displaymessage(fd, atcmd_output);
+ sprintf(output, "%s failed. Player %s not found.", cmd, charname);
+ clif_displaymessage(fd, output);
return true;
}
else {
//we pass fd instead of pl_sd->fd otherwise command output messages are sent to the target
//also, the name is taken out of the message since it's not needed anymore
- sprintf(atcmd_output, "%s %s", cmd, param);
- memcpy(atcmd_temp, atcmd_output, sizeof(atcmd_output));
- message2 = atcmd_temp;
- return is_atcommand_sub(fd,pl_sd,message2,gmlvl,sd->status.name);
+ sprintf(output, "%s %s", cmd, param);
+ memcpy(output2, output, sizeof(output2));
+ message2 = output2;
+ return is_atcommand_sub(fd,pl_sd,message2,gmlvl);
}
}
}
- return is_atcommand_sub(fd,sd,message,gmlvl,sd->status.name);
+ return is_atcommand_sub(fd,sd,message,gmlvl);
}
@@ -8690,8 +9009,8 @@ int atcommand_config_read(const char* cfgName)
if( line[0] == '/' && line[1] == '/' )
continue;
- if( (sscanf(line, "%1023[^:]:%1023[^,],%1023s", w1, w2, w3)) != 3
- && ( sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2 && strcmpi(w1, "import") != 0 ) )
+ if( (sscanf(line, "%1023[^:]:%1023[^,],%1023s", w1, w2, w3)) != 3 && ( sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2
+ && strcmpi(w1, "import") != 0 ) && strcmpi(w1, "command_symbol") != 0 && strcmpi(w1, "char_symbol") != 0 )
continue;
p = get_atcommandinfo_byname(w1);
@@ -8699,8 +9018,16 @@ int atcommand_config_read(const char* cfgName)
{
p->level = atoi(w2);
p->level = cap_value(p->level, 0, 100);
- p->level2 = atoi(w3);
- p->level2 = cap_value(p->level2, 0, 100);
+ if( (sscanf(line, "%1023[^:]:%1023s", w1, w2) == 2) && (sscanf(line, "%1023[^:]:%1023[^,],%1023s", w1, w2, w3)) != 3 )
+ {
+ ShowWarning("atcommand_conf: setting %s:%d is deprecated! Please see atcommand_athena.conf for the new setting format.\n",w1,atoi(w2));
+ ShowWarning("atcommand_conf: defaulting %s charcommand level to %d.\n",w1,atoi(w2));
+ p->level2 = atoi(w2);
+ }
+ else {
+ p->level2 = atoi(w3);
+ p->level2 = cap_value(p->level2, 0, 100);
+ }
}
else
if( strcmpi(w1, "import") == 0 )
@@ -8713,6 +9040,14 @@ int atcommand_config_read(const char* cfgName)
w2[0] != '$' && // symbol of guild chat speaking
w2[0] != '#' ) // remote symbol
atcommand_symbol = w2[0];
+ else
+ if( strcmpi(w1, "char_symbol") == 0 &&
+ w2[0] > 31 &&
+ w2[0] != '/' &&
+ w2[0] != '%' &&
+ w2[0] != '$' &&
+ w2[0] != '@' )
+ charcommand_symbol = w2[0];
else
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}