summaryrefslogblamecommitdiff
path: root/src/emap/atcommand.c
blob: e2b1eb87e5b4d7e2d885390e62d076acd9e0126c (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                         
                                            
 

                            



                   
                              
                        
                          



                          
                          
                     
                      
                    
                    

                      


                               

                           
                       

                                   
 

                                                                 

                                   
                                         
                                                   

                   
                    













                                                          


                                                                 

                                             


                                   
                                                                                                        
                                                   

                   
                    

               

                                                                 
 
                                                                              








                                                                              
                                                
 

                             



                                    

                              














                                                    
                                              
         









                                                                                                                
             
                                  
                 
                                       
                 

                               



                      
                                                                          
 





                                                              









                                                                                      

     
                

 




                        
                                                                             
     
                      
 








                                                                      











                                                                              

































                                                                                                                                                                  
 

           
                                             



            
                                              

 

              








                                                       







                                                               


                



                                     
                                         
                  
                    
                               
                                 
                     
                                  

                 

                                                       


                         


                       
 

                


















                                                      


                                            








                                              


































                                                                                                                               
                                                                                             

                                             
                                               
                                               
                           
                                                                            
                                                                       





























                                                                                                           























                                                                                                         
                                                                                                           







                                                                                                             
 
// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// Copyright (c) 2014 - 2015 Evol developers

#include "common/hercules.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common/cbasetypes.h"
#include "common/HPMi.h"
#include "common/memmgr.h"
#include "common/mmo.h"
#include "common/socket.h"
#include "common/strlib.h"
#include "common/timer.h"
#include "map/atcommand.h"
#include "map/clif.h"
#include "map/guild.h"
#include "map/map.h"
#include "map/pet.h"
#include "map/pc.h"
#include "map/skill.h"

#include "plugins/HPMHooking.h"

#include "emap/atcommand.h"
#include "emap/lang.h"
#include "emap/inter.h"
#include "emap/struct/sessionext.h"
#include "emap/data/session.h"

const char* eatcommand_msgsd_pre(struct map_session_data **sdPtr,
                                 int *msgPtr)
{
    const int msg_number = *msgPtr;
    struct map_session_data *sd = *sdPtr;
    if (!(msg_number >= 0 && msg_number < MAX_MSG))
    {
        hookStop();
        return "??";
    }
    if (*msgPtr == 1435)
    {
        hookStop();
        // service message, must be not translated
        return "You're now in the '#%s' channel for '%s'";
    }
    else if (*msgPtr == 1403)
    {
        hookStop();
        // service message, must be not translated
        return "You're now in the '#%s' channel for '-'";
    }
    hookStop();
    return lang_pctrans(atcommand->msg_table[0][msg_number], sd);
}

const char* eatcommand_msgfd_pre(int *fdPtr,
                                 int *msgPtr)
{
    const int msg_number = *msgPtr;
    const int fd = *fdPtr;
    struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL;
    if (!(msg_number >= 0 && msg_number < MAX_MSG))
    {
        hookStop();
        return "??";
    }
    hookStop();
    return lang_pctrans(atcommand->msg_table[0][msg_number], sd);
}

static bool eatcommand_jump_iterate(struct map_session_data *sd, bool forward)
{
    struct SessionExt *session_ext = session_get_bysd(sd);

    if (!session_ext)
        return false;

    struct map_session_data *pl_sd = map->id2sd(session_ext->jump_iterate_id);
    struct map_session_data *buff_sd = NULL;

    int fd = NULL != pl_sd ? pl_sd->fd : sd->fd;

    bool has_skipped = false;
    int start_fd = fd;
    int max_counter = sockt->fd_max;

    do
    {
        bool has_next = false;

        if (forward)
        {
            fd++;
            has_next = fd < sockt->fd_max;
        }
        else
        {
            fd--;
            has_next = fd > 0;
        }

        if (!has_next)
        {
            fd = (forward ? -1 : sockt->fd_max + 1);
        }
        else if (sockt->session_is_active(fd))
        {
            buff_sd = sockt->session[fd]->session_data;

            if (
                NULL != buff_sd &&
                (
                    (sd == buff_sd) ||
                    (map->list[buff_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) ||
                    (sd->bl.m == buff_sd->bl.m && sd->bl.x == buff_sd->bl.x && sd->bl.y == buff_sd->bl.y)
                )
            )
            {
                if (sd != buff_sd)
                {
                    has_skipped = true;
                }

                buff_sd = NULL;
            }
        }

        --max_counter;
    } while ((NULL == buff_sd) && (fd != start_fd) && (max_counter >= 0));

    if (NULL == buff_sd && !has_skipped)
    {
        session_ext->jump_iterate_id = 0;
        clif->message(sd->fd, "You are alone at map server!");
    }
    else if (NULL != buff_sd)
    {
        char message[80];

        pc->setpos(sd, buff_sd->mapindex, buff_sd->bl.x, buff_sd->bl.y, CLR_TELEPORT);

        sprintf (message, "Jump to %s", buff_sd->status.name);

        clif->message(sd->fd, message);

        session_ext->jump_iterate_id = buff_sd->bl.id;
    }

    return true;
}

ACMD2(setSkill)
{
    int skill_id = 0;
    int skill_level = 0;

    if (!*message || sscanf(message, "%5d %2d", &skill_id, &skill_level) < 2)
    {
        char buf[100];

        if (!*message ||
            sscanf(message, "%99s %2d", &buf[0], &skill_level) != 2 ||
            !script->get_constant(buf, &skill_id))
        {
            const char* text = info->help;
            if (text)
                clif->messageln (fd, text);
            return false;
        }
    }
    if (!skill->get_index(skill_id))
    {
        clif->message(fd, msg_fd(fd,198)); // This skill number doesn't exist.
        return false;
    }

    pc->skill(sd, skill_id, skill_level, 0);
    clif->message(fd, msg_fd(fd,70)); // You have learned the skill.

    return true;
}

ACMD2(slide)
{
    int x = 0;
    int y = 0;
    if (!*message || sscanf(message, "%4d %4d", &x, &y) < 2)
    {
        const char* text = info->help;
        if (text)
            clif->messageln (fd, text);
        return false;
    }

    if (!sd)
    {
        clif->message(fd, msg_fd(fd, 3)); // Character not found.
        return false;
    }

    const int m = sd->bl.m;
    if (x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys)
    {
        ShowError("slide: attempt to place player %s (%d:%d) on invalid coordinates (%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, x, y);
        return false;
    }
    if (map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle->bc->gm_ignore_warpable_area)
    {
        clif->message(fd, msg_fd(fd, 2));
        return false;
    }
    clif->slide(&sd->bl, x, y);
    unit->movepos(&sd->bl, x, y, 1, 0);
    return true;
}

ACMD3(hugo)
{
    return eatcommand_jump_iterate(sd, true);
}

ACMD3(linus)
{
    return eatcommand_jump_iterate(sd, false);
}

ACMD1(mapExit)
{
    int code = 1;
    if (!*message || sscanf(message, "%5d", &code) < 1)
        code = 1;

    map->retval = code;
    map->do_shutdown();
    return true;
}

ACMD0(log)
{
    return true;
}

ACMD4(tee)
{
    clif->disp_overhead(&sd->bl, message, AREA_CHAT_WOC, NULL);
    return true;
}

// 100 - terminate all servers
// 101 - restart all servers
// 102 - restart char and map servers
// 103 - restart map server
// 104 - git pull and restart all servers
// 105 - build all
// 106 - rebuild all
// 107 - git pull and build all
// 108 - git pull and rebuild all
// 109 - build plugin
// 110 - git pull and build plugin
ACMD1(serverExit)
{
    int code = 0;
    if (!*message || sscanf(message, "%5d", &code) < 1)
        return false;

    send_char_exit(code);

    map->retval = code;
    map->do_shutdown();

    return true;
}

ACMD1(getName)
{
    int id = 0;
    if (!*message || sscanf(message, "%10d", &id) < 1)
        return false;

    const struct block_list* bl = map->id2bl(id);
    if (bl == NULL)
    {
        clif->message(fd, "Unit not found");
    }
    else
    {
        clif->message(fd, status->get_name(bl));
    }

    return true;
}

// TMW2
/*==========================================
 * @refresh (like @jumpto <<yourself>>)
 *------------------------------------------*/
ACMD0(refresh)
{
	clif->refresh(sd);
	return true;
}

/*==========================================
 * @item command (usage: @item <name/id_of_item> <quantity>) (modified by [Yor] for pet_egg)
 * @itembound command (usage: @itembound <name/id_of_item> <quantity> <bound type>) (revised by [Mhalicot])
 *------------------------------------------*/
ACMD0(tmw2item)
{
	char item_name[100];
	int number = 0, item_id, flag = 0, bound = 0;
	struct item item_tmp;
	struct item_data *item_data;
	int get_count, i;

	memset(item_name, '\0', sizeof(item_name));

    if (!*message
	       || ( sscanf(message, "\"%99[^\"]\" %12d", item_name, &number) < 1
		 && sscanf(message, "%99s %12d", item_name, &number) < 1
	)) {
		clif->message(fd, msg_fd(fd,983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>).
		return false;
	}

	if (number <= 0)
		number = 1;

	if ((item_data = itemdb->search_name(item_name)) == NULL &&
	    (item_data = itemdb->exists(atoi(item_name))) == NULL)
	{
		clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
		return false;
	}

	item_id = item_data->nameid;
	get_count = number;

    // TMW2: Check for restrictions
    // Strange Coins ; <BronzeGift ~ SupremeGift> ; Legendary Weapons ; Fruits ; DeathPenalty
	if( item_id == 828 ||
        (item_id >= 589 && item_id <= 593) ||
        (item_id >= 3600 && item_id <= 3610) ||
        (item_id >= 8000 && item_id <= 8006) ||
        item_id == 7420 ) {
		clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name
		clif->message(fd, msg_fd(fd,1481)); // TMW2 Restriction
		return false;
	}

	//Check if it's stackable.
	if (!itemdb->isstackable2(item_data)) {
		if( bound && (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
			clif->message(fd, msg_fd(fd,498)); // Cannot create bounded pet eggs or pet armors.
			return false;
		}
		get_count = 1;
	}

	for (i = 0; i < number; i += get_count) {
		// if not pet egg
		if (!pet->create_egg(sd, item_id)) {
			memset(&item_tmp, 0, sizeof(item_tmp));
			item_tmp.nameid = item_id;
			item_tmp.identify = 1;
			item_tmp.bound = (unsigned char)bound;

			if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
				clif->additem(sd, 0, 0, flag);
		}
	}

	if (flag == 0)
		clif->message(fd, msg_fd(fd,18)); // Item created.
	return true;
}

/*==========================================
 * @changegm by durf (changed by Lupus)
 * Changes Master of your Guild to a specified guild member
 *------------------------------------------*/
ACMD0(tmw2changegm)
{
	struct guild *g;
	struct map_session_data *pl_sd;

	if (sd->status.guild_id == 0 || (g = sd->guild) == NULL) {
		clif->message(fd, msg_fd(fd,1181)); // You need to be a Guild Master to use this command.
		return false;
	}

	if (map->list[sd->bl.m].flag.guildlock || map->list[sd->bl.m].flag.gvg_castle) {
		clif->message(fd, msg_fd(fd,1182)); // You cannot change guild leaders in this map.
		return false;
	}

	if (!message[0]) {
		clif->message(fd, msg_fd(fd,1183)); // Usage: @changegm <guild_member_name>
		return false;
	}

	if ((pl_sd=map->nick2sd(message, true)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
		clif->message(fd, msg_fd(fd,1184)); // Target character must be online and be a guild member.
		return false;
	}

	guild->gm_change(sd->status.guild_id, pl_sd->status.char_id);
	return true;
}