diff options
120 files changed, 1503 insertions, 656 deletions
@@ -178,6 +178,7 @@ non npc nsstrunks nyankochan +orn p Paradox924X Peter Kieser @@ -202,6 +203,7 @@ Sel shadow shadoweathena shadowlady +shazeya Shinigami shinomori Shinryo @@ -227,8 +229,10 @@ Tharis Theia theultramage tk44 +ToastOfDoom toms Toshi^2 +Trancid Trojal Tsuyuki V&S @@ -239,6 +243,7 @@ whitedog Wizputer Wolf Xgear +Yhn Yommy Yor Yuuki diff --git a/conf/login-server.conf b/conf/login-server.conf index 5a5a3e049..06e0eb18b 100644 --- a/conf/login-server.conf +++ b/conf/login-server.conf @@ -136,14 +136,21 @@ dnsbl_servers: bl.blocklist.de, socks.dnsbl.sorbs.net // Client MD5 hash check // If turned on, the login server will check if the client's hash matches // the value below, and will not connect tampered clients. -// Note: see doc\md5_hashcheck.txt for more details. +// Note: see doc/md5_hashcheck.txt for more details. client_hash_check: off // Client MD5 hashes -// A player can login with a client hash at or below the account group_id. +// The client with the specified hash can be used to log in by players with +// a group_id equal to or greater than the given value. +// If you specify 'disabled' as hash, players with a group_id greater than or +// equal to the given value will be able to log in regardless of hash (and even +// if their client does not send a hash at all.) // Format: group_id, hash -client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5 -client_hash: 99, cb1ea78023d337c38e8ba5124e2338ae +// Note: see doc/md5_hashcheck.txt for more details. +//client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5 +//client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae +//client_hash: 99, disabled + import: conf/inter-server.conf import: conf/import/login_conf.txt diff --git a/db/const.txt b/db/const.txt index 9a590ac50..577fbc2fc 100644 --- a/db/const.txt +++ b/db/const.txt @@ -1373,25 +1373,6 @@ MOB_ELEMENT 20 MOB_MODE 21 MOB_MVPEXP 22 -AI_ACTION_TYPE 0 -AI_ACTION_TAR_TYPE 1 -AI_ACTION_TAR 2 -AI_ACTION_SRC 3 -AI_ACTION_TAR_TYPE_PC 1 -AI_ACTION_TAR_TYPE_MOB 2 -AI_ACTION_TAR_TYPE_PET 4 -AI_ACTION_TAR_TYPE_HOMUN 8 -AI_ACTION_TAR_TYPE_ITEM 16 -AI_ACTION_TYPE_NPCCLICK 256 -AI_ACTION_TYPE_ATTACK 128 -AI_ACTION_TYPE_DETECT 64 -AI_ACTION_TYPE_DEAD 32 -AI_ACTION_TYPE_ASSIST 16 -AI_ACTION_TYPE_KILL 8 -AI_ACTION_TYPE_UNLOCK 4 -AI_ACTION_TYPE_WALKACK 2 -AI_ACTION_TYPE_WARPACK 1 - ALL_CLIENT 0 ALL_SAMEMAP 1 AREA 2 diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index d401b1b08..d5e5fc513 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -874,7 +874,7 @@ 2314,1,6,1,-1,0,0,1,1,no,0,0,0,weapon,0, LG_RAGEBURST,Rage Burst 2315,0,6,4,0,0x2,3,3,1,yes,0,0,0,none,2, LG_SHIELDSPELL,Shield Spell 2316,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, LG_EXEEDBREAK,Exceed Break -2317,1,6,2,-1,0x2,5,5,1,yes,0,0,0,none,3:4:5:6:7, LG_OVERBRAND,Over Brand //CHECK I know the splash is needed somehow for the strange AoE it gives. +2317,2,6,2,-1,0x2,0,5,1,yes,0,0,0,weapon,0, LG_OVERBRAND,Over Brand 2318,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, LG_PRESTIGE,Prestige 2319,0,6,4,0,0x1,3,5,1,no,0,0,0,weapon,0, LG_BANDING,Banding //CHECK Splash isnt needed right? Banding has its own UNIT ID. 2320,0,6,4,-1,0x2,3,5,1,yes,0,0,0,weapon,0, LG_MOONSLASHER,Moon Slasher @@ -883,6 +883,7 @@ 2323,0,8,4,2,0x2,1:1:2:2:3,5,-5,yes,0,0,0,weapon,0, LG_EARTHDRIVE,Earth Drive 2324,3,8,1,-1,0,0,5,3,yes,0,0,0,weapon,0, LG_HESPERUSLIT,Hesperus Lit 2325,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, LG_INSPIRATION,Inspiration +2519,1,6,1,-1,0x2,0,5,1,yes,0,0,0,weapon,3:4:5:6:7, LG_OVERBRAND_BRANDISH,Over Brand //**** // SR Sura diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index d7d0fe63c..6a3f83e5e 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -886,7 +886,7 @@ 2314,1,6,1,-1,0,0,1,1,no,0,0,0,weapon,0, LG_RAGEBURST,Rage Burst 2315,0,6,4,0,0x2,3,3,1,yes,0,0,0,none,2, LG_SHIELDSPELL,Shield Spell 2316,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, LG_EXEEDBREAK,Exceed Break -2317,1,6,2,-1,0x2,5,5,1,yes,0,0,0,none,3:4:5:6:7, LG_OVERBRAND,Over Brand //CHECK I know the splash is needed somehow for the strange AoE it gives. +2317,2,6,2,-1,0x2,0,5,1,yes,0,0,0,weapon,0, LG_OVERBRAND,Over Brand 2318,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, LG_PRESTIGE,Prestige 2319,0,6,4,0,0x1,3,5,1,no,0,0,0,weapon,0, LG_BANDING,Banding //CHECK Splash isnt needed right? Banding has its own UNIT ID. 2320,0,6,4,-1,0x2,3,5,1,yes,0,0,0,weapon,0, LG_MOONSLASHER,Moon Slasher @@ -895,6 +895,7 @@ 2323,0,8,4,2,0x2,1:1:2:2:3,5,-5,yes,0,0,0,weapon,0, LG_EARTHDRIVE,Earth Drive 2324,3,8,1,-1,0,0,5,3,yes,0,0,0,weapon,0, LG_HESPERUSLIT,Hesperus Lit 2325,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, LG_INSPIRATION,Inspiration +2519,1,6,1,-1,0x2,0,5,1,yes,0,0,0,weapon,3:4:5:6:7, LG_OVERBRAND_BRANDISH,Over Brand //**** // SR Sura diff --git a/doc/md5_hashcheck.txt b/doc/md5_hashcheck.txt index 779785638..d9064b1ab 100644 --- a/doc/md5_hashcheck.txt +++ b/doc/md5_hashcheck.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= Hercules Dev Team //===== Current Version: ===================================== -//= 20120921 +//= 20140208 //===== Description: ========================================= //= This file outlines the login server's MD5 hash check. //============================================================ @@ -13,26 +13,46 @@ This will ensure that a user has not tampered with the client and that the client is the one specific to your server. The client can only send the correct MD5 hash to the server on certain -server types, so a client diff is required to ensure the hash is sent. -A link containing the required WeeDiffGen plugin can be found at: -http://rathena.org/board/topic/70841-r16771-client-md5-hash-check/ +server types, so a client diff may be required to ensure the hash is +sent. +Please refer to your client diff tool manual for the appropriate patch +(i.e. in NEMO it's called "Force Send Client Hash Packet", in other +tools or diffs it may have similar names.) -The settings for the hash check are located in conf\login.conf: +The serverside settings for the hash check are located in +conf/login.conf: // Client MD5 hash check // If turned on, the login server will check if the client's hash matches // the value below, and will not connect tampered clients. -// Note: see doc\md5_hashcheck.txt for more details. +// Note: see doc/md5_hashcheck.txt for more details. client_hash_check: off // Client MD5 hashes -// A player can login with a client hash at or below the account group_id. +// The client with the specified hash can be used to log in by players with +// a group_id equal to or greater than the given value. +// If you specify 'disabled' as hash, players with a group_id greater than or +// equal to the given value will be able to log in regardless of hash (and even +// if their client does not send a hash at all.) // Format: group_id, hash +// Note: see doc/md5_hashcheck.txt for more details. client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5 -client_hash: 99, cb1ea78023d337c38e8ba5124e2338ae +client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae +client_hash: 99, disabled -To enable MD5 hash checks, set 'client_hash_check' to 'on'. -The 'client_hash' group_id can be any of the groups in conf\groups.conf, -and is particularly useful if you wanted to allow GMs a different client -than normal players; for example, a GM client could be hexed differently -with dual-clienting enabled and chat flood disabled. +To enable MD5 hash checks, set 'client_hash_check' to 'on' and add one +'client_hash' entry for each client you want to use. +The group_id can be any of the groups in conf/groups.conf, and it is +useful in case if you want to allow GMs to use a different client +than normal players; for example, a GM client could be hexed +differently, perhaps with dual-clienting enabled and chat flood +disabled. +You will need to replace the example MD5 hashes with the actual hash of +your client. +You can use any MD5 hash tools to generate it, e.g.: +- md5sum (command line) on linux +- WinMD5 on Windows +- md5 (command line) on Mac OS X +- If you hexed your client with NEMO (version 2.0 and above), you + can find the MD5 hash of the generated client automatically saved to + client_filename.exe.secure.txt diff --git a/doc/script_commands.txt b/doc/script_commands.txt index c0b848663..6a48692e8 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -638,7 +638,7 @@ even a value from an another array) to get at an array value: This will make @arrayofnumbers[100] equal to 10. Notice that index numbering always starts with 0. Arrays can hold over -4 billion variables. +2 billion variables. And array indexes probably can't be negative. Nobody tested what happens when you try to get a negatively numbered variable from an array, but it's @@ -4939,21 +4939,17 @@ the command will end silently. --------------------------------------- -*successrefitem <equipment slot>; +*successrefitem <equipment slot>{,<upgrade_count>}; This command will refine an item in the specified equipment slot of the -invoking character by +1. For a list of equipment slots see 'getequipid'. -This command will not only add the +1, but also display a 'refine success' +invoking character by +1 (unless <upgrade_count> is specified). +For a list of equipment slots see 'getequipid'. +This command will also display a 'refine success' effect on the character and put appropriate messages into their chat window. It will also give the character fame points if a weapon reached +10 this way, even though these will only take effect for blacksmith who will later forge a weapon. -The official scripts seems to use the 'successrefitem' command as a -function instead: 'successrefitem(<number>)' but it returns nothing on the -stack. This is since jAthena, so probably nobody knows for sure why is it -so. - --------------------------------------- *failedrefitem <equipment slot>; @@ -7359,20 +7355,31 @@ setitemscript 2637,""; --------------------------------------- -*atoi ("<string>") -*axtoi ("<string>") +*atoi("<string>") +*axtoi("<string>") +*strtol("string", base) These commands are used to convert strings to numbers. 'atoi' will interpret given string as a decimal number (base 10), while 'axtoi' -interprets strings as hexadecimal numbers (base 16). +interprets strings as hexadecimal numbers (base 16). 'strtol' lets +the user specify a base (valid range is between 2 and 36 inclusive, +or the special value0, which means auto-detection). -Hexadecimal number set: {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F} +The atoi and strtol functions conform to the C functions with the same +names, and axtoi is the same as strtol, with a base of 16. Results are +clamped to signed 32 bit int range (INT_MIN ~ INT_MAX) Example: -set @var, atoi("11"); // Sets @var to 11 -set @var, axtoi("FF"); // Sets @var to 255 -mes axtoi("11"); // Displays 17 (1 = 1, 10 = 16) +.@var = atoi("11"); // Sets .@var to 11 +.@var = axtoi("FF"); // Sets .@var to 255 +mes axtoi("11"); // Displays 17 (1 = 1, 10 = 16) +.@var = strtol("11", 10); // Sets .@var to 11 (11 base 10) +.@var = strtol("11", 16); // Sets .@var to 17 (11 base 16) +.@var = strtol("11", 0); // Sets .@var to 11 (11 base 10, auto-detected) +.@var = strtol("0x11", 0); // Sets .@var to 17 (11 base 16, auto-detected because of the "0x" prefix) +.@var = strtol("011", 0); // Sets .@var to 9 (11 base 8, auto-detected because of the "0" prefix) +.@var = strtol("11", 2); // Sets .@var to 3 (binary 11) --------------------------------------- diff --git a/src/char/char.c b/src/char/char.c index 4079e10bb..4ea1f8451 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -3718,6 +3718,40 @@ int parse_frommap(int fd) RFIFOFLUSH(fd); } break; + + /* individual sc data insertion/update */ + case 0x2740: + if( RFIFOREST(fd) < 28 ) + return 0; + else { + int account_id = RFIFOL(fd, 2), char_id = RFIFOL(fd, 6), + val1 = RFIFOL(fd, 12), val2 = RFIFOL(fd, 16), + val3 = RFIFOL(fd, 20), val4 = RFIFOL(fd, 24); + short type = RFIFOW(fd, 10); + + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`char_id`,`type`,`tick`,`val1`,`val2`,`val3`,`val4`) VALUES ('%d','%d','%d',-1,'%d','%d','%d','%d')", + scdata_db, account_id, char_id, type, val1, val2, val3, val4) ) + Sql_ShowDebug(sql_handle); + + RFIFOSKIP(fd, 28); + } + break; + + /* individual sc data delete */ + case 0x2741: + if( RFIFOREST(fd) < 12 ) + return 0; + else { + int account_id = RFIFOL(fd, 2), char_id = RFIFOL(fd, 6); + short type = RFIFOW(fd, 10); + + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id` = '%d' AND `type` = '%d' LIMIT 1", + scdata_db, account_id, char_id, type) ) + Sql_ShowDebug(sql_handle); + + RFIFOSKIP(fd, 12); + } + break; default: diff --git a/src/char/char.h b/src/char/char.h index 1fb3b543f..372af91f7 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _CHAR_SQL_H_ -#define _CHAR_SQL_H_ +#ifndef _COMMON_CHAR_H_ +#define _COMMON_CHAR_H_ #include "../config/core.h" #include "../common/core.h" // CORE_ST_LAST @@ -122,4 +122,4 @@ void global_accreg_to_login_start (int account_id, int char_id); void global_accreg_to_login_send (void); void global_accreg_to_login_add (const char *key, unsigned int index, intptr_t val, bool is_string); -#endif /* _CHAR_SQL_H_ */ +#endif /* _COMMON_CHAR_H_ */ diff --git a/src/char/int_auction.h b/src/char/int_auction.h index bf26b152c..f10794f73 100644 --- a/src/char/int_auction.h +++ b/src/char/int_auction.h @@ -1,12 +1,12 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_AUCTION_SQL_H_ -#define _INT_AUCTION_SQL_H_ +#ifndef _CHAR_INT_AUCTION_H_ +#define _CHAR_INT_AUCTION_H_ int inter_auction_parse_frommap(int fd); int inter_auction_sql_init(void); void inter_auction_sql_final(void); -#endif /* _INT_AUCTION_SQL_H_ */ +#endif /* _CHAR_INT_AUCTION_H_ */ diff --git a/src/char/int_elemental.h b/src/char/int_elemental.h index 7eb5c2958..c90891fc4 100644 --- a/src/char/int_elemental.h +++ b/src/char/int_elemental.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_ELEMENTAL_SQL_H_ -#define _INT_ELEMENTAL_SQL_H_ +#ifndef _CHAR_INT_ELEMENTAL_H_ +#define _CHAR_INT_ELEMENTAL_H_ struct s_elemental; @@ -12,4 +12,4 @@ int inter_elemental_parse_frommap(int fd); bool mapif_elemental_delete(int ele_id); -#endif /* _INT_ELEMENTAL_SQL_H_ */ +#endif /* _CHAR_INT_ELEMENTAL_H_ */ diff --git a/src/char/int_guild.h b/src/char/int_guild.h index 47c42dcc5..4eb7d310b 100644 --- a/src/char/int_guild.h +++ b/src/char/int_guild.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_GUILD_SQL_H_ -#define _INT_GUILD_SQL_H_ +#ifndef _CHAR_INT_GUILD_H_ +#define _CHAR_INT_GUILD_H_ enum { GS_BASIC = 0x0001, @@ -34,4 +34,4 @@ int inter_guild_charname_changed(int guild_id,int account_id, int char_id, char int inter_guild_CharOnline(int char_id, int guild_id); int inter_guild_CharOffline(int char_id, int guild_id); -#endif /* _INT_GUILD_SQL_H_ */ +#endif /* _CHAR_INT_GUILD_H_ */ diff --git a/src/char/int_homun.h b/src/char/int_homun.h index 1c0d76269..561dc848f 100644 --- a/src/char/int_homun.h +++ b/src/char/int_homun.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_HOMUN_SQL_H_ -#define _INT_HOMUN_SQL_H_ +#ifndef _CHAR_INT_HOMUN_H_ +#define _CHAR_INT_HOMUN_H_ struct s_homunculus; @@ -15,4 +15,4 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd); bool mapif_homunculus_delete(int homun_id); bool mapif_homunculus_rename(char *name); -#endif /* _INT_HOMUN_SQL_H_ */ +#endif /* _CHAR_INT_HOMUN_H_ */ diff --git a/src/char/int_mail.h b/src/char/int_mail.h index 77db51e5b..7c06cdc1f 100644 --- a/src/char/int_mail.h +++ b/src/char/int_mail.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_MAIL_SQL_H_ -#define _INT_MAIL_SQL_H_ +#ifndef _CHAR_INT_MAIL_H_ +#define _CHAR_INT_MAIL_H_ int inter_mail_parse_frommap(int fd); void mail_sendmail(int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item); @@ -13,4 +13,4 @@ void inter_mail_sql_final(void); int mail_savemessage(struct mail_message* msg); void mapif_Mail_new(struct mail_message *msg); -#endif /* _INT_MAIL_SQL_H_ */ +#endif /* _CHAR_INT_MAIL_H_ */ diff --git a/src/char/int_mercenary.h b/src/char/int_mercenary.h index 01e4a841f..b614b8cf7 100644 --- a/src/char/int_mercenary.h +++ b/src/char/int_mercenary.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_MERCENARY_SQL_H_ -#define _INT_MERCENARY_SQL_H_ +#ifndef _CHAR_INT_MERCENARY_H_ +#define _CHAR_INT_MERCENARY_H_ struct s_mercenary; @@ -17,4 +17,4 @@ bool mercenary_owner_delete(int char_id); bool mapif_mercenary_delete(int merc_id); -#endif /* _INT_MERCENARY_SQL_H_ */ +#endif /* _CHAR_INT_MERCENARY_H_ */ diff --git a/src/char/int_party.h b/src/char/int_party.h index d8cdcdc6a..84f00635a 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_PARTY_SQL_H_ -#define _INT_PARTY_SQL_H_ +#ifndef _CHAR_INT_PARTY_H_ +#define _CHAR_INT_PARTY_H_ //Party Flags on what to save/delete. enum { @@ -23,4 +23,4 @@ int inter_party_leave(int party_id,int account_id, int char_id); int inter_party_CharOnline(int char_id, int party_id); int inter_party_CharOffline(int char_id, int party_id); -#endif /* _INT_PARTY_SQL_H_ */ +#endif /* _CHAR_INT_PARTY_H_ */ diff --git a/src/char/int_pet.h b/src/char/int_pet.h index 733468c77..a16cb7a37 100644 --- a/src/char/int_pet.h +++ b/src/char/int_pet.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_PET_SQL_H_ -#define _INT_PET_SQL_H_ +#ifndef _CHAR_INT_PET_H_ +#define _CHAR_INT_PET_H_ struct s_pet; @@ -18,4 +18,4 @@ int inter_pet_sql_init(void); //Exported for use in the TXT-SQL converter. int inter_pet_tosql(int pet_id, struct s_pet *p); -#endif /* _INT_PET_SQL_H_ */ +#endif /* _CHAR_INT_PET_H_ */ diff --git a/src/char/int_quest.h b/src/char/int_quest.h index b0403f436..6267c74ad 100644 --- a/src/char/int_quest.h +++ b/src/char/int_quest.h @@ -1,10 +1,10 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _QUEST_H_ -#define _QUEST_H_ +#ifndef _CHAR_QUEST_H_ +#define _CHAR_QUEST_H_ int inter_quest_parse_frommap(int fd); -#endif +#endif /* _CHAR_QUEST_H_ */ diff --git a/src/char/int_storage.h b/src/char/int_storage.h index 811608f82..1693499a5 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _INT_STORAGE_SQL_H_ -#define _INT_STORAGE_SQL_H_ +#ifndef _CHAR_INT_STORAGE_H_ +#define _CHAR_INT_STORAGE_H_ struct storage_data; struct guild_storage; @@ -19,4 +19,4 @@ int storage_fromsql(int account_id, struct storage_data* p); int storage_tosql(int account_id,struct storage_data *p); int guild_storage_tosql(int guild_id, struct guild_storage *p); -#endif /* _INT_STORAGE_SQL_H_ */ +#endif /* _CHAR_INT_STORAGE_H_ */ diff --git a/src/char/inter.h b/src/char/inter.h index aa47496a1..b484a1610 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _INTER_SQL_H_ -#define _INTER_SQL_H_ +#ifndef _CHAR_INTER_H_ +#define _CHAR_INTER_H_ struct accreg; #include "../common/sql.h" @@ -42,4 +42,4 @@ uint64 inter_chk_lastuid(int8 flag, uint64 value); #define updateLastUid(val_) #endif -#endif /* _INTER_SQL_H_ */ +#endif /* _CHAR_INTER_H_ */ diff --git a/src/char/pincode.h b/src/char/pincode.h index a17f70de5..3b71eec7c 100644 --- a/src/char/pincode.h +++ b/src/char/pincode.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _PINCODE_H_ -#define _PINCODE_H_ +#ifndef _CHAR_PINCODE_H_ +#define _CHAR_PINCODE_H_ #include "char.h" @@ -40,4 +40,4 @@ struct pincode_interface *pincode; void pincode_defaults(void); -#endif /* _PINCODE_H_ */ +#endif /* _CHAR_PINCODE_H_ */ diff --git a/src/common/HPM.c b/src/common/HPM.c index 1edf24901..bd2ce93ab 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -116,6 +116,8 @@ struct hplugin *hplugin_load(const char* filename) { bool anyEvent = false; void **import_symbol_ref; Sql **sql_handle; + unsigned int *HPMDataCheckLen; + struct s_HPMDataCheck *HPMDataCheck; if( HPM->exists(filename) ) { ShowWarning("HPM:plugin_load: attempting to load duplicate '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); @@ -203,6 +205,24 @@ struct hplugin *hplugin_load(const char* filename) { if( !HPM->populate(plugin,filename) ) return NULL; + if( !( HPMDataCheckLen = plugin_import(plugin->dll, "HPMDataCheckLen", unsigned int *) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheckLen' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h, skipping...\n", filename); + HPM->unload(plugin); + return NULL; + } + + if( !( HPMDataCheck = plugin_import(plugin->dll, "HPMDataCheck", struct s_HPMDataCheck *) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheck' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h, skipping...\n", filename); + HPM->unload(plugin); + return NULL; + } + + if( HPM->DataCheck && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,plugin->info->name) ) { + ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' failed DataCheck, out of sync from the core (recompile plugin), skipping...\n", filename); + HPM->unload(plugin); + return NULL; + } + /* id */ plugin->hpi->pid = plugin->idx; /* core */ @@ -255,6 +275,12 @@ void hplugins_config_read(void) { const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name FILE *fp; +// uncomment once login/char support is wrapped up +// if( !HPM->DataCheck ) { +// ShowError("HPM:config_read: HPM->DataCheck not set! Failure\n"); +// return; +// } + /* yes its ugly, its temporary and will be gone as soon as the new inter-server.conf is set */ if( (fp = fopen("conf/import/plugins.conf","r")) ) { config_filename = "conf/import/plugins.conf"; @@ -829,4 +855,5 @@ void hpm_defaults(void) { HPM->grabHPData = hplugins_grabHPData; HPM->grabHPDataSub = NULL; HPM->parseConf = hplugins_parse_conf; + HPM->DataCheck = NULL; } diff --git a/src/common/HPM.h b/src/common/HPM.h index 393f8f819..52ad24a03 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -1,8 +1,8 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _HPM_H_ -#define _HPM_H_ +#ifndef _COMMON_HPM_H_ +#define _COMMON_HPM_H_ #include "../common/cbasetypes.h" #include "../common/HPMi.h" @@ -146,10 +146,12 @@ struct HPM_interface { bool (*grabHPDataSub) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr); /* for custom config parsing */ bool (*parseConf) (const char *w1, const char *w2, enum HPluginConfType point); + /* validates plugin data */ + bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, char *name); } HPM_s; struct HPM_interface *HPM; void hpm_defaults(void); -#endif /* _HPM_H_ */ +#endif /* _COMMON_HPM_H_ */ diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h new file mode 100644 index 000000000..48089964d --- /dev/null +++ b/src/common/HPMDataCheck.h @@ -0,0 +1,130 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// +// NOTE: This file was auto-generated and should never be manually edited, +// as it will get overwritten. +#ifndef _HPM_DATA_CHECK_H_ +#define _HPM_DATA_CHECK_H_ + + +HPExport const struct s_HPMDataCheck HPMDataCheck[] = { + #ifdef _COMMON_CONF_H_ + { "libconfig_interface", sizeof(struct libconfig_interface) }, + #else + #define _COMMON_CONF_H_ + #endif // _COMMON_CONF_H_ + #ifdef _COMMON_DB_H_ + { "DBData", sizeof(struct DBData) }, + { "DBIterator", sizeof(struct DBIterator) }, + { "DBMap", sizeof(struct DBMap) }, + #else + #define _COMMON_DB_H_ + #endif // _COMMON_DB_H_ + #ifdef _COMMON_DES_H_ + { "BIT64", sizeof(struct BIT64) }, + #else + #define _COMMON_DES_H_ + #endif // _COMMON_DES_H_ + #ifdef _COMMON_ERS_H_ + { "eri", sizeof(struct eri) }, + #else + #define _COMMON_ERS_H_ + #endif // _COMMON_ERS_H_ + #ifdef _COMMON_MAPINDEX_H_ + { "mapindex_interface", sizeof(struct mapindex_interface) }, + #else + #define _COMMON_MAPINDEX_H_ + #endif // _COMMON_MAPINDEX_H_ + #ifdef _COMMON_MMO_H_ + { "quest", sizeof(struct quest) }, + #else + #define _COMMON_MMO_H_ + #endif // _COMMON_MMO_H_ + #ifdef _COMMON_SOCKET_H_ + { "socket_interface", sizeof(struct socket_interface) }, + #else + #define _COMMON_SOCKET_H_ + #endif // _COMMON_SOCKET_H_ + #ifdef _COMMON_STRLIB_H_ + { "StringBuf", sizeof(struct StringBuf) }, + { "s_svstate", sizeof(struct s_svstate) }, + #else + #define _COMMON_STRLIB_H_ + #endif // _COMMON_STRLIB_H_ + #ifdef _MAP_ATCOMMAND_H_ + { "AliasInfo", sizeof(struct AliasInfo) }, + { "atcommand_interface", sizeof(struct atcommand_interface) }, + #else + #define _MAP_ATCOMMAND_H_ + #endif // _MAP_ATCOMMAND_H_ + #ifdef _MAP_BATTLE_H_ + { "Damage", sizeof(struct Damage) }, + { "battle_interface", sizeof(struct battle_interface) }, + #else + #define _MAP_BATTLE_H_ + #endif // _MAP_BATTLE_H_ + #ifdef _MAP_BUYINGSTORE_H_ + { "buyingstore_interface", sizeof(struct buyingstore_interface) }, + { "s_buyingstore_item", sizeof(struct s_buyingstore_item) }, + #else + #define _MAP_BUYINGSTORE_H_ + #endif // _MAP_BUYINGSTORE_H_ + #ifdef _MAP_CHRIF_H_ + { "auth_node", sizeof(struct auth_node) }, + #else + #define _MAP_CHRIF_H_ + #endif // _MAP_CHRIF_H_ + #ifdef _MAP_CLIF_H_ + { "clif_interface", sizeof(struct clif_interface) }, + #else + #define _MAP_CLIF_H_ + #endif // _MAP_CLIF_H_ + #ifdef _MAP_ELEMENTAL_H_ + { "elemental_skill", sizeof(struct elemental_skill) }, + #else + #define _MAP_ELEMENTAL_H_ + #endif // _MAP_ELEMENTAL_H_ + #ifdef _MAP_GUILD_H_ + { "eventlist", sizeof(struct eventlist) }, + #else + #define _MAP_GUILD_H_ + #endif // _MAP_GUILD_H_ + #ifdef _MAP_MAP_H_ + { "map_data_other_server", sizeof(struct map_data_other_server) }, + #else + #define _MAP_MAP_H_ + #endif // _MAP_MAP_H_ + #ifdef _MAP_PACKETS_STRUCT_H_ + { "EQUIPSLOTINFO", sizeof(struct EQUIPSLOTINFO) }, + #else + #define _MAP_PACKETS_STRUCT_H_ + #endif // _MAP_PACKETS_STRUCT_H_ + #ifdef _MAP_PC_H_ + { "autotrade_vending", sizeof(struct autotrade_vending) }, + { "item_cd", sizeof(struct item_cd) }, + #else + #define _MAP_PC_H_ + #endif // _MAP_PC_H_ + #ifdef _MAP_SCRIPT_H_ + { "Script_Config", sizeof(struct Script_Config) }, + { "script_interface", sizeof(struct script_interface) }, + #else + #define _MAP_SCRIPT_H_ + #endif // _MAP_SCRIPT_H_ + #ifdef _MAP_SEARCHSTORE_H_ + { "searchstore_interface", sizeof(struct searchstore_interface) }, + #else + #define _MAP_SEARCHSTORE_H_ + #endif // _MAP_SEARCHSTORE_H_ + #ifdef _MAP_SKILL_H_ + { "skill_cd", sizeof(struct skill_cd) }, + { "skill_condition", sizeof(struct skill_condition) }, + { "skill_interface", sizeof(struct skill_interface) }, + { "skill_unit_save", sizeof(struct skill_unit_save) }, + #else + #define _MAP_SKILL_H_ + #endif // _MAP_SKILL_H_ +}; +HPExport unsigned int HPMDataCheckLen = ARRAYLENGTH(HPMDataCheck); + +#endif /* _HPM_DATA_CHECK_H_ */ diff --git a/src/common/HPMi.h b/src/common/HPMi.h index fdb6ccf52..95037fd14 100644 --- a/src/common/HPMi.h +++ b/src/common/HPMi.h @@ -1,8 +1,8 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _HPMi_H_ -#define _HPMi_H_ +#ifndef _COMMON_HPMI_H_ +#define _COMMON_HPMI_H_ #include "../common/cbasetypes.h" #include "../common/core.h" @@ -20,7 +20,7 @@ struct map_session_data; #define HPExport #endif -#ifndef _SHOWMSG_H_ +#ifndef _COMMON_SHOWMSG_H_ HPExport void (*ShowMessage) (const char *, ...); HPExport void (*ShowStatus) (const char *, ...); HPExport void (*ShowSQL) (const char *, ...); @@ -45,6 +45,11 @@ struct hplugin_info { char* req_version; }; +struct s_HPMDataCheck { + char *name; + unsigned int size; +}; + HPExport void *(*import_symbol) (char *name, unsigned int pID); HPExport Sql *mysql_handle; @@ -187,8 +192,8 @@ HPExport struct HPMi_interface { /* pc group permission */ void (*addPCGPermission) (unsigned int pluginID, char *name, unsigned int *mask); } HPMi_s; -#ifndef _HPM_H_ +#ifndef _COMMON_HPM_H_ HPExport struct HPMi_interface *HPMi; #endif -#endif /* _HPMi_H_ */ +#endif /* _COMMON_HPMI_H_ */ diff --git a/src/common/atomic.h b/src/common/atomic.h index 5a2ddb4f0..c2227a9d4 100644 --- a/src/common/atomic.h +++ b/src/common/atomic.h @@ -1,8 +1,8 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _rA_ATOMIC_H_ -#define _rA_ATOMIC_H_ +#ifndef _COMMON_ATOMIC_H_ +#define _COMMON_ATOMIC_H_ // Atomic Operations // (Interlocked CompareExchange, Add .. and so on ..) @@ -144,4 +144,4 @@ static forceinline int32 InterlockedExchange(volatile int32 *target, int32 val){ #endif //endif compiler decission -#endif +#endif /* _COMMON_ATOMIC_H_ */ diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index 977897506..654334a9b 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -1,5 +1,5 @@ -#ifndef _CBASETYPES_H_ -#define _CBASETYPES_H_ +#ifndef _COMMON_CBASETYPES_H_ +#define _COMMON_CBASETYPES_H_ /* +--------+-----------+--------+---------+ * | ILP32 | LP64 | ILP64 | (LL)P64 | @@ -431,4 +431,4 @@ void SET_FUNCPOINTER(T1& var, T2 p) #endif -#endif /* _CBASETYPES_H_ */ +#endif /* _COMMON_CBASETYPES_H_ */ diff --git a/src/common/conf.h b/src/common/conf.h index 05e2b1ada..9aff3df47 100644 --- a/src/common/conf.h +++ b/src/common/conf.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _CONF_H_ -#define _CONF_H_ +#ifndef _COMMON_CONF_H_ +#define _COMMON_CONF_H_ #include "../common/cbasetypes.h" #include "../../3rdparty/libconfig/libconfig.h" @@ -94,4 +94,4 @@ struct libconfig_interface *libconfig; void libconfig_defaults(void); -#endif // _CONF_H_ +#endif // _COMMON_CONF_H_ diff --git a/src/common/console.h b/src/common/console.h index 1beed964a..513c769ff 100644 --- a/src/common/console.h +++ b/src/common/console.h @@ -1,8 +1,8 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _CONSOLE_H_ -#define _CONSOLE_H_ +#ifndef _COMMON_CONSOLE_H_ +#define _COMMON_CONSOLE_H_ #include "../common/thread.h" #include "../common/mutex.h" @@ -72,4 +72,4 @@ struct console_interface *console; void console_defaults(void); -#endif /* _CONSOLE_H_ */ +#endif /* _COMMON_CONSOLE_H_ */ diff --git a/src/common/core.h b/src/common/core.h index 8fdcdcfc3..72f956e1d 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _CORE_H_ -#define _CORE_H_ +#ifndef _COMMON_CORE_H_ +#define _COMMON_CORE_H_ #include "../common/db.h" #include "../common/mmo.h" @@ -50,4 +50,4 @@ enum E_CORE_ST { /// If NULL, runflag is set to CORE_ST_STOP instead. extern void (*shutdown_callback)(void); -#endif /* _CORE_H_ */ +#endif /* _COMMON_CORE_H_ */ diff --git a/src/common/db.h b/src/common/db.h index c00489b93..67abe6f19 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -39,8 +39,8 @@ * @encoding US-ASCII * * @see common#db.c * \*****************************************************************************/ -#ifndef _DB_H_ -#define _DB_H_ +#ifndef _COMMON_DB_H_ +#define _COMMON_DB_H_ #include "../common/cbasetypes.h" #include <stdarg.h> @@ -1548,4 +1548,4 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...); -#endif /* _DB_H_ */ +#endif /* _COMMON_DB_H_ */ diff --git a/src/common/des.h b/src/common/des.h index e42136436..3f55448ba 100644 --- a/src/common/des.h +++ b/src/common/des.h @@ -1,7 +1,7 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _DES_H_ -#define _DES_H_ +#ifndef _COMMON_DES_H_ +#define _COMMON_DES_H_ /// One 64-bit block. @@ -12,4 +12,4 @@ void des_decrypt_block(BIT64* block); void des_decrypt(unsigned char* data, size_t size); -#endif // _DES_H_ +#endif // _COMMON_DES_H_ diff --git a/src/common/ers.h b/src/common/ers.h index d74ee02a5..4dae19f3b 100644 --- a/src/common/ers.h +++ b/src/common/ers.h @@ -37,8 +37,8 @@ * @author Flavio @ Amazon Project * * @encoding US-ASCII * \*****************************************************************************/ -#ifndef _ERS_H_ -#define _ERS_H_ +#ifndef _COMMON_ERS_H_ +#define _COMMON_ERS_H_ #include "../common/cbasetypes.h" @@ -180,4 +180,4 @@ void ers_report(void); void ers_force_destroy_all(void); #endif /* DISABLE_ERS / not DISABLE_ERS */ -#endif /* _ERS_H_ */ +#endif /* _COMMON_ERS_H_ */ diff --git a/src/common/grfio.h b/src/common/grfio.h index a88b20393..4f5d0d6bc 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _GRFIO_H_ -#define _GRFIO_H_ +#ifndef _COMMON_GRFIO_H_ +#define _COMMON_GRFIO_H_ void grfio_init(const char* fname); void grfio_final(void); @@ -14,4 +14,4 @@ unsigned long grfio_crc32(const unsigned char *buf, unsigned int len); int decode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen); int encode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen); -#endif /* _GRFIO_H_ */ +#endif /* _COMMON_GRFIO_H_ */ diff --git a/src/common/malloc.h b/src/common/malloc.h index 19b5213bb..7309bb0f7 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _MALLOC_H_ -#define _MALLOC_H_ +#ifndef _COMMON_MALLOC_H_ +#define _COMMON_MALLOC_H_ #include "../common/cbasetypes.h" @@ -88,4 +88,4 @@ struct malloc_interface { void memmgr_report (int extra); struct malloc_interface *iMalloc; -#endif /* _MALLOC_H_ */ +#endif /* _COMMON_MALLOC_H_ */ diff --git a/src/common/mapindex.h b/src/common/mapindex.h index 98150f441..fa9b9e920 100644 --- a/src/common/mapindex.h +++ b/src/common/mapindex.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAPINDEX_H_ -#define _MAPINDEX_H_ +#ifndef _COMMON_MAPINDEX_H_ +#define _COMMON_MAPINDEX_H_ #include "../common/db.h" #include "../common/mmo.h" @@ -90,4 +90,4 @@ struct mapindex_interface *mapindex; void mapindex_defaults(void); -#endif /* _MAPINDEX_H_ */ +#endif /* _COMMON_MAPINDEX_H_ */ diff --git a/src/common/md5calc.h b/src/common/md5calc.h index 323affa2c..d0caf6787 100644 --- a/src/common/md5calc.h +++ b/src/common/md5calc.h @@ -1,8 +1,8 @@ -#ifndef _MD5CALC_H_ -#define _MD5CALC_H_ +#ifndef _COMMON_MD5CALC_H_ +#define _COMMON_MD5CALC_H_ void MD5_String(const char * string, char * output); void MD5_Binary(const char * string, unsigned char * output); void MD5_Salt(unsigned int len, char * output); -#endif /* _MD5CALC_H_ */ +#endif /* _COMMON_MD5CALC_H_ */ diff --git a/src/common/mmo.h b/src/common/mmo.h index 573962601..2b66c516c 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MMO_H_ -#define _MMO_H_ +#ifndef _COMMON_MMO_H_ +#define _COMMON_MMO_H_ #include "cbasetypes.h" #include "../common/db.h" @@ -886,4 +886,4 @@ enum e_pc_reg_loading { #error MAX_ZENY is too big #endif -#endif /* _MMO_H_ */ +#endif /* _COMMON_MMO_H_ */ diff --git a/src/common/mutex.h b/src/common/mutex.h index 1999627cd..eeb24e6ff 100644 --- a/src/common/mutex.h +++ b/src/common/mutex.h @@ -1,8 +1,8 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _rA_MUTEX_H_ -#define _rA_MUTEX_H_ +#ifndef _COMMON_MUTEX_H_ +#define _COMMON_MUTEX_H_ typedef struct ramutex *ramutex; // Mutex @@ -89,4 +89,4 @@ void racond_signal( racond c ); void racond_broadcast( racond c ); -#endif +#endif /* _COMMON_MUTEX_H_ */ diff --git a/src/common/nullpo.h b/src/common/nullpo.h index 581252cca..fb1cf0feb 100644 --- a/src/common/nullpo.h +++ b/src/common/nullpo.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef COMMON_NULLPO_H -#define COMMON_NULLPO_H +#ifndef _COMMON_NULLPO_H_ +#define _COMMON_NULLPO_H_ #include "../common/cbasetypes.h" @@ -125,4 +125,4 @@ void assert_report(const char *file, int line, const char *func, const char *targetname, const char *title); -#endif /* COMMON_NULLPO_H */ +#endif /* _COMMON_NULLPO_H_ */ diff --git a/src/common/random.h b/src/common/random.h index 43dfd36c0..ab83fb4d4 100644 --- a/src/common/random.h +++ b/src/common/random.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _RANDOM_H_ -#define _RANDOM_H_ +#ifndef _COMMON_RANDOM_H_ +#define _COMMON_RANDOM_H_ #include "../common/cbasetypes.h" @@ -15,4 +15,4 @@ int32 rnd_value(int32 min, int32 max);// [min, max] double rnd_uniform(void);// [0.0, 1.0) double rnd_uniform53(void);// [0.0, 1.0) -#endif /* _RANDOM_H_ */ +#endif /* _COMMON_RANDOM_H_ */ diff --git a/src/common/showmsg.h b/src/common/showmsg.h index 01eae4480..49fbc34fb 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -2,10 +2,10 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _SHOWMSG_H_ -#define _SHOWMSG_H_ +#ifndef _COMMON_SHOWMSG_H_ +#define _COMMON_SHOWMSG_H_ -#ifndef _HPMi_H_ +#ifndef _COMMON_HPMI_H_ #include "../../3rdparty/libconfig/libconfig.h" #endif @@ -90,7 +90,7 @@ enum msg_type { }; extern void ClearScreen(void); -#ifndef _HPMi_H_ +#ifndef _COMMON_HPMI_H_ extern void ShowMessage(const char *, ...); extern void ShowStatus(const char *, ...); extern void ShowSQL(const char *, ...); @@ -104,4 +104,4 @@ extern void ClearScreen(void); #endif extern int _vShowMessage(enum msg_type flag, const char *string, va_list ap); -#endif /* _SHOWMSG_H_ */ +#endif /* _COMMON_SHOWMSG_H_ */ diff --git a/src/common/socket.h b/src/common/socket.h index 6879d2e90..ca9141716 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _SOCKET_H_ -#define _SOCKET_H_ +#ifndef _COMMON_SOCKET_H_ +#define _COMMON_SOCKET_H_ #include "../common/cbasetypes.h" @@ -196,4 +196,4 @@ void socket_defaults(void); #define set_eof(fd) ( sockt->set_eof(fd) ) #endif /* _H_SOCKET_C_ */ -#endif /* _SOCKET_H_ */ +#endif /* _COMMON_SOCKET_H_ */ diff --git a/src/common/spinlock.h b/src/common/spinlock.h index 9b9e4ce94..29fbb355b 100644 --- a/src/common/spinlock.h +++ b/src/common/spinlock.h @@ -1,6 +1,6 @@ #pragma once -#ifndef _rA_SPINLOCK_H_ -#define _rA_SPINLOCK_H_ +#ifndef _COMMON_SPINLOCK_H_ +#define _COMMON_SPINLOCK_H_ // // CAS based Spinlock Implementation @@ -101,4 +101,4 @@ static forceinline void LeaveSpinLock(PSPIN_LOCK lck){ -#endif +#endif /* _COMMON_SPINLOCK_H_ */ diff --git a/src/common/strlib.h b/src/common/strlib.h index 7a1066401..10844d257 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _STRLIB_H_ -#define _STRLIB_H_ +#ifndef _COMMON_STRLIB_H_ +#define _COMMON_STRLIB_H_ #include "../common/cbasetypes.h" #include <stdarg.h> @@ -191,4 +191,4 @@ void strlib_defaults(void); #define bin2hex(output,input,count) (strlib->bin2hex((output),(input),(count))) #endif /* STRLIB_C */ -#endif /* _STRLIB_H_ */ +#endif /* _COMMON_STRLIB_H_ */ diff --git a/src/common/thread.h b/src/common/thread.h index a5a66e954..d6b2bbc6e 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -2,8 +2,8 @@ // For more information, see LICENCE in the main folder #pragma once -#ifndef _rA_THREAD_H_ -#define _rA_THREAD_H_ +#ifndef _COMMON_THREAD_H_ +#define _COMMON_THREAD_H_ #include "../common/cbasetypes.h" @@ -116,4 +116,4 @@ void rathread_init(); void rathread_final(); -#endif +#endif /* _COMMON_THREAD_H_ */ diff --git a/src/common/timer.h b/src/common/timer.h index af1a2b036..ab3ffc21f 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -1,8 +1,10 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _TIMER_H_ -#define _TIMER_H_ + +#ifndef _COMMON_TIMER_H_ +#define _COMMON_TIMER_H_ + #include "../common/cbasetypes.h" #define DIFF_TICK(a,b) ((a)-(b)) @@ -65,4 +67,4 @@ struct timer_interface *timer; void timer_defaults(void); -#endif /* _TIMER_H_ */ +#endif /* _COMMON_TIMER_H_ */ diff --git a/src/common/utils.h b/src/common/utils.h index 719e1e533..68dd01ac4 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _UTILS_H_ -#define _UTILS_H_ +#ifndef _COMMON_UTILS_H_ +#define _COMMON_UTILS_H_ #include "../common/cbasetypes.h" #include <stdio.h> // FILE* @@ -54,4 +54,4 @@ struct HCache_interface *HCache; void HCache_defaults(void); -#endif /* _UTILS_H_ */ +#endif /* _COMMON_UTILS_H_ */ diff --git a/src/config/const.h b/src/config/const.h index fc82d66f9..6557cb987 100644 --- a/src/config/const.h +++ b/src/config/const.h @@ -1,8 +1,9 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _H_CONSTANTS_ -#define _H_CONSTANTS_ + +#ifndef _CONFIG_CONSTANTS_H_ +#define _CONFIG_CONSTANTS_H_ /** * Hercules configuration file (http://hercules.ws) @@ -117,4 +118,4 @@ /** * End of File **/ -#endif /* _H_CONSTANTS_ */ +#endif /* _CONFIG_CONSTANTS_H_ */ diff --git a/src/config/renewal.h b/src/config/renewal.h index 3b11aff74..36615d63b 100644 --- a/src/config/renewal.h +++ b/src/config/renewal.h @@ -60,6 +60,7 @@ /// - damage is NOT increased by 400% /// - it does NOT affect grimtooth /// - weapon and status ATK are increased +/// - some skill's damage ratio has modified #define RENEWAL_EDP /// renewal ASPD [malufett] diff --git a/src/config/secure.h b/src/config/secure.h index 5742ae30b..e5e3662d1 100644 --- a/src/config/secure.h +++ b/src/config/secure.h @@ -50,7 +50,7 @@ /** * Uncomment to disable * while enabled, movement of invisible (cloaking, hide, etca [not chase walk]) units is not informed to nearby foes, - * rendering any client-side cheat, that would otherwise make these units visible, to + * rendering any client-side cheat, that would otherwise make these units visible, to not function. * - "Why is this a setting?" because theres a cost, while enabled if a hidden character uses a skill with cast time, * - for example "cloaking -> walk a bit -> soul break another player" the character display will be momentarily abrupted * - on the action of unhiding (its a quick effect, ~0.007s in duration), and due to the nature of the skill cast on the client diff --git a/src/login/account.h b/src/login/account.h index 74a9e9626..234e7c0c1 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef __ACCOUNT_H_INCLUDED__ -#define __ACCOUNT_H_INCLUDED__ +#ifndef _LOGIN_ACCOUNT_H_ +#define _LOGIN_ACCOUNT_H_ #include "../common/cbasetypes.h" #include "../common/mmo.h" // ACCOUNT_REG2_NUM @@ -139,4 +139,4 @@ Sql *account_db_sql_up(AccountDB* self); void mmo_send_accreg2(AccountDB* self, int fd, int account_id, int char_id); void mmo_save_accreg2(AccountDB* self, int fd, int account_id, int char_id); -#endif // __ACCOUNT_H_INCLUDED__ +#endif /* _LOGIN_ACCOUNT_H_ */ diff --git a/src/login/ipban.h b/src/login/ipban.h index b2a1a7d9e..e6851d8dd 100644 --- a/src/login/ipban.h +++ b/src/login/ipban.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef __IPBAN_H_INCLUDED__ -#define __IPBAN_H_INCLUDED__ +#ifndef _LOGIN_IPBAN_H_ +#define _LOGIN_IPBAN_H_ #include "../common/cbasetypes.h" @@ -22,4 +22,4 @@ void ipban_log(uint32 ip); bool ipban_config_read(const char* key, const char* value); -#endif // __IPBAN_H_INCLUDED__ +#endif /* _LOGIN_IPBAN_H_ */ diff --git a/src/login/login.c b/src/login/login.c index d427641f5..252031bb8 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -1017,27 +1017,29 @@ int mmo_auth(struct login_session_data* sd, bool isServer) { } if( login_config.client_hash_check && !isServer ) { - struct client_hash_node *node = login_config.client_hash_nodes; + struct client_hash_node *node = NULL; bool match = false; - if( !sd->has_client_hash ) { - ShowNotice("Client doesn't sent client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip); - return 5; - } - - while( node ) { - if( node->group_id <= acc.group_id && memcmp(node->hash, sd->client_hash, 16) == 0 ) { + for( node = login_config.client_hash_nodes; node; node = node->next ) { + if( acc.group_id < node->group_id ) + continue; + if( *node->hash == '\0' // Allowed to login without hash + || (sd->has_client_hash && memcmp(node->hash, sd->client_hash, 16) == 0 ) // Correct hash + ) { match = true; break; } - - node = node->next; } if( !match ) { char smd5[33]; int i; + if( !sd->has_client_hash ) { + ShowNotice("Client didn't send client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip); + return 5; + } + for( i = 0; i < 16; i++ ) sprintf(&smd5[i * 2], "%02x", sd->client_hash[i]); @@ -1647,15 +1649,19 @@ int login_config_read(const char* cfgName) int i; CREATE(nnode, struct client_hash_node, 1); - for (i = 0; i < 32; i += 2) { - char buf[3]; - unsigned int byte; + if (strcmpi(md5, "disabled") == 0) { + nnode->hash[0] = '\0'; + } else { + for (i = 0; i < 32; i += 2) { + char buf[3]; + unsigned int byte; - memcpy(buf, &md5[i], 2); - buf[2] = 0; + memcpy(buf, &md5[i], 2); + buf[2] = 0; - sscanf(buf, "%x", &byte); - nnode->hash[i / 2] = (uint8)(byte & 0xFF); + sscanf(buf, "%x", &byte); + nnode->hash[i / 2] = (uint8)(byte & 0xFF); + } } nnode->group_id = group; diff --git a/src/login/login.h b/src/login/login.h index d6a021125..14c361a15 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _LOGIN_H_ -#define _LOGIN_H_ +#ifndef _LOGIN_LOGIN_H_ +#define _LOGIN_LOGIN_H_ #include "../common/mmo.h" // NAME_LENGTH,SEX_* #include "../common/core.h" // CORE_ST_LAST @@ -100,4 +100,4 @@ extern struct mmo_char_server server[MAX_SERVERS]; extern struct Login_Config login_config; -#endif /* _LOGIN_H_ */ +#endif /* _LOGIN_LOGIN_H_ */ diff --git a/src/login/loginlog.h b/src/login/loginlog.h index a1ffaae85..730fb6e62 100644 --- a/src/login/loginlog.h +++ b/src/login/loginlog.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef __LOGINLOG_H_INCLUDED__ -#define __LOGINLOG_H_INCLUDED__ +#ifndef _LOGIN_LOGINLOG_H_ +#define _LOGIN_LOGINLOG_H_ unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes); @@ -12,4 +12,4 @@ bool loginlog_final(void); bool loginlog_config_read(const char* w1, const char* w2); -#endif // __LOGINLOG_H_INCLUDED__ +#endif /* _LOGIN_LOGINLOG_H_ */ diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index 4b1338b8d..061479d87 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -5,6 +5,15 @@ #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/HPM.h" +#include "../common/conf.h" +#include "../common/db.h" +#include "../common/des.h" +#include "../common/ers.h" +#include "../common/mapindex.h" +#include "../common/mmo.h" +#include "../common/socket.h" +#include "../common/strlib.h" + #include "HPMmap.h" #include "pc.h" @@ -12,28 +21,47 @@ // #include "atcommand.h" +#include "battle.h" +#include "battleground.h" #include "chat.h" #include "chrif.h" +#include "clif.h" +#include "date.h" #include "duel.h" #include "elemental.h" +#include "guild.h" #include "homunculus.h" #include "instance.h" #include "intif.h" #include "irc-bot.h" +#include "itemdb.h" +#include "log.h" #include "mail.h" #include "mapreg.h" #include "mercenary.h" +#include "mob.h" +#include "npc.h" #include "party.h" +#include "path.h" +#include "pc_groups.h" #include "pet.h" #include "quest.h" +#include "script.h" +#include "searchstore.h" +#include "skill.h" +#include "status.h" #include "storage.h" #include "trade.h" +#include "unit.h" +#include "vending.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> +#include "../common/HPMDataCheck.h" + struct HPM_atcommand_list { //tracking currently not enabled // - requires modifying how plugins calls atcommand creation @@ -46,6 +74,11 @@ struct HPM_atcommand_list { struct HPM_atcommand_list *atcommand_list = NULL; unsigned int atcommand_list_items = 0; +/** + * (char*) data name -> (unsigned int) HPMDataCheck[] index + **/ +DBMap *datacheck_db; + bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) { /* record address */ switch( type ) { @@ -113,20 +146,27 @@ void HPM_map_atcommands(void) { } } -void HPM_map_do_final(void) { - unsigned char i; +/** + * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching! + **/ +bool HPM_map_DataCheck (struct s_HPMDataCheck *src, unsigned int size, char *name) { + unsigned int i, j; - if( atcommand_list ) - aFree(atcommand_list); - /** - * why is pcg->HPM being cleared here? because PCG's do_final is not final, - * is used on reload, and would thus cause plugin-provided permissions to go away - **/ - for( i = 0; i < pcg->HPMpermissions_count; i++ ) { - aFree(pcg->HPMpermissions[i].name); + for(i = 0; i < size; i++) { + + if( !strdb_exists(datacheck_db, src[i].name) ) { + ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name); + return false; + } else { + j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */ + if( src[i].size != HPMDataCheck[j].size ) { + ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,HPMDataCheck[j].size); + return false; + } + } } - if( pcg->HPMpermissions ) - aFree(pcg->HPMpermissions); + + return true; } /** @@ -141,3 +181,35 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in pcg->HPMpermissions[index].name = aStrdup(name); pcg->HPMpermissions[index].mask = mask; } + +void HPM_map_do_init(void) { + unsigned int i; + + /** + * Populates datacheck_db for easy lookup later on + **/ + datacheck_db = strdb_alloc(DB_OPT_BASE,0); + + for(i = 0; i < HPMDataCheckLen; i++) { + strdb_uiput(datacheck_db, HPMDataCheck[i].name, i); + } + +} + +void HPM_map_do_final(void) { + unsigned char i; + + if( atcommand_list ) + aFree(atcommand_list); + /** + * why is pcg->HPM being cleared here? because PCG's do_final is not final, + * is used on reload, and would thus cause plugin-provided permissions to go away + **/ + for( i = 0; i < pcg->HPMpermissions_count; i++ ) { + aFree(pcg->HPMpermissions[i].name); + } + if( pcg->HPMpermissions ) + aFree(pcg->HPMpermissions); + + db_destroy(datacheck_db); +} diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index ff8cf4c74..f291575fb 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -1,8 +1,8 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _HPM_MAP_ -#define _HPM_MAP_ +#ifndef _MAP_HPMMAP_H_ +#define _MAP_HPMMAP_H_ #include "../common/cbasetypes.h" #include "../map/atcommand.h" @@ -22,4 +22,8 @@ void HPM_map_do_final(void); void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask); -#endif /* _HPM_MAP_ */ +bool HPM_map_DataCheck(struct s_HPMDataCheck *src, unsigned int size, char *name); + +void HPM_map_do_init(void); + +#endif /* _MAP_HPMMAP_H_ */ diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 6177fad23..2849ada0b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -64,7 +64,7 @@ struct atcmd_binding_data* get_atcommandbind_byname(const char* name) { if( *name == atcommand->at_symbol || *name == atcommand->char_symbol ) name++; // for backwards compatibility - ARR_FIND( 0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, name) == 0 ); + ARR_FIND( 0, atcommand->binding_count, i, strcmpi(atcommand->binding[i]->command, name) == 0 ); return ( i < atcommand->binding_count ) ? atcommand->binding[i] : NULL; } diff --git a/src/map/atcommand.h b/src/map/atcommand.h index f95940924..39f7cc2b2 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _ATCOMMAND_H_ -#define _ATCOMMAND_H_ +#ifndef _MAP_ATCOMMAND_H_ +#define _MAP_ATCOMMAND_H_ #include "../common/conf.h" #include "../common/db.h" @@ -121,4 +121,4 @@ void atcommand_defaults(void); /* stay here */ #define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) -#endif /* _ATCOMMAND_H_ */ +#endif /* _MAP_ATCOMMAND_H_ */ diff --git a/src/map/battle.c b/src/map/battle.c index fd31f5a1f..1a04aeff9 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -2253,7 +2253,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block case LG_RAGEBURST: if( sc ){ skillratio += -100 + (status_get_max_hp(src) - status_get_hp(src)) / 100 + sc->fv_counter * 200; - clif->millenniumshield(sd, (sc->fv_counter = 0)); + clif->millenniumshield(src, (sc->fv_counter = 0)); } RE_LVL_DMOD(100); break; @@ -2498,12 +2498,14 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block } //Skill damage modifiers that stack linearly if(sc && skill_id != PA_SACRIFICE){ +#ifdef RENEWAL_EDP if( sc->data[SC_EDP] ){ if( skill_id == AS_SONICBLOW || skill_id == GC_COUNTERSLASH || skill_id == GC_CROSSIMPACT ) skillratio >>= 1; } +#endif if(sc->data[SC_OVERTHRUST]) skillratio += sc->data[SC_OVERTHRUST]->val3; if(sc->data[SC_OVERTHRUSTMAX]) @@ -2665,8 +2667,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sce->val3 <= 0 ) { // Shield Down sce->val2--; if( sce->val2 > 0 ) { - if( sd ) - clif->millenniumshield(sd,sce->val2); + clif->millenniumshield(bl,sce->val2); sce->val3 = 1000; // Next Shield } else status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down @@ -2932,9 +2933,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam rnd()%100 < sce->val3) status->heal(src, damage*sce->val4/100, 0, 3); - if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON + if( (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 && sc->fv_counter <= sce->val3 ) - clif->millenniumshield(sd, sc->fv_counter++); + clif->millenniumshield(bl, sc->fv_counter++); if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); @@ -3410,11 +3411,36 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); #endif if(sd) { + uint16 rskill;/* redirect skill */ //Damage bonuses if ((i = pc->skillatk_bonus(sd, skill_id))) ad.damage += ad.damage*i/100; - - if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + switch(skill_id){ + case WL_CHAINLIGHTNING_ATK: + rskill = WL_CHAINLIGHTNING; + break; + case AB_DUPLELIGHT_MAGIC: + rskill = AB_DUPLELIGHT; + break; + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + rskill = WL_TETRAVORTEX; + break; + case WL_SUMMON_ATK_FIRE: + case WL_SUMMON_ATK_WIND: + case WL_SUMMON_ATK_WATER: + case WL_SUMMON_ATK_GROUND: + rskill = WL_RELEASE; + break; + case WM_REVERBERATION_MAGIC: + rskill = WM_REVERBERATION; + break; + default: + rskill = skill_id; + } + if( (i = battle->adjust_skill_damage(src->m,rskill)) ) MATK_RATE(i); //Ignore Defense? @@ -3850,10 +3876,18 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } #endif md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); - - if (sd && (i = pc->skillatk_bonus(sd, skill_id))) - md.damage += md.damage*i/100; - + if(skill_id){ + uint16 rskill;/* redirect skill id */ + switch(skill_id){ + case GN_HELLS_PLANT_ATK: + rskill = GN_HELLS_PLANT; + break; + default: + rskill = skill_id; + } + if (sd && (i = pc->skillatk_bonus(sd, rskill))) + md.damage += md.damage*i/100; + } if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) md.damage = md.damage * i / 100; @@ -4544,6 +4578,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_ADD( 30 * tsc->data[SC_DARKCROW]->val1 ); } + if ( sc && !skill_id && sc->data[SC_EXEEDBREAK] ) { + ATK_ADDRATE(sc->data[SC_EXEEDBREAK]->val1); + status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER); + } #ifdef RENEWAL if( sd && skill_id == NJ_KUNAI ){ flag.tdef = 1; @@ -4695,9 +4733,43 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_ADDRATE(50); break; } - - if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) - ATK_RATE(i); + if( skill_id ){ + uint16 rskill;/* redirect skill id */ + switch(skill_id){ + case AB_DUPLELIGHT_MELEE: + rskill = AB_DUPLELIGHT; + break; + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + rskill = LG_OVERBRAND; + break; + case WM_SEVERE_RAINSTORM_MELEE: + rskill = WM_SEVERE_RAINSTORM; + break; + case WM_REVERBERATION_MELEE: + rskill = WM_REVERBERATION; + break; + case GN_CRAZYWEED_ATK: + rskill = GN_CRAZYWEED; + break; + case GN_SLINGITEM_RANGEMELEEATK: + rskill = GN_SLINGITEM; + break; + case RL_R_TRIP_PLUSATK: + rskill = RL_R_TRIP; + break; + case RL_B_FLICKER_ATK: + rskill = RL_FLICKER; + break; + case RL_GLITTERING_GREED_ATK: + rskill = RL_GLITTERING_GREED; + break; + default: + rskill = skill_id; + } + if( (i = battle->adjust_skill_damage(src->m,rskill)) ) + ATK_RATE(i); + } if( sd ) { if (skill_id && (i = pc->skillatk_bonus(sd, skill_id))) @@ -5533,10 +5605,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t wd = battle->calc_attack(BF_WEAPON, src, target, 0, 0, flag); if( sc && sc->count ) { - if (sc->data[SC_EXEEDBREAK]) { - ATK_RATER(sc->data[SC_EXEEDBREAK]->val1); - status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER); - } if( sc->data[SC_SPELLFIST] ) { if( --(sc->data[SC_SPELLFIST]->val1) >= 0 ){ struct Damage ad = battle->calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT); diff --git a/src/map/battle.h b/src/map/battle.h index 98f2e37e8..0fcef7292 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _BATTLE_H_ -#define _BATTLE_H_ +#ifndef _MAP_BATTLE_H_ +#define _MAP_BATTLE_H_ #include "../common/cbasetypes.h" #include "map.h" //ELE_MAX @@ -596,4 +596,4 @@ struct battle_interface { struct battle_interface *battle; void battle_defaults(void); -#endif /* _BATTLE_H_ */ +#endif /* _MAP_BATTLE_H_ */ diff --git a/src/map/battleground.h b/src/map/battleground.h index 4aeb9f879..ed7347566 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _BATTLEGROUND_H_ -#define _BATTLEGROUND_H_ +#ifndef _MAP_BATTLEGROUND_H_ +#define _MAP_BATTLEGROUND_H_ #include "../common/mmo.h" // struct party #include "clif.h" @@ -112,4 +112,4 @@ struct battleground_interface *bg; void battleground_defaults(void); -#endif /* _BATTLEGROUND_H_ */ +#endif /* _MAP_BATTLEGROUND_H_ */ diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index b0db40661..5141a1013 100644 --- a/src/map/buyingstore.h +++ b/src/map/buyingstore.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _BUYINGSTORE_H_ -#define _BUYINGSTORE_H_ +#ifndef _MAP_BUYINGSTORE_H_ +#define _MAP_BUYINGSTORE_H_ /** * Declarations @@ -70,4 +70,4 @@ struct buyingstore_interface *buyingstore; void buyingstore_defaults (void); -#endif // _BUYINGSTORE_H_ +#endif // _MAP_BUYINGSTORE_H_ diff --git a/src/map/chat.h b/src/map/chat.h index fcbadf008..71e5a11ec 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _CHAT_H_ -#define _CHAT_H_ +#ifndef _MAP_CHAT_H_ +#define _MAP_CHAT_H_ #include "map.h" // struct block_list, CHATROOM_TITLE_SIZE @@ -55,4 +55,4 @@ struct chat_interface *chat; void chat_defaults(void); -#endif /* _CHAT_H_ */ +#endif /* _MAP_CHAT_H_ */ diff --git a/src/map/chrif.c b/src/map/chrif.c index 3dc35fc68..c55b241e6 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1561,6 +1561,50 @@ void chrif_send_report(char* buf, int len) { } /** + * Sends a single scdata for saving into char server, meant to ensure integrity of durationless conditions + **/ +void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) { + + if( !chrif->fd ) + return; + + WFIFOHEAD(chrif->fd, 28); + + WFIFOW(chrif->fd, 0) = 0x2740; + WFIFOL(chrif->fd, 2) = account_id; + WFIFOL(chrif->fd, 6) = char_id; + WFIFOW(chrif->fd, 10) = type; + WFIFOL(chrif->fd, 12) = sce->val1; + WFIFOL(chrif->fd, 16) = sce->val2; + WFIFOL(chrif->fd, 20) = sce->val3; + WFIFOL(chrif->fd, 24) = sce->val4; + + WFIFOSET(chrif->fd, 28); + +} +/** + * Sends a single scdata deletion request into char server, meant to ensure integrity of durationless conditions + **/ +void chrif_del_scdata_single(int account_id, int char_id, short type) { + + if( !chrif->fd ) { + ShowError("MAYDAY! failed to delete status %d from CID:%d/AID:%d\n",type,char_id,account_id); + return; + } + + + WFIFOHEAD(chrif->fd, 12); + + WFIFOW(chrif->fd, 0) = 0x2741; + WFIFOL(chrif->fd, 2) = account_id; + WFIFOL(chrif->fd, 6) = char_id; + WFIFOW(chrif->fd, 10) = type; + + WFIFOSET(chrif->fd, 12); + +} + +/** ` * @see DBApply */ int auth_db_final(DBKey key, DBData *data, va_list ap) { @@ -1728,4 +1772,6 @@ void chrif_defaults(void) { chrif->on_ready = chrif_on_ready; chrif->on_disconnect = chrif_on_disconnect; chrif->parse = chrif_parse; + chrif->save_scdata_single = chrif_save_scdata_single; + chrif->del_scdata_single = chrif_del_scdata_single; } diff --git a/src/map/chrif.h b/src/map/chrif.h index 163fdf670..25e955604 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -2,13 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _CHRIF_H_ -#define _CHRIF_H_ +#ifndef _MAP_CHRIF_H_ +#define _MAP_CHRIF_H_ #include "../common/cbasetypes.h" #include <time.h> #include "map.h" //TBL_stuff +struct status_change_entry; + /** * Defines **/ @@ -140,6 +142,8 @@ struct chrif_interface { void (*on_ready) (void); void (*on_disconnect) (void); int (*parse) (int fd); + void (*save_scdata_single) (int account_id, int char_id, short type, struct status_change_entry *sce); + void (*del_scdata_single) (int account_id, int char_id, short type); }; struct chrif_interface *chrif; @@ -148,4 +152,4 @@ void chrif_defaults(void); // There's no need for another function when a simple macro can do exactly the same effect #define chrif_char_offline(x) chrif->char_offline_nsd((x)->status.account_id,(x)->status.char_id) -#endif /* _CHRIF_H_ */ +#endif /* _MAP_CHRIF_H_ */ diff --git a/src/map/clif.c b/src/map/clif.c index 9ae88200c..5dacf6360 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -11175,11 +11175,10 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd) /// status id: /// SP_STR ~ SP_LUK /// amount: -/// client sends always 1 for this, even when using /str+ and -/// the like -void clif_parse_StatusUp(int fd,struct map_session_data *sd) -{ - pc->statusup(sd,RFIFOW(fd,2)); +/// Old clients send always 1 for this, even when using /str+ and the like. +/// Newer clients (2013-12-23 and newer) send the correct amount. +void clif_parse_StatusUp(int fd,struct map_session_data *sd) { + pc->statusup(sd,RFIFOW(fd,2), RFIFOB(fd, 4)); } @@ -17119,15 +17118,15 @@ int clif_elementalconverter_list(struct map_session_data *sd) { /** * Rune Knight **/ -void clif_millenniumshield(struct map_session_data *sd, short shields ) { +void clif_millenniumshield(struct block_list *bl, short shields ) { #if PACKETVER >= 20081217 unsigned char buf[10]; WBUFW(buf,0) = 0x440; - WBUFL(buf,2) = sd->bl.id; + WBUFL(buf,2) = bl->id; WBUFW(buf,6) = shields; WBUFW(buf,8) = 0; - clif->send(buf,packet_len(0x440),&sd->bl,AREA); + clif->send(buf,packet_len(0x440),bl,AREA); #endif } /** diff --git a/src/map/clif.h b/src/map/clif.h index 6405bbd3e..9006a9ea3 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _CLIF_H_ -#define _CLIF_H_ +#ifndef _MAP_CLIF_H_ +#define _MAP_CLIF_H_ #include "../common/cbasetypes.h" #include "../common/db.h" @@ -763,7 +763,7 @@ struct clif_interface { void (*specialeffect) (struct block_list* bl, int type, enum send_target target); void (*specialeffect_single) (struct block_list* bl, int type, int fd); void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target); - void (*millenniumshield) (struct map_session_data *sd, short shields ); + void (*millenniumshield) (struct block_list *bl, short shields ); void (*charm) (struct map_session_data *sd, short type); void (*charm_single) (int fd, struct map_session_data *sd, short type); void (*snap) ( struct block_list *bl, short x, short y ); @@ -1275,4 +1275,4 @@ struct clif_interface *clif; void clif_defaults(void); -#endif /* _CLIF_H_ */ +#endif /* _MAP_CLIF_H_ */ diff --git a/src/map/date.h b/src/map/date.h index cc19d88d1..02238d7ea 100644 --- a/src/map/date.h +++ b/src/map/date.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _DATE_H_ -#define _DATE_H_ +#ifndef _MAP_DATE_H_ +#define _MAP_DATE_H_ int date_get_year(void); int date_get_month(void); @@ -15,4 +15,4 @@ int is_day_of_sun(void); int is_day_of_moon(void); int is_day_of_star(void); -#endif /* _DATE_H_ */ +#endif /* _MAP_DATE_H_ */ diff --git a/src/map/duel.h b/src/map/duel.h index d60c9531a..5405d2eee 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _DUEL_H_ -#define _DUEL_H_ +#ifndef _MAP_DUEL_H_ +#define _MAP_DUEL_H_ struct duel { int members_count; @@ -42,4 +42,4 @@ struct duel_interface *duel; void duel_defaults(void); -#endif /* _DUEL_H_ */ +#endif /* _MAP_DUEL_H_ */ diff --git a/src/map/elemental.h b/src/map/elemental.h index 830a6a577..6d04a41a5 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _ELEMENTAL_H_ -#define _ELEMENTAL_H_ +#ifndef _MAP_ELEMENTAL_H_ +#define _MAP_ELEMENTAL_H_ #include "status.h" // struct status_data, struct status_change #include "unit.h" // struct unit_data @@ -120,4 +120,4 @@ struct elemental_interface *elemental; void elemental_defaults(void); -#endif /* _ELEMENTAL_H_ */ +#endif /* _MAP_ELEMENTAL_H_ */ diff --git a/src/map/guild.h b/src/map/guild.h index 7878d75c3..b03bd664d 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _GUILD_H_ -#define _GUILD_H_ +#ifndef _MAP_GUILD_H_ +#define _MAP_GUILD_H_ //#include "../common/mmo.h" #include "map.h" // NAME_LENGTH @@ -173,4 +173,4 @@ struct guild_interface *guild; void guild_defaults(void); -#endif /* _GUILD_H_ */ +#endif /* _MAP_GUILD_H_ */ diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 117f9da8e..db250f511 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _HOMUNCULUS_H_ -#define _HOMUNCULUS_H_ +#ifndef _MAP_HOMUNCULUS_H_ +#define _MAP_HOMUNCULUS_H_ #include "status.h" // struct status_data, struct status_change #include "unit.h" // struct unit_data @@ -146,4 +146,4 @@ struct homunculus_interface *homun; void homunculus_defaults(void); -#endif /* _HOMUNCULUS_H_ */ +#endif /* _MAP_HOMUNCULUS_H_ */ diff --git a/src/map/instance.h b/src/map/instance.h index 764a55b2b..66a7d0d6c 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _INSTANCE_H_ -#define _INSTANCE_H_ +#ifndef _MAP_INSTANCE_H_ +#define _MAP_INSTANCE_H_ #define INSTANCE_NAME_LENGTH (60+1) @@ -82,4 +82,4 @@ struct instance_interface *instance; void instance_defaults(void); -#endif +#endif /* _MAP_INSTANCE_H_ */ diff --git a/src/map/intif.h b/src/map/intif.h index f0bb5c16e..290dcfcdc 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _INTIF_H_ -#define _INFIF_H_ +#ifndef _MAP_INTIF_H_ +#define _MAP_INTIF_H_ /** @@ -183,4 +183,4 @@ struct intif_interface *intif; void intif_defaults(void); -#endif /* _INTIF_H_ */ +#endif /* _MAP_INTIF_H_ */ diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h index 7d6a19eba..c15a5d46a 100644 --- a/src/map/irc-bot.h +++ b/src/map/irc-bot.h @@ -3,8 +3,8 @@ // Base Author: shennetsind @ http://hercules.ws -#ifndef _IRC_BOT_H_ -#define _IRC_BOT_H_ +#ifndef _MAP_IRC_BOT_H_ +#define _MAP_IRC_BOT_H_ #define IRC_NICK_LENGTH 40 #define IRC_IDENT_LENGTH 40 @@ -61,4 +61,4 @@ struct irc_bot_interface *ircbot; void ircbot_defaults(void); -#endif /* _IRC_BOT_H_ */ +#endif /* _MAP_IRC_BOT_H_ */ diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 6db503214..bfcc6f795 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1164,6 +1164,9 @@ void itemdb_read_chains(void) { CREATE(itemdb->chains, struct item_chain, libconfig->setting_length(item_chain_conf.root)); itemdb->chain_count = (unsigned short)libconfig->setting_length(item_chain_conf.root); +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = config_filename; +#endif // ENABLE_CASE_CHECK while( (itc = libconfig->setting_get_elem(item_chain_conf.root,i++)) ) { struct item_data *data = NULL; struct item_chain_entry *prev = NULL; @@ -1197,6 +1200,9 @@ void itemdb_read_chains(void) { count++; } +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = NULL; +#endif // ENABLE_CASE_CHECK libconfig->destroy(&item_chain_conf); @@ -1449,8 +1455,7 @@ void itemdb_read_combos() { } else { int items[MAX_ITEMS_PER_COMBO]; int v = 0, retcount = 0; - struct item_data * id = NULL; - int idx = 0; + struct item_combo *combo = NULL; if((retcount = itemdb->combo_split_atoi(str[0], items)) < 2) { ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath); @@ -1467,33 +1472,23 @@ void itemdb_read_combos() { /* failed at some item */ if( v < retcount ) continue; - - id = itemdb->exists(items[0]); - - idx = id->combos_count; - /* first entry, create */ - if( id->combos == NULL ) { - CREATE(id->combos, struct item_combo*, 1); - id->combos_count = 1; - } else { - RECREATE(id->combos, struct item_combo*, ++id->combos_count); - } + RECREATE(itemdb->combos, struct item_combo*, ++itemdb->combo_count); - CREATE(id->combos[idx],struct item_combo,1); + CREATE(combo, struct item_combo, 1); - id->combos[idx]->nameid = aMalloc( retcount * sizeof(unsigned short) ); - id->combos[idx]->count = retcount; - id->combos[idx]->script = script->parse(str[1], filepath, lines, 0); - id->combos[idx]->id = count; - id->combos[idx]->isRef = false; + combo->count = retcount; + combo->script = script->parse(str[1], filepath, lines, 0); + combo->id = itemdb->combo_count - 1; /* populate ->nameid field */ for( v = 0; v < retcount; v++ ) { - id->combos[idx]->nameid[v] = items[v]; + combo->nameid[v] = items[v]; } - /* populate the children to refer to this combo */ - for( v = 1; v < retcount; v++ ) { + itemdb->combos[itemdb->combo_count - 1] = combo; + + /* populate the items to refer to this combo */ + for( v = 0; v < retcount; v++ ) { struct item_data * it; int index; @@ -1501,19 +1496,9 @@ void itemdb_read_combos() { index = it->combos_count; - if( it->combos == NULL ) { - CREATE(it->combos, struct item_combo*, 1); - it->combos_count = 1; - } else { - RECREATE(it->combos, struct item_combo*, ++it->combos_count); - } - - CREATE(it->combos[index],struct item_combo,1); + RECREATE(it->combos, struct item_combo*, ++it->combos_count); - /* we copy previously alloc'd pointers and just set it to reference */ - memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo)); - /* we flag this way to ensure we don't double-dealloc same data */ - it->combos[index]->isRef = true; + it->combos[index] = combo; } } @@ -2076,6 +2061,15 @@ void itemdb_read(bool minimal) { itemdb->uid_load(); } +/** + * retrieves item_combo data by combo id + **/ +struct item_combo * itemdb_id2combo( unsigned short id ) { + if( id > itemdb->combo_count ) + return NULL; + return itemdb->combos[id]; +} + /*========================================== * Initialize / Finalize *------------------------------------------*/ @@ -2092,17 +2086,8 @@ void destroy_item_data(struct item_data* self, int free_self) script->free_code(self->equip_script); if( self->unequip_script ) script->free_code(self->unequip_script); - if( self->combos_count ) { - int i; - for( i = 0; i < self->combos_count; i++ ) { - if( !self->combos[i]->isRef ) { - aFree(self->combos[i]->nameid); - script->free_code(self->combos[i]->script); - } - aFree(self->combos[i]); - } + if( self->combos ) aFree(self->combos); - } #if defined(DEBUG) // trash item memset(self, 0xDD, sizeof(struct item_data)); @@ -2169,6 +2154,16 @@ void itemdb_clear(bool total) { itemdb->packages = NULL; itemdb->package_count = 0; + for(i = 0; i < itemdb->combo_count; i++) { + script->free_code(itemdb->combos[i]->script); + aFree(itemdb->combos[i]); + } + if( itemdb->combos ) + aFree(itemdb->combos); + + itemdb->combos = NULL; + itemdb->combo_count = 0; + if( total ) return; @@ -2225,18 +2220,15 @@ void itemdb_reload(void) { pc->setinventorydata(sd); if( battle_config.item_check ) sd->state.itemcheck = 1; - pc->checkitem(sd); /* clear combo bonuses */ - if( sd->combos.count ) { - aFree(sd->combos.bonus); - aFree(sd->combos.id); - sd->combos.bonus = NULL; - sd->combos.id = NULL; - sd->combos.count = 0; + if( sd->combo_count ) { + aFree(sd->combos); + sd->combos = NULL; + sd->combo_count = 0; if( pc->load_combo(sd) > 0 ) status_calc_pc(sd,SCO_FORCE); } - + pc->checkitem(sd); } mapit->free(iter); } @@ -2244,8 +2236,14 @@ void itemdb_name_constants(void) { DBIterator *iter = db_iterator(itemdb->names); struct item_data *data; +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = "Item Database (Likely an invalid or conflicting AegisName)"; +#endif // ENABLE_CASE_CHECK for( data = dbi_first(iter); dbi_exists(iter); data = dbi_next(iter) ) script->set_constant2(data->name,data->nameid,0); +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = NULL; +#endif // ENABLE_CASE_CHECK dbi_destroy(iter); } @@ -2286,6 +2284,9 @@ void itemdb_defaults(void) { itemdb->packages = NULL; itemdb->package_count = 0; /* */ + itemdb->combos = NULL; + itemdb->combo_count = 0; + /* */ itemdb->names = NULL; /* */ /* itemdb->array is cleared on itemdb->init() */ @@ -2352,4 +2353,5 @@ void itemdb_defaults(void) { itemdb->destroy_item_data = destroy_item_data; itemdb->final_sub = itemdb_final_sub; itemdb->clear = itemdb_clear; + itemdb->id2combo = itemdb_id2combo; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index b3ff606df..c399a0442 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _ITEMDB_H_ -#define _ITEMDB_H_ +#ifndef _MAP_ITEMDB_H_ +#define _MAP_ITEMDB_H_ #include "../common/db.h" #include "../common/mmo.h" // ITEM_NAME_LENGTH @@ -400,10 +400,9 @@ struct item_data { struct item_combo { struct script_code *script; - unsigned short *nameid;/* nameid array */ + unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */ unsigned char count; unsigned short id;/* id of this combo */ - bool isRef;/* whether this struct is a reference or the master */ }; struct item_group { @@ -509,6 +508,9 @@ struct itemdb_interface { /* */ struct item_package *packages; unsigned short package_count; + /* list of item combos loaded */ + struct item_combo **combos; + unsigned short combo_count; /* */ DBMap *names; /* */ @@ -576,10 +578,11 @@ struct itemdb_interface { void (*destroy_item_data) (struct item_data *self, int free_self); int (*final_sub) (DBKey key, DBData *data, va_list ap); void (*clear) (bool total); + struct item_combo * (*id2combo) (unsigned short id); }; struct itemdb_interface *itemdb; void itemdb_defaults(void); -#endif /* _ITEMDB_H_ */ +#endif /* _MAP_ITEMDB_H_ */ diff --git a/src/map/log.h b/src/map/log.h index 9864a54d7..b2cb92c20 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _LOG_H_ -#define _LOG_H_ +#ifndef _MAP_LOG_H_ +#define _MAP_LOG_H_ #include "../common/cbasetypes.h" #include "../common/sql.h" @@ -134,4 +134,4 @@ struct log_interface *logs; void log_defaults(void); -#endif /* _LOG_H_ */ +#endif /* _MAP_LOG_H_ */ diff --git a/src/map/mail.h b/src/map/mail.h index b2b9048cb..8df537ff3 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAIL_H_ -#define _MAIL_H_ +#ifndef _MAP_MAIL_H_ +#define _MAP_MAIL_H_ #include "../common/mmo.h" @@ -23,4 +23,4 @@ struct mail_interface *mail; void mail_defaults(void); -#endif /* _MAIL_H_ */ +#endif /* _MAP_MAIL_H_ */ diff --git a/src/map/map.c b/src/map/map.c index 33721b028..74b81f467 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3675,14 +3675,115 @@ int map_sql_close(void) return 0; } +/** + * Merges two zones into a new one + * @param main the zone whose data must override the others upon conflict, + * e.g. enabling pvp on a town means that main is the pvp zone, while "other" is the towns previous zone + * + * @return the newly created zone from merging main and other + **/ +struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone_data *other) { + char newzone[MAP_ZONE_NAME_LENGTH]; + struct map_zone_data *zone = NULL; + int cursor, i; + + sprintf(newzone, "%s+%s",main->name,other->name); + + if( (zone = strdb_get(map->zone_db, newzone)) ) + return zone;/* this zone has already been merged */ + + CREATE(zone, struct map_zone_data, 1); + + safestrncpy(zone->name, newzone, MAP_ZONE_NAME_LENGTH); + + zone->disabled_skills_count = main->disabled_skills_count + other->disabled_skills_count; + zone->disabled_items_count = main->disabled_items_count + other->disabled_items_count; + zone->mapflags_count = main->mapflags_count + other->mapflags_count; + zone->disabled_commands_count = main->disabled_commands_count + other->disabled_commands_count; + zone->capped_skills_count = main->capped_skills_count + other->capped_skills_count; + + CREATE(zone->disabled_skills, struct map_zone_disabled_skill_entry *, zone->disabled_skills_count ); + + for(i = 0, cursor = 0; i < main->disabled_skills_count; i++, cursor++ ) { + CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 ); + memcpy(zone->disabled_skills[cursor], main->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry)); + } + + for(i = 0; i < other->disabled_skills_count; i++, cursor++ ) { + CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 ); + memcpy(zone->disabled_skills[cursor], other->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry)); + } + + CREATE(zone->disabled_items, int, zone->disabled_items_count ); + + for(i = 0, cursor = 0; i < main->disabled_items_count; i++, cursor++ ) { + zone->disabled_items[cursor] = main->disabled_items[i]; + } + + for(i = 0; i < other->disabled_items_count; i++, cursor++ ) { + zone->disabled_items[cursor] = other->disabled_items[i]; + } + + CREATE(zone->mapflags, char *, zone->mapflags_count ); + + for(i = 0, cursor = 0; i < main->mapflags_count; i++, cursor++ ) { + CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH ); + safestrncpy(zone->mapflags[cursor], main->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + } + + for(i = 0; i < other->mapflags_count; i++, cursor++ ) { + CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH ); + safestrncpy(zone->mapflags[cursor], other->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + } + + CREATE(zone->disabled_commands, struct map_zone_disabled_command_entry *, zone->disabled_commands_count); + + for(i = 0, cursor = 0; i < main->disabled_commands_count; i++, cursor++ ) { + CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1); + memcpy(zone->disabled_commands[cursor], main->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry)); + } + + for(i = 0; i < other->disabled_commands_count; i++, cursor++ ) { + CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1); + memcpy(zone->disabled_commands[cursor], other->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry)); + } + + CREATE(zone->capped_skills, struct map_zone_skill_damage_cap_entry *, zone->capped_skills_count); + + + for(i = 0, cursor = 0; i < main->capped_skills_count; i++, cursor++ ) { + CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1); + memcpy(zone->capped_skills[cursor], main->disabled_commands[i], sizeof(struct map_zone_skill_damage_cap_entry)); + } + + for(i = 0; i < other->capped_skills_count; i++, cursor++ ) { + CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1); + memcpy(zone->capped_skills[cursor], other->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry)); + } + + zone->info.special = 2; + + strdb_put(map->zone_db, newzone, zone); + + return zone; +} + void map_zone_change2(int m, struct map_zone_data *zone) { char empty[1] = "\0"; - map->list[m].prev_zone = map->list[m].zone; - + if( map->list[m].zone == zone ) + return; + + if( map->list[m].zone->info.special != 2 ) /* we don't update it for merged zones! */ + map->list[m].prev_zone = map->list[m].zone; + if( map->list[m].zone_mf_count ) map->zone_remove(m); + if( zone->info.special ) { + zone = map->merge_zone(zone,map->list[m].prev_zone); + } + map->zone_apply(m,zone,empty,empty,empty); } /* when changing from a mapflag to another during runtime */ @@ -4640,7 +4741,7 @@ void read_map_zone_db(void) { zone->disabled_skills_count = 0; zone->disabled_items_count = 0; } - safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH); + safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH/2); if( (skills = libconfig->setting_get_member(zone_e, "disabled_skills")) != NULL ) { disabled_skills_count = libconfig->setting_length(skills); @@ -4981,6 +5082,14 @@ void read_map_zone_db(void) { ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' zones in '"CL_WHITE"%s"CL_RESET"'.\n", zone_count, config_filename); /* not supposed to go in here but in skill_final whatever */ libconfig->destroy(&map_zone_db); + + /* post-load processing */ + if( (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) ) + zone->info.special = 1; + if( (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) ) + zone->info.special = 1; + if( (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) ) + zone->info.special = 1; } } @@ -5447,6 +5556,8 @@ int do_init(int argc, char *argv[]) map_load_defaults(); + HPM_map_do_init(); + HPM->DataCheck = HPM_map_DataCheck; HPM->load_sub = HPM_map_plugin_load_sub; HPM->symbol_defaults_sub = map_hp_symbols; HPM->grabHPDataSub = HPM_map_grabHPData; @@ -5941,6 +6052,8 @@ void map_defaults(void) { map->add_questinfo = map_add_questinfo; map->remove_questinfo = map_remove_questinfo; + map->merge_zone = map_merge_zone; + /** * mapit interface **/ @@ -5954,4 +6067,5 @@ void map_defaults(void) { mapit->next = mapit_next; mapit->prev = mapit_prev; mapit->exists = mapit_exists; + } diff --git a/src/map/map.h b/src/map/map.h index 130b181da..a4e9499b3 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_H_ -#define _MAP_H_ +#ifndef _MAP_MAP_H_ +#define _MAP_MAP_H_ #include "../common/cbasetypes.h" #include "../common/core.h" // CORE_ST_LAST @@ -531,7 +531,7 @@ struct map_zone_skill_damage_cap_entry { enum map_zone_skill_subtype subtype; }; -#define MAP_ZONE_NAME_LENGTH 30 +#define MAP_ZONE_NAME_LENGTH 60 #define MAP_ZONE_ALL_NAME "All" #define MAP_ZONE_NORMAL_NAME "Normal" #define MAP_ZONE_PVP_NAME "PvP" @@ -552,6 +552,9 @@ struct map_zone_data { int disabled_commands_count; struct map_zone_skill_damage_cap_entry **capped_skills; int capped_skills_count; + struct { + unsigned int special : 2;/* 1: whether this is a mergeable zone; 2: whether it is a merged zone */ + } info; }; struct map_drop_list { @@ -1060,10 +1063,11 @@ struct map_interface { int (*get_new_bonus_id) (void); void (*add_questinfo) (int m, struct questinfo *qi); bool (*remove_questinfo) (int m, struct npc_data *nd); + struct map_zone_data *(*merge_zone) (struct map_zone_data *main, struct map_zone_data *other); }; struct map_interface *map; void map_defaults(void); -#endif /* _MAP_H_ */ +#endif /* _MAP_MAP_H_ */ diff --git a/src/map/mapreg.h b/src/map/mapreg.h index 157e634cc..c92b6f602 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAPREG_H_ -#define _MAPREG_H_ +#ifndef _MAP_MAPREG_H_ +#define _MAP_MAPREG_H_ #include "../common/cbasetypes.h" #include "../common/db.h" @@ -51,4 +51,4 @@ struct mapreg_interface *mapreg; void mapreg_defaults(void); -#endif /* _MAPREG_H_ */ +#endif /* _MAP_MAPREG_H_ */ diff --git a/src/map/mercenary.h b/src/map/mercenary.h index 3f2214b65..dd9266b2e 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -1,8 +1,8 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MERCENARY_H_ -#define _MERCENARY_H_ +#ifndef _MAP_MERCENARY_H_ +#define _MAP_MERCENARY_H_ #include "status.h" // struct status_data, struct status_change #include "unit.h" // struct unit_data @@ -98,4 +98,4 @@ struct mercenary_interface *mercenary; void mercenary_defaults(void); -#endif /* _MERCENARY_H_ */ +#endif /* _MAP_MERCENARY_H_ */ diff --git a/src/map/mob.c b/src/map/mob.c index dab7b99ac..dc83be93e 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3962,10 +3962,16 @@ int mob_read_sqldb(void) { void mob_name_constants(void) { int i; +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = "Mob Database (Likely an invalid or conflicting SpriteName)"; +#endif // ENABLE_CASE_CHECK for (i = 0; i < MAX_MOB_DB; i++) { if (mob->db_data[i] && !mob->is_clone(i)) script->set_constant2(mob->db_data[i]->sprite, i, 0); } +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = NULL; +#endif // ENABLE_CASE_CHECK } /*========================================== diff --git a/src/map/mob.h b/src/map/mob.h index 9321cb4fd..80175b1db 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MOB_H_ -#define _MOB_H_ +#ifndef _MAP_MOB_H_ +#define _MAP_MOB_H_ #include "../common/mmo.h" // struct item #include "guild.h" // struct guardian_data @@ -364,4 +364,4 @@ struct mob_interface *mob; void mob_defaults(void); -#endif /* _MOB_H_ */ +#endif /* _MAP_MOB_H_ */ diff --git a/src/map/npc.c b/src/map/npc.c index 458fc52ed..36efc7267 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3173,12 +3173,17 @@ void npc_unsetcells(struct npc_data* nd) { int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; int i,j, x0, x1, y0, y1; - if (nd->subtype == WARP) { - xs = nd->u.warp.xs; - ys = nd->u.warp.ys; - } else { - xs = nd->u.scr.xs; - ys = nd->u.scr.ys; + switch(nd->subtype) { + case WARP: + xs = nd->u.warp.xs; + ys = nd->u.warp.ys; + break; + case SCRIPT: + xs = nd->u.scr.xs; + ys = nd->u.scr.ys; + break; + default: + return; // Other types doesn't have touch area } if (m < 0 || xs < 0 || ys < 0 || map->list[m].cell == (struct mapcell *)0xdeadbeaf) diff --git a/src/map/npc.h b/src/map/npc.h index 266d174fb..346a9f8c0 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _NPC_H_ -#define _NPC_H_ +#ifndef _MAP_NPC_H_ +#define _MAP_NPC_H_ #include "map.h" // struct block_list #include "status.h" // struct status_change @@ -336,6 +336,7 @@ struct pcre_interface { int (*copy_substring) (const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize); void (*free_substring) (const char *stringptr); int (*copy_named_substring) (const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize); + int (*get_substring) (const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr); }; struct pcre_interface *libpcre; @@ -346,4 +347,4 @@ struct pcre_interface *libpcre; void npc_chat_defaults(void); #endif -#endif /* _NPC_H_ */ +#endif /* _MAP_NPC_H_ */ diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 896bbae5b..9d5639efc 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -440,6 +440,7 @@ void npc_chat_defaults(void) { libpcre->copy_substring = pcre_copy_substring; libpcre->free_substring = pcre_free_substring; libpcre->copy_named_substring = pcre_copy_named_substring; + libpcre->get_substring = pcre_get_substring; } #endif //PCRE_SUPPORT diff --git a/src/map/packets.h b/src/map/packets.h index cea916f6d..4cf6f6d6a 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -3,8 +3,8 @@ //Included directly by clif.h in packet_loaddb() -#ifndef _PACKETS_H_ -#define _PACKETS_H_ +#ifndef _MAP_PACKETS_H_ +#define _MAP_PACKETS_H_ #ifndef packet #define packet(a,b,...) @@ -2693,4 +2693,4 @@ packet(0x020d,-1); packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3); #endif -#endif /* _PACKETS_H_ */ +#endif /* _MAP_PACKETS_H_ */ diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 1156f4465..4a599463a 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3,8 +3,8 @@ /* Hercules Renewal: Phase Two http://hercules.ws/board/topic/383-hercules-renewal-phase-two/ */ -#ifndef _PACKETS_STRUCT_H_ -#define _PACKETS_STRUCT_H_ +#ifndef _MAP_PACKETS_STRUCT_H_ +#define _MAP_PACKETS_STRUCT_H_ #include "../common/mmo.h" @@ -945,4 +945,4 @@ struct packet_npc_market_open { #pragma pack(pop) #endif // not NetBSD < 6 / Solaris -#endif /* _PACKETS_STRUCT_H_ */ +#endif /* _MAP_PACKETS_STRUCT_H_ */ diff --git a/src/map/party.h b/src/map/party.h index 051c98af2..05b5309e6 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _PARTY_H_ -#define _PARTY_H_ +#ifndef _MAP_PARTY_H_ +#define _MAP_PARTY_H_ #include "../common/mmo.h" // struct party #include "../config/core.h" @@ -141,4 +141,4 @@ struct party_interface *party; void party_defaults(void); -#endif /* _PARTY_H_ */ +#endif /* _MAP_PARTY_H_ */ diff --git a/src/map/path.h b/src/map/path.h index a889a6409..0b67a0120 100644 --- a/src/map/path.h +++ b/src/map/path.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _PATH_H_ -#define _PATH_H_ +#ifndef _MAP_PATH_H_ +#define _MAP_PATH_H_ #include "map.h" // enum cell_chk @@ -46,4 +46,4 @@ struct path_interface *path; void path_defaults(void); -#endif /* _PATH_H_ */ +#endif /* _MAP_PATH_H_ */ diff --git a/src/map/pc.c b/src/map/pc.c index b6c354189..e29ef343f 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -196,7 +196,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max) sd->spirit_timer[i] = tid; sd->spiritball++; if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) - clif->millenniumshield(sd,sd->spiritball); + clif->millenniumshield(&sd->bl,sd->spiritball); else clif->spiritball(&sd->bl); @@ -235,7 +235,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type) if(!type) { if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) - clif->millenniumshield(sd,sd->spiritball); + clif->millenniumshield(&sd->bl,sd->spiritball); else clif->spiritball(&sd->bl); } @@ -3957,12 +3957,13 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l i = MAX_INVENTORY; - if( itemdb->isstackable2(data) && item_data->expire_time == 0 ) - { // Stackable | Non Rental - for( i = 0; i < MAX_INVENTORY; i++ ) - { - if( sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].bound == item_data->bound && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) - { + // Stackable | Non Rental + if( itemdb->isstackable2(data) && item_data->expire_time == 0 ) { + for( i = 0; i < MAX_INVENTORY; i++ ) { + if( sd->status.inventory[i].nameid == item_data->nameid && + sd->status.inventory[i].bound == item_data->bound && + sd->status.inventory[i].expire_time == 0 && + memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) { if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) ) return 5; sd->status.inventory[i].amount += amount; @@ -5205,7 +5206,8 @@ int pc_checkallowskill(struct map_session_data *sd) SC_LKCONCENTRATION, SC_EDP, #endif - SC_FEARBREEZE + SC_FEARBREEZE, + SC_EXEEDBREAK, }; const enum sc_type scs_list[] = { SC_AUTOGUARD, @@ -6174,52 +6176,88 @@ int pc_need_status_point(struct map_session_data* sd, int type, int val) return sp; } -/// Raises a stat by 1. -/// Obeys max_parameter limits. -/// Subtracts stat points. -/// -/// @param type The stat to change (see enum _sp) -int pc_statusup(struct map_session_data* sd, int type) -{ - int max, need, val; +/** + * Returns the value the specified stat can be increased by with the current + * amount of available status points for the current character's class. + * + * @param sd The target character. + * @param type Stat to verify. + * @return Maximum value the stat could grow by. + */ +int pc_maxparameterincrease(struct map_session_data* sd, int type) { + int base, final, status_points = sd->status.status_point; + + base = final = pc->getstat(sd, type); + + while (final <= pc_maxparameter(sd) && status_points >= 0) { +#ifdef RENEWAL // renewal status point cost formula + status_points -= (final < 100) ? (2 + (final - 1) / 10) : (16 + 4 * ((final - 100) / 5)); +#else + status_points -= ( 1 + (final + 9) / 10 ); +#endif + final++; + } + final--; + + return final > base ? final-base : 0; +} + +/** + * Raises a stat by the specified amount. + * Obeys max_parameter limits. + * Subtracts stat points. + * + * @param sd The target character. + * @param type The stat to change (see enum _sp) + * @param increase The stat increase amount. + * @return true if the stat was increased by any amount, false if there were no + * changes. + */ +bool pc_statusup(struct map_session_data* sd, int type, int increase) { + int max_increase = 0, current = 0, needed_points = 0, final_value = 0; nullpo_ret(sd); // check conditions - need = pc->need_status_point(sd,type,1); - if( type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point ) - { - clif->statusupack(sd,type,0,0); - return 1; + if (type < SP_STR || type > SP_LUK || increase <= 0) { + clif->statusupack(sd, type, 0, 0); + return false; } // check limits - max = pc_maxparameter(sd); - if( pc->getstat(sd,type) >= max ) - { - clif->statusupack(sd,type,0,0); - return 1; + current = pc->getstat(sd, type); + max_increase = pc->maxparameterincrease(sd, type); + increase = cap_value(increase, 0, max_increase); // cap to the maximum status points available + if (increase <= 0 || current + increase > pc_maxparameter(sd)) { + clif->statusupack(sd, type, 0, 0); + return false; + } + + // check status points + needed_points = pc->need_status_point(sd, type, increase); + if (needed_points < 0 || needed_points > sd->status.status_point) { // Sanity check + clif->statusupack(sd, type, 0, 0); + return false; } // set new values - val = pc->setstat(sd, type, pc->getstat(sd,type) + 1); - sd->status.status_point -= need; + final_value = pc->setstat(sd, type, current + increase); + sd->status.status_point -= needed_points; - status_calc_pc(sd,SCO_NONE); + status_calc_pc(sd, SCO_NONE); // update increase cost indicator - if( need != pc->need_status_point(sd,type,1) ) - clif->updatestatus(sd, SP_USTR + type-SP_STR); + clif->updatestatus(sd, SP_USTR + type-SP_STR); // update statpoint count - clif->updatestatus(sd,SP_STATUSPOINT); + clif->updatestatus(sd, SP_STATUSPOINT); // update stat value - clif->statusupack(sd,type,1,val); // required - if( val > 255 ) - clif->updatestatus(sd,type); // send after the 'ack' to override the truncated value + clif->statusupack(sd, type, 1, final_value); // required + if (final_value > 255) + clif->updatestatus(sd, type); // send after the 'ack' to override the truncated value - return 0; + return true; } /// Raises a stat by the specified amount. @@ -8410,17 +8448,19 @@ int pc_cleareventtimer(struct map_session_data *sd) /* called when a item with combo is worn */ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { int i, j, k, z; - int index, idx, success = 0; + int index, success = 0; + struct pc_combos *combo; for( i = 0; i < data->combos_count; i++ ) { /* ensure this isn't a duplicate combo */ - if( sd->combos.bonus != NULL ) { + if( sd->combos != NULL ) { int x; - ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id ); + + ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id ); /* found a match, skip this combo */ - if( x < sd->combos.count ) + if( x < sd->combo_count ) continue; } @@ -8437,7 +8477,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { if(!sd->inventory_data[index]) continue; - + if ( itemdb_type(id) != IT_CARD ) { if ( sd->inventory_data[index]->nameid != id ) continue; @@ -8471,22 +8511,13 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { /* we got here, means all items in the combo are matching */ - idx = sd->combos.count; - - if( sd->combos.bonus == NULL ) { - CREATE(sd->combos.bonus, struct script_code *, 1); - CREATE(sd->combos.id, unsigned short, 1); - sd->combos.count = 1; - } else { - RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count); - RECREATE(sd->combos.id, unsigned short, sd->combos.count); - } - - /* we simply copy the pointer */ - sd->combos.bonus[idx] = data->combos[i]->script; - /* save this combo's id */ - sd->combos.id[idx] = data->combos[i]->id; - + RECREATE(sd->combos, struct pc_combos, ++sd->combo_count); + + combo = &sd->combos[sd->combo_count - 1]; + + combo->bonus = data->combos[i]->script; + combo->id = data->combos[i]->id; + success++; } return success; @@ -8496,26 +8527,30 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { int i, retval = 0; - if( sd->combos.bonus == NULL ) + if( !sd->combos ) return 0;/* nothing to do here, player has no combos */ + for( i = 0; i < data->combos_count; i++ ) { /* check if this combo exists in this user */ int x = 0, cursor = 0, j; - ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id ); + + ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id ); /* no match, skip this combo */ - if( !(x < sd->combos.count) ) + if( !(x < sd->combo_count) ) continue; - sd->combos.bonus[x] = NULL; - sd->combos.id[x] = 0; + sd->combos[x].bonus = NULL; + sd->combos[x].id = 0; + retval++; - for( j = 0, cursor = 0; j < sd->combos.count; j++ ) { - if( sd->combos.bonus[j] == NULL ) + + for( j = 0, cursor = 0; j < sd->combo_count; j++ ) { + if( sd->combos[j].bonus == NULL ) continue; if( cursor != j ) { - sd->combos.bonus[cursor] = sd->combos.bonus[j]; - sd->combos.id[cursor] = sd->combos.id[j]; + sd->combos[cursor].bonus = sd->combos[j].bonus; + sd->combos[cursor].id = sd->combos[j].id; } cursor++; @@ -8526,11 +8561,10 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { continue; /* it's empty, we can clear all the memory */ - if( (sd->combos.count = cursor) == 0 ) { - aFree(sd->combos.bonus); - aFree(sd->combos.id); - sd->combos.bonus = NULL; - sd->combos.id = NULL; + if( (sd->combo_count = cursor) == 0 ) { + aFree(sd->combos); + sd->combos = NULL; + return retval; /* we also can return at this point for we have no more combos to check */ } @@ -8953,7 +8987,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { *------------------------------------------*/ int pc_checkitem(struct map_session_data *sd) { - int i,id,calc_flag = 0; + int i, id, calc_flag = 0; nullpo_ret(sd); @@ -9019,7 +9053,7 @@ int pc_checkitem(struct map_session_data *sd) } } - + if( calc_flag && sd->state.active ) { pc->checkallowskill(sd); status_calc_pc(sd,SCO_NONE); @@ -10359,15 +10393,20 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' LIMIT 1",map->autotrade_merchants_db,sd->status.char_id)) Sql_ShowDebug(map->mysql_handle); break; - case PAUC_START: + case PAUC_START: { + char title[MESSAGE_SIZE*2+1]; + + SQL->EscapeStringLen(map->mysql_handle, title, sd->message, strnlen(sd->message, MESSAGE_SIZE)); + if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`account_id`,`char_id`,`sex`,`title`) VALUES ('%d','%d','%d','%s')", map->autotrade_merchants_db, sd->status.account_id, sd->status.char_id, sd->status.sex, - sd->message + title )) Sql_ShowDebug(map->mysql_handle); + } /* yes we want it to fall */ case PAUC_REFRESH: for( i = 0; i < sd->vend_num; i++ ) { @@ -10674,6 +10713,7 @@ void pc_defaults(void) { pc->thisjobexp = pc_thisjobexp; pc->gets_status_point = pc_gets_status_point; pc->need_status_point = pc_need_status_point; + pc->maxparameterincrease = pc_maxparameterincrease; pc->statusup = pc_statusup; pc->statusup2 = pc_statusup2; pc->skillup = pc_skillup; diff --git a/src/map/pc.h b/src/map/pc.h index 487266646..30a24c00e 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -1,8 +1,9 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _PC_H_ -#define _PC_H_ + +#ifndef _MAP_PC_H_ +#define _MAP_PC_H_ #include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus #include "../common/ers.h" @@ -115,6 +116,12 @@ enum npc_timeout_type { NPCT_MENU = 1, NPCT_WAIT = 2, }; + +struct pc_combos { + struct script_code *bonus;/* the script of the combo */ + unsigned short id;/* this combo id */ +}; + struct map_session_data { struct block_list bl; struct unit_data ud; @@ -467,12 +474,9 @@ struct map_session_data { enum npc_timeout_type npc_idle_type; #endif - struct { - struct script_code **bonus;/* the script */ - unsigned short *id;/* array of combo ids */ - unsigned char count; - } combos; - + struct pc_combos *combos; + unsigned char combo_count; + /** * Guarantees your friend request is legit (for bugreport:4629) **/ @@ -884,7 +888,8 @@ struct pc_interface { unsigned int (*thisjobexp) (struct map_session_data *sd); int (*gets_status_point) (int level); int (*need_status_point) (struct map_session_data *sd,int type,int val); - int (*statusup) (struct map_session_data *sd,int type); + int (*maxparameterincrease) (struct map_session_data* sd, int type); + bool (*statusup) (struct map_session_data *sd, int type, int increase); int (*statusup2) (struct map_session_data *sd,int type,int val); int (*skillup) (struct map_session_data *sd,uint16 skill_id); int (*allskillup) (struct map_session_data *sd); @@ -1044,4 +1049,4 @@ struct pc_interface *pc; void pc_defaults(void); -#endif /* _PC_H_ */ +#endif /* _MAP_PC_H_ */ diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 3396512ea..5c03f999f 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _PC_GROUPS_H_ -#define _PC_GROUPS_H_ +#ifndef _MAP_PC_GROUPS_H_ +#define _MAP_PC_GROUPS_H_ /// PC permissions enum e_pc_permission { @@ -92,4 +92,4 @@ struct pc_groups_interface *pcg; void pc_groups_defaults(void); -#endif // _PC_GROUPS_H_ +#endif /* _MAP_PC_GROUPS_H_ */ diff --git a/src/map/pet.h b/src/map/pet.h index f1a219700..537a50c4b 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _PET_H_ -#define _PET_H_ +#ifndef _MAP_PET_H_ +#define _MAP_PET_H_ #define MAX_PET_DB 300 #define MAX_PETLOOT_SIZE 30 @@ -152,4 +152,4 @@ struct pet_interface *pet; void pet_defaults(void); -#endif /* _PET_H_ */ +#endif /* _MAP_PET_H_ */ diff --git a/src/map/quest.h b/src/map/quest.h index 28815a6c3..e01e35619 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _QUEST_H_ -#define _QUEST_H_ +#ifndef _MAP_QUEST_H_ +#define _MAP_QUEST_H_ #define MAX_QUEST_DB (60355+1) // Highest quest ID + 1 @@ -48,4 +48,4 @@ struct quest_interface *quest; void quest_defaults(void); -#endif +#endif /* _MAP_QUEST_H_ */ diff --git a/src/map/script.c b/src/map/script.c index adea269c7..7ca6a7ddd 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -2275,7 +2275,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o for(i=0; i<size; i++) linkdb_final(&script->syntax.curly[i].case_label); #ifdef ENABLE_CASE_CHECK - script->local_casecheck.clear(); + script->local_casecheck.clear(); + script->parser_current_src = NULL; + script->parser_current_file = NULL; + script->parser_current_line = 0; #endif // ENABLE_CASE_CHECK return NULL; } @@ -2292,7 +2295,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o script->size = 0; script->buf = NULL; #ifdef ENABLE_CASE_CHECK - script->local_casecheck.clear(); + script->local_casecheck.clear(); + script->parser_current_src = NULL; + script->parser_current_file = NULL; + script->parser_current_line = 0; #endif // ENABLE_CASE_CHECK return NULL; } @@ -2310,7 +2316,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o script->size = 0; script->buf = NULL; #ifdef ENABLE_CASE_CHECK - script->local_casecheck.clear(); + script->local_casecheck.clear(); + script->parser_current_src = NULL; + script->parser_current_file = NULL; + script->parser_current_line = 0; #endif // ENABLE_CASE_CHECK return NULL; } @@ -2428,6 +2437,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o code->script_vars = NULL; #ifdef ENABLE_CASE_CHECK script->local_casecheck.clear(); + script->parser_current_src = NULL; + script->parser_current_file = NULL; + script->parser_current_line = 0; #endif // ENABLE_CASE_CHECK return code; } @@ -7654,9 +7666,8 @@ BUILDIN(getequippercentrefinery) { /*========================================== * Refine +1 item at pos and log and display refine *------------------------------------------*/ -BUILDIN(successrefitem) -{ - int i=-1,num,ep; +BUILDIN(successrefitem) { + int i = -1 , num, ep, up = 1; TBL_PC *sd; num = script_getnum(st,2); @@ -7664,6 +7675,9 @@ BUILDIN(successrefitem) if( sd == NULL ) return true; + if( script_hasdata(st, 3) ) + up = script_getnum(st, 3); + if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); if(i >= 0) { @@ -7675,7 +7689,8 @@ BUILDIN(successrefitem) if (sd->status.inventory[i].refine >= MAX_REFINE) return true; - sd->status.inventory[i].refine++; + sd->status.inventory[i].refine += up; + sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below clif->refine(sd->fd,0,i,sd->status.inventory[i].refine); @@ -7803,8 +7818,7 @@ BUILDIN(delequip) /*========================================== * *------------------------------------------*/ -BUILDIN(statusup) -{ +BUILDIN(statusup) { int type; TBL_PC *sd; @@ -7813,7 +7827,7 @@ BUILDIN(statusup) if( sd == NULL ) return true; - pc->statusup(sd,type); + pc->statusup(sd, type, 1); return true; } @@ -14065,6 +14079,15 @@ BUILDIN(sscanf) { argc = script_lastdata(st)-3; len = strlen(format); + + if (len != 0 && strlen(str) == 0) { + // If the source string is empty but the format string is not, we return -1 + // according to the C specs. (if the format string is also empty, we shall + // continue and return 0: 0 conversions took place out of the 0 attempted.) + script_pushint(st, -1); + return true; + } + CREATE(buf, char, len*2+1); // Issue sscanf for each parameter @@ -14380,14 +14403,34 @@ BUILDIN(setnpcdisplay) { return true; } -BUILDIN(atoi) -{ +BUILDIN(atoi) { const char *value; value = script_getstr(st,2); script_pushint(st,atoi(value)); return true; } +BUILDIN(axtoi) { + const char *hex = script_getstr(st,2); + long value = strtol(hex, NULL, 16); +#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN + value = cap_value(value, INT_MIN, INT_MAX); +#endif + script_pushint(st, (int)value); + return true; +} + +BUILDIN(strtol) { + const char *string = script_getstr(st, 2); + int base = script_getnum(st, 3); + long value = strtol(string, NULL, base); +#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN + value = cap_value(value, INT_MIN, INT_MAX); +#endif + script_pushint(st, (int)value); + return true; +} + // case-insensitive substring search [lordalfa] BUILDIN(compare) { @@ -15113,47 +15156,6 @@ BUILDIN(searchitem) return true; } -int axtoi(const char *hexStg) -{ - int n = 0; // position in string - int16 m = 0; // position in digit[] to shift - int count; // loop index - int intValue = 0; // integer value of hex string - int digit[11]; // hold values to convert - while (n < 10) { - if (hexStg[n]=='\0') - break; - if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9 - digit[n] = hexStg[n] & 0x0f; //convert to int - else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f - digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int - else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F - digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int - else break; - n++; - } - count = n; - m = n - 1; - n = 0; - while(n < count) { - // digit[n] is value of hex digit at position n - // (m << 2) is the number of positions to shift - // OR the bits into return value - intValue = intValue | (digit[n] << (m << 2)); - m--; // adjust the position to set - n++; // next digit to process - } - return (intValue); -} - -// [Lance] Hex string to integer converter -BUILDIN(axtoi) -{ - const char *hex = script_getstr(st,2); - script_pushint(st,script->axtoi(hex)); - return true; -} - // [zBuffer] List of player cont commands ---> BUILDIN(rid2name) { struct block_list *bl = NULL; @@ -18581,7 +18583,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(getequiprefinerycnt,"i"), BUILDIN_DEF(getequipweaponlv,"i"), BUILDIN_DEF(getequippercentrefinery,"i"), - BUILDIN_DEF(successrefitem,"i"), + BUILDIN_DEF(successrefitem,"i?"), BUILDIN_DEF(failedrefitem,"i"), BUILDIN_DEF(downrefitem,"i?"), BUILDIN_DEF(statusup,"i"), @@ -18838,6 +18840,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(query_logsql,"s*"), BUILDIN_DEF(escape_sql,"v"), BUILDIN_DEF(atoi,"s"), + BUILDIN_DEF(strtol,"si"), // [zBuffer] List of player cont commands ---> BUILDIN_DEF(rid2name,"i"), BUILDIN_DEF(pcfollow,"ii"), @@ -19221,7 +19224,6 @@ void script_defaults(void) { script->playbgm_foreachpc_sub = playbgm_foreachpc_sub; script->soundeffect_sub = soundeffect_sub; script->buildin_query_sql_sub = buildin_query_sql_sub; - script->axtoi = axtoi; script->buildin_instance_warpall_sub = buildin_instance_warpall_sub; script->buildin_mobuseskill_sub = buildin_mobuseskill_sub; script->cleanfloor_sub = script_cleanfloor_sub; diff --git a/src/map/script.h b/src/map/script.h index 97db2a775..872c5bc31 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _SCRIPT_H_ -#define _SCRIPT_H_ +#ifndef _MAP_SCRIPT_H_ +#define _MAP_SCRIPT_H_ #include "../common/strlib.h" //StringBuf #include "../common/cbasetypes.h" @@ -23,8 +23,9 @@ struct eri; **/ // TODO: Remove temporary code #define ENABLE_CASE_CHECK -#define DeprecationWarning(func, bad, good, file, line) ShowError("%s: use of deprecated keyword '%s' (use '%s' instead) in file '%s', line '%d'.\n", (func), (bad), (good), (file), (line)); -#define DeprecationWarning2(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), (where)); +#define get_script_source(source) ((source) ? (source) : "Unknown (Possibly source or variables stored in database") +#define DeprecationWarning(func, bad, good, file, line) ShowError("%s: use of deprecated keyword '%s' (use '%s' instead) in file '%s', line '%d'.\n", (func), (bad), (good), get_script_source(file), (line)); +#define DeprecationWarning2(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), get_script_source(where)); #define disp_deprecation_message(func, good, p) disp_warning_message(func": use of deprecated keyword (use '"good"' instead).", (p)); #define NUM_WHISPER_VAR 10 @@ -665,7 +666,6 @@ struct script_interface { int (*playbgm_foreachpc_sub) (struct map_session_data *sd, va_list args); int (*soundeffect_sub) (struct block_list *bl, va_list ap); int (*buildin_query_sql_sub) (struct script_state *st, Sql *handle); - int (*axtoi) (const char *hexStg); int (*buildin_instance_warpall_sub) (struct block_list *bl, va_list ap); int (*buildin_mobuseskill_sub) (struct block_list *bl, va_list ap); int (*cleanfloor_sub) (struct block_list *bl, va_list ap); @@ -700,4 +700,4 @@ struct script_interface *script; void script_defaults(void); -#endif /* _SCRIPT_H_ */ +#endif /* _MAP_SCRIPT_H_ */ diff --git a/src/map/searchstore.h b/src/map/searchstore.h index d7a327181..827e39053 100644 --- a/src/map/searchstore.h +++ b/src/map/searchstore.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _SEARCHSTORE_H_ -#define _SEARCHSTORE_H_ +#ifndef _MAP_SEARCHSTORE_H_ +#define _MAP_SEARCHSTORE_H_ /** * Defines @@ -93,4 +93,4 @@ struct searchstore_interface *searchstore; void searchstore_defaults (void); -#endif // _SEARCHSTORE_H_ +#endif /* _MAP_SEARCHSTORE_H_ */ diff --git a/src/map/skill.c b/src/map/skill.c index 0df90a538..a66ead4ae 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7778,10 +7778,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case RK_MILLENNIUMSHIELD: - if( sd ){ + { short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); sc_start4(bl,type,100,skill_lv,shields,1000,0,skill->get_time(skill_id,skill_lv)); - clif->millenniumshield(sd,shields); + clif->millenniumshield(src,shields); clif->skill_nodamage(src,bl,skill_id,1,1); } break; @@ -7811,12 +7811,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int value = 0; type = SC_NONE; if( skill->area_temp[5]&0x10 ){ - if( dstsd ){ - value = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); - clif->millenniumshield(dstsd,value); - skill->area_temp[5] &= ~0x10; - type = SC_MILLENNIUMSHIELD; - } + value = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); + clif->millenniumshield(bl,value); + skill->area_temp[5] &= ~0x10; + type = SC_MILLENNIUMSHIELD; }else if( skill->area_temp[5]&0x20 ){ value = status_get_max_hp(bl) * 25 / 100; status->change_clear_buffs(bl,4); @@ -15069,7 +15067,7 @@ int skill_maelstrom_suction(struct block_list *bl, va_list ap) { *------------------------------------------*/ int skill_enchant_elemental_end (struct block_list *bl, int type) { struct status_change *sc; - const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS, SC_EXEEDBREAK }; + const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS }; int i; nullpo_ret(bl); nullpo_ret(sc = status->get_sc(bl)); @@ -18132,7 +18130,13 @@ void skill_readdb(bool minimal) { safestrncpy(skill->db[0].name, "UNKNOWN_SKILL", sizeof(skill->db[0].name)); safestrncpy(skill->db[0].desc, "Unknown Skill", sizeof(skill->db[0].desc)); +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = DBPATH"skill_db.txt"; +#endif // ENABLE_CASE_CHECK sv->readdb(map->db_path, DBPATH"skill_db.txt", ',', 17, 17, MAX_SKILL_DB, skill->parse_row_skilldb); +#ifdef ENABLE_CASE_CHECK + script->parser_current_file = NULL; +#endif // ENABLE_CASE_CHECK if (minimal) return; diff --git a/src/map/skill.h b/src/map/skill.h index 28cb548d2..78829f17e 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _SKILL_H_ -#define _SKILL_H_ +#ifndef _MAP_SKILL_H_ +#define _MAP_SKILL_H_ #include "../common/mmo.h" // MAX_SKILL, struct square #include "../common/db.h" @@ -2015,4 +2015,4 @@ struct skill_interface *skill; void skill_defaults(void); -#endif /* _SKILL_H_ */ +#endif /* _MAP_SKILL_H_ */ diff --git a/src/map/status.c b/src/map/status.c index 74b2571e1..df79cee74 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2598,12 +2598,29 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } /* we've got combos to process */ - if( sd->combos.count ) { - for( i = 0; i < sd->combos.count; i++ ) { - script->run(sd->combos.bonus[i],0,sd->bl.id,0); - if (!calculating) //Abort, script->run retriggered this. - return 1; + for( i = 0; i < sd->combo_count; i++ ) { + struct item_combo *combo = itemdb->id2combo(sd->combos[i].id); + unsigned char j; + + /** + * ensure combo usage is allowed at this location + **/ + for(j = 0; j < combo->count; j++) { + for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) { + if( map->list[sd->bl.m].zone->disabled_items[k] == combo->nameid[j] ) { + break; + } + } + if( k != map->list[sd->bl.m].zone->disabled_items_count ) + break; } + + if( j != combo->count ) + continue; + + script->run(sd->combos[i].bonus,0,sd->bl.id,0); + if (!calculating) //Abort, script->run retriggered this. + return 1; } //Store equipment script bonuses @@ -5529,12 +5546,14 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int } unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) { + // It has been confirmed on official servers that MvP mobs have no dmotion even without endure + if( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) ) + return 0; + if( !sc || !sc->count || map_flag_gvg2(bl->m) || map->list[bl->m].flag.battleground ) return cap_value(dmotion,0,USHRT_MAX); - /** - * It has been confirmed on official servers that MvP mobs have no dmotion even without endure - **/ - if( sc->data[SC_ENDURE] || ( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) ) ) + + if( sc->data[SC_ENDURE] ) return 0; if( sc->data[SC_RUN] || sc->data[SC_WUGDASH] ) return 0; @@ -8416,12 +8435,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick = -1; //endless duration in the client break; case SC_EXEEDBREAK: - val1 *= 150; // 150 * skill_lv - if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) { // Chars. - val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status->get_lv(bl) / 100); - val1 += 15 * (sd ? sd->status.job_level:50) + 100; - } else // Mobs - val1 += (400 * status->get_lv(bl) / 100) + (15 * (status->get_lv(bl) / 2)); // About 1138% at mob_lvl 99. Is an aproximation to a standard weapon. [pakpil] + if( sd ){ + short index = sd->equip_index[EQI_HAND_R]; + val1 = 15 * (sd->status.job_level + val1 * 10); + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) + val1 += (sd->inventory_data[index]->weight / 10 * sd->inventory_data[index]->wlv) * status->get_lv(bl) / 100; + } break; case SC_PRESTIGE: // Based on suggested formula in iRO Wiki and some test, still need more test. [pakpil] val2 = ((st->int_ + st->luk) / 6) + 5; // Chance to evade magic damage. @@ -9123,8 +9142,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val sce->val4 = val4; if (tick >= 0) sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); - else + else { sce->timer = INVALID_TIMER; //Infinite duration + if( sd ) + chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + } if (calc_flag) status_calc_bl(bl,calc_flag); @@ -9305,6 +9327,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (sce->timer != tid && tid != INVALID_TIMER) return 0; + if( sd && sce->timer == INVALID_TIMER ) + chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type); + if (tid == INVALID_TIMER) { if (type == SC_ENDURE && sce->val4) //Do not end infinite endure. @@ -9658,7 +9683,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const * 3rd Stuff **/ case SC_MILLENNIUMSHIELD: - clif->millenniumshield(sd,0); + clif->millenniumshield(bl,0); break; case SC_HALLUCINATIONWALK: sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill->get_time2(GC_HALLUCINATIONWALK,sce->val1)); diff --git a/src/map/status.h b/src/map/status.h index f319b1506..d3148b4e0 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _STATUS_H_ -#define _STATUS_H_ +#ifndef _MAP_STATUS_H_ +#define _MAP_STATUS_H_ #include "../common/mmo.h" @@ -2012,4 +2012,4 @@ struct status_interface *status; void status_defaults(void); -#endif /* _STATUS_H_ */ +#endif /* _MAP_STATUS_H_ */ diff --git a/src/map/storage.h b/src/map/storage.h index 8a10c9f3b..8f9f904f6 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _STORAGE_H_ -#define _STORAGE_H_ +#ifndef _MAP_STORAGE_H_ +#define _MAP_STORAGE_H_ struct storage_data; struct guild_storage; @@ -59,4 +59,4 @@ struct guild_storage_interface *gstorage; void storage_defaults(void); void gstorage_defaults(void); -#endif /* _STORAGE_H_ */ +#endif /* _MAP_STORAGE_H_ */ diff --git a/src/map/trade.h b/src/map/trade.h index d0b900504..f2c0d4622 100644 --- a/src/map/trade.h +++ b/src/map/trade.h @@ -2,10 +2,11 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _TRADE_H_ -#define _TRADE_H_ +#ifndef _MAP_TRADE_H_ +#define _MAP_TRADE_H_ //Max distance from traders to enable a trade to take place. +//TODO: battle_config candidate? #define TRADE_DISTANCE 2 struct map_session_data; @@ -26,4 +27,4 @@ struct trade_interface *trade; void trade_defaults(void); -#endif /* _TRADE_H_ */ +#endif /* _MAP_TRADE_H_ */ diff --git a/src/map/unit.c b/src/map/unit.c index 7b37be266..320649a6c 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2363,11 +2363,11 @@ int unit_free(struct block_list *bl, clr_type clrtype) { sd->st = NULL; sd->npc_id = 0; } - if( sd->combos.count ) { - aFree(sd->combos.bonus); - aFree(sd->combos.id); - sd->combos.count = 0; + if( sd->combos ) { + aFree(sd->combos); + sd->combos = NULL; } + sd->combo_count = 0; /* [Ind/Hercules] */ if( sd->sc_display_count ) { for(i = 0; i < sd->sc_display_count; i++) { diff --git a/src/map/unit.h b/src/map/unit.h index a2d743875..33fa4e052 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -1,8 +1,9 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams -#ifndef _UNIT_H_ -#define _UNIT_H_ +#ifndef _MAP_UNIT_H_ +#define _MAP_UNIT_H_ //#include "map.h" struct block_list; @@ -125,4 +126,4 @@ struct unit_interface *unit; void unit_defaults(void); -#endif /* _UNIT_H_ */ +#endif /* _MAP_UNIT_H_ */ diff --git a/src/map/vending.h b/src/map/vending.h index b760bf064..b2ba22955 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _VENDING_H_ -#define _VENDING_H_ +#ifndef _MAP_VENDING_H_ +#define _MAP_VENDING_H_ #include "../common/cbasetypes.h" #include "../common/db.h" @@ -35,4 +35,4 @@ struct vending_interface *vending; void vending_defaults(void); -#endif /* _VENDING_H_ */ +#endif /* _MAP_VENDING_H_ */ diff --git a/src/plugins/HPMHooking.c b/src/plugins/HPMHooking.c index 1ca5b5f3c..e6e698383 100644 --- a/src/plugins/HPMHooking.c +++ b/src/plugins/HPMHooking.c @@ -46,6 +46,8 @@ #include "../map/mail.h" #include "../map/irc-bot.h" +#include "../common/HPMDataCheck.h" + HPExport struct hplugin_info pinfo = { "HPMHooking", // Plugin name SERVER_TYPE_MAP,// Which server types this plugin works with? diff --git a/src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc index 3dfa69d4c..ed58b79a3 100644 --- a/src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc @@ -397,6 +397,10 @@ struct { struct HPMHookPoint *HP_chrif_on_disconnect_post; struct HPMHookPoint *HP_chrif_parse_pre; struct HPMHookPoint *HP_chrif_parse_post; + struct HPMHookPoint *HP_chrif_save_scdata_single_pre; + struct HPMHookPoint *HP_chrif_save_scdata_single_post; + struct HPMHookPoint *HP_chrif_del_scdata_single_pre; + struct HPMHookPoint *HP_chrif_del_scdata_single_post; struct HPMHookPoint *HP_clif_init_pre; struct HPMHookPoint *HP_clif_init_post; struct HPMHookPoint *HP_clif_final_pre; @@ -2573,6 +2577,8 @@ struct { struct HPMHookPoint *HP_itemdb_final_sub_post; struct HPMHookPoint *HP_itemdb_clear_pre; struct HPMHookPoint *HP_itemdb_clear_post; + struct HPMHookPoint *HP_itemdb_id2combo_pre; + struct HPMHookPoint *HP_itemdb_id2combo_post; struct HPMHookPoint *HP_logs_pick_pc_pre; struct HPMHookPoint *HP_logs_pick_pc_post; struct HPMHookPoint *HP_logs_pick_mob_pre; @@ -2893,6 +2899,8 @@ struct { struct HPMHookPoint *HP_map_add_questinfo_post; struct HPMHookPoint *HP_map_remove_questinfo_pre; struct HPMHookPoint *HP_map_remove_questinfo_post; + struct HPMHookPoint *HP_map_merge_zone_pre; + struct HPMHookPoint *HP_map_merge_zone_post; struct HPMHookPoint *HP_mapit_alloc_pre; struct HPMHookPoint *HP_mapit_alloc_post; struct HPMHookPoint *HP_mapit_free_pre; @@ -3649,6 +3657,8 @@ struct { struct HPMHookPoint *HP_pc_gets_status_point_post; struct HPMHookPoint *HP_pc_need_status_point_pre; struct HPMHookPoint *HP_pc_need_status_point_post; + struct HPMHookPoint *HP_pc_maxparameterincrease_pre; + struct HPMHookPoint *HP_pc_maxparameterincrease_post; struct HPMHookPoint *HP_pc_statusup_pre; struct HPMHookPoint *HP_pc_statusup_post; struct HPMHookPoint *HP_pc_statusup2_pre; @@ -4225,8 +4235,6 @@ struct { struct HPMHookPoint *HP_script_soundeffect_sub_post; struct HPMHookPoint *HP_script_buildin_query_sql_sub_pre; struct HPMHookPoint *HP_script_buildin_query_sql_sub_post; - struct HPMHookPoint *HP_script_axtoi_pre; - struct HPMHookPoint *HP_script_axtoi_post; struct HPMHookPoint *HP_script_buildin_instance_warpall_sub_pre; struct HPMHookPoint *HP_script_buildin_instance_warpall_sub_post; struct HPMHookPoint *HP_script_buildin_mobuseskill_sub_pre; @@ -5416,6 +5424,10 @@ struct { int HP_chrif_on_disconnect_post; int HP_chrif_parse_pre; int HP_chrif_parse_post; + int HP_chrif_save_scdata_single_pre; + int HP_chrif_save_scdata_single_post; + int HP_chrif_del_scdata_single_pre; + int HP_chrif_del_scdata_single_post; int HP_clif_init_pre; int HP_clif_init_post; int HP_clif_final_pre; @@ -7592,6 +7604,8 @@ struct { int HP_itemdb_final_sub_post; int HP_itemdb_clear_pre; int HP_itemdb_clear_post; + int HP_itemdb_id2combo_pre; + int HP_itemdb_id2combo_post; int HP_logs_pick_pc_pre; int HP_logs_pick_pc_post; int HP_logs_pick_mob_pre; @@ -7912,6 +7926,8 @@ struct { int HP_map_add_questinfo_post; int HP_map_remove_questinfo_pre; int HP_map_remove_questinfo_post; + int HP_map_merge_zone_pre; + int HP_map_merge_zone_post; int HP_mapit_alloc_pre; int HP_mapit_alloc_post; int HP_mapit_free_pre; @@ -8668,6 +8684,8 @@ struct { int HP_pc_gets_status_point_post; int HP_pc_need_status_point_pre; int HP_pc_need_status_point_post; + int HP_pc_maxparameterincrease_pre; + int HP_pc_maxparameterincrease_post; int HP_pc_statusup_pre; int HP_pc_statusup_post; int HP_pc_statusup2_pre; @@ -9244,8 +9262,6 @@ struct { int HP_script_soundeffect_sub_post; int HP_script_buildin_query_sql_sub_pre; int HP_script_buildin_query_sql_sub_post; - int HP_script_axtoi_pre; - int HP_script_axtoi_post; int HP_script_buildin_instance_warpall_sub_pre; int HP_script_buildin_instance_warpall_sub_post; int HP_script_buildin_mobuseskill_sub_pre; diff --git a/src/plugins/HPMHooking/HPMHooking.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking.HookingPoints.inc index 0b7201cdc..d43852d40 100644 --- a/src/plugins/HPMHooking/HPMHooking.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking.HookingPoints.inc @@ -207,6 +207,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(chrif->on_ready, HP_chrif_on_ready) }, { HP_POP(chrif->on_disconnect, HP_chrif_on_disconnect) }, { HP_POP(chrif->parse, HP_chrif_parse) }, + { HP_POP(chrif->save_scdata_single, HP_chrif_save_scdata_single) }, + { HP_POP(chrif->del_scdata_single, HP_chrif_del_scdata_single) }, /* clif */ { HP_POP(clif->init, HP_clif_init) }, { HP_POP(clif->final, HP_clif_final) }, @@ -1305,6 +1307,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(itemdb->destroy_item_data, HP_itemdb_destroy_item_data) }, { HP_POP(itemdb->final_sub, HP_itemdb_final_sub) }, { HP_POP(itemdb->clear, HP_itemdb_clear) }, + { HP_POP(itemdb->id2combo, HP_itemdb_id2combo) }, /* logs */ { HP_POP(logs->pick_pc, HP_logs_pick_pc) }, { HP_POP(logs->pick_mob, HP_logs_pick_mob) }, @@ -1468,6 +1471,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(map->get_new_bonus_id, HP_map_get_new_bonus_id) }, { HP_POP(map->add_questinfo, HP_map_add_questinfo) }, { HP_POP(map->remove_questinfo, HP_map_remove_questinfo) }, + { HP_POP(map->merge_zone, HP_map_merge_zone) }, /* mapit */ { HP_POP(mapit->alloc, HP_mapit_alloc) }, { HP_POP(mapit->free, HP_mapit_free) }, @@ -1855,6 +1859,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(pc->thisjobexp, HP_pc_thisjobexp) }, { HP_POP(pc->gets_status_point, HP_pc_gets_status_point) }, { HP_POP(pc->need_status_point, HP_pc_need_status_point) }, + { HP_POP(pc->maxparameterincrease, HP_pc_maxparameterincrease) }, { HP_POP(pc->statusup, HP_pc_statusup) }, { HP_POP(pc->statusup2, HP_pc_statusup2) }, { HP_POP(pc->skillup, HP_pc_skillup) }, @@ -2146,7 +2151,6 @@ struct HookingPointData HookingPoints[] = { { HP_POP(script->playbgm_foreachpc_sub, HP_script_playbgm_foreachpc_sub) }, { HP_POP(script->soundeffect_sub, HP_script_soundeffect_sub) }, { HP_POP(script->buildin_query_sql_sub, HP_script_buildin_query_sql_sub) }, - { HP_POP(script->axtoi, HP_script_axtoi) }, { HP_POP(script->buildin_instance_warpall_sub, HP_script_buildin_instance_warpall_sub) }, { HP_POP(script->buildin_mobuseskill_sub, HP_script_buildin_mobuseskill_sub) }, { HP_POP(script->cleanfloor_sub, HP_script_cleanfloor_sub) }, diff --git a/src/plugins/HPMHooking/HPMHooking.Hooks.inc b/src/plugins/HPMHooking/HPMHooking.Hooks.inc index 4db53868d..2e8389d59 100644 --- a/src/plugins/HPMHooking/HPMHooking.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking.Hooks.inc @@ -5138,6 +5138,56 @@ int HP_chrif_parse(int fd) { } return retVal___; } +void HP_chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) { + int hIndex = 0; + if( HPMHooks.count.HP_chrif_save_scdata_single_pre ) { + void (*preHookFunc) (int *account_id, int *char_id, short *type, struct status_change_entry *sce); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chrif_save_scdata_single_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chrif_save_scdata_single_pre[hIndex].func; + preHookFunc(&account_id, &char_id, &type, sce); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.chrif.save_scdata_single(account_id, char_id, type, sce); + } + if( HPMHooks.count.HP_chrif_save_scdata_single_post ) { + void (*postHookFunc) (int *account_id, int *char_id, short *type, struct status_change_entry *sce); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chrif_save_scdata_single_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chrif_save_scdata_single_post[hIndex].func; + postHookFunc(&account_id, &char_id, &type, sce); + } + } + return; +} +void HP_chrif_del_scdata_single(int account_id, int char_id, short type) { + int hIndex = 0; + if( HPMHooks.count.HP_chrif_del_scdata_single_pre ) { + void (*preHookFunc) (int *account_id, int *char_id, short *type); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chrif_del_scdata_single_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chrif_del_scdata_single_pre[hIndex].func; + preHookFunc(&account_id, &char_id, &type); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.chrif.del_scdata_single(account_id, char_id, type); + } + if( HPMHooks.count.HP_chrif_del_scdata_single_post ) { + void (*postHookFunc) (int *account_id, int *char_id, short *type); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chrif_del_scdata_single_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chrif_del_scdata_single_post[hIndex].func; + postHookFunc(&account_id, &char_id, &type); + } + } + return; +} /* clif */ int HP_clif_init(bool minimal) { int hIndex = 0; @@ -10395,13 +10445,13 @@ void HP_clif_specialeffect_value(struct block_list *bl, int effect_id, int num, } return; } -void HP_clif_millenniumshield(struct map_session_data *sd, short shields) { +void HP_clif_millenniumshield(struct block_list *bl, short shields) { int hIndex = 0; if( HPMHooks.count.HP_clif_millenniumshield_pre ) { - void (*preHookFunc) (struct map_session_data *sd, short *shields); + void (*preHookFunc) (struct block_list *bl, short *shields); for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_millenniumshield_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_clif_millenniumshield_pre[hIndex].func; - preHookFunc(sd, &shields); + preHookFunc(bl, &shields); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -10409,13 +10459,13 @@ void HP_clif_millenniumshield(struct map_session_data *sd, short shields) { } } { - HPMHooks.source.clif.millenniumshield(sd, shields); + HPMHooks.source.clif.millenniumshield(bl, shields); } if( HPMHooks.count.HP_clif_millenniumshield_post ) { - void (*postHookFunc) (struct map_session_data *sd, short *shields); + void (*postHookFunc) (struct block_list *bl, short *shields); for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_millenniumshield_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_clif_millenniumshield_post[hIndex].func; - postHookFunc(sd, &shields); + postHookFunc(bl, &shields); } } return; @@ -32801,6 +32851,32 @@ void HP_itemdb_clear(bool total) { } return; } +struct item_combo* HP_itemdb_id2combo(unsigned short id) { + int hIndex = 0; + struct item_combo* retVal___ = NULL; + if( HPMHooks.count.HP_itemdb_id2combo_pre ) { + struct item_combo* (*preHookFunc) (unsigned short *id); + for(hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_id2combo_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_itemdb_id2combo_pre[hIndex].func; + retVal___ = preHookFunc(&id); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.itemdb.id2combo(id); + } + if( HPMHooks.count.HP_itemdb_id2combo_post ) { + struct item_combo* (*postHookFunc) (struct item_combo* retVal___, unsigned short *id); + for(hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_id2combo_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_itemdb_id2combo_post[hIndex].func; + retVal___ = postHookFunc(retVal___, &id); + } + } + return retVal___; +} /* logs */ void HP_logs_pick_pc(struct map_session_data *sd, e_log_pick_type type, int amount, struct item *itm, struct item_data *data) { int hIndex = 0; @@ -37054,6 +37130,32 @@ bool HP_map_remove_questinfo(int m, struct npc_data *nd) { } return retVal___; } +struct map_zone_data* HP_map_merge_zone(struct map_zone_data *main, struct map_zone_data *other) { + int hIndex = 0; + struct map_zone_data* retVal___ = NULL; + if( HPMHooks.count.HP_map_merge_zone_pre ) { + struct map_zone_data* (*preHookFunc) (struct map_zone_data *main, struct map_zone_data *other); + for(hIndex = 0; hIndex < HPMHooks.count.HP_map_merge_zone_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_map_merge_zone_pre[hIndex].func; + retVal___ = preHookFunc(main, other); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.map.merge_zone(main, other); + } + if( HPMHooks.count.HP_map_merge_zone_post ) { + struct map_zone_data* (*postHookFunc) (struct map_zone_data* retVal___, struct map_zone_data *main, struct map_zone_data *other); + for(hIndex = 0; hIndex < HPMHooks.count.HP_map_merge_zone_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_map_merge_zone_post[hIndex].func; + retVal___ = postHookFunc(retVal___, main, other); + } + } + return retVal___; +} /* mapit */ struct s_mapiterator* HP_mapit_alloc(enum e_mapitflags flags, enum bl_type types) { int hIndex = 0; @@ -46994,14 +47096,40 @@ int HP_pc_need_status_point(struct map_session_data *sd, int type, int val) { } return retVal___; } -int HP_pc_statusup(struct map_session_data *sd, int type) { +int HP_pc_maxparameterincrease(struct map_session_data *sd, int type) { int hIndex = 0; int retVal___ = 0; - if( HPMHooks.count.HP_pc_statusup_pre ) { + if( HPMHooks.count.HP_pc_maxparameterincrease_pre ) { int (*preHookFunc) (struct map_session_data *sd, int *type); + for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_maxparameterincrease_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_pc_maxparameterincrease_pre[hIndex].func; + retVal___ = preHookFunc(sd, &type); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.pc.maxparameterincrease(sd, type); + } + if( HPMHooks.count.HP_pc_maxparameterincrease_post ) { + int (*postHookFunc) (int retVal___, struct map_session_data *sd, int *type); + for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_maxparameterincrease_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_pc_maxparameterincrease_post[hIndex].func; + retVal___ = postHookFunc(retVal___, sd, &type); + } + } + return retVal___; +} +bool HP_pc_statusup(struct map_session_data *sd, int type, int increase) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_pc_statusup_pre ) { + bool (*preHookFunc) (struct map_session_data *sd, int *type, int *increase); for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_statusup_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_pc_statusup_pre[hIndex].func; - retVal___ = preHookFunc(sd, &type); + retVal___ = preHookFunc(sd, &type, &increase); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -47009,13 +47137,13 @@ int HP_pc_statusup(struct map_session_data *sd, int type) { } } { - retVal___ = HPMHooks.source.pc.statusup(sd, type); + retVal___ = HPMHooks.source.pc.statusup(sd, type, increase); } if( HPMHooks.count.HP_pc_statusup_post ) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, int *type); + bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, int *type, int *increase); for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_statusup_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_pc_statusup_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, &type); + retVal___ = postHookFunc(retVal___, sd, &type, &increase); } } return retVal___; @@ -54554,32 +54682,6 @@ int HP_script_buildin_query_sql_sub(struct script_state *st, Sql *handle) { } return retVal___; } -int HP_script_axtoi(const char *hexStg) { - int hIndex = 0; - int retVal___ = 0; - if( HPMHooks.count.HP_script_axtoi_pre ) { - int (*preHookFunc) (const char *hexStg); - for(hIndex = 0; hIndex < HPMHooks.count.HP_script_axtoi_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_script_axtoi_pre[hIndex].func; - retVal___ = preHookFunc(hexStg); - } - if( *HPMforce_return ) { - *HPMforce_return = false; - return retVal___; - } - } - { - retVal___ = HPMHooks.source.script.axtoi(hexStg); - } - if( HPMHooks.count.HP_script_axtoi_post ) { - int (*postHookFunc) (int retVal___, const char *hexStg); - for(hIndex = 0; hIndex < HPMHooks.count.HP_script_axtoi_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_script_axtoi_post[hIndex].func; - retVal___ = postHookFunc(retVal___, hexStg); - } - } - return retVal___; -} int HP_script_buildin_instance_warpall_sub(struct block_list *bl, va_list ap) { int hIndex = 0; int retVal___ = 0; diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c index e72d47b80..46d654e0d 100644 --- a/src/plugins/db2sql.c +++ b/src/plugins/db2sql.c @@ -16,6 +16,8 @@ #include <stdio.h> #include <stdlib.h> +#include "../common/HPMDataCheck.h" + HPExport struct hplugin_info pinfo = { "DB2SQL", // Plugin name SERVER_TYPE_MAP, // Which server types this plugin works with? diff --git a/src/plugins/sample.c b/src/plugins/sample.c index b3e2b570f..750ab31f9 100644 --- a/src/plugins/sample.c +++ b/src/plugins/sample.c @@ -14,6 +14,8 @@ #include "../map/pc.h" #include "../map/clif.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 = { "Sample", // Plugin name SERVER_TYPE_MAP,// Which server types this plugin works with? diff --git a/tools/HPMHookGen/HPMDataCheckGen.pl b/tools/HPMHookGen/HPMDataCheckGen.pl new file mode 100644 index 000000000..a79811c47 --- /dev/null +++ b/tools/HPMHookGen/HPMDataCheckGen.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl + +# Copyright (c) Hercules Dev Team, licensed under GNU GPL. +# See the LICENSE file + +use strict; +use warnings; +use XML::Simple; + +# XML Parser hint (some are faster than others) +#local $ENV{XML_SIMPLE_PREFERRED_PARSER} = ''; # 0m14.181s +local $ENV{XML_SIMPLE_PREFERRED_PARSER} = 'XML::Parser'; # 0m4.256s +#local $ENV{XML_SIMPLE_PREFERRED_PARSER} = 'XML::SAX::Expat'; # 0m14.186s +#local $ENV{XML_SIMPLE_PREFERRED_PARSER} = 'XML::LibXML::SAX'; # 0m7.055s + +my @files = grep { -f } grep { /[^h]\.xml/ } glob 'doxyoutput/xml/struct*.xml'; +my %out; + +foreach my $file (@files) { + my $xml = new XML::Simple; + my $data = $xml->XMLin($file); + next unless $data->{compounddef}->{includes}; # means its a struct from a .c file, plugins cant access those so we don't care. + next if $data->{compounddef}->{compoundname} =~ /::/; # its a duplicate with a :: name e.g. struct script_state {<...>} ay; + my @filepath = split(/[\/\\]/, $data->{compounddef}->{location}->{file}); + my $foldername = uc($filepath[-2]); + my $filename = uc($filepath[-1]); $filename =~ s/-/_/g; $filename =~ s/\.[^.]*$//; + my $name = "_${foldername}_${filename}_H_"; + push @{ $out{$name} }, $data->{compounddef}->{compoundname}; +} + +my $fname = '../../src/common/HPMDataCheck.h'; +open(FH, '>', $fname); + +print FH <<"EOF"; +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// +// NOTE: This file was auto-generated and should never be manually edited, +// as it will get overwritten. +#ifndef _HPM_DATA_CHECK_H_ +#define _HPM_DATA_CHECK_H_ + + +HPExport const struct s_HPMDataCheck HPMDataCheck[] = { +EOF + +foreach my $key (sort keys %out) { + print FH <<"EOF"; + #ifdef $key +EOF + foreach my $entry (@{ $out{$key} }) { + print FH <<"EOF" + { "$entry", sizeof(struct $entry) }, +EOF + } + print FH <<"EOF" + #else + #define $key + #endif // $key +EOF +} +print FH <<"EOF"; +}; +HPExport unsigned int HPMDataCheckLen = ARRAYLENGTH(HPMDataCheck); + +#endif /* _HPM_DATA_CHECK_H_ */ +EOF +close(FH); diff --git a/tools/HPMHookGen/HPMHookGen.pl b/tools/HPMHookGen/HPMHookGen.pl index eef490e29..b035687e2 100755 --- a/tools/HPMHookGen/HPMHookGen.pl +++ b/tools/HPMHookGen/HPMHookGen.pl @@ -7,6 +7,12 @@ use strict; use warnings; use XML::Simple; +# XML Parser hint (some are faster than others) +#local $ENV{XML_SIMPLE_PREFERRED_PARSER} = ''; # 0m7.138s +local $ENV{XML_SIMPLE_PREFERRED_PARSER} = 'XML::Parser'; # 0m2.674s +#local $ENV{XML_SIMPLE_PREFERRED_PARSER} = 'XML::SAX::Expat'; # 0m7.026s +#local $ENV{XML_SIMPLE_PREFERRED_PARSER} = 'XML::LibXML::SAX'; # 0m4.152s + sub trim($) { my $s = $_[0]; $s =~ s/^\s+//; $s =~ s/\s+$//; diff --git a/tools/HPMHookGen/Makefile.in b/tools/HPMHookGen/Makefile.in index c89228c7a..eb9cad8ff 100644 --- a/tools/HPMHookGen/Makefile.in +++ b/tools/HPMHookGen/Makefile.in @@ -1,18 +1,24 @@ @SET_MAKE@ -COMMON_C = $(wildcard ../../src/common/*.c) -COMMON_H = $(wildcard ../../src/common/*.h) -MAP_C = $(wildcard ../../src/map/*.c) -MAP_H = $(wildcard ../../src/map/*.h) -CHAR_C = $(wildcard ../../src/char/*.c) -CHAR_H = $(wildcard ../../src/char/*.h) -LOGIN_C = $(wildcard ../../src/login/*.c) -LOGIN_H = $(wildcard ../../src/login/*.h) +COMMON_D = ../../src/common +MAP_D = ../../src/map +CHAR_D = ../../src/char +LOGIN_D = ../../src/login +PLUGIN_D = ../../src/plugins +COMMON_C = $(wildcard $(COMMON_D)/*.c) +COMMON_H = $(filter-out $(COMMON_D)/HPMDataCheck.%,$(wildcard $(COMMON_D)/*.h)) +MAP_C = $(wildcard $(MAP_D)/*.c) +MAP_H = $(wildcard $(MAP_D)/*.h) +CHAR_C = $(wildcard $(CHAR_D)/*.c) +CHAR_H = $(wildcard $(CHAR_D)/*.h) +LOGIN_C = $(wildcard $(LOGIN_D)/*.c) +LOGIN_H = $(wildcard $(LOGIN_D)/*.h) ALL_C = $(COMMON_C) $(MAP_C) $(CHAR_C) $(LOGIN_C) ALL_H = $(COMMON_H) $(MAP_H) $(CHAR_H) $(LOGIN_H) -HOOK_INC = $(addprefix ../../src/plugins/HPMHooking., \ - $(addsuffix .inc, HookingPoints sources GetSymbol HPMHooksCore Hooks)) +HOOK_INC = $(addprefix $(PLUGIN_D)/HPMHooking., \ + $(addsuffix .inc, HookingPoints sources GetSymbol HPMHooksCore Hooks)) \ + $(COMMON_D)/HPMDataCheck.h HAVE_DOXYGEN=@HAVE_DOXYGEN@ HAVE_PERL=@HAVE_PERL@ @@ -49,8 +55,10 @@ hooks: $(HOOK_INC) $(HOOK_INC): generate generate: doxyoutput - @echo " Regenerating hook definitions..." + @echo " Regenerating HPM Hook definitions..." @perl HPMHookGen.pl + @echo " Regenerating HPM Data Check definitions..." + @perl HPMDataCheckGen.pl doxyoutput: $(ALL_C) $(ALL_H) doxygen.conf @echo " Extracting functions information..." |