Jump to content

Like it~*

Members
  • Content Count

    175
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by Like it~*


  1. Read the rocred.ini comments on how to set up.

     

    Hi, thanks a lot Ai4rei, I managed to login to my server normally. But, I do not understand one thing, why do we need rocred.exe, if we have to put the password twice? Does rocred.exe only serve to save the MAC of the player? I'm confused / gt

     

    Did I do some things wrong? I just copied the rocred.ini and rocred.exe files to my RO folder.


  2.  

     

    As you might imagine, Smoke is always involved in big, cool projects. I would like to congratulate you and thank you on behalf of the whole community.
     
    However, I do not see so many great utilities in this ... I do not know if it is due to the difficulty of understanding the language, or because the text has not been clarified, but I have not really seen it. (Please do not get me wrong, I'm just curious)
     
    Is this system official?
    Is there any utility besides not having to create custom cards to give players bonuses?
     
    I'm sorry I looked ignorant, but I'm just curious.

     

    i guess it is a different way of displaying flavor text and equipment bonuses

     

     

     

     

    As you might imagine, Smoke is always involved in big, cool projects. I would like to congratulate you and thank you on behalf of the whole community.
     
    However, I do not see so many great utilities in this ... I do not know if it is due to the difficulty of understanding the language, or because the text has not been clarified, but I have not really seen it. (Please do not get me wrong, I'm just curious)
     
    Is this system official?
    Is there any utility besides not having to create custom cards to give players bonuses?
     
    I'm sorry I looked ignorant, but I'm just curious.

     

    This is an official system yes.

    This doesn't have anything to do with creating custom cards.

     

    This system makes it possible to do things such as -

    1. creating unique equipments in the game with unique stats.
    2. creating dynamic equipments with options. (possibly with an equipment levelling system)
    3. if one is lazy, not having to put a description in the item and providing it with desired stats through an npc?

     

    The use of it ultimately depends on one's creative capabilities.

     

    Thank you very much for clarifying my doubts. What I meant by custom cards is that bonuses could be given by creating custom cards too, you know?


  3. As you might imagine, Smoke is always involved in big, cool projects. I would like to congratulate you and thank you on behalf of the whole community.

     

    However, I do not see so many great utilities in this ... I do not know if it is due to the difficulty of understanding the language, or because the text has not been clarified, but I have not really seen it. (Please do not get me wrong, I'm just curious)

     

    Is this system official?

    Is there any utility besides not having to create custom cards to give players bonuses?

     

    I'm sorry I looked ignorant, but I'm just curious.


  4. What do I need to change so that the command does not convert the item's status, bonus, etc, only its visual part?

     

     

    topic plugin: http://herc.ws/board/topic/4383-costume-item-plugins/

     

     

    @edit

    I found a topic with the same request, however the resolution is with a patch and I like it as a plugin, could anyone convert it or edit the original plugin?

    http://herc.ws/board/topic/11415-costumeitem-adds-stats/

     

    Patch by Annieruru

     

     src/map/status.c | 3 +++ 1 file changed, 3 insertions(+)diff --git a/src/map/status.c b/src/map/status.cindex 699e734..7223a04 100644--- a/src/map/status.c+++ b/src/map/status.c@@ -2317,6 +2317,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { 			continue; 		if(!sd->inventory_data[index]) 			continue;+		if ( i >= EQI_COSTUME_TOP || i <= EQI_SHADOW_ACC_L )+			if ( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) == 999998 )+				continue;  		for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) { 			if( map->list[sd->bl.m].zone->disabled_items[k] == sd->inventory_data[index]->nameid ) {

     

    @edit2

    I apologize to everyone, because I only realized that the plugin already has this functionality. The problem is in the main post of the official author, as he updated the plugin but not the description of the main topic post.

     

     

     

     

    thumb-f03b8f9102faf60e646f2e87ed116e71-s

    File Name: Costume Item Plugins

    File SubmitterMhalicot

    File Submitted: 10 Feb 2014

    File CategoryPlugins

     

    HPM @costumeitem complete package.

     

    Compatible with Windows System Only

     

    if you are using Linux, ignore other files and use only afk.c

    some Linux Systwem got many bugs with files what are all ready compiled under VS2010 .

    (Windows Compiled wont work on *nix)

    Instruction.

     

    1. Download and extract files using 7z or any application that can extract it.

    2. extract it in your server directory ex: C:/RO Server/Hercules/

    2.1. edit conf/plugins.conf and add costumeitem

    3. Your done. you can now try your plugins

     

    if you are using VS2010/VS2009/vs2013 or whatsoever and you are failing to compile because of platform issue.

    this is what you need to do.

     

    In Recompiling:

    If you are using other MSVS/C

    Quote

    >>>>>

    >right click costumeitem>Configuration Properties>General>

    search for Platform Toolset, change to VS2009(v90) / VS2010(v100) / VS2012(v110) / VS2013(v120)

    then try to recompile again..

    Note: Recompile if you modify the script.

    the command is @costumeitem

    If you want to edit look for src/plugins/costumeitem.c

    you can also add alias in atcommand.conf

    If you have any questions feel free to drop a comment.

     

    NOTE: You done have to edit your src to add this custom features(Less conflict when you want to update your server). Thanks to Mr. Ind for making this Plugins possible, This Plugins will convert your items to costume(item stats/combos/bonuses will also copied)

     

    for more info on how to to use HPM visit Here

    (Tested on Hercules rev. 146**)

    Script Release: Costume System

     

    Click here to download this file

     

     

     

    Update

    • 2.0 Converted Costume Items will now removed normal stats and Bonuses. [Mhalicot]
    • 3.0 Item Combos will now Ignore Converted Costume Items. [Mhalicot]
    • 3.1 Fixed HP/SP becomes 1/1 [Mhalicot]
    • 3.2 Fixed Sinx Can't Equipt dagger/sword on both arms(L/R), Special Thanks to Haru for Help [Mhalicot]
    • 3.3 Fixed Error when compiling.

     

     

     

     

    Please, ask some moderators to delete or close the topic! Thank you!

     

     Solved!  :)


  5. Yes i understand all that. I want to make it so the NPC takes a record of their IP and block usage of that npc afterwards.

     

    I did some searching and found a guild pack script to use in what I'm after. From this thread: https://rathena.org/board/topic/94294-guild-pack-npc-giver-help-please/

     

    1. First script needs label to call in callsub:

     

    S_Check_IP:
        return query_sql("SELECT 1 FROM `guildpack` join login on login.`last_ip` = `guildpack`.`last_ip` where login.account_id = "+ getcharid(CHAR_ID_ACCOUNT), .@tmp);
    

     

    2. Then define IP:

     

    .@myip$ = getcharip();

     

    3. Return true through callsub if IP exists in table:

     

        if (callsub(S_Check_IP))
        {
            mes .@name$;
            mes("^616D7EIt seems I have already recorded your IP Address: ^ff0000" + .@myip$ + "^000000.");
            close;
        }
    

     

    4. If does not exist, enter new entry to previously created table:

     

    query_sql("INSERT INTO `guildpack` VALUES (NULL," + getcharid(CHAR_ID_ACCOUNT) + ",'" + escape_sql(strcharinfo(PC_NAME)) + "','" + .@myip$ + "')");

     

    All in all it looks something like this: https://pastebin.com/Lk8MHMBg

     

    This can be used for get_unique_id() too if you have gepard shield.

     

    My intention was to use this in a Lottery script, so people could only purchase one ticket per week.

    After each lottery draw, the table would be truncated so everybody can buy tickets again.

     

    To put in any script, would I just need to change the storage table, 'guildpack'? Give me an example, please.


  6. Hello guys. The theme I bring up here is simple and straightforward, but maybe even a bit controversial. The intention is to address the issues that are opened in the official repository of the emulator. I understand that it is a lot of work for developers and it is very difficult to reconcile with personal life. However, what I do not understand is why there is no order to resolve issues in the repositories. I know that big bugs should have priorities, but in some cases they are not bugs, they are fixed before problems open on previous dates and I do not understand why? Is not the correct order execution? My idea here is not to criticize or even be controversial, though I would like to discuss this so that we will have an even better emulator in the future.


  7. you can add donpcevent and set it up on your own liking.

     

     

     

    you can add donpcevent and set it up on your own liking.

     

    Yup, basically this. You can use an arrangement of donpcevent() commands to activate events for your set times.

     

    Example:

     

     
    -     script     event 1     FAKE_NPC,{
     
    OnAtCommand:
    OnEventOne:
    announce "Event 1 started.", bc_all;
    initnpctimer;
    end;
     
    OnTimer10000:
    announce "Event 1 ended." bc_all;
    end;
     
    OnTimer15000:
    donpcevent("event 2::OnEventTwo");
    stopnpctimer;
    end;
     
    OnInit:
    bindatcmd("event1","event 1::OnAtCommand");
    end;
     
    }
     
    -     script     event 2     FAKE_NPC,{
     
    OnEventTwo:
    announce "Event 2 started.", bc_all;
    initnpctimer;
    end;
     
    OnTimer10000:
    announce "Event 2 ended.", bc_all;
    end;
     
    OnTimer15000:
    donpcevent("event 1::OnEventTwo");
    stopnpctimer;
    end;
     
    }
    

     

    You can start the loop by typing @event1, then it would loop the announcements every 10/15 seconds.

     

    Hello, gentlemen. Thank you very much for replying. I see that is a possibility. However, it is not yet fully effective, since events have varying times of duration. That is, it may be that one event ends sooner than expected and the other does not start because the interval between them has not yet been reached. So, is there any other way to be able to accomplish this in the best way?


  8. Hello, I would like to know if it is possible to do this since there are many npcs in different files. The events are all already assembled, but each one in its separate file. I would like that as soon as one event is over, another is started, then another, another, and so on ... So after the last event is over, start the event count again from 1.
    Example:
    Started: event 1
    Finished: event 1
    Started: event 2
    Finished: event 2
    Started: event 3
    Finished: event 3
    ...
    ...
    ...
    Started: event 20
    Finished: event 20
    Started: event 1
    Finished: event 1
    Started: event 2
    Finished: event 2

     


  9. For noitem.c, look for this line:

    HPExport void plugin_init (void) {
    	addHookPre( "map->flags_init", map_flags_init_pre );
    	addHookPre( "npc->parse_unknown_mapflag", npc_parse_unknown_mapflag_pre );
    	addHookPost( "pc->isequip", pc_isequip_post );
    	addHookPost( "pc->isUseitem", pc_isUseitem_post );
    	addHookPost( "pc->checkitem", pc_checkitem_post );
    }
    

    and replace it with:

    HPExport void plugin_init (void) {
    	addHookPre( map, flags_init, map_flags_init_pre );
    	addHookPre( npc, parse_unknown_mapflag, npc_parse_unknown_mapflag_pre );
    	addHookPost( pc, isequip, pc_isequip_post );
    	addHookPost( pc, isUseitem, pc_isUseitem_post );
    	addHookPost( pc, checkitem, pc_checkitem_post );
    }
    

     

     

    For maintenance.c, look for this line:

    	addHookPre( "pc->authok", pc_authok_pre );
    	addHookPre( "clif->pLoadEndAck", clif_parse_LoadEndAck_pre );
    

    replace it with:

    	addHookPre( pc, authok, pc_authok_pre );
    	addHookPre( clif, pLoadEndAck, clif_parse_LoadEndAck_pre );
    

    ;)

     

    Thank you very much.

    But, there is still an error.

     

    Severity	Code	Description	Project	File	Line	Suppression State
    Error	C2065	'HPMHOOK_pre_npc_parse_unknown_mapflag': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2143	syntax error: missing ')' before 'constant'	noitem	Hercules\src\plugins\noitem.c	192	
    Warning	C4028	formal parameter 3 different from declaration	noitem	Hercules\src\plugins\noitem.c	193
    Warning	C4028	formal parameter 3 different from declaration	noitem	Hercules\src\plugins\noitem.c	194
    

  10. remove this 

    #define safestrncpy(dst,src,n)       (strlib->safestrncpy((dst),(src),(n)))
    

    from 

    partyscript.c

     

     

     

    remove this 

    #define safestrncpy(dst,src,n)       (strlib->safestrncpy((dst),(src),(n)))
    

    from 

    partyscript.c

     

    Thanks you very much.

    Amazingly, now there are only two plugins

     

    Severity	Code	Description	Project	File	Line	Suppression State
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	noitem	Hercules\src\plugins\noitem.c	191	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	191	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	191	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	191	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	192	
    Warning	C4003	not enough actual parameters for macro 'addHookPost'	noitem	Hercules\src\plugins\noitem.c	193	
    Error	C2065	'HPMHOOK_post_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	193	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	193	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	193	
    Warning	C4003	not enough actual parameters for macro 'addHookPost'	noitem	Hercules\src\plugins\noitem.c	194	
    Error	C2065	'HPMHOOK_post_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	194	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	194	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	194	
    Warning	C4003	not enough actual parameters for macro 'addHookPost'	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C2065	'HPMHOOK_post_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	195	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	maintenance	Hercules\src\plugins\maintenance.c	551	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	maintenance	Hercules\src\plugins\maintenance.c	551	
    Error	C2143	syntax error: missing ')' before 'string'	maintenance	Hercules\src\plugins\maintenance.c	551	
    Error	C2059	syntax error: ')'	maintenance	Hercules\src\plugins\maintenance.c	551	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	maintenance	Hercules\src\plugins\maintenance.c	552	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	maintenance	Hercules\src\plugins\maintenance.c	552	
    Error	C2143	syntax error: missing ')' before 'string'	maintenance	Hercules\src\plugins\maintenance.c	552	
    Error	C2059	syntax error: ')'	maintenance	Hercules\src\plugins\maintenance.c	552
    

  11. Warnings.

    Note: Tested with the latest versions of the Hercules plugin and emulator. Compiled with Microsoft Visual Studio 2015

    Severity	Code	Description	Project	File	Line	Suppression State
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	1071	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2049	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2050	
    Warning	C4018	'>=': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2523	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2581	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2587	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2717	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	3722	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	3724	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	3862

  12.  

    For example autopot.c

     

     

    Replace top of file by

     

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "common/hercules.h" /* Should always be the first Hercules file included! (if you don't make it first, you won't be able to use interfaces) */
    
    #include "common/HPMi.h"
    #include "common/timer.h"
    #include "map/script.h"
    #include "map/pc.h"
    #include "map/map.h"
    #include "map/unit.h"
    #include "map/atcommand.h"
    #include "map/itemdb.h"
    
    #include "plugins/HPMHooking.h"
    #include "common/HPMDataCheck.h"/* should always be the last file included! (if you don't make it last, it'll intentionally break compile time) */
    
    #define OPTION_AUTOPOTS 0x40000000
    

     

     

    Then,

     

    remove 

    	clif = GET_SYMBOL("clif");
        script = GET_SYMBOL("script");
    	pc = GET_SYMBOL("pc");
    	atcommand = GET_SYMBOL("atcommand");
    	map = GET_SYMBOL("map");
    	unit = GET_SYMBOL("unit");
    	timer = GET_SYMBOL("timer");
    	itemdb = GET_SYMBOL("itemdb");
    

    from 

     

    HPExport void plugin_init (void) {
     

     

    Recompile..

     

    samme principle apply to others...

     

     

     

    UPD : Maintenance.c

     

    add

    #include "plugins/HPMHooking.h" 
    

    before

    #include "common/HPMDataCheck.h"
    

     

    Wow. Thank you very much. I solved most of the problems. But there are still some. Look:

     

     

     

    Severity	Code	Description	Project	File	Line	Suppression State
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	1071	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2049	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2050	
    Warning	C4018	'>=': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2523	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2581	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2587	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	2717	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	3722	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	3724	
    Warning	C4018	'<': signed/unsigned mismatch	hBG	Hercules\src\plugins\hBG.c	3862	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	maintenance	Hercules\src\plugins\maintenance.c	551	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	noitem	Hercules\src\plugins\noitem.c	191	
    Warning	C4018	'<=': signed/unsigned mismatch	market	Hercules\src\plugins\market.c	259	
    Warning	C4018	'<=': signed/unsigned mismatch	market	Hercules\src\plugins\market.c	290	
    Warning	C4018	'<=': signed/unsigned mismatch	market	Hercules\src\plugins\market.c	309	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	191	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	191	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	maintenance	Hercules\src\plugins\maintenance.c	551	
    Error	C2143	syntax error: missing ')' before 'string'	maintenance	Hercules\src\plugins\maintenance.c	551	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	191	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2059	syntax error: ')'	maintenance	Hercules\src\plugins\maintenance.c	551	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	192	
    Warning	C4003	not enough actual parameters for macro 'addHookPre'	maintenance	Hercules\src\plugins\maintenance.c	552	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2065	'HPMHOOK_pre_': undeclared identifier	maintenance	Hercules\src\plugins\maintenance.c	552	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	192	
    Error	C2143	syntax error: missing ')' before 'string'	maintenance	Hercules\src\plugins\maintenance.c	552	
    Error	C2059	syntax error: ')'	maintenance	Hercules\src\plugins\maintenance.c	552	
    Warning	C4003	not enough actual parameters for macro 'addHookPost'	noitem	Hercules\src\plugins\noitem.c	193	
    Error	C2065	'HPMHOOK_post_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	193	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	193	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	193	
    Warning	C4003	not enough actual parameters for macro 'addHookPost'	noitem	Hercules\src\plugins\noitem.c	194	
    Error	C2065	'HPMHOOK_post_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	194	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	194	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	194	
    Warning	C4003	not enough actual parameters for macro 'addHookPost'	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C2065	'HPMHOOK_post_': undeclared identifier	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C2143	syntax error: missing ')' before 'string'	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C2059	syntax error: ')'	noitem	Hercules\src\plugins\noitem.c	195	
    Error	C1083	Cannot open include file: 'common/malloc.h': No such file or directory	partyscript	Hercules\src\plugins\partyscript.c	15	
    Warning	C4715	'buildin_storageadditem': not all control paths return a value	storageadditem	hercules\src\plugins\storageadditem.c	74	
    Warning	C4267	'initializing': conversion from 'size_t' to 'unsigned short', possible loss of data	vending_extended	Hercules\src\plugins\vending_extended.c	86	 

     

     

     

    maintenance.c

     

     

    //===== Hercules Plugin ======================================
    //= @Maintenance mod
    //===== By: ==================================================
    //= AnnieRuru
    //===== Current Version: =====================================
    //= 1.4
    //===== Compatible With: ===================================== 
    //= Hercules 2015-12-08
    //===== Description: =========================================
    //= Turn the server into maintenance mode.
    //= -> blocked players from login the game for a set of duration
    //= a GM will announce the maintenance, and players will be kicked out after a while for maintenance. 
    //= Player below {Group ID can login} will not able to login for the duration
    //= but GM99 can always login without restriction
    //===== Topic ================================================
    //= http://hercules.ws/board/topic/7127-
    //===== Additional Comments: =================================  
    //= -- AtCommands --
    //= @maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>
    //= @maintenanceoff
    //=
    //= -- Script Commands --
    //= maintenance <Group ID can stay 1~99>, <duration to kick in minute>, <maintenance duration in minute> { , <reason> };
    //=   reason field is optional, default to '*Regular server maintenance*'
    //= maintenanceoff { <reason> };
    //=   reason field is optional, default to '*maintenanceoff*'
    //= maintenancecheck( <type> );
    //=   default:
    //=	    return 0 if server is normal
    //=	    return 1 if server is going to have maintenance
    //=	    return 2 if server is having maintenance
    //=   type 1:
    //=	    return the Group ID that has been denied to login
    //=   type 2:
    //=     return the time stamp of last/current starting time for the maintenance
    //=   type 3:
    //=     return the time stamp of last/current ending time for the maintenance
    //=   type 4:
    //=     return the ID of last used maintenance_countid ( for debugging only )
    //=   type 5:
    //=     return the ID of last used maintenance_timerid ( for debugging only )
    //============================================================
    
    /*	Remember to build a Sql table !
    create table maintenance (
    	id int(11) primary key auto_increment,
    	account_id int(11),
    	name varchar(23),
    	reason varchar(99),
    	minlv2connect tinyint(4),
    	order_time datetime,
    	start_time datetime,
    	end_time datetime
    ) engine = innodb;
    */
    
    //	change the announcement color
    int maintenance_color = 0xFFFF00;
    //	If you still want to personalize each announcement to different color, just Ctrl+F 'maintenance_color' below
    
    //	==========================================================
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #include "common/hercules.h"
    #include "map/pc.h"
    #include "map/map.h"
    #include "map/intif.h"
    #include "login/login.h"
    #include "common/timer.h"
    #include "common/strlib.h"
    #include "common/memmgr.h"
    #include "common/nullpo.h"
    #include "common/sql.h"
    #include "plugins/HPMHooking.h"
    #include "common/HPMDataCheck.h"
    
    HPExport struct hplugin_info pinfo = {
    	"maintenance",	// Plugin name
    	SERVER_TYPE_MAP,// Which server types this plugin works with?
    	"1.4",			// Plugin version
    	HPM_VERSION,	// HPM Version (don't change, macro is automatically updated)
    };
    
    int maintenance_group = 1;
    int maintenance_starttime = 1;
    int maintenance_endtime = 1;
    int maintenance_countid = INVALID_TIMER;
    int maintenance_timerid = INVALID_TIMER;
    char maintenance_timeformat[24];
    
    int maintenance_progress( int tid, int64 tick, int id, intptr data ) {
    	char output[CHAT_SIZE_MAX];
    	timer->delete( maintenance_timerid, maintenance_progress );
    	maintenance_timerid = INVALID_TIMER;
    	safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode has ended. Players are able to login now." );
    	intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    	maintenance_group = 0;
    	maintenance_starttime = (int)time(NULL);
    	maintenance_endtime = (int)time(NULL);
    	ShowStatus( CL_YELLOW "Maintenance has ended." CL_RESET "\n" );
    	return false;
    }
    
    int maintenance_countdown( int tid, int64 tick, int id, intptr data ) {
    	char output[CHAT_SIZE_MAX];
    	int countdown = maintenance_starttime - (int)time(NULL);
    	if ( countdown > 90 ) {
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance will start in %d minutes", countdown /60 );
    		intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    		timer->delete( maintenance_countid, maintenance_countdown );
    		if ( ( countdown % 60 ) > 0 ) // fine tune the timer
    			maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 60 ) * 1000 ), maintenance_countdown, 0, 0 );
    		else
    			maintenance_countid = timer->add( timer->gettick() + 60000, maintenance_countdown, 0, 0 );
    	}
    	else if ( countdown > 15 ) {
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance will start in %d seconds", countdown );
    		intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    		timer->delete( maintenance_countid, maintenance_countdown );
    		if ( ( countdown % 10 ) > 0 ) // fine tune the timer
    			maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 10 ) * 1000 ), maintenance_countdown, 0, 0 );
    		else
    			maintenance_countid = timer->add( timer->gettick() + 10000, maintenance_countdown, 0, 0 );
    	}
    	else if ( countdown > 0 ) {
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance will start in %d seconds", countdown );
    		intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    		timer->delete( maintenance_countid, maintenance_countdown );
    		maintenance_countid = timer->add( timer->gettick() + 1000, maintenance_countdown, 0, 0 );
    	}
    	else {
    		struct s_mapiterator* iter = mapit->alloc( MAPIT_NORMAL, BL_PC );
    		TBL_PC *sd;
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance starts now. Every player will be kick out." );
    		intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    		for ( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
    			if ( sd->group_id < maintenance_group )
    				clif->authfail_fd( sd->fd, 1 );
    		mapit->free(iter);
    		timer->delete( maintenance_countid, maintenance_countdown );
    		maintenance_countid = INVALID_TIMER;
    		maintenance_timerid = timer->add( timer->gettick() + ( ( maintenance_endtime - maintenance_starttime )*1000 ), maintenance_progress, 0, 0 );
    		ShowStatus( CL_YELLOW "Maintenance has started." CL_RESET "\n" );
    	}
    	return false;
    }
    
    HPExport void server_online (void) {
    	if ( SQL->Query( map->mysql_handle, "select minlv2connect, unix_timestamp( start_time ), unix_timestamp( end_time ), weekday( end_time ), hour( end_time ), minute( end_time ) from maintenance where id = ( select max(id) from maintenance )" ) == SQL_ERROR )
    		Sql_ShowDebug( map->mysql_handle );
    	else if ( SQL->NextRow( map->mysql_handle ) == SQL_SUCCESS ) {
    		char *data;
    		short weekday = 0, hour = 0, minute = 0;
    		char* weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
    		char am_pm[3], min_display[3];
    		if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
    			maintenance_group = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
    			maintenance_starttime = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
    			maintenance_endtime = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 3, &data, NULL ) == SQL_SUCCESS )
    			weekday = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 4, &data, NULL ) == SQL_SUCCESS )
    			hour = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 5, &data, NULL ) == SQL_SUCCESS )
    			minute = atoi(data);
    		if ( hour == 0 ) {
    			hour = 12;
    			safesnprintf( am_pm, 3, "AM" );
    		}
    		else if ( hour < 12 )
    			safesnprintf( am_pm, 3, "AM" );
    		else {
    			hour = hour - 12;
    			safesnprintf( am_pm, 3, "PM" );
    		}
    		if ( minute < 10 )
    			safesnprintf( min_display, 3, "0%d", minute );
    		else
    			safesnprintf( min_display, 3, "%d", minute );
    		safesnprintf( maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
    	}
    	if ( maintenance_starttime > (int)time(NULL) ) {
    		int countdown = maintenance_starttime - (int)time(NULL);
    		if ( countdown > 60 )
    			maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 60 )*1000 ), maintenance_countdown, 0, 0 );
    		else
    			maintenance_countid = timer->add( timer->gettick() + 1000, maintenance_countdown, 0, 0 );
    		ShowStatus( CL_YELLOW "Maintenance will start in %d min %d sec." CL_RESET "\n", countdown /60, countdown %60 );
    	}
    	else if ( maintenance_endtime > (int)time(NULL) ) {
    		int countdown = maintenance_endtime - (int)time(NULL);
    		maintenance_timerid = timer->add( timer->gettick() + ( countdown *1000 ), maintenance_progress, 0, 0 );
    		ShowStatus( CL_YELLOW "Maintenance will end in %d min %d sec on %s." CL_RESET "\n", countdown/60, countdown %60, maintenance_timeformat );
    	}
    }
    
    bool pc_authok_pre( struct map_session_data *sd, int *login_id2, time_t *expiration_time, int *group_id, struct mmo_charstatus *st, bool *changing_mapservers ) {
    	nullpo_retr( false, sd );
    	if ( (int)time(NULL) > maintenance_starttime && maintenance_endtime > (int)time(NULL) && *group_id < maintenance_group ) {
    		clif->authfail_fd( sd->fd, 1 );
    		hookStop();
    		return false;
    	}
    	return true;
    }
    
    void clif_parse_LoadEndAck_pre( int *fd, struct map_session_data *sd ) {
    	nullpo_retv(sd);
    	if ( sd->state.connect_new ) {
    		if ( maintenance_starttime > (int)time(NULL) ) {
    			char output[CHAT_SIZE_MAX];
    			safesnprintf( output, CHAT_SIZE_MAX, "Maintenance starts in %d min %d sec, last %d minutes. Server up by %s", ( maintenance_starttime - (int)time(NULL) ) /60, ( maintenance_starttime - (int)time(NULL) ) %60, ( maintenance_endtime - maintenance_starttime ) /60, maintenance_timeformat );
    			clif->message( sd->fd, output );
    		}
    		else if ( maintenance_endtime > (int)time(NULL) ) {
    			char output[CHAT_SIZE_MAX];
    			safesnprintf( output, CHAT_SIZE_MAX, "Server is currently in maintenance mode, will end in %d min %d sec on %s", ( maintenance_endtime - (int)time(NULL) ) /60, ( maintenance_endtime - (int)time(NULL) ) %60, maintenance_timeformat );
    			clif->message( sd->fd, output );
    		}
    	}
    	return;
    }
    
    ACMD(maintenance) {
    	int group_id = 0, kick_duration = 0, maintenance_duration = 0;
    	char reason[99], esc_reason[198], esc_name[46], min_display[3], output[CHAT_SIZE_MAX];
    	short weekday = 0, hour = 0, minute = 0;
    	if ( maintenance_starttime > (int)time(NULL) ) {
    		int countdown = maintenance_starttime - (int)time(NULL);
    		clif->message( sd->fd, "Type '@maintenanceoff' to turn off maintenance mode." );
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode will start in %d min %d sec.", countdown /60, countdown %60 );
    		clif->message( sd->fd, output );
    		return true;
    	}
    	if ( maintenance_endtime > (int)time(NULL) ) {
    		int countdown = maintenance_endtime - (int)time(NULL);
    		clif->message( sd->fd, "Type '@maintenanceoff' to turn off maintenance mode." );
    		safesnprintf( output, CHAT_SIZE_MAX, "Server is currently in maintenance mode, will end in %d min %d sec on %s", countdown /60, countdown %60, maintenance_timeformat );
    		clif->message( sd->fd, output );
    		return true;
    	}
    	if ( !message || !*message ) {
    		clif->message( sd->fd, "@maintenance Syntax :" );
    		clif->message( sd->fd, "@maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>" );
    		return false;
    	}
    //	WTF ! sscanf can't be used ??
    //	if ( sscanf( message, "%d %d %d %99[^\n]", &group_id, &kick_duration, &maintenance_duration, &reason ) < 4 ) {
    //		clif->message( sd->fd, "@maintenance Syntax :" );
    //		clif->message( sd->fd, "@maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>" );
    //		return false;
    //	}
    //	now has to do the stupid string calculation 
    	{
    		int i = 0, j = 0, k = 0, l = strlen( message );
    		char *temp = (char*)aMalloc( strlen( message ) +1 );
    		while ( i <= l && k < 3 ) {
    			if ( message[i] != ' ' && message[i] != '\0' ) {
    				temp[j++] = message[i];
    			}
    			else if ( message[i-1] != ' ' ) {
    				temp[j] = '\0';
    				if ( k == 0 )
    					group_id = atoi( temp );
    				else if ( k == 1 )
    					kick_duration = atoi( temp );
    				else if ( k == 2 )
    					maintenance_duration = atoi( temp );
    				k++;
    				j = 0;
    			}
    			i++;
    		}
    		safestrncpy( reason, &message[i], 99 );
    		aFree( temp );
    		if ( k < 3 ) {
    			clif->message( sd->fd, "@maintenance Syntax :" );
    			clif->message( sd->fd, "@maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>" );
    			return false;
    		}
    	}
    	if ( !group_id ) {
    		clif->message( sd->fd, "The Group ID field cannot be 0, otherwise normal player able to login." );
    		return false;
    	}
    	if ( group_id < 1 || group_id > 99 ) {
    		safesnprintf( output, 255, "Invalid Group ID %d. Range must between 1~99.", group_id );
    		clif->message( sd->fd, output );
    		return false;
    	}
    	if ( kick_duration <= 0 ) {
    		clif->message( sd->fd, "Kick duration cannot be 0 or negative numbers." );
    		return false;
    	}
    	if ( kick_duration > 1440 ) {
    		clif->message( sd->fd, "Kick duration cannot be more than 1 day." );
    		return false;
    	}
    	if ( maintenance_duration <= 0 ) {
    		clif->message( sd->fd, "Maintenance duration cannot be 0 or negative numbers." );
    		return false;
    	}
    	if ( maintenance_duration > 10080 ) {
    		clif->message( sd->fd, "Maintenance duration cannot be more than 1 week." );
    		return false;
    	}
    	if ( safestrnlen( reason, 99 ) < 4 ) {
    		clif->message( sd->fd, "You must input a valid reason for doing this." );
    		return false;
    	}
    	SQL->EscapeString( map->mysql_handle, esc_name, sd->status.name );
    	SQL->EscapeString( map->mysql_handle, esc_reason, reason );
    	if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, %d, '%s', '%s', %d, now(), timestampadd( minute, %d, now() ), timestampadd( minute, %d, now() ) )", sd->status.account_id, esc_name, esc_reason, group_id, kick_duration, kick_duration + maintenance_duration ) == SQL_ERROR ) {
    		Sql_ShowDebug( map->mysql_handle );
    		return false;
    	}
    	if ( SQL->Query( map->mysql_handle, "select unix_timestamp( start_time ), unix_timestamp( end_time ), weekday( end_time ), hour( end_time ), minute( end_time ) from maintenance where id = ( select max(id) from maintenance )" ) == SQL_ERROR ) {
    		Sql_ShowDebug( map->mysql_handle );
    		return false;
    	}
    	else if ( SQL->NextRow( map->mysql_handle ) == SQL_SUCCESS ) {
    		char *data;
    		maintenance_group = group_id;
    		if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
    			maintenance_starttime = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
    			maintenance_endtime = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
    			weekday = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 3, &data, NULL ) == SQL_SUCCESS )
    			hour = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 4, &data, NULL ) == SQL_SUCCESS )
    			minute = atoi(data);
    		SQL->FreeResult( map->mysql_handle );
    	}
    	else {
    		SQL->FreeResult( map->mysql_handle );
    		return false;
    	}
    	{	// stupid date_format doesn't work
    		char* weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
    		char am_pm[3];
    		if ( hour == 0 ) {
    			hour = 12;
    			safesnprintf( am_pm, 3, "AM" );
    		}
    		else if ( hour < 12 )
    			safesnprintf( am_pm, 3, "AM" );
    		else {
    			hour = hour - 12;
    			safesnprintf( am_pm, 3, "PM" );
    		}
    		if ( minute < 10 )
    			safesnprintf( min_display, 3, "0%d", minute );
    		else
    			safesnprintf( min_display, 3, "%d", minute );
    		safesnprintf( maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode will be commence in %d minutes. Players are adviced to log out right now. Maintenance last %d minutes. Server will come back up on %s", kick_duration, maintenance_duration, maintenance_timeformat );
    		intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    	}
    	maintenance_countid = timer->add( timer->gettick() +( ( kick_duration == 1 )? 1000 : 60000 ), maintenance_countdown, 0, 0 );
    	ShowStatus( CL_YELLOW "Maintenance will start in %d min by " CL_GREEN "%s" CL_RESET ".\n", kick_duration, sd->status.name );
    	return true;
    }
    
    ACMD(maintenanceoff) {
    	char esc_name[46], output[CHAT_SIZE_MAX];
    	if ( maintenance_endtime <= (int)time(NULL) ) {
    		clif->message( sd->fd, "The server is currently in not in maintenance mode." );
    		return true;
    	}
    	SQL->EscapeString( map->mysql_handle, esc_name, sd->status.name );
    	if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, %d, '%s', '   @maintenanceoff', 0, null, now(), now() )", sd->status.account_id, esc_name ) == SQL_ERROR ) {
    		Sql_ShowDebug( map->mysql_handle );
    		return false;
    	}
    	maintenance_group = 0;
    	maintenance_starttime = (int)time(NULL);
    	maintenance_endtime = (int)time(NULL);
    	if ( maintenance_countid != INVALID_TIMER ) {
    		timer->delete( maintenance_countid, maintenance_countdown );
    		maintenance_countid = INVALID_TIMER;
    	}
    	if ( maintenance_timerid != INVALID_TIMER ) {
    		timer->delete( maintenance_timerid, maintenance_progress );
    		maintenance_timerid = INVALID_TIMER;
    	}
    	safesnprintf( output, CHAT_SIZE_MAX, "%s ended the Maintenance mode. Players are able to login now.", sd->status.name );
    	intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    	ShowStatus( CL_YELLOW "Maintenance has ended by " CL_GREEN "%s" CL_RESET ".\n", sd->status.name );
    	return true;
    }
    
    //	maintenance <Group ID can stay 1~99>, <duration to kick in minute>, <maintenance duration in minute> { , <reason> };
    BUILDIN(maintenance) {
    	int group_id = 0, kick_duration = 0, maintenance_duration = 0;
    	char reason[99], esc_reason[198], min_display[3];
    	short weekday = 0, hour = 0, minute = 0;
    	if ( maintenance_endtime > (int)time(NULL) ) {
    		ShowError( "buildin_maintenance: Maintenance is currently ON.\n" );
    		return false;
    	}
    	group_id = script_getnum(st,2);
    	kick_duration = script_getnum(st,3);
    	maintenance_duration = script_getnum(st,4);
    	if ( !group_id ) {
    		ShowError( "buildin_maintenance: Group ID field cannot be 0.\n" );
    		return false;
    	}
    	if ( group_id < 1 || group_id > 99 ) {
    		ShowError( "buildin_maintenance: Invalid Group ID %d. Range must between 1~99.\n", group_id );
    		return false;
    	}
    	if ( kick_duration <= 0 ) {
    		ShowError( "buildin_maintenance: Kick duration cannot be 0 or negative numbers.\n" );
    		return false;
    	}
    	if ( kick_duration > 1440 ) {
    		ShowError( "buildin_maintenance: Kick duration cannot be more than 1 day.\n" );
    		return false;
    	}
    	if ( maintenance_duration <= 0 ) {
    		ShowError( "buildin_maintenance: Maintenance duration cannot be 0 or negative numbers.\n" );
    		return false;
    	}
    	if ( maintenance_duration > 10080 ) {
    		ShowError( "buildin_maintenance: Maintenance duration cannot be more than 1 week.\n" );
    		return false;
    	}
    	safesnprintf( reason, 99, script_hasdata(st,5)? script_getstr(st,5) : "   *Regular server maintenance*" );
    	SQL->EscapeString( map->mysql_handle, esc_reason, reason );
    	if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, 0, 'NPC', '%s', %d, now(), timestampadd( minute, %d, now() ), timestampadd( minute, %d, now() ) )", esc_reason, group_id, kick_duration, kick_duration + maintenance_duration ) == SQL_ERROR ) {
    		Sql_ShowDebug( map->mysql_handle );
    		return false;
    	}
    	if ( SQL->Query( map->mysql_handle, "select unix_timestamp( start_time ), unix_timestamp( end_time ), weekday( end_time ), hour( end_time ), minute( end_time ) from maintenance where id = ( select max(id) from maintenance )" ) == SQL_ERROR ) {
    		Sql_ShowDebug( map->mysql_handle );
    		return false;
    	}
    	else if ( SQL->NextRow( map->mysql_handle ) == SQL_SUCCESS ) {
    		char *data;
    		maintenance_group = group_id;
    		if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
    			maintenance_starttime = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
    			maintenance_endtime = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
    			weekday = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 3, &data, NULL ) == SQL_SUCCESS )
    			hour = atoi(data);
    		if ( SQL->GetData( map->mysql_handle, 4, &data, NULL ) == SQL_SUCCESS )
    			minute = atoi(data);
    		SQL->FreeResult( map->mysql_handle );
    	}
    	else {
    		SQL->FreeResult( map->mysql_handle );
    		return false;
    	}
    	{	// stupid date_format doesn't work
    		char* weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
    		char am_pm[3], output[CHAT_SIZE_MAX];
    		if ( hour == 0 ) {
    			hour = 12;
    			safesnprintf( am_pm, 3, "AM" );
    		}
    		else if ( hour < 12 )
    			safesnprintf( am_pm, 3, "AM" );
    		else {
    			hour = hour - 12;
    			safesnprintf( am_pm, 3, "PM" );
    		}
    		if ( minute < 10 )
    			safesnprintf( min_display, 3, "0%d", minute );
    		else
    			safesnprintf( min_display, 3, "%d", minute );
    		safesnprintf( maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
    		safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode will be commence in %d minutes. Players are adviced to log out right now. Maintenance last %d minutes. Server will come back up on %s", kick_duration, maintenance_duration, maintenance_timeformat );
    		intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
    	}
    	maintenance_countid = timer->add( timer->gettick() +( ( kick_duration == 1 )? 1000 : 60000 ), maintenance_countdown, 0, 0 );
    	ShowStatus( CL_YELLOW "Maintenance will start in %d min" CL_RESET ".\n", kick_duration );
    	return true;
    }
    
    BUILDIN(maintenanceoff) {
    	char reason[99], esc_reason[198];
    	if ( maintenance_endtime <= (int)time(NULL) ) {
    		ShowError( "buildin_maintenanceoff: Maintenance is currently OFF.\n" );
    		return false;
    	}
    	safesnprintf( reason, 99, script_hasdata(st,2)? script_getstr(st,2) : "   *maintenance off*" );
    	SQL->EscapeString( map->mysql_handle, esc_reason, reason );
    	if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, 0, 'NPC', '%s', 0, null, now(), now() )", esc_reason ) == SQL_ERROR ) {
    		Sql_ShowDebug( map->mysql_handle );
    		return false;
    	}
    	maintenance_group = 0;
    	maintenance_starttime = (int)time(NULL);
    	maintenance_endtime = (int)time(NULL);
    	if ( maintenance_countid != INVALID_TIMER ) {
    		timer->delete( maintenance_countid, maintenance_countdown );
    		maintenance_countid = INVALID_TIMER;
    	}
    	if ( maintenance_timerid != INVALID_TIMER ) {
    		timer->delete( maintenance_timerid, maintenance_progress );
    		maintenance_timerid = INVALID_TIMER;
    	}
    	intif->broadcast2( "Maintenance mode has ended. Players are able to login now." , 255, maintenance_color, 0x190, 12, 0, 0);
    	ShowStatus( CL_YELLOW "Maintenance has ended" CL_RESET ".\n" );
    	return true;
    }
    
    BUILDIN(maintenancecheck) {
    	int type = script_hasdata(st,2)? script_getnum(st,2) : 0;
    	switch( type ) {
    	default:
    		if ( maintenance_starttime > (int)time(NULL) )
    			script_pushint(st, 1);
    		else if ( maintenance_endtime > (int)time(NULL) )
    			script_pushint(st, 2);
    		else
    			script_pushint(st, 0);
    		return true;
    	case 1:
    		script_pushint(st, maintenance_group);
    		return true;
    	case 2:
    		script_pushint(st, maintenance_starttime);
    		return true;
    	case 3:
    		script_pushint(st, maintenance_endtime);
    		return true;
    	case 4:
    		script_pushint(st, maintenance_countid);
    		return true;
    	case 5:
    		script_pushint(st, maintenance_timerid);
    		return true;
    //	case 6: // for some reason this cause memory leak
    //		script_pushstr(st, maintenance_timeformat );
    //		return true;
    	}
    }
    
    HPExport void plugin_init (void) {
    	addHookPre( "pc->authok", pc_authok_pre );
    	addHookPre( "clif->pLoadEndAck", clif_parse_LoadEndAck_pre );
    
    	addAtcommand( "maintenance", maintenance );
    	addAtcommand( "maintenanceoff", maintenanceoff );
    
    	addScriptCommand( "maintenance", "iii?", maintenance );
    	addScriptCommand( "maintenanceoff", "?", maintenanceoff );
    	addScriptCommand( "maintenancecheck", "?", maintenancecheck );
    } 

     

     

     

    noitem

     

     

    //===== Hercules Plugin ======================================
    //= noitem mapflag
    //===== By: ==================================================
    //= AnnieRuru
    //===== Current Version: =====================================
    //= 1.3
    //===== Compatible With: ===================================== 
    //= Hercules 2015-11-12
    //===== Description: =========================================
    //= block players from using items
    //===== Topic ================================================
    //= http://herc.ws/board/topic/4830-noitem-mapflag/
    //===== Additional Comments: =================================  
    //= prontera   mapflag   noitem   IT_WEAPON,IT_ARMOR
    //= block players from equipping weapon and armor
    //============================================================
    
    #include "common/hercules.h"
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "map/pc.h"
    #include "common/memmgr.h"
    #include "plugins/HPMHooking.h" 
    #include "common/HPMDataCheck.h"
    
    HPExport struct hplugin_info pinfo = {
    	"noitem", // Plugin name
    	SERVER_TYPE_MAP,// Which server types this plugin works with?
    	"1.3",			// Plugin version
    	HPM_VERSION,	// HPM Version (don't change, macro is automatically updated)
    };
    
    struct mapflag_data {
    	int noitem;
    	int noitemlist[50];
    };
    
    //	flush all noitem mapflag back to default upon @reloadscript
    void map_flags_init_pre(void) {
    	int i;
    	for ( i = 0; i < map->count; i++ ) {
    		struct mapflag_data *mf = getFromMAPD( &map->list[i], 0 );
    		if ( mf )
    			removeFromMAPD( &map->list[i], 0 );
    	}
    	return;
    }
    
    void npc_parse_unknown_mapflag_pre( const char *name, char *w3, char *w4, const char* start, const char* buffer, const char* filepath, int *retval ) {
    	if ( !strcmp(w3,"noitem") ) {
    		int id = 0, i = 0, j = 0, k = 0, l = strlen(w4);
    		char *temp = (char*)aMalloc( strlen(w4) +1 );
    		struct item_data *i_data;
    		struct mapflag_data *mf;
    		if ( l ) {
    			int16 m = map->mapname2mapid( name );
    			CREATE( mf, struct mapflag_data, 1 );
    			while ( i <= l && k < 50 ) {
    				if ( w4[i] != ' ' && w4[i] != '	' && w4[i] != ',' && w4[i] != '\0' ) {
    					temp[j++] = w4[i];
    				}
    				else if ( w4[i-1] != ' ' && w4[i-1] != '	' && w4[i-1] != ',' ) {
    					temp[j] = '\0';
    					if ( !strcmp( temp, "IT_HEALING" ) || !strcmp( temp, "0" ) )
    						mf->noitemlist[k] = 0;
    					else if ( !strcmp( temp, "IT_USABLE" ) || !strcmp( temp, "2" ) )
    						mf->noitemlist[k] = 2;
    					else if ( !strcmp( temp, "IT_WEAPON" ) || !strcmp( temp, "4" ) )
    						mf->noitemlist[k] = 4;
    					else if ( !strcmp( temp, "IT_ARMOR" ) || !strcmp( temp, "5" ) )
    						mf->noitemlist[k] = 5;
    					else if ( !strcmp( temp, "IT_CARD" ) || !strcmp( temp, "6" ) )
    						mf->noitemlist[k] = 6;
    					else if ( !strcmp( temp, "IT_DELAYCONSUME" ) || !strcmp( temp, "11" ) )
    						mf->noitemlist[k] = 11;
    					else if ( !strcmp( temp, "IT_CASH" ) || !strcmp( temp, "18" ) )
    						mf->noitemlist[k] = 18;
    					else if ( atoi(temp) == 0 ) {
    						i_data = itemdb->search_name( temp );
    						if ( i_data )
    							mf->noitemlist[k] = i_data->nameid;
    						else {
    							ShowWarning("npc_parse_mapflag: Item name \"%s\" does not exist.\n    Mapflag noitem: At %s (file '%s', line '%d').\n", temp, name, filepath, strline(buffer,start-buffer) );
    							mf->noitemlist[k] = -1;
    						}
    					}
    					else {
    						id = atoi(temp);
    						if ( itemdb->exists(id) )
    							mf->noitemlist[k] = id;
    						else {
    							ShowWarning("npc_parse_mapflag: Item ID \"%s\" does not exist.\n    Mapflag noitem: At %s (file '%s', line '%d').\n", temp, name, filepath, strline(buffer,start-buffer) );
    							mf->noitemlist[k] = -1;
    						}
    					}
    					k++;
    					j = 0;
    				}
    				i++;
    			}
    			mf->noitem = k;
    			addToMAPD( &map->list[m], mf, 0, true );
    		}
    		else
    			ShowWarning("npc_parse_mapflag: no Item ID/type input.\n           Mapflag noitem: At %s (file '%s', line '%d').\n", name, filepath, strline(buffer,start-buffer));
    		aFree(temp);
    		hookStop();
    	}
    	return;
    }
    
    int pc_isequip_post( int retVal, struct map_session_data *sd, int *n ) {
    	if ( retVal == 1 ) {
    		struct mapflag_data *mf = getFromMAPD( &map->list[sd->bl.m], 0 );
    		if ( mf && mf->noitem ) {
    			struct item_data *item = sd->inventory_data[*n];
    			int i = 0, slot = 0;
    			ARR_FIND( 0, mf->noitem, i, item->nameid == mf->noitemlist[i] || item->type == mf->noitemlist[i] );
    			if ( i < mf->noitem )
    				return 0;
    			if ( !itemdb_isspecial( sd->status.inventory[*n].card[0] ) ) {
    				for ( slot = 0; slot < MAX_SLOTS; slot++ ) {
    					if ( sd->status.inventory[*n].card[slot] ) {
    						struct item_data *i_data = itemdb->exists( sd->status.inventory[*n].card[slot] );
    						ARR_FIND( 0, mf->noitem, i, i_data->nameid == mf->noitemlist[i] || i_data->type == mf->noitemlist[i] );
    						if ( i < mf->noitem )
    							return 0;
    					}
    				}
    			}
    		}
    	}
    	return retVal;
    }
    
    int pc_isUseitem_post( int retVal, struct map_session_data *sd, int *n ) {
    	if ( retVal == 1 ) {
    		struct mapflag_data *mf = getFromMAPD( &map->list[sd->bl.m], 0 );
    		if ( mf && mf->noitem ) {
    			struct item_data *item = sd->inventory_data[*n];
    			int i = 0;
    			ARR_FIND( 0, mf->noitem, i, mf->noitemlist[i] == sd->status.inventory[*n].nameid || item->type == mf->noitemlist[i] );
    			if ( i < mf->noitem )
    				return 0;
    		}
    	}
    	return retVal;
    }
    
    int pc_checkitem_post( int retVal, struct map_session_data *sd ) {
    	struct mapflag_data *mf = getFromMAPD( &map->list[sd->bl.m], 0 );
    	int i, calc_flag = 0;
    	if ( sd->state.vending )
    		return 0;
    	if ( mf && mf->noitem ) {
    		for ( i = 0; i < MAX_INVENTORY; i++ ) {
    			int j = 0, slot = 0;
    			struct item_data *i_data = itemdb->exists( sd->status.inventory[i].nameid );
    			if ( sd->status.inventory[i].nameid == 0 || !sd->status.inventory[i].equip )
    				continue;
    			ARR_FIND( 0, mf->noitem, j, mf->noitemlist[j] == i_data->type || mf->noitemlist[j] == sd->status.inventory[i].nameid );
    			if ( j < mf->noitem ) {
    				pc->unequipitem(sd, i, 2);
    				calc_flag = 1;
    				continue;
    			}
    			if ( !itemdb_isspecial( sd->status.inventory[i].card[0] ) ) {
    				for ( slot = 0; slot < MAX_SLOTS; slot++ ) {
    					if ( sd->status.inventory[i].card[slot] ) {
    						struct item_data *i_datac = itemdb->exists( sd->status.inventory[i].card[slot] );
    						ARR_FIND( 0, mf->noitem, j, mf->noitemlist[j] == i_datac->type || mf->noitemlist[j] == sd->status.inventory[i].card[slot] );
    						if ( j < mf->noitem ) {
    							pc->unequipitem(sd, i, 2);
    							calc_flag = 1;
    							break;
    						}
    					}
    				}
    			}
    		}
    		if ( calc_flag && sd->state.active ) {
    			pc->checkallowskill(sd);
    			status_calc_pc( sd,SCO_NONE );
    		}
    	}
    	return retVal;
    }
    
    HPExport void plugin_init (void) {
    	addHookPre( "map->flags_init", map_flags_init_pre );
    	addHookPre( "npc->parse_unknown_mapflag", npc_parse_unknown_mapflag_pre );
    	addHookPost( "pc->isequip", pc_isequip_post );
    	addHookPost( "pc->isUseitem", pc_isUseitem_post );
    	addHookPost( "pc->checkitem", pc_checkitem_post );
    } 

     

     

     

    partyscript.c

     

     

    // Copyright (c) Hercules Dev Team, licensed under GNU GPL.
    // See the LICENSE file
    // Mhalicot PartyScript Hercules Plugin
    // Special Thanks for Mr. [Hercules/Ind]
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "common/hercules.h" /* Should always be the first Hercules file included! (if you don't make it first, you won't be able to use interfaces) */
    #include "common/HPMi.h"
    #include "common/cbasetypes.h"
    #include "common/strlib.h"
    #include "common/utils.h"
    #include "common/malloc.h"
    #include "common/mmo.h"
    #include "common/db.h"
    #include "map/atcommand.h"
    #include "map/script.h"
    #include "map/party.h"
    #include "map/intif.h"
    #include "map/status.h"
    #include "map/clif.h"
    #include "map/map.h"
    #include "map/mapreg.h"
    #include "map/pc.h"
    #include "map/instance.h"
    #include "plugins/HPMHooking.h" 
    #include "common/HPMDataCheck.h"/* should always be the last file included! (if you don't make it last, it'll intentionally break compile time) */
    
    #define party_add_member(party_id,sd) party_reply_invite_mine(sd,party_id,1)
    #define safestrncpy(dst,src,n)       (strlib->safestrncpy((dst),(src),(n)))
    #define idb_remove(db,k)    ( (db)->remove((db),DB->i2key(k),NULL) )
    /*
    1.0 Initial HPM Release [Mhalicot]
    1.1 Rewrite party_delmember, removemember2 dropped.
    1.2 Update Compatibility to latest Revision 137**
    2.0 Update codes, Drop some useless codes.
    2.1 Fixed Map crash when using designate in Party Window
    2.2 Resolved crashing issue when leaving party from instance. [Mumbles / Haru]
    3.0 Added @leaveparty Command [Mhalicot]
    3.1 Fixed Various Compile Warnings and some logic [Dastgir]
    ---------------------------------------
    Documentation
    ---------------------------------------
    
    *party_create("<party name>"{,<character id>{,<item share>,<item share type>}});
    
    Organizes a party with the attached or specified character as leader. If
    successful, the command returns 1 and sets the global temporary variable
    "$@party_create_id" to the ID of the party created.
    
    Additionally, item sharing options can be provided:
     - Item Share: 0-Each Take (default), 1-Party Share
     - Item Share Type: 0-Each Take (default), 1-Even Share
    
    These values are returned upon failure:
     0: Unknown error.
    -1: Player not found.
    -2: Player already has a party.
    -3: Party name exists.
    
    ---------------------------------------
    
    *party_destroy(<party id>);
    
    Disbands a party. The command returns 1 upon success and 0 upon failure.
    
    ---------------------------------------
    
    *party_addmember(<party id>,<character id>);
    
    Adds a player to an existing party.
    
    The command returns 1 upon success, and these values upon failure:
     0: Unknown error.
    -1: Player not found.
    -2: Player already has a party.
    -3: Party not found.
    -4: Party is full.
    
    ---------------------------------------
    
    *party_delmember({<character id>}); 
     
    Removes a player from his/her party. If no player is specified, the command 
    will run for the invoking player. If that player is the only party member 
    remaining, the party will be disbanded. 
     
    The command returns 1 upon success, and these values upon failure: 
     0: Unknown error. 
    -1: Player not found. 
    -2: Player is not in the party. 
    
    ---------------------------------------
    
    *party_changeleader(<party id>,<character id>);
    
    Transfers leadership of a party to the specified character. The original
    party leader doesn't need be online.
    
    The command returns 1 upon success, and these values upon failure:
     0: Unknown error.
    -1: Party not found.
    -2: Player not found.
    -3: Player is not in the party.
    -4: Player is already party leader
    
    ---------------------------------------
    
    *party_changeoption(<party id>,<option>,<flag>);
    
    Changes a party option.
    
    Valid options are:
     0 - Exp Share (flags: 0-Each Take, 1-Even Share)
     1 - Item Share (flags: 0-Each Take, 1-Party Share)
     2 - Item Share Type (flags: 0-Each Take, 1-Even Share)
    
    The command returns 1 upon success, and these values upon failure:
     0: Invalid option.
    -1: Party not found.
    */
    HPExport struct hplugin_info pinfo = {
            "partyscript",		// Plugin name
            SERVER_TYPE_MAP,	// Which server types this plugin works with?
            "2.2",				// Plugin version
            HPM_VERSION,		// HPM Version (don't change, macro is automatically updated)
    };
    
    int create_byscript;
    int party_change_leader_val = 0;
    struct party_data *party_change_leader_p = NULL;
    
    int party_create_mine(struct map_session_data *sd,char *name,int item,int item2) {
    	struct party_member leader;
    	char tname[NAME_LENGTH];
    
    	safestrncpy(tname, name, NAME_LENGTH);
    	trim(tname);
    
    	if( !tname[0] ) {// empty name
    		return 0;
    	}
    
    	if( sd->status.party_id > 0 || sd->party_joining || sd->party_creating ) {// already associated with a party
    		clif->party_created(sd,2);
    		return -2;
    	}
    
    	sd->party_creating = true;
    
    	party->fill_member(&leader, sd, 1);
    
    	intif->create_party(&leader,name,item,item2);
    	return 1;
    }
    
    void party_created_mine(int account_id,int char_id,int fail,int party_id,char *name) {
    	struct map_session_data *sd;
    	sd=map->id2sd(account_id);
    
    	if (!sd || sd->status.char_id != char_id || !sd->party_creating ) {
    		//Character logged off before creation ack?
    		if (!fail) //break up party since player could not be added to it.
    			intif->party_leave(party_id,account_id,char_id);
    		return;
    	}
    
    	sd->party_creating = false;
    
    	if( !fail ) {
    		sd->status.party_id = party_id;
    		clif->party_created(sd,0); //Success message
    		//We don't do any further work here because the char-server sends a party info packet right after creating the party 
    		if(create_byscript) {     //returns party id in $@party_create_id if party is created by script 
    		  mapreg->setreg(script->add_str("$@party_create_id"),party_id); 
    		  create_byscript = 0; 
    		}
    	} else 
    		clif->party_created(sd,1); // "party name already exists"
    }
    
    int party_reply_invite_mine(struct map_session_data *sd,int party_id,int flag) {
    	struct map_session_data* tsd;
    	struct party_member member;
    
    	if( sd->party_invite != party_id ) {// forged
    		sd->party_invite = 0;
    		sd->party_invite_account = 0;
    		return 0;
    	}
    	tsd = map->id2sd(sd->party_invite_account);
    
    	if( flag == 1 && !sd->party_creating && !sd->party_joining ) {// accepted and allowed
    		sd->party_joining = true;
    		party->fill_member(&member, sd, 0);
    		intif->party_addmember(sd->party_invite, &member);
    		return 1;
    	} else {// rejected or failure
    		sd->party_invite = 0;
    		sd->party_invite_account = 0;
    		if( tsd != NULL )
    			clif->party_inviteack(tsd,sd->status.name,1);
    		return 0;
    	}
    	return 0;
    }
    
    void party_reply_invite_overload(struct map_session_data *sd,int party_id,int flag) {
    	party_reply_invite_mine(sd,party_id,flag);
    }
    
    //options: 0-exp, 1-item share, 2-pickup distribution
    int party_setoption(struct party_data *pdata, int option, int flag) {
    	int i;
    	ARR_FIND(0,MAX_PARTY,i,pdata->party.member[i].leader);
    	if(i >= MAX_PARTY)
    		return 0;
    	switch(option) {
    		case 0:
    			intif->party_changeoption(pdata->party.party_id,pdata->party.member[i].account_id,flag,pdata->party.item);
    			break;
    		case 1:
    			if(flag) flag = pdata->party.item|1;
    			else flag = pdata->party.item&~1;
    			intif->party_changeoption(pdata->party.party_id,pdata->party.member[i].account_id,pdata->party.exp,flag);
    			break;
    		case 2:
    			if(flag) flag = pdata->party.item|2;
    			else flag = pdata->party.item&~2;
    			intif->party_changeoption(pdata->party.party_id,pdata->party.member[i].account_id,pdata->party.exp,flag);
    			break;
    		default:
    			return 0;
    			break;
    	}
    	return 1;
    }
    
    bool party_changeleader_mine(struct map_session_data *sd, struct map_session_data *tsd) {
    	int mi, tmi;
    	struct party_data *p = party_change_leader_p;
    
    	party_change_leader_p = NULL;
    
    	if ( !p ) {
    		if (!sd || !sd->status.party_id) {
    			party_change_leader_val = -1;
    			return false;
    		}
    
    		if (!tsd || tsd->status.party_id != sd->status.party_id) {
    			clif->message(sd->fd, "Target character must be online and in your current party.");
    			party_change_leader_val = -3;
    			return false;
    		}
    
    		if ( map->list[sd->bl.m].flag.partylock ) {
    			clif->message(sd->fd, "You cannot change party leaders on this map.");
    			party_change_leader_val = 0;
    			return false;
    		}
    
    		if ((p = party->search(sd->status.party_id)) == NULL ) {
    			party_change_leader_val = -1;
    			return false;
    		}
    
    		ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
    		if (mi == MAX_PARTY) {
    			party_change_leader_val = 0; //Shouldn't happen
    			return false;
    		}
    
    		if (!p->party.member[mi].leader) {
    			clif->message(sd->fd, "You need to be a party leader to use this command.");
    			party_change_leader_val = 0;
    			return false;
    		}
    
    		ARR_FIND( 0, MAX_PARTY, tmi, p->data[tmi].sd == tsd);
    		if (tmi == MAX_PARTY) {
    			party_change_leader_val = 0; //Shouldn't happen
    			return false;
    		}
    	} else {
    		ARR_FIND(0,MAX_PARTY,mi,p->party.member[mi].leader);
    		ARR_FIND(0,MAX_PARTY,tmi,p->data[tmi].sd ==  tsd);
    	}
    
    	if (!p->party.member[mi].leader) {
    		clif->message(sd->fd, "You need to be a party leader to use this command.");
    		party_change_leader_val = 0;
    		return false;
    	}
    
    	ARR_FIND( 0, MAX_PARTY, tmi, p->data[tmi].sd == tsd);
    	if (tmi == MAX_PARTY) {
    		party_change_leader_val = 0; //Shouldn't happen
    		return false;
    	}
    
    	//Change leadership.
    	p->party.member[mi].leader = 0;
    	if (p->data[mi].sd && p->data[mi].sd->fd)
    		clif->message(p->data[mi].sd->fd, "Leadership transferred.");
    
    	p->party.member[tmi].leader = 1;
    	if (p->data[tmi].sd && p->data[tmi].sd->fd)
    		clif->message(p->data[tmi].sd->fd, "You've become the party leader.");
    
    	//Update info.
    	intif->party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id);
    	clif->party_info(p,NULL);
    	party_change_leader_val = 1;
    	return true;
    }
    
    /*==========================================
     * party_create "<party name>"{,<char id>{,<item share: 0-no. 1-yes>{,<item share type: 0-favorite. 1-shared>}}};
     * Return values:
     *      -3      - party name is exist
     *      -2      - player is in party already
     *      -1      - player is not found
     *      0       - unknown error
     *      1       - success, will return party id $@party_create_id
     *------------------------------------------*/
    BUILDIN(party_create) {
    	char party_name[NAME_LENGTH];
    	int item1 = 0, item2 = 0;
    	TBL_PC *sd = NULL;
    
    	if( (!script_hasdata(st,3) && !(sd = script->rid2sd(st))) || (script_hasdata(st,3) && !(sd = map->charid2sd(script_getnum(st,3)))) ) {
    		script_pushint(st,-1);
    		return false;
    	}
    
    	if( sd->status.party_id ) {
    		script_pushint(st,-2);
    		return false;
    	}
    
    	safestrncpy(party_name,script_getstr(st,2),NAME_LENGTH);
    	trim(party_name);
    	if( party->searchname(party_name) ) {
    		script_pushint(st,-3);
    		return false;
    	}
    
    	if( script_getnum(st,4) )
    		item1 = 1;
    
    	if( script_getnum(st,5) )
    		item2 = 1;
    
    	create_byscript = 1;
    	script_pushint(st,party_create_mine(sd,party_name,item1,item2));
    	return true;
    }
    
    /*==========================================
     * party_addmember <party id>,<char id>;
     * Adds player to specified party
     * Return values:
     *      -4      - party is full
     *      -3      - party is not found
     *      -2      - player is in party already
     *      -1      - player is not found
     *      0       - unknown error
     *      1       - success
     *------------------------------------------*/
    BUILDIN(party_addmember) {
    	int party_id = script_getnum(st,2);
    	TBL_PC *sd;
    	struct party_data *pty;
    
    	if( !(sd = map->charid2sd(script_getnum(st,3))) ) {
    		script_pushint(st,-1);
    		return false;
    	}
    
    	if( sd->status.party_id ) {
    		script_pushint(st,-2);
    		return false;
    	}
    
    	if( !(pty = party->search(party_id)) ) {
    		script_pushint(st,-3);
    		return false;
    	}
    
    	if( pty->party.count >= MAX_PARTY ) {
    		script_pushint(st,-4);
    		return false;
    	}
    
    	sd->party_invite = party_id;
    	script_pushint(st,party_add_member(party_id,sd));
    	return true;
    }
    
    /*==========================================
     * party_delmember {<char id>}; 
     * Removes player from his/her party 
     * Return values: 
     *      -2      - player is not in party 
     *      -1      - player is not found 
     *      0       - unknown error 
     *      1       - success 
     *------------------------------------------*/
    BUILDIN(party_delmember) {
    	TBL_PC *sd = NULL;
    
    	if( (!script_hasdata(st,2) && !(sd = script->rid2sd(st))) || 
    		(script_hasdata(st,2) && !(sd = map->charid2sd(script_getnum(st,2))))
    	  ){
    		script_pushint(st,-1);
    		return false;
    	}
    
    	if( !sd->status.party_id ) {
    		script_pushint(st,-2);
    		return false;
    	}
    
    	script_pushint(st,party->leave(sd));
    	return true;
    }
    
    /*==========================================
     * party_changeleader <party id>,<char id>;
     * Can change party leader even the leader is not online
     * Return values:
     *      -4      - player is party leader already 
     *      -3      - player is not in this party
     *      -2      - player is not found
     *      -1      - party is not found
     *      0       - unknown error
     *      1       - success
     *------------------------------------------*/
    BUILDIN(party_changeleader) {
    	int i, party_id = script_getnum(st,2);
    	TBL_PC *sd = NULL;
    	TBL_PC *tsd = NULL;
    	struct party_data *pty = NULL;
    
    	if( !(pty = party->search(party_id)) ) {
    		script_pushint(st,-1);
    		return false;
    	}
    
    	if( !(tsd = map->charid2sd(script_getnum(st,3))) ) {
    		script_pushint(st,-2);
    		return false;
    	}
    
    	if( tsd->status.party_id != party_id ) {
    		script_pushint(st,-3);
    		return false;
    	}
    
    	ARR_FIND(0,MAX_PARTY,i,pty->party.member[i].leader);
    	if( i >= MAX_PARTY ) {  //this is should impossible!
    		script_pushint(st,0);
    		return false;
    	}
    
    	if( pty->data[i].sd == tsd ) {
    		script_pushint(st,-4);
    		return false;
    	}
    
    	party_change_leader_p = pty;
    	party_changeleader_mine(sd,tsd);
    
    	script_pushint(st,party_change_leader_val);
    	return true;
    }
    
    /*==========================================
     * party_changeoption <party id>,<option>,<flag>;
     * Return values:
     *      -1      - party is not found
     *      0       - invalid option
     *      1       - success
     *------------------------------------------*/
    BUILDIN(party_changeoption) {
    	struct party_data *pty;
    
    	if( !(pty = party->search(script_getnum(st,2))) ) {
    		script_pushint(st,-1);
    		return true;
    	}
    
    	script_pushint(st,party_setoption(pty,script_getnum(st,3),script_getnum(st,4)));
    	return true;
    }
    
    /*==========================================
     * party_destroy <party id>;
     * Destroys party with party id. 
     * Return values:
     *      0       - failed
     *      1       - success
     *------------------------------------------*/
    BUILDIN(party_destroy) {
    	int i;
    	struct party_data *pty;
    
    	if( !(pty = party->search(script_getnum(st,2))) ) {
    		script_pushint(st,0);
    	}
    
    	ARR_FIND(0,MAX_PARTY,i,pty->party.member[i].leader);
    	if( i >= MAX_PARTY || !pty->data[i].sd ) { //leader not online
    		int j;
    		for( j = 0; j < MAX_PARTY; j++ ) {
    			TBL_PC *sd = pty->data[j].sd;
    			if(sd)
    				party->member_withdraw(pty->party.party_id,sd->status.account_id,sd->status.char_id);
    			else if( pty->party.member[j].char_id )
    			intif->party_leave(pty->party.party_id,pty->party.member[j].account_id,pty->party.member[j].char_id);
    		}
    		//party_broken_mine(pty->party.party_id);
    		party->broken(pty->party.party_id);
    		script_pushint(st,1);
    	}
    	else    //leader leave = party broken
    		script_pushint(st,party->leave(pty->data[i].sd));
    	return true;
    }
    
    /*==========================================
     *
     *------------------------------------------*/
    ACMD(party) {
    	char party_name[NAME_LENGTH];
    
    	memset(party_name, '\0', sizeof(party_name));
    
    	if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) {
    		clif->message(fd, "Please enter a party name (usage: @party <party_name>).");
    		return false;
    	}
    
    	party_create_mine(sd, party_name, 0, 0);
    	return true;
    }
    
    ACMD(leaveparty) {
    
    	if( !sd->status.party_id ) {
    		clif->message(fd, "You must have a party to use this command");
    		return false;
    	}
    
    	party->leave(sd);
    	return true;
    }
    ACMD(partyoption) {
    	struct party_data *p;
    	int mi, option;
    	char w1[16], w2[16];
    
    	if (sd->status.party_id == 0 || (p = party->search(sd->status.party_id)) == NULL) {
    		clif->message(fd, "You need to be a party leader to use this command.");
    		return false;
    	}
    
    	ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
    	if (mi == MAX_PARTY)
    		return false; //Shouldn't happen
    
    	if (!p->party.member[mi].leader) {
    		clif->message(fd, "You need to be a party leader to use this command.");
    		return false;
    	}
    
    	if(!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2) {
    		clif->message(fd, "Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no>");
    		return false;
    	}
    
    	option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0);
    
    	//Change item share type.
    	if (option != p->party.item)
    		party->changeoption(sd, p->party.exp, option);
    	else
    		clif->message(fd, "There's been no change in the setting.");
    
    	return true;
    }
    
    /* Server Startup */
    HPExport void plugin_init (void) {
    
    	//Commands
    	addAtcommand("partyoption",partyoption);
    	addAtcommand("leaveparty",leaveparty);
    	addAtcommand("party",party);
    	
    	//Scripts
    	addScriptCommand("party_changeoption","iii",party_changeoption);
    	addScriptCommand("party_changeleader","ii",party_changeleader);
    	addScriptCommand("party_addmember","ii",party_addmember);
    	addScriptCommand("party_delmember","?",party_delmember);
    	addScriptCommand("party_create","s???",party_create);
    	addScriptCommand("party_destroy","i",party_destroy);
    
    	party->changeleader = &party_changeleader_mine;
    	party->reply_invite = &party_reply_invite_overload;
    	party->created = &party_created_mine;
    	party->create = &party_create_mine;
    };
     

     

     

     

    I removed from partyscript.c

    #include "common/malloc.h"
    

    Error change to

    Severity	Code	Description	Project	File	Line	Suppression State
    Error	C2039	'safestrncpy': is not a member of 'strlib_interface'	partyscript	Hercules\src\plugins\partyscript.c	343	
    Error	C2039	'safestrncpy': is not a member of 'strlib_interface'	partyscript	Hercules\src\plugins\partyscript.c	138	
    
    

     

     

    vending_extended.c

     

     

    /**
     * Extended Vending System
     * Please Check conf/ExtendedVending.conf, db/item_vending.txt, db/item_db2.conf
     * By Dastgir/Hercules
     */
    
    /*
    Add Following Items to ClientSide:
    
    idnum2itemdisplaynametable.txt
        30000#Zeny#
        30001#Cash#
    
    idnum2itemresnametable.txt
        30000#±ÝÈ#
        30001#¹Ì½º¸±È­#
    */
    
    #include "common/hercules.h"
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
    
    #include "common/HPMi.h"
    #include "common/utils.h"
    #include "common/mmo.h"
    #include "common/socket.h"
    #include "common/memmgr.h"
    #include "common/timer.h"
    #include "common/ers.h"
    #include "common/nullpo.h"
    #include "common/strlib.h"
    #include "common/sql.h"
    
    #include "map/battle.h"
    #include "map/clif.h"
    #include "map/pc.h"
    #include "map/map.h"
    #include "map/mob.h"
    #include "map/skill.h"
    #include "map/atcommand.h"
    #include "map/itemdb.h"
    #include "map/vending.h"
    #include "map/intif.h"
    #include "map/chrif.h"
    #include "map/path.h"
    #include "map/pet.h"
    #include "map/homunculus.h"
    #include "map/status.h"
    #include "map/searchstore.h"
    
    #include "plugins/HPMHooking.h"
    #include "common/HPMDataCheck.h" /* should always be the last file included! (if you don't make it last, it'll intentionally break compile time) */
    
    HPExport struct hplugin_info pinfo =
    {
        "Extended Vending System",	// Plugin name
        SERVER_TYPE_MAP,// Which server types this plugin works with?
        "1.0",			// Plugin version
        HPM_VERSION,	// HPM Version (don't change, macro is automatically updated)
    };
    
    #define VEND_COLOR 0x00FFFF // Cyan
    
    struct s_ext_vend{
    	int itemid;
    };
    struct s_ext_vend ext_vend[MAX_INVENTORY];
    
    struct player_data {
        int vend_loot;
    	int vend_lvl;
    };
    
    struct autotrade_data {
    	int vend_loot;
    };
    
    //Clif Edits
    void clif_vend_message(struct map_session_data *sd, const char* msg, uint32 color);
    void clif_vend_message(struct map_session_data *sd, const char* msg, uint32 color)
    {
    	int fd;
    	unsigned short len = strlen(msg) + 1;
    	
    	nullpo_retv(sd);
    	
    	color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16; // RGB to BGR
    	
    	fd = sd->fd;
    	WFIFOHEAD(fd, len+12);
    	WFIFOW(fd,0) = 0x2C1;
    	WFIFOW(fd,2) = len+12;
    	WFIFOL(fd,4) = 0;
    	WFIFOL(fd,8) = color;
    	memcpy(WFIFOP(fd,12), msg, len);
    	WFIFOSET(fd, WFIFOW(fd,2));
    }
    
    //Skill_Vending
    int skill_vending_ev( struct map_session_data *sd, int nameid);
    int skill_vending_ev( struct map_session_data *sd, int nameid) {
    	struct item_data *item;
    	struct player_data *ssd;
    	char output[1024];
    	
    	nullpo_ret(sd);
    
    
    	if ( nameid <= 0) {
    		clif->skill_fail(sd,MC_VENDING,USESKILL_FAIL_LEVEL,0);
    		return 0;
    	}
    	
    	if ( nameid > MAX_ITEMDB ){
    		return 0;
    	}
        if ( !( ssd = getFromMSD(sd,0) ) ) {
    		CREATE( ssd, struct player_data, 1 );
    		ssd->vend_loot = 0;
    		ssd->vend_lvl = 0;
    		addToMSD( sd, ssd, 0, true );
        }
    	ssd->vend_loot = nameid;
    	item = itemdb->exists(nameid);
    	
    	sprintf(output,"You have selected: %s",item->jname);
    	clif_vend_message(sd,output,VEND_COLOR);
    
    	if ( !pc_can_give_items(sd) ){
    		clif->skill_fail(sd,MC_VENDING,USESKILL_FAIL_LEVEL,0);
    	}
    	else {
    		sd->state.prevend = 1;
    		clif->openvendingreq(sd,2+ssd->vend_lvl);
    	}
    	
    	return 0;
    }
    
    
    //Had to duplicate
    void assert_report(const char *file, int line, const char *func, const char *targetname, const char *title) {
    	if (file == NULL)
    		file = "??";
    	
    	if (func == NULL || *func == '\0')
    		func = "unknown";
    	
    	ShowError("--- %s --------------------------------------------\n", title);
    	ShowError("%s:%d: '%s' in function `%s'\n", file, line, targetname, func);
    	ShowError("--- end %s ----------------------------------------\n", title);
    }
    
    int bc_extended_vending;
    int bc_show_item_vending;
    int bc_ex_vending_info;
    int bc_item_zeny;
    int bc_item_cash;
    void ev_bc(const char *key, const char *val) {
    	if (strcmpi(key,"battle_configuration/extended_vending") == 0) {
    		bc_extended_vending = config_switch(val);
    		if (bc_extended_vending > 1 || bc_extended_vending < 0){
    			ShowDebug("Wrong Value for extended_vending: %d\n",config_switch(val));
    			bc_extended_vending = 0;
    		}
    	} else if (strcmpi(key,"battle_configuration/show_item_vending") == 0) {
    		bc_show_item_vending = config_switch(val);
    		if (bc_show_item_vending > 1 || bc_show_item_vending < 0){
    			ShowDebug("Wrong Value for show_item_vending: %d\n",config_switch(val));
    			bc_extended_vending = 0;
    		}
    	} else if (strcmpi(key,"battle_configuration/ex_vending_info") == 0) {
    		bc_ex_vending_info = config_switch(val);
    		if (bc_ex_vending_info>1 || bc_ex_vending_info<0){
    			ShowDebug("Wrong Value for ex_vending_info: %d\n",config_switch(val));
    			bc_extended_vending = 0;
    		}
    	} else if (strcmpi(key,"battle_configuration/item_zeny") == 0) {
    		bc_item_zeny = config_switch(val);
    		if (bc_item_zeny != 0 && bc_item_zeny > MAX_ITEMDB ){
    			ShowDebug("Wrong Value for item_zeny: %d\n",config_switch(val));
    			bc_extended_vending = 0;
    		}
    	} else if (strcmpi(key,"battle_configuration/item_cash") == 0) {
    		bc_item_cash = config_switch(val);
    		if (bc_item_cash != 0 && bc_item_cash > MAX_ITEMDB ){
    			ShowDebug("Wrong Value for item_cash: %d\n",config_switch(val));
    			bc_extended_vending = 0;
    		}
    	}
    	return;
    }
    
    int ev_return_bc(const char *key)
    {
    	if (strcmpi(key,"battle_configuration/extended_vending") == 0) {
    		return bc_extended_vending;
    	} else if (strcmpi(key,"battle_configuration/show_item_vending") == 0) {
    		return bc_show_item_vending;
    	} else if (strcmpi(key,"battle_configuration/ex_vending_info") == 0) {
    		return bc_ex_vending_info;
    	} else if (strcmpi(key,"battle_configuration/item_zeny") == 0) {
    		return bc_item_zeny;
    	} else if (strcmpi(key,"battle_configuration/item_cash") == 0) {
    		return bc_item_cash;
    	}
    	return 0;
    }
    
    //Clif Edits
    void clif_parse_SelectArrow_pre(int *fd,struct map_session_data **sd)
    {
    	if (pc_istrading(*sd)) {
    	//Make it fail to avoid shop exploits where you sell something different than you see.
    		clif->skill_fail(*sd,(*sd)->ud.skill_id,USESKILL_FAIL_LEVEL,0);
    		clif_menuskill_clear(*sd);
    		return;
    	}
    	switch( (*sd)->menuskill_id ) {
    		case MC_VENDING: // Extended Vending system 
    			skill_vending_ev(*sd, RFIFOW(*fd,2));
    			clif_menuskill_clear(*sd);
    			hookStop();
    			break;
    	}
    	return;
    }
    
    void clif_parse_OpenVending_pre(int *fd, struct map_session_data **sd_) {
    	int fd2 = *fd;
    	short len = (short)RFIFOW(fd2,2) - 85;
    	const char* mes_orig = (const char*)RFIFOP(fd2,4);
    	bool flag = (bool)RFIFOB(fd2,84);
    	const uint8* data = (const uint8*)RFIFOP(fd2,85);
    	char message[1024];
    	struct player_data* ssd;
    	struct item_data *item;
    	struct map_session_data *sd = *sd_;
    	
    	if (!( ssd = getFromMSD(sd,0))) {
    		CREATE( ssd, struct player_data, 1 );
    		ssd->vend_loot = 0;
    		ssd->vend_lvl = 0;
    		addToMSD( sd, ssd, 0, true );
        }
    	item = itemdb->exists(ssd->vend_loot);
    
    	if ((bc_extended_vending == 1) && (bc_show_item_vending==1) && ssd->vend_loot){
    		memset(message, '\0', sizeof(message));
    		strcat(strcat(strcat(strcat(message,"["),item->jname),"] "),mes_orig);
    	}
    
    	
    	if ( !flag )
    		sd->state.prevend = sd->state.workinprogress = 0;
    
    	if ( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM )
    		return;
    	if ( map->list[sd->bl.m].flag.novending ) {
    		clif->message (sd->fd, msg_txt(276)); // "You can't open a shop on this map"
    		return;
    	}
    	if ( map->getcell(sd->bl.m,&sd->bl,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) {
    		clif->message (sd->fd, msg_txt(204)); // "You can't open a shop on this cell."
    		return;
    	}
    
    	if ( message[0] == '\0' ) // invalid input
    		return;
    	if ((bc_extended_vending == 1) && (bc_show_item_vending == 1) && ssd->vend_loot){
    		vending->open(sd, message, data, len/8);
    	}else{
    		vending->open(sd, mes_orig, data, len/8);
    	}
    
    }
    
    int clif_vend(struct map_session_data *sd, int skill_lv) {
    	struct item_data *item;
    	int c, i, d = 0;
    	int fd;
    	nullpo_ret(sd);
    	fd = sd->fd;
    	WFIFOHEAD(fd, 8 * 8 + 8);
    	WFIFOW(fd,0) = 0x1ad;
    	if (bc_item_zeny){
    		WFIFOW(fd, d * 2 + 4) = bc_item_zeny;
    		d++;
    	}
    	if (bc_item_cash){
    		WFIFOW(fd, d * 2 + 4) = bc_item_cash;
    		d++;
    	}
    	for( c = d, i = 0; i < ARRAYLENGTH(ext_vend); i ++ ) {
    		if ((item = itemdb->exists(ext_vend[i].itemid)) != NULL && 
    			(int)item->nameid != bc_item_zeny && (int)item->nameid != bc_item_cash){
    		WFIFOW(fd, c * 2 + 4) = (int)item->nameid;
    			c++;
    		}
    	}
    	if ( c > 0 ) {
    		sd->menuskill_id = MC_VENDING;
    		sd->menuskill_val = skill_lv;
    		WFIFOW(fd,2) = c * 2 + 4;
    		WFIFOSET(fd, WFIFOW(fd, 2));
    	} else {
    		clif->skill_fail(sd,MC_VENDING,USESKILL_FAIL_LEVEL,0);
    		return 0;
    	}
    
    	return 1;
    }
    
    /**
     * Extended Vending system 
     **/
    static bool itemdb_read_vendingdb(char* fields[], int columns, int current)
    {
    	struct item_data* id;
    	int nameid;
     
    	nameid = atoi(fields[0]);
     
    	if ( ( id = itemdb->exists(nameid) ) == NULL )
    	{
    		ShowWarning("itemdb_read_vending: Invalid item id %d.\n", nameid);
    		return false;
    	}
    
    	if ( id->type == IT_ARMOR || id->type == IT_WEAPON )
    	{
    		ShowWarning("itemdb_read_vending: item id %d cannot be equipment or weapon.\n", nameid);
    		return false;
    	}
    
    	ext_vend[current].itemid = nameid;
    
    	return true;
    }
    
    //ItemDB.c
    void itemdb_read_post(bool minimal) {
    	if (minimal) return;
    	sv->readdb(map->db_path, "item_vending.txt", ',', 1, 1, ARRAYLENGTH(ext_vend), itemdb_read_vendingdb);
    	return;
    }
    //Skill.c
    int skill_castend_nodamage_id_pre(struct block_list **src_, struct block_list **bl_, uint16 *skill_id2, uint16 *skill_lv2, int64 *tick2, int *flag2){
    	uint16 skill_id = *skill_id2;
    	uint16 skill_lv = *skill_lv2;
    	struct map_session_data *sd;
    	struct player_data* ssd;
    	struct block_list *src = *src_, *bl = *bl_;
    	if (skill_id > 0 && !skill_lv)
    		return 0;	// celest
    
    
    	nullpo_retr(1, src);
    	nullpo_retr(1, bl);
    
    
    	if (src->m != bl->m)
    		return 1;
    
    
    	sd = BL_CAST(BL_PC, src);
    	if (sd == NULL)
    		return 1;
    	if ( !( ssd = getFromMSD(sd,0) ) ) {
    		CREATE( ssd, struct player_data, 1 );
    		ssd->vend_loot = 0;
    		ssd->vend_lvl = 0;
    		addToMSD( sd, ssd, 0, true );
        }
    
    	//dstsd deleted
    	if (bl->prev == NULL)
    		return 1;
    	if (status->isdead(src))
    		return 1;
    	switch(skill_id){
    		case MC_VENDING:
    			if (sd){
    				if ( !pc_can_give_items(sd) ) //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex]
    					clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
    				else { // Extended Vending system 
    					if (bc_extended_vending == 1){
    						struct item_data *item;
    						char output[1024];
    
    						int c = 0, i, d = 0;
    					
    
    						ssd->vend_lvl = (int)skill_lv;
    						if (bc_item_zeny)
    							d++;
    						if (bc_item_cash)
    							d++;
    						for ( c = d, i = 0; i < ARRAYLENGTH(ext_vend); i ++ ) {
    							if ( (item = itemdb->exists(ext_vend[i].itemid)) != NULL && 
    								item->nameid != bc_item_zeny && item->nameid != bc_item_cash)
    								c++;
    						}
    					
    						if ( c > 1 ){
    							clif_vend(sd,ssd->vend_lvl);
    						} else {
    							sd->state.prevend = 1;
    							if ( c ) {
    								item = itemdb->exists(bc_item_zeny?bc_item_zeny:bc_item_cash?bc_item_cash:ext_vend[0].itemid);
    								ssd->vend_loot = item->nameid;
    								sprintf(output,"Current Currency: %s",itemdb_jname(ssd->vend_loot));
    								clif->messagecolor_self(sd->fd,COLOR_WHITE,output);
    								clif->openvendingreq(sd,2+ssd->vend_lvl);
    							} else {
    								ssd->vend_loot = 0;
    								clif->openvendingreq(sd,2+ssd->vend_lvl);
    							}
    						}
    						hookStop();
    					} else {
    						ssd->vend_loot = 0;
    						sd->state.prevend = sd->state.workinprogress = 3;
    						clif->openvendingreq(sd,2+skill_lv);
    					}
    				}
    			}
    			break;
    	}
    	return 1;
    }
    
    void vending_list_pre(struct map_session_data **sd, unsigned int *id2) {
    	unsigned int id = *id2;
    	struct map_session_data *vsd;
    	struct player_data *ssd;
    	char output[1024];
    	int vend_loot = 0;
    	nullpo_retv(*sd);
    
    	if ((vsd = map->id2sd(id)) == NULL)
    		return;
    	if (!vsd->state.vending)
    		return; // not vending
    	ssd = getFromMSD(vsd, 0);
    	if (ssd) {
    		vend_loot = ssd->vend_loot;
    	}
        
    	if ( !pc_can_give_items(*sd) || !pc_can_give_items(vsd) ) { //check if both GMs are allowed to trade
    		// GM is not allowed to trade
    		if ((*sd)->lang_id >= atcommand->max_message_table)
    			clif->message((*sd)->fd, atcommand->msg_table[0][246]);
    		else
    			clif->message((*sd)->fd, atcommand->msg_table[(*sd)->lang_id][246]);
    		return;
    	} 
    
    	if ( bc_extended_vending == 1 && vend_loot ) {
    		sprintf(output,"You've opened %s's shop. Sale is carried out: %s",vsd->status.name, itemdb_jname(vend_loot));
    		clif->messagecolor_self((*sd)->fd,COLOR_WHITE,output);
    	}
    }
    
    void vending_purchasereq_mod(struct map_session_data **sd_, int *aid2, unsigned int *uid2, const uint8 **data_, int *count2) {
    	int aid = *aid2;
    	unsigned int uid = *uid2;
    	int count = *count2;
    	int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING];
    	double z;
    	struct s_vending vend[MAX_VENDING]; // against duplicate packets
    	struct map_session_data* vsd = map->id2sd(aid);
    	struct player_data* ssd;
    	struct map_session_data *sd = *sd_;
    	int vend_loot = 0;
    	const uint8 *data = *data_;
    
    	nullpo_retv(sd);
    	if (vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id)
    		return; // invalid shop
    	
    	ssd = getFromMSD(vsd, 0);
    	if (ssd)
    		vend_loot = ssd->vend_loot;
    	
    	if (vend_loot)
    		hookStop();
    	if ( vsd->vender_id != uid ) { // shop has changed
    		clif->buyvending(sd, 0, 0, 6);  // store information was incorrect
    		return;
    	}
    
    	if (!searchstore->queryremote(sd, aid) &&
    		(sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE)))
    		return; // shop too far away
    
    	searchstore->clearremote(sd);
    
    	if ( count < 1 || count > MAX_VENDING || count > vsd->vend_num )
    		return; // invalid amount of purchased items
    
    	blank = pc->inventoryblank(sd); //number of free cells in the buyer's inventory
    	// duplicate item in vending to check hacker with multiple packets
    	memcpy(&vend, &vsd->vending, sizeof(vsd->vending)); // copy vending list
    
    	// some checks
    	z = 0.; // zeny counter
    	w = 0;  // weight counter
    	for( i = 0; i < count; i++ ) {
    		short amount = *(const uint16*)(data + 4*i + 0);
    		short idx    = *(const uint16*)(data + 4*i + 2);
    		idx -= 2;
    
    		if ( amount <= 0 )
    			return;
    
    		// check of item index in the cart
    		if ( idx < 0 || idx >= MAX_CART )
    			return;
    
    		ARR_FIND( 0, vsd->vend_num, j, vsd->vending[j].index == idx );
    		if ( j == vsd->vend_num )
    			return; //picked non-existing item
    		else
    			vend_list[i] = j;
    
    		z += ((double)vsd->vending[j].value * (double)amount);
    		/**
    		 * Extended Vending system 
    		 **/
    		if ( bc_extended_vending == 1 ){
    			if ( vend_loot == bc_item_zeny || !vend_loot ) {
    				if ( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) {
    					//clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny
    					return;
    				}
    				if ( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle->bc->vending_over_max ) {
    					clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow
    					return;
    		
    				}
    			} else if (vend_loot == bc_item_cash){
    				if ( z > sd->cashPoints || z < 0. || z > (double)MAX_ZENY ) {
    					clif->messagecolor_self(sd->fd,COLOR_WHITE,"You do not have enough CashPoint");
    					return;
    				}
    			} else {
    				int k, loot_count = 0, vsd_w = 0;
    				for (k = 0; k < MAX_INVENTORY; k++)
    					if (sd->status.inventory[k].nameid == vend_loot)
    						loot_count += sd->status.inventory[k].amount;
    						
    				if ( z > loot_count || z < 0) {
    					clif->messagecolor_self(sd->fd,COLOR_WHITE,"You do not have enough items");
    					return;
    				}
    				if ( pc->inventoryblank(vsd) <= 0 ) {
    					clif->messagecolor_self(sd->fd,COLOR_WHITE,"Seller has not enough space in your inventory");
    					return;
    				}
    				vsd_w += itemdb_weight(vend_loot) * (int)z;
    				if ( vsd_w + vsd->weight > vsd->max_weight ) {
    					clif->messagecolor_self(sd->fd,COLOR_WHITE,"Seller can not take all the item");
    					return;
    				} 
    			}
    		} else {
    			if ( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY )
    			{
    				clif->buyvending(sd, idx, amount, 1); // you don't have enough zeny
    				return;
    			}
    			if ( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle->bc->vending_over_max )
    			{
    				clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow
    				return;
    			}
    
    		}
    		w += itemdb_weight(vsd->status.cart[idx].nameid) * amount;
    		if ( w + sd->weight > sd->max_weight ) {
    			clif->buyvending(sd, idx, amount, 2); // you can not buy, because overweight
    			return;
    		}
    		
    		//Check to see if cart/vend info is in sync.
    		if ( vend[j].amount > vsd->status.cart[idx].amount )
    			vend[j].amount = vsd->status.cart[idx].amount;
    		
    		// if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
    		// here, we check cumulative amounts
    		if ( vend[j].amount < amount ) {
    			// send more quantity is not a hack (an other player can have buy items just before)
    			clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
    			return;
    		}
    		
    		vend[j].amount -= amount;
    
    		switch( pc->checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) {
    			case ADDITEM_EXIST:
    				break;	//We'd add this item to the existing one (in buyers inventory)
    			case ADDITEM_NEW:
    				new_++;
    				if (new_ > blank)
    					return; //Buyer has no space in his inventory
    				break;
    			case ADDITEM_OVERAMOUNT:
    				return; //too many items
    		}
    	}
    /**
     * Extended Vending system 
     **/
    	if (bc_extended_vending == 1) {
    		if ( vend_loot == bc_item_zeny || !vend_loot ) {
    		
    			//Logs (V)ending Zeny [Lupus]
    		
    			pc->payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd);
    			if ( battle->bc->vending_tax )
    				z -= z * (battle->bc->vending_tax/10000.);
    			pc->getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd);
    
    		} else if ( vend_loot == bc_item_cash ) {
    			pc->paycash(sd,(int)z,0);
    			pc->getcash(vsd,(int)z,0);
    		} else {
    			for( i = 0; i < MAX_INVENTORY; i++)
    				if ( sd->status.inventory[i].nameid == vend_loot ) {
    					struct item *item;
    					item = &sd->status.inventory[i];
    					pc->additem(vsd,item,(int)z, LOG_TYPE_VENDING);
    				}
    			pc->delitem(sd,pc->search_inventory(sd, vend_loot),(int)z,0,6, LOG_TYPE_VENDING);
    			
    		}
    	} else {
    		//Logs (V)ending Zeny [Lupus]
    			pc->payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd);
    		if ( battle->bc->vending_tax )
    			z -= z * (battle->bc->vending_tax/10000.);
    		pc->getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd);
    	}
    
    
    	for (i = 0; i < count; i++) {
    		short amount = *(const uint16*)(data + 4*i + 0);
    		short idx    = *(const uint16*)(data + 4*i + 2);
    		const char *item_name = itemdb_jname(vsd->status.cart[idx].nameid);
    		double rev = 0.;
    		idx -= 2;
    
    		if ( bc_ex_vending_info ) // Extended Vending system 
    			rev = ((double)vsd->vending[vend_list[i]].value * (double)amount);
    		
    		// vending item
    		pc->additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING);
    		vsd->vending[vend_list[i]].amount -= amount;
    		pc->cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING);
    		clif->vendingreport(vsd, idx, amount, sd->status.char_id, (int)z);
    
    		//print buyer's name
    		if ( battle->bc->buyer_name ) {
    			char temp[256];
    			if ( bc_ex_vending_info ) { // Extended Vending system 
    				
    				sprintf(temp, "%s has bought '%s' in the amount of %d. Revenue: %d %s", sd->status.name, item_name, amount, (int)(rev -= rev * (battle->bc->vending_tax/10000.)), vend_loot?itemdb_jname(vend_loot):"Zeny");
    			} else {
    				if (sd->lang_id >= atcommand->max_message_table)
    					sprintf(temp, atcommand->msg_table[0][265], sd->status.name);
    				else
    					sprintf(temp, atcommand->msg_table[sd->lang_id][265], sd->status.name);
    			}
    			clif_disp_onlyself(vsd, temp);
    		}
    	}
    
    	if ( bc_ex_vending_info ) { // Extended Vending system 
    		char temp[256];
    		sprintf(temp, "Full revenue from %s is %d %s", sd->status.name, (int)z, vend_loot?itemdb_jname(vend_loot):"Zeny");
    		clif_disp_onlyself(vsd, temp);
    	}
    
    	// compact the vending list
    	for( i = 0, cursor = 0; i < vsd->vend_num; i++ ) {
    		if ( vsd->vending[i].amount == 0 )
    			continue;
    		
    		if ( cursor != i ) { // speedup
    			vsd->vending[cursor].index = vsd->vending[i].index;
    			vsd->vending[cursor].amount = vsd->vending[i].amount;
    			vsd->vending[cursor].value = vsd->vending[i].value;
    		}
    
    		cursor++;
    	}
    	vsd->vend_num = cursor;
    
    	//Always save BOTH: buyer and customer
    	if ( map->save_settings&2 ) {
    		chrif->save(sd,0);
    		chrif->save(vsd,0);
    	}
    
    	//check for @AUTOTRADE users [durf]
    	if ( vsd->state.autotrade ) {
    		//see if there is anything left in the shop
    		ARR_FIND( 0, vsd->vend_num, i, vsd->vending[i].amount > 0 );
    		if ( i == vsd->vend_num ) {
    			//Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex]
    			vending->close(vsd);
    			map->quit(vsd); //They have no reason to stay around anymore, do they?
    		}
    	}
    	if (bc_extended_vending){
    		hookStop();
    	}
    }
    
    void pc_autotrade_prepare_pre(struct map_session_data **sd) {
    	struct player_data *ssd;
    	ssd = getFromMSD(*sd, 0);
    	if (ssd){
    		if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `evs_info` (`vend_loot`,`vend_lvl`,`char_id`) VALUES ('%d','%d','%d')ON DUPLICATE KEY UPDATE `vend_lvl`='%d', `vend_loot`='%d'",
    										ssd->vend_loot,
    										ssd->vend_lvl,
    										(*sd)->status.char_id,
    										ssd->vend_lvl,
    										ssd->vend_loot
    										))
    			Sql_ShowDebug(map->mysql_handle);
    	}
    }
    
    void pc_autotrade_populate_pre(struct map_session_data **sd) {
    	struct player_data *ssd;
    	char *mdata = NULL;
    	
    	if (!( ssd = getFromMSD(*sd,0))) {
    		CREATE(ssd, struct player_data, 1);
    		ssd->vend_loot = 0;
    		ssd->vend_lvl = 0;
    		addToMSD(*sd, ssd, 0, true);
    	}
    	if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `vend_loot`,`vend_lvl` FROM `evs_info` WHERE `char_id` = '%d'", (*sd)->status.char_id))
    		Sql_ShowDebug(map->mysql_handle);
    
    	while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
    		SQL->GetData(map->mysql_handle, 0, &mdata, NULL); ssd->vend_loot = atoi(mdata);
    		SQL->GetData(map->mysql_handle, 1, &mdata, NULL); ssd->vend_lvl = atoi(mdata);
    		break;
    	}
    	return;
    }
    
    HPExport void plugin_init (void){
    	
    	addHookPre(clif, pSelectArrow, clif_parse_SelectArrow_pre);
    	addHookPre(clif, pOpenVending, clif_parse_OpenVending_pre);
    	addHookPre(skill, castend_nodamage_id, skill_castend_nodamage_id_pre);
    	addHookPre(vending, list, vending_list_pre);
    	addHookPre(vending, purchase, vending_purchasereq_mod);
    	addHookPre(pc, autotrade_prepare, pc_autotrade_prepare_pre);
    	addHookPre(pc, autotrade_populate, pc_autotrade_populate_pre);
    	addHookPost(itemdb, read, itemdb_read_post);
    	if (SQL_ERROR == SQL->Query(map->mysql_handle, "CREATE TABLE IF NOT EXISTS `evs_info` (`char_id` int(10) NOT NULL,`vend_loot` int(6) NOT NULL,`vend_lvl` int(5) NOT NULL, PRIMARY KEY(`char_id`))")){
    		Sql_ShowDebug(map->mysql_handle);
    	}
    }
    
    HPExport void server_preinit (void) {
    	addBattleConf("battle_configuration/extended_vending",ev_bc, ev_return_bc, false);
    	addBattleConf("battle_configuration/show_item_vending",ev_bc, ev_return_bc, false);
    	addBattleConf("battle_configuration/ex_vending_info",ev_bc, ev_return_bc, false);
    	addBattleConf("battle_configuration/item_zeny",ev_bc, ev_return_bc, false);
    	addBattleConf("battle_configuration/item_cash",ev_bc, ev_return_bc, false);
    }
    
    HPExport void server_online (void) {
    	ShowInfo ("'%s' Plugin by Dastgir/Hercules. Version '%s'\n",pinfo.name,pinfo.version);
    }
     

     

     

     

    storageadditem.c

     

     

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #include "common/hercules.h" /* Should always be the first Hercules file included! (if you don't make it first, you won't be able to use interfaces) */
    #include "common/HPMi.h"
    #include "map/intif.h"
    #include "map/pc.h"
    #include "map/storage.h"
    #include "plugins/HPMHooking.h" 
    #include "common/HPMDataCheck.h" // should always be the last file included! (if you don't make it last, it'll intentionally break compile time)
    
    HPExport struct hplugin_info pinfo = {
    	"storageadditem", // Plugin name
    	SERVER_TYPE_MAP,// Which server types this plugin works with?
    	"0.1",			// Plugin version
    	HPM_VERSION,	// HPM Version (don't change, macro is automatically updated)
    };
    
    
    /*==========================================
     * storageadditem <item id>,<amount>{,<account id>}
     * Adds items from the target/attached player.
     *==========================================*/
    BUILDIN(storageadditem) {
    	TBL_PC *sd;
    	struct item it;
    
    	if (script_hasdata(st,4)) {
    		int account_id = script_getnum(st,4);
    		sd = map->id2sd(account_id); // <account id>
    		if (sd == NULL) {
    			ShowError("script:storageadditem: player not found (AID=%d).\n", account_id);
    			st->state = END;
    			return false;
    		}
    	} else {
    		sd = script->rid2sd(st);// attached player
    		if (sd == NULL)
    			return true;
    	}
    
    	memset(&it, 0, sizeof(it));
    	if (script_isstringtype(st, 2)) {
    		const char* item_name = script_getstr(st, 2);
    		struct item_data* id = itemdb->search_name(item_name);
    		if (id == NULL) {
    			ShowError("script:storageadditem: unknown item \"%s\".\n", item_name);
    			st->state = END;
    			return false;
    		}
    		it.nameid = id->nameid;// "<item name>"
    	} else {
    		it.nameid = script_getnum(st, 2);// <item id>
    		if (!itemdb->exists(it.nameid)) {
    			ShowError("script:storageadditem: unknown item \"%d\".\n", it.nameid);
    			st->state = END;
    			return false;
    		}
    	}
    
    	it.amount=script_getnum(st,3);
    
    	if( it.amount <= 0 ) {
    		return true;// nothing to do
    	}
    	if( sd->status.storage.storage_amount > MAX_STORAGE ) {
    		return 0; // storage full
    	}
    	it.identify=1;
    	storage->open(sd);
    	storage->additem(sd,&it,it.amount);
    	storage->close(sd);
    }
    
    /* Server Startup */
    HPExport void plugin_init (void) {
    	addScriptCommand( "storageadditem", "vi?", storageadditem);
    } 

     

     

     

    @edit 

    I forgot to say that I added ALL the plugins

    #include "common/hercules.h" /* Should always be the first Hercules file included! (if you don't make it first, you won't be able to use interfaces) */
    

    Is correct?


  13. What do I need to change so that the command does not convert the item's status, bonus, etc, only its visual part?

     

    I'm Sorry, solved.

     

     

    Update

    • 2.0 Converted Costume Items will now removed normal stats and Bonuses. [Mhalicot]
    •  
    • 3.0 Item Combos will now Ignore Converted Costume Items. [Mhalicot]
    •  
    • 3.1 Fixed HP/SP becomes 1/1 [Mhalicot]
    •  
    • 3.2 Fixed Sinx Can't Equipt dagger/sword on both arms(L/R), Special Thanks to Haru for Help [Mhalicot]
    •  
    • 3.3 Fixed Error when compiling.

  14. Criando habilidades ou clonando-as
     
    Introdução
     
    Uma grande área onde os jogadores têm dificuldade é adicionar novas habilidades para a fonte e o cliente. Abaixo será documentado como implementar essas novas habilidades.
     
    A habilidade
     
    A habilidade que estaremos trabalhando é simples.

     

    Nome: Earth Bolt
    Level Máx: 10
    Tipo: Ativa
    Custo de SP: 20 + 5*SkillLV
    Alvo: 1 inimigo
    Tempo de conjuração: 2 seg
    Delay: 1 seg
    Duração: Instantânea
    Descrição: Causa dano mágico de elemento terra ao inimigo, conforme level da habilidade, a 150% MATK por hit.
    Basicamente, essa habilidade deve atingir 1 inimigo e lidar com 10 hits de 150% MATK, propriedade elemental da Terra e deve ser baseada em dano mágico.
     

     

    Abra /src/map/skill.h
    Role para baixo até encontrar

     

    EL_STONE_HAMMER,
    EL_ROCK_CRUSHER,
    EL_ROCK_CRUSHER_ATK,
    EL_STONE_RAIN,
     

     

    Depois daqui é onde nós adicionamos quaisquer habilidades adicionais. É melhor dar às habilidades um ID personalizado para começar. Então, vamos adicionar a nossa habilidade "Earth Bolt".
    Depois disso, adicione
    MG_EARTHBOLT = 8443,
     

     

    MG_ definição significa "Mago", você vai trabalhar para fora as siglas como você percorrer as habilidades. Definimos a base da habilidade. Como você pode ver, o id de habilidade é definido como '8443' desde Stone Elemental's Stone Rain é definido como 8442 (e é o última habilidade de jogador acessível).
     
    Abra /src/map/skill.c
     
    Esse arquivo é onde definimos as implementações de habilidades reais. Para habilidades de alvo único, todo o processamento dessa habilidade irá em skill_castend_damage_id (para habilidades prejudiciais) ou skill_castend_nodamage_id (para skills que não causam danos).
     
    Habilidades baseadas em mágica ou mágia.
     
    Como o Earth Bolt é baseado em danos, encontre a função skill_castend_damage_id e localize:

     

        case AB_RENOVATIO:
        case AB_HIGHNESSHEAL:
        case AB_DUPLELIGHT_MAGIC:
        case WM_METALICSOUND:
        case MH_ERASER_CUTTER:
        case KO_KAIHOU:
     

     

    A razão pela qual estaremos colocando a case para Earth Bolt aqui é porque:
     

     

           skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
     

     

    A definição BF_MAGIC significa que a habilidade é baseada em magia e deve ser calculada sob cálculos de batalha mágica. Assim, após a case NJ_HUUJIN adicionar:

     

        case MG_EARTHBOLT:
     

     

    Habilidades baseadas em armas
     
    No caso de querer adicionar uma habilidade que é baseada em Arma, em vez de Magia, encontre:

     

        case WM_GREAT_ECHO:
        case GN_SLINGITEM_RANGEMELEEATK:
        case KO_JYUMONJIKIRI:
        case KO_SETSUDAN:
        case GC_DARKCROW:
        case LG_OVERBRAND_BRANDISH:
        case LG_OVERBRAND:
     

     

    E adicione a case depois disso. Se quiséssemos que o Earth Bolt fosse baseado em armas, ficaria assim:

     

        case WM_GREAT_ECHO:
        case GN_SLINGITEM_RANGEMELEEATK:
        case KO_JYUMONJIKIRI:
        case KO_SETSUDAN:
        case GC_DARKCROW:
        case LG_OVERBRAND_BRANDISH:
        case LG_OVERBRAND:
        case MG_EARTHBOLT:
     

     

    No entanto, vamos manter a função Magic em vez disso.
     
    Abra /src/map/battle.c
     
    Nesta função, todos os cálculos de danos principais são realizados. E em funções separadas, as % modificadoras para as habilidades são armazenados. Portanto, para os nossos danos de 150%, adicionamos o extra de 50% (já que 100% é o padrão) na função apropriada.
    Ataques baseado em mágica
    Para ataques baseados em Magia, os modificadores são encontrados em battle_calc_magic_attack. Basta encontrar:

     

    case NPC_EARTHQUAKE:
        skillratio += 100 +100*skill_lv +100*(skill_lv/2);
        break;
     

     

    E adicione o modificador de danos abaixo. Como Earth Bolt é baseado em magia, nós adicionaremos-a aqui.

     

        case MG_EARTHBOLT:
            skillratio += 50;
            break;
     

     

    Isso agora significa que o Earth Bolt causará dano mágico de 150% MATK.
     
    Átaques baseado em armas
     
    Para ataques baseados em armas, os modificadores são encontrados em battle_calc_weapon_attack. Basta encontrar:

     

        case NPC_VAMPIRE_GIFT:
            skillratio += ((skill_lv-1)%5+1)*100;
            break;
     

     

    E adicione seu modificador de dano lá. Por exemplo, se o Earth Bolt fosse baseado em Weapon, acrescentaríamos:

     

        case MG_EARTHBOLT:
            skillratio += 50;
            break;
     

     

    O + = 50 significa simplesmente "Adicionar 50% ao 100%" para danos de ATK de 150%.
     
    Suporte a banco de dados de habilidades
     
    Tecnicamente falando, a base da habilidade está agora correta. Claro, se você quiser implementar habilidades mais complexas, há muito mais para isso. A seção separada será criada no futuro para isso. Mas, por enquanto, precisamos implementar as entradas do banco de dados de habilidades. Os arquivos abaixo podem ser encontrados em db / (pre / re) /. Apenas um de ambos (pre / re) precisa ser atualizado, é o qual você usa em seu servidor.
     
    • Nessa parte é sempre aconselhável que você tenha alguma habilidade escolhida para se utilizar como base, pois facilitará muito a criação e/ou clonagem de sua habilidade.
    • Aqui há diferenças, então dependendo do emulador usado, cada forma será de um jeito, caso o seu emulador seja alguns dos abaixos, continue. Caso não, pule para a parte: ** p/ Hercules.
     
    ** p/ rAthena, brAthena, Cronus.
     
    Skill_db.txt
     
    Para a nossa habilidade Earth Bolt, podemos agora digitar o seguinte:
    Estrutura:

    // ID,Alcance,Dano,Inf,Elemento,Nk,Splash,MaxLv,ListNum,CastCancel,ChanceDefCast,Inf2,MaxCount,TipoSkill,BlowCount,Nome,Descrição
    // 01 ID
    // 02  Alcance	(Habilidades de combo não verificam pelo alcance
    //           Se o alcance < 5, então a habilidade é considerada melee)
    // 03 Dano (8- dano repetitivo, 6- dano único)
    // 04 inf (0- passivo, 1- inimigo, 2- local, 4- si próprio, 16- amigo, 32- armadilha)
    // 05 Elemento (0 - neutro, 1 - água, 2 - terra, 3 - fogo, 4 - vento, 5 - veneno,
    //             6 - sagrado, 7 - sombrio, 8 - fantasma, 9 - morto-vivo, -1 - elemento da arma
    //             -2 - elemento endowed, -3 - elemento aleatório.)
    // 06 nk (Propriedade de Dano das Habilidades):
    //    0x01 - habilidade sem dano
    //    0x02 - tem área visual (necessária modificação na source)
    //    0x04 - dano dividido entre os alvos (necessário 0x02 em ordem de trabalho)
    //    0x08 - habilidade ignora dano bônus dado por cartas de quem a conjura
    //    0x10 - habilidade ignora bônus elementais
    //    0x20 - habilidade ignora a defesa do alvo (tipo variado sempre ingnora)
    //    0x40 - habilidade ignora a esquiva do alvo (tipo mágido sempre ignora)
    //    0x80 - habilidade ignora defesa do alvo dada por cartas
    // 07 Área de efeito (-1 para wide)
    // 08 Nível máximo da habilidade
    // 09 Número de danos (Quando positivo, acresenta o dano por dano, 
    //    valores negativos apenas mostraram o número de acertos, sem aumentar os danos totais)
    // 10 A conjuração pode ser cancelada?
    // 11 Redução de defesa durante conjuração.
    // 12 inf2 (Informações de Habilidades 2):
    //    0x0001- habilidade de quest
    //    0x0002- habilidade de npc
    //    0x0004- habilidade de casamento
    //    0x0008- habilidade de espírito
    //    0x0010- habilidade de clã
    //    0x0020- habilidade de música
    //    0x0040- habilidade de dueto
    //    0x0080- armadilha
    //    0x0100- habilidade que o alvo é quem invoca
    //    0x0200- não pode ser usada em si próprio
    //    0x0400- apenas pode ser usada em membros de grupo
    //    0x0800- apenas pode ser usada em membros de clã
    //    0x1000- não pode ser usada em inimigos
    //    0x2000- habilidade ignora proteção terrestre (exemplo: Chuva de Flechas)
    //    0x4000- chorus skill
    // 13 maxcount: Quantidade máxima de habilidades colocadas no chão.
    //    player_land_skill_limit/monster_land_skill_limit está ativo. Para Habilidades
    //    que atacam usando um caminho, este é o comprimento do caminho a ser utilizado.
    // 14 Tipo de Ataque (nenhum, arma, magia, misc)
    // 15 Blowcount (amount of tiles skill knockbacks)
    // 16 Nome
    // 17 Descrição
    //=================================================================*/

    8443,5,8,1,2,0,0,10,1:2:3:4:5:6:7:8:9:10,yes,0,0,0,magic, 0, MG_EARTHBOLT, Earth Bolt
     

     

    Isso define que:
    Earth Bolt tem um intervalo de 5 células, bate várias vezes, é elemento da Terra e alvos 1 inimigo. Ele pode ser interrompido, e é de dano de tipo mágico. A quantidade de acessos aumenta em 1 em cada nível, com um nível máximo de 10.
     
    Skill_cast_db.txt
     
    Para a nossa habilidade Earth Bolt, podemos agora digitar o seguinte:
    Estrutura:

    // SkillID,TempoConjuracao,AfterCastActDelay,AfterCastWalkDelay,Duracao1,Duracao2,Cool Down,Tempo de Cast Fixo
    //== Explanando:
    // TempoConjuracao: Tempo para lançar esta habilidade, em milissegundos.
    // AfterCastActDelay: Atraso "normal",o personagem não pode usar habilidades,em milésimos de segundo.
    // AfterCastWalkDleay: Tempo necessário para que o personagem possa mover-se novamente, em milésimos de segundo.
    // Duracao1 / Duracao2: Geralmente, o tempo ultilizado pela habilidade, em alguns casos é usado para salvar dados especiais.
    // Cool Down: Tempo necessário até que o personagem possa voltar a usar essa habilidade, em milésimos de segundo.
    // Tempo de Cast Fixo: Tempo de execução das habilidades em milissegundos (quando 0, usa-se 20% do tempo de cast e menor que 0 significa que não há tempo de cast fixo)
    //== Extra
    // Em todos os campos você pode usar ":" como delimitador de valores específicos do nível,
    // - Exemplo usando SM_PROVOKE
    // - Original:6,0,0,0,30000,0,1000
    // - Modificado:6,0,0,0,30000,0,1000:2500:3000:etc
    // - Faz no nível 1 ter 1000 (1s) cool down, lvl 2 2500 (2.5s), lvl 3 3000, e assim por diante.
    //==========================================

    8443,2000,1,000,0,0,0
     

     

    Isso define que:
    Earth Bolt tem um segundo tempo de ligação e um tempo de atraso de 1 segundo. Não há atraso de caminhada após o lançamento.
     
    Skill_require_db.txt
     
    Para o nosso Earth Bolt, podemos agora digitar o seguinte:
    Estrutura:

    // SkillID,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10
    //
    // 01 ID
    // 02 HP cost
    // 03 Max HP trigger
    // 04 SP cost
    // 05 HP rate
    //	If positive, it is a percent of your current hp, otherwise it is a percent of your max hp.
    // 06 SP rate
    //	If positive, it is a percent of your current sp, otherwise it is a percent of your max sp.
    // 07 Zeny cost
    // 08 Required Weapon
    //	See doc/item_db.txt for weapon types
    //	99 any weapon **includes bare fists**
    //	To include more than one weapon type use type1:type2:type3
    // 09 Required Ammo
    //	See doc/item_db.txt for ammo types
    //	99 any ammo type
    //	To include more than one ammo type use type1:type2:type3
    // 10 Required ammo ammount
    // 11 Required State
    //	none = Nothing special
    //	move_enable = Requires to be able to move
    //	recover_weight_rate = Requires to be less than 50% weight
    //	water = Requires to be standing on a water cell
    //	cart = Requires a Pushcart
    //	riding = Requires to ride either a peco or a dragon
    //	falcon = Requires a Falcon
    //	sight = Requires Sight skill activated
    //	hiding = Requires Hiding skill activated
    //	cloaking = Requires Cloaking skill activated
    //	explosionspirits = Requires Fury skill activated
    //	cartboost = Requires a Pushcart and Cart Boost skill activated
    //	shield = Requires a 0,shield equipped
    //	warg = Requires a Warg
    //	dragon = Requires to ride a Dragon
    //	ridingwarg = Requires to ride a Warg
    //	mado = Requires to have an active mado
    //	poisonweapon = Requires to be under Poisoning Weapon.
    //	rollingcutter = Requires at least one Rotation Counter from Rolling Cutter.
    //	elementalspirit = Requires to have an Elemental Spirit summoned.
    //	mh_fighting = Requires Eleanor fighthing mode
    //	mh_grappling = Requires Eleanor grappling mode
    //	peco = Requires riding a peco
    // 12 Spirit sphere cos
    

     

    8443,0,0,25: 30: 35: 40: 45: 50: 55: 60: 65: 70,0,0,0,0,0,0,0,0,0,0,0,0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
     

     

    Isso define que:
    Earth Bolt requer 25 SP no nível 1, 30 SP no nível 2 .. 70 SP no nível 10. Pode ser lançado com qualquer arma, não requer nenhum estado e não requer nenhum item para ser consumido.
    ===========================================================================
    ** p/ Hercules.
     
    Skill_db.txt
     

    {
    	// ------------------------------ Mandatory Fields ----------------------------
    	Id: ID                                      (int)     (Required)
    	Name: "Skill Name"                          (string)  (Required)
    	MaxLevel: Skill Level                       (int)     (Required)
    	// ------------------------------ Optional Fields -----------------------------
    	Description: "Skill Description"            (string)  (optional but recommended)
    	Range: Skill Range                          (int) (optional, defaults to 0) (can be grouped by Levels)
    	                                            Note: Range < 5 is considered Melee range.
    	Hit: Hit Type                               (int) (optional, default "BDT_NORMAL")
    	                                            Types - "BDT_SKILL", "BDT_MULTIHIT" or "BDT_NORMAL"
    	SkillType: {                                (bool, defaults to "Passive")
    		Passive: true/false                     (boolean, defaults to false)
    		Enemy: true/false                       (boolean, defaults to false)
    		Place: true/false                       (boolean, defaults to false)
    		Self: true/false                        (boolean, defaults to false)
    		Friend: true/false                      (boolean, defaults to false)
    		Trap: true/false                        (boolean, defaults to false)
    	}
    	SkillInfo: {                                (bool, defaults to "None")
    		Quest: true/false                       (boolean, defaults to false)
    		NPC: true/false                         (boolean, defaults to false)
    		Wedding: true/false                     (boolean, defaults to false)
    		Spirit: true/false                      (boolean, defaults to false)
    		Guild: true/false                       (boolean, defaults to false)
    		Song: true/false                        (boolean, defaults to false)
    		Ensemble: true/false                    (boolean, defaults to false)
    		Trap: true/false                        (boolean, defaults to false)
    		TargetSelf: true/false                  (boolean, defaults to false)
    		NoCastSelf: true/false                  (boolean, defaults to false)
    		PartyOnly: true/false                   (boolean, defaults to false)
    		GuildOnly: true/false                   (boolean, defaults to false)
    		NoEnemy: true/false                     (boolean, defaults to false)
    		IgnoreLandProtector: true/false         (boolean, defaults to false)
    		Chorus: true/false                      (boolean, defaults to false)
    		FreeCastReduced: true/false             (boolean, defaults to false)
    							Works like skill SA_FREECAST, allow move and attack with reduced speed.
    		FreeCastNormal: true/false              (boolean, defaults to false)
    							Works like FreeCastReduced, but not reduce speed.
    	}
    	AttackType: "Attack Type"                   (string, defaults to "None")
    	                                            Types: "None", "Weapon", "Magic" or "Misc"
    	Element: "Element Type"                     (string) (Optional field - Default "Ele_Neutral")
    	                                            (can be grouped by Levels)
    	                                            Types: "Ele_Neutral", "Ele_Water", "Ele_Earth", "Ele_Fire", "Ele_Wind"
    	                                            "Ele_Poison", "Ele_Holy", "Ele_Dark", "Ele_Ghost", "Ele_Undead"
    	                                            "Ele_Weapon" - Uses weapon's element.
    	                                            "Ele_Endowed" - Uses Endowed element.
    	                                            "Ele_Random" - Uses random element.
    	DamageType: {                               (bool, default to "NoDamage")
    		NoDamage: true/false                     No damage skill
    		SplashArea: true/false                   Has splash area (requires source modification)
    		SplitDamage: true/false                  Damage should be split among targets (requires 'SplashArea' in order to work)
    		IgnoreCards: true/false                  Skill ignores caster's % damage cards (misc type always ignores)
    		IgnoreElement: true/false                Skill ignores elemental adjustments
    		IgnoreDefense: true/false                Skill ignores target's defense (misc type always ignores)
    		IgnoreFlee: true/false                   Skill ignores target's flee (magic type always ignores)
    		IgnoreDefCards: true/false               Skill ignores target's def cards
    	}
    	SplashRange: Damage Splash Area             (int, defaults to 0) (can be grouped by Levels)
    	                                            Note: -1 for screen-wide.
    	NumberOfHits: Number of Hits                (int, defaults to 1) (can be grouped by Levels)
    	                                            Note: when positive, damage is increased by hits,
    	                                            negative values just show number of hits without
    	                                            increasing total damage.
    	InterruptCast: Cast Interruption            (bool, defaults to false)
    	CastDefRate: Cast Defense Reduction         (int, defaults to 0)
    	SkillInstances: Skill instances             (int, defaults to 0) (can be grouped by Levels)
    	                                            Notes: max amount of skill instances to place on the ground when
    	                                            player_land_skill_limit/monster_land_skill_limit is enabled. For skills
    	                                            that attack using a path, this is the path length to be used.
    	KnockBackTiles: Knock-back by 'n' Tiles     (int, defaults to 0) (can be grouped by Levels)
    	CastTime: Skill cast Time (in ms)           (int, defaults to 0) (can be grouped by Levels)
    	AfterCastActDelay: Skill Delay (in ms)      (int, defaults to 0) (can be grouped by Levels)
    	AfterCastWalkDelay: Walk Delay (in ms)      (int, defaults to 0) (can be grouped by Levels)
    	SkillData1: Skill Data/Duration (in ms)     (int, defaults to 0) (can be grouped by Levels)
    	SkillData2: Skill Data/Duration (in ms)     (int, defaults to 0) (can be grouped by Levels)
    	CoolDown: Skill Cooldown (in ms)            (int, defaults to 0) (can be grouped by Levels)
    	FixedCastTime: Fixed Cast Time (in ms)      (int, defaults to 0) (can be grouped by Levels)
    	                                            Note: when 0, uses 20% of cast time and less than
    	                                            0 means no fixed cast time.
    	CastTimeOptions: {
    		IgnoreDex: true/false                   (boolean, defaults to false)
    		IgnoreStatusEffect: true/false          (boolean, defaults to false)
    		IgnoreItemBonus: true/false             (boolean, defaults to false)
    		                                        Note: Delay setting 'IgnoreDex' only makes sense when
    		                                        delay_dependon_dex is enabled.
    	}
    	SkillDelayOptions: {
    		IgnoreDex: true/false                   (boolean, defaults to false)
    		IgnoreStatusEffect: true/false          (boolean, defaults to false)
    		IgnoreItemBonus: true/false             (boolean, defaults to false)
    		                                        Note: Delay setting 'IgnoreDex' only makes sense when
    		                                        delay_dependon_dex is enabled.
    	}
    	Requirements: {
    		HPCost: HP Cost                         (int, defaults to 0) (can be grouped by Levels)
    		SPCost: SP Cost                         (int, defaults to 0) (can be grouped by Levels)
    		HPRateCost: HP % Cost                   (int, defaults to 0) (can be grouped by Levels)
    		                                        Note: If positive, it is a percent of your current hp,
    		                                        otherwise it is a percent of your max hp.
    		SPRateCost: SP % Cost                   (int, defaults to 0) (can be grouped by Levels)
    		                                        Note: If positive, it is a percent of your current sp,
    		                                        otherwise it is a percent of your max sp.
    		ZenyCost: Zeny Cost                     (int, defaults to 0) (can be grouped by Levels)
    		WeaponTypes: {                          (bool or string, defaults to "All")
    			NoWeapon: true/false                (boolean, defaults to false)
    			Daggers: true/false                 (boolean, defaults to false)
    			1HSwords: true/false                (boolean, defaults to false)
    			2HSwords: true/false                (boolean, defaults to false)
    			1HSpears: true/false                (boolean, defaults to false)
    			2HSpears: true/false                (boolean, defaults to false)
    			1HAxes: true/false                  (boolean, defaults to false)
    			2HAxes: true/false                  (boolean, defaults to false)
    			Maces: true/false                   (boolean, defaults to false)
    			2HMaces: true/false                 (boolean, defaults to false)
    			Staves: true/false                  (boolean, defaults to false)
    			Bows: true/false                    (boolean, defaults to false)
    			Knuckles: true/false                (boolean, defaults to false)
    			Instruments: true/false             (boolean, defaults to false)
    			Whips: true/false                   (boolean, defaults to false)
    			Books: true/false                   (boolean, defaults to false)
    			Katars: true/false                  (boolean, defaults to false)
    			Revolvers: true/false               (boolean, defaults to false)
    			Rifles: true/false                  (boolean, defaults to false)
    			GatlingGuns: true/false             (boolean, defaults to false)
    			Shotguns: true/false                (boolean, defaults to false)
    			GrenadeLaunchers: true/false        (boolean, defaults to false)
    			FuumaShurikens: true/false          (boolean, defaults to false)
    			2HStaves: true/false                (boolean, defaults to false)
    			MaxSingleWeaponType: true/false     (boolean, defaults to false)
    			DWDaggers: true/false               (boolean, defaults to false)
    			DWSwords: true/false                (boolean, defaults to false)
    			DWAxes: true/false                  (boolean, defaults to false)
    			DWDaggerSword: true/false           (boolean, defaults to false)
    			DWDaggerAxe: true/false             (boolean, defaults to false)
    			DWSwordAxe: true/false              (boolean, defaults to false)
    		}
    		AmmoTypes: {                            (for all types use string "All")
    			A_ARROW: true/false                 (boolean, defaults to false)
    			A_DAGGER: true/false                (boolean, defaults to false)
    			A_BULLET: true/false                (boolean, defaults to false)
    			A_SHELL: true/false                 (boolean, defaults to false)
    			A_GRENADE: true/false               (boolean, defaults to false)
    			A_SHURIKEN: true/false              (boolean, defaults to false)
    			A_KUNAI: true/false                 (boolean, defaults to false)
    			A_CANNONBALL: true/false            (boolean, defaults to false)
    			A_THROWWEAPON: true/false           (boolean, defaults to false)
    		}
    		AmmoAmount: Ammunition Amount           (int, defaults to 0) (can be grouped by Levels)
    		State: "Required State"                 (string, defaults to "None") (can be grouped by Levels)
    		                                        Types : 'None' = Nothing special
    		                                        'Moveable' = Requires to be able to move
    		                                        'NotOverWeight' = Requires to be less than 50% weight
    		                                        'InWater' = Requires to be standing on a water cell
    		                                        'Cart' = Requires a Pushcart
    		                                        'Riding' = Requires to ride either a peco or a dragon
    		                                        'Falcon' = Requires a Falcon
    		                                        'Sight' = Requires Sight skill activated
    		                                        'Hiding' = Requires Hiding skill activated
    		                                        'Cloaking' = Requires Cloaking skill activated
    		                                        'ExplosionSpirits' = Requires Fury skill activated
    		                                        'CartBoost' = Requires a Pushcart and Cart Boost skill activated
    		                                        'Shield' = Requires a 0,shield equipped
    		                                        'Warg' = Requires a Warg
    		                                        'Dragon' = Requires to ride a Dragon
    		                                        'RidingWarg' = Requires to ride a Warg
    		                                        'Mado' = Requires to have an active mado
    		                                        'PoisonWeapon' = Requires to be under Poisoning Weapon.
    		                                        'RollingCutter' = Requires at least one Rotation Counter from Rolling Cutter.
    		                                        'ElementalSpirit' = Requires to have an Elemental Spirit summoned.
    		                                        'MH_Fighting' = Requires Eleanor fighthing mode
    		                                        'MH_Grappling' = Requires Eleanor grappling mode
    		                                        'Peco' = Requires riding a peco
    		SpiritSphereCost: Spirit Sphere Cost    (int, defaults to 0) (can be grouped by Levels)
    		Items: {
    			ItemID or Aegis_Name : Amount       (int, defaults to 0) (can be grouped by Levels)
    			                                    Item example: "ID717" or "Blue_Gemstone".
    			                                    Notes: Items with amount 0 will not be consumed.
    			                                    Amount can also be grouped by levels.
    		}
    	}
    	Unit: {
    		Id: [ UnitID, UnitID2 ]                 (int, defaults to 0) (can be grouped by Levels)
    		Layout: Unit Layout                     (int, defaults to 0) (can be grouped by Levels)
    		Range: Unit Range                       (int, defaults to 0) (can be grouped by Levels)
    		Interval: Unit Interval                 (int, defaults to 0) (can be grouped by Levels)
    		Target: "Unit Target"                   (string, defaults to "None")
    		                                        Types:
    		                                        All             - affects everyone
    		                                        NotEnemy        - affects anyone who isn't an enemy
    		                                        Friend          - affects party, guildmates and neutral players
    		                                        Party           - affects party only
    		                                        Guild           - affects guild only
    		                                        Ally            - affects party and guildmates only
    		                                        Sameguild       - affects guild but not allies
    		                                        Enemy           - affects enemies only
    		                                        None            - affects nobody
    		Flag: {
    			UF_DEFNOTENEMY: true/false          (boolean, defaults to false)
    			UF_NOREITERATION: true/false        (boolean, defaults to false)
    			UF_NOFOOTSET: true/false            (boolean, defaults to false)
    			UF_NOOVERLAP: true/false            (boolean, defaults to false)
    			UF_PATHCHECK: true/false            (boolean, defaults to false)
    			UF_NOPC: true/false                 (boolean, defaults to false)
    			UF_NOMOB: true/false                (boolean, defaults to false)
    			UF_SKILL: true/false                (boolean, defaults to false)
    			UF_DANCE: true/false                (boolean, defaults to false)
    			UF_ENSEMBLE: true/false             (boolean, defaults to false)
    			UF_SONG: true/false                 (boolean, defaults to false)
    			UF_DUALMODE: true/false             (boolean, defaults to false)
    			UF_RANGEDSINGLEUNI: true/false      (boolean, defaults to false)
    		}
    	}
    }

     

     

     

    {
        Id: 8443
        Name: "MG_EARTHBOLT"
        Description: "Earth Bolt"
        MaxLevel: 10
        Range: 9
        Hit: "BDT_MULTIHIT"
        SkillType: {
            Enemy: true
        }
            }
        AttackType: "Magic"
        Element: "Ele_Earth"
        NumberOfHits: {
            Lv1: 1
            Lv2: 2
            Lv3: 3
            Lv4: 4
            Lv5: 5
            Lv6: 6
            Lv7: 7
            Lv8: 8
            Lv9: 9
            Lv10: 10
        }
        InterruptCast: true
        CastTime: {
            Lv1: 640
            Lv2: 960
            Lv3: 1280
            Lv4: 1600
            Lv5: 1920
            Lv6: 2100
            Lv7: 1560
            Lv8: 2880
            Lv9: 3200
            Lv10: 3520
        }
        AfterCastActDelay: {
            Lv1: 1000
            Lv2: 1200
            Lv3: 1400
            Lv4: 1600
            Lv5: 1800
            Lv6: 2000
            Lv7: 2200
            Lv8: 2400
            Lv9: 2600
            Lv10: 2800
        }
        FixedCastTime: {
            Lv1: 160
            Lv2: 240
            Lv3: 320
            Lv4: 400
            Lv5: 480
            Lv6: 700
            Lv7: 640
            Lv8: 720
            Lv9: 800
            Lv10: 880
        }
        Requirements: {
            SPCost: {
                Lv1: 25
                Lv2: 50
                Lv3: 75
                Lv4: 100
                Lv5: 125
                Lv6: 150
                Lv7: 175
                Lv8: 200
                Lv9: 225
                Lv10: 250
            }
        }
    },
     

     

     

    ===========================================================================
     
    Skill_tree.txt
     
    Esta parte do banco de dados não é necessária se não for lida por uma classe. No entanto, se você quiser que uma classe aprenda uma habilidade, você deve fazer uma entrada em skill_tree.txt. Um exemplo abaixo:

    Job_Name: { // Job names as in src/map/pc.c (they are hardcoded at the moment so if you want to add a new job you should add it there)
    	inherit: ( "Other_Job_Name" ); // Base job from which this job will inherit its skill tree. NV_TRICKDEAD inheritance is skipped for non-novices from the source
    
    	skills: { // SKILL_NAMEs come from the Name (16th column) value in db/re/skill_db.txt
    		SKILL_NAME1: Max_Level // Use this for skills that don't have other skill prerequisite; Max_Level is a numeric value that should match your client side files
    		SKILL_NAME2: { // Use this for skills which have other skills as prerequisites
    			MaxLevel: Max_Level // Max_Level is a numeric value that should match your client side files
    			SKILL_NAME_PREREQUISITE: Level_Prerequisite // The prerequisite skill and min level for having this skill available. Should also match your client side files
    			SKILL_NAME_PREREQUISITE2: Level_Prerequisite2 // You can add as many prerequisite skills as you want. Minimum of 1 if you add a skill this way
    	}
    }

     

    MG_EARTHBOLT: {
    MaxLevel: 10
    MG_FIREBOLT: 5
    MG_LIGHTNINGBOLT: 5
    }
     
    Isso define que:
    Earth Bolt pode ser aprendido por Mago, tem um nível máximo de 10 (para esta classe), e requer habilidade MG_FIREBOLT no nível 5 e habilidade MG_LIGHTNINGBOLT no nível 5.
    Tecnicamente, estas são as partes geralmente utilizas com arquivos de banco de dados de habilidade. Há mais, mas isso ficará pra vocês explorarem.
     
    Arquivos .lua e .lub
     
    As seguintes implementações estão de acordo com a Revisão 228 do Projeto Lua (2012-05-23).
    A implementação é diferente entre muitas versões de cliente, mas geralmente há 2 implementações:
     
    Sem arquivos skillinfoz
     
    Em data/lua files/skillinfo/skilltreeview.lua encontre:
    {"MG_FIREWALL", 18; Pos = 19, MaxLv = 10, NeedSkillList = {6, 12}}
    

    Adicione a baixo:

    {"MG_EARTHBOLT",8443; Pos = 20, MaxLv = 10, NeedSkillList = {19,20}}
    

     

    Com arquivos skillinfoz
     
    Em skillid.lua encontre:
    ECLAGE_RECALL = 3035,
    

    Depois adicione:

    MG_EARTHBOLT = 8443,
    

    in data/lua files/skillinfo/skilldescript.lua localize:

    [SKID.MG_THUNDERSTORM] = {
    
    		"Thunder Storm",
    		"Max Level:^777777 10 ^000000",
    		"Type:^777777 Offensive ^000000",
    		"SP Cost:^777777 24 + 5*SkillLV ^000000",
    		"Target:^777777 cell ^000000",
    		"Range:^777777 9 cells ^000000",
    		"Cast Time:^777777 1*SkillLV sec ^000000",
    		"Cool Down:^777777 2 sec ^000000",
    		"Duration:^777777 0.2*SkillLV sec ^000000",
    		"Effect:^777777 Hits every Enemy in a 5x5 area around the targeted cell with 1 Wind Element Bolt per level at a rate of 1 bolt every 0.2 seconds. Each bolt does 0.8*MATK Wind element damage. ^000000",
    		"[LV 1]^777777 1 Bolt ^000000",
    		"[LV 2]^777777 2 Bolts ^000000",
    		"[LV 3]^777777 3 Bolts ^000000",
    		"[LV 4]^777777 4 Bolts ^000000",
    		"[LV 5]^777777 5 Bolts ^000000",
    		"[LV 6]^777777 6 Bolts ^000000",
    		"[LV 7]^777777 7 Bolts ^000000",
    		"[LV 8]^777777 8 Bolts ^000000",
    		"[LV 9]^777777 9 Bolts ^000000",
    		"[LV 10]^777777 10 Bolts ^000000",
    	},
    

    Depois adicione:

    	[SKID.MG_EARTHBOLT] = {
    		"Earth Bolt",
    		"Max Level:^777777 10 ^000000"
    		"Type:^77777 Active ^000000"
    		"SP Cost:^777777 20 + 5*SkillLV ^000000"
    		"Target:^777777 1 Enemy ^000000"
    		"Cast Time:^777777 2 sec ^000000"
    		"Cool Down:^777777 1 sec ^000000"
    		"Duration:^777777 Instant ^000000"
    		"Effect: ^777777 Deals SkillLV bolts of Earth magic damage to one enemy, at 150% MATK per hit.^000000",
    	},
    

    skilltreeview.lua mude:

    [JOBID.JT_MAGICIAN] = {
    		[1] = SKID.MG_STONECURSE,
    		[2] = SKID.MG_COLDBOLT,
    		[3] = SKID.MG_LIGHTNINGBOLT,
    		[4] = SKID.MG_NAPALMBEAT,
    		[5] = SKID.MG_FIREBOLT,
    		[6] = SKID.MG_SIGHT,
    		[8] = SKID.MG_SRECOVERY,
    		[9] = SKID.MG_FROSTDIVER,
    		[10] = SKID.MG_THUNDERSTORM,
    		[11] = SKID.MG_SOULSTRIKE,
    		[12] = SKID.MG_FIREBALL,
    		[13] = SKID.MG_ENERGYCOAT,
    		[18] = SKID.MG_SAFETYWALL,
    		[19] = SKID.MG_FIREWALL
    	},	
    

     para:

    [JOBID.JT_MAGICIAN] = {
    		[1] = SKID.MG_STONECURSE,
    		[2] = SKID.MG_COLDBOLT,
    		[3] = SKID.MG_LIGHTNINGBOLT,
    		[4] = SKID.MG_NAPALMBEAT,
    		[5] = SKID.MG_FIREBOLT,
    		[6] = SKID.MG_SIGHT,
    		[8] = SKID.MG_SRECOVERY,
    		[9] = SKID.MG_FROSTDIVER,
    		[10] = SKID.MG_THUNDERSTORM,
    		[11] = SKID.MG_SOULSTRIKE,
    		[12] = SKID.MG_FIREBALL,
    		[13] = SKID.MG_ENERGYCOAT,
    		[18] = SKID.MG_SAFETYWALL,
    		[19] = SKID.MG_FIREWALL,
    		[20] = SKID.MG_EARTHBOLT
    	},
    

    skillinfolist.lua Mude:

    	[SKID.ECL_SEQUOIADUST] = {
    		"ECL_SEQUOIADUST";
    		SkillName = "Sequoia Dust",
    		MaxLv = 1,
    		SpAmount = { 0 },
    		bSeperateLv = false,
    		AttackRange = { 7 },
    	}
    

    Para:

    	[SKID.ECL_SEQUOIADUST] = {
    		"ECL_SEQUOIADUST";
    		SkillName = "Sequoia Dust",
    		MaxLv = 1,
    		SpAmount = { 0 },
    		bSeperateLv = false,
    		AttackRange = { 7 },
    	},
    	[SKID.MG_EARTHBOLT] = {
    		"MG_EARTHBOLT";
    		SkillName = "Earth Bolt",
    		MaxLv = 10,
    		SpAmount = { 25, 30, 35, 40, 45, 50, 55, 60, 65, 70 },
    		_NeedSkillList = {
    			{ SKID.MG_FIREBOLT, 5},
    			{ SKID.MG_LIGHTNINGBOLT, 5}
    		}
    
    Finalizando
     
    Não se esqueça que você precisará de adicionar o arquivo Sprite e BMP apropriado para a habilidade. Use o nome MG_EARTHBOLT como o nome do arquivo em:
    data\texture\À¯ÀúÀÎÅÍÆäÀ̽º\item
    data\sprite\¾ÆÀÌÅÛ
     
    Efeitos
     

    Vá a src/map/skill.h, Procure a skill que deseja adicionar/editar o efeito:

     

            case WE_BABY:
                if(sd) {
                    struct map_session_data *f_sd = pc->get_father(sd);
                    struct map_session_data *m_sd = pc->get_mother(sd);
                    bool we_baby_parents = false;
                    if(m_sd && check_distance_bl(bl,&m_sd->bl,AREA_SIZE)) {
                        sc_start(src,&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
                        clif->specialeffect(&m_sd->bl,408,AREA);
                        we_baby_parents = true;
                    }
     
     
    Aqui está sendo utilizado como exemplo a habilidade de convocação das classes bebês. Onde 408 é o efeito adicionado para que seja mostrado ao utilizar a skill. Para a sua habilidade customizada, como ela é uma habilidade nova, não há nenhum efeito, então você terá que adicioná-lo ao arquivo, seguindo de exemplo a mesma forma mostrada acima. Para saber a lista de todos os efeitos, basta utilizar doc/effect_list.txt.
     
     
    Fontes e créditos
     
     
    Comentários
     
    Decidi fazer esse tutorial pois percebi que ainda não há nenhum guia com esse assunto em PT-BR e havia uma grande demanda de pessoas procurando. Tinha dado uma olhada no Hercules e percebi que é um bom tutorial, mas ainda estava incompleto e bem desatualizado, então decidi usa-lo como base e também pensei, por que não criar um?
    Espero que esteja de boa compreensão, caso estiver faltando algo que eu esqueci ou que eu não saiba, por favor me informe para torná-lo o melhor possível.
    Estou aberto a sugestões e críticas construtivas. Façam um bom proveito  ;)

  15. It would be wiser to post errors in English, if asking for help in English...

     

    I don't speak this language...

     

    I'm sorry. I had forgotten. Now it has been fixed. Tested with today's version of Hercules.

     

    Severity	Code	Description	Project	File	Line	Suppression State
    Warning	C4018	'<=': signed/unsigned mismatch	char-server	hercules\src\char\int_party.c	320	
    Warning	C4013	'GET_SYMBOL' undefined; assuming extern returning int	autopots	Hercules\src\plugins\autopots.c	267	
    Warning	C4047	'=': 'clif_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	267	
    Warning	C4047	'=': 'script_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	268	
    Warning	C4047	'=': 'pc_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	269	
    Warning	C4047	'=': 'atcommand_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	270	
    Warning	C4047	'=': 'map_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	271	
    Warning	C4047	'=': 'unit_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	272	
    Warning	C4047	'=': 'timer_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	273	
    Warning	C4047	'=': 'itemdb_interface *' differs in levels of indirection from 'int'	autopots	Hercules\src\plugins\autopots.c	274	
    Warning	C4013	'hookStop' undefined; assuming extern returning int	maintenance	Hercules\src\plugins\maintenance.c	205	
    Warning	C4013	'addHookPre' undefined; assuming extern returning int	maintenance	Hercules\src\plugins\maintenance.c	550	
    Warning	C4018	'<=': signed/unsigned mismatch	market	Hercules\src\plugins\market.c	259	
    Warning	C4018	'<=': signed/unsigned mismatch	market	Hercules\src\plugins\market.c	290	
    Warning	C4018	'<=': signed/unsigned mismatch	market	Hercules\src\plugins\market.c	309	
    Warning	C4013	'hookStop' undefined; assuming extern returning int	noitem	Hercules\src\plugins\noitem.c	107	
    Warning	C4013	'addHookPre' undefined; assuming extern returning int	noitem	Hercules\src\plugins\noitem.c	190	
    Warning	C4013	'addHookPost' undefined; assuming extern returning int	noitem	Hercules\src\plugins\noitem.c	192	
    Error	LNK2019	unresolved external symbol _GET_SYMBOL referenced in function _plugin_init	autopots	Hercules\vcproj-14\autopots.obj	1	
    Error	MSB6006	"link.exe" exited with code 1120.	maintenance	C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets	638	
    Error	MSB6006	"link.exe" exited with code 1120.	autopots	C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets	638	
    Error	MSB6006	"link.exe" exited with code 1120.	noitem	C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets	638	
    Error	LNK2019	unresolved external symbol _hookStop referenced in function _pc_authok_pre	maintenance	Hercules\vcproj-14\maintenance.obj	1	
    Error	LNK1120	1 unresolved externals	autopots	Hercules\plugins\autopots.dll	1	
    Error	LNK2019	unresolved external symbol _hookStop referenced in function _npc_parse_unknown_mapflag_pre	noitem	Hercules\vcproj-14\noitem.obj	1	
    Error	LNK2019	unresolved external symbol _addHookPre referenced in function _plugin_init	maintenance	Hercules\vcproj-14\maintenance.obj	1	
    Error	LNK2019	unresolved external symbol _addHookPre referenced in function _plugin_init	noitem	Hercules\vcproj-14\noitem.obj	1	
    Error	LNK1120	2 unresolved externals	maintenance	Hercules\plugins\maintenance.dll	1	
    Error	LNK2019	unresolved external symbol _addHookPost referenced in function _plugin_init	noitem	Hercules\vcproj-14\noitem.obj	1	
    Error	LNK1120	3 unresolved externals	noitem	Hercules\plugins\noitem.dll	1	
    Warning	C4715	'buildin_storageadditem': not all control paths return a value	storageadditem	hercules\src\plugins\storageadditem.c	72	
    Error	C1083	Cannot open include file: 'common/malloc.h': No such file or directory	partyscript	Hercules\src\plugins\partyscript.c	13	

  16. There was no update here for quite a while, but clans is actually ready and full configurable. You can set an inactivity timer, buffs and also add custom clans. Adel made a small image pack for a custom clan (which I attach upon the release).

    There is some last testing and then we show it to Haru and hope for a quick merge. Afterwards I do a topic about how everything works.

     

    Will it be possible to create new fake guilds without editing in source?

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.