root/src/map/charcommand.c @ 13

Revision 1, 127.8 kB (checked in by jinshiro, 17 years ago)
Line 
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/cbasetypes.h"
5#include "../common/mmo.h"
6#include "../common/timer.h"
7#include "../common/nullpo.h"
8#include "../common/showmsg.h"
9#include "../common/strlib.h"
10#include "../common/utils.h"
11
12#include "atcommand.h" // msg_txt()
13#include "charcommand.h"
14#include "battle.h"
15#include "clif.h"
16#include "chrif.h"
17#include "intif.h"
18#include "itemdb.h"
19#include "log.h"
20#include "map.h"
21#include "pc.h"
22#include "status.h"
23#include "skill.h"
24#include "mob.h"
25#include "npc.h"
26#include "pet.h"
27#include "mercenary.h"
28#include "party.h"
29#include "guild.h"
30#include "script.h"
31#include "trade.h"
32#include "unit.h"
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <math.h>
38
39char charcommand_symbol = '#';
40
41extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
42
43#define CCMD_FUNC(x) int charcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
44
45typedef struct CharCommandInfo {
46        const char* command;
47        int level;
48        CharCommandFunc func;
49} CharCommandInfo;
50
51static CharCommandInfo* get_charcommandinfo_byname(const char* name);
52static CharCommandInfo* get_charcommandinfo_byfunc(const CharCommandFunc func);
53
54
55/*==========================================
56 * ‘ΏۃLƒƒƒ‰ƒNƒ^[‚ð“]E‚³‚¹‚é upperŽw’è‚Å“]¶‚â—{Žq‚à‰Â”\
57 *------------------------------------------*/
58int charcommand_jobchange(const int fd, struct map_session_data* sd, const char* command, const char* message)
59{
60        char character[100];
61        struct map_session_data* pl_sd;
62        int job = 0, upper = -1;
63
64        memset(character, '\0', sizeof(character));
65
66        if (!message || !*message || sscanf(message, "%d %23[^\n]", &job, character) < 2) {
67                clif_displaymessage(fd, "Please, enter a job and a player name (usage: #job/#jobchange <job ID> <player>).");
68                clif_displaymessage(fd, "   0 Novice            7 Knight           14 Crusader         21 Peco Crusader");
69                clif_displaymessage(fd, "   1 Swordman          8 Priest           15 Monk             22 N/A");
70                clif_displaymessage(fd, "   2 Mage              9 Wizard           16 Sage             23 Super Novice");
71                clif_displaymessage(fd, "   3 Archer           10 Blacksmith       17 Rogue            24 Gunslinger");
72                clif_displaymessage(fd, "   4 Acolyte          11 Hunter           18 Alchemist        25 Ninja");
73                clif_displaymessage(fd, "   5 Merchant         12 Assassin         19 Bard             26 N/A");
74                clif_displaymessage(fd, "   6 Thief            13 Peco Knight      20 Dancer");
75                clif_displaymessage(fd, "4001 Novice High    4008 Lord Knight      4015 Paladin        4022 Peco Paladin");
76                clif_displaymessage(fd, "4002 Swordman High  4009 High Priest      4016 Champion");
77                clif_displaymessage(fd, "4003 Mage High      4010 High Wizard      4017 Professor");
78                clif_displaymessage(fd, "4004 Archer High    4011 Whitesmith       4018 Stalker");
79                clif_displaymessage(fd, "4005 Acolyte High   4012 Sniper           4019 Creator");
80                clif_displaymessage(fd, "4006 Merchant High  4013 Assassin Cross   4020 Clown");
81                clif_displaymessage(fd, "4007 Thief High     4014 Peco Lord Knight 4021 Gypsy");
82                clif_displaymessage(fd, "4023 Baby Novice    4030 Baby Knight      4037 Baby Crusader  4044 Baby Peco Crusader");
83                clif_displaymessage(fd, "4024 Baby Swordsman 4031 Baby Priest      4038 Baby Monk      4045 Super Baby");
84                clif_displaymessage(fd, "4025 Baby Mage      4032 Baby Wizard      4039 Baby Sage      4046 Taekwon Kid");
85                clif_displaymessage(fd, "4026 Baby Archer    4033 Baby Blacksmith  4040 Baby Rogue     4047 Taekwon Master");
86                clif_displaymessage(fd, "4027 Baby Acolyte   4034 Baby Hunter      4041 Baby Alchemist 4048 N/A");
87                clif_displaymessage(fd, "4028 Baby Merchant  4035 Baby Assassin    4042 Baby Bard      4049 Soul Linker");
88                clif_displaymessage(fd, "4029 Baby Thief     4036 Baby Peco-Knight 4043 Baby Dancer");
89                return -1;
90        }
91
92        if ((pl_sd = map_nick2sd(character)) == NULL) {
93                clif_displaymessage(fd, msg_txt(3)); // Character not found.
94                return -1;
95        }
96
97        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
98        {
99                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
100                return -1;
101        }
102
103        if (!pcdb_checkid(job)) {
104                clif_displaymessage(fd, msg_txt(49)); // Invalid job ID.
105                return -1;
106        }
107
108        if (pc_jobchange(pl_sd, job, upper) != 0) {
109                clif_displaymessage(fd, msg_txt(192)); // Impossible to change the character's job.
110                return -1;
111        }
112
113        clif_displaymessage(fd, msg_txt(48)); // Character's job changed.
114        return 0;
115}
116
117/*==========================================
118 *
119 *------------------------------------------*/
120int charcommand_petrename(const int fd, struct map_session_data* sd, const char* command, const char* message)
121{
122        char character[NAME_LENGTH];
123        struct map_session_data *pl_sd;
124        struct pet_data *pd;
125
126        memset(character, '\0', sizeof(character));
127
128        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
129                clif_displaymessage(fd, "Please, enter a player name (usage: #petrename <player>).");
130                return -1;
131        }
132
133        if ((pl_sd = map_nick2sd(character)) == NULL) {
134                clif_displaymessage(fd, msg_txt(3)); // Character not found.
135                return -1;
136        }
137
138        if (!pl_sd->status.pet_id || !pl_sd->pd) {
139                clif_displaymessage(fd, msg_txt(191)); // Sorry, but this player has no pet.
140                return -1;
141        }
142
143        pd = pl_sd->pd;
144
145        if (pd->pet.rename_flag) {
146                clif_displaymessage(fd, msg_txt(190)); // This player can already rename his/her pet.
147                return -1;
148        }
149        pd->pet.rename_flag = 0;
150        intif_save_petdata(pl_sd->status.account_id, &pd->pet);
151        clif_send_petstatus(pl_sd);
152        clif_displaymessage(fd, msg_txt(189)); // This player can now rename his/her pet.
153        return 0;
154}
155
156
157/*==========================================
158 *
159 *------------------------------------------*/
160int charcommand_petfriendly(const int fd, struct map_session_data* sd, const char* command, const char* message)
161{
162        int friendly = 0;
163        char character[NAME_LENGTH];
164        struct map_session_data *pl_sd;
165        struct pet_data *pd;
166
167        memset(character, '\0', sizeof(character));
168        if (!message || !*message || sscanf(message,"%d %23s",&friendly,character) < 2) {
169                clif_displaymessage(fd, "Please, enter a valid value (usage: #petfriendly <0-1000> <player>).");
170                return -1;
171        }
172
173        if ( (pl_sd = map_nick2sd(character)) == NULL )
174        {
175                clif_displaymessage(fd, msg_txt(3)); // Character not found.
176                return -1;
177        }
178
179        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
180        {
181                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
182                return -1;
183        }
184
185        if (!pl_sd->status.pet_id  || !pl_sd->pd) {
186                clif_displaymessage(fd, msg_txt(191)); // Sorry, but this player has no pet.
187                return -1;
188        }
189
190        friendly = cap_value(friendly, 0, 1000);
191
192        pd = pl_sd->pd;
193        if (friendly == pd->pet.intimate) {
194                clif_displaymessage(fd, msg_txt(183)); // Pet friendly is already the good value.
195                return -1;
196        }
197       
198        pd->pet.intimate = friendly;
199        clif_send_petstatus(pl_sd);
200        clif_pet_emotion(pd,0);
201        clif_displaymessage(pl_sd->fd, msg_txt(182)); // Pet friendly value changed!
202        clif_displaymessage(sd->fd, msg_txt(182)); // Pet friendly value changed!
203        return 0;
204}
205
206/*==========================================
207 *
208 *------------------------------------------*/
209int charcommand_stats(const int fd, struct map_session_data* sd, const char* command, const char* message)
210{
211        char character[NAME_LENGTH];
212        char job_jobname[100];
213        char output[200];
214        struct map_session_data *pl_sd;
215        int i;
216        struct {
217                const char* format;
218                int value;
219        } output_table[] = {
220                { "Base Level - %d", 0 },
221                { NULL, 0 },
222                { "Hp - %d", 0 },
223                { "MaxHp - %d", 0 },
224                { "Sp - %d", 0 },
225                { "MaxSp - %d", 0 },
226                { "Str - %3d", 0 },
227                { "Agi - %3d", 0 },
228                { "Vit - %3d", 0 },
229                { "Int - %3d", 0 },
230                { "Dex - %3d", 0 },
231                { "Luk - %3d", 0 },
232                { "Zeny - %d", 0 },
233                { "Free SK Points - %d", 0 },
234                { "JobChangeLvl - %d", 0 },
235                { NULL, 0 }
236        };
237
238        memset(character, '\0', sizeof(character));
239        memset(job_jobname, '\0', sizeof(job_jobname));
240        memset(output, '\0', sizeof(output));
241
242        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
243                clif_displaymessage(fd, "Please, enter a player name (usage: #stats <player>).");
244                return -1;
245        }
246
247        if ( (pl_sd = map_nick2sd(character)) == NULL )
248        {
249                clif_displaymessage(fd, msg_txt(3)); // Character not found.
250                return -1;
251        }
252
253        //direct array initialization with variables is not standard C compliant.
254        output_table[0].value = pl_sd->status.base_level;
255        output_table[1].format = job_jobname;
256        output_table[1].value = pl_sd->status.job_level;
257        output_table[2].value = pl_sd->status.hp;
258        output_table[3].value = pl_sd->status.max_hp;
259        output_table[4].value = pl_sd->status.sp;
260        output_table[5].value = pl_sd->status.max_sp;
261        output_table[6].value = pl_sd->status.str;
262        output_table[7].value = pl_sd->status.agi;
263        output_table[8].value = pl_sd->status.vit;
264        output_table[9].value = pl_sd->status.int_;
265        output_table[10].value = pl_sd->status.dex;
266        output_table[11].value = pl_sd->status.luk;
267        output_table[12].value = pl_sd->status.zeny;
268        output_table[13].value = pl_sd->status.skill_point;
269        output_table[14].value = pl_sd->change_level;
270
271        sprintf(job_jobname, "Job - %s %s", job_name(pl_sd->status.class_), "(level %d)");
272        sprintf(output, msg_txt(53), pl_sd->status.name); // '%s' stats:
273
274        clif_displaymessage(fd, output);
275       
276        for (i = 0; output_table[i].format != NULL; i++) {
277                sprintf(output, output_table[i].format, output_table[i].value);
278                clif_displaymessage(fd, output);
279        }
280
281        return 0;
282}
283
284/*==========================================
285 * Character Reset
286 *------------------------------------------*/
287int charcommand_reset(const int fd, struct map_session_data* sd, const char* command, const char* message)
288{
289        char character[NAME_LENGTH];
290        char output[200];
291        struct map_session_data *pl_sd;
292
293        memset(character, '\0', sizeof(character));
294        memset(output, '\0', sizeof(output));
295
296        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
297                clif_displaymessage(fd, "Please, enter a player name (usage: #reset <player>).");
298                return -1;
299        }
300
301        if ( (pl_sd = map_nick2sd(character)) == NULL )
302        {
303                clif_displaymessage(fd, msg_txt(3)); // Character not found.
304                return -1;
305        }
306
307        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
308        {
309                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
310                return -1;
311        }
312
313        pc_resetstate(pl_sd);
314        pc_resetskill(pl_sd,1);
315        sprintf(output, msg_txt(208), character); // '%s' skill and stats points reseted!
316        clif_displaymessage(fd, output);
317
318        return 0;
319}
320
321/*==========================================
322 *
323 *------------------------------------------*/
324int charcommand_option(const int fd, struct map_session_data* sd, const char* command, const char* message)
325{
326        char character[NAME_LENGTH];
327        int opt1 = 0, opt2 = 0, opt3 = 0;
328        struct map_session_data* pl_sd;
329
330        memset(character, '\0', sizeof(character));
331
332        if (!message || !*message ||
333                sscanf(message, "%d %d %d %23[^\n]", &opt1, &opt2, &opt3, character) < 4 ||
334                opt1 < 0 || opt2 < 0 || opt3 < 0) {
335                clif_displaymessage(fd, "Please, enter valid options and a player name (usage: #option <param1> <param2> <param3> <player>).");
336                return -1;
337        }
338
339        if ( (pl_sd = map_nick2sd(character)) == NULL )
340        {
341                clif_displaymessage(fd, msg_txt(3)); // Character not found.
342                return -1;
343        }
344
345        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
346        {
347                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
348                return -1;
349        }
350
351        pl_sd->sc.opt1 = opt1;
352        pl_sd->sc.opt2 = opt2;
353        pc_setoption(pl_sd, opt3);
354        clif_displaymessage(fd, msg_txt(58)); // Character's options changed.
355
356        return 0;
357}
358
359/*==========================================
360 *
361 *------------------------------------------*/
362int charcommand_save(const int fd, struct map_session_data* sd, const char* command, const char* message)
363{
364        char map_name[MAP_NAME_LENGTH_EXT];
365        char character[NAME_LENGTH];
366        struct map_session_data* pl_sd;
367        int x = 0, y = 0;
368        int m;
369
370        memset(map_name, '\0', sizeof(map_name));
371        memset(character, '\0', sizeof(character));
372
373        if (!message || !*message || sscanf(message, "%15s %d %d %23[^\n]", map_name, &x, &y, character) < 4 || x < 0 || y < 0) {
374                clif_displaymessage(fd, "Please, enter a valid save point and a player name (usage: #save <map> <x> <y> <player>).");
375                return -1;
376        }
377
378        if ( (pl_sd = map_nick2sd(character)) == NULL )
379        {
380                clif_displaymessage(fd, msg_txt(3)); // Character not found.
381                return -1;
382        }
383
384        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
385        {
386                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
387                return -1;
388        }
389
390        m = map_mapname2mapid(map_name);
391        if (m < 0 && !mapindex_name2id(map_name)) {
392                clif_displaymessage(fd, msg_txt(1)); // Map not found.
393                return -1;
394        }
395
396        //FIXME: What do you do if the map is in another map server with the nowarpto flag?
397        if (m>=0 && map[m].flag.nosave && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
398                clif_displaymessage(fd, "You are not authorised to set this map as a save map.");
399                return -1;
400        }
401
402        if (m>=0)
403                pc_setsavepoint(pl_sd, map[m].index, x, y);
404        else
405                pc_setsavepoint(pl_sd, mapindex_name2id(map_name), x, y);
406        clif_displaymessage(fd, msg_txt(57)); // Character's respawn point changed.
407
408        return 0;
409}
410
411/*==========================================
412 * CharSpiritBall Function by PalasX
413 *------------------------------------------*/
414int charcommand_spiritball(const int fd, struct map_session_data* sd,const char* command, const char* message)
415{
416        struct map_session_data *pl_sd;
417        char character[NAME_LENGTH];
418        int spirit = 0;
419
420        memset(character, '\0', sizeof(character));
421
422        if(!message || !*message || sscanf(message, "%d %23[^\n]", &spirit, character) < 2 || spirit < 0 || spirit > 1000) {
423                clif_displaymessage(fd, "Usage: @spiritball <number: 0-1000> <player>.");
424                return -1;
425        }
426
427        if ( (pl_sd = map_nick2sd(character)) == NULL )
428        {
429                clif_displaymessage(fd, msg_txt(3)); // Character not found.
430                return -1;
431        }
432
433        if (spirit >= 0 && spirit <= 0x7FFF) {
434                if (pl_sd->spiritball != spirit || spirit > 999) {
435                        if (pl_sd->spiritball > 0)
436                                pc_delspiritball(pl_sd, pl_sd->spiritball, 1);
437                }
438                pl_sd->spiritball = spirit;
439                clif_spiritball(pl_sd);
440                // no message, player can look the difference
441                if (spirit > 1000)
442                        clif_displaymessage(fd, msg_txt(204)); // WARNING: more than 1000 spiritballs can CRASH your server and/or client!
443        } else {
444                clif_displaymessage(fd, msg_txt(205)); // You already have this number of spiritballs.
445                return -1;
446        }
447
448        return 0;
449}
450
451/*==========================================
452 * #itemlist <character>: Displays the list of a player's items.
453 *------------------------------------------*/
454int charcommand_itemlist(const int fd, struct map_session_data* sd, const char* command, const char* message)
455{
456        struct map_session_data *pl_sd;
457        struct item_data *item_data, *item_temp;
458        int i, j, equip, count, counter, counter2;
459        char character[NAME_LENGTH], output[200], equipstr[100], outputtmp[200];
460        struct item *i_item; //Current inventory item.
461        nullpo_retr(-1, sd);
462
463        memset(character, '\0', sizeof(character));
464        memset(output, '\0', sizeof(output));
465        memset(equipstr, '\0', sizeof(equipstr));
466        memset(outputtmp, '\0', sizeof(outputtmp));
467
468        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
469                clif_displaymessage(fd, "Please, enter a player name (usage: #itemlist <player>).");
470                return -1;
471        }
472
473        if ( (pl_sd = map_nick2sd(character)) == NULL )
474        {
475                clif_displaymessage(fd, msg_txt(3)); // Character not found.
476                return -1;
477        }
478
479        counter = 0;
480        count = 0;
481        for (i = 0; i < MAX_INVENTORY; i++) {
482                i_item = &pl_sd->status.inventory[i];
483                if (pl_sd->status.inventory[i].nameid > 0 && (item_data = itemdb_exists(i_item->nameid)) != NULL) {
484                        counter = counter + i_item->amount;
485                        count++;
486                        if (count == 1) {
487                                sprintf(output, "------ Items list of '%s' ------", pl_sd->status.name);
488                                clif_displaymessage(fd, output);
489                        }
490                        if ((equip = i_item->equip)) {
491                                strcpy(equipstr, "| equiped: ");
492                                if (equip & EQP_GARMENT)
493                                        strcat(equipstr, "robe/gargment, ");
494                                if (equip & EQP_ACC_L)
495                                        strcat(equipstr, "left accessory, ");
496                                if (equip & EQP_ARMOR)
497                                        strcat(equipstr, "body/armor, ");
498                                if ((equip & EQP_ARMS) == EQP_HAND_R)
499                                        strcat(equipstr, "right hand, ");
500                                if ((equip & EQP_ARMS) == EQP_HAND_L)
501                                        strcat(equipstr, "left hand, ");
502                                if ((equip & EQP_ARMS) == EQP_ARMS)
503                                        strcat(equipstr, "both hands, ");
504                                if (equip & EQP_SHOES)
505                                        strcat(equipstr, "feet, ");
506                                if (equip & EQP_ACC_R)
507                                        strcat(equipstr, "right accessory, ");
508                                if ((equip & EQP_HELM) == EQP_HEAD_LOW)
509                                        strcat(equipstr, "lower head, ");
510                                if ((equip & EQP_HELM) == EQP_HEAD_TOP)
511                                        strcat(equipstr, "top head, ");
512                                if ((equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_TOP))
513                                        strcat(equipstr, "lower/top head, ");
514                                if ((equip & EQP_HELM) == EQP_HEAD_MID)
515                                        strcat(equipstr, "mid head, ");
516                                if ((equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_MID))
517                                        strcat(equipstr, "lower/mid head, ");
518                                if ((equip & EQP_HELM) == EQP_HELM)
519                                        strcat(equipstr, "lower/mid/top head, ");
520                                // remove final ', '
521                                equipstr[strlen(equipstr) - 2] = '\0';
522                        } else
523                                memset(equipstr, '\0', sizeof(equipstr));
524                        if (i_item->refine)
525                                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);
526                        else
527                                sprintf(output, "%d %s (%s, id: %d) %s", i_item->amount, item_data->name, item_data->jname, i_item->nameid, equipstr);
528                        clif_displaymessage(fd, output);
529                        memset(output, '\0', sizeof(output));
530                        counter2 = 0;
531
532                        if(i_item->card[0]==CARD0_PET) { //pet eggs
533                                if (i_item->card[3])
534                                        sprintf(outputtmp, " -> (pet egg, pet id: %u, named)", (unsigned int)MakeDWord(i_item->card[1], i_item->card[2]));
535                                else
536                                        sprintf(outputtmp, " -> (pet egg, pet id: %u, unnamed)", (unsigned int)MakeDWord(i_item->card[1], i_item->card[2]));
537                                strcat(output, outputtmp);
538                        } else
539                        if(i_item->card[0]==CARD0_FORGE) { //forged items.
540                                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);
541                        } else
542                        if(i_item->card[0]==CARD0_CREATE) { //created items.
543                                sprintf(outputtmp, " -> (produced item, creator id: %u)", (unsigned int)MakeDWord(i_item->card[2], i_item->card[3]));
544                                strcat(output, outputtmp);
545                        } else //Normal slots
546                        for (j = 0; j < item_data->slot; j++) {
547                                if (pl_sd->status.inventory[i].card[j]) {
548                                        if ((item_temp = itemdb_exists(i_item->card[j])) != NULL) {
549                                                if (output[0] == '\0')
550                                                        sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
551                                                else
552                                                        sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
553                                                strcat(output, outputtmp);
554                                        }
555                                }
556                        }
557                        if (output[0] != '\0') {
558                                output[strlen(output) - 2] = ')';
559                                output[strlen(output) - 1] = '\0';
560                                clif_displaymessage(fd, output);
561                        }
562                }
563        }
564        if (count == 0)
565        {
566                clif_displaymessage(fd, "No item found on this player.");
567                return -1;
568        }
569
570        sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
571        clif_displaymessage(fd, output);
572        return 0;
573}
574
575/*==========================================
576 * #effect by [MouseJstr]
577 *
578 * Create a effect localized on another character
579 *------------------------------------------*/
580int charcommand_effect(const int fd, struct map_session_data* sd, const char* command, const char* message)
581{
582        struct map_session_data *pl_sd = NULL;
583        char character[NAME_LENGTH];
584        int type = 0;
585        nullpo_retr(-1, sd);
586
587        if (!message || !*message || sscanf(message, "%d %23[^\n]", &type, character) != 2) {
588                clif_displaymessage(fd, "usage: #effect <type+> <target>.");
589                return -1;
590        }
591
592        if ( (pl_sd = map_nick2sd(character)) == NULL )
593        {
594                clif_displaymessage(fd, msg_txt(3)); // Character not found.
595                return -1;
596        }
597
598        clif_specialeffect(&pl_sd->bl, type, AREA);
599        clif_displaymessage(fd, msg_txt(229)); // Your effect has changed.
600
601        return 0;
602}
603
604/*==========================================
605 * #storagelist <character>: Displays the items list of a player's storage.
606 *------------------------------------------*/
607int charcommand_storagelist(const int fd, struct map_session_data* sd, const char* command, const char* message)
608{
609        struct storage *stor;
610        struct map_session_data *pl_sd;
611        struct item_data *item_data, *item_temp;
612        int i, j, count, counter, counter2;
613        char character[NAME_LENGTH], output[200], outputtmp[200];
614        nullpo_retr(-1, sd);
615
616        memset(character, '\0', sizeof(character));
617        memset(output, '\0', sizeof(output));
618        memset(outputtmp, '\0', sizeof(outputtmp));
619
620        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
621                clif_displaymessage(fd, "Please, enter a player name (usage: #itemlist <char name>).");
622                return -1;
623        }
624
625        if ( (pl_sd = map_nick2sd(character)) == NULL )
626        {
627                clif_displaymessage(fd, msg_txt(3)); // Character not found.
628                return -1;
629        }
630
631        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
632        {
633                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
634                return -1;
635        }
636
637        if((stor = account2storage2(pl_sd->status.account_id)) != NULL) {
638                counter = 0;
639                count = 0;
640                for (i = 0; i < MAX_STORAGE; i++) {
641                        if (stor->storage_[i].nameid > 0 && (item_data = itemdb_search(stor->storage_[i].nameid)) != NULL) {
642                                counter = counter + stor->storage_[i].amount;
643                                count++;
644                                if (count == 1) {
645                                        sprintf(output, "------ Storage items list of '%s' ------", pl_sd->status.name);
646                                        clif_displaymessage(fd, output);
647                                }
648                                if (stor->storage_[i].refine)
649                                        sprintf(output, "%d %s %+d (%s %+d, id: %d)", stor->storage_[i].amount, item_data->name, stor->storage_[i].refine, item_data->jname, stor->storage_[i].refine, stor->storage_[i].nameid);
650                                else
651                                        sprintf(output, "%d %s (%s, id: %d)", stor->storage_[i].amount, item_data->name, item_data->jname, stor->storage_[i].nameid);
652                                clif_displaymessage(fd, output);
653                                memset(output, '\0', sizeof(output));
654                                counter2 = 0;
655                                for (j = 0; j < item_data->slot; j++) {
656                                        if (stor->storage_[i].card[j]) {
657                                                if ((item_temp = itemdb_search(stor->storage_[i].card[j])) != NULL) {
658                                                        if (output[0] == '\0')
659                                                                sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
660                                                        else
661                                                                sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
662                                                        strcat(output, outputtmp);
663                                                }
664                                        }
665                                }
666                                if (output[0] != '\0') {
667                                        output[strlen(output) - 2] = ')';
668                                        output[strlen(output) - 1] = '\0';
669                                        clif_displaymessage(fd, output);
670                                }
671                        }
672                }
673                if (count == 0)
674                        clif_displaymessage(fd, "No item found in the storage of this player.");
675                else {
676                        sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
677                        clif_displaymessage(fd, output);
678                }
679        } else {
680                clif_displaymessage(fd, "This player has no storage.");
681                return 0;
682        }
683
684        return 0;
685}
686
687static void charcommand_item_sub(struct map_session_data *sd,struct item_data *item_data,int number)
688{
689        int loop, get_count, pet_id, i;
690
691        if( sd == NULL || item_data == NULL )
692                return;
693       
694        if( !itemdb_isstackable2(item_data) ) {
695                loop = number; get_count = 1;
696        } else {
697                loop = 1; get_count = number;
698        }
699
700        for (i = 0; i < loop; i++)
701        {
702                if( (pet_id = search_petDB_index(item_data->nameid, PET_EGG)) >= 0 )
703                {// if pet egg
704                        sd->catch_target_class = pet_db[pet_id].class_;
705                        intif_create_pet(sd->status.account_id, sd->status.char_id,
706                                         (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv,
707                                         (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
708                                         100, 0, 1, pet_db[pet_id].jname);
709                }
710                else
711                {// if not pet egg
712                        int flag = 0;
713                        struct item item_tmp;
714                        memset(&item_tmp, 0, sizeof(item_tmp));
715                        item_tmp.nameid = item_data->nameid;
716                        item_tmp.identify = 1;
717
718                        if ((flag = pc_additem(sd, &item_tmp, get_count)))
719                                clif_additem(sd, 0, 0, flag);
720
721                        //Logs (A)dmins items [Lupus]
722                        if(log_config.enable_logs&0x400)
723                                log_pick_pc(sd, "A", item_tmp.nameid, number, &item_tmp);
724                }
725        }
726}
727
728/*==========================================
729 * #item command (usage: #item <name/id_of_item> <quantity> <player>)
730 * by MC Cameri
731 *------------------------------------------*/
732int charcommand_item(const int fd, struct map_session_data* sd, const char* command, const char* message)
733{
734        char item_name[100];
735        char character[NAME_LENGTH];
736        struct map_session_data *pl_sd;
737        int number = 0, item_id;
738        struct item_data *item_data;
739        int gmlvl;
740        char tmp_cmdoutput[1024];
741        nullpo_retr(-1, sd);
742
743        memset(item_name, '\0', sizeof(item_name));
744
745        if (!message || !*message || (
746                sscanf(message, "\"%99[^\"]\" %d %23[^\n]", item_name, &number, character) < 3 &&
747                sscanf(message, "%99s %d %23[^\n]", item_name, &number, character) < 3
748        )) {
749                clif_displaymessage(fd, "Please, enter an item name/id (usage: #item <item name or ID> <quantity> <char name>).");
750                return -1;
751        }
752
753        if (number <= 0)
754                number = 1;
755
756        item_id = 0;
757        if ((item_data = itemdb_searchname(item_name)) != NULL ||
758                (item_data = itemdb_exists(atoi(item_name))) != NULL)
759                item_id = item_data->nameid;
760
761        if (item_id < 500) {
762                clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name.
763                return -1;
764        }
765
766        gmlvl = pc_isGM(sd);
767        if( !pc_can_give_items(gmlvl) )
768        {
769                clif_displaymessage(fd, msg_txt(246)); // GM is not allowed to trade
770                return -1;
771        }
772
773        if ((pl_sd = map_nick2sd(character)) != NULL)
774        {
775                int pl_gmlvl = pc_isGM(pl_sd);
776                if( gmlvl < pl_gmlvl || !itemdb_cantrade_sub(item_data, gmlvl, pl_gmlvl) )
777                {// you can give items only to lower or same level
778                        clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
779                        return -1;
780                }
781
782                charcommand_item_sub(pl_sd,item_data,number);
783                clif_displaymessage(fd, msg_txt(18)); // Item created.
784        }
785        else if (strcmpi(character,"all")==0 || strcmpi(character,"everyone")==0)
786        {
787                struct s_mapiterator* iter = mapit_getallusers();
788                for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
789                {
790                        int pl_gmlvl = pc_isGM(pl_sd);
791                        if( gmlvl < pl_gmlvl || !itemdb_cantrade_sub(item_data, gmlvl, pl_gmlvl) )
792                                continue;
793
794                        charcommand_item_sub(pl_sd,item_data,number);
795                        clif_displaymessage(pl_sd->fd, msg_txt(18)); // Item created.
796                }
797                mapit_free(iter);
798
799                snprintf(tmp_cmdoutput, sizeof(tmp_cmdoutput), "Everyone received %s %d.",item_name,number);
800                clif_displaymessage(fd, tmp_cmdoutput);
801        }
802        else
803        {
804                clif_displaymessage(fd, msg_txt(3)); // Character not found.
805                return -1;
806        }
807
808        return 0;
809}
810
811/*==========================================
812 * #warp/#rura/#rura+ <mapname> <x> <y> <char name>
813 *------------------------------------------*/
814int charcommand_warp(const int fd, struct map_session_data* sd, const char* command, const char* message)
815{
816        char map_name[MAP_NAME_LENGTH_EXT];
817        char character[NAME_LENGTH];
818        int x = 0, y = 0;
819        struct map_session_data *pl_sd;
820        int m;
821
822        nullpo_retr(-1, sd);
823
824        memset(map_name, '\0', sizeof(map_name));
825        memset(character, '\0', sizeof(character));
826
827        if (!message || !*message || sscanf(message, "%15s %d %d %23[^\n]", map_name, &x, &y, character) < 4) {
828                clif_displaymessage(fd, "Usage: #warp/#rura/#rura+ <mapname> <x> <y> <char name>");
829                return -1;
830        }
831
832        if ((pl_sd = map_nick2sd(character)) == NULL) {
833                clif_displaymessage(fd, msg_txt(3)); // Character not found.
834                return -1;
835        }
836        if (pc_isGM(sd) < pc_isGM(pl_sd)) { // you can rura+ only lower or same GM level
837                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
838                return -1;
839        }
840        m = map_mapname2mapid(map_name);
841        if (m < 0) {
842                clif_displaymessage(fd, msg_txt(1)); // Map not found.
843                return -1;
844        }
845        if ((x || y) && map_getcell(m, x, y, CELL_CHKNOREACH)) {
846                clif_displaymessage(fd, msg_txt(2)); // Coordinates out of range.
847                x = y = 0;
848        }
849        if (map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
850                clif_displaymessage(fd, "You are not authorised to warp someone to this map.");
851                return -1;
852        }
853        if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
854                clif_displaymessage(fd, "You are not authorised to warp this player from its actual map.");
855                return -1;
856        }
857        if (pc_setpos(pl_sd, map[m].index, x, y, 3) == 0) {
858                clif_displaymessage(pl_sd->fd, msg_txt(0)); // Warped.
859                if (pl_sd->fd != fd)
860                        clif_displaymessage(fd, msg_txt(15)); // Player warped (message sends to player too).
861                return 0;
862        }
863        //No error message specified...?
864        return -1;
865}
866
867/*==========================================
868 * #zeny <charname>
869 *------------------------------------------*/
870int charcommand_zeny(const int fd, struct map_session_data* sd, const char* command, const char* message)
871{
872        struct map_session_data *pl_sd;
873        char character[NAME_LENGTH];
874        int zeny = 0, new_zeny;
875        nullpo_retr(-1, sd);
876
877        memset(character, '\0', sizeof(character));
878
879        if (!message || !*message || sscanf(message, "%d %23[^\n]", &zeny, character) < 2 || zeny == 0) {
880                clif_displaymessage(fd, "Please, enter a number and a player name (usage: #zeny <zeny> <name>).");
881                return -1;
882        }
883
884        if ((pl_sd = map_nick2sd(character)) != NULL) {
885                new_zeny = pl_sd->status.zeny + zeny;
886                if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow
887                        new_zeny = MAX_ZENY;
888                else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow
889                        new_zeny = 0;
890                if (new_zeny != pl_sd->status.zeny) {
891                        pl_sd->status.zeny = new_zeny;
892                        clif_updatestatus(pl_sd, SP_ZENY);
893                        clif_displaymessage(fd, msg_txt(211)); // Character's number of zenys changed!
894                } else {
895                        if (zeny < 0)
896                                clif_displaymessage(fd, msg_txt(41)); // Impossible to decrease the number/value.
897                        else
898                                clif_displaymessage(fd, msg_txt(149)); // Impossible to increase the number/value.
899                        return -1;
900                }
901        } else {
902                clif_displaymessage(fd, msg_txt(3)); // Character not found.
903                return -1;
904        }
905
906        return 0;
907}
908
909/*==========================================
910 * #cash or #points <amount> <charname>
911 *------------------------------------------*/
912int charcommand_cash(const int fd, struct map_session_data* sd, const char* command, const char* message)
913{
914        struct map_session_data *pl_sd;
915        char character[NAME_LENGTH];
916        int value = 0;
917        nullpo_retr(-1, sd);
918
919        memset(character, '\0', sizeof(character));
920
921        if( !message || !*message || sscanf(message, "%d %23[^\n]", &value, character) < 2 || value == 0 )
922        {
923                clif_displaymessage(fd, "Please, enter a number and a player name (usage: #cash|#points <points> <name>).");
924                return -1;
925        }
926
927        if( (pl_sd = map_nick2sd(character)) != NULL )
928        {
929                if( !strcmpi(command+1,"cash") )
930                {
931                        if( value > 0 )
932                                pc_getcash(pl_sd, value, 0);
933                        else
934                                pc_paycash(pl_sd, value, 0);
935
936                        clif_displaymessage(fd, "Character's Cash Points changed!.");
937                }
938                else
939                { // @points
940                        if( value > 0 )
941                                pc_getcash(pl_sd, 0, value);
942                        else
943                                pc_paycash(pl_sd, value, value);
944
945                        clif_displaymessage(fd, "Character's Kafra Points changed!.");
946                }
947        }
948        else
949        {
950                clif_displaymessage(fd, msg_txt(3)); // Character not found.
951                return -1;
952        }
953
954        return 0;
955}
956
957/*==========================================
958 * #fakename <char name> <fake name>
959 *------------------------------------------*/
960int charcommand_fakename(const int fd, struct map_session_data* sd, const char* command, const char* message)
961{
962        struct map_session_data *pl_sd;
963        char name[NAME_LENGTH];
964        char char_name[NAME_LENGTH];
965       
966        nullpo_retr(-1, sd);
967
968        name[0] = '\0'; //If you don't pass a second word, name is left as garbage, most definitely not a blank name! [Skotlex]
969        if (!message || !*message || sscanf(message, "%23s %23[^\n]", char_name, name) < 1) {
970                clif_displaymessage(sd->fd,"Usage: #fakename <char name> <fake name>.");
971                clif_displaymessage(sd->fd,"Or: #fakename <char name> to disable.");
972                return 0;
973        }
974
975        if(!(pl_sd = map_nick2sd(char_name))) {
976                clif_displaymessage(sd->fd,"Character not found.");
977                return -1;
978        }
979
980        if(!name[0]) {
981                if(strlen(pl_sd->fakename) > 1) {
982                        pl_sd->fakename[0]='\0';
983                        clif_charnameack(0, &pl_sd->bl);
984                        clif_displaymessage(sd->fd,"Returned to real name.");
985                } else {
986                        clif_displaymessage(sd->fd,"Character does not has a fake name.");
987                }
988                return 0;
989        }
990
991        if(strlen(name) < 2) {
992                clif_displaymessage(sd->fd,"Fake name must be at least two characters.");
993                return 0;
994        }
995       
996        memcpy(pl_sd->fakename, name, NAME_LENGTH);
997        clif_charnameack(0, &pl_sd->bl);
998        clif_displaymessage(sd->fd,"Fake name enabled.");
999       
1000        return 0;
1001}
1002
1003
1004/*==========================================
1005 * #baselvl <#> <nickname>
1006 * Transferred by: Kevin
1007 *------------------------------------------*/
1008int charcommand_baselevel(const int fd, struct map_session_data* sd, const char* command, const char* message)
1009{
1010        struct map_session_data *pl_sd;
1011        char player[NAME_LENGTH];
1012        int level = 0, i, status_point=0;
1013        nullpo_retr(-1, sd);
1014
1015        if (!message || !*message || sscanf(message, "%d %23[^\n]", &level, player) < 2 || level == 0) {
1016                clif_displaymessage(fd, "Please, enter a level adjustment and a player name (usage: #baselvl <#> <nickname>).");
1017                return -1;
1018        }
1019
1020        if ((pl_sd = map_nick2sd(player)) == NULL) {
1021                clif_displaymessage(fd, msg_table[3]); // Character not found.
1022                return -1;
1023        }
1024        if (pc_isGM(sd) < pc_isGM(pl_sd)) { // you can change base level only lower or same gm level
1025                clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
1026                return -1;
1027        }
1028
1029        if (level > 0) {
1030                if (pl_sd->status.base_level == pc_maxbaselv(pl_sd)) {  // check for max level by Valaris
1031                        clif_displaymessage(fd, msg_table[91]); // Character's base level can't go any higher.
1032                        return 0;
1033                }       // End Addition
1034                if ((unsigned int)level > pc_maxbaselv(pl_sd) ||
1035                        pl_sd->status.base_level > pc_maxbaselv(pl_sd) -level)
1036                        level = pc_maxbaselv(pl_sd) - pl_sd->status.base_level;
1037                for (i = 1; i <= level; i++)
1038                        status_point += (pl_sd->status.base_level + i + 14) / 5;
1039
1040                if (pl_sd->status.status_point > USHRT_MAX -  status_point)
1041                        pl_sd->status.status_point = USHRT_MAX;
1042                else
1043                        pl_sd->status.status_point += status_point;
1044                pl_sd->status.base_level += (unsigned int)level;
1045                status_percent_heal(&pl_sd->bl, 100, 100);
1046                clif_misceffect(&pl_sd->bl, 0);
1047                clif_displaymessage(fd, msg_table[65]); // Character's base level raised.
1048        } else {
1049                if (pl_sd->status.base_level == 1) {
1050                        clif_displaymessage(fd, msg_table[193]); // Character's base level can't go any lower.
1051                        return -1;
1052                }
1053                level *= -1;
1054                if ((unsigned int)level >= pl_sd->status.base_level)
1055                        level = pl_sd->status.base_level -1;
1056                for (i = 0; i > -level; i--)
1057                        status_point += (pl_sd->status.base_level +i + 14) / 5;
1058                if (pl_sd->status.status_point < status_point)
1059                        pc_resetstate(pl_sd);
1060                if (pl_sd->status.status_point < status_point)
1061                        pl_sd->status.status_point = 0;
1062                else
1063                        pl_sd->status.status_point -= status_point;
1064                pl_sd->status.base_level -= (unsigned int)level;
1065                clif_displaymessage(fd, msg_table[66]); // Character's base level lowered.
1066        }
1067        clif_updatestatus(pl_sd, SP_BASELEVEL);
1068        clif_updatestatus(pl_sd, SP_NEXTBASEEXP);
1069        clif_updatestatus(pl_sd, SP_STATUSPOINT);
1070        status_calc_pc(pl_sd, 0);
1071        if(pl_sd->status.party_id) 
1072                party_send_levelup(pl_sd); 
1073        return 0; //³íI—¹
1074}
1075
1076/*==========================================
1077 * #jlvl <#> <nickname>
1078 * Transferred by: Kevin
1079 *------------------------------------------*/
1080int charcommand_joblevel(const int fd, struct map_session_data* sd, const char* command, const char* message)
1081{
1082        struct map_session_data *pl_sd;
1083        char player[NAME_LENGTH];
1084        int level = 0;
1085        //“]¶‚â—{Žq‚̏ꍇ‚ÌŒ³‚̐E‹Æ‚ðŽZo‚·‚é
1086        nullpo_retr(-1, sd);
1087
1088        if (!message || !*message || sscanf(message, "%d %23[^\n]", &level, player) < 2 || level == 0) {
1089                clif_displaymessage(fd, "Please, enter a level adjustment and a player name (usage: #joblvl <#> <nickname>).");
1090                return -1;
1091        }
1092
1093        if ((pl_sd = map_nick2sd(player)) != NULL) {
1094                if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change job level only lower or same gm level
1095                        if (level > 0) {
1096                                if (pl_sd->status.job_level == pc_maxjoblv(pl_sd)) {
1097                                        clif_displaymessage(fd, msg_txt(67)); // Character's job level can't go any higher.
1098                                        return -1;
1099                                }
1100                                if ((unsigned int)level > pc_maxjoblv(pl_sd) ||
1101                                        pl_sd->status.job_level > pc_maxjoblv(pl_sd) -level)
1102                                        level = pc_maxjoblv(pl_sd) - pl_sd->status.job_level;
1103                                pl_sd->status.job_level += (unsigned int)level;
1104                                clif_updatestatus(pl_sd, SP_JOBLEVEL);
1105                                clif_updatestatus(pl_sd, SP_NEXTJOBEXP);
1106
1107                                if (pl_sd->status.skill_point > USHRT_MAX - level)
1108                                        pl_sd->status.skill_point = USHRT_MAX;
1109                                else
1110                                        pl_sd->status.skill_point += level;
1111                                clif_updatestatus(pl_sd, SP_SKILLPOINT);
1112                                status_calc_pc(pl_sd, 0);
1113                                clif_misceffect(&pl_sd->bl, 1);
1114                                clif_displaymessage(fd, msg_txt(68)); // character's job level raised.
1115                        } else {
1116                                if (pl_sd->status.job_level == 1) {
1117                                        clif_displaymessage(fd, msg_txt(194)); // Character's job level can't go any lower.
1118                                        return -1;
1119                                }
1120                                level*=-1;
1121                                if ((unsigned int)level >= pl_sd->status.job_level)
1122                                        level = pl_sd->status.job_level-1;
1123                                pl_sd->status.job_level -= (unsigned int)level;
1124                                clif_updatestatus(pl_sd, SP_JOBLEVEL);
1125                                clif_updatestatus(pl_sd, SP_NEXTJOBEXP);
1126                                if (pl_sd->status.skill_point < level)
1127                                        pc_resetskill(pl_sd, 0); //Need more skill points to substract
1128                                if (pl_sd->status.skill_point < level)
1129                                        pl_sd->status.skill_point = 0;
1130                                else
1131                                        pl_sd->status.skill_point -= level;
1132                                clif_updatestatus(pl_sd, SP_SKILLPOINT);
1133                                status_calc_pc(pl_sd, 0);
1134                                clif_displaymessage(fd, msg_txt(69)); // Character's job level lowered.
1135                        }
1136                } else {
1137                        clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1138                        return -1;
1139                }
1140        } else {
1141                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1142                return -1;
1143        }
1144
1145        return 0;
1146}
1147
1148
1149/*==========================================
1150 * #questskill <skill_#> <nickname>
1151 * Transferred by: Kevin
1152 *------------------------------------------*/
1153int charcommand_questskill(const int fd, struct map_session_data* sd, const char* command, const char* message)
1154{
1155        struct map_session_data *pl_sd;
1156        char player[NAME_LENGTH];
1157        int skill_id = 0;
1158        nullpo_retr(-1, sd);
1159
1160        if (!message || !*message || sscanf(message, "%d %23[^\n]", &skill_id, player) < 2 || skill_id < 0) {
1161                clif_displaymessage(fd, "Please, enter a quest skill number and a player name (usage: #questskill <#:0+> <nickname>).");
1162                return -1;
1163        }
1164
1165        if (skill_id < 0 && skill_id >= MAX_SKILL_DB) {
1166                clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist.
1167                return -1;
1168        }
1169        if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) {
1170                clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill.
1171                return -1;
1172        }
1173        if ((pl_sd = map_nick2sd(player)) == NULL) {
1174                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1175                return -1;
1176        }
1177        if (pc_checkskill(pl_sd, skill_id) > 0) {
1178                clif_displaymessage(fd, msg_txt(200)); // This player already has this quest skill.
1179                return -1;
1180        }
1181
1182        pc_skill(pl_sd, skill_id, 1, 0);
1183        clif_displaymessage(fd, msg_txt(199)); // This player has learned the skill.
1184
1185        return 0;
1186}
1187
1188
1189/*==========================================
1190 * #lostskill <skill_#> <nickname>
1191 * Transferred by: Kevin
1192 *------------------------------------------*/
1193int charcommand_lostskill(const int fd, struct map_session_data* sd, const char* command, const char* message)
1194{
1195        struct map_session_data *pl_sd;
1196        char player[NAME_LENGTH];
1197        int skill_id = 0;
1198        nullpo_retr(-1, sd);
1199
1200        if (!message || !*message || sscanf(message, "%d %23[^\n]", &skill_id, player) < 2 || skill_id < 0) {
1201                clif_displaymessage(fd, "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>).");
1202                return -1;
1203        }
1204
1205        if (skill_id < 0 && skill_id >= MAX_SKILL) {
1206                clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist.
1207                return -1;
1208        }
1209        if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) {
1210                clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill.
1211                return -1;
1212        }
1213        if ((pl_sd = map_nick2sd(player)) == NULL) {
1214                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1215                return -1;
1216        }
1217        if (pc_checkskill(pl_sd, skill_id) == 0) {
1218                clif_displaymessage(fd, msg_txt(203)); // This player doesn't have this quest skill.
1219                return -1;
1220        }
1221
1222        pl_sd->status.skill[skill_id].lv = 0;
1223        pl_sd->status.skill[skill_id].flag = 0;
1224        clif_skillinfoblock(pl_sd);
1225        clif_displaymessage(fd, msg_txt(202)); // This player has forgotten the skill.
1226
1227        return 0;
1228}
1229
1230/*==========================================
1231 * Character Skill Reset
1232 *------------------------------------------*/
1233int charcommand_skreset(const int fd, struct map_session_data* sd, const char* command, const char* message)
1234{
1235        struct map_session_data *pl_sd;
1236        char player[NAME_LENGTH];
1237        char tmp_cmdoutput[1024];
1238        nullpo_retr(-1, sd);
1239
1240        if (!message || !*message || sscanf(message, "%23[^\n]", player) < 1) {
1241                clif_displaymessage(fd, "Please, enter a player name (usage: @charskreset <charname>).");
1242                return -1;
1243        }
1244
1245        if ((pl_sd = map_nick2sd(player)) != NULL) {
1246                if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset skill points only lower or same gm level
1247                        pc_resetskill(pl_sd,1);
1248                        sprintf(tmp_cmdoutput, msg_txt(206), player); // '%s' skill points reseted!
1249                        clif_displaymessage(fd, tmp_cmdoutput);
1250                } else {
1251                        clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1252                        return -1;
1253                }
1254        } else {
1255                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1256                return -1;
1257        }
1258
1259        return 0;
1260}
1261
1262/*==========================================
1263 * Character Stat Reset
1264 *------------------------------------------*/
1265int charcommand_streset(const int fd, struct map_session_data* sd, const char* command, const char* message)
1266{
1267        struct map_session_data *pl_sd;
1268        char player[NAME_LENGTH];
1269        char tmp_cmdoutput[1024];
1270        nullpo_retr(-1, sd);
1271
1272        if (!message || !*message || sscanf(message, "%23[^\n]", player) < 1) {
1273                clif_displaymessage(fd, "Please, enter a player name (usage: @charstreset <charname>).");
1274                return -1;
1275        }
1276
1277        if ((pl_sd = map_nick2sd(player)) != NULL) {
1278                if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset stats points only lower or same gm level
1279                        pc_resetstate(pl_sd);
1280                        sprintf(tmp_cmdoutput, msg_txt(207), player); // '%s' stats points reseted!
1281                        clif_displaymessage(fd, tmp_cmdoutput);
1282                } else {
1283                        clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1284                        return -1;
1285                }
1286        } else {
1287                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1288                return -1;
1289        }
1290
1291        return 0;
1292}
1293
1294/*==========================================
1295 * Character Model by chbrules
1296 *------------------------------------------*/
1297int charcommand_model(const int fd, struct map_session_data* sd, const char* command, const char* message)
1298{
1299        int hair_style = 0, hair_color = 0, cloth_color = 0;
1300        struct map_session_data *pl_sd;
1301        char player[NAME_LENGTH];
1302        char tmp_cmdoutput[1024];
1303        nullpo_retr(-1, sd);
1304
1305        if (!message || !*message || sscanf(message, "%d %d %d %23[^\n]", &hair_style, &hair_color, &cloth_color, player) < 4 || hair_style < 0 || hair_color < 0 || cloth_color < 0) {
1306                sprintf(tmp_cmdoutput, "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).",
1307                                MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
1308                clif_displaymessage(fd, tmp_cmdoutput);
1309                return -1;
1310        }
1311
1312        if ((pl_sd = map_nick2sd(player)) != NULL) {
1313                if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
1314                        hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
1315                        cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
1316                                pc_changelook(pl_sd, LOOK_HAIR, hair_style);
1317                                pc_changelook(pl_sd, LOOK_HAIR_COLOR, hair_color);
1318                                pc_changelook(pl_sd, LOOK_CLOTHES_COLOR, cloth_color);
1319                                clif_displaymessage(fd, msg_txt(36)); // Appearence changed.
1320                } else {
1321                        clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified.
1322                        return -1;
1323                }
1324        } else {
1325                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1326                return -1;
1327        }
1328
1329        return 0;
1330}
1331
1332/*==========================================
1333 * Character Skill Point (Rewritten by [Yor])
1334 *------------------------------------------*/
1335int charcommand_skpoint(const int fd, struct map_session_data* sd, const char* command, const char* message)
1336{
1337        struct map_session_data *pl_sd;
1338        char player[NAME_LENGTH];
1339        int new_skill_point;
1340        int point = 0;
1341        nullpo_retr(-1, sd);
1342
1343        if (!message || !*message || sscanf(message, "%d %23[^\n]", &point, player) < 2 || point == 0) {
1344                clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charskpoint <amount> <name>).");
1345                return -1;
1346        }
1347
1348        if ((pl_sd = map_nick2sd(player)) != NULL) {
1349                if (point > 0 && pl_sd->status.skill_point > USHRT_MAX - point)
1350                        new_skill_point = USHRT_MAX;
1351                else if (point < 0 && pl_sd->status.skill_point < -point)
1352                        new_skill_point = 0;
1353                else
1354                        new_skill_point = pl_sd->status.skill_point + point;
1355                if (new_skill_point != (int)pl_sd->status.skill_point) {
1356                        pl_sd->status.skill_point = new_skill_point;
1357                        clif_updatestatus(pl_sd, SP_SKILLPOINT);
1358                        clif_displaymessage(fd, msg_txt(209)); // Character's number of skill points changed!
1359                } else {
1360                        if (point < 0)
1361                                clif_displaymessage(fd, msg_txt(41)); // Impossible to decrease the number/value.
1362                        else
1363                                clif_displaymessage(fd, msg_txt(149)); // Impossible to increase the number/value.
1364                        return -1;
1365                }
1366        } else {
1367                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1368                return -1;
1369        }
1370
1371        return 0;
1372}
1373
1374/*==========================================
1375 * Character Status Point (rewritten by [Yor])
1376 *------------------------------------------*/
1377int charcommand_stpoint(const int fd, struct map_session_data* sd, const char* command, const char* message)
1378{
1379        struct map_session_data *pl_sd;
1380        char player[NAME_LENGTH];
1381        int new_status_point;
1382        int point = 0;
1383        nullpo_retr(-1, sd);
1384
1385        if (!message || !*message || sscanf(message, "%d %23[^\n]", &point, player) < 2 || point == 0) {
1386                clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charstpoint <amount> <name>).");
1387                return -1;
1388        }
1389
1390        if ((pl_sd = map_nick2sd(player)) != NULL) {
1391                if (point > 0 && pl_sd->status.status_point > USHRT_MAX - point)
1392                        new_status_point = USHRT_MAX;
1393                else if (point < 0 && pl_sd->status.status_point < -point)
1394                        new_status_point = 0;
1395                else
1396                        new_status_point = pl_sd->status.status_point + point;
1397                if (new_status_point != (int)pl_sd->status.status_point) {
1398                        pl_sd->status.status_point = new_status_point;
1399                        clif_updatestatus(pl_sd, SP_STATUSPOINT);
1400                        clif_displaymessage(fd, msg_txt(210)); // Character's number of status points changed!
1401                } else {
1402                        if (point < 0)
1403                                clif_displaymessage(fd, msg_txt(41)); // Impossible to decrease the number/value.
1404                        else
1405                                clif_displaymessage(fd, msg_txt(149)); // Impossible to increase the number/value.
1406                        return -1;
1407                }
1408        } else {
1409                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1410                return -1;
1411        }
1412
1413        return 0;
1414}
1415
1416/*==========================================
1417 * charchangesex command (usage: charchangesex <player_name>)
1418 *------------------------------------------*/
1419int charcommand_changesex(const int fd, struct map_session_data* sd, const char* command, const char* message)
1420{
1421        struct map_session_data *pl_sd;
1422        char player[NAME_LENGTH];
1423        nullpo_retr(-1, sd);
1424
1425        if (!message || !*message || sscanf(message, "%23[^\n]", player) < 1) {
1426                clif_displaymessage(fd, "Please, enter a player name (usage: @charchangesex <name>).");
1427                return -1;
1428        }
1429
1430        if ((pl_sd = map_nick2sd(player)) == NULL)
1431        {
1432                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1433                return -1;
1434        }
1435        if (pc_isGM(sd) < pc_isGM(pl_sd)) {
1436                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1437                return -1;
1438        }
1439        clif_displaymessage(fd, msg_table[88]); // Character name sent to char-server to ask it.
1440        chrif_changesex(pl_sd);
1441        return 0;
1442}
1443
1444/*==========================================
1445 * Feel (SG save map) Reset
1446 *------------------------------------------*/
1447int charcommand_feelreset(const int fd, struct map_session_data* sd, const char* command, const char* message)
1448{
1449        char character[NAME_LENGTH];
1450        char output[200];
1451        struct map_session_data *pl_sd;
1452
1453        memset(character, '\0', sizeof(character));
1454        memset(output, '\0', sizeof(output));
1455
1456        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1457                clif_displaymessage(fd, "Please, enter a player name (usage: #feelreset <charname>).");
1458                return -1;
1459        }
1460
1461        if ((pl_sd = map_nick2sd(character)) != NULL) {
1462                if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset a character only for lower or same GM level
1463                        pc_resetfeel(pl_sd);
1464                        sprintf(output, msg_txt(267), character); // '%s' designated maps reseted!
1465                        clif_displaymessage(fd, output);
1466                } else {
1467                        clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1468                        return -1;
1469                }
1470        } else {
1471                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1472                return -1;
1473        }
1474
1475        return 0;
1476}
1477
1478/*==========================================
1479 * #help - Char commands [Kayla]
1480 *------------------------------------------*/
1481int charcommand_help(const int fd, struct map_session_data* sd, const char* command, const char* message)
1482{
1483        char buf[2048], w1[2048], w2[2048];
1484        int i, gm_level;
1485        FILE* fp;
1486        nullpo_retr(-1, sd);
1487
1488        memset(buf, '\0', sizeof(buf));
1489
1490        if ((fp = fopen(charhelp_txt, "r")) != NULL) {
1491                clif_displaymessage(fd, msg_txt(26)); /* Help commands: */
1492                gm_level = pc_isGM(sd);
1493                while(fgets(buf, sizeof(buf), fp) != NULL)
1494                {
1495                        if (buf[0] == '/' && buf[1] == '/')
1496                                continue;
1497                        for (i = 0; buf[i] != '\0'; i++) {
1498                                if (buf[i] == '\r' || buf[i] == '\n') {
1499                                        buf[i] = '\0';
1500                                        break;
1501                                }
1502                        }
1503                        if (sscanf(buf, "%2047[^:]:%2047[^\n]", w1, w2) < 2)
1504                                clif_displaymessage(fd, buf);
1505                        else if (gm_level >= atoi(w1))
1506                                clif_displaymessage(fd, w2);
1507                }
1508                fclose(fp);
1509        } else {
1510                clif_displaymessage(fd, msg_txt(27)); /*  File help.txt not found. */
1511                return -1;
1512        }
1513
1514        return 0;
1515}
1516
1517/*==========================================
1518 * Loads a character back to their save point [HiddenDragon]
1519 *------------------------------------------*/
1520int charcommand_load(const int fd, struct map_session_data* sd, const char* command, const char* message)
1521{
1522        int m;
1523        char character[NAME_LENGTH];
1524
1525        struct map_session_data *pl_sd;
1526
1527        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1528                clif_displaymessage(fd, "Please, enter a player name (usage: #load <player>).");
1529                return -1;
1530        }
1531       
1532        if ( (pl_sd = map_nick2sd(character)) == NULL )
1533        {
1534                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1535                return -1;
1536        }
1537
1538        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1539        {
1540                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1541                return -1;
1542        }
1543
1544        m = map_mapindex2mapid(pl_sd->status.save_point.map);
1545        if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(pl_sd)) {
1546                clif_displaymessage(fd, "Not authorized to warp to target map.");
1547                return -1;
1548        }
1549        if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(pl_sd)) {
1550                clif_displaymessage(fd, "Not authorized to warp from current map.");
1551                return -1;
1552        }
1553
1554        pc_setpos(pl_sd, pl_sd->status.save_point.map, pl_sd->status.save_point.x, pl_sd->status.save_point.y, 0);
1555        clif_displaymessage(pl_sd->fd, msg_txt(7)); // Warping to respawn point.
1556        if (pl_sd->fd != fd)
1557                clif_displaymessage(fd, msg_txt(7)); // Warping to respawn point.
1558       
1559        return 0;
1560}
1561
1562/*==========================================
1563 * Changes the targets speed [HiddenDragon]
1564 *------------------------------------------*/
1565int charcommand_speed(const int fd, struct map_session_data* sd, const char* command, const char* message)
1566{
1567        int speed;
1568        char character[NAME_LENGTH];
1569        char output[200];
1570        struct map_session_data *pl_sd;
1571
1572        if (!message || !*message || sscanf(message, "%d %23[^\n]", &speed, character) < 2) {
1573                sprintf(output, "Please, enter proper values (usage: #speed <%d-%d> <player>).", MIN_WALK_SPEED, MAX_WALK_SPEED);
1574                clif_displaymessage(fd, output);
1575                return -1;
1576        }
1577
1578        if ( (pl_sd = map_nick2sd(character)) == NULL )
1579        {
1580                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1581                return -1;
1582        }
1583
1584        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1585        {
1586                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1587                return -1;
1588        }
1589       
1590        pl_sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
1591        status_calc_bl(&pl_sd->bl, SCB_SPEED);
1592        clif_displaymessage(pl_sd->fd, msg_txt(8)); // Speed changed.
1593        if (pl_sd->fd != fd)
1594                clif_displaymessage(fd, msg_txt(8)); // Speed changed.
1595        return 0;
1596}
1597
1598/*==========================================
1599 * Opens their storage [HiddenDragon]
1600 *------------------------------------------*/
1601int charcommand_storage(const int fd, struct map_session_data* sd, const char* command, const char* message)
1602{
1603        char character[NAME_LENGTH];
1604
1605        struct map_session_data *pl_sd;
1606
1607        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1608                clif_displaymessage(fd, "Please, enter a player name (usage: #storage <player>).");
1609                return -1;
1610        }
1611       
1612        if ( (pl_sd = map_nick2sd(character)) == NULL )
1613        {
1614                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1615                return -1;
1616        }
1617
1618        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1619        {
1620                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1621                return -1;
1622        }
1623       
1624        if (pl_sd->npc_id || pl_sd->vender_id || pl_sd->state.trading || pl_sd->state.storage_flag)
1625                return -1;
1626
1627        if (storage_storageopen(pl_sd) == 1)
1628        {       //Already open.
1629                clif_displaymessage(fd, "Players storage already open.");
1630                return -1;
1631        }
1632       
1633        clif_displaymessage(pl_sd->fd, "Storage opened.");
1634        if (pl_sd->fd != fd)
1635                clif_displaymessage(fd, "Player's storage opened.");
1636
1637        return 0;
1638}
1639
1640
1641/*==========================================
1642 * Opens their guild storage
1643 *------------------------------------------*/
1644int charcommand_guildstorage(const int fd, struct map_session_data* sd, const char* command, const char* message)
1645{
1646        struct storage *stor; //changes from Freya/Yor
1647        char character[NAME_LENGTH];
1648
1649        struct map_session_data *pl_sd;
1650       
1651        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1652                clif_displaymessage(fd, "Please, enter a player name (usage: #gstorage <player>).");
1653                return -1;
1654        }
1655       
1656        if ( (pl_sd = map_nick2sd(character)) == NULL )
1657        {
1658                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1659                return -1;
1660        }
1661
1662        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1663        {
1664                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1665                return -1;
1666        }
1667       
1668        if (pl_sd->npc_id || pl_sd->vender_id || pl_sd->state.trading || pl_sd->state.storage_flag)
1669                return -1;
1670
1671        if (pl_sd->status.guild_id > 0) {
1672                if (pl_sd->state.storage_flag) {
1673                        clif_displaymessage(fd, "Guild storage is currently in use.");
1674                        return -1;
1675                }
1676                if ((stor = account2storage2(pl_sd->status.account_id)) != NULL && stor->storage_status == 1) {
1677                        clif_displaymessage(fd, "Guild storage is currently in use.");
1678                        return -1;
1679                }
1680                storage_guild_storageopen(pl_sd);
1681        } else {
1682                clif_displaymessage(fd, "Target player is not in a guild.");
1683                return -1;
1684        }
1685
1686        clif_displaymessage(pl_sd->fd, "Guild storage opened.");
1687        if (pl_sd->fd != fd)
1688                clif_displaymessage(fd, "Player's guild storage opened.");
1689
1690        return 0;
1691}
1692
1693/*==========================================
1694 * Applies GM Hide to a character [HiddenDragon]
1695 *------------------------------------------*/
1696int charcommand_hide(const int fd, struct map_session_data* sd, const char* command, const char* message)
1697{
1698        char character[NAME_LENGTH];
1699
1700        struct map_session_data *pl_sd;
1701       
1702        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1703                clif_displaymessage(fd, "Please, enter a player name (usage: #hide <player>).");
1704                return -1;
1705        }
1706       
1707        if ( (pl_sd = map_nick2sd(character)) == NULL )
1708        {
1709                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1710                return -1;
1711        }
1712
1713        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1714        {
1715                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1716                return -1;
1717        }
1718       
1719        if (pl_sd->sc.option & OPTION_INVISIBLE) {
1720                pl_sd->sc.option &= ~OPTION_INVISIBLE;
1721                if (pl_sd->disguise)
1722                        status_set_viewdata(&pl_sd->bl, pl_sd->disguise);
1723                else
1724                        status_set_viewdata(&pl_sd->bl, pl_sd->status.class_);
1725                clif_changeoption(&pl_sd->bl);
1726                clif_displaymessage(pl_sd->fd, msg_txt(10)); // Invisible: Off
1727                if (pl_sd->fd != fd)
1728                        clif_displaymessage(fd, msg_txt(10)); // Invisible: Off
1729        } else {
1730                pl_sd->sc.option |= OPTION_INVISIBLE;
1731                pl_sd->vd.class_ = INVISIBLE_CLASS;
1732                clif_changeoption(&pl_sd->bl);
1733                clif_displaymessage(pl_sd->fd, msg_txt(11)); // Invisible: On
1734                if (pl_sd->fd != fd)
1735                        clif_displaymessage(fd, msg_txt(11)); // Invisible: On
1736        }
1737
1738        return 0;
1739}
1740
1741/*==========================================
1742 * Resurrects a dead character [HiddenDragon]
1743 *------------------------------------------*/
1744int charcommand_alive(const int fd, struct map_session_data* sd, const char* command, const char* message)
1745{
1746        char character[NAME_LENGTH];
1747
1748        struct map_session_data *pl_sd;
1749       
1750        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1751                clif_displaymessage(fd, "Please, enter a player name (usage: #alive <player>).");
1752                return -1;
1753        }
1754       
1755        if ( (pl_sd = map_nick2sd(character)) == NULL )
1756        {
1757                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1758                return -1;
1759        }
1760
1761        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1762        {
1763                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1764                return -1;
1765        }
1766       
1767        if (!status_revive(&pl_sd->bl, 100, 100))
1768        {
1769                clif_displaymessage(fd, "Target player is not dead.");
1770                return -1;
1771        }
1772        clif_skill_nodamage(&pl_sd->bl,&pl_sd->bl,ALL_RESURRECTION,4,1);
1773        clif_displaymessage(pl_sd->fd, msg_txt(16)); // You've been revived! It's a miracle!
1774        return 0;
1775}
1776
1777/*==========================================
1778 * Heals someone's HP and SP [HiddenDragon]
1779 *------------------------------------------*/
1780int charcommand_heal(const int fd, struct map_session_data* sd, const char* command, const char* message)
1781{
1782        int hp = 0, sp = 0; // [Valaris] thanks to fov
1783        char character[NAME_LENGTH];
1784
1785        struct map_session_data *pl_sd;
1786       
1787        if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &hp, &sp, character) < 3) {
1788                clif_displaymessage(fd, "Please, enter proper values (usage: #heal <hp> <sp> <player>).");
1789                return -1;
1790        }
1791       
1792        if ( (pl_sd = map_nick2sd(character)) == NULL )
1793        {
1794                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1795                return -1;
1796        }
1797
1798        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1799        {
1800                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1801                return -1;
1802        }
1803
1804        if (hp == 0 && sp == 0) {
1805                if (!status_percent_heal(&pl_sd->bl, 100, 100))
1806                        clif_displaymessage(fd, msg_txt(157)); // HP and SP are already with the good value.
1807                else
1808                {
1809                        clif_displaymessage(pl_sd->fd, msg_txt(17)); // HP, SP recovered.
1810                        if (pl_sd->fd != fd)
1811                                clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered.
1812                }
1813                return 0;
1814        }
1815       
1816        if(hp > 0 && sp >= 0) {
1817                if(!status_heal(&pl_sd->bl, hp, sp, 2))
1818                        clif_displaymessage(fd, msg_txt(157)); // HP and SP are already with the good value.
1819                else
1820                {
1821                        clif_displaymessage(pl_sd->fd, msg_txt(17)); // HP, SP recovered.
1822                        if (pl_sd->fd != fd)
1823                                clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered.
1824                }
1825                return 0;
1826        }
1827
1828        if(hp < 0 && sp <= 0) {
1829                status_damage(NULL, &pl_sd->bl, -hp, -sp, 0, 0);
1830                clif_damage(&pl_sd->bl,&pl_sd->bl, gettick(), 0, 0, -hp, 0 , 4, 0);
1831                clif_displaymessage(pl_sd->fd, msg_txt(156)); // HP or/and SP modified.
1832                if (pl_sd->fd != fd)
1833                        clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified.
1834                return 0;
1835        }
1836
1837        //Opposing signs.
1838        if (hp) {
1839                if (hp > 0)
1840                        status_heal(&pl_sd->bl, hp, 0, 2);
1841                else {
1842                        status_damage(NULL, &pl_sd->bl, -hp, 0, 0, 0);
1843                        clif_damage(&pl_sd->bl,&pl_sd->bl, gettick(), 0, 0, -hp, 0 , 4, 0);
1844                }
1845        }
1846
1847        if (sp) {
1848                if (sp > 0)
1849                        status_heal(&pl_sd->bl, 0, sp, 2);
1850                else
1851                        status_damage(NULL, &pl_sd->bl, 0, -sp, 0, 0);
1852        }
1853
1854        clif_displaymessage(pl_sd->fd, msg_txt(156)); // HP or/and SP modified.
1855        if (pl_sd->fd != fd)
1856                clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified.
1857        return 0;
1858}
1859
1860/*==========================================
1861 * Creates items as specified [HiddenDragon]
1862 *------------------------------------------*/
1863int charcommand_item2(const int fd, struct map_session_data* sd, const char* command, const char* message)
1864{
1865        struct item item_tmp;
1866        struct item_data *item_data;
1867        char item_name[100];
1868        int item_id, number = 0;
1869        int identify = 0, refine = 0, attr = 0;
1870        int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1871        int flag;
1872        int loop, get_count, i;
1873        char character[NAME_LENGTH];
1874
1875        struct map_session_data *pl_sd;
1876       
1877        if (!message || !*message || (
1878                sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %23[^\n]", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, character) < 10 &&
1879                sscanf(message, "%99s %d %d %d %d %d %d %d %d %23[^\n]", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, character) < 10
1880        )) {
1881                clif_displaymessage(fd, "Please, enter all informations (usage: @item2 <item name or ID> <quantity>");
1882                clif_displaymessage(fd, "  <Identify_flag[1|0]> <refine> <attribut> <Card1> <Card2> <Card3> <Card4> <player>).");
1883                return -1;
1884        }
1885
1886        if ( (pl_sd = map_nick2sd(character)) == NULL )
1887        {
1888                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1889                return -1;
1890        }
1891
1892        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1893        {
1894                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1895                return -1;
1896        }
1897        if (number <= 0)
1898                number = 1;
1899
1900        item_id = 0;
1901        if ((item_data = itemdb_searchname(item_name)) != NULL ||
1902            (item_data = itemdb_exists(atoi(item_name))) != NULL)
1903                item_id = item_data->nameid;
1904
1905        if (item_id > 500) {
1906                loop = 1;
1907                get_count = number;
1908                if (item_data->type == 4 || item_data->type == 5 ||
1909                        item_data->type == 7 || item_data->type == 8) {
1910                        loop = number;
1911                        get_count = 1;
1912                        if (item_data->type == 7) {
1913                                identify = 1;
1914                                refine = 0;
1915                        }
1916                        if (item_data->type == 8)
1917                                refine = 0;
1918                        if (refine > 10)
1919                                refine = 10;
1920                } else {
1921                        identify = 1;
1922                        refine = attr = 0;
1923                }
1924                for (i = 0; i < loop; i++) {
1925                        memset(&item_tmp, 0, sizeof(item_tmp));
1926                        item_tmp.nameid = item_id;
1927                        item_tmp.identify = identify;
1928                        item_tmp.refine = refine;
1929                        item_tmp.attribute = attr;
1930                        item_tmp.card[0] = c1;
1931                        item_tmp.card[1] = c2;
1932                        item_tmp.card[2] = c3;
1933                        item_tmp.card[3] = c4;
1934                        if ((flag = pc_additem(pl_sd, &item_tmp, get_count)))
1935                                clif_additem(pl_sd, 0, 0, flag);
1936                }
1937
1938                //Logs (A)dmins items [Lupus]
1939                if(log_config.enable_logs&0x400)
1940                        log_pick_pc(pl_sd, "A", item_tmp.nameid, number, &item_tmp);
1941
1942                clif_displaymessage(pl_sd->fd, msg_txt(18)); // Item created.
1943                if (pl_sd->fd != fd)
1944                        clif_displaymessage(fd, msg_txt(18)); // Item created.
1945        } else {
1946                clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name.
1947                return -1;
1948        }
1949
1950        return 0;
1951}
1952
1953/*==========================================
1954 * Reset a character's items [HiddenDragon]
1955 *------------------------------------------*/
1956int charcommand_itemreset(const int fd, struct map_session_data* sd, const char* command, const char* message)
1957{
1958        int i, count = 0;
1959        char character[NAME_LENGTH];
1960        char output[200];
1961
1962        struct map_session_data *pl_sd;
1963
1964        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
1965                clif_displaymessage(fd, "Please, enter a player name (usage: #itemreset <player>).");
1966                return -1;
1967        }
1968       
1969        if ( (pl_sd = map_nick2sd(character)) == NULL )
1970        {
1971                clif_displaymessage(fd, msg_txt(3)); // Character not found.
1972                return -1;
1973        }
1974
1975        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
1976        {
1977                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
1978                return -1;
1979        }
1980       
1981        for (i = 0; i < MAX_INVENTORY; i++) {
1982                if (pl_sd->status.inventory[i].amount && pl_sd->status.inventory[i].equip == 0) {
1983
1984                        //Logs (A)dmins items [Lupus]
1985                        if(log_config.enable_logs&0x400)
1986                                log_pick_pc(pl_sd, "A", pl_sd->status.inventory[i].nameid, -pl_sd->status.inventory[i].amount, &pl_sd->status.inventory[i]);
1987
1988                        pc_delitem(pl_sd, i, pl_sd->status.inventory[i].amount, 0);
1989                        count++;
1990                }
1991        }
1992       
1993        sprintf(output, msg_txt(114), count);
1994        if (pl_sd->fd != fd)
1995                clif_displaymessage(pl_sd->fd, output); // %d item(s) removed from the player.
1996        clif_displaymessage(fd, msg_txt(20)); // All of your items have been removed.
1997
1998        return 0;
1999}
2000
2001/*==========================================
2002 * Refine their items [HiddenDragon]
2003 *------------------------------------------*/
2004int charcommand_refine(const int fd, struct map_session_data* sd, const char* command, const char* message)
2005{
2006        int i,j, position = 0, refine = 0, current_position, final_refine;
2007        int count;
2008        char character[NAME_LENGTH];
2009        char output[200];
2010        struct map_session_data *pl_sd;
2011
2012        if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &position, &refine, character) < 3) {
2013                clif_displaymessage(fd, "Please, enter a position and a amount (usage: #refine <equip position> <+/- amount> <player>).");
2014                sprintf(output, "%d: Left Accessory", EQI_ACC_L);
2015                clif_displaymessage(fd, output);
2016                sprintf(output, "%d: Right Accessory", EQI_ACC_R);
2017                clif_displaymessage(fd, output);
2018                sprintf(output, "%d: Shoes", EQI_SHOES);
2019                clif_displaymessage(fd, output);
2020                sprintf(output, "%d: Garment", EQI_GARMENT);
2021                clif_displaymessage(fd, output);
2022                sprintf(output, "%d: Lower Headgear", EQI_HEAD_LOW);
2023                clif_displaymessage(fd, output);
2024                sprintf(output, "%d: Mid Headgear", EQI_HEAD_MID);
2025                clif_displaymessage(fd, output);
2026                sprintf(output, "%d: Top Headgear", EQI_HEAD_TOP);
2027                clif_displaymessage(fd, output);
2028                sprintf(output, "%d: Body Armor", EQI_ARMOR);
2029                clif_displaymessage(fd, output);
2030                sprintf(output, "%d: Left Hand", EQI_HAND_L);
2031                clif_displaymessage(fd, output);
2032                sprintf(output, "%d: Right Hand", EQI_HAND_R);
2033                clif_displaymessage(fd, output);
2034                return -1;
2035        }
2036
2037        if ( (pl_sd = map_nick2sd(character)) == NULL )
2038        {
2039                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2040                return -1;
2041        }
2042
2043        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2044        {
2045                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2046                return -1;
2047        }
2048       
2049        if (refine < -MAX_REFINE)
2050                refine = -MAX_REFINE;
2051        else if (refine > MAX_REFINE)
2052                refine = MAX_REFINE;
2053        else if (refine == 0)
2054                refine = 1;
2055
2056        count = 0;
2057        for (j = 0; j < EQI_MAX-1; j++) {
2058                if ((i = pl_sd->equip_index[j]) < 0)
2059                        continue;
2060                if(j == EQI_HAND_R && pl_sd->equip_index[EQI_HAND_L] == i)
2061                        continue;
2062                if(j == EQI_HEAD_MID && pl_sd->equip_index[EQI_HEAD_LOW] == i)
2063                        continue;
2064                if(j == EQI_HEAD_TOP && (pl_sd->equip_index[EQI_HEAD_MID] == i || pl_sd->equip_index[EQI_HEAD_LOW] == i))
2065                        continue;
2066
2067                if(position && !(pl_sd->status.inventory[i].equip & position))
2068                        continue;
2069
2070                final_refine = pl_sd->status.inventory[i].refine + refine;
2071                if (final_refine > MAX_REFINE)
2072                        final_refine = MAX_REFINE;
2073                else if (final_refine < 0)
2074                        final_refine = 0;
2075                if (pl_sd->status.inventory[i].refine != final_refine) {
2076                        pl_sd->status.inventory[i].refine = final_refine;
2077                        current_position = pl_sd->status.inventory[i].equip;
2078                        pc_unequipitem(pl_sd, i, 3);
2079                        clif_refine(fd, 0, i, pl_sd->status.inventory[i].refine);
2080                        clif_delitem(pl_sd, i, 1);
2081                        clif_additem(pl_sd, i, 1, 0);
2082                        pc_equipitem(pl_sd, i, current_position);
2083                        clif_misceffect(&pl_sd->bl, 3);
2084                        count++;
2085                }
2086        }
2087
2088        if (count == 0)
2089                clif_displaymessage(fd, msg_txt(166)); // No item has been refined!
2090        else if (count == 1)
2091        {
2092                clif_displaymessage(pl_sd->fd, msg_txt(167)); // 1 item has been refined!
2093                if (pl_sd->fd != fd)
2094                        clif_displaymessage(fd, msg_txt(167)); // 1 item has been refined!
2095        }
2096        else {
2097                sprintf(output, msg_txt(168), count); // %d items have been refined!
2098                clif_displaymessage(pl_sd->fd, output);
2099                if (pl_sd->fd != fd)
2100                        clif_displaymessage(fd, output);
2101        }
2102
2103        return 0;
2104}
2105
2106/*==========================================
2107 * Produce a manufactured item in their inventory [HiddenDragon]
2108 *------------------------------------------*/
2109int charcommand_produce(const int fd, struct map_session_data* sd, const char* command, const char* message)
2110{
2111        char item_name[100];
2112        int item_id, attribute = 0, star = 0;
2113        int flag = 0;
2114        struct item_data *item_data;
2115        struct item tmp_item;
2116        char character[NAME_LENGTH];
2117        char output[200];
2118
2119        struct map_session_data *pl_sd;
2120
2121        nullpo_retr(-1, sd);
2122
2123        if (!message || !*message || (
2124                sscanf(message, "\"%99[^\"]\" %d %d %23[^\n]", item_name, &attribute, &star, character) < 4 &&
2125                sscanf(message, "%99s %d %d %23[^\n]", item_name, &attribute, &star, character) < 4
2126        )) {
2127                clif_displaymessage(fd, "Please, enter at least an item name/id (usage: #produce <equip name or equip ID> <element> <# of very's> <player>).");
2128                return -1;
2129        }
2130
2131        if ( (pl_sd = map_nick2sd(character)) == NULL )
2132        {
2133                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2134                return -1;
2135        }
2136
2137        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2138        {
2139                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2140                return -1;
2141        }
2142
2143        item_id = 0;
2144        if ((item_data = itemdb_searchname(item_name)) == NULL &&
2145            (item_data = itemdb_exists(atoi(item_name))) == NULL)
2146        {
2147                sprintf(output, msg_txt(170)); // This item is not an equipment.
2148                clif_displaymessage(fd, output);
2149                return -1;
2150        }
2151        item_id = item_data->nameid;
2152        if (itemdb_isequip2(item_data)) {
2153                if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE)
2154                        attribute = ATTRIBUTE_NORMAL;
2155                if (star < MIN_STAR || star > MAX_STAR)
2156                        star = 0;
2157                memset(&tmp_item, 0, sizeof tmp_item);
2158                tmp_item.nameid = item_id;
2159                tmp_item.amount = 1;
2160                tmp_item.identify = 1;
2161                tmp_item.card[0] = CARD0_FORGE;
2162                tmp_item.card[1] = item_data->type==IT_WEAPON?
2163                        ((star*5) << 8) + attribute:0;
2164                tmp_item.card[2] = GetWord(pl_sd->status.char_id, 0);
2165                tmp_item.card[3] = GetWord(pl_sd->status.char_id, 1);
2166                clif_produceeffect(pl_sd, 0, item_id);
2167                clif_misceffect(&pl_sd->bl, 3);
2168
2169                //Logs (A)dmins items [Lupus]
2170                if(log_config.enable_logs&0x400)
2171                        log_pick_pc(pl_sd, "A", tmp_item.nameid, 1, &tmp_item);
2172
2173                if ((flag = pc_additem(pl_sd, &tmp_item, 1)))
2174                {
2175                        clif_additem(pl_sd, 0, 0, flag);
2176                        clif_displaymessage(fd, msg_txt(18));
2177                }
2178        } else {
2179                sprintf(output, msg_txt(169), item_id, item_data->name); // This item (%d: '%s') is not an equipment.
2180                clif_displaymessage(fd, output);
2181                return -1;
2182        }
2183
2184        return 0;
2185}
2186
2187/*==========================================
2188 * Changes a character's stats [HiddenDragon
2189 *------------------------------------------*/
2190int charcommand_param(const int fd, struct map_session_data* sd, const char* command, const char* message)
2191{
2192        int index, value = 0, new_value;
2193        char character[NAME_LENGTH];
2194        char output[200];
2195        struct map_session_data *pl_sd;
2196        const char* param[] = { "#str", "#agi", "#vit", "#int", "#dex", "#luk", NULL };
2197        short* status[6];
2198
2199       
2200        if (!message || !*message || sscanf(message, "%d %s", &value, character) < 2 || value == 0) {
2201                sprintf(output, "Please, enter a valid value (usage: #str,#agi,#vit,#int,#dex,#luk <+/-adjustment> <player>).");
2202                clif_displaymessage(fd, output);
2203                return -1;
2204        }
2205
2206        if ( (pl_sd = map_nick2sd(character)) == NULL )
2207        {
2208                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2209                return -1;
2210        }
2211
2212        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2213        {
2214                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2215                return -1;
2216        }
2217
2218        status[0] = &pl_sd->status.str;
2219        status[1] = &pl_sd->status.agi;
2220        status[2] = &pl_sd->status.vit;
2221        status[3] = &pl_sd->status.int_;
2222        status[4] = &pl_sd->status.dex;
2223        status[5] = &pl_sd->status.luk;
2224
2225        index = -1;
2226        for (index = 0; index < ARRAYLENGTH(param); index++) {
2227                if (strcmpi(command, param[index]) == 0)
2228                        break;
2229        }
2230        if (index == ARRAYLENGTH(param) || index > MAX_STATUS_TYPE) {
2231                // normaly impossible...
2232                sprintf(output, "Please, enter a valid value (usage: #str,#agi,#vit,#int,#dex,#luk <+/-adjustment> <player>).");
2233                clif_displaymessage(fd, output);
2234                return -1;
2235        }
2236
2237        if (value > 0 && *status[index] > 999 - value)
2238                new_value = 999;
2239        else if (value < 0 && *status[index] <= -value)
2240                new_value = 1;
2241        else
2242                new_value = *status[index] + value;
2243       
2244        if (new_value != (int)*status[index]) {
2245                *status[index] = new_value;
2246                clif_updatestatus(pl_sd, SP_STR + index);
2247                clif_updatestatus(pl_sd, SP_USTR + index);
2248                status_calc_pc(pl_sd, 0);
2249                clif_displaymessage(pl_sd->fd, msg_txt(42)); // Stat changed.
2250                if (pl_sd->fd != fd)
2251                        clif_displaymessage(fd, msg_txt(42)); // Stat changed.
2252        } else {
2253                if (value < 0)
2254                        clif_displaymessage(fd, msg_txt(41)); // Impossible to decrease the number/value.
2255                else
2256                        clif_displaymessage(fd, msg_txt(149)); // Impossible to increase the number/value.
2257                return -1;
2258        }
2259
2260        return 0;
2261}
2262
2263/*==========================================
2264 * Levels up a character's guild [HiddenDragon]
2265 *------------------------------------------*/
2266int charcommand_guildlevelup(const int fd, struct map_session_data* sd, const char* command, const char* message)
2267{
2268        int level = 0;
2269        short added_level;
2270        struct guild *guild_info;
2271        char character[NAME_LENGTH];
2272        struct map_session_data *pl_sd;
2273        nullpo_retr(-1, sd);
2274
2275        if (!message || !*message || sscanf(message, "%d %s", &level, character) < 2 || level == 0) {
2276                clif_displaymessage(fd, "Please, enter a valid level and player (usage: #guildlvup/@guildlvlup <# of levels> <player>).");
2277                return -1;
2278        }
2279
2280        if ( (pl_sd = map_nick2sd(character)) == NULL )
2281        {
2282                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2283                return -1;
2284        }
2285
2286        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2287        {
2288                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2289                return -1;
2290        }
2291       
2292        if (pl_sd->status.guild_id <= 0 || (guild_info = guild_search(pl_sd->status.guild_id)) == NULL) {
2293                clif_displaymessage(fd, "Target player is not in a guild"); // You're not in a guild.
2294                return -1;
2295        }
2296        //if (strcmp(sd->status.name, guild_info->master) != 0) {
2297        //      clif_displaymessage(fd, msg_txt(44)); // You're not the master of your guild.
2298        //      return -1;
2299        //}
2300
2301        added_level = (short)level;
2302        if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short)MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow
2303                added_level = (short)MAX_GUILDLEVEL - guild_info->guild_lv;
2304        else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv))) // fix negativ overflow
2305                added_level = 1 - guild_info->guild_lv;
2306
2307        if (added_level != 0) {
2308                intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, 2);
2309                clif_displaymessage(pl_sd->fd, msg_txt(179)); // Guild level changed.
2310                if (pl_sd->fd != fd)
2311                        clif_displaymessage(fd, msg_txt(179));
2312        } else {
2313                clif_displaymessage(fd, msg_txt(45)); // Guild level change failed.
2314                return -1;
2315        }
2316
2317        return 0;
2318}
2319
2320/*==========================================
2321 * Opens a hatch window for them [HiddenDragon]
2322 *------------------------------------------*/
2323int charcommand_hatch(const int fd, struct map_session_data* sd, const char* command, const char* message)
2324{
2325        char character[NAME_LENGTH];
2326        struct map_session_data *pl_sd;
2327
2328        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2329                clif_displaymessage(fd, "Please, enter a player name (usage: #hatch <player>).");
2330                return -1;
2331        }
2332       
2333        if ( (pl_sd = map_nick2sd(character)) == NULL )
2334        {
2335                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2336                return -1;
2337        }
2338
2339        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2340        {
2341                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2342                return -1;
2343        }
2344
2345        if (pl_sd->status.pet_id <= 0)
2346                clif_sendegg(sd);
2347        else {
2348                clif_displaymessage(fd, "Target player already has a pet"); // You already have a pet.
2349                return -1;
2350        }
2351
2352        return 0;
2353}
2354
2355/*==========================================
2356 * Change target pet's hunger [HiddenDragon]
2357 *------------------------------------------*/
2358int charcommand_pethungry(const int fd, struct map_session_data* sd, const char* command, const char* message)
2359{
2360        int hungry;
2361        struct pet_data *pd;
2362        char character[NAME_LENGTH];
2363        struct map_session_data *pl_sd;
2364
2365        nullpo_retr(-1, sd);
2366
2367        if (!message || !*message || sscanf(message, "%d %23[^\n]", &hungry, character) < 2) {
2368                clif_displaymessage(fd, "Please, enter a valid number and player (usage: #pethungry <0-100> <player>).");
2369                return -1;
2370        }
2371
2372        if ( (pl_sd = map_nick2sd(character)) == NULL )
2373        {
2374                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2375                return -1;
2376        }
2377
2378        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2379        {
2380                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2381                return -1;
2382        }
2383
2384        pd = pl_sd->pd;
2385        if (!pl_sd->status.pet_id || !pd) {
2386                clif_displaymessage(fd, "Target has no pet"); // Sorry, but you have no pet.
2387                return -1;
2388        }
2389        if (hungry < 0 || hungry > 100) {
2390                clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified.
2391                return -1;
2392        }
2393        if (hungry == pd->pet.hungry) {
2394                clif_displaymessage(fd, msg_txt(186)); // Pet hungry is already the good value.
2395                return -1;
2396        }
2397
2398        pd->pet.hungry = hungry;
2399        clif_send_petstatus(pl_sd);
2400        clif_displaymessage(pl_sd->fd, msg_txt(185)); // Pet hungry value changed!
2401        if (pl_sd->fd != fd)
2402                clif_displaymessage(fd, msg_txt(185)); // Pet hungry value changed!
2403
2404        return 0;
2405}
2406
2407/*==========================================
2408 * Give all skills to target [HiddenDragon]
2409 *------------------------------------------*/
2410int charcommand_allskill(const int fd, struct map_session_data* sd, const char* command, const char* message)
2411{
2412        char character[NAME_LENGTH];
2413
2414        struct map_session_data *pl_sd;
2415
2416        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2417                clif_displaymessage(fd, "Please, enter a player name (usage: #allskill <player>).");
2418                return -1;
2419        }
2420       
2421        if ( (pl_sd = map_nick2sd(character)) == NULL )
2422        {
2423                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2424                return -1;
2425        }
2426
2427        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2428        {
2429                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2430                return -1;
2431        }
2432       
2433        pc_allskillup(pl_sd); // all skills
2434        pl_sd->status.skill_point = 0; // 0 skill points
2435        clif_updatestatus(pl_sd, SP_SKILLPOINT); // update
2436        clif_displaymessage(pl_sd->fd, msg_txt(76)); // You have received all skills.
2437        if (pl_sd->fd != fd)
2438                clif_displaymessage(fd, "Player has received all skills for his/her class.");
2439
2440        return 0;
2441}
2442
2443
2444/*==========================================
2445 * Change target's clothing color [HiddenDragon]
2446 *------------------------------------------*/
2447int charcommand_dye(const int fd, struct map_session_data* sd, const char* command, const char* message)
2448{
2449        int cloth_color = 0;
2450        char character[NAME_LENGTH];
2451        char output[200];
2452       
2453        struct map_session_data *pl_sd;
2454
2455        if (!message || !*message || sscanf(message, "%d %23[^\n]", &cloth_color, character) < 2) {
2456                sprintf(output, "Please, enter a clothes color (usage: #dye/@ccolor <clothes color: %d-%d> <player>).", MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
2457                clif_displaymessage(fd,output);
2458                return -1;
2459        }
2460
2461        if ( (pl_sd = map_nick2sd(character)) == NULL )
2462        {
2463                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2464                return -1;
2465        }
2466
2467        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2468        {
2469                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2470                return -1;
2471        }
2472       
2473        if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
2474                pc_changelook(pl_sd, LOOK_CLOTHES_COLOR, cloth_color);
2475                clif_displaymessage(pl_sd->fd, msg_txt(36)); // Appearence changed.
2476                if (pl_sd->fd != fd)
2477                        clif_displaymessage(fd, msg_txt(36)); // Appearence changed.
2478        } else {
2479                clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified.
2480                return -1;
2481        }
2482
2483        return 0;
2484}
2485
2486/*==========================================
2487 * Change target's hair style [HiddenDragon]
2488 *------------------------------------------*/
2489int charcommand_hair_style(const int fd, struct map_session_data* sd, const char* command, const char* message)
2490{
2491        int hair_style = 0;
2492        char character[NAME_LENGTH];
2493        char output[200];
2494        struct map_session_data *pl_sd;
2495        nullpo_retr(-1, sd);
2496
2497        if (!message || !*message || sscanf(message, "%d %23[^\n]", &hair_style, character) < 2) {
2498                sprintf(output, "Please, enter a hair style (usage: #hairstyle/#hstyle <hair ID: %d-%d> <player>.", MIN_HAIR_STYLE, MAX_HAIR_STYLE);
2499                clif_displaymessage(fd, output);
2500                return -1;
2501        }
2502
2503        if ( (pl_sd = map_nick2sd(character)) == NULL )
2504        {
2505                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2506                return -1;
2507        }
2508
2509        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2510        {
2511                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2512                return -1;
2513        }
2514
2515        if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) {
2516                        pc_changelook(pl_sd, LOOK_HAIR, hair_style);
2517                        clif_displaymessage(pl_sd->fd, msg_txt(36)); // Appearence changed.
2518                        if (pl_sd->fd != fd)
2519                                clif_displaymessage(fd, msg_txt(36)); // Appearence changed.
2520        } else {
2521                clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified.
2522                return -1;
2523        }
2524
2525        return 0;
2526}
2527
2528/*==========================================
2529 * Change target's hair color [HiddenDragon]
2530 *------------------------------------------*/
2531int charcommand_hair_color(const int fd, struct map_session_data* sd, const char* command, const char* message)
2532{
2533        int hair_color = 0;
2534        char character[NAME_LENGTH];
2535        char output[200];
2536        struct map_session_data *pl_sd;
2537        nullpo_retr(-1, sd);
2538
2539        memset(output, '\0', sizeof(output));
2540
2541        if (!message || !*message || sscanf(message, "%d %23[^\n]", &hair_color, character) < 2) {
2542                sprintf(output, "Please, enter a hair color (usage: #haircolor/#hcolor <hair color: %d-%d> <player>).", MIN_HAIR_COLOR, MAX_HAIR_COLOR);
2543                clif_displaymessage(fd, output);
2544                return -1;
2545        }
2546
2547        if ( (pl_sd = map_nick2sd(character)) == NULL )
2548        {
2549                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2550                return -1;
2551        }
2552
2553        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2554        {
2555                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2556                return -1;
2557        }
2558
2559        if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) {
2560                        pc_changelook(pl_sd, LOOK_HAIR_COLOR, hair_color);
2561                        clif_displaymessage(pl_sd->fd, msg_txt(36)); // Appearence changed.
2562                        if (pl_sd->fd != fd)
2563                                clif_displaymessage(fd, msg_txt(36)); // Appearence changed.
2564        } else {
2565                clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified.
2566                return -1;
2567        }
2568
2569        return 0;
2570}
2571
2572/*==========================================
2573 * Change all target's stats [HiddenDragon]
2574 *------------------------------------------*/
2575int charcommand_allstats(const int fd, struct map_session_data* sd, const char* command, const char* message)
2576{
2577        int index, count, value = 0, max, new_value;
2578        short* status[6];
2579        char character[NAME_LENGTH];
2580        struct map_session_data *pl_sd;
2581
2582        //we don't use direct initialization because it isn't part of the c standard.
2583        nullpo_retr(-1, sd);
2584        memset(character, '\0', sizeof(character));
2585       
2586        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2587                clif_displaymessage(fd, "Please, enter a player name (usage: #statall/#statsall/#allstat/#allstats <player>).");
2588                return -1;
2589        }
2590       
2591        if ( (pl_sd = map_nick2sd(character)) == NULL )
2592        {
2593                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2594                return -1;
2595        }
2596
2597        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2598        {
2599                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2600                return -1;
2601        }
2602
2603        status[0] = &pl_sd->status.str;
2604        status[1] = &pl_sd->status.agi;
2605        status[2] = &pl_sd->status.vit;
2606        status[3] = &pl_sd->status.int_;
2607        status[4] = &pl_sd->status.dex;
2608        status[5] = &pl_sd->status.luk;
2609
2610        count = 0;
2611        max = pc_maxparameter(pl_sd);
2612        for (index = 0; index < ARRAYLENGTH(status); index++) {
2613
2614                if (value > 0 && *status[index] > max - value)
2615                        new_value = max;
2616                else if (value < 0 && *status[index] <= -value)
2617                        new_value = 1;
2618                else
2619                        new_value = *status[index] +value;
2620               
2621                if (new_value != (int)*status[index]) {
2622                        *status[index] = new_value;
2623                        clif_updatestatus(pl_sd, SP_STR + index);
2624                        clif_updatestatus(pl_sd, SP_USTR + index);
2625                        status_calc_pc(pl_sd, 0);
2626                        count++;
2627                }
2628        }
2629
2630        if (count > 0) // if at least 1 stat modified
2631        {
2632                clif_displaymessage(pl_sd->fd, msg_txt(84)); // All stats changed!
2633                if (fd != pl_sd->fd)
2634                        clif_displaymessage(fd, "Player's stats changed"); // All stats changed!
2635        }
2636        else {
2637                if (value < 0)
2638                        clif_displaymessage(fd, msg_txt(177)); // Impossible to decrease a stat.
2639                else
2640                        clif_displaymessage(fd, msg_txt(178)); // Impossible to increase a stat.
2641                return -1;
2642        }
2643
2644        return 0;
2645}
2646
2647/*==========================================
2648 * Gives/Removes a peco from a player [HiddenDragon]
2649 *------------------------------------------*/
2650int charcommand_mount_peco(const int fd, struct map_session_data* sd, const char* command, const char* message)
2651{
2652        struct map_session_data *pl_sd;
2653        char character[NAME_LENGTH];
2654        nullpo_retr(-1, sd);
2655
2656        memset(character, '\0', sizeof(character));
2657
2658        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2659                clif_displaymessage(fd, "Please, enter a player name (usage: #mount/#mountpeco <player>).");
2660                return -1;
2661        }
2662
2663        if ( (pl_sd = map_nick2sd(character)) == NULL )
2664        {
2665                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2666                return -1;
2667        }
2668
2669        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2670        {
2671                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2672                return -1;
2673        }
2674
2675        if (!pc_isriding(pl_sd))
2676        { // if actually no peco
2677                if (!pc_checkskill(pl_sd, KN_RIDING))
2678                {
2679                        clif_displaymessage(fd, msg_txt(217));  // Player cannot mount a PecoePeco with his/her job.
2680                        return -1;
2681                }
2682
2683                if (pl_sd->disguise)
2684                {
2685                        clif_displaymessage(fd, msg_txt(215)); // Player cannot mount a PecoPeco while in disguise.
2686                        return -1;
2687                }
2688
2689                pc_setoption(pl_sd, pl_sd->sc.option | OPTION_RIDING);
2690                if (pl_sd->fd != fd)
2691                        clif_displaymessage(fd, "Player mounted a peco.");
2692                clif_displaymessage(pl_sd->fd, msg_txt(216));   // Mounted Peco.
2693        }
2694        else
2695        {       //Dismount
2696                pc_setoption(pl_sd, pl_sd->sc.option & ~OPTION_RIDING);
2697                clif_displaymessage(pl_sd->fd, msg_txt(218)); // Unmounted Peco.
2698                if (pl_sd->fd != fd)
2699                        clif_displaymessage(fd, "Player unmounted a peco.");
2700        }
2701
2702        return 0;
2703}
2704
2705/*==========================================
2706 * Remove items from a player (now a char command) [HiddenDragon]
2707 *------------------------------------------*/
2708int charcommand_delitem(const int fd, struct map_session_data* sd, const char* command, const char* message)
2709{
2710        struct map_session_data *pl_sd;
2711        char item_name[100];
2712        int i, number = 0, item_id, item_position, count;
2713        struct item_data *item_data;
2714        char character[NAME_LENGTH];
2715        char output[200];
2716
2717        nullpo_retr(-1, sd);
2718
2719        memset(character, '\0', sizeof(character));
2720        memset(item_name, '\0', sizeof(item_name));
2721        memset(output, '\0', sizeof(output));
2722
2723        if (!message || !*message || (
2724                sscanf(message, "\"%99[^\"]\" %d %23[^\n]", item_name, &number, character) < 3 &&
2725                sscanf(message, "%s %d %23[^\n]", item_name, &number, character) < 3
2726        ) || number < 1) {
2727                clif_displaymessage(fd, "Please, enter an item name/id, a quantity and a player name (usage: #delitem <item_name_or_ID> <quantity> <player>).");
2728                return -1;
2729        }
2730
2731        if ( (pl_sd = map_nick2sd(character)) == NULL )
2732        {
2733                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2734                return -1;
2735        }
2736
2737        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2738        {
2739                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2740                return -1;
2741        }
2742
2743        item_id = 0;
2744        if ((item_data = itemdb_searchname(item_name)) != NULL ||
2745            (item_data = itemdb_exists(atoi(item_name))) != NULL)
2746                item_id = item_data->nameid;
2747       
2748        if (item_id > 500) {
2749                item_position = pc_search_inventory(pl_sd, item_id);
2750                if (item_position >= 0) {
2751                        count = 0;
2752                        for(i = 0; i < number && item_position >= 0; i++) {
2753
2754                                //Logs (A)dmins items [Lupus]
2755                                if(log_config.enable_logs&0x400)
2756                                        log_pick_pc(pl_sd, "A", pl_sd->status.inventory[item_position].nameid, -1, &pl_sd->status.inventory[item_position]);
2757
2758                                pc_delitem(pl_sd, item_position, 1, 0);
2759                                count++;
2760                                item_position = pc_search_inventory(pl_sd, item_id); // for next loop
2761                        }
2762                        sprintf(output, msg_txt(113), count); // %d item(s) removed by a GM.
2763                        clif_displaymessage(pl_sd->fd, output);
2764                        if (number == count)
2765                                sprintf(output, msg_txt(114), count); // %d item(s) removed from the player.
2766                        else
2767                                sprintf(output, msg_txt(115), count, count, number); // %d item(s) removed. Player had only %d on %d items.
2768                        clif_displaymessage(fd, output);
2769                } else {
2770                        clif_displaymessage(fd, msg_txt(116)); // Character does not have the item.
2771                        return -1;
2772                }
2773        }
2774        else
2775        {
2776                clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name.
2777                return -1;
2778        }
2779
2780        return 0;
2781}
2782
2783//Added by Coltaro
2784//We're using this function here instead of using time_t so that it only counts player's jail time when he/she's online (and since the idea is to reduce the amount of minutes one by one in status_change_timer...).
2785//Well, using time_t could still work but for some reason that looks like more coding x_x
2786static void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int* minute) {
2787        const int factor_year = 518400; //12*30*24*60 = 518400
2788        const int factor_month = 43200; //30*24*60 = 43200
2789        const int factor_day = 1440; //24*60 = 1440
2790        const int factor_hour = 60;
2791
2792        *year = jailtime/factor_year;
2793        jailtime -= *year*factor_year;
2794        *month = jailtime/factor_month;
2795        jailtime -= *month*factor_month;
2796        *day = jailtime/factor_day;
2797        jailtime -= *day*factor_day;
2798        *hour = jailtime/factor_hour;
2799        jailtime -= *hour*factor_hour;
2800        *minute = jailtime;
2801
2802        *year = *year > 0? *year : 0;
2803        *month = *month > 0? *month : 0;
2804        *day = *day > 0? *day : 0;
2805        *hour = *hour > 0? *hour : 0;
2806        *minute = *minute > 0? *minute : 0;
2807        return;
2808}
2809
2810/*==========================================
2811 * Jail a player for a certain amount of time [Coltaro]
2812 *------------------------------------------*/
2813int charcommand_jailtime(const int fd, struct map_session_data* sd, const char* command, const char* message)
2814{ 
2815        struct map_session_data* pl_sd;
2816        int year, month, day, hour, minute;
2817        char character[NAME_LENGTH];
2818        char output[200];
2819        memset(character, '\0', sizeof(character));
2820
2821        nullpo_retr(-1, sd);
2822
2823        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2824                clif_displaymessage(fd, "Please, enter a player name (usage: #jailtime <player>).");
2825                return -1;
2826        }
2827
2828        if ( (pl_sd = map_nick2sd(character)) == NULL )
2829        {
2830                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2831                return -1;
2832        }
2833
2834        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2835        {
2836                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2837                return -1;
2838        }
2839
2840        if (!pl_sd->sc.data[SC_JAILED]) {
2841                clif_displaymessage(fd, "This player is not in jail.");
2842                return -1;
2843        }
2844
2845        if (pl_sd->sc.data[SC_JAILED]->val1 == INT_MAX) {
2846                clif_displaymessage(fd, "This player has been jailed indefinitely.");
2847                return 0;
2848        }
2849
2850        if (pl_sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?)
2851                clif_displaymessage(fd, "This player has been jailed for an unknown amount of time.");
2852                return -1;
2853        }
2854        //Get remaining jail time
2855        get_jail_time(pl_sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute);
2856        sprintf(output,msg_txt(402),"This player will remain",year,month,day,hour,minute); 
2857        clif_displaymessage(fd, output);
2858
2859        return 0;
2860}
2861
2862/*==========================================
2863 * Disguises a player [HiddenDragon]
2864 *------------------------------------------*/
2865int charcommand_disguise(const int fd, struct map_session_data* sd, const char* command, const char* message)
2866{
2867        int mob_id;
2868        char mob_name[NAME_LENGTH];
2869        struct map_session_data* pl_sd;
2870        char character[NAME_LENGTH];
2871        nullpo_retr(-1, sd);
2872
2873        memset(character, '\0', sizeof(character));
2874        memset(mob_name, '\0', sizeof(mob_name));
2875
2876        if (!message || !*message || sscanf(message, "%s %23[^\n]", mob_name, character) < 2) {
2877                clif_displaymessage(fd, "Please, enter a Monster/NPC name/id and a player name (usage: #disguise <monster_name_or_monster_ID> <player>).");
2878                return -1;
2879        }
2880
2881        if ( (pl_sd = map_nick2sd(character)) == NULL )
2882        {
2883                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2884                return -1;
2885        }
2886
2887        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2888        {
2889                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2890                return -1;
2891        }
2892
2893        if ((mob_id = atoi(mob_name)) > 0)
2894        {       //Acquired an ID
2895                if (!mobdb_checkid(mob_id) && !npcdb_checkid(mob_id))
2896                        mob_id = 0; //Invalid id for either mobs or npcs.
2897        }       else    { //Acquired a Name
2898                if ((mob_id = mobdb_searchname(mob_name)) == 0)
2899                {
2900                        struct npc_data* nd = npc_name2id(mob_name);
2901                        if (nd != NULL)
2902                                mob_id = nd->class_;
2903                }
2904        }
2905
2906        if (mob_id == 0)
2907        {
2908                clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found.
2909                return -1;
2910        }
2911
2912        if(pc_isriding(pl_sd))
2913        {
2914                //FIXME: wrong message [ultramage]
2915                //clif_displaymessage(fd, msg_txt(228));        // Character cannot wear disguise while riding a PecoPeco.
2916                return -1;
2917        }
2918
2919        pc_disguise(pl_sd, mob_id);
2920        clif_displaymessage(pl_sd->fd, msg_txt(122));   // Disguise applied.
2921        if (pl_sd->fd != fd)
2922                clif_displaymessage(fd, msg_txt(140)); // Character's disguise applied.
2923       
2924       
2925        return 0;
2926}
2927
2928/*==========================================
2929 * Undisguises a player [HiddenDragon]
2930 *------------------------------------------*/
2931int charcommand_undisguise(const int fd, struct map_session_data* sd, const char* command, const char* message)
2932{
2933        char character[NAME_LENGTH];
2934        struct map_session_data* pl_sd;
2935        nullpo_retr(-1, sd);
2936
2937        memset(character, '\0', sizeof(character));
2938
2939        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2940                clif_displaymessage(fd, "Please, enter a player name (usage: #undisguise <player>).");
2941                return -1;
2942        }
2943
2944        if ( (pl_sd = map_nick2sd(character)) == NULL )
2945        {
2946                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2947                return -1;
2948        }
2949
2950        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
2951        {
2952                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
2953                return -1;
2954        }
2955
2956        if (pl_sd->disguise)
2957        {
2958                pc_disguise(pl_sd, 0);
2959                clif_displaymessage(pl_sd->fd, msg_txt(124));   // Disguise removed from character
2960                if (pl_sd->fd != fd)
2961                        clif_displaymessage(fd, msg_txt(141));  // Undisguise applied
2962        }
2963        else {
2964                clif_displaymessage(fd, msg_txt(142)); // Character is not disguised.
2965                return -1;
2966        }
2967
2968        return 0;
2969}
2970
2971/*==========================================
2972 * Displays contents of target's cart [HiddenDragon]
2973 *------------------------------------------*/
2974int charcommand_cart_list(const int fd, struct map_session_data* sd, const char* command, const char* message)
2975{
2976        char outputtmp[200];
2977        char output[200];
2978        char character[NAME_LENGTH];
2979        struct map_session_data *pl_sd;
2980        struct item_data *item_data, *item_temp;
2981        int i, j, count = 0, counter = 0, counter2;
2982        nullpo_retr(-1, sd);
2983
2984        memset(character, '\0', sizeof(character));
2985        memset(output, '\0', sizeof(output));
2986        memset(outputtmp, '\0', sizeof(outputtmp));
2987
2988        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
2989                clif_displaymessage(fd, "Please, enter a player name (usage: #cartlist <player>).");
2990                return -1;
2991        }
2992
2993        if ( (pl_sd = map_nick2sd(character)) == NULL )
2994        {
2995                clif_displaymessage(fd, msg_txt(3)); // Character not found.
2996                return -1;
2997        }
2998
2999        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3000        {
3001                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3002                return -1;
3003        }
3004
3005        for (i = 0; i < MAX_CART; i++) {
3006                if (pl_sd->status.cart[i].nameid > 0 && (item_data = itemdb_search(pl_sd->status.cart[i].nameid)) != NULL) {
3007                        counter = counter + pl_sd->status.cart[i].amount;
3008                        count++;
3009                        if (count == 1) {
3010                                sprintf(output, "------ Cart items list of '%s' ------", pl_sd->status.name);
3011                                clif_displaymessage(fd, output);
3012                        }
3013                        if (pl_sd->status.cart[i].refine)
3014                                sprintf(output, "%d %s %+d (%s %+d, id: %d)", pl_sd->status.cart[i].amount, item_data->name, pl_sd->status.cart[i].refine, item_data->jname, pl_sd->status.cart[i].refine, pl_sd->status.cart[i].nameid);
3015                        else
3016                                sprintf(output, "%d %s (%s, id: %d)", pl_sd->status.cart[i].amount, item_data->name, item_data->jname, pl_sd->status.cart[i].nameid);
3017                        clif_displaymessage(fd, output);
3018                        memset(output, '\0', sizeof(output));
3019                        counter2 = 0;
3020                        for (j = 0; j < item_data->slot; j++) {
3021                                if (pl_sd->status.cart[i].card[j]) {
3022                                        if ( (item_temp = itemdb_search(pl_sd->status.cart[i].card[j])) != NULL) {
3023                                                if (output[0] == '\0')
3024                                                        sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
3025                                                else
3026                                                        sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
3027                                                strcat(output, outputtmp);
3028                                        }
3029                                }
3030                        }
3031                        if (output[0] != '\0') {
3032                                output[strlen(output) - 2] = ')';
3033                                output[strlen(output) - 1] = '\0';
3034                                clif_displaymessage(fd, output);
3035                        }
3036                }
3037        }
3038        if (count == 0)
3039                clif_displaymessage(fd, "No item found in the cart of this player.");
3040        else {
3041                sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
3042                clif_displaymessage(fd, output);
3043        }
3044
3045        return 0;
3046}
3047
3048static int charcommand_stopattack(struct block_list *bl,va_list ap)
3049{
3050        struct unit_data *ud = unit_bl2ud(bl);
3051        int id = va_arg(ap, int);
3052        if (ud && ud->attacktimer != INVALID_TIMER && (!id || id == ud->target))
3053        {
3054                unit_stop_attack(bl);
3055                return 1;
3056        }
3057        return 0;
3058}
3059
3060/*==========================================
3061 * Enable a player to kill players even when not in pvp [HiddenDragon]
3062 *------------------------------------------*/
3063int charcommand_killer(const int fd, struct map_session_data* sd, const char* command, const char* message)
3064{
3065        char character[NAME_LENGTH];
3066        struct map_session_data *pl_sd;
3067        memset(character, '\0', sizeof(character));
3068
3069        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3070                clif_displaymessage(fd, "Please, enter a player name (usage: #killer <player>).");
3071                return -1;
3072        }
3073       
3074        if ( (pl_sd = map_nick2sd(character)) == NULL )
3075        {
3076                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3077                return -1;
3078        }
3079
3080        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3081        {
3082                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3083                return -1;
3084        }
3085       
3086        pl_sd->state.killer = !pl_sd->state.killer;
3087
3088        if(pl_sd->state.killer)
3089        {
3090                clif_displaymessage(pl_sd->fd, msg_txt(241));
3091                if (pl_sd->fd != fd)
3092                        clif_displaymessage(fd, "Target player can now kill anybody.");
3093        }
3094        else
3095        {
3096                clif_displaymessage(pl_sd->fd, msg_txt(287));
3097                if (pl_sd->fd != fd)
3098                        clif_displaymessage(fd, msg_txt(287));
3099                pc_stop_attack(pl_sd);
3100        }
3101
3102        return 0;
3103}
3104
3105/*==========================================
3106 * Enable other players to kill target even when not in pvp [HiddenDragon]
3107 *------------------------------------------*/
3108int charcommand_killable(const int fd, struct map_session_data* sd, const char* command, const char* message)
3109{
3110        char character[NAME_LENGTH];
3111        struct map_session_data *pl_sd;
3112        memset(character, '\0', sizeof(character));
3113       
3114        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3115                clif_displaymessage(fd, "Please, enter a player name (usage: #killable <player>).");
3116                return -1;
3117        }
3118       
3119        if ( (pl_sd = map_nick2sd(character)) == NULL )
3120        {
3121                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3122                return -1;
3123        }
3124
3125        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3126        {
3127                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3128                return -1;
3129        }
3130       
3131        pl_sd->state.killable = !pl_sd->state.killable;
3132
3133        if(pl_sd->state.killable)
3134        {
3135                clif_displaymessage(pl_sd->fd, msg_txt(242));
3136                if (pl_sd->fd != fd)
3137                        clif_displaymessage(fd, msg_txt(289));
3138        }
3139        else
3140        {
3141                clif_displaymessage(pl_sd->fd, msg_txt(288));
3142                if (pl_sd->fd != fd)
3143                        clif_displaymessage(fd, msg_txt(290));
3144                map_foreachinrange(charcommand_stopattack,&pl_sd->bl, AREA_SIZE, BL_CHAR, pl_sd->bl.id);
3145        }
3146
3147        return 0;
3148}
3149
3150/*==========================================
3151 * Drop all of the target's possessions on the ground
3152 *------------------------------------------*/
3153int charcommand_dropall(const int fd, struct map_session_data* sd, const char* command, const char* message)
3154{
3155        int i;
3156        struct map_session_data *pl_sd = NULL;
3157        nullpo_retr(-1, sd);
3158
3159        if (!message || !*message)
3160                return -1;
3161        if((pl_sd=map_nick2sd((char *) message)) == NULL)
3162                return -1;
3163        for (i = 0; i < MAX_INVENTORY; i++) {
3164                if (pl_sd->status.inventory[i].amount) {
3165                        if(pl_sd->status.inventory[i].equip != 0)
3166                                pc_unequipitem(pl_sd, i, 3);
3167                        pc_dropitem(pl_sd,  i, pl_sd->status.inventory[i].amount);
3168                }
3169        }
3170
3171        clif_displaymessage(pl_sd->fd, "All items dropped");
3172        clif_displaymessage(fd, "It is done");
3173
3174        return 0;
3175}
3176
3177/*==========================================
3178 * Put all of the target's possessions into storage
3179 *------------------------------------------*/
3180int charcommand_storeall(const int fd, struct map_session_data* sd, const char* command, const char* message)
3181{
3182        int i;
3183        struct map_session_data *pl_sd = NULL;
3184        nullpo_retr(-1, sd);
3185
3186        if (!message || !*message)
3187                return -1;
3188        if((pl_sd=map_nick2sd((char *) message)) == NULL)
3189                return -1;
3190
3191        if (pl_sd->state.storage_flag != 1)
3192        {       //Open storage.
3193                switch (storage_storageopen(pl_sd)) {
3194                case 2: //Try again
3195                        clif_displaymessage(fd, "Had to open the characters storage window...");
3196                        clif_displaymessage(fd, "run this command again..");
3197                        return 0;
3198                case 1: //Failure
3199                        clif_displaymessage(fd, "The character currently can't use the storage.");
3200                        return 1;
3201                }
3202        }
3203
3204        for (i = 0; i < MAX_INVENTORY; i++) {
3205                if (pl_sd->status.inventory[i].amount) {
3206                        if(pl_sd->status.inventory[i].equip != 0)
3207                                pc_unequipitem(pl_sd, i, 3);
3208                        storage_storageadd(pl_sd,  i, sd->status.inventory[i].amount);
3209                }
3210        }
3211        storage_storageclose(pl_sd);
3212
3213        clif_displaymessage(pl_sd->fd, "Everything you own has been put away for safe keeping.");
3214        clif_displaymessage(pl_sd->fd, "go to the nearest kafka to retrieve it..");
3215        clif_displaymessage(pl_sd->fd, "   -- the management");
3216
3217        clif_displaymessage(fd, "It is done");
3218
3219        return 0;
3220}
3221
3222/*==========================================
3223 * Refreshes target [HiddenDragon]
3224 *------------------------------------------*/
3225int charcommand_refresh(const int fd, struct map_session_data* sd, const char* command, const char* message)
3226{
3227        char character[NAME_LENGTH];
3228        struct map_session_data *pl_sd;
3229        memset(character, '\0', sizeof(character));
3230
3231        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3232                clif_displaymessage(fd, "Please, enter a player name (usage: #refresh <player>).");
3233                return -1;
3234        }
3235       
3236        if ( (pl_sd = map_nick2sd(character)) == NULL )
3237        {
3238                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3239                return -1;
3240        }
3241
3242        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3243        {
3244                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3245                return -1;
3246        }
3247       
3248        clif_refresh(pl_sd);
3249        return 0;
3250}
3251
3252
3253/*==========================================
3254 * View target's exp [HiddenDragon]
3255 *------------------------------------------*/
3256int charcommand_exp(const int fd, struct map_session_data* sd, const char* command, const char* message)
3257{
3258        char output[200];
3259        double nextb, nextj;
3260        char character[NAME_LENGTH];
3261        struct map_session_data *pl_sd;
3262       
3263        memset(character, '\0', sizeof(character));
3264        memset(output, '\0', sizeof(output));
3265       
3266
3267        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3268                clif_displaymessage(fd, "Please, enter a player name (usage: #exp <player>).");
3269                return -1;
3270        }
3271       
3272        if ( (pl_sd = map_nick2sd(character)) == NULL )
3273        {
3274                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3275                return -1;
3276        }
3277
3278        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3279        {
3280                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3281                return -1;
3282        }
3283       
3284        nextb = pc_nextbaseexp(pl_sd);
3285        if (nextb)
3286                nextb = pl_sd->status.base_exp*100.0/nextb;
3287       
3288        nextj = pc_nextjobexp(pl_sd);
3289        if (nextj)
3290                nextj = pl_sd->status.job_exp*100.0/nextj;
3291       
3292        sprintf(output, "Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%)", pl_sd->status.base_level, nextb, pl_sd->status.job_level, nextj);
3293        clif_displaymessage(fd, output);
3294        return 0;
3295}
3296
3297/*==========================================
3298 * Makes monsters ignore target [HiddenDragon]
3299 *------------------------------------------*/ 
3300int charcommand_monsterignore(const int fd, struct map_session_data* sd, const char* command, const char* message)
3301{
3302        char character[NAME_LENGTH];
3303        struct map_session_data *pl_sd;
3304        memset(character, '\0', sizeof(character));
3305
3306        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3307                clif_displaymessage(fd, "Please, enter a player name (usage: #monsterignore/#battleignore <player>).");
3308                return -1;
3309        }
3310       
3311        if ( (pl_sd = map_nick2sd(character)) == NULL )
3312        {
3313                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3314                return -1;
3315        }
3316
3317        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3318        {
3319                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3320                return -1;
3321        }
3322
3323        if (!pl_sd->state.monster_ignore) {
3324                pl_sd->state.monster_ignore = 1;
3325                clif_displaymessage(pl_sd->fd, "You are now immune to attacks.");
3326                if (fd != pl_sd->fd)
3327                        clif_displaymessage(pl_sd->fd, "Target player is now immune to attacks.");
3328        } else {
3329                sd->state.monster_ignore = 0;
3330                clif_displaymessage(sd->fd, "You are no longer immune to attacks.");
3331                if (fd != pl_sd->fd)
3332                        clif_displaymessage(pl_sd->fd, "Target player is no longer immune to attacks.");
3333
3334        }
3335
3336        return 0;
3337}
3338
3339/*==========================================
3340 * Change target's size [HiddenDragon]
3341 *------------------------------------------*/
3342int charcommand_size(const int fd, struct map_session_data* sd, const char* command, const char* message)
3343{
3344        int size=0;
3345        char character[NAME_LENGTH];
3346        struct map_session_data *pl_sd;
3347        memset(character, '\0', sizeof(character));
3348
3349        if (!message || !*message || sscanf(message, "%d %23[^\n]", &size, character) < 2) {
3350                clif_displaymessage(fd, "Please, enter a player name (usage: #size <0-2> <player>).");
3351                return -1;
3352        }
3353       
3354        if ( (pl_sd = map_nick2sd(character)) == NULL )
3355        {
3356                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3357                return -1;
3358        }
3359
3360        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3361        {
3362                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3363                return -1;
3364        }
3365
3366        if(pl_sd->state.size) {
3367                pl_sd->state.size=0;
3368                pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, 3);
3369        }
3370
3371        if(size==1) {
3372                pl_sd->state.size=1;
3373                clif_specialeffect(&pl_sd->bl,420,AREA);
3374                clif_displaymessage(fd, "Size changed."); 
3375                if (fd != pl_sd->fd)
3376                        clif_displaymessage(pl_sd->fd, "Size changed."); 
3377        } else if(size==2) {
3378                pl_sd->state.size=2;
3379                clif_specialeffect(&pl_sd->bl,422,AREA);
3380                clif_displaymessage(fd, "Size changed."); 
3381                if (fd != pl_sd->fd)
3382                        clif_displaymessage(pl_sd->fd, "Size changed."); 
3383        }
3384        else
3385        {
3386                clif_displaymessage(fd, "Size restored."); 
3387                if (fd != pl_sd->fd)
3388                        clif_displaymessage(pl_sd->fd, "Size restored."); 
3389        }
3390
3391
3392        return 0;
3393}
3394
3395/*==========================================
3396 * Level up target's homunculus [HiddenDragon]
3397 *------------------------------------------*/
3398int charcommand_homlevel(const int fd, struct map_session_data* sd, const char* command, const char* message)
3399{
3400        TBL_HOM * hd;
3401        int level = 0, i = 0;
3402
3403        char character[NAME_LENGTH];
3404        struct map_session_data *pl_sd;
3405        memset(character, '\0', sizeof(character));
3406
3407        if (!message || !*message || sscanf(message, "%d %23[^\n]", &level, character) < 2) {
3408                clif_displaymessage(fd, "Please, enter a player name and level (usage: #homlevel <# of levels> <player>).");
3409                return -1;
3410        }
3411       
3412        if ( (pl_sd = map_nick2sd(character)) == NULL )
3413        {
3414                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3415                return -1;
3416        }
3417
3418        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3419        {
3420                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3421                return -1;
3422        }
3423               
3424        if ( !merc_is_hom_active(pl_sd->hd) )
3425        {
3426                clif_displaymessage(fd, "Target player does not have a homunculus."); 
3427                return 1;
3428        }
3429
3430        hd = pl_sd->hd;
3431       
3432        for (i = 1; i <= level && hd->exp_next; i++){
3433                hd->homunculus.exp += hd->exp_next;
3434                merc_hom_levelup(hd);
3435        }
3436        status_calc_homunculus(hd,0);
3437        status_percent_heal(&hd->bl, 100, 100);
3438        clif_misceffect2(&hd->bl,568);
3439        clif_displaymessage(pl_sd->fd, "Homunculus level changed."); 
3440        if (pl_sd->fd != fd)
3441                clif_displaymessage(fd, "Player's homunculus level changed.");
3442
3443        return 0;
3444}
3445
3446/*==========================================
3447 * Evolve target's homunculus [HiddenDragon]
3448 *------------------------------------------*/
3449int charcommand_homevolution(const int fd, struct map_session_data* sd, const char* command, const char* message)
3450{
3451        char character[NAME_LENGTH];
3452        struct map_session_data *pl_sd;
3453        memset(character, '\0', sizeof(character));
3454
3455        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3456                clif_displaymessage(fd, "Please, enter a player name (usage: #homevolution <player>).");
3457                return -1;
3458        }
3459
3460        if ( (pl_sd = map_nick2sd(character)) == NULL )
3461        {
3462                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3463                return -1;
3464        }
3465
3466        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3467        {
3468                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3469                return -1;
3470        }
3471
3472        if ( !merc_is_hom_active(pl_sd->hd) ) {
3473                clif_displaymessage(fd, "Target player does not have a homunculus."); 
3474                return -1;
3475        }
3476
3477        if ( !merc_hom_evolution(pl_sd->hd) ) {
3478                clif_displaymessage(fd, "Target homunculus cannot evolve."); 
3479                return -1;
3480        }
3481
3482        clif_displaymessage(pl_sd->fd, "Homunculus evolution initiated."); 
3483        if (pl_sd->fd != fd)
3484                clif_displaymessage(fd, "Homunculus evolution initiated."); 
3485        return 0;
3486}
3487
3488/*==========================================
3489 * Create a homunculus for target [HiddenDragon]
3490 *------------------------------------------*/
3491int charcommand_makehomun(const int fd, struct map_session_data* sd, const char* command, const char* message)
3492{
3493        int homunid;
3494       
3495        char character[NAME_LENGTH];
3496        char output[200];
3497        struct map_session_data *pl_sd;
3498        memset(character, '\0', sizeof(character));
3499        memset(output, '\0', sizeof(output));
3500
3501        if (!message || !*message || sscanf(message, "%d %23[^\n]", &homunid, character) < 2) {
3502                sprintf(output, "Please, enter a player name (usage: #makehomun <homunculus id: %d-%d> <player>).", HM_CLASS_BASE, HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1);
3503                clif_displaymessage(fd, output);
3504                return -1;
3505        }
3506       
3507        if ( (pl_sd = map_nick2sd(character)) == NULL )
3508        {
3509                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3510                return -1;
3511        }
3512
3513        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3514        {
3515                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3516                return -1;
3517        }
3518       
3519        if( homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1 )
3520        {
3521                clif_displaymessage(fd, "Invalid homunculus ID."); 
3522                return -1;
3523        }
3524       
3525        if(pl_sd->status.hom_id == 0)
3526        {
3527                merc_create_homunculus_request(pl_sd,homunid);
3528        }
3529        else
3530        {
3531                clif_displaymessage(fd, "Target player already has a homunculus.");
3532        }
3533        return 0;
3534}
3535
3536/*==========================================
3537 * Change Target's homunculus' friendlyness [HiddenDragon]
3538 *------------------------------------------*/
3539int charcommand_homfriendly(const int fd, struct map_session_data* sd, const char* command, const char* message)
3540{
3541        int friendly = 0;
3542
3543        char character[NAME_LENGTH];
3544        struct map_session_data *pl_sd;
3545        memset(character, '\0', sizeof(character));
3546
3547        if (!message || !*message || sscanf(message, "%d %23[^\n]", &friendly, character) < 2) {
3548                clif_displaymessage(fd, "Please, enter a player name and friendly value (usage: #homfriendly <0-1000> <player>).");
3549                return -1;
3550        }
3551       
3552        if ( (pl_sd = map_nick2sd(character)) == NULL )
3553        {
3554                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3555                return -1;
3556        }
3557
3558        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3559        {
3560                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3561                return -1;
3562        }
3563
3564        if (merc_is_hom_active(pl_sd->hd)) {
3565                if (friendly > 0 && friendly <= 1000) {
3566                        pl_sd->hd->homunculus.intimacy = friendly * 100 ;
3567                        clif_send_homdata(pl_sd,SP_INTIMATE,friendly);
3568                        clif_displaymessage(pl_sd->fd, "Homunculus friendly value changed."); 
3569                        if (fd != pl_sd->fd)
3570                                clif_displaymessage(fd, "Homunculus friendly value changed."); 
3571                } else {
3572                        clif_displaymessage(fd, "Invalid friendly value."); 
3573                }
3574        }
3575        else
3576        {
3577                clif_displaymessage(fd, "Target player's homunculus does not exist."); 
3578                return -1;
3579        }
3580
3581        return 0;
3582}
3583
3584/*==========================================
3585 * Modify target's homunculus hunger [HiddenDragon]
3586 *------------------------------------------*/
3587int charcommand_homhungry(const int fd, struct map_session_data* sd, const char* command, const char* message)
3588{
3589        int hungry = 0;
3590
3591        char character[NAME_LENGTH];
3592        struct map_session_data *pl_sd;
3593        memset(character, '\0', sizeof(character));
3594
3595        if (!message || !*message || sscanf(message, "%d %23[^\n]", &hungry, character) < 2) {
3596                clif_displaymessage(fd, "Please, enter a player name (usage: #homhungry <0-100> <player>).");
3597                return -1;
3598        }
3599       
3600        if ( (pl_sd = map_nick2sd(character)) == NULL )
3601        {
3602                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3603                return -1;
3604        }
3605
3606        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3607        {
3608                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3609                return -1;
3610        }
3611
3612        if (pl_sd->status.hom_id > 0 && pl_sd->hd) {
3613                struct homun_data *hd = pl_sd->hd;
3614                if (hungry >= 0 && hungry <= 100) {
3615                        hd->homunculus.hunger = hungry;
3616                        clif_send_homdata(pl_sd,SP_HUNGRY,hd->homunculus.hunger);
3617                        clif_displaymessage(pl_sd->fd, "Homunculus hungry value changed."); 
3618                        if (fd != pl_sd->fd)
3619                                clif_displaymessage(fd, "Homunculus hungry value changed."); 
3620                } else {
3621                        clif_displaymessage(fd, "Invalid hungry value."); 
3622                        return -1;
3623                }
3624        }
3625        else
3626        {
3627                clif_displaymessage(fd, "Target player does not have a homunculus."); 
3628                return -1;
3629        }
3630       
3631
3632        return 0;
3633}
3634
3635/*==========================================
3636 * Show target's homunculus stats [HiddenDragon]
3637 *------------------------------------------*/
3638int charcommand_hominfo(const int fd, struct map_session_data* sd, const char* command, const char* message)
3639{
3640        struct homun_data *hd;
3641        struct status_data *status;
3642        char output[200];
3643        char character[NAME_LENGTH];
3644        struct map_session_data *pl_sd;
3645        memset(character, '\0', sizeof(character));
3646        memset(output, '\0', sizeof(output));
3647
3648        if (!message || !*message || sscanf(message, "%23[^\n]", character) < 1) {
3649                clif_displaymessage(fd, "Please, enter a player name (usage: #hominfo <player>).");
3650                return -1;
3651        }
3652
3653        if ( (pl_sd = map_nick2sd(character)) == NULL )
3654        {
3655                clif_displaymessage(fd, msg_txt(3)); // Character not found.
3656                return -1;
3657        }
3658
3659        if ( pc_isGM(sd) < pc_isGM(pl_sd) )
3660        {
3661                clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
3662                return -1;
3663        }
3664
3665        if(!merc_is_hom_active(pl_sd->hd))
3666                return -1;
3667
3668        hd = pl_sd->hd;
3669        status = status_get_status_data(&hd->bl);
3670        clif_displaymessage(fd, "Homunculus stats :");
3671
3672        snprintf(output, sizeof(output), "HP : %d/%d - SP : %d/%d", status->hp, status->max_hp, status->sp, status->max_sp);
3673        clif_displaymessage(fd, output);
3674
3675        snprintf(output, sizeof(output), "ATK : %d - MATK : %d~%d", status->rhw.atk2 +status->batk, status->matk_min, status->matk_max);
3676        clif_displaymessage(fd, output);
3677
3678        snprintf(output, sizeof(output), "Hungry : %d - Intimacy : %u", hd->homunculus.hunger, hd->homunculus.intimacy/100);
3679        clif_displaymessage(fd, output);
3680
3681        snprintf(output, sizeof(output), "Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d", status->str, status->agi, status->vit, status->int_, status->dex, status->luk);
3682        clif_displaymessage(fd, output);
3683
3684        return 0;
3685}
3686
3687
3688/*==========================================
3689 * charcommand_info[] structure definition
3690 *------------------------------------------*/
3691
3692CharCommandInfo charcommand_info[] = {
3693        { "job",               60,     charcommand_jobchange },
3694        { "jobchange",         60,     charcommand_jobchange },
3695        { "petrename",         50,     charcommand_petrename },
3696        { "petfriendly",       50,     charcommand_petfriendly },
3697        { "stats",             40,     charcommand_stats },
3698        { "option",            60,     charcommand_option },
3699        { "reset",             60,     charcommand_reset },
3700        { "save",              60,     charcommand_save },
3701        { "spiritball",        40,     charcommand_spiritball },
3702        { "itemlist",          40,     charcommand_itemlist },
3703        { "effect",            40,     charcommand_effect },
3704        { "storagelist",       40,     charcommand_storagelist },
3705        { "item",              60,     charcommand_item },
3706        { "warp",              60,     charcommand_warp },
3707        { "rura",              60,     charcommand_warp },
3708        { "rura+",             60,     charcommand_warp },
3709        { "zeny",              60,     charcommand_zeny },
3710        { "fakename",          50,     charcommand_fakename },
3711        { "baselvl",           60,     charcommand_baselevel },
3712        { "baselevel",         60,     charcommand_baselevel },
3713        { "blvl",              60,     charcommand_baselevel },
3714        { "blevel",            60,     charcommand_baselevel },
3715        { "joblvl",            60,     charcommand_joblevel },
3716        { "joblevel",          60,     charcommand_joblevel },
3717        { "jlvl",              60,     charcommand_joblevel },
3718        { "jlevel",            60,     charcommand_joblevel },
3719        { "questskill",        60,     charcommand_questskill },
3720        { "lostskill",         60,     charcommand_lostskill },
3721        { "skreset",           60,     charcommand_skreset },
3722        { "streset",           60,     charcommand_streset },
3723        { "model",             50,     charcommand_model },
3724        { "skpoint",           60,     charcommand_skpoint },
3725        { "stpoint",           60,     charcommand_stpoint },
3726        { "changesex",         60,     charcommand_changesex },
3727        { "feelreset",         60,     charcommand_feelreset },
3728        { "help",              20,     charcommand_help },
3729        { "load",              60,     charcommand_load },
3730        { "speed",             60,     charcommand_speed },
3731        { "storage",           60,     charcommand_storage },
3732        { "gstorage",          60,     charcommand_guildstorage },
3733        { "hide",              60,     charcommand_hide },
3734        { "alive",             60,     charcommand_alive },
3735        { "revive",            60,     charcommand_alive },
3736        { "heal",              60,     charcommand_heal },
3737        { "item2",             60,     charcommand_item2 },
3738        { "itemreset",         60,     charcommand_itemreset },
3739        { "refine",            60,     charcommand_refine },
3740        { "produce",           60,     charcommand_produce },
3741        { "str",               60,     charcommand_param },
3742        { "agi",               60,     charcommand_param },
3743        { "vit",               60,     charcommand_param },
3744        { "int",               60,     charcommand_param },
3745        { "dex",               60,     charcommand_param },
3746        { "luk",               60,     charcommand_param },
3747        { "glvl",              60,     charcommand_guildlevelup },
3748        { "glevel",            60,     charcommand_guildlevelup },
3749        { "guildlvl",          60,     charcommand_guildlevelup },
3750        { "guildlevel",        60,     charcommand_guildlevelup },
3751        { "hatch",             50,     charcommand_hatch },
3752        { "pethungry",         60,     charcommand_pethungry },
3753        { "allskill",          60,     charcommand_allskill },
3754        { "allskills",         60,     charcommand_allskill },
3755        { "skillall",          60,     charcommand_allskill },
3756        { "skillsall",         60,     charcommand_allskill },
3757        { "dye",               50,     charcommand_dye },
3758        { "hairstyle",         50,     charcommand_hair_style },
3759        { "hstyle",            50,     charcommand_hair_style },
3760        { "haircolor",         50,     charcommand_hair_color },
3761        { "hcolor",            50,     charcommand_hair_color },
3762        { "allstat",           60,     charcommand_allstats },
3763        { "allstats",          60,     charcommand_allstats },
3764        { "statall",           60,     charcommand_allstats },
3765        { "statsall",          60,     charcommand_allstats },
3766        { "mount",             50,     charcommand_mount_peco },
3767        { "mountpeco",         50,     charcommand_mount_peco },
3768        { "delitem",           60,     charcommand_delitem },
3769        { "jailtime",          40,     charcommand_jailtime },
3770        { "disguise",          60,     charcommand_disguise },
3771        { "undisguise",        60,     charcommand_undisguise },
3772        { "cartlist",          40,     charcommand_cart_list },
3773        { "killer",            60,     charcommand_killer },
3774        { "killable",          60,     charcommand_killable },
3775        { "dropall",           60,     charcommand_dropall },
3776        { "storeall",          60,     charcommand_storeall },
3777        { "refresh",           40,     charcommand_refresh },
3778        { "exp",                1,     charcommand_exp },
3779        { "monsterignore",     60,     charcommand_monsterignore },
3780        { "size",              50,     charcommand_size },
3781        { "hlvl",              60,     charcommand_homlevel },
3782        { "hlevel",            60,     charcommand_homlevel },
3783        { "homlvl",            60,     charcommand_homlevel },
3784        { "homlevel",          60,     charcommand_homlevel },
3785        { "homevolve",         60,     charcommand_homevolution },
3786        { "homevolution",      60,     charcommand_homevolution },
3787        { "homfriendly",       60,     charcommand_homfriendly },
3788        { "homhungry",         60,     charcommand_homhungry },
3789        { "hominfo",           40,     charcommand_hominfo },
3790        { "cash",              60,     charcommand_cash },
3791        { "points",            60,     charcommand_cash },
3792};
3793
3794
3795/*==========================================
3796 * Command lookup functions
3797 *------------------------------------------*/
3798static CharCommandInfo* get_charcommandinfo_byname(const char* name)
3799{
3800        int i;
3801        if( *name == charcommand_symbol ) name++; // for backwards compatibility
3802        ARR_FIND( 0, ARRAYLENGTH(charcommand_info), i, strcmpi(charcommand_info[i].command, name) == 0 );
3803        return ( i < ARRAYLENGTH(charcommand_info) ) ? &charcommand_info[i] : NULL;
3804}
3805
3806static CharCommandInfo* get_charcommandinfo_byfunc(const CharCommandFunc func)
3807{
3808        int i;
3809        ARR_FIND( 0, ARRAYLENGTH(charcommand_info), i, charcommand_info[i].func == func );
3810        return ( i < ARRAYLENGTH(charcommand_info) ) ? &charcommand_info[i] : NULL;
3811}
3812
3813
3814/*==========================================
3815 * Retrieve the command's required gm level
3816 *------------------------------------------*/
3817int get_charcommand_level(const CharCommandFunc func)
3818{
3819        CharCommandInfo* info = get_charcommandinfo_byfunc(func);
3820        return ( info != NULL ) ? info->level : 100; // 100: command can not be used
3821}
3822
3823
3824/// Executes a char-command.
3825/// To be called by internal server code (bypasses various restrictions).
3826bool is_charcommand_sub(const int fd, struct map_session_data* sd, const char* str, int gmlvl)
3827{
3828        CharCommandInfo* info;
3829        char command[100];
3830        char args[100];
3831        char output[200];
3832       
3833        if( !str || !*str )
3834                return false;
3835
3836        if( *str != charcommand_symbol ) // check first char
3837                return false;
3838
3839        if( sscanf(str, "%99s %99[^\n]", command, args) < 2 )
3840                args[0] = '\0';
3841
3842        info = get_charcommandinfo_byname(command);
3843        if( info == NULL || info->func == NULL || gmlvl < info->level )
3844        {
3845                if( gmlvl == 0 )
3846                        return false; // will just display as normal text
3847                else
3848                {
3849                        sprintf(output, msg_txt(153), command); // "%s is Unknown Command."
3850                        clif_displaymessage(fd, output);
3851                        return true;
3852                }
3853        }
3854
3855        if( log_config.gm && info->level >= log_config.gm )
3856                log_atcommand(sd, str);
3857
3858        if( info->func(fd, sd, command, args) != 0 )
3859        {
3860                sprintf(output, msg_txt(154), command); // "%s failed."
3861                clif_displaymessage(fd, output);
3862        }
3863       
3864        return true;
3865}
3866
3867/// Executes a char-command.
3868/// To be used by player-invoked code (restrictions will be applied)
3869bool is_charcommand(const int fd, struct map_session_data* sd, const char* message)
3870{
3871        int gmlvl = pc_isGM(sd);
3872
3873        nullpo_retr(false, sd);
3874
3875        if( !message || !*message )
3876                return false;
3877
3878        if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND )
3879                return true; // so that it won't display as normal message
3880
3881        if( battle_config.atc_gmonly != 0 && gmlvl == 0 )
3882                return false;
3883
3884        if( map[sd->bl.m].nocommand && gmlvl < map[sd->bl.m].nocommand )
3885        {
3886                clif_displaymessage(fd, msg_txt(143)); // "Commands are disabled on this map."
3887                return false;
3888        }
3889       
3890        // skip 10/11-langtype's codepage indicator, if detected
3891        if( message[0] == '|' && strlen(message) >= 4 && message[3] == charcommand_symbol )
3892                message += 3;
3893
3894        return is_charcommand_sub(fd,sd,message,gmlvl);
3895}
3896
3897
3898/*==========================================
3899 *
3900 *------------------------------------------*/
3901int charcommand_config_read(const char* cfgName)
3902{
3903        char line[1024], w1[1024], w2[1024];
3904        CharCommandInfo* p;
3905        FILE* fp;
3906
3907        if( (fp = fopen(cfgName, "r")) == NULL )
3908        {
3909                ShowError("CharCommand configuration file not found: %s\n", cfgName);
3910                return 1;
3911        }
3912
3913        while( fgets(line, sizeof(line), fp) )
3914        {
3915                if( line[0] == '/' && line[1] == '/' )
3916                        continue;
3917               
3918                if( sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2 )
3919                        continue;
3920               
3921                p = get_charcommandinfo_byname(w1);
3922                if( p != NULL )
3923                {
3924                        p->level = atoi(w2);
3925                        p->level = cap_value(p->level, 0, 100);
3926                }
3927                else
3928                if( strcmpi(w1, "import") == 0 )
3929                        charcommand_config_read(w2);
3930                else
3931                if( strcmpi(w1, "command_symbol") == 0 &&
3932                        w2[0] > 31   && // control characters
3933                        w2[0] != '/' && // symbol of standard ragnarok GM commands
3934                        w2[0] != '%' && // symbol of party chat speaking
3935                        w2[0] != '$' && // symbol of guild chat speaking
3936                        w2[0] != '@' )  // symbol of atcommand
3937                        charcommand_symbol = w2[0];
3938                else
3939                        ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
3940        }
3941        fclose(fp);
3942
3943        return 0;
3944}
Note: See TracBrowser for help on using the browser.